backtrace: test with DLLs

- tests2/113_btdll.c: test handling multiple stabs infos
Also:
- libtcc.c: remove _ISOC99_SOURCE pre-defines.  It is causing
  strange warnings such as 'strdup not declared'

- i386/x86_64-gen.c cleanup bounds_pro/epilog.  This discards
  the extra code for main's argv.  If needed, __argv might be
  processed instead.

- tccgen.c:block(): reduce stackspace usage.  For example with
  code like "if (..) ... else if (..) ... else if (..)... "
  considerable numbers of nested block() calls may occur.

  Before that most stack space used when compiling itself was
  for libtcc.c:tcc_set_linker().

  Now it's rather this construct at tccpp.c:2765: in next_nomacro1():

  if (!((isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
        || c == '.'
        || ((c == '+' || c == '-')
        ...
mob
grischka 2020-01-19 11:15:12 +01:00
parent a5f6e6189e
commit d79e1dee8c
13 changed files with 209 additions and 218 deletions

View File

@ -97,6 +97,8 @@ static int func_ret_sub;
#ifdef CONFIG_TCC_BCHECK
static addr_t func_bound_offset;
static unsigned long func_bound_ind;
static void gen_bounds_prolog(void);
static void gen_bounds_epilog(void);
#endif
/* XXX: make it faster ? */
@ -480,6 +482,7 @@ ST_FUNC void gfunc_call(int nb_args)
else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT)
args_size -= 4;
#endif
gcall_or_jmp(0);
if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
@ -499,7 +502,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
CType *func_type = &func_sym->type;
int addr, align, size, func_call, fastcall_nb_regs;
int param_index, param_addr;
int n_arg = 0;
uint8_t *fastcall_regs_ptr;
Sym *sym;
CType *type;
@ -542,7 +544,6 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
}
/* define parameters */
while ((sym = sym->next) != NULL) {
n_arg++;
type = &sym->type;
size = type_size(type, &align);
size = (size + 3) & ~3;
@ -576,19 +577,8 @@ ST_FUNC void gfunc_prolog(Sym *func_sym)
#endif
#ifdef CONFIG_TCC_BCHECK
/* leave some room for bound checking code */
if (tcc_state->do_bounds_check) {
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
oad(0xb8, 0); /* lbound section pointer */
oad(0xb8, 0); /* call to function */
if (n_arg >= 2 && strcmp (get_tok_str(func_sym->v, NULL), "main") == 0) {
o(0x0c458b); /* mov 0x12(%ebp),%eax */
o(0x50); /* push %eax */
gen_static_call(TOK___bound_main_arg);
o(0x04c483); /* add $0x4,%esp */
}
}
if (tcc_state->do_bounds_check)
gen_bounds_prolog();
#endif
}
@ -598,34 +588,8 @@ ST_FUNC void gfunc_epilog(void)
addr_t v, saved_ind;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check
&& func_bound_offset != lbounds_section->data_offset) {
addr_t saved_ind;
addr_t *bounds_ptr;
Sym *sym_data;
/* add end of table info */
bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
*bounds_ptr = 0;
/* generate bound local allocation */
saved_ind = ind;
ind = func_bound_ind;
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
func_bound_offset, lbounds_section->data_offset);
greloc(cur_text_section, sym_data,
ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
gen_static_call(TOK___bound_local_new);
ind = saved_ind;
/* generate bound check local freeing */
o(0x5250); /* save returned value, if any */
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
gen_static_call(TOK___bound_local_delete);
o(0x585a); /* restore returned value, if any */
}
if (tcc_state->do_bounds_check)
gen_bounds_epilog();
#endif
/* align local size to word & save local variables */
@ -1096,6 +1060,43 @@ ST_FUNC void gen_bounded_ptr_deref(void)
rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.i);
rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
}
static void gen_bounds_prolog(void)
{
/* leave some room for bound checking code */
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
oad(0xb8, 0); /* lbound section pointer */
oad(0xb8, 0); /* call to function */
}
static void gen_bounds_epilog(void)
{
addr_t saved_ind;
addr_t *bounds_ptr;
Sym *sym_data;
/* add end of table info */
bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
*bounds_ptr = 0;
/* generate bound local allocation */
saved_ind = ind;
ind = func_bound_ind;
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
func_bound_offset, lbounds_section->data_offset);
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
ind = ind + 5;
gen_static_call(TOK___bound_local_new);
ind = saved_ind;
/* generate bound check local freeing */
o(0x5250); /* save returned value, if any */
greloc(cur_text_section, sym_data, ind + 1, R_386_32);
oad(0xb8, 0); /* mov %eax, xxx */
gen_static_call(TOK___bound_local_delete);
o(0x585a); /* restore returned value, if any */
}
#endif
/* Save the stack pointer onto the stack */

