From fc977d56c90b6c6a54b7e831b5c88e37f54a5cae Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 18 Jul 2009 22:06:54 +0200 Subject: [PATCH] x86-64: chkstk, alloca --- Makefile | 43 +++++++++++---------------- lib/alloca86-bt.S | 2 +- lib/alloca86_64.S | 9 +++++- tccpe.c | 9 ++---- tests/Makefile | 4 +-- tests/boundtest.c | 19 ++++++++++++ win32/lib/chkstk.S | 74 +++++++++++++++++++++++++++++++++------------- x86_64-gen.c | 3 +- 8 files changed, 104 insertions(+), 59 deletions(-) diff --git a/Makefile b/Makefile index 448860a..01c3e27 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,9 @@ LIBS_P= ifneq ($(GCC_MAJOR),2) CFLAGS+=-fno-strict-aliasing +ifneq ($(GCC_MAJOR),3) +CFLAGS+=-Wno-pointer-sign -Wno-sign-compare -D_FORTIFY_SOURCE=0 +endif endif ifeq ($(ARCH),i386) @@ -19,15 +22,8 @@ ifeq ($(GCC_MAJOR),2) CFLAGS+=-m386 -malign-functions=0 else CFLAGS+=-march=i386 -falign-functions=0 -ifneq ($(GCC_MAJOR),3) -CFLAGS+=-Wno-pointer-sign -Wno-sign-compare -D_FORTIFY_SOURCE=0 endif endif -endif - -ifeq ($(ARCH),x86-64) -CFLAGS+=-Wno-pointer-sign -endif ifndef CONFIG_WIN32 LIBS=-lm @@ -36,26 +32,29 @@ LIBS+=-ldl endif endif -ifdef CONFIG_WIN32 -NATIVE_TARGET=-DTCC_TARGET_PE -LIBTCC1=libtcc1.a -else ifeq ($(ARCH),i386) NATIVE_TARGET=-DTCC_TARGET_I386 LIBTCC1=libtcc1.a BCHECK_O=bcheck.o -else -ifeq ($(ARCH),arm) -NATIVE_TARGET=-DTCC_TARGET_ARM -NATIVE_TARGET+=$(if $(wildcard /lib/ld-linux.so.3),-DTCC_ARM_EABI) -NATIVE_TARGET+=$(if $(shell grep -l "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo),-DTCC_ARM_VFP) +ALLOCA_O=alloca86.o alloca86-bt.o else ifeq ($(ARCH),x86-64) NATIVE_TARGET=-DTCC_TARGET_X86_64 LIBTCC1=libtcc1.a +BCHECK_O= +ALLOCA_O=alloca86_64.o endif endif + +ifeq ($(ARCH),arm) +NATIVE_TARGET=-DTCC_TARGET_ARM +NATIVE_TARGET+=$(if $(wildcard /lib/ld-linux.so.3),-DTCC_ARM_EABI) +NATIVE_TARGET+=$(if $(shell grep -l "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo),-DTCC_ARM_VFP) endif + +ifdef CONFIG_WIN32 +NATIVE_TARGET+=-DTCC_TARGET_PE +BCHECK_O= endif ifneq ($(wildcard /lib/ld-uClibc.so.0),) @@ -70,7 +69,6 @@ endif ifeq ($(TOP),.) PROGS=tcc$(EXESUF) - I386_CROSS = i386-tcc$(EXESUF) WIN32_CROSS = i386-win32-tcc$(EXESUF) WIN64_CROSS = x86_64-win32-tcc$(EXESUF) @@ -171,26 +169,19 @@ tiny_libmaker$(EXESUF): win32/tools/tiny_libmaker.c $(CC) -o $@ $< $(CFLAGS) # TinyCC runtime libraries -LIBTCC1_OBJS=libtcc1.o +LIBTCC1_OBJS=libtcc1.o $(ALLOCA_O) LIBTCC1_CC=$(CC) VPATH+=lib + ifdef CONFIG_WIN32 # for windows, we must use TCC because we generate ELF objects LIBTCC1_OBJS+=crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o LIBTCC1_CC=./tcc.exe -Bwin32 -Iinclude $(NATIVE_TARGET) VPATH+=win32/lib endif -ifeq ($(ARCH),i386) -LIBTCC1_OBJS+=alloca86.o alloca86-bt.o -else -ifeq ($(ARCH),x86-64) -LIBTCC1_OBJS+=alloca86_64.o -endif -endif %.o: %.c $(LIBTCC1_CC) -o $@ -c $< -O2 -Wall - %.o: %.S $(LIBTCC1_CC) -o $@ -c $< diff --git a/lib/alloca86-bt.S b/lib/alloca86-bt.S index 994da20..c5d5f4d 100644 --- a/lib/alloca86-bt.S +++ b/lib/alloca86-bt.S @@ -1,5 +1,5 @@ /* ---------------------------------------------- */ -/* alloca86b.S */ +/* alloca86-bt.S */ #include "../config.h" diff --git a/lib/alloca86_64.S b/lib/alloca86_64.S index 684a3e9..13c4672 100644 --- a/lib/alloca86_64.S +++ b/lib/alloca86_64.S @@ -7,13 +7,16 @@ alloca: pop %rdx +#ifdef TCC_TARGET_PE + mov %rcx,%rax +#else mov %rdi,%rax +#endif add $15,%rax and $-16,%rax jz p3 #ifdef TCC_TARGET_PE - /* XXX: not tested */ p1: cmp $4096,%rax jle p2 @@ -26,6 +29,10 @@ p2: sub %rax,%rsp mov %rsp,%rax +#ifdef TCC_TARGET_PE + add $32,%rax +#endif + p3: push %rdx ret diff --git a/tccpe.c b/tccpe.c index ac3688f..89ff3bd 100644 --- a/tccpe.c +++ b/tccpe.c @@ -193,8 +193,8 @@ typedef struct _IMAGE_EXPORT_DIRECTORY { typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { - DWORD Characteristics; - DWORD OriginalFirstThunk; + DWORD Characteristics; + DWORD OriginalFirstThunk; }; DWORD TimeDateStamp; DWORD ForwarderChain; @@ -350,12 +350,7 @@ ST_DATA struct pe_header pe_header = { 0x0002, /*WORD Subsystem; */ 0x0000, /*WORD DllCharacteristics; */ 0x00100000, /*DWORD SizeOfStackReserve; */ -#ifdef TCC_TARGET_X86_64 - // need to have a __chkstk eventually - 0x00008000, /*DWORD SizeOfStackCommit; */ -#else 0x00001000, /*DWORD SizeOfStackCommit; */ -#endif 0x00100000, /*DWORD SizeOfHeapReserve; */ 0x00001000, /*DWORD SizeOfHeapCommit; */ 0x00000000, /*DWORD LoaderFlags; */ diff --git a/tests/Makefile b/tests/Makefile index f91e4fd..019c890 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -81,8 +81,8 @@ test4: test.ref @if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi # memory and bound check auto test -BOUNDS_OK = 1 4 8 10 -BOUNDS_FAIL= 2 5 7 9 11 12 13 +BOUNDS_OK = 1 4 8 10 14 +BOUNDS_FAIL= 2 5 7 9 11 12 13 15 btest: boundtest.c @echo ------------ $@ ------------ diff --git a/tests/boundtest.c b/tests/boundtest.c index 9bc9828..c2b2953 100644 --- a/tests/boundtest.c +++ b/tests/boundtest.c @@ -169,6 +169,23 @@ int test13(void) return strlen(tab); } +int test14(void) +{ + char *p = alloca(TAB_SIZE); + memset(p, 'a', TAB_SIZE); + p[TAB_SIZE-1] = 0; + return strlen(p); +} + +/* error */ +int test15(void) +{ + char *p = alloca(TAB_SIZE-1); + memset(p, 'a', TAB_SIZE); + p[TAB_SIZE-1] = 0; + return strlen(p); +} + int (*table_test[])(void) = { test1, test1, @@ -184,6 +201,8 @@ int (*table_test[])(void) = { test11, test12, test13, + test14, + test15, }; int main(int argc, char **argv) diff --git a/win32/lib/chkstk.S b/win32/lib/chkstk.S index 837d8af..9be9597 100644 --- a/win32/lib/chkstk.S +++ b/win32/lib/chkstk.S @@ -1,29 +1,61 @@ -// ================================================= -// chkstk.s +/* ---------------------------------------------- */ +/* chkstk86.s */ + +#include "../../config.h" + +/* ---------------------------------------------- */ +#ifndef TCC_TARGET_X86_64 +/* ---------------------------------------------- */ -.text .globl __chkstk __chkstk: - xchg (%esp), %ebp // store ebp, get ret.addr - push %ebp // push ret.addr - lea 4(%esp), %ebp // setup frame ptr - push %ecx // save ecx - mov %ebp, %ecx + xchg (%esp),%ebp /* store ebp, get ret.addr */ + push %ebp /* push ret.addr */ + lea 4(%esp),%ebp /* setup frame ptr */ + push %ecx /* save ecx */ + mov %ebp,%ecx P0: - sub $4096,%ecx - test %eax,(%ecx) - sub $4096,%eax - cmp $4096,%eax - jge P0 + sub $4096,%ecx + test %eax,(%ecx) + sub $4096,%eax + cmp $4096,%eax + jge P0 + sub %eax,%ecx + test %eax,(%ecx) - sub %eax,%ecx - mov %esp,%eax - test %eax,(%ecx) - mov %ecx,%esp + mov %esp,%eax + mov %ecx,%esp + mov (%eax),%ecx /* restore ecx */ + jmp *4(%eax) - mov (%eax),%ecx // restore ecx - mov 4(%eax),%eax - push %eax - ret +/* ---------------------------------------------- */ +#else +/* ---------------------------------------------- */ +.globl __chkstk + +__chkstk: + xchg (%rsp),%rbp /* store ebp, get ret.addr */ + push %rbp /* push ret.addr */ + lea 8(%rsp),%rbp /* setup frame ptr */ + push %rcx /* save ecx */ + mov %rbp,%rcx + movslq %eax,%rax +P0: + sub $4096,%rcx + test %rax,(%rcx) + sub $4096,%rax + cmp $4096,%rax + jge P0 + sub %rax,%rcx + test %rax,(%rcx) + + mov %rsp,%rax + mov %rcx,%rsp + mov (%rax),%rcx /* restore ecx */ + jmp *8(%rax) + +/* ---------------------------------------------- */ +#endif +/* ---------------------------------------------- */ diff --git a/x86_64-gen.c b/x86_64-gen.c index 19e8028..cc68e34 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -919,12 +919,13 @@ void gfunc_epilog(void) v = (-loc + 15) & -16; saved_ind = ind; ind = func_sub_sp_offset - FUNC_PROLOG_SIZE; -#if 0 // def TCC_TARGET_PE - don't have __chkstk yet, because assembler does not work +#ifdef TCC_TARGET_PE if (v >= 4096) { Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0); oad(0xb8, v); /* mov stacksize, %eax */ oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */ greloc(cur_text_section, sym, ind-4, R_X86_64_PC32); + o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */ } else #endif {