Arm has a problem with tls after a fork. The pthread_key_create seems to
be forgotten?
Apple has a problem with the exit(0) code in do_fork(). An IO mutex
is still held after a fork().
The BOUNDS_CHECKING_ON/BOUNDS_CHECKING_OFF is not working for
signal/sigaction/fork. The reason is that the code stops bound checking
for the whole application. This result in wrong handling of
__bound_local_new/__bound_local_delete and malloc/calloc/realloc/free.
Consider the following code:
void tst(int n) {
int i, arr[n];
for (i = 0; i < n; i++) arr[i] = 0;
}
void *some_thread(void *dummy) {
while (running) { tst(10); tst(20); }
}
void signal_handler(int sig) { ... }
When the signal handler is called the some_thread code can be interrupted when
is just registered the arr[10] data. When the signal handler is leaved the
arr[10] is still registered and did not see the call to deregister arr[10] and
then register arr[20]. The code resumes when tst(20) is running. This results
in a bound checking error when i >= 10.
To solve the above problem I changed the bound checking code to use
tls (thread local storage) for the no_checking variable.
This also makes it now possible to redirect signal/sigaction/fork code
through the bound checking library and disable checking when a signal is
running and to correct the bounds_sem for the fork child process.
The BOUNDS_CHECKING_ON/BOUNDS_CHECKING_OFF is not needed any more for
signal/sigaction/fork. In fact I could remove them from all my applications.
The use of the tls function code slows down the code by about 10%.
So if the slowdown due to bound checking was 5. It is now 5.5 times slower.
For x86_64/i386 I also allowed to use __thread variable in bcheck.c when
compiled with gcc with:
make x86_64-libtcc1-usegcc=yes
make i386-libtcc1-usegcc=yes
This makes code run faster due to use of gcc and __thread variable.
With the __thread variable there is no 10% slowdown.
For other targets this does not work because stabs is not supported.
Changes:
lib/bcheck.c:
- Add TRY_SEM
- Add HAVE_SIGNAL/HAVE_SIGACTION/HAVE_FORK/HAVE_TLS_FUNC/HAVE_TLS_VAR
- HAVE_SIGNAL: redirect signal() call if set.
- HAVE_SIGACTION: redirect sigaction() call if set.
- HAVE_FORK: redirect fork() call if set.
- HAVE_TLS_FUNC: If target has tls function calls.
- HAVE_TLS_VAR: If target has __thread tls support.
- Replace all no_checking refecrences to NO_CHECKING_SET/NO_CHECKING_GET macros
tcc-doc.texi:
- Remove examples for signal/sigaction/fork code.
- Add some explanation for signal/sigaction/fork code.
- Add documentaion for __bounds_checking().
tccelf.c:
- Add support for SHF_TLS
tests/tests2/114_bound_signal.c:
- Remove BOUNDS_CHECKING_ON/BOUNDS_CHECKING_OFF
- Add code to trigger failure when tls is not working.
x86_64-link.c:
- Add support for R_X86_64_TLSGD/R_X86_64_TLSLD/R_X86_64_DTPOFF32/R_X86_64_TPOFF32
i386-link.c:
- Add support for R_386_TLS_GD/R_386_TLS_LDM/R_386_TLS_LDO_32/R_386_TLS_LE
Providing both run-time and compile-time control for bounds
checking as an user interface appears unnecessary and confusing.
Also:
- replace 'bound_...' by 'bounds_...' for consistency
- tcc-doc: put related info into one place and cleanup
The __bounds_checking(x) function is still missing explanation.
(I.e. what happens if the accumulated value drops below zero.)
tcctok.h:
- Add CONFIG_TCC_BCHECK arround TOK_NO_BOUND_CHECK1/TOK_NO_BOUND_CHECK2
tccgen.c:
- Add CONFIG_TCC_BCHECK arround TOK_NO_BOUND_CHECK1/TOK_NO_BOUND_CHECK2
- Undo alias definition in tccpp.c when function bound checking if off
tests/tests2/114_bound_signal.c:
- Test alias undo
- fix sleep problem
- configure/Makefile : cleanup, really use CC_NAME
- tccasm.c : remove C99 construct that MSVC doesn't compile
- arm-gen.c, x86_64-gen.c, riscv64-gen.c, tccmacho.c : ditto
- arm64-gen.c: commit 383acf8eff wrote:
"Instead of a cast, it would be better to pass the exact type."
It is true that there are better solutions but it is not
passing the exact type (I think).
- tcctest.c: revert "fix cast test for clang" 03646ad46f
this obviously wants to test non-portable conversions
- 114_bound_signal.test: clock_nanosleep is too new for older
linuxes, just use sleep() instead