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.)
The switch/case operation was entirely performed on int64_t, resulting
in a warning and bad code to be emitted on 64 bit machines when used on
an unsigned long with a case range whose signed representation starts
positive and ends negative like in the example below:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int nbdg(unsigned long n)
{
switch (n) {
case 1UL ... 9UL: return 1;
case 10UL ... 99UL: return 2;
case 100UL ... 999UL: return 3;
case 1000UL ... 9999UL: return 4;
case 10000UL ... 99999UL: return 5;
case 100000UL ... 999999UL: return 6;
case 1000000UL ... 9999999UL: return 7;
case 10000000UL ... 99999999UL: return 8;
case 100000000UL ... 999999999UL: return 9;
case 1000000000UL ... 9999999999UL: return 10;
case 10000000000UL ... 99999999999UL: return 11;
case 100000000000UL ... 999999999999UL: return 12;
case 1000000000000UL ... 9999999999999UL: return 13;
case 10000000000000UL ... 99999999999999UL: return 14;
case 100000000000000UL ... 999999999999999UL: return 15;
case 1000000000000000UL ... 9999999999999999UL: return 16;
case 10000000000000000UL ... 99999999999999999UL: return 17;
case 100000000000000000UL ... 999999999999999999UL: return 18;
case 1000000000000000000UL ... 9999999999999999999UL: return 19; // this one
case 10000000000000000000UL ... ULONG_MAX: return 20;
}
return 0;
}
int main(int argc, char **argv)
{
unsigned long v = strtoul(argc > 1 ? argv[1] : "1111", NULL, 0);
printf("%lu : %d\n", v, nbdg(v));
return 0;
}
$ tcc dg.c
dg.c:26: warning: empty case range
$ x="";for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0; do x=$x$i; ./a.out $x;done
1 : 1
12 : 2
123 : 3
1234 : 4
12345 : 5
123456 : 6
1234567 : 7
12345678 : 8
123456789 : 9
1234567890 : 10
12345678901 : 11
123456789012 : 12
1234567890123 : 13
12345678901234 : 14
123456789012345 : 15
1234567890123456 : 16
12345678901234567 : 17
123456789012345678 : 18
1234567890123456789 : 0
12345678901234567890 : 20
What this patch does is to use a separate set of signed and unsigned
case_cmp functions depending on whether the expression is signed or
unsigned, and also does this to decide when to emit the warning.
The bad code on output was caused by the removal of the unsigned bit
resulting from the signed sort, which causes only signed comparisons
to be emitted in the asm code. As such some sets could not match.
Note that there is no way to rely on the values only to sort properly
nor to emit the warning because we're effectively dealing with 65-bit
arithmetic here and any two values will have a different behavior
depending on the signed or unsigned expectation.
For unsigned expressions now the warning only happens when bounds are
switched, For signed expressions (e.g. if the input is signed long
above), the warning remains and the abnormal output as well. In both
cases this remains consistent with what gcc produces.
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
Most support was already present.
arm-link.c:
- set RELOCATE_DLLPLT to 1
- create_plt_entry:
- remove DLLs unimplemented!
- leave code gen to relocate_plt. only set got_offset
- relocate_plt:
- create code for got entry
- relocate:
- Add TCC_OUTPUT_DLL for R_ARM_ABS32
tccelf.c:
- prepare_dynamic_rel:
- Add R_ARM_ABS32
- alloc_sec_names:
- Always add SHT_ARM_ATTRIBUTES section
- New function create_arm_attribute_section
- elf_output_file:
- call create_arm_attribute_section
The load/store code is optimized to make better use of the offsets
present in the load/store instructions.
Also use GOT reloc's instead of ABS64 relocs.
arm64-gen.c/arm64_check_offset:
- New function to split offset used by load/store and by arm64_sym.
arm64-gen.c/arm64_sym:
- Use GOT reloc's instead of ABS64 relocs.
arm64-gen.c/load arm64-gen.c/store:
- Use new arm64_check_offset function.
arm64-gen.c/gen_bounds_prolog arm64-gen.c/gen_bounds_epilog:
- Use GOT reloc's instaed of ABS64 relocs.
old qemu (before april 2020) have a bug in the layout of
struct ucontext, so we get invalid values under qemu-userspace emulation
when inspecting the signal context. Try to recognize this and
graciously error out instead of segfaulting in the backtracer routines.
found in mpfr. Expressions like "(longlong)i <= MAX_ULONGLONG" are
always true (not yet short-circuited in tcc), but still need to be
handled correctly in the backends.
The orignal code does:
push eax/edx/size
call alloca
pop eax/edx/size
The pop does not work because the stack pointer has changed.
To make this also work with bound checking the code is now
using the stack probing from alloca.
i386-gen.c:
- Fix large stack size alloca code.
The returned value of alloca was not used corectly.
libtcc.c:
- Use __SIZE_TYPE__ for __builtin_offsetof
tccpp.c:
- Fix __MAYBE_REDIR and abort builtins.
tests/tests2/Makefile
- Run 117_gcc_test also with bound checking enabled
This found the above problems.
those aren't preprocessed, but our use of a fake file in
preprocess_start requires inline stack processing (which isn't done
without preprocessing). Just don't try to setup anything requiring
preprocessing at all in this case.
for benchmarking the preprocessor, without having to use the PP_BENCH
macro. No output will be produced for '-E -bench', so it's the raw
tokenization/preprocess speed.
tccgen.c:
- cleanup __builtin_... stuff
- merge __attribute((alias("sym"))) with __asm__("sym")
Now one cannot have both, however for alias underscores are
added if enabled. For __asm__ they aren't.
tccpp.c:
- extend tcc_predefs accordingly. Was generated with
'cd tests/misc && tcc -run c2str.c tcc_predef.h tcc_predefs'
xxx-gen.c:
- move bcheck setjmp test to tccgen.c:gbound_args()
i386-gen.c:
- create win32 compatible stack space for big structures
tcctest.c:
- some cleanup + nicer output