mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-27 06:10:06 +08:00
Fix bounds checking for linux/windows
This commit is contained in:
parent
474f95dda8
commit
4461f38a9e
19
Makefile
19
Makefile
@ -16,6 +16,7 @@ endif
|
||||
|
||||
LIBTCC = libtcc.a
|
||||
LIBTCC1 = libtcc1.a
|
||||
LIBTCCB1 = libtccb1.a
|
||||
LINK_LIBTCC =
|
||||
LIBS =
|
||||
CFLAGS += -I$(TOP)
|
||||
@ -86,7 +87,7 @@ ifeq ($(INCLUDED),no)
|
||||
# running top Makefile
|
||||
|
||||
PROGS = tcc$(EXESUF)
|
||||
TCCLIBS = $(LIBTCC1) $(LIBTCC) $(LIBTCCDEF)
|
||||
TCCLIBS = $(LIBTCC1) $(LIBTCCB1) $(LIBTCC) $(LIBTCCDEF)
|
||||
TCCDOCS = tcc.1 tcc-doc.html tcc-doc.info
|
||||
|
||||
all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
|
||||
@ -100,11 +101,15 @@ TCC_X += riscv64
|
||||
LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince
|
||||
LIBTCC1_X += riscv64
|
||||
|
||||
# cross libtccb1.a targets to build
|
||||
LIBTCCB1_X = i386 x86_64 i386-win32 x86_64-win32
|
||||
|
||||
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
|
||||
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a)
|
||||
LIBTCCB1_CROSS = $(foreach X,$(LIBTCCB1_X),$X-libtcc1.a)
|
||||
|
||||
# build cross compilers & libs
|
||||
cross: $(LIBTCC1_CROSS) $(PROGS_CROSS)
|
||||
cross: $(LIBTCC1_CROSS) $(LIBTCCB1_CROSS) $(PROGS_CROSS)
|
||||
|
||||
# build specific cross compiler & lib
|
||||
cross-%: %-tcc$(EXESUF) %-libtcc1.a ;
|
||||
@ -148,10 +153,10 @@ DEFINES += $(DEF-$(or $(findstring win,$T),unx))
|
||||
|
||||
ifneq ($(X),)
|
||||
ifeq ($(CONFIG_WIN32),yes)
|
||||
DEF-win += -DTCC_LIBTCC1="\"$(X)libtcc1.a\""
|
||||
DEF-unx += -DTCC_LIBTCC1="\"lib/$(X)libtcc1.a\""
|
||||
DEF-win += -DTCC_LIBTCC1="\"$(X)libtcc1.a\"" -DTCC_LIBTCCB1="\"$(X)libtccb1.a\""
|
||||
DEF-unx += -DTCC_LIBTCC1="\"lib/$(X)libtcc1.a\"" -DTCC_LIBTCCB1="\"lib/$(X)libtccb1.a\""
|
||||
else
|
||||
DEF-all += -DTCC_LIBTCC1="\"$(X)libtcc1.a\""
|
||||
DEF-all += -DTCC_LIBTCC1="\"$(X)libtcc1.a\"" -DTCC_LIBTCCB1="\"$(X)libtccb1.a\""
|
||||
DEF-win += -DCONFIG_TCCDIR="\"$(tccdir)/win32\""
|
||||
endif
|
||||
endif
|
||||
@ -269,6 +274,8 @@ STRIP_yes = -s
|
||||
|
||||
LIBTCC1_W = $(filter %-win32-libtcc1.a %-wince-libtcc1.a,$(LIBTCC1_CROSS))
|
||||
LIBTCC1_U = $(filter-out $(LIBTCC1_W),$(LIBTCC1_CROSS))
|
||||
LIBTCCB1_W = $(filter %-win32-libtccb1.a %-wince-libtccb1.a,$(LIBTCCB1_CROSS))
|
||||
LIBTCCB1_U = $(filter-out $(LIBTCCB1_W),$(LIBTCCB1_CROSS))
|
||||
IB = $(if $1,mkdir -p $2 && $(INSTALLBIN) $1 $2)
|
||||
IBw = $(call IB,$(wildcard $1),$2)
|
||||
IF = $(if $1,mkdir -p $2 && $(INSTALL) $1 $2)
|
||||
@ -279,6 +286,7 @@ IR = mkdir -p $2 && cp -r $1/. $2
|
||||
install-unx:
|
||||
$(call IBw,$(PROGS) $(PROGS_CROSS),"$(bindir)")
|
||||
$(call IFw,$(LIBTCC1) $(LIBTCC1_U),"$(tccdir)")
|
||||
$(call IFw,$(LIBTCCB1) $(LIBTCCB1_U),"$(tccdir)")
|
||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
||||
$(call $(if $(findstring .so,$(LIBTCC)),IBw,IFw),$(LIBTCC),"$(libdir)")
|
||||
$(call IF,$(TOPSRC)/libtcc.h,"$(includedir)")
|
||||
@ -304,6 +312,7 @@ install-win:
|
||||
$(call IBw,$(PROGS) $(PROGS_CROSS) $(subst libtcc.a,,$(LIBTCC)),"$(bindir)")
|
||||
$(call IF,$(TOPSRC)/win32/lib/*.def,"$(tccdir)/lib")
|
||||
$(call IFw,libtcc1.a $(LIBTCC1_W),"$(tccdir)/lib")
|
||||
$(call IFw,libtccb1.a $(LIBTCCB1_W),"$(tccdir)/lib")
|
||||
$(call IF,$(TOPSRC)/include/*.h $(TOPSRC)/tcclib.h,"$(tccdir)/include")
|
||||
$(call IR,$(TOPSRC)/win32/include,"$(tccdir)/include")
|
||||
$(call IR,$(TOPSRC)/win32/examples,"$(tccdir)/examples")
|
||||
|
@ -1264,8 +1264,9 @@ void gfunc_call(int nb_args)
|
||||
}
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
void gfunc_prolog(CType *func_type)
|
||||
void gfunc_prolog(Sym *func_sym)
|
||||
{
|
||||
CType *func_type = &func_sym->type;
|
||||
Sym *sym,*sym2;
|
||||
int n, nf, size, align, rs, struct_ret = 0;
|
||||
int addr, pn, sn; /* pn=core, sn=stack */
|
||||
|
@ -996,8 +996,9 @@ static int arm64_func_va_list_gr_offs;
|
||||
static int arm64_func_va_list_vr_offs;
|
||||
static int arm64_func_sub_sp_offset;
|
||||
|
||||
ST_FUNC void gfunc_prolog(CType *func_type)
|
||||
ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
{
|
||||
CType *func_type = &func_sym->type;
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
Sym *sym;
|
||||
|
@ -1939,8 +1939,9 @@ void gfunc_call(int nb_args)
|
||||
// parameters are loaded and restored upon return (or if/when needed).
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
void gfunc_prolog(CType * func_type)
|
||||
void gfunc_prolog(Sym *func_sym)
|
||||
{
|
||||
CType *func_type = &func_sym->type;
|
||||
int addr, align, size, func_call, i;
|
||||
Sym *sym;
|
||||
CType *type;
|
||||
|
89
i386-gen.c
89
i386-gen.c
@ -512,10 +512,12 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
#endif
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
ST_FUNC void gfunc_prolog(CType *func_type)
|
||||
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;
|
||||
@ -558,6 +560,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
|
||||
}
|
||||
/* define parameters */
|
||||
while ((sym = sym->next) != NULL) {
|
||||
n_arg++;
|
||||
type = &sym->type;
|
||||
size = type_size(type, &align);
|
||||
size = (size + 3) & ~3;
|
||||
@ -597,6 +600,12 @@ ST_FUNC void gfunc_prolog(CType *func_type)
|
||||
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 */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1003,6 +1012,7 @@ ST_FUNC void gen_cvt_itof(int t)
|
||||
o(0x2404db); /* fildl (%esp) */
|
||||
o(0x04c483); /* add $4, %esp */
|
||||
}
|
||||
vtop->r2 = VT_CONST;
|
||||
vtop->r = TREG_ST0;
|
||||
}
|
||||
|
||||
@ -1040,14 +1050,87 @@ ST_FUNC void ggoto(void)
|
||||
/* bound check support functions */
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
/* generate a bounded pointer addition */
|
||||
ST_FUNC void gen_bounded_ptr_add(void)
|
||||
{
|
||||
/* save all temporary registers */
|
||||
save_regs(0);
|
||||
/* prepare fast i386 function call (args in eax and edx) */
|
||||
gv2(RC_EAX, RC_EDX);
|
||||
/* save all temporary registers */
|
||||
vtop -= 2;
|
||||
save_regs(0);
|
||||
/* do a fast function call */
|
||||
gen_static_call(TOK___bound_ptr_add);
|
||||
/* returned pointer is in eax */
|
||||
|
35
lib/Makefile
35
lib/Makefile
@ -8,6 +8,7 @@ VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
|
||||
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
|
||||
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
|
||||
BIN = $(TOP)/$(X)libtcc1.a
|
||||
BINB = $(TOP)/$(X)libtccb1.a
|
||||
|
||||
XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
|
||||
XCC = $(XTCC)
|
||||
@ -19,6 +20,8 @@ XCFG = $(or $(findstring -win,$T),-unx)
|
||||
|
||||
# in order to use gcc, tyoe: make <target>-libtcc1-usegcc=yes
|
||||
arm-libtcc1-usegcc ?= no
|
||||
x86_64-libtcc1-usegcc ?= no
|
||||
i386-libtcc1-usegcc ?= no
|
||||
|
||||
ifeq "$($(T)-libtcc1-usegcc)" "yes"
|
||||
XCC = $(CC)
|
||||
@ -39,6 +42,8 @@ ifdef CONFIG_OSX
|
||||
XFLAGS += -D_ANSI_SOURCE
|
||||
endif
|
||||
|
||||
XFLAGS += -g -Wno-deprecated-declarations
|
||||
|
||||
I386_O = libtcc1.o alloca86.o alloca86-bt.o
|
||||
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o
|
||||
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o
|
||||
@ -46,11 +51,11 @@ ARM64_O = lib-arm64.o
|
||||
RISCV64_O = lib-arm64.o
|
||||
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
|
||||
|
||||
OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
|
||||
OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O)
|
||||
OBJ-i386 = $(I386_O) $(DSO_O)
|
||||
OBJ-x86_64 = $(X86_64_O) va_list.o $(DSO_O)
|
||||
OBJ-x86_64-osx = $(X86_64_O) va_list.o
|
||||
OBJ-i386-win32 = $(I386_O) chkstk.o bcheck.o $(WIN_O)
|
||||
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o bcheck.o $(WIN_O)
|
||||
OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
|
||||
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o (WIN_O)
|
||||
OBJ-arm64 = $(ARM64_O) $(DSO_O)
|
||||
OBJ-arm = $(ARM_O) $(DSO_O)
|
||||
OBJ-arm-fpa = $(ARM_O) $(DSO_O)
|
||||
@ -61,9 +66,29 @@ OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
|
||||
OBJ-arm-wince = $(ARM_O) $(WIN_O)
|
||||
OBJ-riscv64 = $(RISCV64_O) $(DSO_O)
|
||||
|
||||
OBJB-i386 = $(BCHECK_O)
|
||||
OBJB-x86_64 = $(BCHECK_O)
|
||||
OBJB-x86_64-osx =
|
||||
OBJB-i386-win32 = bcheck.o
|
||||
OBJB-x86_64-win32 = bcheck.o
|
||||
OBJB-arm64 =
|
||||
OBJB-arm =
|
||||
OBJB-arm-fpa =
|
||||
OBJB-arm-fpa-ld =
|
||||
OBJB-arm-vfp =
|
||||
OBJB-arm-eabi =
|
||||
OBJB-arm-eabihf =
|
||||
OBJB-arm-wince =
|
||||
OBJB-riscv64 =
|
||||
|
||||
all: $(BIN) $(BINB)
|
||||
|
||||
$(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T))
|
||||
$(XAR) rcs $@ $^
|
||||
|
||||
$(BINB) : $(patsubst %.o,$(X)%.o,$(OBJB-$T))
|
||||
$(XAR) rcs $@ $^
|
||||
|
||||
$(X)%.o : %.c
|
||||
$(XCC) -c $< -o $@ $(XFLAGS)
|
||||
|
||||
@ -74,4 +99,4 @@ $(X)crt1w.o : crt1.c
|
||||
$(X)wincrt1w.o : wincrt1.c
|
||||
|
||||
clean :
|
||||
rm -f *.a *.o $(BIN)
|
||||
rm -f *.a *.o $(BIN) $(BINB)
|
||||
|
1402
lib/bcheck.c
1402
lib/bcheck.c
File diff suppressed because it is too large
Load Diff
@ -614,8 +614,9 @@ ST_FUNC void gfunc_call(int nb_args)
|
||||
|
||||
static int func_sub_sp_offset, num_va_regs, func_va_list_ofs;
|
||||
|
||||
ST_FUNC void gfunc_prolog(CType *func_type)
|
||||
ST_FUNC void gfunc_prolog(Sym *func_sym)
|
||||
{
|
||||
CType *func_type = &func_sym->type;
|
||||
int i, addr, align, size;
|
||||
int param_addr = 0;
|
||||
int areg[2];
|
||||
|
8
tcc.h
8
tcc.h
@ -292,6 +292,9 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||
#ifndef TCC_LIBTCC1
|
||||
# define TCC_LIBTCC1 "libtcc1.a"
|
||||
#endif
|
||||
#ifndef TCC_LIBTCCB1
|
||||
# define TCC_LIBTCCB1 "libtccb1.a"
|
||||
#endif
|
||||
|
||||
/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
|
||||
#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC
|
||||
@ -1202,6 +1205,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
||||
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
|
||||
#endif
|
||||
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
ST_FUNC void tcc_add_bcheck(TCCState *s1);
|
||||
#endif
|
||||
ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
|
||||
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
||||
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
||||
@ -1518,7 +1524,7 @@ ST_FUNC void load(int r, SValue *sv);
|
||||
ST_FUNC void store(int r, SValue *v);
|
||||
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
|
||||
ST_FUNC void gfunc_call(int nb_args);
|
||||
ST_FUNC void gfunc_prolog(CType *func_type);
|
||||
ST_FUNC void gfunc_prolog(Sym *func_sym);
|
||||
ST_FUNC void gfunc_epilog(void);
|
||||
ST_FUNC void gen_fill_nops(int);
|
||||
ST_FUNC int gjmp(int t);
|
||||
|
56
tccelf.c
56
tccelf.c
@ -1317,42 +1317,13 @@ ST_FUNC void add_fini_array (TCCState *s1, Sym *sym)
|
||||
add_array (".fini_array", s1, sym);
|
||||
}
|
||||
|
||||
ST_FUNC void tcc_add_bcheck(TCCState *s1)
|
||||
{
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
addr_t *ptr;
|
||||
int sym_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;
|
||||
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 */
|
||||
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 = 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 */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* add tcc runtime libraries */
|
||||
ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
{
|
||||
s1->filetype = 0;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
tcc_add_bcheck(s1);
|
||||
#endif
|
||||
tcc_add_pragma_libs(s1);
|
||||
#ifndef TCC_TARGET_PE
|
||||
/* add libc */
|
||||
@ -1365,6 +1336,13 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
else
|
||||
tcc_add_dll(s1, TCC_LIBGCC, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
|
||||
tcc_add_library_err(s1, "pthread");
|
||||
tcc_add_library_err(s1, "dl");
|
||||
tcc_add_support(s1, TCC_LIBTCCB1);
|
||||
}
|
||||
#endif
|
||||
tcc_add_support(s1, TCC_LIBTCC1);
|
||||
/* add crt end if not memory output */
|
||||
@ -2814,6 +2792,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
|
||||
const char *ar_names, *p;
|
||||
const uint8_t *ar_index;
|
||||
ElfW(Sym) *sym;
|
||||
Section *s;
|
||||
|
||||
data = tcc_malloc(size);
|
||||
if (full_read(fd, data, size) != size)
|
||||
@ -2825,14 +2804,19 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
|
||||
do {
|
||||
bound = 0;
|
||||
for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
|
||||
sym_index = find_elf_sym(symtab_section, p);
|
||||
s = symtab_section;
|
||||
sym_index = find_elf_sym(s, p);
|
||||
if(sym_index == 0) {
|
||||
s = s1->dynsymtab_section;
|
||||
sym_index = find_elf_sym(s, p);
|
||||
}
|
||||
if(sym_index) {
|
||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||
sym = &((ElfW(Sym) *)s->data)[sym_index];
|
||||
if(sym->st_shndx == SHN_UNDEF) {
|
||||
off = (entrysize == 4
|
||||
? get_be32(ar_index + i * 4)
|
||||
: get_be64(ar_index + i * 8))
|
||||
+ sizeof(ArchiveHeader);
|
||||
? get_be32(ar_index + i * 4)
|
||||
: get_be64(ar_index + i * 8))
|
||||
+ sizeof(ArchiveHeader);
|
||||
++bound;
|
||||
if(tcc_load_object_file(s1, fd, off) < 0) {
|
||||
fail:
|
||||
|
38
tccgen.c
38
tccgen.c
@ -405,6 +405,8 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
||||
case TOK_strlen:
|
||||
case TOK_strcpy:
|
||||
case TOK_alloca:
|
||||
case TOK_mmap:
|
||||
case TOK_munmap:
|
||||
strcpy(buf, "__bound_");
|
||||
strcat(buf, name);
|
||||
name = buf;
|
||||
@ -1191,7 +1193,11 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
||||
type = &int_type;
|
||||
#endif
|
||||
size = type_size(type, &align);
|
||||
l=get_temp_local_var(size,align);
|
||||
if ((p->r2 & VT_VALMASK) < VT_CONST) {
|
||||
size *= 2;
|
||||
align *= 2;
|
||||
}
|
||||
l=get_temp_local_var(size,align);
|
||||
sv.type.t = type->t;
|
||||
sv.r = VT_LOCAL | VT_LVAL;
|
||||
sv.c.i = l;
|
||||
@ -1375,7 +1381,7 @@ static void gbound(void)
|
||||
|
||||
vtop->r &= ~VT_MUSTBOUND;
|
||||
/* if lvalue, then use checking code before dereferencing */
|
||||
if (vtop->r & VT_LVAL) {
|
||||
if ((vtop->r & VT_LVAL) && !nocode_wanted) {
|
||||
/* if not VT_BOUNDED value, then make one */
|
||||
if (!(vtop->r & VT_BOUNDED)) {
|
||||
lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
|
||||
@ -5478,6 +5484,15 @@ special_math_val:
|
||||
Sym *sa;
|
||||
int nb_args, ret_nregs, ret_align, regsize, variadic;
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check && (vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) {
|
||||
addr_t *bounds_ptr;
|
||||
|
||||
bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(addr_t));
|
||||
bounds_ptr[0] = 1; /* marks alloca/vla used */
|
||||
bounds_ptr[1] = 0;
|
||||
}
|
||||
#endif
|
||||
/* function call */
|
||||
if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
|
||||
/* pointer test (no array accepted) */
|
||||
@ -7413,7 +7428,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
if ((r & VT_VALMASK) == VT_LOCAL) {
|
||||
sec = NULL;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (bcheck && (type->t & VT_ARRAY)) {
|
||||
if (bcheck && ((type->t & VT_ARRAY) ||
|
||||
(type->t & VT_BTYPE) == VT_STRUCT)) {
|
||||
loc--;
|
||||
}
|
||||
#endif
|
||||
@ -7422,8 +7438,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
/* handles bounds */
|
||||
/* XXX: currently, since we do only one pass, we cannot track
|
||||
'&' operators, so we add only arrays */
|
||||
if (bcheck && (type->t & VT_ARRAY)) {
|
||||
'&' operators, so we add only arrays/structs/unions */
|
||||
if (bcheck && ((type->t & VT_ARRAY) ||
|
||||
(type->t & VT_BTYPE) == VT_STRUCT)) {
|
||||
addr_t *bounds_ptr;
|
||||
/* add padding between regions */
|
||||
loc--;
|
||||
@ -7542,6 +7559,15 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
gen_vla_sp_save(addr);
|
||||
cur_scope->vla.loc = addr;
|
||||
cur_scope->vla.num++;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (bcheck) {
|
||||
addr_t *bounds_ptr;
|
||||
|
||||
bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(addr_t));
|
||||
bounds_ptr[0] = 1; /* marks alloca/vla used */
|
||||
bounds_ptr[1] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
} else if (has_init) {
|
||||
size_t oldreloc_offset = 0;
|
||||
@ -7599,7 +7625,7 @@ static void gen_function(Sym *sym, AttributeDef *ad)
|
||||
/* push a dummy symbol to enable local sym storage */
|
||||
sym_push2(&local_stack, SYM_FIELD, 0, 0);
|
||||
local_scope = 1; /* for function parameters */
|
||||
gfunc_prolog(&sym->type);
|
||||
gfunc_prolog(sym);
|
||||
local_scope = 0;
|
||||
rsym = 0;
|
||||
clear_temp_local_var_list();
|
||||
|
16
tccpe.c
16
tccpe.c
@ -1880,15 +1880,29 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||
|
||||
if (0 == s1->nostdlib) {
|
||||
static const char *libs[] = {
|
||||
TCC_LIBTCC1, "msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
||||
TCC_LIBTCC1,
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
TCC_LIBTCCB1,
|
||||
#endif
|
||||
"msvcrt", "kernel32", "", "user32", "gdi32", NULL
|
||||
};
|
||||
const char **pp, *p;
|
||||
for (pp = libs; 0 != (p = *pp); ++pp) {
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (pp == libs + 1 &&
|
||||
(s1->do_bounds_check == 0 || s1->output_type == TCC_OUTPUT_DLL)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (0 == *p) {
|
||||
if (PE_DLL != pe_type && PE_GUI != pe_type)
|
||||
break;
|
||||
} else if (pp == libs && tcc_add_dll(s1, p, 0) >= 0) {
|
||||
continue;
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
} else if (pp == libs + 1 && tcc_add_dll(s1, p, 0) >= 0) {
|
||||
continue;
|
||||
#endif
|
||||
} else {
|
||||
tcc_add_library_err(s1, p);
|
||||
}
|
||||
|
19
tccrun.c
19
tccrun.c
@ -137,30 +137,23 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
|
||||
if (s1->do_bounds_check) {
|
||||
void (*bound_init)(void);
|
||||
void (*bound_exit)(void);
|
||||
void (*bound_new_region)(void *p, addr_t size);
|
||||
int (*bound_delete_region)(void *p);
|
||||
int i, ret;
|
||||
void (*bounds_add_static_var)(size_t *p);
|
||||
size_t *bounds_start;
|
||||
int ret;
|
||||
|
||||
/* set error function */
|
||||
rt_bound_error_msg = tcc_get_symbol_err(s1, "__bound_error_msg");
|
||||
/* XXX: use .init section so that it also work in binary ? */
|
||||
bound_init = tcc_get_symbol_err(s1, "__bound_init");
|
||||
bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
|
||||
bound_new_region = tcc_get_symbol_err(s1, "__bound_new_region");
|
||||
bound_delete_region = tcc_get_symbol_err(s1, "__bound_delete_region");
|
||||
bounds_add_static_var = tcc_get_symbol_err(s1, "__bounds_add_static_var");
|
||||
bounds_start = tcc_get_symbol_err(s1, "__bounds_start");
|
||||
|
||||
bound_init();
|
||||
/* mark argv area as valid */
|
||||
bound_new_region(argv, argc*sizeof(argv[0]));
|
||||
for (i=0; i<argc; ++i)
|
||||
bound_new_region(argv[i], strlen(argv[i]) + 1);
|
||||
bounds_add_static_var (bounds_start);
|
||||
|
||||
ret = (*prog_main)(argc, argv);
|
||||
|
||||
/* unmark argv area */
|
||||
for (i=0; i<argc; ++i)
|
||||
bound_delete_region(argv[i]);
|
||||
bound_delete_region(argv);
|
||||
bound_exit();
|
||||
return ret;
|
||||
}
|
||||
|
2
tcctok.h
2
tcctok.h
@ -312,6 +312,8 @@
|
||||
DEF(TOK_memalign, "memalign")
|
||||
DEF(TOK_calloc, "calloc")
|
||||
# endif
|
||||
DEF(TOK_mmap, "mmap")
|
||||
DEF(TOK_munmap, "munmap")
|
||||
DEF(TOK_strlen, "strlen")
|
||||
DEF(TOK_strcpy, "strcpy")
|
||||
#endif
|
||||
|
@ -151,8 +151,9 @@ memtest:
|
||||
|
||||
|
||||
# memory and bound check auto test
|
||||
BOUNDS_OK = 1 4 8 10 14
|
||||
BOUNDS_FAIL= 2 5 7 9 11 12 13 15
|
||||
# 3 is profiling test
|
||||
BOUNDS_OK = 1 4 8 10 14 16
|
||||
BOUNDS_FAIL= 2 5 6 7 9 11 12 13 15 17
|
||||
|
||||
btest: boundtest.c
|
||||
@echo ------------ $@ ------------
|
||||
|
@ -81,7 +81,6 @@ int test5(void)
|
||||
}
|
||||
|
||||
/* error */
|
||||
/* XXX: currently: bug */
|
||||
int test6(void)
|
||||
{
|
||||
int i, sum = 0;
|
||||
@ -253,10 +252,20 @@ int (*table_test[])(void) = {
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char *cp;
|
||||
int index;
|
||||
int (*ftest)(void);
|
||||
int index_max = sizeof(table_test)/sizeof(table_test[0]);
|
||||
|
||||
/* check bounds checking main arg */
|
||||
for (i = 0; i < argc; i++) {
|
||||
cp = argv[i];
|
||||
while (*cp) {
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
printf(
|
||||
"test TCC bound checking system\n"
|
||||
|
@ -123,6 +123,7 @@ void math_cmp_test(void);
|
||||
void callsave_test(void);
|
||||
void builtin_frame_address_test(void);
|
||||
void attrib_test(void);
|
||||
void bounds_check1_test(void);
|
||||
|
||||
int fib(int n);
|
||||
void num(int n);
|
||||
@ -771,6 +772,7 @@ int main(int argc, char **argv)
|
||||
if (via_volatile (42) != 42)
|
||||
printf ("via_volatile broken\n");
|
||||
attrib_test();
|
||||
bounds_check1_test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3884,9 +3886,11 @@ void builtin_frame_address_test(void)
|
||||
|
||||
printf("str: %s\n", str);
|
||||
#ifndef __riscv
|
||||
#ifndef __BOUNDS_CHECKING_ON
|
||||
bfa1(str-fp0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
char via_volatile (char i)
|
||||
@ -3961,3 +3965,18 @@ int force_get_order(unsigned long s)
|
||||
{
|
||||
return __get_order(s);
|
||||
}
|
||||
|
||||
#define pv(m) printf(sizeof (s->m + 0) == 8 ? "%016lx\n" : "%02x\n", s->m)
|
||||
|
||||
/* Test failed when using bounds checking */
|
||||
void bounds_check1_test (void)
|
||||
{
|
||||
struct s {
|
||||
int x;
|
||||
long long y;
|
||||
} _s, *s = &_s;
|
||||
s->x = 10;
|
||||
s->y = 20;
|
||||
pv(x);
|
||||
pv(y);
|
||||
}
|
||||
|
27
tests/tests2/110_average.c
Normal file
27
tests/tests2/110_average.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double average;
|
||||
int count;
|
||||
}
|
||||
stats_type;
|
||||
|
||||
static void
|
||||
testc (stats_type *s, long long data)
|
||||
{
|
||||
s->average = (s->average * s->count + data) / (s->count + 1);
|
||||
s->count++;
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
stats_type s;
|
||||
|
||||
s.average = 0;
|
||||
s.count = 0;
|
||||
testc (&s, 10);
|
||||
testc (&s, 20);
|
||||
printf ("%g %d\n", s.average, s.count);
|
||||
return 0;
|
||||
}
|
1
tests/tests2/110_average.expect
Normal file
1
tests/tests2/110_average.expect
Normal file
@ -0,0 +1 @@
|
||||
15 2
|
22
tests/tests2/111_conversion.c
Normal file
22
tests/tests2/111_conversion.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
|
||||
union u {
|
||||
unsigned long ul;
|
||||
long double ld;
|
||||
};
|
||||
|
||||
void
|
||||
conv (union u *p)
|
||||
{
|
||||
p->ul = (unsigned int) p->ld;
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
union u v;
|
||||
|
||||
v.ld = 42;
|
||||
conv (&v);
|
||||
printf ("%lu\n", v.ul);
|
||||
return 0;
|
||||
}
|
1
tests/tests2/111_conversion.expect
Normal file
1
tests/tests2/111_conversion.expect
Normal file
@ -0,0 +1 @@
|
||||
42
|
220
x86_64-gen.c
220
x86_64-gen.c
@ -141,6 +141,7 @@ ST_DATA const int reg_classes[NB_REGS] = {
|
||||
|
||||
static unsigned long func_sub_sp_offset;
|
||||
static int func_ret_sub;
|
||||
static int in_call;
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
ST_FUNC void g(int c)
|
||||
@ -636,16 +637,101 @@ static void gcall_or_jmp(int is_jmp)
|
||||
}
|
||||
|
||||
#if defined(CONFIG_TCC_BCHECK)
|
||||
#ifndef TCC_TARGET_PE
|
||||
static addr_t func_bound_offset;
|
||||
static unsigned long func_bound_ind;
|
||||
#endif
|
||||
|
||||
static void gen_static_call(int v)
|
||||
static void gen_bounds_call(int v)
|
||||
{
|
||||
Sym *sym = external_global_sym(v, &func_old_type);
|
||||
oad(0xe8, 0);
|
||||
#ifdef TCC_TARGET_PE
|
||||
greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
|
||||
#else
|
||||
greloca(cur_text_section, sym, ind-4, R_X86_64_PLT32, -4);
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/* generate a bounded pointer addition */
|
||||
@ -654,22 +740,49 @@ ST_FUNC void gen_bounded_ptr_add(void)
|
||||
/* save all temporary registers */
|
||||
save_regs(0);
|
||||
|
||||
if (in_call) {
|
||||
o(0x51525657); /* push $rdi/%rsi/%rdx/%rcx */
|
||||
o(0x51415041); /* push $r8/%r9 */
|
||||
o(0x53415241); /* push $r10/%r11 */
|
||||
}
|
||||
|
||||
/* prepare fast x86_64 function call */
|
||||
gv(RC_RAX);
|
||||
#ifdef TCC_TARGET_PE
|
||||
o(0xc28948); // mov %rax,%rdx ## second arg in %rdx, this must be size
|
||||
#else
|
||||
o(0xc68948); // mov %rax,%rsi ## second arg in %rsi, this must be size
|
||||
#endif
|
||||
vtop--;
|
||||
|
||||
gv(RC_RAX);
|
||||
#ifdef TCC_TARGET_PE
|
||||
o(0xc18948); // mov %rax,%rcx ## first arg in %rcx, this must be ptr
|
||||
#else
|
||||
o(0xc78948); // mov %rax,%rdi ## first arg in %rdi, this must be ptr
|
||||
#endif
|
||||
vtop--;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
o(0x20ec8348); /* sub $20, %rsp */
|
||||
#endif
|
||||
|
||||
/* do a fast function call */
|
||||
gen_static_call(TOK___bound_ptr_add);
|
||||
gen_bounds_call(TOK___bound_ptr_add);
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
o(0x20c48348); /* add $20, %rsp */
|
||||
#endif
|
||||
|
||||
/* returned pointer is in rax */
|
||||
vtop++;
|
||||
vtop->r = TREG_RAX | VT_BOUNDED;
|
||||
|
||||
if (in_call) {
|
||||
o(0x5a415b41); /* pop $r11/%r10 */
|
||||
o(0x58415941); /* pop $r9/%r8 */
|
||||
o(0x5f5e5a59); /* pop $rcx/$rdx/$rsi/%rdi */
|
||||
}
|
||||
|
||||
/* relocation offset of the bounding function call point */
|
||||
vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW(Rela)));
|
||||
@ -799,6 +912,8 @@ void gfunc_call(int nb_args)
|
||||
int size, r, args_size, i, d, bt, struct_size;
|
||||
int arg;
|
||||
|
||||
in_call = 1;
|
||||
|
||||
args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;
|
||||
arg = nb_args;
|
||||
|
||||
@ -909,7 +1024,7 @@ void gfunc_call(int nb_args)
|
||||
|
||||
if ((vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) {
|
||||
/* need to add the "func_scratch" area after alloca */
|
||||
o(0x48); func_alloca = oad(0x05, func_alloca); /* sub $NN, %rax */
|
||||
o(0x48); func_alloca = oad(0x2d, func_alloca); /* sub $NN, %rax */
|
||||
}
|
||||
|
||||
/* other compilers don't clear the upper bits when returning char/short */
|
||||
@ -929,17 +1044,20 @@ void gfunc_call(int nb_args)
|
||||
o(0xc089); /* mov %eax,%eax */
|
||||
#endif
|
||||
vtop--;
|
||||
in_call = 0;
|
||||
}
|
||||
|
||||
|
||||
#define FUNC_PROLOG_SIZE 11
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
void gfunc_prolog(CType *func_type)
|
||||
void gfunc_prolog(Sym *func_sym)
|
||||
{
|
||||
CType *func_type = &func_sym->type;
|
||||
int addr, reg_param_index, bt, size;
|
||||
Sym *sym;
|
||||
CType *type;
|
||||
int n_arg = 0;
|
||||
|
||||
func_ret_sub = 0;
|
||||
func_scratch = 0;
|
||||
@ -967,6 +1085,7 @@ void gfunc_prolog(CType *func_type)
|
||||
|
||||
/* define parameters */
|
||||
while ((sym = sym->next) != NULL) {
|
||||
n_arg++;
|
||||
type = &sym->type;
|
||||
bt = type->t & VT_BTYPE;
|
||||
size = gfunc_arg_size(type);
|
||||
@ -1002,6 +1121,25 @@ void gfunc_prolog(CType *func_type)
|
||||
}
|
||||
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 */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* generate function epilog */
|
||||
@ -1009,6 +1147,40 @@ 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 + 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 */
|
||||
}
|
||||
#endif
|
||||
o(0xc9); /* leave */
|
||||
if (func_ret_sub == 0) {
|
||||
o(0xc3); /* ret */
|
||||
@ -1226,6 +1398,8 @@ void gfunc_call(int nb_args)
|
||||
int sse_reg, gen_reg;
|
||||
char _onstack[nb_args ? nb_args : 1], *onstack = _onstack;
|
||||
|
||||
in_call = 1;
|
||||
|
||||
/* calculate the number of integer/float register arguments, remember
|
||||
arguments to be passed via stack (in onstack[]), and also remember
|
||||
if we have to align the stack pointer to 16 (onstack[i] == 2). Needs
|
||||
@ -1419,6 +1593,7 @@ void gfunc_call(int nb_args)
|
||||
else if (bt == (VT_SHORT | VT_UNSIGNED))
|
||||
o(0xc0b70f); /* movzwl %al, %eax */
|
||||
vtop--;
|
||||
in_call = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1430,11 +1605,13 @@ static void push_arg_reg(int i) {
|
||||
}
|
||||
|
||||
/* generate function prolog of type 't' */
|
||||
void gfunc_prolog(CType *func_type)
|
||||
void gfunc_prolog(Sym *func_sym)
|
||||
{
|
||||
CType *func_type = &func_sym->type;
|
||||
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;
|
||||
|
||||
@ -1518,6 +1695,7 @@ void gfunc_prolog(CType *func_type)
|
||||
}
|
||||
/* define parameters */
|
||||
while ((sym = sym->next) != NULL) {
|
||||
n_arg++;
|
||||
type = &sym->type;
|
||||
mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count);
|
||||
switch (mode) {
|
||||
@ -1574,9 +1752,14 @@ void gfunc_prolog(CType *func_type)
|
||||
if (tcc_state->do_bounds_check) {
|
||||
func_bound_offset = lbounds_section->data_offset;
|
||||
func_bound_ind = ind;
|
||||
oad(0xb8, 0); /* lbound section pointer */
|
||||
o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
|
||||
oad(0xb8, 0); /* call to function */
|
||||
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);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1588,7 +1771,7 @@ void gfunc_epilog(void)
|
||||
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
if (tcc_state->do_bounds_check
|
||||
&& func_bound_offset != lbounds_section->data_offset)
|
||||
&& func_bound_offset != lbounds_section->data_offset)
|
||||
{
|
||||
addr_t saved_ind;
|
||||
addr_t *bounds_ptr;
|
||||
@ -1603,17 +1786,18 @@ void gfunc_epilog(void)
|
||||
func_bound_offset, lbounds_section->data_offset);
|
||||
saved_ind = ind;
|
||||
ind = func_bound_ind;
|
||||
greloca(cur_text_section, sym_data, ind + 1, R_X86_64_64, 0);
|
||||
ind = ind + 5 + 3;
|
||||
gen_static_call(TOK___bound_local_new);
|
||||
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 + 1, R_X86_64_64, 0);
|
||||
oad(0xb8, 0); /* mov xxx, %rax */
|
||||
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_static_call(TOK___bound_local_delete);
|
||||
gen_bounds_call(TOK___bound_local_delete);
|
||||
o(0x585a); /* restore returned value, if any */
|
||||
}
|
||||
#endif
|
||||
@ -1940,6 +2124,7 @@ void gen_opf(int op)
|
||||
v1.c.i = fc;
|
||||
load(r, &v1);
|
||||
fc = 0;
|
||||
vtop->r = r = r | VT_LVAL;
|
||||
}
|
||||
|
||||
if (op == TOK_EQ || op == TOK_NE) {
|
||||
@ -2007,6 +2192,7 @@ void gen_opf(int op)
|
||||
v1.c.i = fc;
|
||||
load(r, &v1);
|
||||
fc = 0;
|
||||
vtop->r = r = r | VT_LVAL;
|
||||
}
|
||||
|
||||
assert(!(vtop[-1].r & VT_LVAL));
|
||||
|
Loading…
Reference in New Issue
Block a user