mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-04 06:30:10 +08:00
Update bound checking code.
Add __attribute__((constructor)) to __bounds_init. - remove tcc_add_bcheck from i386-link.c and x86_64-link.c - add simplified tcc_add_bcheck to tccelf.c - Update tccrun.c to call constructor/destructor. Set dynsym sh_info to number of local symbols in tccelf.c Reduce stack size when bounds checking is enabled. Added variable TCC_LIBBCHECK for windows support. Add signal stack to detect stack overflow. Add all & parameters in lbound_section and remove them if not used. Close fd in tcc_relocate in tccrun.c Fix section type constructor/destructor in tccelf.c Add check code in tests/boundtest.c for mem/str functions. Remove -ba from documentation. Add bounds check signal info in documentation. bcheck.c: - Fix initial_pool alignment. . Fix printf statements. . Add prototypes for all external interface functions. - Add TCC_BOUNDS_WARN_POINTER_ADD environment variable. . Add ctype and errno data. - Fix alloca when multithreading is used. - Add lock for __bound_checking and __bound_never_fatal. - Catch pthread_create and use locks when called. - Detect in loaded in shared lib and use locks when found - Use spin locks instead of semaphore locks. - Make spin locked code as small as possible. - Fix mem/str functions checking. - Fix overlap checking mem/str functions.
This commit is contained in:
parent
0d6801b130
commit
3877618785
@ -95,7 +95,6 @@ ST_DATA const int reg_classes[NB_REGS] = {
|
|||||||
static unsigned long func_sub_sp_offset;
|
static unsigned long func_sub_sp_offset;
|
||||||
static int func_ret_sub;
|
static int func_ret_sub;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
static addr_t func_bound_offset;
|
|
||||||
static unsigned long func_bound_ind;
|
static unsigned long func_bound_ind;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -402,8 +401,10 @@ ST_FUNC void gfunc_call(int nb_args)
|
|||||||
Sym *func_sym;
|
Sym *func_sym;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (tcc_state->do_bounds_check)
|
if (tcc_state->do_bounds_check) {
|
||||||
|
save_temp_local (nb_args);
|
||||||
gbound_args(nb_args);
|
gbound_args(nb_args);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
args_size = 0;
|
args_size = 0;
|
||||||
@ -485,6 +486,10 @@ ST_FUNC void gfunc_call(int nb_args)
|
|||||||
if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
|
if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
|
||||||
gadd_sp(args_size);
|
gadd_sp(args_size);
|
||||||
vtop--;
|
vtop--;
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
if (tcc_state->do_bounds_check)
|
||||||
|
restore_temp_local ();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TCC_TARGET_PE
|
#ifdef TCC_TARGET_PE
|
||||||
|
75
i386-link.c
75
i386-link.c
@ -235,79 +235,4 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
ST_FUNC void tcc_add_bcheck(TCCState *s1)
|
|
||||||
{
|
|
||||||
addr_t *ptr;
|
|
||||||
int loc_glob;
|
|
||||||
int sym_index;
|
|
||||||
int bsym_index;
|
|
||||||
|
|
||||||
if (0 == s1->do_bounds_check)
|
|
||||||
return;
|
|
||||||
/* XXX: add an object file to do that */
|
|
||||||
ptr = section_ptr_add(bounds_section, sizeof(*ptr));
|
|
||||||
*ptr = 0;
|
|
||||||
loc_glob = s1->output_type != TCC_OUTPUT_MEMORY ? STB_LOCAL : STB_GLOBAL;
|
|
||||||
bsym_index = set_elf_sym(symtab_section, 0, 0,
|
|
||||||
ELFW(ST_INFO)(loc_glob, STT_NOTYPE), 0,
|
|
||||||
bounds_section->sh_num, "__bounds_start");
|
|
||||||
/* pull bcheck.o from libtcc1.a */
|
|
||||||
sym_index = set_elf_sym(symtab_section, 0, 0,
|
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
|
||||||
SHN_UNDEF, "__bound_init");
|
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY) {
|
|
||||||
/* add 'call __bound_init()' in .init section */
|
|
||||||
Section *init_section = find_section(s1, ".init");
|
|
||||||
unsigned char *pinit;
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
pinit = section_ptr_add(init_section, 3);
|
|
||||||
pinit[0] = 0x55; /* push %rbp */
|
|
||||||
pinit[1] = 0x89; /* mov %esp,%ebp */
|
|
||||||
pinit[2] = 0xe5;
|
|
||||||
#endif
|
|
||||||
pinit = section_ptr_add(init_section, 5);
|
|
||||||
pinit[0] = 0xe8;
|
|
||||||
write32le(pinit + 1, -4);
|
|
||||||
put_elf_reloc(symtab_section, init_section,
|
|
||||||
init_section->data_offset - 4, R_386_PC32, sym_index);
|
|
||||||
/* R_386_PC32 = R_X86_64_PC32 = 2 */
|
|
||||||
pinit = section_ptr_add(init_section, 6);
|
|
||||||
pinit[0] = 0xb8; /* mov xx,%eax */
|
|
||||||
write32le(pinit + 1, 0);
|
|
||||||
pinit[5] = 0x50; /* push %eax */
|
|
||||||
put_elf_reloc(symtab_section, init_section,
|
|
||||||
init_section->data_offset - 5, R_386_32, bsym_index);
|
|
||||||
sym_index = set_elf_sym(symtab_section, 0, 0,
|
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
|
||||||
SHN_UNDEF, "__bounds_add_static_var");
|
|
||||||
pinit = section_ptr_add(init_section, 5);
|
|
||||||
pinit[0] = 0xe8;
|
|
||||||
write32le(pinit + 1, -4);
|
|
||||||
put_elf_reloc(symtab_section, init_section,
|
|
||||||
init_section->data_offset - 4, R_386_PC32, sym_index);
|
|
||||||
/* R_386_PC32 = R_X86_64_PC32 = 2 */
|
|
||||||
pinit = section_ptr_add(init_section, 3);
|
|
||||||
pinit[0] = 0x83; /* add $0x4,%esp */
|
|
||||||
pinit[1] = 0xc4;
|
|
||||||
pinit[2] = 0x04;
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
{
|
|
||||||
int init_index = set_elf_sym(symtab_section,
|
|
||||||
0, 0,
|
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
|
||||||
init_section->sh_num, "__init_start");
|
|
||||||
Sym sym;
|
|
||||||
init_section->sh_flags |= SHF_EXECINSTR;
|
|
||||||
pinit = section_ptr_add(init_section, 2);
|
|
||||||
pinit[0] = 0xc9; /* leave */
|
|
||||||
pinit[1] = 0xc3; /* ret */
|
|
||||||
sym.c = init_index;
|
|
||||||
add_init_array (s1, &sym);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !TARGET_DEFS_ONLY */
|
#endif /* !TARGET_DEFS_ONLY */
|
||||||
|
1132
lib/bcheck.c
1132
lib/bcheck.c
File diff suppressed because it is too large
Load Diff
43
tcc-doc.texi
43
tcc-doc.texi
@ -356,8 +356,10 @@ memory allocations and array/pointer bounds. @option{-g} is implied. Note
|
|||||||
that the generated code is slower and bigger in this case.
|
that the generated code is slower and bigger in this case.
|
||||||
The bound checking code is not included in shared libaries. The main executable should always be compiled with the @option{-b}.
|
The bound checking code is not included in shared libaries. The main executable should always be compiled with the @option{-b}.
|
||||||
|
|
||||||
There are four environment variables that can be used:
|
There are five environment variables that can be used:
|
||||||
@table @option
|
@table @option
|
||||||
|
@item TCC_BOUNDS_WARN_POINTER_ADD
|
||||||
|
Print warning when pointer add creates an illegal pointer.
|
||||||
@item TCC_BOUNDS_PRINT_CALLS
|
@item TCC_BOUNDS_PRINT_CALLS
|
||||||
Print bound checking calls. Can be used for debugging.
|
Print bound checking calls. Can be used for debugging.
|
||||||
@item TCC_BOUNDS_PRINT_HEAP
|
@item TCC_BOUNDS_PRINT_HEAP
|
||||||
@ -368,10 +370,7 @@ Print statistic information at exit of program.
|
|||||||
Try to continue in case of a bound checking error.
|
Try to continue in case of a bound checking error.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) when using libtcc for the moment.
|
Note: @option{-b} is only available on i386 (linux and windows) and x86_64 (linux and windows) for the moment.
|
||||||
|
|
||||||
@item -ba
|
|
||||||
Generate address checking tests when using @option{-b}. This will be a lot slower but finds more errors.
|
|
||||||
|
|
||||||
@item -bt N
|
@item -bt N
|
||||||
Display N callers in stack traces. This is useful with @option{-g} or
|
Display N callers in stack traces. This is useful with @option{-g} or
|
||||||
@ -947,6 +946,40 @@ Here are some examples of caught errors:
|
|||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
Signal handlers are not compatible with bounds checking. The code
|
||||||
|
below can be used to protect signal handlers.
|
||||||
|
The call to __bound_checking(1) will disable bounds checking in the
|
||||||
|
whole application.
|
||||||
|
|
||||||
|
The BOUNDS_CHECKING_OFF and BOUNDS_CHECKING_ON can also be used to
|
||||||
|
disable bounds checking for some code. This is not recommended.
|
||||||
|
It is better to fix the code.
|
||||||
|
|
||||||
|
@example
|
||||||
|
|
||||||
|
#ifdef __BOUNDS_CHECKING_ON
|
||||||
|
extern void __bound_checking (int no_check);
|
||||||
|
#define BOUNDS_CHECKING_OFF __bound_checking(1)
|
||||||
|
#define BOUNDS_CHECKING_ON __bound_checking(-1)
|
||||||
|
#else
|
||||||
|
#define BOUNDS_CHECKING_OFF
|
||||||
|
#define BOUNDS_CHECKING_ON
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void real_signal_handler(int sig, siginfo_t *info, void *ucontext)
|
||||||
|
@{
|
||||||
|
...
|
||||||
|
@}
|
||||||
|
|
||||||
|
void signal_handler(int sig, void *info, void *ucontext)
|
||||||
|
@{
|
||||||
|
BOUNDS_CHECKING_OFF;
|
||||||
|
real_signal_handler(sig, info, data);
|
||||||
|
BOUNDS_CHECKING_ON;
|
||||||
|
@}
|
||||||
|
|
||||||
|
@end example
|
||||||
|
|
||||||
@node Libtcc
|
@node Libtcc
|
||||||
@chapter The @code{libtcc} library
|
@chapter The @code{libtcc} library
|
||||||
|
|
||||||
|
8
tcc.h
8
tcc.h
@ -292,6 +292,9 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||||||
#ifndef TCC_LIBTCC1
|
#ifndef TCC_LIBTCC1
|
||||||
# define TCC_LIBTCC1 "libtcc1.a"
|
# define TCC_LIBTCC1 "libtcc1.a"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef TCC_LIBBCHECK
|
||||||
|
# define TCC_LIBBCHECK "bcheck.o"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
|
/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
|
||||||
#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC
|
#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC
|
||||||
@ -1375,6 +1378,9 @@ ST_DATA CType func_vt; /* current function return type (used by return instructi
|
|||||||
ST_DATA int func_var; /* true if current function is variadic */
|
ST_DATA int func_var; /* true if current function is variadic */
|
||||||
ST_DATA int func_vc;
|
ST_DATA int func_vc;
|
||||||
ST_DATA const char *funcname;
|
ST_DATA const char *funcname;
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
ST_DATA addr_t func_bound_offset;
|
||||||
|
#endif
|
||||||
|
|
||||||
ST_FUNC void tcc_debug_start(TCCState *s1);
|
ST_FUNC void tcc_debug_start(TCCState *s1);
|
||||||
ST_FUNC void tcc_debug_end(TCCState *s1);
|
ST_FUNC void tcc_debug_end(TCCState *s1);
|
||||||
@ -1440,6 +1446,8 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty);
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
ST_FUNC void gbound_args(int nb_args);
|
ST_FUNC void gbound_args(int nb_args);
|
||||||
|
ST_FUNC void save_temp_local(int nb_args);
|
||||||
|
ST_FUNC void restore_temp_local(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ------------ tccelf.c ------------ */
|
/* ------------ tccelf.c ------------ */
|
||||||
|
33
tccelf.c
33
tccelf.c
@ -85,6 +85,23 @@ ST_FUNC void tccelf_bounds_new(TCCState *s)
|
|||||||
lbounds_section = new_section(s, ".lbounds",
|
lbounds_section = new_section(s, ".lbounds",
|
||||||
SHT_PROGBITS, SHF_ALLOC);
|
SHT_PROGBITS, SHF_ALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ST_FUNC void tcc_add_bcheck(TCCState *s1)
|
||||||
|
{
|
||||||
|
addr_t *ptr;
|
||||||
|
|
||||||
|
if (0 == s1->do_bounds_check)
|
||||||
|
return;
|
||||||
|
ptr = section_ptr_add(bounds_section, sizeof(*ptr));
|
||||||
|
*ptr = 0;
|
||||||
|
set_elf_sym(symtab_section, 0, 0,
|
||||||
|
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
||||||
|
bounds_section->sh_num, "__bounds_start");
|
||||||
|
/* pull bcheck.o from libtcc1.a */
|
||||||
|
set_elf_sym(symtab_section, 0, 0,
|
||||||
|
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
||||||
|
SHN_UNDEF, "__bound_init");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ST_FUNC void tccelf_stab_new(TCCState *s)
|
ST_FUNC void tccelf_stab_new(TCCState *s)
|
||||||
@ -1288,7 +1305,7 @@ static int tcc_add_support(TCCState *s1, const char *filename)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void add_array (const char *section, TCCState *s1, Sym *sym)
|
static void add_array (const char *section, TCCState *s1, Sym *sym, int sh_type)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
@ -1296,6 +1313,9 @@ static void add_array (const char *section, TCCState *s1, Sym *sym)
|
|||||||
s = find_section(s1, section);
|
s = find_section(s1, section);
|
||||||
if (s) {
|
if (s) {
|
||||||
s->sh_flags |= SHF_WRITE;
|
s->sh_flags |= SHF_WRITE;
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
|
s->sh_type = sh_type;
|
||||||
|
#endif
|
||||||
ptr = section_ptr_add(s, PTR_SIZE);
|
ptr = section_ptr_add(s, PTR_SIZE);
|
||||||
memset (ptr, 0, PTR_SIZE);
|
memset (ptr, 0, PTR_SIZE);
|
||||||
put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);
|
put_elf_reloc (s1->symtab, s, ptr - s->data, R_DATA_PTR, sym->c);
|
||||||
@ -1304,12 +1324,12 @@ static void add_array (const char *section, TCCState *s1, Sym *sym)
|
|||||||
|
|
||||||
ST_FUNC void add_init_array (TCCState *s1, Sym *sym)
|
ST_FUNC void add_init_array (TCCState *s1, Sym *sym)
|
||||||
{
|
{
|
||||||
add_array (".init_array", s1, sym);
|
add_array (".init_array", s1, sym, SHT_INIT_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)
|
ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)
|
||||||
{
|
{
|
||||||
add_array (".fini_array", s1, sym);
|
add_array (".fini_array", s1, sym, SHT_FINI_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add tcc runtime libraries */
|
/* add tcc runtime libraries */
|
||||||
@ -1336,7 +1356,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
|||||||
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
|
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
|
||||||
tcc_add_library_err(s1, "pthread");
|
tcc_add_library_err(s1, "pthread");
|
||||||
tcc_add_library_err(s1, "dl");
|
tcc_add_library_err(s1, "dl");
|
||||||
tcc_add_support(s1, "bcheck.o");
|
tcc_add_support(s1, TCC_LIBBCHECK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
tcc_add_support(s1, TCC_LIBTCC1);
|
tcc_add_support(s1, TCC_LIBTCC1);
|
||||||
@ -2040,6 +2060,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
|
|||||||
Section *s;
|
Section *s;
|
||||||
ElfW(Ehdr) ehdr;
|
ElfW(Ehdr) ehdr;
|
||||||
ElfW(Shdr) shdr, *sh;
|
ElfW(Shdr) shdr, *sh;
|
||||||
|
ElfW(Sym) *sym;
|
||||||
|
|
||||||
file_type = s1->output_type;
|
file_type = s1->output_type;
|
||||||
shnum = s1->nb_sections;
|
shnum = s1->nb_sections;
|
||||||
@ -2110,6 +2131,10 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
|
|||||||
offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
|
offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
|
||||||
|
|
||||||
sort_syms(s1, symtab_section);
|
sort_syms(s1, symtab_section);
|
||||||
|
if (s1->dynsym)
|
||||||
|
for_each_elem(s1->dynsym, 0, sym, ElfW(Sym))
|
||||||
|
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
|
||||||
|
s1->dynsym->sh_info++;
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[sec_order[i]];
|
s = s1->sections[sec_order[i]];
|
||||||
if (s->sh_type != SHT_NOBITS) {
|
if (s->sh_type != SHT_NOBITS) {
|
||||||
|
140
tccgen.c
140
tccgen.c
@ -110,6 +110,16 @@ ST_DATA struct temp_local_variable {
|
|||||||
short align;
|
short align;
|
||||||
} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
|
} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
|
||||||
short nb_temp_local_vars;
|
short nb_temp_local_vars;
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
static short call_nesting;
|
||||||
|
static char used_location[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
|
||||||
|
static int nb_bound_local_param;
|
||||||
|
struct {
|
||||||
|
unsigned long data_offset;
|
||||||
|
int v;
|
||||||
|
} *bound_local_param;
|
||||||
|
ST_DATA addr_t func_bound_offset;
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct scope {
|
static struct scope {
|
||||||
struct scope *prev;
|
struct scope *prev;
|
||||||
@ -1383,11 +1393,6 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
|||||||
bt = VT_PTR;
|
bt = VT_PTR;
|
||||||
sv.type.t = bt;
|
sv.type.t = bt;
|
||||||
size = type_size(&sv.type, &align);
|
size = type_size(&sv.type, &align);
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
if (tcc_state->do_bounds_check)
|
|
||||||
l = loc = (loc - size) & -align;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
l = get_temp_local_var(size,align);
|
l = get_temp_local_var(size,align);
|
||||||
sv.r = VT_LOCAL | VT_LVAL;
|
sv.r = VT_LOCAL | VT_LVAL;
|
||||||
sv.c.i = l;
|
sv.c.i = l;
|
||||||
@ -1496,7 +1501,11 @@ static int get_temp_local_var(int size,int align){
|
|||||||
found=0;
|
found=0;
|
||||||
for(i=0;i<nb_temp_local_vars;i++){
|
for(i=0;i<nb_temp_local_vars;i++){
|
||||||
temp_var=&arr_temp_local_vars[i];
|
temp_var=&arr_temp_local_vars[i];
|
||||||
if(temp_var->size<size||align!=temp_var->align){
|
if(temp_var->size<size||align!=temp_var->align
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
|| (tcc_state->do_bounds_check && used_location[i])
|
||||||
|
#endif
|
||||||
|
){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*check if temp_var is free*/
|
/*check if temp_var is free*/
|
||||||
@ -1596,6 +1605,50 @@ ST_FUNC void gbound_args(int nb_args)
|
|||||||
vrott(i);
|
vrott(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ST_FUNC void save_temp_local(int nb_args)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (call_nesting++ == 0)
|
||||||
|
for (i = 1; i <= nb_args; ++i)
|
||||||
|
for (j = 0; j < nb_temp_local_vars; j++)
|
||||||
|
if (vtop[1 - i].c.i == arr_temp_local_vars[j].location) {
|
||||||
|
used_location[j] = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ST_FUNC void restore_temp_local()
|
||||||
|
{
|
||||||
|
if (--call_nesting == 0)
|
||||||
|
memset (used_location, 0, sizeof (used_location));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_bound_param(CType *type, int size, int v, int c)
|
||||||
|
{
|
||||||
|
addr_t *bounds_ptr;
|
||||||
|
/* Add arrays/structs/unions because we always take address */
|
||||||
|
int taken = (type->t & VT_ARRAY)
|
||||||
|
|| (type->t & VT_BTYPE) == VT_STRUCT;
|
||||||
|
|
||||||
|
if (taken == 0) {
|
||||||
|
/* Add parameter to check */
|
||||||
|
nb_bound_local_param++;
|
||||||
|
bound_local_param =
|
||||||
|
tcc_realloc (bound_local_param,
|
||||||
|
nb_bound_local_param *
|
||||||
|
sizeof (*bound_local_param));
|
||||||
|
bound_local_param[nb_bound_local_param-1].data_offset =
|
||||||
|
lbounds_section->data_offset;
|
||||||
|
bound_local_param[nb_bound_local_param-1].v = v;
|
||||||
|
}
|
||||||
|
/* add local bound info */
|
||||||
|
bounds_ptr = section_ptr_add(lbounds_section,
|
||||||
|
2 * sizeof(addr_t));
|
||||||
|
bounds_ptr[0] = c;
|
||||||
|
bounds_ptr[1] = taken ? size : ~size;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void incr_bf_adr(int o)
|
static void incr_bf_adr(int o)
|
||||||
@ -3418,6 +3471,7 @@ ST_FUNC void vstore(void)
|
|||||||
|
|
||||||
vswap();
|
vswap();
|
||||||
/* source */
|
/* source */
|
||||||
|
vtop->r &= ~VT_MUSTBOUND;
|
||||||
vpushv(vtop - 2);
|
vpushv(vtop - 2);
|
||||||
vtop->type.t = VT_PTR;
|
vtop->type.t = VT_PTR;
|
||||||
gaddrof();
|
gaddrof();
|
||||||
@ -5083,6 +5137,23 @@ ST_FUNC void unary(void)
|
|||||||
if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
|
if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
|
||||||
!(vtop->type.t & VT_ARRAY))
|
!(vtop->type.t & VT_ARRAY))
|
||||||
test_lvalue();
|
test_lvalue();
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
if (tcc_state->do_bounds_check && vtop->sym) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Mark parameter as being used for address off */
|
||||||
|
for (i = 0; i < nb_bound_local_param; i++) {
|
||||||
|
if (bound_local_param[i].v == vtop->sym->v) {
|
||||||
|
addr_t *bounds_ptr =
|
||||||
|
(addr_t *) (lbounds_section->data +
|
||||||
|
bound_local_param[i].data_offset);
|
||||||
|
bounds_ptr[1] = ~bounds_ptr[1];
|
||||||
|
bound_local_param[i].v = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
mk_pointer(&vtop->type);
|
mk_pointer(&vtop->type);
|
||||||
gaddrof();
|
gaddrof();
|
||||||
break;
|
break;
|
||||||
@ -7435,8 +7506,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
if ((r & VT_VALMASK) == VT_LOCAL) {
|
if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||||
sec = NULL;
|
sec = NULL;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (bcheck && ((type->t & VT_ARRAY) ||
|
if (bcheck && v) {
|
||||||
(type->t & VT_BTYPE) == VT_STRUCT)) {
|
/* add padding between stack variables */
|
||||||
loc--;
|
loc--;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -7444,17 +7515,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||||||
addr = loc;
|
addr = loc;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
/* handles bounds */
|
/* handles bounds */
|
||||||
/* XXX: currently, since we do only one pass, we cannot track
|
if (bcheck && v) {
|
||||||
'&' operators, so we add only arrays/structs/unions */
|
add_bound_param (type, size, v, addr);
|
||||||
if (bcheck && ((type->t & VT_ARRAY) ||
|
/* add padding between stack variables */
|
||||||
(type->t & VT_BTYPE) == VT_STRUCT)) {
|
|
||||||
addr_t *bounds_ptr;
|
|
||||||
/* add padding between regions */
|
|
||||||
loc--;
|
loc--;
|
||||||
/* then add local bound info */
|
|
||||||
bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(addr_t));
|
|
||||||
bounds_ptr[0] = addr;
|
|
||||||
bounds_ptr[1] = size;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (v) {
|
if (v) {
|
||||||
@ -7633,12 +7697,52 @@ static void gen_function(Sym *sym, AttributeDef *ad)
|
|||||||
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
||||||
local_scope = 1; /* for function parameters */
|
local_scope = 1; /* for function parameters */
|
||||||
gfunc_prolog(sym);
|
gfunc_prolog(sym);
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
if (tcc_state->do_bounds_check
|
||||||
|
&& sym->type.ref->f.func_type != FUNC_ELLIPSIS) {
|
||||||
|
Sym *fpar;
|
||||||
|
|
||||||
|
/* Add function arguments in case & is used */
|
||||||
|
for (fpar = sym->type.ref->next; fpar; fpar = fpar->next) {
|
||||||
|
Sym *fsym = sym_find (fpar->v & ~SYM_FIELD);
|
||||||
|
|
||||||
|
if (fsym && (fsym->r & VT_VALMASK) == VT_LOCAL) {
|
||||||
|
int align;
|
||||||
|
int size = type_size(&fsym->type, &align);
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
add_bound_param (&fsym->type, size, fsym->v, fsym->c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
local_scope = 0;
|
local_scope = 0;
|
||||||
rsym = 0;
|
rsym = 0;
|
||||||
clear_temp_local_var_list();
|
clear_temp_local_var_list();
|
||||||
block(0);
|
block(0);
|
||||||
gsym(rsym);
|
gsym(rsym);
|
||||||
nocode_wanted = 0;
|
nocode_wanted = 0;
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
if (tcc_state->do_bounds_check) {
|
||||||
|
addr_t o = func_bound_offset;
|
||||||
|
|
||||||
|
/* Remove parameters where address off is not used */
|
||||||
|
while (o != lbounds_section->data_offset) {
|
||||||
|
addr_t *bounds_ptr = (addr_t *) (lbounds_section->data + o);
|
||||||
|
if ((ssize_t) bounds_ptr[1] < 0) {
|
||||||
|
lbounds_section->data_offset -= 2 * sizeof (addr_t);
|
||||||
|
memmove(bounds_ptr, bounds_ptr + 2,
|
||||||
|
lbounds_section->data_offset - o);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
o += 2 * sizeof (addr_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tcc_free (bound_local_param);
|
||||||
|
nb_bound_local_param = 0;
|
||||||
|
bound_local_param = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
gfunc_epilog();
|
gfunc_epilog();
|
||||||
cur_text_section->data_offset = ind;
|
cur_text_section->data_offset = ind;
|
||||||
/* reset local stack */
|
/* reset local stack */
|
||||||
|
2
tccpe.c
2
tccpe.c
@ -1897,7 +1897,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
|||||||
const char **pp, *p;
|
const char **pp, *p;
|
||||||
#ifdef TCC_IS_NATIVE
|
#ifdef TCC_IS_NATIVE
|
||||||
if (s1->do_bounds_check)
|
if (s1->do_bounds_check)
|
||||||
tcc_add_support(s1, "bcheck.o");
|
tcc_add_support(s1, TCC_LIBBCHECK);
|
||||||
#endif
|
#endif
|
||||||
tcc_add_support(s1, TCC_LIBTCC1);
|
tcc_add_support(s1, TCC_LIBTCC1);
|
||||||
for (pp = libs; 0 != (p = *pp); ++pp) {
|
for (pp = libs; 0 != (p = *pp); ++pp) {
|
||||||
|
68
tccrun.c
68
tccrun.c
@ -86,6 +86,7 @@ LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
|
|||||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
|
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
|
||||||
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx);
|
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, prx);
|
||||||
ptr_diff = (char*)prx - (char*)ptr;
|
ptr_diff = (char*)prx - (char*)ptr;
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ptr = tcc_malloc(size);
|
ptr = tcc_malloc(size);
|
||||||
@ -119,6 +120,17 @@ ST_FUNC void tcc_run_free(TCCState *s1)
|
|||||||
/* launch the compiled program with the given arguments */
|
/* launch the compiled program with the given arguments */
|
||||||
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
/* PE target overwrites runtime_main */
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
|
typedef void (*init_array_func)(int, char **, char **);
|
||||||
|
typedef void (*fini_array_func)(void);
|
||||||
|
init_array_func *__init_array_start;
|
||||||
|
init_array_func *__init_array_end;
|
||||||
|
fini_array_func *__fini_array_start;
|
||||||
|
fini_array_func *__fini_array_end;
|
||||||
|
#endif
|
||||||
|
int i;
|
||||||
|
int ret;
|
||||||
int (*prog_main)(int, char **);
|
int (*prog_main)(int, char **);
|
||||||
|
|
||||||
s1->runtime_main = s1->nostdlib ? "_start" : "main";
|
s1->runtime_main = s1->nostdlib ? "_start" : "main";
|
||||||
@ -140,31 +152,34 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
|||||||
errno = 0; /* clean errno value */
|
errno = 0; /* clean errno value */
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (s1->do_bounds_check) {
|
if (s1->do_bounds_check)
|
||||||
void (*bound_init)(void);
|
|
||||||
void (*bound_exit)(void);
|
|
||||||
void (*bounds_add_static_var)(size_t *p);
|
|
||||||
size_t *bounds_start;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* set error function */
|
/* set error function */
|
||||||
s1->rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
|
s1->rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
|
||||||
/* XXX: use .init section so that it also work in binary ? */
|
#endif
|
||||||
bound_init = tcc_get_symbol_err(s1, "__bound_init");
|
|
||||||
bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
|
|
||||||
bounds_add_static_var = tcc_get_symbol_err(s1, "__bounds_add_static_var");
|
|
||||||
bounds_start = tcc_get_symbol_err(s1, "__bounds_start");
|
|
||||||
|
|
||||||
bound_init();
|
#ifndef TCC_TARGET_PE
|
||||||
bounds_add_static_var (bounds_start);
|
__init_array_start = tcc_get_symbol_err(s1, "__init_array_start");
|
||||||
|
__init_array_end = tcc_get_symbol_err(s1, "__init_array_end");
|
||||||
|
__fini_array_start = tcc_get_symbol_err(s1, "__fini_array_start");
|
||||||
|
__fini_array_end = tcc_get_symbol_err(s1, "__fini_array_end");
|
||||||
|
|
||||||
ret = (*prog_main)(argc, argv);
|
if (__init_array_start && __init_array_end) {
|
||||||
|
i = 0;
|
||||||
bound_exit();
|
while (&__init_array_start[i] != __init_array_end)
|
||||||
return ret;
|
(*__init_array_start[i++])(argc, argv, environ);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return (*prog_main)(argc, argv);
|
|
||||||
|
ret = (*prog_main)(argc, argv);
|
||||||
|
|
||||||
|
#ifndef TCC_TARGET_PE
|
||||||
|
if (__fini_array_start && __fini_array_end) {
|
||||||
|
i = 0;
|
||||||
|
while (&__fini_array_end[i] != __fini_array_start)
|
||||||
|
(*__fini_array_end[--i])();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||||
@ -649,6 +664,9 @@ static void set_exception_handler(void)
|
|||||||
/* install TCC signal handlers to print debug info on fatal
|
/* install TCC signal handlers to print debug info on fatal
|
||||||
runtime errors */
|
runtime errors */
|
||||||
sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
|
sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
|
||||||
|
#ifdef SIGSTKSZ
|
||||||
|
sigact.sa_flags |= SA_ONSTACK;
|
||||||
|
#endif
|
||||||
sigact.sa_sigaction = sig_error;
|
sigact.sa_sigaction = sig_error;
|
||||||
sigemptyset(&sigact.sa_mask);
|
sigemptyset(&sigact.sa_mask);
|
||||||
sigaction(SIGFPE, &sigact, NULL);
|
sigaction(SIGFPE, &sigact, NULL);
|
||||||
@ -656,6 +674,18 @@ static void set_exception_handler(void)
|
|||||||
sigaction(SIGSEGV, &sigact, NULL);
|
sigaction(SIGSEGV, &sigact, NULL);
|
||||||
sigaction(SIGBUS, &sigact, NULL);
|
sigaction(SIGBUS, &sigact, NULL);
|
||||||
sigaction(SIGABRT, &sigact, NULL);
|
sigaction(SIGABRT, &sigact, NULL);
|
||||||
|
#ifdef SIGSTKSZ
|
||||||
|
/* This allows stack overflow to be reported instead of a SEGV */
|
||||||
|
{
|
||||||
|
stack_t ss;
|
||||||
|
static unsigned char stack[SIGSTKSZ] __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
ss.ss_sp = stack;
|
||||||
|
ss.ss_size = SIGSTKSZ;
|
||||||
|
ss.ss_flags = 0;
|
||||||
|
sigaltstack(&ss, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* WIN32 */
|
#else /* WIN32 */
|
||||||
|
@ -168,7 +168,7 @@ memtest:
|
|||||||
|
|
||||||
|
|
||||||
# memory and bound check auto test
|
# memory and bound check auto test
|
||||||
BOUNDS_OK = 1 4 8 10 14 16
|
BOUNDS_OK = 1 4 8 10 14 16 18
|
||||||
BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17
|
BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17
|
||||||
|
|
||||||
btest: boundtest.c
|
btest: boundtest.c
|
||||||
|
@ -230,6 +230,202 @@ int test17()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHECK(s) if (strstr (__bound_error_msg, s) == 0) abort();
|
||||||
|
|
||||||
|
extern void __bound_never_fatal (int neverfatal);
|
||||||
|
extern const char *__bound_error_msg;
|
||||||
|
|
||||||
|
static void init18(char *a, char *b)
|
||||||
|
{
|
||||||
|
memset (a, 'a', 10);
|
||||||
|
a[3] = 0;
|
||||||
|
a[9] = 0;
|
||||||
|
memset (b, 'b', 10);
|
||||||
|
__bound_error_msg = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ok (catch all errors) */
|
||||||
|
int test18()
|
||||||
|
{
|
||||||
|
char pad1[10];
|
||||||
|
char a[10];
|
||||||
|
char pad2[10];
|
||||||
|
char b[10];
|
||||||
|
char pad3[10];
|
||||||
|
|
||||||
|
memset (pad1, 0, sizeof(pad1));
|
||||||
|
memset (pad2, 0, sizeof(pad2));
|
||||||
|
memset (pad3, 0, sizeof(pad3));
|
||||||
|
|
||||||
|
/* -2 in case TCC_BOUNDS_NEVER_FATAL is set */
|
||||||
|
__bound_never_fatal (-2);
|
||||||
|
|
||||||
|
/* memcpy */
|
||||||
|
init18(a,b);
|
||||||
|
memcpy(&a[1],&b[0],10);
|
||||||
|
CHECK("memcpy dest");
|
||||||
|
init18(a,b);
|
||||||
|
memcpy(&a[0],&b[1],10);
|
||||||
|
CHECK("memcpy src");
|
||||||
|
init18(a,b);
|
||||||
|
memcpy(&a[0],&a[3],4);
|
||||||
|
CHECK("overlapping regions");
|
||||||
|
init18(a,b);
|
||||||
|
memcpy(&a[3],&a[0],4);
|
||||||
|
CHECK("overlapping regions");
|
||||||
|
|
||||||
|
/* memcmp */
|
||||||
|
init18(a,b);
|
||||||
|
memcmp(&b[1],&b[0],10);
|
||||||
|
CHECK("memcmp s1");
|
||||||
|
init18(a,b);
|
||||||
|
memcmp(&b[0],&b[1],10);
|
||||||
|
CHECK("memcmp s2");
|
||||||
|
|
||||||
|
/* memmove */
|
||||||
|
init18(a,b);
|
||||||
|
memmove(&b[1],&b[0],10);
|
||||||
|
CHECK("memmove dest");
|
||||||
|
init18(a,b);
|
||||||
|
memmove(&b[0],&b[1],10);
|
||||||
|
CHECK("memmove src");
|
||||||
|
|
||||||
|
/* memset */
|
||||||
|
init18(a,b);
|
||||||
|
memset(&b[1],'b',10);
|
||||||
|
CHECK("memset");
|
||||||
|
|
||||||
|
/* strlen */
|
||||||
|
init18(a,b);
|
||||||
|
strlen(&b[0]);
|
||||||
|
CHECK("strlen");
|
||||||
|
|
||||||
|
/* strcpy */
|
||||||
|
init18(a,b);
|
||||||
|
strcpy(&a[7], &a[0]);
|
||||||
|
CHECK("strcpy dest");
|
||||||
|
init18(a,b);
|
||||||
|
strcpy(&a[0], &b[7]);
|
||||||
|
CHECK("strcpy src");
|
||||||
|
init18(a,b);
|
||||||
|
strcpy(&a[0], &a[1]);
|
||||||
|
CHECK("overlapping regions");
|
||||||
|
init18(a,b);
|
||||||
|
strcpy(&a[2], &a[0]);
|
||||||
|
CHECK("overlapping regions");
|
||||||
|
|
||||||
|
/* strncpy */
|
||||||
|
init18(a,b);
|
||||||
|
strncpy(&a[7], &a[0], 10);
|
||||||
|
CHECK("strncpy dest");
|
||||||
|
init18(a,b);
|
||||||
|
strncpy(&a[0], &b[7], 10);
|
||||||
|
CHECK("strncpy src");
|
||||||
|
init18(a,b);
|
||||||
|
strncpy(&a[0], &a[1], 10);
|
||||||
|
CHECK("overlapping regions");
|
||||||
|
strncpy(&a[2], &a[0], 10);
|
||||||
|
CHECK("overlapping regions");
|
||||||
|
|
||||||
|
/* strcmp */
|
||||||
|
init18(a,b);
|
||||||
|
strcmp(&b[2], &b[0]);
|
||||||
|
CHECK("strcmp s1");
|
||||||
|
init18(a,b);
|
||||||
|
strcmp(&b[0], &b[2]);
|
||||||
|
CHECK("strcmp s2");
|
||||||
|
|
||||||
|
/* strncmp */
|
||||||
|
init18(a,b);
|
||||||
|
strncmp(&b[5], &b[0], 10);
|
||||||
|
CHECK("strncmp s1");
|
||||||
|
init18(a,b);
|
||||||
|
strncmp(&b[0], &b[5], 10);
|
||||||
|
CHECK("strncmp s2");
|
||||||
|
|
||||||
|
/* strcat */
|
||||||
|
init18(a,b);
|
||||||
|
strcat(&a[7], &a[0]);
|
||||||
|
CHECK("strcat dest");
|
||||||
|
init18(a,b);
|
||||||
|
strcat(&a[0], &b[5]);
|
||||||
|
CHECK("strcat src");
|
||||||
|
init18(a,b);
|
||||||
|
strcat(&a[0], &a[4]);
|
||||||
|
CHECK("overlapping regions");
|
||||||
|
init18(a,b);
|
||||||
|
strcat(&a[3], &a[0]);
|
||||||
|
CHECK("overlapping regions");
|
||||||
|
|
||||||
|
/* strchr */
|
||||||
|
init18(a,b);
|
||||||
|
strchr(&b[0], 'a');
|
||||||
|
CHECK("strchr");
|
||||||
|
|
||||||
|
/* strdup */
|
||||||
|
init18(a,b);
|
||||||
|
free(strdup(&b[0]));
|
||||||
|
CHECK("strdup");
|
||||||
|
|
||||||
|
__bound_never_fatal (2);
|
||||||
|
|
||||||
|
/* memcpy */
|
||||||
|
init18(a,b);
|
||||||
|
memcpy(&a[0],&b[0],10);
|
||||||
|
init18(a,b);
|
||||||
|
memcpy(&a[0],&a[3],3);
|
||||||
|
init18(a,b);
|
||||||
|
memcpy(&a[3],&a[0],3);
|
||||||
|
|
||||||
|
/* memcmp */
|
||||||
|
init18(a,b);
|
||||||
|
memcmp(&b[0],&b[0],10);
|
||||||
|
|
||||||
|
/* memmove */
|
||||||
|
init18(a,b);
|
||||||
|
memmove(&b[0],&b[5],5);
|
||||||
|
init18(a,b);
|
||||||
|
memmove(&b[5],&b[0],5);
|
||||||
|
|
||||||
|
/* memset */
|
||||||
|
init18(a,b);
|
||||||
|
memset(&b[0],'b',10);
|
||||||
|
|
||||||
|
/* strlen */
|
||||||
|
init18(a,b);
|
||||||
|
strlen (&a[0]);
|
||||||
|
|
||||||
|
/* strcpy */
|
||||||
|
init18(a,b);
|
||||||
|
strcpy (&a[0], &a[7]);
|
||||||
|
|
||||||
|
/* strncpy */
|
||||||
|
init18(a,b);
|
||||||
|
strncpy (&a[0], &a[7], 4);
|
||||||
|
|
||||||
|
/* strcmp */
|
||||||
|
init18(a,b);
|
||||||
|
strcmp (&a[0], &a[4]);
|
||||||
|
|
||||||
|
/* strncmp */
|
||||||
|
init18(a,b);
|
||||||
|
strncmp (&a[0], &a[4], 10);
|
||||||
|
|
||||||
|
/* strcat */
|
||||||
|
init18(a,b);
|
||||||
|
strcat (&a[0], &a[7]);
|
||||||
|
|
||||||
|
/* strchr */
|
||||||
|
init18(a,b);
|
||||||
|
strchr (&a[0], 0);
|
||||||
|
|
||||||
|
/* strdup */
|
||||||
|
init18(a,b);
|
||||||
|
free (strdup (&a[0]));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int (*table_test[])(void) = {
|
int (*table_test[])(void) = {
|
||||||
test1,
|
test1,
|
||||||
test2,
|
test2,
|
||||||
@ -248,6 +444,7 @@ int (*table_test[])(void) = {
|
|||||||
test15,
|
test15,
|
||||||
test16,
|
test16,
|
||||||
test17,
|
test17,
|
||||||
|
test18,
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
17
x86_64-gen.c
17
x86_64-gen.c
@ -637,7 +637,6 @@ static void gcall_or_jmp(int is_jmp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_TCC_BCHECK)
|
#if defined(CONFIG_TCC_BCHECK)
|
||||||
static addr_t func_bound_offset;
|
|
||||||
static unsigned long func_bound_ind;
|
static unsigned long func_bound_ind;
|
||||||
|
|
||||||
static void gen_bounds_call(int v)
|
static void gen_bounds_call(int v)
|
||||||
@ -784,8 +783,10 @@ void gfunc_call(int nb_args)
|
|||||||
int arg;
|
int arg;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (tcc_state->do_bounds_check)
|
if (tcc_state->do_bounds_check) {
|
||||||
|
save_temp_local (nb_args);
|
||||||
gbound_args(nb_args);
|
gbound_args(nb_args);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;
|
args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;
|
||||||
@ -906,6 +907,10 @@ void gfunc_call(int nb_args)
|
|||||||
|
|
||||||
}
|
}
|
||||||
vtop--;
|
vtop--;
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
if (tcc_state->do_bounds_check)
|
||||||
|
restore_temp_local ();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1271,8 +1276,10 @@ void gfunc_call(int nb_args)
|
|||||||
char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;
|
char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (tcc_state->do_bounds_check)
|
if (tcc_state->do_bounds_check) {
|
||||||
|
save_temp_local (nb_args);
|
||||||
gbound_args(nb_args);
|
gbound_args(nb_args);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* calculate the number of integer/float register arguments, remember
|
/* calculate the number of integer/float register arguments, remember
|
||||||
@ -1453,6 +1460,10 @@ void gfunc_call(int nb_args)
|
|||||||
if (args_size)
|
if (args_size)
|
||||||
gadd_sp(args_size);
|
gadd_sp(args_size);
|
||||||
vtop--;
|
vtop--;
|
||||||
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
if (tcc_state->do_bounds_check)
|
||||||
|
restore_temp_local ();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FUNC_PROLOG_SIZE 11
|
#define FUNC_PROLOG_SIZE 11
|
||||||
|
@ -287,89 +287,4 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
|
||||||
ST_FUNC void tcc_add_bcheck(TCCState *s1)
|
|
||||||
{
|
|
||||||
addr_t *ptr;
|
|
||||||
int loc_glob;
|
|
||||||
int sym_index;
|
|
||||||
int bsym_index;
|
|
||||||
|
|
||||||
if (0 == s1->do_bounds_check)
|
|
||||||
return;
|
|
||||||
/* XXX: add an object file to do that */
|
|
||||||
ptr = section_ptr_add(bounds_section, sizeof(*ptr));
|
|
||||||
*ptr = 0;
|
|
||||||
loc_glob = s1->output_type != TCC_OUTPUT_MEMORY ? STB_LOCAL : STB_GLOBAL;
|
|
||||||
bsym_index = set_elf_sym(symtab_section, 0, 0,
|
|
||||||
ELFW(ST_INFO)(loc_glob, STT_NOTYPE), 0,
|
|
||||||
bounds_section->sh_num, "__bounds_start");
|
|
||||||
/* pull bcheck.o from libtcc1.a */
|
|
||||||
sym_index = set_elf_sym(symtab_section, 0, 0,
|
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
|
||||||
SHN_UNDEF, "__bound_init");
|
|
||||||
if (s1->output_type != TCC_OUTPUT_MEMORY) {
|
|
||||||
/* add 'call __bound_init()' in .init section */
|
|
||||||
Section *init_section = find_section(s1, ".init");
|
|
||||||
unsigned char *pinit;
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
pinit = section_ptr_add(init_section, 8);
|
|
||||||
pinit[0] = 0x55; /* push %rbp */
|
|
||||||
pinit[1] = 0x48; /* mov %rsp,%rpb */
|
|
||||||
pinit[2] = 0x89;
|
|
||||||
pinit[3] = 0xe5;
|
|
||||||
pinit[4] = 0x48; /* sub $0x10,%rsp */
|
|
||||||
pinit[5] = 0x83;
|
|
||||||
pinit[6] = 0xec;
|
|
||||||
pinit[7] = 0x10;
|
|
||||||
#endif
|
|
||||||
pinit = section_ptr_add(init_section, 5);
|
|
||||||
pinit[0] = 0xe8;
|
|
||||||
write32le(pinit + 1, -4);
|
|
||||||
put_elf_reloc(symtab_section, init_section,
|
|
||||||
init_section->data_offset - 4, R_386_PC32, sym_index);
|
|
||||||
/* R_386_PC32 = R_X86_64_PC32 = 2 */
|
|
||||||
pinit = section_ptr_add(init_section, 13);
|
|
||||||
pinit[0] = 0x48; /* mov xx,%rax */
|
|
||||||
pinit[1] = 0xb8;
|
|
||||||
write64le(pinit + 2, 0);
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
pinit[10] = 0x48; /* mov %rax,%rcx */
|
|
||||||
pinit[11] = 0x89;
|
|
||||||
pinit[12] = 0xc1;
|
|
||||||
#else
|
|
||||||
pinit[10] = 0x48; /* mov %rax,%rdi */
|
|
||||||
pinit[11] = 0x89;
|
|
||||||
pinit[12] = 0xc7;
|
|
||||||
#endif
|
|
||||||
put_elf_reloc(symtab_section, init_section,
|
|
||||||
init_section->data_offset - 11, R_X86_64_64, bsym_index);
|
|
||||||
sym_index = set_elf_sym(symtab_section, 0, 0,
|
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
|
||||||
SHN_UNDEF, "__bounds_add_static_var");
|
|
||||||
pinit = section_ptr_add(init_section, 5);
|
|
||||||
pinit[0] = 0xe8;
|
|
||||||
write32le(pinit + 1, -4);
|
|
||||||
put_elf_reloc(symtab_section, init_section,
|
|
||||||
init_section->data_offset - 4, R_386_PC32, sym_index);
|
|
||||||
/* R_386_PC32 = R_X86_64_PC32 = 2 */
|
|
||||||
#ifdef TCC_TARGET_PE
|
|
||||||
{
|
|
||||||
int init_index = set_elf_sym(symtab_section,
|
|
||||||
0, 0,
|
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
|
|
||||||
init_section->sh_num, "__init_start");
|
|
||||||
Sym sym;
|
|
||||||
init_section->sh_flags |= SHF_EXECINSTR;
|
|
||||||
pinit = section_ptr_add(init_section, 2);
|
|
||||||
pinit[0] = 0xc9; /* leave */
|
|
||||||
pinit[1] = 0xc3; /* ret */
|
|
||||||
sym.c = init_index;
|
|
||||||
add_init_array (s1, &sym);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !TARGET_DEFS_ONLY */
|
#endif /* !TARGET_DEFS_ONLY */
|
||||||
|
Loading…
Reference in New Issue
Block a user