View File

@ -353,7 +353,8 @@ void * __bound_ptr_add(void *p, size_t offset)
if (addr <= tree->size) {
if (tree->is_invalid || addr + offset > tree->size) {
POST_SEM ();
bound_warning("%p is outside of the region", p + offset);
if (print_warn_ptr_add)
bound_warning("%p is outside of the region", p + offset);
if (never_fatal <= 0)
return INVALID_POINTER; /* return an invalid pointer */
return p + offset;

View File

@ -802,11 +802,6 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
tcc_define_symbol(s, "__STDC_HOSTED__", NULL);
#if !defined(TCC_TARGET_PE)
/* glibc compatible macro (default for C99) */
tcc_define_symbol(s, "_ISOC99_SOURCE", "1");
#endif
/* target defines */
#if defined(TCC_TARGET_I386)
tcc_define_symbol(s, "__i386__", NULL);
@ -1905,11 +1900,6 @@ reparse:
* encoding used is implementationdened.
*/
tcc_define_symbol(s, "__STDC_UTF_32__", "1");
/*
* glibc compatible macro used when -std=c11 is used.
* _ISOC99_SOURCE remains defined as does gcc.
*/
tcc_define_symbol(s, "_ISOC11_SOURCE", "1");
#endif /* !TCC_TARGET_PE */
s->cversion = 201112;
}

3
tcc.h
View File

@ -884,6 +884,9 @@ struct TCCState {
const char *runtime_main;
void **runtime_mem;
int nb_runtime_mem;
#endif
#ifdef CONFIG_TCC_BACKTRACE
int rt_num_callers;
#endif

View File

@ -1387,7 +1387,11 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
"__attribute__((constructor)) static void __bt_init_rt(){");
#ifdef TCC_TARGET_PE
if (s1->output_type == TCC_OUTPUT_DLL)
#ifdef CONFIG_TCC_BCHECK
cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check);
#else
cstr_printf(&cstr, "__bt_init_dll(0);");
#endif
#endif
cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1);

View File

@ -101,6 +101,8 @@ ST_DATA struct switch_t {
int def_sym; /* default symbol */
int *bsym;
struct scope *scope;
struct switch_t *prev;
SValue sv;
} *cur_switch; /* current switch */
#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8
@ -6447,6 +6449,7 @@ static void lblock(int *bsym, int *csym)
static void block(int is_expr)
{
int a, b, c, d, e, t;
struct scope o;
Sym *s;
if (is_expr) {
@ -6487,7 +6490,6 @@ again:
gsym(a);
} else if (t == '{') {
struct scope o;
new_scope(&o);
/* handle local labels declarations */
@ -6545,10 +6547,10 @@ again:
/* compute jump */
if (!cur_scope->bsym)
tcc_error("cannot break");
if (!cur_switch || cur_scope->bsym != cur_switch->bsym)
leave_scope(loop_scope);
else
if (cur_switch && cur_scope->bsym == cur_switch->bsym)
leave_scope(cur_switch->scope);
else
leave_scope(loop_scope);
*cur_scope->bsym = gjmp(*cur_scope->bsym);
skip(';');
@ -6561,7 +6563,6 @@ again:
skip(';');
} else if (t == TOK_FOR) {
struct scope o;
new_scope(&o);
skip('(');
@ -6611,22 +6612,18 @@ again:
gsym(a);
} else if (t == TOK_SWITCH) {
struct switch_t *saved, sw;
SValue switchval;
struct switch_t *sw;
sw.p = NULL;
sw.n = 0;
sw.def_sym = 0;
sw.bsym = &a;
sw.scope = cur_scope;
saved = cur_switch;
cur_switch = &sw;
sw = tcc_mallocz(sizeof *sw);
sw->bsym = &a;
sw->scope = cur_scope;
sw->prev = cur_switch;
cur_switch = sw;
skip('(');
gexpr();
skip(')');
switchval = *vtop--;
sw->sv = *vtop--; /* save switch value */
a = 0;
b = gjmp(0); /* jump to first case */
@ -6635,28 +6632,29 @@ again:
/* case lookup */
gsym(b);
qsort(sw.p, sw.n, sizeof(void*), case_cmp);
for (b = 1; b < sw.n; b++)
if (sw.p[b - 1]->v2 >= sw.p[b]->v1)
qsort(sw->p, sw->n, sizeof(void*), case_cmp);
for (b = 1; b < sw->n; b++)
if (sw->p[b - 1]->v2 >= sw->p[b]->v1)
tcc_error("duplicate case value");
/* Our switch table sorting is signed, so the compared
value needs to be as well when it's 64bit. */
if ((switchval.type.t & VT_BTYPE) == VT_LLONG)
switchval.type.t &= ~VT_UNSIGNED;
vpushv(&switchval);
vpushv(&sw->sv);
if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
vtop->type.t &= ~VT_UNSIGNED;
gv(RC_INT);
d = 0, gcase(sw.p, sw.n, &d);
d = 0, gcase(sw->p, sw->n, &d);
vpop();
if (sw.def_sym)
gsym_addr(d, sw.def_sym);
if (sw->def_sym)
gsym_addr(d, sw->def_sym);
else
gsym(d);
/* break label */
gsym(a);
dynarray_reset(&sw.p, &sw.n);
cur_switch = saved;
dynarray_reset(&sw->p, &sw->n);
cur_switch = sw->prev;
tcc_free(sw);
} else if (t == TOK_CASE) {
struct case_t *cr = tcc_malloc(sizeof(struct case_t));

View File

@ -48,7 +48,7 @@ static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap);
static void rt_exit(int code);
#endif /* CONFIG_TCC_BACKTRACE */
/* defined when included from lib/bt.c */
/* defined when included from lib/bt-exe.c */
#ifndef CONFIG_TCC_BACKTRACE_ONLY
#ifndef _WIN32
@ -412,15 +412,15 @@ next:
/* Stab_Sym.n_value is only 32bits */
pc += rc->prog_base;
#endif
break;
goto check_pc;
rel_pc:
pc += func_addr;
check_pc:
if (pc >= wanted_pc && wanted_pc >= last_pc)
goto found;
break;
}
if (pc >= wanted_pc && wanted_pc >= last_pc)
goto found;
switch(sym->n_type) {
/* function start or end */
case N_FUN:

View File

@ -12,8 +12,6 @@
[test_bcheck_1]
* main
* f1()
112_backtrace.c:38: at f1: BCHECK: ........ is outside of the region
112_backtrace.c:43: by main
112_backtrace.c:38: at f1: BCHECK: invalid pointer ........, size 0x? in memmove dest
112_backtrace.c:43: by main
[returns 255]
@ -32,12 +30,10 @@
[returns 1]
[test_bcheck_100]
112_backtrace.c:107: at main: BCHECK: ........ is outside of the region
112_backtrace.c:107: at main: BCHECK: invalid pointer ........, size 0x? in memcpy dest
[returns 255]
[test_bcheck_101]
112_backtrace.c:109: at main: BCHECK: ........ is outside of the region
112_backtrace.c:109: at main: BCHECK: invalid pointer ........, size 0x? in memcpy src
[returns 255]
@ -50,42 +46,34 @@
[returns 255]
[test_bcheck_104]
112_backtrace.c:115: at main: BCHECK: ........ is outside of the region
112_backtrace.c:115: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s1
[returns 255]
[test_bcheck_105]
112_backtrace.c:117: at main: BCHECK: ........ is outside of the region
112_backtrace.c:117: at main: BCHECK: invalid pointer ........, size 0x? in memcmp s2
[returns 255]
[test_bcheck_106]
112_backtrace.c:119: at main: BCHECK: ........ is outside of the region
112_backtrace.c:119: at main: BCHECK: invalid pointer ........, size 0x? in memmove dest
[returns 255]
[test_bcheck_107]
112_backtrace.c:121: at main: BCHECK: ........ is outside of the region
112_backtrace.c:121: at main: BCHECK: invalid pointer ........, size 0x? in memmove src
[returns 255]
[test_bcheck_108]
112_backtrace.c:123: at main: BCHECK: ........ is outside of the region
112_backtrace.c:123: at main: BCHECK: invalid pointer ........, size 0x? in memset
[returns 255]
[test_bcheck_109]
112_backtrace.c:125: at main: BCHECK: ........ is outside of the region
112_backtrace.c:125: at main: BCHECK: invalid pointer ........, size 0x? in strlen
[returns 255]
[test_bcheck_110]
112_backtrace.c:127: at main: BCHECK: ........ is outside of the region
112_backtrace.c:127: at main: BCHECK: invalid pointer ........, size 0x? in strcpy dest
[returns 255]
[test_bcheck_111]
112_backtrace.c:129: at main: BCHECK: ........ is outside of the region
112_backtrace.c:129: at main: BCHECK: invalid pointer ........, size 0x? in strcpy src
[returns 255]
@ -98,12 +86,10 @@
[returns 255]
[test_bcheck_114]
112_backtrace.c:135: at main: BCHECK: ........ is outside of the region
112_backtrace.c:135: at main: BCHECK: invalid pointer ........, size 0x? in strncpy dest
[returns 255]
[test_bcheck_115]
112_backtrace.c:137: at main: BCHECK: ........ is outside of the region
112_backtrace.c:137: at main: BCHECK: invalid pointer ........, size 0x? in strncpy src
[returns 255]
@ -116,32 +102,26 @@
[returns 255]
[test_bcheck_118]
112_backtrace.c:143: at main: BCHECK: ........ is outside of the region
112_backtrace.c:143: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s1
[returns 255]
[test_bcheck_119]
112_backtrace.c:145: at main: BCHECK: ........ is outside of the region
112_backtrace.c:145: at main: BCHECK: invalid pointer ........, size 0x? in strcmp s2
[returns 255]
[test_bcheck_120]
112_backtrace.c:147: at main: BCHECK: ........ is outside of the region
112_backtrace.c:147: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s1
[returns 255]
[test_bcheck_121]
112_backtrace.c:149: at main: BCHECK: ........ is outside of the region
112_backtrace.c:149: at main: BCHECK: invalid pointer ........, size 0x? in strncmp s2
[returns 255]
[test_bcheck_122]
112_backtrace.c:151: at main: BCHECK: ........ is outside of the region
112_backtrace.c:151: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest
[returns 255]
[test_bcheck_123]
112_backtrace.c:153: at main: BCHECK: ........ is outside of the region
112_backtrace.c:153: at main: BCHECK: invalid pointer ........, size 0x? in strcat dest
[returns 255]
@ -154,11 +134,9 @@
[returns 255]
[test_bcheck_126]
112_backtrace.c:159: at main: BCHECK: ........ is outside of the region
112_backtrace.c:159: at main: BCHECK: invalid pointer ........, size 0x? in strchr
[returns 255]
[test_bcheck_127]
112_backtrace.c:161: at main: BCHECK: ........ is outside of the region
112_backtrace.c:161: at main: BCHECK: invalid pointer ........, size 0x? in strdup
[returns 255]

View File

@ -0,0 +1,43 @@
int tcc_backtrace(const char*, ...);
#define hello() \
tcc_backtrace("hello from %s() / %s:%d",__FUNCTION__,__FILE__,__LINE__)
#ifndef _WIN32
# define __declspec(n)
#endif
#if DLL==1
__declspec(dllexport) int f_1()
{
hello();
return 0;
}
#elif DLL==2
__declspec(dllexport) int f_2()
{
hello();
return 0;
}
#else
int f_1();
int f_2();
int f_main()
{
hello();
return 0;
}
int main ()
{
f_1();
f_2();
f_main();
return 0;
}
#endif

View File

@ -0,0 +1,6 @@
113_btdll.c:12: at f_1: hello from f_1() / 113_btdll.c:12
113_btdll.c:37: by main
113_btdll.c:20: at f_2: hello from f_2() / 113_btdll.c:20
113_btdll.c:38: by main
113_btdll.c:31: at f_main: hello from f_main() / 113_btdll.c:31
113_btdll.c:39: by main

View File

@ -24,7 +24,7 @@ ifeq (,$(filter i386,$(ARCH)))
endif
ifeq (,$(filter i386 x86_64,$(ARCH)))
SKIP += 85_asm-outside-function.test
SKIP += 112_backtrace.test
SKIP += 112_backtrace.test 113_btdll.test
endif
ifeq (-$(findstring gcc,$(CC))-,--)
SKIP += $(patsubst %.expect,%.test,$(GEN-ALWAYS))
@ -61,7 +61,7 @@ GEN-ALWAYS =
95_bitfields_ms.test : GEN = $(GEN-MSC)
# this test compiles/links two files:
104_inline.test : FLAGS += $(SRC)/104+_inline.c
104_inline.test : FLAGS += $(subst 104,104+,$1)
104_inline.test : GEN = $(GEN-TCC)
# this test needs pthread
@ -72,7 +72,16 @@ GEN-ALWAYS =
108_constructor.test: NORUN = true
112_backtrace.test: FLAGS += -dt -b
112_backtrace.test: FILTER += -e 's;[0-9A-Fa-fx]\{8,\};........;g' -e 's;0x[0-9A-Fa-f]\+;0x?;g'
112_backtrace.test 113_btdll.test: FILTER += \
-e 's;[0-9A-Fa-fx]\{8,\};........;g' \
-e 's;0x[0-9A-Fa-f]\+;0x?;g'
# this test creates two DLLs and an EXE
113_btdll.test: NORUN = true
113_btdll.test: FLAGS += \
-bt $1 -shared -D DLL=1 -o a1$(DLLSUF) && $(TCC) \
-bt $1 -shared -D DLL=2 -o a2$(DLLSUF) && $(TCC) \
-bt a1$(DLLSUF) a2$(DLLSUF) -Wl,-rpath=.
# Filter source directory in warnings/errors (out-of-tree builds)
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'
@ -81,10 +90,10 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS)) ;
%.test: %.c %.expect
@echo Test: $*...
@$(if $(NORUN),$(T1),$(T2)) $(if $(NODIFF),,$(T3))
@$(call T1,$<) $(T3)
T1 = $(TCC) $(FLAGS) $< -o a.exe && ./a.exe $(ARGS)
T2 = $(TCC) $(FLAGS) -run $< $(ARGS)
T1 = $(TCC) $(FLAGS) $(T2) $(ARGS)
T2 = $(if $(NORUN),$1 -o a.exe && ./a.exe,-run $1)
T3 = $(FILTER) >$*.output 2>&1 || true \
&& diff -Nbu $(filter %.expect,$^) $*.output \
&& rm -f $*.output $(filter $*.expect,$(GEN-ALWAYS))
@ -95,7 +104,7 @@ tests2.%+:
# just run tcc to see the output, e.g. "make tests2.37-"
tests2.%-:
@$(MAKE) $(call F1,$*) NODIFF=true --no-print-directory
@$(MAKE) $(call F1,$*) T3= --no-print-directory
# run single test, e.g. "make tests2.37"
tests2.%:
@ -111,9 +120,9 @@ F2 = $1 UPDATE="$(patsubst %.test,%.expect,$1)"
@rm -f *.exe *.obj *.pdb
# using TCC for .expect if -dt in FLAGS
GEN = $(if $(filter -dt,$(FLAGS)),$(GEN-TCC),$(GEN-CC))
GEN = $(if $(filter -dt -bt -b,$(FLAGS)),$(GEN-TCC),$(GEN-CC))
GEN-CC = $(CC) -w -std=gnu99 $(FLAGS) $1 -o a.exe && ./a.exe $(ARGS)
GEN-TCC = $(TCC) $(FLAGS) -run $1 $(ARGS)
GEN-TCC = $(T1)
GEN-MSC = $(MS-CC) $1 && ./$(basename $@).exe
MS-CC = cl
@ -124,5 +133,5 @@ MS-CC = cl
$(sort $(GEN-ALWAYS) $(UPDATE)) : force
force:
clean:
rm -f fred.txt *.output a.exe $(GEN-ALWAYS)
clean tests2.clean :
rm -f fred.txt *.output a.exe *.dll *.so *.def $(GEN-ALWAYS)

View File

@ -163,7 +163,7 @@ copy>nul tcc-win32.txt doc
.\tcc -m64 -c ../lib/alloca86_64-bt.S
.\tcc -m64 -ar lib/libtcc1-64.a %O1% alloca86_64.o alloca86_64-bt.o
@if errorlevel 1 goto :the_end
.\tcc -m%T% -c ../lib/bcheck.c -o lib/bcheck.o
.\tcc -m%T% -c ../lib/bcheck.c -o lib/bcheck.o -g
.\tcc -m%T% -c ../lib/bt-exe.c -o lib/bt-exe.o
.\tcc -m%T% -c ../lib/bt-log.c -o lib/bt-log.o
.\tcc -m%T% -c ../lib/bt-dll.c -o lib/bt-dll.o

View File

@ -701,10 +701,57 @@ ST_FUNC void gen_bounded_ptr_deref(void)
rel = (ElfW(Rela) *)(cur_text_section->reloc->data + vtop->c.i);
rel->r_info = ELF64_R_INFO(sym->c, ELF64_R_TYPE(rel->r_info));
}
#ifdef TCC_TARGET_PE
# define TREG_FASTCALL_1 TREG_RCX
#else
# define TREG_FASTCALL_1 TREG_RDI
#endif
static void gen_bounds_prolog(void)
{
/* leave some room for bound checking code */
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
o(0xb848 + TREG_FASTCALL_1 * 0x100); /*lbound section pointer */
gen_le64 (0);
oad(0xb8, 0); /* call to function */
}
static void gen_bounds_epilog(void)
{
addr_t saved_ind;
addr_t *bounds_ptr;
Sym *sym_data;
/* add end of table info */
bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
*bounds_ptr = 0;
/* generate bound local allocation */
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
func_bound_offset, lbounds_section->data_offset);
saved_ind = ind;
ind = func_bound_ind;
greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);
ind = ind + 10;
gen_bounds_call(TOK___bound_local_new);
ind = saved_ind;
/* generate bound check local freeing */
o(0x525051); /* save returned value, if any (+ scratch-space for windows) */
greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);
o(0xb848 + TREG_FASTCALL_1 * 0x100); /* mov xxx, %rcx/di */
gen_le64 (0);
gen_bounds_call(TOK___bound_local_delete);
o(0x59585a); /* restore returned value, if any */
}
#endif
#ifdef TCC_TARGET_PE
static int func_scratch, func_alloca;
#define REGN 4
static const uint8_t arg_regs[REGN] = {
TREG_RCX, TREG_RDX, TREG_R8, TREG_R9
@ -720,8 +767,6 @@ static int arg_prepare_reg(int idx) {
return arg_regs[idx];
}
static int func_scratch, func_alloca;
/* Generate function call. The function address is pushed first, then
all the parameters in call order. This functions pops all the
parameters and the function address. */
@ -918,7 +963,6 @@ void gfunc_prolog(Sym *func_sym)
int addr, reg_param_index, bt, size;
Sym *sym;
CType *type;
int n_arg = 0;
func_ret_sub = 0;
func_scratch = 32;
@ -946,7 +990,6 @@ void gfunc_prolog(Sym *func_sym)
/* define parameters */
while ((sym = sym->next) != NULL) {
n_arg++;
type = &sym->type;
bt = type->t & VT_BTYPE;
size = gfunc_arg_size(type);
@ -983,23 +1026,8 @@ void gfunc_prolog(Sym *func_sym)
reg_param_index++;
}
#ifdef CONFIG_TCC_BCHECK
/* leave some room for bound checking code */
if (tcc_state->do_bounds_check) {
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
o(0xb848); /* lbound section pointer */
gen_le64 (0);
o(0xc18948); /* mov %rax,%rcx ## first arg in %rdi, this must be ptr */
o(0x20ec8348); /* sub $20, %rsp */
oad(0xb8, 0); /* call to function */
o(0x20c48348); /* add $20, %rsp */
if (n_arg >= 2 && strcmp (get_tok_str(func_sym->v, NULL), "main") == 0) {
o(0x184d8b48); /* mov 0x18(%rbp),%rcx */
o(0x20ec8348); /* sub $20, %rsp */
gen_bounds_call(TOK___bound_main_arg);
o(0x20c48348); /* add $20, %rsp */
}
}
if (tcc_state->do_bounds_check)
gen_bounds_prolog();
#endif
}
@ -1013,39 +1041,10 @@ void gfunc_epilog(void)
loc = (loc & -16) - func_scratch;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check
&& func_bound_offset != lbounds_section->data_offset)
{
addr_t saved_ind;
addr_t *bounds_ptr;
Sym *sym_data;
/* add end of table info */
bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
*bounds_ptr = 0;
/* generate bound local allocation */
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
func_bound_offset, lbounds_section->data_offset);
saved_ind = ind;
ind = func_bound_ind;
greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);
ind = ind + 10 + 3 + 4;
gen_bounds_call(TOK___bound_local_new);
ind = saved_ind;
/* generate bound check local freeing */
o(0x5250); /* save returned value, if any */
greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);
o(0xb848); /* mov xxx, %rax */
gen_le64 (0);
o(0xc18948); /* mov %rax,%rcx # first arg in %rdi, this must be ptr */
o(0x20ec8348); /* sub $20, %rsp */
gen_bounds_call(TOK___bound_local_delete);
o(0x20c48348); /* add $20, %rsp */
o(0x585a); /* restore returned value, if any */
}
if (tcc_state->do_bounds_check)
gen_bounds_epilog();
#endif
o(0xc9); /* leave */
if (func_ret_sub == 0) {
o(0xc3); /* ret */
@ -1469,7 +1468,6 @@ void gfunc_prolog(Sym *func_sym)
X86_64_Mode mode;
int i, addr, align, size, reg_count;
int param_addr = 0, reg_param_index, sse_param_index;
int n_arg = 0;
Sym *sym;
CType *type;
@ -1553,7 +1551,6 @@ void gfunc_prolog(Sym *func_sym)
}
/* define parameters */
while ((sym = sym->next) != NULL) {
n_arg++;
type = &sym->type;
mode = classify_x86_64_arg(type, NULL, &size, &align, &reg_count);
switch (mode) {
@ -1606,19 +1603,8 @@ void gfunc_prolog(Sym *func_sym)
}
#ifdef CONFIG_TCC_BCHECK
/* leave some room for bound checking code */
if (tcc_state->do_bounds_check) {
func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind;
o(0xb848); /* lbound section pointer */
gen_le64 (0);
o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
oad(0xb8, 0); /* call to function */
if (n_arg >= 2 && strcmp (get_tok_str(func_sym->v, NULL), "main") == 0) {
o(0xf07d8b48); /* mov -0x10(%rbp),%rdi */
gen_bounds_call(TOK___bound_main_arg);
}
}
if (tcc_state->do_bounds_check)
gen_bounds_prolog();
#endif
}
@ -1628,36 +1614,8 @@ void gfunc_epilog(void)
int v, saved_ind;
#ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check
&& func_bound_offset != lbounds_section->data_offset)
{
addr_t saved_ind;
addr_t *bounds_ptr;
Sym *sym_data;
/* add end of table info */
bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
*bounds_ptr = 0;
/* generate bound local allocation */
sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
func_bound_offset, lbounds_section->data_offset);
saved_ind = ind;
ind = func_bound_ind;
greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);
ind = ind + 10 + 3;
gen_bounds_call(TOK___bound_local_new);
ind = saved_ind;
/* generate bound check local freeing */
o(0x5250); /* save returned value, if any */
greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);
o(0xb848); /* mov xxx, %rax */
gen_le64 (0);
o(0xc78948); /* mov %rax,%rdi # first arg in %rdi, this must be ptr */
gen_bounds_call(TOK___bound_local_delete);
o(0x585a); /* restore returned value, if any */
}
if (tcc_state->do_bounds_check)
gen_bounds_epilog();
#endif
o(0xc9); /* leave */
if (func_ret_sub == 0) {