From 73faaea227a53e365dd75f1dba7a5071c7b5e541 Mon Sep 17 00:00:00 2001 From: grischka Date: Wed, 28 Aug 2013 22:55:05 +0200 Subject: i386-gen: preserve fp control word in gen_cvt_ftoi - Use runtime function for conversion - Also initialize fp with tcc -run on windows This fixes a bug where double x = 1.0; double y = 1.0000000000000001; double z = x < y ? 0 : sqrt (x*x - y*y); caused a bad sqrt because rounding precision for the x < y comparison was different to the one used within the sqrt function. This also fixes a bug where printf("%d, %d", (int)pow(10, 2), (int)pow(10, 2)); would print 100, 99 Unrelated: win32: document relative include & lib lookup win32: normalize_slashes: do not mirror silly gcc behavior This reverts part of commit 8a81f9e1036637e21a47e14fb56bf64133546890 winapi: add missing WINAPI decl. for some functions --- tcc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 859d4fd..c988e4f 100644 --- a/tcc.h +++ b/tcc.h @@ -665,6 +665,7 @@ struct TCCState { #endif #ifdef TCC_IS_NATIVE + const char *runtime_main; /* for tcc_relocate */ void *runtime_mem; # ifdef HAVE_SELINUX -- cgit v1.3.1 From 9382d6f1a0e2d0104a82ed805207d9e742c6b068 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sat, 7 Sep 2013 19:26:36 +0200 Subject: Fix lib, include, crt and libgcc search paths --- configure | 2 +- tcc.h | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'tcc.h') diff --git a/configure b/configure index b513cc1..d654fd9 100755 --- a/configure +++ b/configure @@ -304,7 +304,7 @@ if test -z "$cross_prefix" ; then if test "$mingw32" = "no" ; then triplet="$($CONFTEST triplet)" if test -f "/usr/lib/$triplet/crti.o" ; then - tcc_lddir="lib/$triplet" + tcc_lddir="lib" multiarch_triplet="$triplet" elif test -f "/usr/lib64/crti.o" ; then tcc_lddir="lib64" diff --git a/tcc.h b/tcc.h index c988e4f..98f28db 100644 --- a/tcc.h +++ b/tcc.h @@ -168,10 +168,13 @@ #ifndef CONFIG_LDDIR # define CONFIG_LDDIR "lib" #endif +#ifndef CONFIG_MULTIARCHDIR +#define CONFIG_MULTIARCHDIR +#endif /* path to find crt1.o, crti.o and crtn.o */ #ifndef CONFIG_TCC_CRTPREFIX -# define CONFIG_TCC_CRTPREFIX CONFIG_SYSROOT "/usr/" CONFIG_LDDIR +# define CONFIG_TCC_CRTPREFIX CONFIG_SYSROOT "/usr/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR #endif /* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */ @@ -180,16 +183,11 @@ #ifndef CONFIG_TCC_SYSINCLUDEPATHS # ifdef TCC_TARGET_PE # define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include;{B}/include/winapi" -# elif defined CONFIG_MULTIARCHDIR +# else # define CONFIG_TCC_SYSINCLUDEPATHS \ - CONFIG_SYSROOT "/usr/local/include" \ ":" CONFIG_SYSROOT "/usr/local/include/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/include" \ + ":" CONFIG_SYSROOT "/usr/local/include" \ ":" CONFIG_SYSROOT "/usr/include/" CONFIG_MULTIARCHDIR \ - ":" "{B}/include" -# else -# define CONFIG_TCC_SYSINCLUDEPATHS \ - CONFIG_SYSROOT "/usr/local/include" \ ":" CONFIG_SYSROOT "/usr/include" \ ":" "{B}/include" # endif @@ -201,8 +199,11 @@ # define CONFIG_TCC_LIBPATHS "{B}/lib;{B}" # else # define CONFIG_TCC_LIBPATHS \ - CONFIG_SYSROOT "/usr/" CONFIG_LDDIR \ + CONFIG_SYSROOT "/usr/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ + ":" CONFIG_SYSROOT "/usr/" CONFIG_LDDIR \ + ":" CONFIG_SYSROOT "/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ ":" CONFIG_SYSROOT "/" CONFIG_LDDIR \ + ":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ ":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR # endif #endif @@ -235,7 +236,7 @@ #endif /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ -#define TCC_LIBGCC CONFIG_SYSROOT "/" CONFIG_LDDIR "/libgcc_s.so.1" +#define TCC_LIBGCC CONFIG_SYSROOT "/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR "/libgcc_s.so.1" /* -------------------------------------------- */ /* include the target specific definitions */ -- cgit v1.3.1 From 76cb1144ef91924c53c57ea71e6f67ce73ce1cc6 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 16 Sep 2013 14:48:33 +0200 Subject: Generate an error when a function is redefined Use one more bit in AttributeDef to differenciate between declared function (only its prototype is known) and defined function (its body is also known). This allows to generate an error in cases like: int f(){return 0;} int f(){return 1;} --- tcc.h | 4 +++- tccgen.c | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 98f28db..5ed3e21 100644 --- a/tcc.h +++ b/tcc.h @@ -389,9 +389,10 @@ typedef struct AttributeDef { func_export : 1, func_import : 1, func_args : 5, + func_proto : 1, mode : 4, weak : 1, - fill : 11; + fill : 10; struct Section *section; int alias_target; /* token */ } AttributeDef; @@ -401,6 +402,7 @@ typedef struct AttributeDef { #define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export) #define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import) #define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args) +#define FUNC_PROTO(r) (((AttributeDef*)&(r))->func_proto) #define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned) #define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed) #define ATTR_MODE(r) (((AttributeDef*)&(r))->mode) diff --git a/tccgen.c b/tccgen.c index 4849b6c..a937358 100644 --- a/tccgen.c +++ b/tccgen.c @@ -5818,6 +5818,10 @@ static int decl0(int l, int is_for_loop_init) goto func_error1; r = sym->type.ref->r; + + if (!FUNC_PROTO(r)) + tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); + /* use func_call from prototype if not defined */ if (FUNC_CALL(r) != FUNC_CDECL && FUNC_CALL(type.ref->r) == FUNC_CDECL) @@ -5836,6 +5840,7 @@ static int decl0(int l, int is_for_loop_init) tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } + FUNC_PROTO(type.ref->r) = 0; /* if symbol is already defined, then put complete type */ sym->type = type; } else { @@ -5901,6 +5906,7 @@ static int decl0(int l, int is_for_loop_init) if ((type.t & VT_BTYPE) == VT_FUNC) { /* external function definition */ /* specific case for func_call attribute */ + ad.func_proto = 1; type.ref->r = INT_ATTR(&ad); } else if (!(type.t & VT_ARRAY)) { /* not lvalue if array */ -- cgit v1.3.1 From d0c2f00df2366ba2114c75ada95c578864a81387 Mon Sep 17 00:00:00 2001 From: Ramsay Jones Date: Wed, 2 Oct 2013 21:49:55 +0200 Subject: Fix CONFIG_TCC_SYSINCLUDEPATHS on !win32 systems Commit 9382d6f1 ("Fix lib, include, crt and libgcc search paths", 07-09-2013) inadvertently included an initial empty entry to the CONFIG_TCC_SYSINCLUDEPATHS variable (for non win32 targets). In addition to an empty line in the 'tcc -vv' display, this leads to the preprocessor attempting to read an include file from the root of the filesystem (i.e. '/header.h'). Signed-off-by: Ramsay Jones --- tcc.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 5ed3e21..92e528d 100644 --- a/tcc.h +++ b/tcc.h @@ -185,7 +185,7 @@ # define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include;{B}/include/winapi" # else # define CONFIG_TCC_SYSINCLUDEPATHS \ - ":" CONFIG_SYSROOT "/usr/local/include/" CONFIG_MULTIARCHDIR \ + CONFIG_SYSROOT "/usr/local/include/" CONFIG_MULTIARCHDIR \ ":" CONFIG_SYSROOT "/usr/local/include" \ ":" CONFIG_SYSROOT "/usr/include/" CONFIG_MULTIARCHDIR \ ":" CONFIG_SYSROOT "/usr/include" \ @@ -753,8 +753,9 @@ struct TCCState { #define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */ #define VT_EXPORT 0x00008000 /* win32: data exported from dll */ #define VT_WEAK 0x00010000 /* weak symbol */ +#define VT_TLS 0x00040000 /* thread-local storage */ -#define VT_STRUCT_SHIFT 18 /* shift for bitfield shift values (max: 32 - 2*6) */ +#define VT_STRUCT_SHIFT 19 /* shift for bitfield shift values (max: 32 - 2*6) */ /* type mask (except storage) */ #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK) @@ -1140,6 +1141,7 @@ ST_FUNC void expect(const char *msg); /* ------------ tccgen.c ------------ */ ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ +ST_DATA Section *tdata_section, *tbss_section; /* thread-local storage sections */ ST_DATA Section *cur_text_section; /* current section where function code is generated */ #ifdef CONFIG_TCC_ASM ST_DATA Section *last_text_section; /* to handle .previous asm directive */ -- cgit v1.3.1 From a01d83d78380e84b04d62ca34a142a7e3d8e390d Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 6 Jan 2014 11:09:06 +0800 Subject: Don't enable bound check if libgcc is used Bound check rely on some functions provided by libtcc. It should therefore not be enabled when libgcc is used. --- tcc-doc.texi | 2 +- tcc.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'tcc.h') diff --git a/tcc-doc.texi b/tcc-doc.texi index dbfbb4a..fbb0220 100644 --- a/tcc-doc.texi +++ b/tcc-doc.texi @@ -338,7 +338,7 @@ Generate additional support code to check memory allocations and array/pointer bounds. @option{-g} is implied. Note that the generated code is slower and bigger in this case. -Note: @option{-b} is only available on i386 for the moment. +Note: @option{-b} is only available on i386 when using libtcc for the moment. @item -bt N Display N callers in stack traces. This is useful with @option{-g} or diff --git a/tcc.h b/tcc.h index 92e528d..50642b7 100644 --- a/tcc.h +++ b/tcc.h @@ -128,7 +128,8 @@ #endif #if !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \ - !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) + !defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64) && \ + !defined(CONFIG_USE_LIBGCC) #define CONFIG_TCC_BCHECK /* enable bound checking code */ #endif -- cgit v1.3.1 From 8efaa711904b897f9a4821656ac10f980c5ae9fe Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 6 Jan 2014 22:27:39 +0800 Subject: Fix struct ret in variadic fct with ARM hardfloat The procedure calling standard for ARM architecture mandate the use of the base standard for variadic function. Therefore, hgen float aggregate must be returned via stack when greater than 4 bytes and via core registers else in case of variadic function. This patch improve gfunc_sret() to take into account whether the function is variadic or not and make use of gfunc_sret() return value to determine whether to pass a structure via stack in gfunc_prolog(). It also take advantage of knowing if a function is variadic or not move float result value from VFP register to core register in gfunc_epilog(). --- arm-gen.c | 34 ++++++++++++++++++---------------- c67-gen.c | 3 ++- i386-gen.c | 3 ++- il-gen.c | 1 + tcc.h | 3 ++- tccgen.c | 11 ++++++++--- x86_64-gen.c | 3 ++- 7 files changed, 35 insertions(+), 23 deletions(-) (limited to 'tcc.h') diff --git a/arm-gen.c b/arm-gen.c index eecb7d2..9e6c638 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -839,12 +839,12 @@ int floats_in_core_regs(SValue *sval) /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { #ifdef TCC_ARM_EABI int size, align; size = type_size(vt, &align); #ifdef TCC_ARM_HARDFLOAT - if (is_float(vt->t) || is_hgen_float_aggr(vt)) { + if (!variadic && (is_float(vt->t) || is_hgen_float_aggr(vt))) { *ret_align = 8; ret->ref = NULL; ret->t = VT_DOUBLE; @@ -1221,21 +1221,19 @@ void gfunc_call(int nb_args) void gfunc_prolog(CType *func_type) { Sym *sym,*sym2; - int n,nf,size,align, variadic, struct_ret = 0; + int n, nf, size, align, struct_ret = 0; #ifdef TCC_ARM_HARDFLOAT struct avail_regs avregs = AVAIL_REGS_INITIALIZER; #endif + CType ret_type; sym = func_type->ref; func_vt = sym->type; + func_var = (func_type->ref->c == FUNC_ELLIPSIS); n = nf = 0; - variadic = (func_type->ref->c == FUNC_ELLIPSIS); - if((func_vt.t & VT_BTYPE) == VT_STRUCT -#ifdef TCC_ARM_HARDFLOAT - && (variadic || !is_hgen_float_aggr(&func_vt)) -#endif - && type_size(&func_vt,&align) > 4) + if ((func_vt.t & VT_BTYPE) == VT_STRUCT && + !gfunc_sret(&func_vt, func_var, &ret_type, &align)) { n++; struct_ret = 1; @@ -1244,7 +1242,7 @@ void gfunc_prolog(CType *func_type) for(sym2=sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) { size = type_size(&sym2->type, &align); #ifdef TCC_ARM_HARDFLOAT - if (!variadic && (is_float(sym2->type.t) + if (!func_var && (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { int tmpnf = assign_vfpreg(&avregs, align, size); tmpnf += (size + 3) / 4; @@ -1255,9 +1253,9 @@ void gfunc_prolog(CType *func_type) n += (size + 3) / 4; } o(0xE1A0C00D); /* mov ip,sp */ - if(variadic) + if (func_var) n=4; - if(n) { + if (n) { if(n>4) n=4; #ifdef TCC_ARM_EABI @@ -1289,7 +1287,7 @@ void gfunc_prolog(CType *func_type) size = (size + 3) >> 2; align = (align + 3) & ~3; #ifdef TCC_ARM_HARDFLOAT - if (!variadic && (is_float(sym->type.t) + if (!func_var && (is_float(sym->type.t) || is_hgen_float_aggr(&sym->type))) { int fpn = assign_vfpreg(&avregs, align, size << 2); if (fpn >= 0) { @@ -1329,10 +1327,14 @@ void gfunc_epilog(void) { uint32_t x; int diff; + /* Copy float return value to core register if base standard is used and + float computation is made with VFP */ #ifdef TCC_ARM_EABI - /* Useless but harmless copy of the float result into main register(s) in case - of variadic function in the hardfloat variant */ - if(is_float(func_vt.t)) { + if ( +#ifdef TCC_ARM_HARDFLOAT + func_var && +#endif + is_float(func_vt.t)) { if((func_vt.t & VT_BTYPE) == VT_FLOAT) o(0xEE100A10); /* fmrs r0, s0 */ else { diff --git a/c67-gen.c b/c67-gen.c index df4b5d3..f2baea5 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -1881,7 +1881,7 @@ static void gcall_or_jmp(int is_jmp) /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { *ret_align = 1; // Never have to re-align return values for x86-64 return 0; } @@ -1971,6 +1971,7 @@ void gfunc_prolog(CType * func_type) /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->type; + func_var = (sym->c == FUNC_ELLIPSIS); if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { func_vc = addr; addr += 4; diff --git a/i386-gen.c b/i386-gen.c index 4201ac2..2eb6922 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -376,7 +376,7 @@ static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { #ifdef TCC_TARGET_PE int size, align; @@ -527,6 +527,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->type; + func_var = (sym->c == FUNC_ELLIPSIS); #ifdef TCC_TARGET_PE size = type_size(&func_vt,&align); if (((func_vt.t & VT_BTYPE) == VT_STRUCT) && (size > 8)) { diff --git a/il-gen.c b/il-gen.c index 33f9f36..9e1ec64 100644 --- a/il-gen.c +++ b/il-gen.c @@ -441,6 +441,7 @@ void gfunc_prolog(int t) /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->t; + func_var = (sym->c == FUNC_ELLIPSIS); if ((func_vt & VT_BTYPE) == VT_STRUCT) { func_vc = addr; addr++; diff --git a/tcc.h b/tcc.h index 50642b7..21957e7 100644 --- a/tcc.h +++ b/tcc.h @@ -1176,6 +1176,7 @@ ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ ST_DATA CType func_vt; /* current function return type (used by return instruction) */ +ST_DATA int func_var; /* true if current function is variadic */ ST_DATA int func_vc; ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ ST_DATA char *funcname; @@ -1288,7 +1289,7 @@ ST_FUNC void gsym_addr(int t, int a); ST_FUNC void gsym(int t); ST_FUNC void load(int r, SValue *sv); ST_FUNC void store(int r, SValue *v); -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *align); +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align); ST_FUNC void gfunc_call(int nb_args); ST_FUNC void gfunc_prolog(CType *func_type); ST_FUNC void gfunc_epilog(void); diff --git a/tccgen.c b/tccgen.c index 55b03e6..8355aae 100644 --- a/tccgen.c +++ b/tccgen.c @@ -66,6 +66,7 @@ ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ ST_DATA CType func_vt; /* current function return type (used by return instruction) */ +ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ ST_DATA int func_vc; ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ ST_DATA char *funcname; @@ -3960,7 +3961,7 @@ ST_FUNC void unary(void) } else if (tok == '(') { SValue ret; Sym *sa; - int nb_args, ret_nregs, ret_align; + int nb_args, ret_nregs, ret_align, variadic; /* function call */ if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { @@ -3984,7 +3985,9 @@ ST_FUNC void unary(void) ret.r2 = VT_CONST; /* compute first implicit argument if a structure is returned */ if ((s->type.t & VT_BTYPE) == VT_STRUCT) { - ret_nregs = gfunc_sret(&s->type, &ret.type, &ret_align); + variadic = (s->c == FUNC_ELLIPSIS); + ret_nregs = gfunc_sret(&s->type, variadic, &ret.type, + &ret_align); if (!ret_nregs) { /* get some space for the returned structure */ size = type_size(&s->type, &align); @@ -4637,7 +4640,8 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { CType type, ret_type; int ret_align, ret_nregs; - ret_nregs = gfunc_sret(&func_vt, &ret_type, &ret_align); + ret_nregs = gfunc_sret(&func_vt, func_var, &ret_type, + &ret_align); if (0 == ret_nregs) { /* if returning structure, must copy it to implicit first pointer arg location */ @@ -5747,6 +5751,7 @@ static void gen_function(Sym *sym) cur_text_section = NULL; funcname = ""; /* for safety */ func_vt.t = VT_VOID; /* for safety */ + func_var = 0; /* for safety */ ind = 0; /* for safety */ nocode_wanted = saved_nocode_wanted; } diff --git a/x86_64-gen.c b/x86_64-gen.c index fe028d9..9aee875 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -658,7 +658,7 @@ void gen_offs_sp(int b, int r, int d) /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { int size, align; *ret_align = 1; // Never have to re-align return values for x86-64 @@ -833,6 +833,7 @@ void gfunc_prolog(CType *func_type) /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->type; + func_var = (sym->c == FUNC_ELLIPSIS); size = gfunc_arg_size(&func_vt); if (size > 8) { gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); -- cgit v1.3.1 From 2bd0daabbe1fc40e65e4a4631e68f5ca093ea1fb Mon Sep 17 00:00:00 2001 From: grischka Date: Mon, 6 Jan 2014 19:56:26 +0100 Subject: misc. fixes - tccgen: error out for cast to void, as in void foo(void) { return 1; } This avoids an assertion failure in x86_64-gen.c, also. also fix tests2/03_struct.c accordingly - Error: "memory full" - be more specific - Makefiles: remove circular dependencies, lookup tcctest.c from VPATH - tcc.h: cleanup lib, include, crt and libgcc search paths" avoid duplication or trailing slashes with no CONFIG_MULTIARCHDIR (as from 9382d6f1a0e2d0104a82ed805207d9e742c6b068) - tcc.h: remove ";{B}" from PE search path in ce5e12c2f950052d8109b6b7a56d900547705c08 James Lyon wrote: "... I'm not sure this is the right way to fix this problem." And the answer is: No, please. (copying libtcc1.a for tests instead) - win32/build_tcc.bat: do not move away a versioned file --- Makefile | 3 --- lib/Makefile | 3 --- libtcc.c | 4 ++-- tcc.h | 30 +++++++++++++++--------------- tccgen.c | 8 ++++---- tccpp.c | 4 ++-- tests/Makefile | 39 ++++++++++++++++++++------------------- tests/tests2/03_struct.c | 2 +- tests/tests2/Makefile | 3 --- win32/build-tcc.bat | 4 ++-- 10 files changed, 46 insertions(+), 54 deletions(-) (limited to 'tcc.h') diff --git a/Makefile b/Makefile index 24a7c09..5052758 100644 --- a/Makefile +++ b/Makefile @@ -362,9 +362,6 @@ tar: tcc-doc.html rm -rf $(TCC-VERSION) git reset -Makefile: $(top_srcdir)/Makefile - cp $< $@ - .PHONY: all clean tar distclean install uninstall FORCE endif # ifeq ($(TOP),.) diff --git a/lib/Makefile b/lib/Makefile index a8a2b5d..394df67 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -111,6 +111,3 @@ $(DIR)/exists : clean : rm -rfv i386-win32 x86_64-win32 i386 x86_64 - -Makefile: $(top_srcdir)/lib/Makefile - cp $< $@ diff --git a/libtcc.c b/libtcc.c index df201ae..072b77f 100644 --- a/libtcc.c +++ b/libtcc.c @@ -214,7 +214,7 @@ PUB_FUNC void *tcc_malloc(unsigned long size) void *ptr; ptr = malloc(size); if (!ptr && size) - tcc_error("memory full"); + tcc_error("memory full (malloc)"); #ifdef MEM_DEBUG mem_cur_size += malloc_usable_size(ptr); if (mem_cur_size > mem_max_size) @@ -239,7 +239,7 @@ PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size) #endif ptr1 = realloc(ptr, size); if (!ptr1 && size) - tcc_error("memory full"); + tcc_error("memory full (realloc)"); #ifdef MEM_DEBUG /* NOTE: count not correct if alloc error, but not critical */ mem_cur_size += malloc_usable_size(ptr1); diff --git a/tcc.h b/tcc.h index 21957e7..0933b01 100644 --- a/tcc.h +++ b/tcc.h @@ -169,13 +169,18 @@ #ifndef CONFIG_LDDIR # define CONFIG_LDDIR "lib" #endif -#ifndef CONFIG_MULTIARCHDIR -#define CONFIG_MULTIARCHDIR + +#ifdef CONFIG_MULTIARCHDIR +# define USE_MUADIR(s) s "/" CONFIG_MULTIARCHDIR +# define ALSO_MUADIR(s) s "/" CONFIG_MULTIARCHDIR ":" s +#else +# define USE_MUADIR(s) s +# define ALSO_MUADIR(s) s #endif /* path to find crt1.o, crti.o and crtn.o */ #ifndef CONFIG_TCC_CRTPREFIX -# define CONFIG_TCC_CRTPREFIX CONFIG_SYSROOT "/usr/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR +# define CONFIG_TCC_CRTPREFIX USE_MUADIR(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) #endif /* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */ @@ -186,10 +191,8 @@ # define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include;{B}/include/winapi" # else # define CONFIG_TCC_SYSINCLUDEPATHS \ - CONFIG_SYSROOT "/usr/local/include/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/local/include" \ - ":" CONFIG_SYSROOT "/usr/include/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/include" \ + ALSO_MUADIR(CONFIG_SYSROOT "/usr/local/include") \ + ":" ALSO_MUADIR(CONFIG_SYSROOT "/usr/include") \ ":" "{B}/include" # endif #endif @@ -197,15 +200,12 @@ /* library search paths */ #ifndef CONFIG_TCC_LIBPATHS # ifdef TCC_TARGET_PE -# define CONFIG_TCC_LIBPATHS "{B}/lib;{B}" +# define CONFIG_TCC_LIBPATHS "{B}/lib" # else # define CONFIG_TCC_LIBPATHS \ - CONFIG_SYSROOT "/usr/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/" CONFIG_LDDIR \ - ":" CONFIG_SYSROOT "/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/" CONFIG_LDDIR \ - ":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR \ - ":" CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR + ALSO_MUADIR(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \ + ":" ALSO_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) \ + ":" ALSO_MUADIR(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR) # endif #endif @@ -237,7 +237,7 @@ #endif /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ -#define TCC_LIBGCC CONFIG_SYSROOT "/" CONFIG_LDDIR "/" CONFIG_MULTIARCHDIR "/libgcc_s.so.1" +#define TCC_LIBGCC USE_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1" /* -------------------------------------------- */ /* include the target specific definitions */ diff --git a/tccgen.c b/tccgen.c index 8355aae..f23cd07 100644 --- a/tccgen.c +++ b/tccgen.c @@ -309,7 +309,7 @@ static void vsetc(CType *type, int r, CValue *vc) int v; if (vtop >= vstack + (VSTACK_SIZE - 1)) - tcc_error("memory full"); + tcc_error("memory full (vstack)"); /* cannot let cpu flags if other instruction are generated. Also avoid leaving VT_JMP anywhere except on the top of the stack because it would complicate the code generator. */ @@ -483,7 +483,7 @@ ST_FUNC void vswap(void) ST_FUNC void vpushv(SValue *v) { if (vtop >= vstack + (VSTACK_SIZE - 1)) - tcc_error("memory full"); + tcc_error("memory full (vstack)"); vtop++; *vtop = *v; } @@ -2348,8 +2348,8 @@ static void gen_assign_cast(CType *dt) st = &vtop->type; /* source type */ dbt = dt->t & VT_BTYPE; sbt = st->t & VT_BTYPE; - if (sbt == VT_VOID) - tcc_error("Cannot assign void value"); + if (sbt == VT_VOID || dbt == VT_VOID) + tcc_error("cannot cast from/to void"); if (dt->t & VT_CONSTANT) tcc_warning("assignment of read-only location"); switch(dbt) { diff --git a/tccpp.c b/tccpp.c index aeaf6be..e1ccded 100644 --- a/tccpp.c +++ b/tccpp.c @@ -197,7 +197,7 @@ static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len) int i; if (tok_ident >= SYM_FIRST_ANOM) - tcc_error("memory full"); + tcc_error("memory full (symbols)"); /* expand token table if needed */ i = tok_ident - TOK_IDENT; @@ -1528,7 +1528,7 @@ include_done: c = (define_find(tok) != 0) ^ c; do_if: if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE) - tcc_error("memory full"); + tcc_error("memory full (ifdef)"); *s1->ifdef_stack_ptr++ = c; goto test_skip; case TOK_ELSE: diff --git a/tests/Makefile b/tests/Makefile index 08dfa42..b958a48 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -27,7 +27,7 @@ ifneq ($(ARCH),i386) TESTS := $(filter-out btest,$(TESTS)) endif ifdef CONFIG_WIN32 - TESTS := $(filter-out test3,$(TESTS)) + TESTS := w32-prep $(filter-out test3,$(TESTS)) endif ifeq ($(TARGETOS),Darwin) TESTS := $(filter-out hello-exe test3 btest,$(TESTS)) @@ -84,6 +84,9 @@ moretests: @echo ------------ $@ ------------ $(MAKE) -C tests2 +w32-prep: + cp ../libtcc1.a ../lib + # test.ref - generate using gcc # copy only tcclib.h so GCC's stddef and stdarg will be used test.ref: tcctest.c @@ -91,41 +94,41 @@ test.ref: tcctest.c ./tcctest.gcc > $@ # auto test -test1: test.ref +test1: tcctest.c test.ref @echo ------------ $@ ------------ - $(TCC) -run $(SRCDIR)/tcctest.c > test.out1 + $(TCC) -run $< > test.out1 @if diff -u test.ref test.out1 ; then echo "Auto Test OK"; fi # iterated test2 (compile tcc then compile tcctest.c !) -test2: test.ref +test2: tcctest.c test.ref @echo ------------ $@ ------------ - $(TCC) $(RUN_TCC) $(RUN_TCC) -run $(SRCDIR)/tcctest.c > test.out2 + $(TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out2 @if diff -u test.ref test.out2 ; then echo "Auto Test2 OK"; fi # iterated test3 (compile tcc then compile tcc then compile tcctest.c !) -test3: test.ref +test3: tcctest.c test.ref @echo ------------ $@ ------------ - $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $(SRCDIR)/tcctest.c > test.out3 + $(TCC) $(RUN_TCC) $(RUN_TCC) $(RUN_TCC) -run $< > test.out3 @if diff -u test.ref test.out3 ; then echo "Auto Test3 OK"; fi # binary output test -test4: test.ref +test4: tcctest.c test.ref @echo ------------ $@ ------------ # object + link output - $(TCC) -c -o tcctest3.o $(SRCDIR)/tcctest.c + $(TCC) -c -o tcctest3.o $< $(TCC) -o tcctest3 tcctest3.o ./tcctest3 > test3.out @if diff -u test.ref test3.out ; then echo "Object Auto Test OK"; fi # dynamic output - $(TCC) -o tcctest1 $(SRCDIR)/tcctest.c + $(TCC) -o tcctest1 $< ./tcctest1 > test1.out @if diff -u test.ref test1.out ; then echo "Dynamic Auto Test OK"; fi # dynamic output + bound check - $(TCC) -b -o tcctest4 $(SRCDIR)/tcctest.c + $(TCC) -b -o tcctest4 $< ./tcctest4 > test4.out @if diff -u test.ref test4.out ; then echo "BCheck Auto Test OK"; fi # static output - $(TCC) -static -o tcctest2 $(SRCDIR)/tcctest.c + $(TCC) -static -o tcctest2 $< ./tcctest2 > test2.out @if diff -u test.ref test2.out ; then echo "Static Auto Test OK"; fi @@ -161,9 +164,9 @@ speedtest: ex2 ex3 time ./ex3 35 time $(TCC) -run $(top_srcdir)/examples/ex3.c 35 -weaktest: test.ref - $(TCC) -c tcctest.c -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS) - $(CC) -c tcctest.c -o weaktest.gcc.o -I. $(CPPFLAGS) -w $(CFLAGS) +weaktest: tcctest.c test.ref + $(TCC) -c $< -o weaktest.tcc.o $(CPPFLAGS) $(CFLAGS) + $(CC) -c $< -o weaktest.gcc.o -I. $(CPPFLAGS) -w $(CFLAGS) objdump -t weaktest.tcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.tcc.o.txt objdump -t weaktest.gcc.o | grep ' w ' | sed -e 's/.* \([a-zA-Z0-9_]*\)$$/\1/' | LC_ALL=C sort > weaktest.gcc.o.txt diff weaktest.gcc.o.txt weaktest.tcc.o.txt && echo "Weak Auto Test OK" @@ -220,7 +223,5 @@ cache: tcc_g clean: $(MAKE) -C tests2 $@ rm -vf *~ *.o *.a *.bin *.i *.ref *.out *.out? *.out?b *.gcc *.exe \ - hello libtcc_test tcctest[1234] ex? tcc_g tcclib.h - -Makefile: $(SRCDIR)/Makefile - cp $< $@ + hello libtcc_test tcctest[1234] ex? tcc_g tcclib.h \ + ../lib/libtcc1.a diff --git a/tests/tests2/03_struct.c b/tests/tests2/03_struct.c index df0d3e7..c5d48c5 100644 --- a/tests/tests2/03_struct.c +++ b/tests/tests2/03_struct.c @@ -6,7 +6,7 @@ struct fred int natasha; }; -void main() +int main() { struct fred bloggs; diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 369ed47..51dc38d 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -96,6 +96,3 @@ all test: $(TESTS) clean: rm -vf fred.txt *.output - -Makefile: $(top_srcdir)/tests/tests2/Makefile - cp $< $@ diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat index 772ed26..bd897c4 100644 --- a/win32/build-tcc.bat +++ b/win32/build-tcc.bat @@ -63,5 +63,5 @@ del *.o echo>..\config.texi @set VERSION %VERSION% if not exist doc md doc makeinfo --html --no-split -o doc\tcc-doc.html ../tcc-doc.texi -if exist tcc-win32.txt move tcc-win32.txt doc\ -copy ..\tests\libtcc_test.c examples\ +copy tcc-win32.txt doc +copy ..\tests\libtcc_test.c examples -- cgit v1.3.1 From 3fe2a95d7fe854c8cf496a009a467bb65cdf030d Mon Sep 17 00:00:00 2001 From: grischka Date: Tue, 7 Jan 2014 14:57:07 +0100 Subject: be stricter with aliasing Refactoring (no logical changes): - use memcpy in tccgen.c:ieee_finite(double d) - use union to store attribute flags in Sym Makefile: "CFLAGS+=-fno-strict-aliasing" basically not necessary anymore but I left it for now because gcc sometimes behaves unexpectedly without. Also: - configure: back to mode 100755 - tcc.h: remove unused variables tdata/tbss_section - x86_64-gen.c: adjust gfunc_sret for prototype --- configure | 0 i386-gen.c | 4 +-- libtcc.c | 8 ++--- tcc.h | 57 ++++++++++++++++------------------- tccgen.c | 97 +++++++++++++++++++++++++++++++----------------------------- x86_64-gen.c | 15 ++++++---- 6 files changed, 92 insertions(+), 89 deletions(-) mode change 100644 => 100755 configure (limited to 'tcc.h') diff --git a/configure b/configure old mode 100644 new mode 100755 diff --git a/i386-gen.c b/i386-gen.c index 4c4a54b..ece054b 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -457,7 +457,7 @@ ST_FUNC void gfunc_call(int nb_args) } save_regs(0); /* save used temporary registers */ func_sym = vtop->type.ref; - func_call = FUNC_CALL(func_sym->r); + func_call = func_sym->a.func_call; /* fast call case */ if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || func_call == FUNC_FASTCALLW) { @@ -505,7 +505,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) CType *type; sym = func_type->ref; - func_call = FUNC_CALL(sym->r); + func_call = sym->a.func_call; addr = 8; loc = 0; func_vc = 0; diff --git a/libtcc.c b/libtcc.c index 072b77f..154a266 100644 --- a/libtcc.c +++ b/libtcc.c @@ -493,11 +493,11 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, if (sym->type.t & VT_EXPORT) other |= 1; if (sym_type == STT_FUNC && sym->type.ref) { - int attr = sym->type.ref->r; - if (FUNC_EXPORT(attr)) + Sym *ref = sym->type.ref; + if (ref->a.func_export) other |= 1; - if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) { - sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE); + if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) { + sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE); name = buf1; other |= 2; can_add_underscore = 0; diff --git a/tcc.h b/tcc.h index 0933b01..f3d868f 100644 --- a/tcc.h +++ b/tcc.h @@ -326,11 +326,35 @@ typedef struct SValue { struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */ } SValue; +struct Attribute { + unsigned + func_call : 3, /* calling convention (0..5), see below */ + aligned : 5, /* alignement (0..16) */ + packed : 1, + func_export : 1, + func_import : 1, + func_args : 5, + func_proto : 1, + mode : 4, + weak : 1, + fill : 10; // 10 bits left to fit well in union below +}; + +/* GNUC attribute definition */ +typedef struct AttributeDef { + struct Attribute a; + struct Section *section; + int alias_target; /* token */ +} AttributeDef; + /* symbol management */ typedef struct Sym { int v; /* symbol token */ char *asm_label; /* associated asm label */ - long r; /* associated register */ + union { + long r; /* associated register */ + struct Attribute a; + }; union { long c; /* associated number */ int *d; /* define token stream */ @@ -381,34 +405,6 @@ typedef struct DLLReference { char name[1]; } DLLReference; -/* GNUC attribute definition */ -typedef struct AttributeDef { - unsigned - func_call : 3, /* calling convention (0..5), see below */ - aligned : 5, /* alignement (0..16) */ - packed : 1, - func_export : 1, - func_import : 1, - func_args : 5, - func_proto : 1, - mode : 4, - weak : 1, - fill : 10; - struct Section *section; - int alias_target; /* token */ -} AttributeDef; - -/* gr: wrappers for casting sym->r for other purposes */ -#define FUNC_CALL(r) (((AttributeDef*)&(r))->func_call) -#define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export) -#define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import) -#define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args) -#define FUNC_PROTO(r) (((AttributeDef*)&(r))->func_proto) -#define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned) -#define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed) -#define ATTR_MODE(r) (((AttributeDef*)&(r))->mode) -#define INT_ATTR(ad) (*(int*)(ad)) - /* -------------------------------------------------- */ #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */ @@ -1142,7 +1138,6 @@ ST_FUNC void expect(const char *msg); /* ------------ tccgen.c ------------ */ ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ -ST_DATA Section *tdata_section, *tbss_section; /* thread-local storage sections */ ST_DATA Section *cur_text_section; /* current section where function code is generated */ #ifdef CONFIG_TCC_ASM ST_DATA Section *last_text_section; /* to handle .previous asm directive */ @@ -1268,7 +1263,7 @@ ST_FUNC void build_got_entries(TCCState *s1); ST_FUNC void tcc_add_runtime(TCCState *s1); ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err); -#ifdef TCC_IS_NATIVE +#if defined TCC_IS_NATIVE || defined TCC_TARGET_PE ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); #endif diff --git a/tccgen.c b/tccgen.c index f23cd07..7a675cc 100644 --- a/tccgen.c +++ b/tccgen.c @@ -103,7 +103,8 @@ ST_INLN int is_float(int t) /* XXX: endianness dependent */ ST_FUNC int ieee_finite(double d) { - int *p = (int *)&d; + int p[4]; + memcpy(p, &d, sizeof(double)); return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; } @@ -2172,7 +2173,7 @@ static int is_compatible_func(CType *type1, CType *type2) if (!is_compatible_types(&s1->type, &s2->type)) return 0; /* check func_call */ - if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r)) + if (s1->a.func_call != s2->a.func_call) return 0; /* XXX: not complete */ if (s1->c == FUNC_OLD || s2->c == FUNC_OLD) @@ -2659,15 +2660,15 @@ static void parse_attribute(AttributeDef *ad) } else { n = MAX_ALIGN; } - ad->aligned = n; + ad->a.aligned = n; break; case TOK_PACKED1: case TOK_PACKED2: - ad->packed = 1; + ad->a.packed = 1; break; case TOK_WEAK1: case TOK_WEAK2: - ad->weak = 1; + ad->a.weak = 1; break; case TOK_UNUSED1: case TOK_UNUSED2: @@ -2682,12 +2683,12 @@ static void parse_attribute(AttributeDef *ad) case TOK_CDECL1: case TOK_CDECL2: case TOK_CDECL3: - ad->func_call = FUNC_CDECL; + ad->a.func_call = FUNC_CDECL; break; case TOK_STDCALL1: case TOK_STDCALL2: case TOK_STDCALL3: - ad->func_call = FUNC_STDCALL; + ad->a.func_call = FUNC_STDCALL; break; #ifdef TCC_TARGET_I386 case TOK_REGPARM1: @@ -2699,26 +2700,26 @@ static void parse_attribute(AttributeDef *ad) else if (n < 0) n = 0; if (n > 0) - ad->func_call = FUNC_FASTCALL1 + n - 1; + ad->a.func_call = FUNC_FASTCALL1 + n - 1; skip(')'); break; case TOK_FASTCALL1: case TOK_FASTCALL2: case TOK_FASTCALL3: - ad->func_call = FUNC_FASTCALLW; + ad->a.func_call = FUNC_FASTCALLW; break; #endif case TOK_MODE: skip('('); switch(tok) { case TOK_MODE_DI: - ad->mode = VT_LLONG + 1; + ad->a.mode = VT_LLONG + 1; break; case TOK_MODE_HI: - ad->mode = VT_SHORT + 1; + ad->a.mode = VT_SHORT + 1; break; case TOK_MODE_SI: - ad->mode = VT_INT + 1; + ad->a.mode = VT_INT + 1; break; default: tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL)); @@ -2728,10 +2729,10 @@ static void parse_attribute(AttributeDef *ad) skip(')'); break; case TOK_DLLEXPORT: - ad->func_export = 1; + ad->a.func_export = 1; break; case TOK_DLLIMPORT: - ad->func_import = 1; + ad->a.func_import = 1; break; default: if (tcc_state->warn_unsupported) @@ -2873,10 +2874,10 @@ static void struct_decl(CType *type, int u, int tdef) get_tok_str(v, NULL)); } size = type_size(&type1, &align); - if (ad.aligned) { - if (align < ad.aligned) - align = ad.aligned; - } else if (ad.packed) { + if (ad.a.aligned) { + if (align < ad.a.aligned) + align = ad.a.aligned; + } else if (ad.a.packed) { align = 1; } else if (*tcc_state->pack_stack_ptr) { if (align > *tcc_state->pack_stack_ptr) @@ -3118,8 +3119,8 @@ static int parse_btype(CType *type, AttributeDef *ad) case TOK_ATTRIBUTE1: case TOK_ATTRIBUTE2: parse_attribute(ad); - if (ad->mode) { - u = ad->mode -1; + if (ad->a.mode) { + u = ad->a.mode -1; t = (t & ~VT_BTYPE) | u; } break; @@ -3143,11 +3144,11 @@ static int parse_btype(CType *type, AttributeDef *ad) type->ref = s->type.ref; if (s->r) { /* get attributes from typedef */ - if (0 == ad->aligned) - ad->aligned = FUNC_ALIGN(s->r); - if (0 == ad->func_call) - ad->func_call = FUNC_CALL(s->r); - ad->packed |= FUNC_PACKED(s->r); + if (0 == ad->a.aligned) + ad->a.aligned = s->a.aligned; + if (0 == ad->a.func_call) + ad->a.func_call = s->a.func_call; + ad->a.packed |= s->a.packed; } next(); typespec_found = 1; @@ -3287,8 +3288,9 @@ static void post_type(CType *type, AttributeDef *ad) type->t |= VT_PTR; } /* we push a anonymous symbol which will contain the function prototype */ - ad->func_args = arg_size; - s = sym_push(SYM_FIELD, type, INT_ATTR(ad), l); + ad->a.func_args = arg_size; + s = sym_push(SYM_FIELD, type, 0, l); + s->a = ad->a; s->next = first; type->t = VT_FUNC; type->ref = s; @@ -5484,10 +5486,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if (flexible_array) size += flexible_array->type.ref->c * pointed_size(&flexible_array->type); /* take into account specified alignment if bigger */ - if (ad->aligned) { - if (ad->aligned > align) - align = ad->aligned; - } else if (ad->packed) { + if (ad->a.aligned) { + if (ad->a.aligned > align) + align = ad->a.aligned; + } else if (ad->a.packed) { align = 1; } if ((r & VT_VALMASK) == VT_LOCAL) { @@ -5869,12 +5871,12 @@ static int decl0(int l, int is_for_loop_init) parse_attribute(&ad); } - if (ad.weak) + if (ad.a.weak) type.t |= VT_WEAK; #ifdef TCC_TARGET_PE - if (ad.func_import) + if (ad.a.func_import) type.t |= VT_IMPORT; - if (ad.func_export) + if (ad.a.func_export) type.t |= VT_EXPORT; #endif if (tok == '{') { @@ -5895,22 +5897,22 @@ static int decl0(int l, int is_for_loop_init) sym = sym_find(v); if (sym) { + Sym *ref; if ((sym->type.t & VT_BTYPE) != VT_FUNC) goto func_error1; - r = sym->type.ref->r; - - if (!FUNC_PROTO(r)) + ref = sym->type.ref; + if (0 == ref->a.func_proto) tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); /* use func_call from prototype if not defined */ - if (FUNC_CALL(r) != FUNC_CDECL - && FUNC_CALL(type.ref->r) == FUNC_CDECL) - FUNC_CALL(type.ref->r) = FUNC_CALL(r); + if (ref->a.func_call != FUNC_CDECL + && type.ref->a.func_call == FUNC_CDECL) + type.ref->a.func_call = ref->a.func_call; /* use export from prototype */ - if (FUNC_EXPORT(r)) - FUNC_EXPORT(type.ref->r) = 1; + if (ref->a.func_export) + type.ref->a.func_export = 1; /* use static from prototype */ if (sym->type.t & VT_STATIC) @@ -5921,7 +5923,7 @@ static int decl0(int l, int is_for_loop_init) tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } - FUNC_PROTO(type.ref->r) = 0; + type.ref->a.func_proto = 0; /* if symbol is already defined, then put complete type */ sym->type = type; } else { @@ -5980,15 +5982,16 @@ static int decl0(int l, int is_for_loop_init) if (btype.t & VT_TYPEDEF) { /* save typedefed type */ /* XXX: test storage specifiers ? */ - sym = sym_push(v, &type, INT_ATTR(&ad), 0); + sym = sym_push(v, &type, 0, 0); + sym->a = ad.a; sym->type.t |= VT_TYPEDEF; } else { r = 0; if ((type.t & VT_BTYPE) == VT_FUNC) { /* external function definition */ /* specific case for func_call attribute */ - ad.func_proto = 1; - type.ref->r = INT_ATTR(&ad); + ad.a.func_proto = 1; + type.ref->a = ad.a; } else if (!(type.t & VT_ARRAY)) { /* not lvalue if array */ r |= lvalue_type(type.t); @@ -6039,7 +6042,7 @@ static int decl0(int l, int is_for_loop_init) } next(); } - ad.aligned = 0; + ad.a.aligned = 0; } } return 0; diff --git a/x86_64-gen.c b/x86_64-gen.c index 9aee875..9acca3c 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -933,7 +933,8 @@ typedef enum X86_64_Mode { x86_64_mode_x87 } X86_64_Mode; -static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) { +static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) +{ if (a == b) return a; else if (a == x86_64_mode_none) @@ -950,7 +951,8 @@ static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) { return x86_64_mode_sse; } -static X86_64_Mode classify_x86_64_inner(CType *ty) { +static X86_64_Mode classify_x86_64_inner(CType *ty) +{ X86_64_Mode mode; Sym *f; @@ -988,7 +990,8 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) { assert(0); } -static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) { +static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) +{ X86_64_Mode mode; int size, align, ret_t = 0; @@ -1045,7 +1048,8 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p return mode; } -ST_FUNC int classify_x86_64_va_arg(CType *ty) { +ST_FUNC int classify_x86_64_va_arg(CType *ty) +{ /* This definition must be synced with stdarg.h */ enum __va_arg_type { __va_gen_reg, __va_float_reg, __va_stack @@ -1061,7 +1065,8 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) { /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -int gfunc_sret(CType *vt, CType *ret, int *ret_align) { +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) +{ int size, align, reg_count; *ret_align = 1; // Never have to re-align return values for x86-64 return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) != x86_64_mode_memory); -- cgit v1.3.1 From b6247d1f3c34e93e8603fddf5fc6da8dc6b81d00 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 7 Jan 2014 15:23:54 +0800 Subject: Add support for runtime selection of float ABI --- Changelog | 1 + arm-gen.c | 131 ++++++++++++++++++++++++++++++++--------------------------- libtcc.c | 23 ++++++++++- tcc-doc.texi | 3 ++ tcc.c | 2 +- tcc.h | 21 +++++++--- tccelf.c | 2 +- 7 files changed, 113 insertions(+), 70 deletions(-) (limited to 'tcc.h') diff --git a/Changelog b/Changelog index 52f8a10..9a497cf 100644 --- a/Changelog +++ b/Changelog @@ -18,6 +18,7 @@ Features: - improved variable length array support (James Lyon) - add the possibility to use noname functions by ordinal (YX Hao) - add a install-strip target to install tcc (Thomas Preud'homme) +- add runtime selection of float ABI on ARM (Thomas Preud'homme) Platforms: - support Debian GNU/kfreeBSD 64bit userspace (Thomas Preud'homme) diff --git a/arm-gen.c b/arm-gen.c index 05bccb0..bc24f70 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -141,6 +141,13 @@ enum { #define ELF_START_ADDR 0x00008000 #define ELF_PAGE_SIZE 0x1000 +enum float_abi { + ARM_SOFTFP_FLOAT, + ARM_HARD_FLOAT, +}; + +enum float_abi float_abi; + /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ /******************************************************/ @@ -169,7 +176,7 @@ static int leaffunc; #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) static CType float_type, double_type, func_float_type, func_double_type; -ST_FUNC void arm_init_types(void) +ST_FUNC void arm_init(struct TCCState *s) { float_type.t = VT_FLOAT; double_type.t = VT_DOUBLE; @@ -177,12 +184,14 @@ ST_FUNC void arm_init_types(void) func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); func_double_type.t = VT_FUNC; func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); + + float_abi = s->float_abi; } #else #define func_float_type func_old_type #define func_double_type func_old_type #define func_ldouble_type func_old_type -ST_FUNC void arm_init_types(void) {} +ST_FUNC void arm_init(void) {} #endif static int two2mask(int a,int b) { @@ -195,6 +204,16 @@ static int regmask(int r) { /******************************************************/ +#ifdef TCC_ARM_EABI +char *default_elfinterp(struct TCCState *s) +{ + if (s->float_abi == ARM_HARD_FLOAT) + return "/lib/ld-linux-armhf.so.3"; + else + return "/lib/ld-linux.so.3"; +} +#endif + void o(uint32_t i) { /* this is a good place to start adding big-endian support*/ @@ -841,22 +860,19 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { #ifdef TCC_ARM_EABI int size, align; size = type_size(vt, &align); -#ifdef TCC_ARM_HARDFLOAT - if (!variadic && (is_float(vt->t) || is_hgen_float_aggr(vt))) { + if (float_abi == ARM_HARD_FLOAT && !variadic && + (is_float(vt->t) || is_hgen_float_aggr(vt))) { *ret_align = 8; ret->ref = NULL; ret->t = VT_DOUBLE; return (size + 7) >> 3; - } else -#endif - if (size > 4) { - return 0; - } else { + } else if (size <= 4) { *ret_align = 4; ret->ref = NULL; ret->t = VT_INT; return 1; - } + } else + return 0; #else return 0; #endif @@ -1171,9 +1187,11 @@ void gfunc_call(int nb_args) int todo; struct plan plan; -#ifdef TCC_ARM_HARDFLOAT - variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); - corefloat = variadic || floats_in_core_regs(&vtop[-nb_args]); +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT) { + variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); + corefloat = variadic || floats_in_core_regs(&vtop[-nb_args]); + } #endif /* cannot let cpu flags if other instruction are generated. Also avoid leaving VT_JMP anywhere except on the top of the stack because it would complicate @@ -1199,9 +1217,9 @@ void gfunc_call(int nb_args) gcall_or_jmp(0); if (args_size) gadd_sp(args_size); /* pop all parameters passed on the stack */ -#ifdef TCC_ARM_EABI -#ifdef TCC_ARM_VFP - if(corefloat && is_float(vtop->type.ref->type.t)) { +#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) + if(float_abi == ARM_SOFTFP_FLOAT && corefloat && + is_float(vtop->type.ref->type.t)) { if((vtop->type.ref->type.t & VT_BTYPE) == VT_FLOAT) { o(0xEE000A10); /*vmov s0, r0 */ } else { @@ -1209,7 +1227,6 @@ void gfunc_call(int nb_args) o(0xEE201B10); /* vmov.32 d0[1], r1 */ } } -#endif #endif vtop -= nb_args + 1; /* Pop all params and fct address from value stack */ leaffunc = 0; /* we are calling a function, so we aren't in a leaf function */ @@ -1220,9 +1237,8 @@ void gfunc_prolog(CType *func_type) { Sym *sym,*sym2; int n, nf, size, align, struct_ret = 0; -#ifdef TCC_ARM_HARDFLOAT + int addr, pn, sn; /* pn=core, sn=stack */ struct avail_regs avregs = AVAIL_REGS_INITIALIZER; -#endif CType ret_type; sym = func_type->ref; @@ -1237,11 +1253,11 @@ void gfunc_prolog(CType *func_type) struct_ret = 1; func_vc = 12; /* Offset from fp of the place to store the result */ } - for(sym2=sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) { + for(sym2 = sym->next; sym2 && (n < 4 || nf < 16); sym2 = sym2->next) { size = type_size(&sym2->type, &align); -#ifdef TCC_ARM_HARDFLOAT - if (!func_var && (is_float(sym2->type.t) - || is_hgen_float_aggr(&sym2->type))) { +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT && !func_var && + (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { int tmpnf = assign_vfpreg(&avregs, align, size); tmpnf += (size + 3) / 4; nf = (tmpnf > nf) ? tmpnf : nf; @@ -1270,50 +1286,49 @@ void gfunc_prolog(CType *func_type) o(0xE92D5800); /* save fp, ip, lr */ o(0xE1A0B00D); /* mov fp, sp */ func_sub_sp_offset = ind; - o(0xE1A00000); /* nop, leave space for stack adjustment in epilogue */ - { - int addr, pn = struct_ret, sn = 0; /* pn=core, sn=stack */ + o(0xE1A00000); /* nop, leave space for stack adjustment in epilog */ -#ifdef TCC_ARM_HARDFLOAT +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT) { func_vc += nf * 4; avregs = AVAIL_REGS_INITIALIZER; + } #endif - while ((sym = sym->next)) { - CType *type; - type = &sym->type; - size = type_size(type, &align); - size = (size + 3) >> 2; - align = (align + 3) & ~3; -#ifdef TCC_ARM_HARDFLOAT - if (!func_var && (is_float(sym->type.t) - || is_hgen_float_aggr(&sym->type))) { - int fpn = assign_vfpreg(&avregs, align, size << 2); - if (fpn >= 0) { - addr = fpn * 4; - } else - goto from_stack; - } else + pn = struct_ret, sn = 0; + while ((sym = sym->next)) { + CType *type; + type = &sym->type; + size = type_size(type, &align); + size = (size + 3) >> 2; + align = (align + 3) & ~3; +#ifdef TCC_ARM_EABI + if (float_abi == ARM_HARD_FLOAT && !func_var && (is_float(sym->type.t) + || is_hgen_float_aggr(&sym->type))) { + int fpn = assign_vfpreg(&avregs, align, size << 2); + if (fpn >= 0) + addr = fpn * 4; + else + goto from_stack; + } else #endif - if (pn < 4) { + if (pn < 4) { #ifdef TCC_ARM_EABI pn = (pn + (align-1)/4) & -(align/4); #endif - addr = (nf + pn) * 4; - pn += size; - if (!sn && pn > 4) - sn = (pn - 4); - } else { -#ifdef TCC_ARM_HARDFLOAT + addr = (nf + pn) * 4; + pn += size; + if (!sn && pn > 4) + sn = (pn - 4); + } else { from_stack: -#endif #ifdef TCC_ARM_EABI sn = (sn + (align-1)/4) & -(align/4); #endif - addr = (n + nf + sn) * 4; - sn += size; - } - sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), addr+12); + addr = (n + nf + sn) * 4; + sn += size; } + sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), + addr + 12); } last_itod_magic=0; leaffunc = 1; @@ -1327,12 +1342,8 @@ void gfunc_epilog(void) int diff; /* Copy float return value to core register if base standard is used and float computation is made with VFP */ -#ifdef TCC_ARM_EABI - if ( -#ifdef TCC_ARM_HARDFLOAT - func_var && -#endif - is_float(func_vt.t)) { +#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP) + if ((float_abi == ARM_SOFTFP_FLOAT || func_var) && is_float(func_vt.t)) { if((func_vt.t & VT_BTYPE) == VT_FLOAT) o(0xEE100A10); /* fmrs r0, s0 */ else { diff --git a/libtcc.c b/libtcc.c index 154a266..127806f 100644 --- a/libtcc.c +++ b/libtcc.c @@ -757,7 +757,7 @@ static int tcc_compile(TCCState *s1) func_old_type.t = VT_FUNC; func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); #ifdef TCC_TARGET_ARM - arm_init_types(); + arm_init(s1); #endif #if 0 @@ -945,9 +945,12 @@ LIBTCCAPI TCCState *tcc_new(void) tcc_define_symbol(s, "__ARMEL__", NULL); #if defined(TCC_ARM_EABI) tcc_define_symbol(s, "__ARM_EABI__", NULL); +#endif #if defined(TCC_ARM_HARDFLOAT) + s->float_abi = ARM_HARD_FLOAT; tcc_define_symbol(s, "__ARM_PCS_VFP", NULL); -#endif +#else + s->float_abi = ARM_SOFTFP_FLOAT; #endif #endif @@ -1628,6 +1631,7 @@ enum { TCC_OPTION_b, TCC_OPTION_g, TCC_OPTION_c, + TCC_OPTION_float_abi, TCC_OPTION_static, TCC_OPTION_shared, TCC_OPTION_soname, @@ -1680,6 +1684,9 @@ static const TCCOption tcc_options[] = { #endif { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "c", TCC_OPTION_c, 0 }, +#ifdef TCC_TARGET_ARM + { "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG }, +#endif { "static", TCC_OPTION_static, 0 }, { "shared", TCC_OPTION_shared, 0 }, { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG }, @@ -1817,6 +1824,18 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) case TCC_OPTION_c: s->output_type = TCC_OUTPUT_OBJ; break; +#ifdef TCC_TARGET_ARM + case TCC_OPTION_float_abi: + /* tcc doesn't support soft float yet */ + if (!strcmp(optarg, "softfp")) { + s->float_abi = ARM_SOFTFP_FLOAT; + tcc_undefine_symbol(s, "__ARM_PCS_VFP"); + } else if (!strcmp(optarg, "hard")) + s->float_abi = ARM_HARD_FLOAT; + else + tcc_error("unsupported float abi '%s'", optarg); + break; +#endif case TCC_OPTION_static: s->static_link = 1; break; diff --git a/tcc-doc.texi b/tcc-doc.texi index 540b4b6..e8832f6 100644 --- a/tcc-doc.texi +++ b/tcc-doc.texi @@ -176,6 +176,9 @@ In a script, it gives the following header: #!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11 @end example +@item -mfloat-abi (ARM only) +Select the float ABI. Possible values: @code{softfp} and @code{hard} + @item -dumpversion Print only the compiler version and nothing else. diff --git a/tcc.c b/tcc.c index 58f9007..9b5ca2e 100644 --- a/tcc.c +++ b/tcc.c @@ -224,7 +224,7 @@ static void display_info(TCCState *s, int what) print_paths("crt", s->crt_paths, s->nb_crt_paths); print_paths("libraries", s->library_paths, s->nb_library_paths); print_paths("include", s->sysinclude_paths, s->nb_sysinclude_paths); - printf("elfinterp:\n %s\n", CONFIG_TCC_ELFINTERP); + printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); break; } } diff --git a/tcc.h b/tcc.h index f3d868f..73285ae 100644 --- a/tcc.h +++ b/tcc.h @@ -221,21 +221,24 @@ # endif # elif defined __GNU__ # define CONFIG_TCC_ELFINTERP "/lib/ld.so" -# elif defined TCC_ARM_HARDFLOAT -# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-armhf.so.3" -# elif defined TCC_ARM_EABI -# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.3" # elif defined(TCC_TARGET_X86_64) # define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2" # elif defined(TCC_UCLIBC) # define CONFIG_TCC_ELFINTERP "/lib/ld-uClibc.so.0" # elif defined(TCC_TARGET_PE) # define CONFIG_TCC_ELFINTERP "-" -# else +# elif !defined(TCC_ARM_EABI) # define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2" # endif #endif +/* var elf_interp dans *-gen.c */ +#ifdef CONFIG_TCC_ELFINTERP +# define DEFAULT_ELFINTERP(s) CONFIG_TCC_ELFINTERP +#else +# define DEFAULT_ELFINTERP(s) default_elfinterp(s) +#endif + /* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */ #define TCC_LIBGCC USE_MUADIR(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1" @@ -561,6 +564,9 @@ struct TCCState { /* compile with built-in memory and bounds checker */ int do_bounds_check; #endif +#ifdef TCC_TARGET_ARM + enum float_abi float_abi; /* float ABI of the generated code*/ +#endif addr_t text_addr; /* address of text section */ int has_text_addr; @@ -1329,7 +1335,10 @@ ST_FUNC void gen_opl(int op); /* ------------ arm-gen.c ------------ */ #ifdef TCC_TARGET_ARM -ST_FUNC void arm_init_types(void); +#ifdef TCC_ARM_EABI +ST_FUNC char *default_elfinterp(struct TCCState *s); +#endif +ST_FUNC void arm_init(struct TCCState *s); ST_FUNC uint32_t encbranch(int pos, int addr, int fail); ST_FUNC void gen_cvt_itof1(int t); #endif diff --git a/tccelf.c b/tccelf.c index aa3daac..43a8086 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1592,7 +1592,7 @@ static int elf_output_file(TCCState *s1, const char *filename) /* allow override the dynamic loader */ const char *elfint = getenv("LD_SO"); if (elfint == NULL) - elfint = CONFIG_TCC_ELFINTERP; + elfint = DEFAULT_ELFINTERP(s1); /* add interpreter section only if executable */ interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC); interp->sh_addralign = 1; -- cgit v1.3.1 From b0b5165d1668373c5d7b7933da599426f33e723b Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Thu, 6 Feb 2014 20:51:47 +0800 Subject: Def signedness != signed != unsigned for char When checking for exact compatibility between types (such as in __builtin_types_compatible_p) consider the case of default signedness to be incompatible with both of the explicit signedness for char. That is, char is incompatible with signed char *and* unsigned char, no matter what the default signedness for char is. --- Changelog | 1 + tcc-doc.texi | 2 +- tcc.h | 2 +- tccgen.c | 36 +++++++++++++++++++++++------------- 4 files changed, 26 insertions(+), 15 deletions(-) (limited to 'tcc.h') diff --git a/Changelog b/Changelog index b7ddd42..af206e3 100644 --- a/Changelog +++ b/Changelog @@ -68,6 +68,7 @@ Bug fixes: - fix integer to double conversion on ARM (Thomas Preud'homme) - fix parameter passing of (unsigned) long long bitfield (Thomas Preud'homme) - fix relocation of Thumb branch to ARM function (Thomas Preud'homme) +- fix char wrong compatibility with [un]signed char (Thomas Preud'homme) version 0.9.26: diff --git a/tcc-doc.texi b/tcc-doc.texi index e8832f6..3a1c7df 100644 --- a/tcc-doc.texi +++ b/tcc-doc.texi @@ -970,7 +970,7 @@ be the best solution. #define VT_BITFIELD 0x0040 /* bitfield modifier */ #define VT_CONSTANT 0x0800 /* const modifier */ #define VT_VOLATILE 0x1000 /* volatile modifier */ -#define VT_SIGNED 0x2000 /* signed type */ +#define VT_DEFSIGN 0x2000 /* signed type */ #define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */ @end example diff --git a/tcc.h b/tcc.h index 73285ae..476cdf7 100644 --- a/tcc.h +++ b/tcc.h @@ -745,7 +745,7 @@ struct TCCState { #define VT_BITFIELD 0x0040 /* bitfield modifier */ #define VT_CONSTANT 0x0800 /* const modifier */ #define VT_VOLATILE 0x1000 /* volatile modifier */ -#define VT_SIGNED 0x2000 /* signed type */ +#define VT_DEFSIGN 0x2000 /* signed type */ #define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */ /* storage */ diff --git a/tccgen.c b/tccgen.c index 03a446a..2f5b366 100644 --- a/tccgen.c +++ b/tccgen.c @@ -949,7 +949,7 @@ static void lexpand(void) { int u; - u = vtop->type.t & VT_UNSIGNED; + u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED); gv(RC_INT); vdup(); vtop[0].r = vtop[-1].r2; @@ -965,7 +965,7 @@ ST_FUNC void lexpand_nr(void) { int u,v; - u = vtop->type.t & VT_UNSIGNED; + u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED); vdup(); vtop->r2 = VT_CONST; vtop->type.t = VT_INT | u; @@ -1621,8 +1621,8 @@ static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op) return; tmp_type1 = *type1; tmp_type2 = *type2; - tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); - tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); + tmp_type1.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); + tmp_type2.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); if (!is_compatible_types(&tmp_type1, &tmp_type2)) { /* gcc-like error if '-' is used */ if (op == '-') @@ -2212,6 +2212,11 @@ static int compare_types(CType *type1, CType *type2, int unqualified) t1 &= ~(VT_CONSTANT | VT_VOLATILE); t2 &= ~(VT_CONSTANT | VT_VOLATILE); } + /* Default Vs explicit signedness only matters for char */ + if ((t1 & VT_BTYPE) != VT_BYTE) { + t1 &= ~VT_DEFSIGN; + t2 &= ~VT_DEFSIGN; + } /* XXX: bitfields ? */ if (t1 != t2) return 0; @@ -2264,8 +2269,10 @@ static void type_to_str(char *buf, int buf_size, pstrcat(buf, buf_size, "const "); if (t & VT_VOLATILE) pstrcat(buf, buf_size, "volatile "); - if (t & VT_UNSIGNED) + if (t & (VT_DEFSIGN | VT_UNSIGNED)) pstrcat(buf, buf_size, "unsigned "); + else if (t & VT_DEFSIGN) + pstrcat(buf, buf_size, "signed "); switch(bt) { case VT_VOID: tstr = "void"; @@ -2385,8 +2392,10 @@ static void gen_assign_cast(CType *dt) /* exact type match, except for unsigned */ tmp_type1 = *type1; tmp_type2 = *type2; - tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); - tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE); + tmp_type1.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | + VT_VOLATILE); + tmp_type2.t &= ~(VT_DEFSIGN | VT_UNSIGNED | VT_CONSTANT | + VT_VOLATILE); if (!is_compatible_types(&tmp_type1, &tmp_type2)) tcc_warning("assignment from incompatible pointer type"); } @@ -3081,8 +3090,10 @@ static int parse_btype(CType *type, AttributeDef *ad) case TOK_SIGNED1: case TOK_SIGNED2: case TOK_SIGNED3: + if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == (VT_DEFSIGN|VT_UNSIGNED)) + tcc_error("signed and unsigned modifier"); typespec_found = 1; - t |= VT_SIGNED; + t |= VT_DEFSIGN; next(); break; case TOK_REGISTER: @@ -3093,7 +3104,9 @@ static int parse_btype(CType *type, AttributeDef *ad) next(); break; case TOK_UNSIGNED: - t |= VT_UNSIGNED; + if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == VT_DEFSIGN) + tcc_error("signed and unsigned modifier"); + t |= VT_DEFSIGN | VT_UNSIGNED; next(); typespec_found = 1; break; @@ -3160,13 +3173,10 @@ static int parse_btype(CType *type, AttributeDef *ad) type_found = 1; } the_end: - if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED)) - tcc_error("signed and unsigned modifier"); if (tcc_state->char_is_unsigned) { - if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE) + if ((t & (VT_DEFSIGN|VT_BTYPE)) == VT_BYTE) t |= VT_UNSIGNED; } - t &= ~VT_SIGNED; /* long is never used as type */ if ((t & VT_BTYPE) == VT_LONG) -- cgit v1.3.1 From aa561d70119accb59a17f10f9ba69076fb0ab516 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Wed, 26 Mar 2014 22:13:20 +0800 Subject: Simplify and fix GOT32 + PLT32 reloc commit Introduce a new attribute to check the existence of a PLT entry for a given symbol has the presence of an entry for that symbol in the dynsym section is not proof that a PLT entry exists. This fixes commit dc8ea93b13faefb565fb937f8b8c08c40c063549. --- tcc.h | 1 + tccelf.c | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 476cdf7..e83e6c0 100644 --- a/tcc.h +++ b/tcc.h @@ -522,6 +522,7 @@ typedef struct ASMOperand { struct sym_attr { unsigned long got_offset; + unsigned char has_plt_entry:1; #ifdef TCC_TARGET_ARM unsigned char plt_thumb_stub:1; #endif diff --git a/tccelf.c b/tccelf.c index 6bde7d5..217c917 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1042,10 +1042,9 @@ static void put_got_entry(TCCState *s1, if (s1->dynsym) { sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; name = (char *) symtab_section->link->data + sym->st_name; - if (!find_elf_sym(s1->dynsym, name)) - need_plt_entry = 1; - else + if (s1->sym_attrs[sym_index].has_plt_entry) return; + s1->sym_attrs[sym_index].has_plt_entry = 1; offset = sym->st_value; #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) if (need_plt_entry) { -- cgit v1.3.1 From 0ac8aaab1bef770929e5592d02bc06d3a529952e Mon Sep 17 00:00:00 2001 From: grischka Date: Sat, 29 Mar 2014 16:40:54 +0100 Subject: tccpp: reorder some tokens ... and make future reordering possibly easier related to 9a6ee577f6165dccfde424732bfc6f16f1e2811b --- tcc.h | 33 ++++++++++++++++++--------------- tccpp.c | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 21 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index e83e6c0..f89b146 100644 --- a/tcc.h +++ b/tcc.h @@ -783,35 +783,38 @@ struct TCCState { #define TOK_LAND 0xa0 #define TOK_LOR 0xa1 - #define TOK_DEC 0xa2 #define TOK_MID 0xa3 /* inc/dec, to void constant */ #define TOK_INC 0xa4 #define TOK_UDIV 0xb0 /* unsigned division */ #define TOK_UMOD 0xb1 /* unsigned modulo */ #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */ -#define TOK_CINT 0xb3 /* number in tokc */ -#define TOK_CCHAR 0xb4 /* char constant in tokc */ -#define TOK_STR 0xb5 /* pointer to string in tokc */ -#define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */ -#define TOK_LCHAR 0xb7 -#define TOK_LSTR 0xb8 -#define TOK_CFLOAT 0xb9 /* float constant */ -#define TOK_LINENUM 0xba /* line number info */ -#define TOK_CDOUBLE 0xc0 /* double constant */ -#define TOK_CLDOUBLE 0xc1 /* long double constant */ + +/* tokens that carry values (in additional token string space / tokc) --> */ +#define TOK_CCHAR 0xb3 /* char constant in tokc */ +#define TOK_LCHAR 0xb4 +#define TOK_CINT 0xb5 /* number in tokc */ +#define TOK_CUINT 0xb6 /* unsigned int constant */ +#define TOK_CLLONG 0xb7 /* long long constant */ +#define TOK_CULLONG 0xb8 /* unsigned long long constant */ +#define TOK_STR 0xb9 /* pointer to string in tokc */ +#define TOK_LSTR 0xba +#define TOK_CFLOAT 0xbb /* float constant */ +#define TOK_CDOUBLE 0xbc /* double constant */ +#define TOK_CLDOUBLE 0xbd /* long double constant */ +#define TOK_PPNUM 0xbe /* preprocessor number */ +#define TOK_LINENUM 0xbf /* line number info */ +/* <-- */ + +#define TOK_TWOSHARPS 0xc0 /* ## preprocessing token */ #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */ #define TOK_ADDC1 0xc3 /* add with carry generation */ #define TOK_ADDC2 0xc4 /* add with carry use */ #define TOK_SUBC1 0xc5 /* add with carry generation */ #define TOK_SUBC2 0xc6 /* add with carry use */ -#define TOK_CUINT 0xc8 /* unsigned int constant */ -#define TOK_CLLONG 0xc9 /* long long constant */ -#define TOK_CULLONG 0xca /* unsigned long long constant */ #define TOK_ARROW 0xcb #define TOK_DOTS 0xcc /* three dots */ #define TOK_SHR 0xcd /* unsigned shift right */ -#define TOK_PPNUM 0xce /* preprocessor number */ #define TOK_NOSUBST 0xcf /* means following token has already been pp'd */ #define TOK_SHL 0x01 /* shift left */ diff --git a/tccpp.c b/tccpp.c index f4b7b1a..b2e389b 100644 --- a/tccpp.c +++ b/tccpp.c @@ -70,8 +70,33 @@ static const char tcc_keywords[] = /* WARNING: the content of this string encodes token numbers */ static const unsigned char tok_two_chars[] = +/* outdated -- gr "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253" "-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266"; +*/{ + '<','=', TOK_LE, + '>','=', TOK_GE, + '!','=', TOK_NE, + '&','&', TOK_LAND, + '|','|', TOK_LOR, + '+','+', TOK_INC, + '-','-', TOK_DEC, + '=','=', TOK_EQ, + '<','<', TOK_SHL, + '>','>', TOK_SHR, + '+','=', TOK_A_ADD, + '-','=', TOK_A_SUB, + '*','=', TOK_A_MUL, + '/','=', TOK_A_DIV, + '%','=', TOK_A_MOD, + '&','=', TOK_A_AND, + '^','=', TOK_A_XOR, + '|','=', TOK_A_OR, + '-','>', TOK_ARROW, + '.','.', 0xa8, // C++ token ? + '#','#', TOK_TWOSHARPS, + 0 +}; struct macro_level { struct macro_level *prev; @@ -255,21 +280,19 @@ ST_FUNC char *get_tok_str(int v, CValue *cv) static char buf[STRING_MAX_SIZE + 1]; static CString cstr_buf; CString *cstr; - CValue cval; char *p; int i, len; - if (!cv) { - cval.ull = 0; - cv = &cval; - } - /* NOTE: to go faster, we give a fixed buffer for small strings */ cstr_reset(&cstr_buf); cstr_buf.data = buf; cstr_buf.size_allocated = sizeof(buf); p = buf; +/* just an explanation, should never happen: + if (v <= TOK_LINENUM && v >= TOK_CINT && cv == NULL) + tcc_error("internal error: get_tok_str"); */ + switch(v) { case TOK_CINT: case TOK_CUINT: @@ -317,6 +340,15 @@ ST_FUNC char *get_tok_str(int v, CValue *cv) cstr_ccat(&cstr_buf, '\"'); cstr_ccat(&cstr_buf, '\0'); break; + + case TOK_CFLOAT: + case TOK_CDOUBLE: + case TOK_CLDOUBLE: + case TOK_LINENUM: + return NULL; /* should not happen */ + + /* above tokens have value, the ones below don't */ + case TOK_LT: v = '<'; goto addv; -- cgit v1.3.1 From 5a5fee867a2427b35bf6acec3e176e768cb5b7d2 Mon Sep 17 00:00:00 2001 From: mingodad Date: Sun, 30 Mar 2014 10:10:24 +0100 Subject: Add __attribute__ ((noreturn)) to tcc_error and expect functions. This make use of static analysis tools like scan-build report less false positives. --- tcc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index f89b146..5ab50d6 100644 --- a/tcc.h +++ b/tcc.h @@ -1045,7 +1045,7 @@ PUB_FUNC char *tcc_strdup(const char *str); #define strdup(s) use_tcc_strdup(s) PUB_FUNC void tcc_memstats(void); PUB_FUNC void tcc_error_noabort(const char *fmt, ...); -PUB_FUNC void tcc_error(const char *fmt, ...); +PUB_FUNC void tcc_error(const char *fmt, ...) __attribute__ ((noreturn)); PUB_FUNC void tcc_warning(const char *fmt, ...); /* other utilities */ @@ -1143,7 +1143,7 @@ ST_FUNC void preprocess_init(TCCState *s1); ST_FUNC void preprocess_new(void); ST_FUNC int tcc_preprocess(TCCState *s1); ST_FUNC void skip(int c); -ST_FUNC void expect(const char *msg); +ST_FUNC void expect(const char *msg) __attribute__ ((noreturn)); /* ------------ tccgen.c ------------ */ -- cgit v1.3.1 From 0bd128205979f59f3bbe6ee7cb98599a5088d0d0 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 31 Mar 2014 05:36:12 +0200 Subject: x86-64: shared libs improvement This correctly resolves local references to global functions from shared libs to their PLT slot (instead of directly to the target symbol), so that interposition works. This is still not 100% conforming (executables don't export symbols that are also defined in linked shared libs, as they must), but normal shared lib situations work. --- tcc.h | 2 +- tccelf.c | 70 +++++++++++++++++++++++++++++++++++++++++----------------------- 2 files changed, 46 insertions(+), 26 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 5ab50d6..f508097 100644 --- a/tcc.h +++ b/tcc.h @@ -522,7 +522,7 @@ typedef struct ASMOperand { struct sym_attr { unsigned long got_offset; - unsigned char has_plt_entry:1; + unsigned long plt_offset; #ifdef TCC_TARGET_ARM unsigned char plt_thumb_stub:1; #endif diff --git a/tccelf.c b/tccelf.c index 38d3e3e..7544d2e 100644 --- a/tccelf.c +++ b/tccelf.c @@ -841,8 +841,18 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) break; } } - /* fall through */ - case R_X86_64_PLT32: { + goto plt32pc32; + + case R_X86_64_PLT32: + /* We've put the PLT slot offset into r_addend when generating + it, and that's what we must use as relocation value (adjusted + by section offset of course). */ + if (s1->output_type != TCC_OUTPUT_MEMORY) + val = s1->plt->sh_addr + rel->r_addend; + /* fallthrough. */ + + plt32pc32: + { long long diff; diff = (long long)val - addr; if (diff <= -2147483647 || diff > 2147483647) { @@ -1011,13 +1021,14 @@ static void build_got(TCCState *s1) #endif } -/* put a got entry corresponding to a symbol in symtab_section. 'size' - and 'info' can be modifed if more precise info comes from the DLL */ -static void put_got_entry(TCCState *s1, - int reloc_type, unsigned long size, int info, - int sym_index) +/* put a got or plt entry corresponding to a symbol in symtab_section. 'size' + and 'info' can be modifed if more precise info comes from the DLL. + Returns offset of GOT or PLT slot. */ +static unsigned long put_got_entry(TCCState *s1, + int reloc_type, unsigned long size, int info, + int sym_index) { - int index, need_plt_entry, got_entry_present = 0; + int index, need_plt_entry; const char *name; ElfW(Sym) *sym; unsigned long offset; @@ -1038,16 +1049,16 @@ static void put_got_entry(TCCState *s1, 0; #endif - /* if a got entry already exists for that symbol, no need to add one */ - if (sym_index < s1->nb_sym_attrs && - s1->sym_attrs[sym_index].got_offset) { - if (!need_plt_entry || s1->sym_attrs[sym_index].has_plt_entry) - return; - else - got_entry_present = 1; + /* If a got/plt entry already exists for that symbol, no need to add one */ + if (sym_index < s1->nb_sym_attrs) { + if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset) + return s1->sym_attrs[sym_index].plt_offset; + else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset) + return s1->sym_attrs[sym_index].got_offset; } symattr = alloc_sym_attr(s1, sym_index); + /* Only store the GOT offset if it's not generated for the PLT entry. */ if (!need_plt_entry) symattr->got_offset = s1->got->data_offset; @@ -1090,6 +1101,7 @@ static void put_got_entry(TCCState *s1, via offset. The reloc entry is created below, so its offset is the current data_offset. */ relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; + symattr->plt_offset = plt->data_offset; p = section_ptr_add(plt, 16); p[0] = 0xff; /* jmp *(got + x) */ p[1] = modrm; @@ -1104,13 +1116,11 @@ static void put_got_entry(TCCState *s1, p[11] = 0xe9; /* jmp plt_start */ put32(p + 12, -(plt->data_offset)); - /* the symbol is modified so that it will be relocated to - the PLT */ -#if !defined(TCC_OUTPUT_DLL_WITH_PLT) - if (s1->output_type == TCC_OUTPUT_EXE) -#endif - offset = plt->data_offset - 16; - symattr->has_plt_entry = 1; + /* If this was an UNDEF symbol set the offset in the + dynsymtab to the PLT slot, so that PC32 relocs to it + can be resolved. */ + if (sym->st_shndx == SHN_UNDEF) + offset = plt->data_offset - 16; } #elif defined(TCC_TARGET_ARM) if (need_plt_entry) { @@ -1132,6 +1142,7 @@ static void put_got_entry(TCCState *s1, put32(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */ } + symattr->plt_offset = plt->data_offset; if (symattr->plt_thumb_stub) { p = section_ptr_add(plt, 20); put32(p, 0x4778); /* bx pc */ @@ -1148,7 +1159,6 @@ static void put_got_entry(TCCState *s1, the PLT */ if (s1->output_type == TCC_OUTPUT_EXE) offset = plt->data_offset - 16; - symattr->has_plt_entry = 1; } #elif defined(TCC_TARGET_C67) tcc_error("C67 got not implemented"); @@ -1167,6 +1177,10 @@ static void put_got_entry(TCCState *s1, /* And now create the GOT slot itself. */ ptr = section_ptr_add(s1->got, PTR_SIZE); *ptr = 0; + if (need_plt_entry) + return symattr->plt_offset; + else + return symattr->got_offset; } /* build GOT and PLT entries */ @@ -1281,6 +1295,7 @@ ST_FUNC void build_got_entries(TCCState *s1) build_got(s1); if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL || type == R_X86_64_PLT32) { + unsigned long ofs; sym_index = ELFW(R_SYM)(rel->r_info); sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; /* look at the symbol got offset. If none, then add one */ @@ -1288,8 +1303,13 @@ ST_FUNC void build_got_entries(TCCState *s1) reloc_type = R_X86_64_GLOB_DAT; else reloc_type = R_X86_64_JUMP_SLOT; - put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, - sym_index); + ofs = put_got_entry(s1, reloc_type, sym->st_size, + sym->st_info, sym_index); + if (type == R_X86_64_PLT32 + && s1->output_type != TCC_OUTPUT_MEMORY) + /* We store the place of the generated PLT slot + in our addend. */ + rel->r_addend += ofs; } break; #else -- cgit v1.3.1 From 5879c854fb94f722a7ffdd4e895c9ce418548959 Mon Sep 17 00:00:00 2001 From: grischka Date: Fri, 4 Apr 2014 20:18:39 +0200 Subject: tccgen: x86_64: fix garbage in the SValue upper bits This was going wrong (case TOK_LAND in unary: computed labels) - vset(&s->type, VT_CONST | VT_SYM, 0); - vtop->sym = s; This does the right thing and is shorter: + vpushsym(&s->type, s); Test case was: int main(int argc, char **argv) { int x; static void *label_return = &&lbl_return; printf("label_return = %p\n", label_return); goto *label_return; //<<<<< here segfault on linux X86_64 without the memset on vset printf("unreachable\n"); lbl_return: return 0; } Also:: - Rename "void* CValue.ptr" to more usable "addr_t ptr_offset" and start to use it in obvious cases. - use __attribute__ ((noreturn)) only with gnu compiler - Revert CValue memsets ("After several days searching ...") commit 4bc83ac3933efa565ae3326b55fcd711b63c073d Doesn't mean that the vsetX/vpush thingy isn't brittle and there still might be bugs as to differences in how the CValue union was set and is then interpreted later on. However the big memset hammer was just too slow (-3% overall). --- tcc.h | 76 +++++++++++++++++++++++++++++++++------------------------------- tccgen.c | 30 ++++++++----------------- tccpp.c | 16 ++++---------- 3 files changed, 52 insertions(+), 70 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index f508097..093e758 100644 --- a/tcc.h +++ b/tcc.h @@ -55,18 +55,27 @@ # ifndef CONFIG_TCC_STATIC # include # endif -#else +/* XXX: need to define this to use them in non ISOC99 context */ + extern float strtof (const char *__nptr, char **__endptr); + extern long double strtold (const char *__nptr, char **__endptr); +#else /* on _WIN32: */ # include # include # include /* open, close etc. */ # include /* getcwd */ # ifdef __GNUC__ # include -# else - typedef UINT_PTR uintptr_t; # endif # define inline __inline # define inp next_inp +# define snprintf _snprintf +# define vsnprintf _vsnprintf +# ifndef __GNUC__ +# define strtold (long double)strtod +# define strtof (float)strtod +# define strtoll _strtoi64 +# define strtoull _strtoui64 +# endif # ifdef LIBTCC_AS_DLL # define LIBTCCAPI __declspec(dllexport) # define PUB_FUNC LIBTCCAPI @@ -79,6 +88,30 @@ # define O_BINARY 0 #endif +#ifdef __GNUC__ +# define NORETURN __attribute__ ((noreturn)) +#elif defined _MSC_VER +# define NORETURN __declspec(noreturn) +#else +# define NORETURN +#endif + +#ifdef _WIN32 +# define IS_DIRSEP(c) (c == '/' || c == '\\') +# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) +# define PATHCMP stricmp +#else +# define IS_DIRSEP(c) (c == '/') +# define IS_ABSPATH(p) IS_DIRSEP(p[0]) +# define PATHCMP strcmp +#endif + +#ifdef TCC_TARGET_PE +#define PATHSEP ';' +#else +#define PATHSEP ':' +#endif + #include "elf.h" #ifdef TCC_TARGET_X86_64 # define ELFCLASSW ELFCLASS64 @@ -315,7 +348,7 @@ typedef union CValue { long long ll; unsigned long long ull; struct CString *cstr; - void *ptr; + addr_t ptr_offset; int tab[LDOUBLE_SIZE/4]; } CValue; @@ -938,37 +971,6 @@ enum tcc_token { #define TOK_UIDENT TOK_DEFINE -#ifdef _WIN32 -#define snprintf _snprintf -#define vsnprintf _vsnprintf -#ifndef __GNUC__ -# define strtold (long double)strtod -# define strtof (float)strtod -# define strtoll _strtoi64 -# define strtoull _strtoui64 -#endif -#else -/* XXX: need to define this to use them in non ISOC99 context */ -extern float strtof (const char *__nptr, char **__endptr); -extern long double strtold (const char *__nptr, char **__endptr); -#endif - -#ifdef _WIN32 -#define IS_DIRSEP(c) (c == '/' || c == '\\') -#define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) -#define PATHCMP stricmp -#else -#define IS_DIRSEP(c) (c == '/') -#define IS_ABSPATH(p) IS_DIRSEP(p[0]) -#define PATHCMP strcmp -#endif - -#ifdef TCC_TARGET_PE -#define PATHSEP ';' -#else -#define PATHSEP ':' -#endif - /* space exlcuding newline */ static inline int is_space(int ch) { @@ -1045,7 +1047,7 @@ PUB_FUNC char *tcc_strdup(const char *str); #define strdup(s) use_tcc_strdup(s) PUB_FUNC void tcc_memstats(void); PUB_FUNC void tcc_error_noabort(const char *fmt, ...); -PUB_FUNC void tcc_error(const char *fmt, ...) __attribute__ ((noreturn)); +PUB_FUNC NORETURN void tcc_error(const char *fmt, ...); PUB_FUNC void tcc_warning(const char *fmt, ...); /* other utilities */ @@ -1143,7 +1145,7 @@ ST_FUNC void preprocess_init(TCCState *s1); ST_FUNC void preprocess_new(void); ST_FUNC int tcc_preprocess(TCCState *s1); ST_FUNC void skip(int c); -ST_FUNC void expect(const char *msg) __attribute__ ((noreturn)); +ST_FUNC NORETURN void expect(const char *msg); /* ------------ tccgen.c ------------ */ diff --git a/tccgen.c b/tccgen.c index 84188ad..b698da9 100644 --- a/tccgen.c +++ b/tccgen.c @@ -329,7 +329,6 @@ static void vsetc(CType *type, int r, CValue *vc) void vpush(CType *type) { CValue cval; - memset(&cval, 0, sizeof(CValue)); vsetc(type, VT_CONST, &cval); } @@ -337,29 +336,23 @@ void vpush(CType *type) ST_FUNC void vpushi(int v) { CValue cval; - memset(&cval, 0, sizeof(CValue)); cval.i = v; vsetc(&int_type, VT_CONST, &cval); } /* push a pointer sized constant */ -static void vpushs(long long v) +static void vpushs(addr_t v) { CValue cval; - memset(&cval, 0, sizeof(CValue)); - if (PTR_SIZE == 4) - cval.i = (int)v; - else - cval.ull = v; + cval.ptr_offset = v; vsetc(&size_type, VT_CONST, &cval); } /* push arbitrary 64bit constant */ void vpush64(int ty, unsigned long long v) { - CType ctype; CValue cval; - memset(&cval, 0, sizeof(CValue)); + CType ctype; ctype.t = ty; ctype.ref = NULL; cval.ull = v; @@ -376,9 +369,7 @@ static inline void vpushll(long long v) static inline void vpushsym(CType *type, Sym *sym) { CValue cval; - memset(&cval, 0, sizeof(CValue)); - - cval.ull = 0; + cval.ptr_offset = 0; vsetc(type, VT_CONST | VT_SYM, &cval); vtop->sym = sym; } @@ -451,7 +442,6 @@ ST_FUNC void vpush_global_sym(CType *type, int v) ST_FUNC void vset(CType *type, int r, int v) { CValue cval; - memset(&cval, 0, sizeof(CValue)); cval.i = v; vsetc(type, r, &cval); @@ -737,7 +727,6 @@ ST_FUNC int gv(int rc) unsigned long offset; #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP) CValue check; - memset(&check, 0, sizeof(CValue)); #endif /* XXX: unify with initializers handling ? */ @@ -770,7 +759,7 @@ ST_FUNC int gv(int rc) sym = get_sym_ref(&vtop->type, data_section, offset, size << 2); vtop->r |= VT_LVAL | VT_SYM; vtop->sym = sym; - vtop->c.ull = 0; + vtop->c.ptr_offset = 0; } #ifdef CONFIG_TCC_BCHECK if (vtop->r & VT_MUSTBOUND) @@ -1581,7 +1570,7 @@ static inline int is_null_pointer(SValue *p) return 0; return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || - ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr == 0); + ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0); } static inline int is_integer_btype(int bt) @@ -3886,8 +3875,7 @@ ST_FUNC void unary(void) mk_pointer(&s->type); s->type.t |= VT_STATIC; } - vset(&s->type, VT_CONST | VT_SYM, 0); - vtop->sym = s; + vpushsym(&s->type, s); next(); break; @@ -3939,7 +3927,7 @@ ST_FUNC void unary(void) /* if forward reference, we must point to s */ if (vtop->r & VT_SYM) { vtop->sym = s; - vtop->c.ull = 0; + vtop->c.ptr_offset = 0; } break; } @@ -5157,7 +5145,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c, if (vtop->r & VT_SYM) { greloc(sec, vtop->sym, c, R_DATA_PTR); } - *(addr_t *)ptr |= (vtop->c.ull & bit_mask) << bit_pos; + *(addr_t *)ptr |= (vtop->c.ptr_offset & bit_mask) << bit_pos; break; default: if (vtop->r & VT_SYM) { diff --git a/tccpp.c b/tccpp.c index fbf109b..7144ee4 100644 --- a/tccpp.c +++ b/tccpp.c @@ -974,7 +974,6 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv) ST_FUNC void tok_str_add_tok(TokenString *s) { CValue cval; - memset(&cval, 0, sizeof(CValue)); /* save line number info */ if (file->line_num != s->last_line_num) { @@ -1038,9 +1037,8 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv) static int macro_is_equal(const int *a, const int *b) { char buf[STRING_MAX_SIZE + 1]; - int t; CValue cv; - memset(&cv, 0, sizeof(CValue)); + int t; while (*a && *b) { TOK_GET(&t, &a, &cv); pstrcpy(buf, sizeof buf, get_tok_str(t, &cv)); @@ -1199,7 +1197,6 @@ static void tok_print(int *str) { int t; CValue cval; - memset(&cval, 0, sizeof(CValue)); printf("<"); while (1) { @@ -2566,10 +2563,9 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) int last_tok, t, spc; const int *st; Sym *s; + CValue cval; TokenString str; CString cstr; - CValue cval; - memset(&cval, 0, sizeof(CValue)); tok_str_new(&str); last_tok = 0; @@ -2671,10 +2667,9 @@ static int macro_subst_tok(TokenString *tok_str, const int *p; TokenString str; char *cstrval; + CValue cval; CString cstr; char buf[32]; - CValue cval; - memset(&cval, 0, sizeof(CValue)); /* if symbol is a macro, prepare substitution */ /* special macros */ @@ -2849,7 +2844,6 @@ static inline int *macro_twosharps(const int *macro_str) /* we search the first '##' */ for(ptr = macro_str;;) { CValue cval; - memset(&cval, 0, sizeof(CValue)); TOK_GET(&t, &ptr, &cval); if (t == TOK_TWOSHARPS) break; @@ -2880,7 +2874,6 @@ static inline int *macro_twosharps(const int *macro_str) t = *++ptr; if (t && t != TOK_TWOSHARPS) { CValue cval; - memset(&cval, 0, sizeof(CValue)); TOK_GET(&t, &ptr, &cval); /* We concatenate the two tokens */ cstr_new(&cstr); @@ -2922,10 +2915,9 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, int *macro_str1; const int *ptr; int t, ret, spc; + CValue cval; struct macro_level ml; int force_blank; - CValue cval; - memset(&cval, 0, sizeof(CValue)); /* first scan for '##' operator handling */ ptr = macro_str; -- cgit v1.3.1 From 9750d0b725d65296364c08451a985c717bf1890d Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sun, 6 Apr 2014 00:30:22 +0200 Subject: x86_64: Create proper PLT and GOT also for -run This makes us use the normal PLT/GOT codepaths also for -run, which formerly used an on-the-side blob for the jump tables. For x86_64 only for now, arm coming up. --- tcc.h | 3 ++- tccelf.c | 37 +++++++++++++++++++++---------------- tccrun.c | 1 + 3 files changed, 24 insertions(+), 17 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 093e758..76f25bd 100644 --- a/tcc.h +++ b/tcc.h @@ -712,7 +712,7 @@ struct TCCState { void *write_mem; unsigned long mem_size; # endif -# if !defined TCC_TARGET_PE && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM) +# if !defined TCC_TARGET_PE && (defined TCC_TARGET_ARM) /* write PLT and GOT here */ char *runtime_plt_and_got; unsigned runtime_plt_and_got_offset; @@ -1265,6 +1265,7 @@ ST_FUNC void put_stabd(int type, int other, int desc); ST_FUNC void relocate_common_syms(void); ST_FUNC void relocate_syms(TCCState *s1, int do_resolve); ST_FUNC void relocate_section(TCCState *s1, Section *s); +ST_FUNC void relocate_plt(TCCState *s1); ST_FUNC void tcc_add_linker_symbols(TCCState *s1); ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset); diff --git a/tccelf.c b/tccelf.c index b55dbc9..4ed845b 100644 --- a/tccelf.c +++ b/tccelf.c @@ -851,8 +851,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) /* We've put the PLT slot offset into r_addend when generating it, and that's what we must use as relocation value (adjusted by section offset of course). */ - if (s1->output_type != TCC_OUTPUT_MEMORY) - val = s1->plt->sh_addr + rel->r_addend; + val = s1->plt->sh_addr + rel->r_addend; /* fallthrough. */ plt32pc32: @@ -878,7 +877,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: /* They don't need addend */ - *(int *)ptr = val - rel->r_addend; + *(addr_t *)ptr = val - rel->r_addend; break; case R_X86_64_GOTPCREL: #ifdef TCC_HAS_RUNTIME_PLTGOT @@ -1042,7 +1041,7 @@ static unsigned long put_got_entry(TCCState *s1, if (!s1->got) build_got(s1); - need_plt_entry = s1->dynsym && + need_plt_entry = #ifdef TCC_TARGET_X86_64 (reloc_type == R_X86_64_JUMP_SLOT); #elif defined(TCC_TARGET_I386) @@ -1053,6 +1052,13 @@ static unsigned long put_got_entry(TCCState *s1, 0; #endif + if (need_plt_entry && !s1->plt) { + /* add PLT */ + s1->plt = new_section(s1, ".plt", SHT_PROGBITS, + SHF_ALLOC | SHF_EXECINSTR); + s1->plt->sh_entsize = 4; + } + /* If a got/plt entry already exists for that symbol, no need to add one */ if (sym_index < s1->nb_sym_attrs) { if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset) @@ -1067,10 +1073,9 @@ static unsigned long put_got_entry(TCCState *s1, if (!need_plt_entry) symattr->got_offset = s1->got->data_offset; - if (s1->dynsym) { - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; - name = (char *) symtab_section->link->data + sym->st_name; - offset = sym->st_value; + sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; + name = (char *) symtab_section->link->data + sym->st_name; + offset = sym->st_value; #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) if (need_plt_entry) { Section *plt; @@ -1165,10 +1170,13 @@ static unsigned long put_got_entry(TCCState *s1, offset = plt->data_offset - 16; } #elif defined(TCC_TARGET_C67) + if (s1->dynsym) { tcc_error("C67 got not implemented"); + } #else #error unsupported CPU #endif + if (s1->dynsym) { /* XXX This might generate multiple syms for name. */ index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx, name); @@ -1316,8 +1324,7 @@ ST_FUNC void build_got_entries(TCCState *s1) reloc_type = R_X86_64_JUMP_SLOT; ofs = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, sym_index); - if (type == R_X86_64_PLT32 - && s1->output_type != TCC_OUTPUT_MEMORY) + if (type == R_X86_64_PLT32) /* We store the place of the generated PLT slot in our addend. */ rel->r_addend += ofs; @@ -1754,10 +1761,13 @@ static void export_global_syms(TCCState *s1) /* relocate the PLT: compute addresses and offsets in the PLT now that final address for PLT and GOT are known (see fill_program_header) */ -static void relocate_plt(TCCState *s1) +ST_FUNC void relocate_plt(TCCState *s1) { uint8_t *p, *p_end; + if (!s1->plt) + return; + p = s1->plt->data; p_end = p + s1->plt->data_offset; if (p < p_end) { @@ -2346,11 +2356,6 @@ static int elf_output_file(TCCState *s1, const char *filename) dynamic->link = dynstr; dynamic->sh_entsize = sizeof(ElfW(Dyn)); - /* add PLT */ - s1->plt = new_section(s1, ".plt", SHT_PROGBITS, - SHF_ALLOC | SHF_EXECINSTR); - s1->plt->sh_entsize = 4; - build_got(s1); if (file_type == TCC_OUTPUT_EXE) { diff --git a/tccrun.c b/tccrun.c index bd8c33f..2876ab7 100644 --- a/tccrun.c +++ b/tccrun.c @@ -197,6 +197,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr) if (s->reloc) relocate_section(s1, s); } + relocate_plt(s1); for(i = 1; i < s1->nb_sections; i++) { s = s1->sections[i]; -- cgit v1.3.1 From 01c041923474750a236da02561f0f8835445848b Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sun, 6 Apr 2014 01:02:42 +0200 Subject: arm: Use proper PLT/GOT for -run. Same as with x86_64, disable the runtime_plt_and_got hack for -run on arm as well. For that we need to handle several relocations as (potentially) generating PLT slots as well. Tested with mpfr-3.1.2 and gawk (both using --disable-shared), there are two resp. five pre-existing problems, so no regressions. This also works toward enabling real shared libs for arm, but it's not there yet. --- tcc.h | 2 +- tccelf.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 10 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 76f25bd..5033b19 100644 --- a/tcc.h +++ b/tcc.h @@ -712,7 +712,7 @@ struct TCCState { void *write_mem; unsigned long mem_size; # endif -# if !defined TCC_TARGET_PE && (defined TCC_TARGET_ARM) +# if !defined TCC_TARGET_PE && (0) /* write PLT and GOT here */ char *runtime_plt_and_got; unsigned runtime_plt_and_got_offset; diff --git a/tccelf.c b/tccelf.c index 4ed845b..6f63f83 100644 --- a/tccelf.c +++ b/tccelf.c @@ -20,6 +20,9 @@ #include "tcc.h" +/* Define this to get some debug output during relocation processing. */ +#undef DEBUG_RELOC + /* XXX: avoid static variable */ static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */ @@ -438,6 +441,9 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) addr = resolve_sym(s1, name); if (addr) { sym->st_value = (addr_t)addr; +#ifdef DEBUG_RELOC + printf ("relocate_sym: %s -> 0x%x\n", name, sym->st_value); +#endif goto found; } #endif @@ -601,6 +607,11 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) { int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko; x = (*(int *) ptr) & 0xffffff; + if (sym->st_shndx == SHN_UNDEF) + val = s1->plt->sh_addr; +#ifdef DEBUG_RELOC + printf ("reloc %d: x=0x%x val=0x%x ", type, x, val); +#endif (*(int *)ptr) &= 0xff000000; if (x & 0x800000) x -= 0x1000000; @@ -610,6 +621,10 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) is_bl = (*(unsigned *) ptr) >> 24 == 0xeb; is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl)); x += val - addr; +#ifdef DEBUG_RELOC + printf (" newx=0x%x name=%s\n", x, + (char *) symtab_section->link->data + sym->st_name); +#endif h = x & 2; th_ko = (x & 3) && (!blx_avail || !is_call); #ifdef TCC_HAS_RUNTIME_PLTGOT @@ -622,7 +637,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) } #endif if (th_ko || x >= 0x2000000 || x < -0x2000000) - tcc_error("can't relocate value at %x",addr); + tcc_error("can't relocate value at %x,%d",addr, type); x >>= 2; x &= 0xffffff; /* Only reached if blx is avail and it is a call */ @@ -686,7 +701,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) - instruction must be a call (bl) or a jump to PLT */ if (!to_thumb || x >= 0x1000000 || x < -0x1000000) if (to_thumb || (val & 2) || (!is_call && !to_plt)) - tcc_error("can't relocate value at %x",addr); + tcc_error("can't relocate value at %x,%d",addr, type); /* Compute and store final offset */ s = (x >> 24) & 1; @@ -743,7 +758,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) x = (x * 2) / 2; x += val - addr; if((x^(x>>1))&0x40000000) - tcc_error("can't relocate value at %x",addr); + tcc_error("can't relocate value at %x,%d",addr, type); (*(int *)ptr) |= x & 0x7fffffff; } case R_ARM_ABS32: @@ -769,6 +784,10 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10) *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */ break; + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + *(addr_t *)ptr = val; + break; case R_ARM_NONE: /* Nothing to do. Normally used to indicate a dependency on a certain symbol (like for exception handling under EABI). */ @@ -1166,7 +1185,7 @@ static unsigned long put_got_entry(TCCState *s1, /* the symbol is modified so that it will be relocated to the PLT */ - if (s1->output_type == TCC_OUTPUT_EXE) + if (sym->st_shndx == SHN_UNDEF) offset = plt->data_offset - 16; } #elif defined(TCC_TARGET_C67) @@ -1240,22 +1259,47 @@ ST_FUNC void build_got_entries(TCCState *s1) } break; #elif defined(TCC_TARGET_ARM) + case R_ARM_PC24: + case R_ARM_CALL: + case R_ARM_JUMP24: case R_ARM_GOT32: case R_ARM_GOTOFF: case R_ARM_GOTPC: case R_ARM_PLT32: if (!s1->got) build_got(s1); - if (type == R_ARM_GOT32 || type == R_ARM_PLT32) { - sym_index = ELFW(R_SYM)(rel->r_info); - sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; + sym_index = ELFW(R_SYM)(rel->r_info); + sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; + if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC + && sym->st_shndx == SHN_UNDEF) { + unsigned long ofs; /* look at the symbol got offset. If none, then add one */ if (type == R_ARM_GOT32) reloc_type = R_ARM_GLOB_DAT; else reloc_type = R_ARM_JUMP_SLOT; - put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, - sym_index); + ofs = put_got_entry(s1, reloc_type, sym->st_size, + sym->st_info, sym_index); +#ifdef DEBUG_RELOC + printf ("maybegot: %s, %d, %d --> ofs=0x%x\n", + (char *) symtab_section->link->data + sym->st_name, + type, sym->st_shndx, ofs); +#endif + if (type != R_ARM_GOT32) { + addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data + + rel->r_offset); + /* x must be signed! */ + int x = *ptr & 0xffffff; + x = (x << 8) >> 8; + x <<= 2; + x += ofs; + x >>= 2; +#ifdef DEBUG_RELOC + printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr, + (*ptr & 0xff000000) | x, x); +#endif + *ptr = (*ptr & 0xff000000) | x; + } } break; case R_ARM_THM_JUMP24: -- cgit v1.3.1 From 6a947d9d2610723db3f46bcae4f35d5d5c572f89 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sun, 6 Apr 2014 01:59:35 +0200 Subject: ELF: Remove traces of old RUNTIME_PLTGOT code The last users of it went away, no use in keeping this code. --- tcc.h | 6 ------ tccelf.c | 64 +--------------------------------------------------------------- tccrun.c | 13 ------------- 3 files changed, 1 insertion(+), 82 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 5033b19..1688a0c 100644 --- a/tcc.h +++ b/tcc.h @@ -712,12 +712,6 @@ struct TCCState { void *write_mem; unsigned long mem_size; # endif -# if !defined TCC_TARGET_PE && (0) - /* write PLT and GOT here */ - char *runtime_plt_and_got; - unsigned runtime_plt_and_got_offset; -# define TCC_HAS_RUNTIME_PLTGOT -# endif #endif /* used by main and tcc_parse_args only */ diff --git a/tccelf.c b/tccelf.c index 6f63f83..6955847 100644 --- a/tccelf.c +++ b/tccelf.c @@ -476,42 +476,6 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) } } -#ifdef TCC_HAS_RUNTIME_PLTGOT -#ifdef TCC_TARGET_X86_64 -#define JMP_TABLE_ENTRY_SIZE 14 -static addr_t add_jmp_table(TCCState *s1, addr_t val) -{ - char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset; - s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE; - /* jmp *0x0(%rip) */ - p[0] = 0xff; - p[1] = 0x25; - *(int *)(p + 2) = 0; - *(addr_t *)(p + 6) = val; - return (addr_t)p; -} - -static addr_t add_got_table(TCCState *s1, addr_t val) -{ - addr_t *p = (addr_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset); - s1->runtime_plt_and_got_offset += sizeof(addr_t); - *p = val; - return (addr_t)p; -} -#elif defined TCC_TARGET_ARM -#define JMP_TABLE_ENTRY_SIZE 8 -static addr_t add_jmp_table(TCCState *s1, int val) -{ - uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset); - s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE; - /* ldr pc, [pc, #-4] */ - p[0] = 0xE51FF004; - p[1] = val; - return (addr_t)p; -} -#endif -#endif /* def TCC_HAS_RUNTIME_PLTGOT */ - /* relocate a given section (CPU dependent) by applying the relocations in the associated relocation section */ ST_FUNC void relocate_section(TCCState *s1, Section *s) @@ -627,15 +591,6 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) #endif h = x & 2; th_ko = (x & 3) && (!blx_avail || !is_call); -#ifdef TCC_HAS_RUNTIME_PLTGOT - if (s1->output_type == TCC_OUTPUT_MEMORY) { - if (th_ko || x >= 0x2000000 || x < -0x2000000) { - x += add_jmp_table(s1, val) - val; /* add veneer */ - th_ko = (x & 3) && (!blx_avail || !is_call); - is_thumb = 0; /* Veneer uses ARM instructions */ - } - } -#endif if (th_ko || x >= 0x2000000 || x < -0x2000000) tcc_error("can't relocate value at %x,%d",addr, type); x >>= 2; @@ -878,17 +833,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) long long diff; diff = (long long)val - addr; if (diff <= -2147483647 || diff > 2147483647) { -#ifdef TCC_HAS_RUNTIME_PLTGOT - /* XXX: naive support for over 32bit jump */ - if (s1->output_type == TCC_OUTPUT_MEMORY) { - val = (add_jmp_table(s1, val - rel->r_addend) + - rel->r_addend); - diff = val - addr; - } -#endif - if (diff <= -2147483647 || diff > 2147483647) { - tcc_error("internal error: relocation failed"); - } + tcc_error("internal error: relocation failed"); } *(int *)ptr += diff; } @@ -899,13 +844,6 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) *(addr_t *)ptr = val - rel->r_addend; break; case R_X86_64_GOTPCREL: -#ifdef TCC_HAS_RUNTIME_PLTGOT - if (s1->output_type == TCC_OUTPUT_MEMORY) { - val = add_got_table(s1, val - rel->r_addend) + rel->r_addend; - *(int *)ptr += val - addr; - break; - } -#endif *(int *)ptr += (s1->got->sh_addr - addr + s1->sym_attrs[sym_index].got_offset - 4); break; diff --git a/tccrun.c b/tccrun.c index 2876ab7..52a74b3 100644 --- a/tccrun.c +++ b/tccrun.c @@ -180,14 +180,6 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr) if (s1->nb_errors) return -1; -#ifdef TCC_HAS_RUNTIME_PLTGOT - s1->runtime_plt_and_got_offset = 0; - s1->runtime_plt_and_got = (char *)(mem + offset); - /* double the size of the buffer for got and plt entries - XXX: calculate exact size for them? */ - offset *= 2; -#endif - if (0 == mem) return offset; @@ -215,11 +207,6 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr) set_pages_executable(ptr, length); } -#ifdef TCC_HAS_RUNTIME_PLTGOT - set_pages_executable(s1->runtime_plt_and_got, - s1->runtime_plt_and_got_offset); -#endif - #ifdef _WIN64 win64_add_function_table(s1); #endif -- cgit v1.3.1 From b8eb7dd8e8ceec65d10a95989daf96f6f82e47a3 Mon Sep 17 00:00:00 2001 From: minux Date: Sat, 12 Apr 2014 01:10:12 -0400 Subject: tcc.h: add ELF interpreter for DragonFly BSD. --- tcc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 1688a0c..9955839 100644 --- a/tcc.h +++ b/tcc.h @@ -252,6 +252,8 @@ # else # define CONFIG_TCC_ELFINTERP "/lib/ld.so.1" # endif +# elif defined __DragonFly__ +# define CONFIG_TCC_ELFINTERP "/usr/libexec/ld-elf.so.2" # elif defined __GNU__ # define CONFIG_TCC_ELFINTERP "/lib/ld.so" # elif defined(TCC_TARGET_X86_64) -- cgit v1.3.1 From 6e56bb387db8af055ff6de71a23b270de55c3dc8 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sat, 12 Apr 2014 12:00:13 +0800 Subject: Fix preprocessor concat with empty arg --- tcc.h | 1 + tccpp.c | 42 ++++++++++++++++++++++++++++++++----- tests/tests2/67_macro_concat.c | 14 +++++++++++++ tests/tests2/67_macro_concat.expect | 2 ++ tests/tests2/Makefile | 3 ++- 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 tests/tests2/67_macro_concat.c create mode 100644 tests/tests2/67_macro_concat.expect (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index 9955839..dda2fc1 100644 --- a/tcc.h +++ b/tcc.h @@ -836,6 +836,7 @@ struct TCCState { /* <-- */ #define TOK_TWOSHARPS 0xc0 /* ## preprocessing token */ +#define TOK_PLCHLDR 0xc1 /* placeholder token as defined in C99 */ #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */ #define TOK_ADDC1 0xc3 /* add with carry generation */ #define TOK_ADDC2 0xc4 /* add with carry use */ diff --git a/tccpp.c b/tccpp.c index c8beec5..dfdee50 100644 --- a/tccpp.c +++ b/tccpp.c @@ -2565,7 +2565,8 @@ ST_FUNC void next_nomacro(void) } while (is_space(tok)); } -/* substitute args in macro_str and return allocated string */ +/* substitute arguments in replacement lists in macro_str by the values in + args (field d) and return allocated string */ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) { int last_tok, t, spc; @@ -2622,7 +2623,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) if (gnu_ext && s->type.t && last_tok == TOK_TWOSHARPS && str.len >= 2 && str.str[str.len - 2] == ',') { - if (*st == 0) { + if (*st == TOK_PLCHLDR) { /* suppress ',' '##' */ str.len -= 2; } else { @@ -2793,6 +2794,8 @@ static int macro_subst_tok(TokenString *tok_str, tok_str_add2(&str, tok, &tokc); next_nomacro_spc(); } + if (!str.len) + tok_str_add(&str, TOK_PLCHLDR); str.len -= spc; tok_str_add(&str, 0); sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0); @@ -2885,9 +2888,11 @@ static inline int *macro_twosharps(const int *macro_str) TOK_GET(&t, &ptr, &cval); /* We concatenate the two tokens */ cstr_new(&cstr); - cstr_cat(&cstr, get_tok_str(tok, &tokc)); + if (tok != TOK_PLCHLDR) + cstr_cat(&cstr, get_tok_str(tok, &tokc)); n = cstr.size; - cstr_cat(&cstr, get_tok_str(t, &cval)); + if (t != TOK_PLCHLDR || tok == TOK_PLCHLDR) + cstr_cat(&cstr, get_tok_str(t, &cval)); cstr_ccat(&cstr, '\0'); tcc_open_bf(tcc_state, ":paste:", cstr.size); @@ -2904,8 +2909,35 @@ static inline int *macro_twosharps(const int *macro_str) cstr_free(&cstr); } } - if (tok != TOK_NOSUBST) + if (tok != TOK_NOSUBST) { + const int *oldptr; + CValue cval; + + /* Check if a space need to be added after ## concatenation in + order to avoid misinterpreting the newly formed token + followed by the next token as being a single token (see + macro_concat test) */ + cstr_new(&cstr); + cstr_cat(&cstr, get_tok_str(tok, &tokc)); + oldptr = ptr; + TOK_GET(&t, &ptr, &cval); + ptr = oldptr; + cstr_cat(&cstr, get_tok_str(t, &cval)); + cstr_ccat(&cstr, '\0'); + t = tok; + cval = tokc; + tcc_open_bf(tcc_state, ":paste:", cstr.size); + memcpy(file->buffer, cstr.data, cstr.size); + next_nomacro1(); + if (!*file->buf_ptr) { + tok_str_add2(¯o_str1, t, &cval); + tok = ' '; + } + tcc_close(); + cstr_free(&cstr); + start_of_nosubsts = -1; + } tok_str_add2(¯o_str1, tok, &tokc); } tok_str_add(¯o_str1, 0); diff --git a/tests/tests2/67_macro_concat.c b/tests/tests2/67_macro_concat.c new file mode 100644 index 0000000..c580d3a --- /dev/null +++ b/tests/tests2/67_macro_concat.c @@ -0,0 +1,14 @@ +#include + +#define P(A,B) A ## B ; bob +#define Q(A,B) A ## B+ + +int main(void) +{ + int bob, jim = 21; + bob = P(jim,) *= 2; + printf("jim: %d, bob: %d\n", jim, bob); + jim = 60 Q(+,)3; + printf("jim: %d\n", jim); + return 0; +} diff --git a/tests/tests2/67_macro_concat.expect b/tests/tests2/67_macro_concat.expect new file mode 100644 index 0000000..8386c2d --- /dev/null +++ b/tests/tests2/67_macro_concat.expect @@ -0,0 +1,2 @@ +jim: 21, bob: 42 +jim: 63 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 41adb2d..a7c8a2f 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -81,7 +81,8 @@ TESTS = \ 63_local_enumerator_redefinition.test \ 64_macro_nesting.test \ 65_macro_concat_start.test \ - 66_macro_concat_end.test + 66_macro_concat_end.test \ + 67_macro_concat.test # 30_hanoi.test -- seg fault in the code, gcc as well # 34_array_assignment.test -- array assignment is not in C standard -- cgit v1.3.1 From fbda78aefeaaa97182658bb81b5a6f215cc24b17 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 14 Apr 2014 02:53:11 +0200 Subject: Parse and emit hidden visibility This adds parsing of (GCC compatible) visibility attribute in order to mark selected global symbols as hidden. The generated .o files contain hidden symbols already, the TCC linker doesn't yet do the right thing. --- tcc.h | 12 ++++++++++-- tccgen.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- tcctok.h | 2 ++ 3 files changed, 69 insertions(+), 5 deletions(-) (limited to 'tcc.h') diff --git a/tcc.h b/tcc.h index dda2fc1..ab14b38 100644 --- a/tcc.h +++ b/tcc.h @@ -375,7 +375,8 @@ struct Attribute { func_proto : 1, mode : 4, weak : 1, - fill : 10; // 10 bits left to fit well in union below + visibility : 2, + fill : 8; // 8 bits left to fit well in union below }; /* GNUC attribute definition */ @@ -787,11 +788,18 @@ struct TCCState { #define VT_EXPORT 0x00008000 /* win32: data exported from dll */ #define VT_WEAK 0x00010000 /* weak symbol */ #define VT_TLS 0x00040000 /* thread-local storage */ +#define VT_VIS_SHIFT 19 /* shift for symbol visibility, overlapping + bitfield values, because bitfields never + have linkage and hence never have + visibility. */ +#define VT_VIS_SIZE 2 /* We have four visibilities. */ +#define VT_VIS_MASK (((1 << VT_VIS_SIZE)-1) << VT_VIS_SHIFT) #define VT_STRUCT_SHIFT 19 /* shift for bitfield shift values (max: 32 - 2*6) */ + /* type mask (except storage) */ -#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK) +#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK | VT_VIS_MASK) #define VT_TYPE (~(VT_STORAGE)) /* token values */ diff --git a/tccgen.c b/tccgen.c index 78f24aa..9b00824 100644 --- a/tccgen.c +++ b/tccgen.c @@ -300,6 +300,29 @@ static void weaken_symbol(Sym *sym) } } +static void apply_visibility(Sym *sym, CType *type) +{ + int vis = sym->type.t & VT_VIS_MASK; + int vis2 = type->t & VT_VIS_MASK; + if (vis == (STV_DEFAULT << VT_VIS_SHIFT)) + vis = vis2; + else if (vis2 == (STV_DEFAULT << VT_VIS_SHIFT)) + ; + else + vis = (vis < vis2) ? vis : vis2; + sym->type.t &= ~VT_VIS_MASK; + sym->type.t |= vis; + + if (sym->c > 0) { + int esym_type; + ElfW(Sym) *esym; + + esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; + vis >>= VT_VIS_SHIFT; + esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | vis; + } +} + /* ------------------------------------------------------------------------- */ ST_FUNC void swap(int *p, int *q) @@ -436,6 +459,13 @@ static Sym *external_sym(int v, CType *type, int r, char *asm_label) tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } + /* Merge some storage attributes. */ + if (type->t & VT_WEAK) + weaken_symbol(s); + + if (type->t & VT_VIS_MASK) + apply_visibility(s, type); + return s; } @@ -2662,6 +2692,24 @@ static void parse_attribute(AttributeDef *ad) next(); skip(')'); break; + case TOK_VISIBILITY1: + case TOK_VISIBILITY2: + skip('('); + if (tok != TOK_STR) + expect("visibility(\"default|hidden|internal|protected\")"); + if (!strcmp (tokc.cstr->data, "default")) + ad->a.visibility = STV_DEFAULT; + else if (!strcmp (tokc.cstr->data, "hidden")) + ad->a.visibility = STV_HIDDEN; + else if (!strcmp (tokc.cstr->data, "internal")) + ad->a.visibility = STV_INTERNAL; + else if (!strcmp (tokc.cstr->data, "protected")) + ad->a.visibility = STV_PROTECTED; + else + expect("visibility(\"default|hidden|internal|protected\")"); + next(); + skip(')'); + break; case TOK_ALIGNED1: case TOK_ALIGNED2: if (tok == '(') { @@ -5656,6 +5704,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, /* patch symbol weakness */ if (type->t & VT_WEAK) weaken_symbol(sym); + apply_visibility(sym, type); #ifdef CONFIG_TCC_BCHECK /* handles bounds now because the symbol must be defined before for the relocation */ @@ -5801,6 +5850,7 @@ static void gen_function(Sym *sym) /* patch symbol weakness (this definition overrules any prototype) */ if (sym->type.t & VT_WEAK) weaken_symbol(sym); + apply_visibility(sym, &sym->type); if (tcc_state->do_debug) { put_stabn(N_FUN, 0, 0, ind - func_ind); } @@ -5934,6 +5984,8 @@ static int decl0(int l, int is_for_loop_init) if (ad.a.func_export) type.t |= VT_EXPORT; #endif + type.t |= ad.a.visibility << VT_VIS_SHIFT; + if (tok == '{') { if (l == VT_LOCAL) tcc_error("cannot use local functions"); @@ -5973,6 +6025,11 @@ static int decl0(int l, int is_for_loop_init) if (sym->type.t & VT_STATIC) type.t = (type.t & ~VT_EXTERN) | VT_STATIC; + /* If the definition has no visibility use the + one from prototype. */ + if (! (type.t & VT_VIS_MASK)) + type.t |= sym->type.t & VT_VIS_MASK; + if (!is_compatible_types(&sym->type, &type)) { func_error1: tcc_error("incompatible types for redefinition of '%s'", @@ -6063,9 +6120,6 @@ static int decl0(int l, int is_for_loop_init) extern */ sym = external_sym(v, &type, r, asm_label); - if (type.t & VT_WEAK) - weaken_symbol(sym); - if (ad.alias_target) { Section tsec; Elf32_Sym *esym; diff --git a/tcctok.h b/tcctok.h index c17711f..d8c0344 100644 --- a/tcctok.h +++ b/tcctok.h @@ -121,6 +121,8 @@ DEF(TOK_DLLIMPORT, "dllimport") DEF(TOK_NORETURN1, "noreturn") DEF(TOK_NORETURN2, "__noreturn__") + DEF(TOK_VISIBILITY1, "visibility") + DEF(TOK_VISIBILITY2, "__visibility__") DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p") DEF(TOK_builtin_constant_p, "__builtin_constant_p") DEF(TOK_builtin_frame_address, "__builtin_frame_address") -- cgit v1.3.1 From 2ac238fc507b64a8dd2d5d3d5c00210c1ffabea5 Mon Sep 17 00:00:00 2001 From: grischka Date: Thu, 17 Apr 2014 17:01:28 +0200 Subject: tccpe: adjust for new 'hidden' symbols feature in order to avoid conflicts with windows specific (ab)usage of the Elf32_Sym -> st_other field. --- libtcc.c | 12 +++++------- tcc.h | 4 ++++ tccpe.c | 16 ++++++++-------- 3 files changed, 17 insertions(+), 15 deletions(-) (limited to 'tcc.h') diff --git a/libtcc.c b/libtcc.c index 05abaef..deda7e6 100644 --- a/libtcc.c +++ b/libtcc.c @@ -491,22 +491,22 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, #ifdef TCC_TARGET_PE if (sym->type.t & VT_EXPORT) - other |= 1; + other |= ST_PE_EXPORT; if (sym_type == STT_FUNC && sym->type.ref) { Sym *ref = sym->type.ref; if (ref->a.func_export) - other |= 1; + other |= ST_PE_EXPORT; if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) { sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE); name = buf1; - other |= 2; + other |= ST_PE_STDCALL; can_add_underscore = 0; } } else { if (find_elf_sym(tcc_state->dynsymtab_section, name)) - other |= 4; + other |= ST_PE_IMPORT; if (sym->type.t & VT_IMPORT) - other |= 4; + other |= ST_PE_IMPORT; } #else if (! (sym->type.t & VT_STATIC)) @@ -1316,8 +1316,6 @@ LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val) So it is handled here as if it were in a DLL. */ pe_putimport(s, 0, name, (uintptr_t)val); #else - /* XXX: Same problem on linux but currently "solved" elsewhere - via the rather dirty 'runtime_plt_and_got' hack. */ add_elf_sym(symtab_section, (uintptr_t)val, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_ABS, name); diff --git a/tcc.h b/tcc.h index ab14b38..c93cedf 100644 --- a/tcc.h +++ b/tcc.h @@ -1392,6 +1392,10 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2); #ifdef TCC_TARGET_X86_64 ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack); #endif +/* symbol properties stored in Elf32_Sym->st_other */ +# define ST_PE_EXPORT 0x10 +# define ST_PE_IMPORT 0x20 +# define ST_PE_STDCALL 0x40 #endif /* ------------ tccrun.c ----------------- */ diff --git a/tccpe.c b/tccpe.c index 6ee3865..b972d75 100644 --- a/tccpe.c +++ b/tccpe.c @@ -363,7 +363,7 @@ struct pe_info { static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym) { const char *name = symtab_section->link->data + sym->st_name; - if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & 2)) + if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL)) return name + 1; return name; } @@ -378,7 +378,7 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym) s = pe_export_name(s1, sym); if (n) { /* second try: */ - if (sym->st_other & 2) { + if (sym->st_other & ST_PE_STDCALL) { /* try w/0 stdcall deco (windows API convention) */ p = strrchr(s, '@'); if (!p || s[0] != '_') @@ -899,7 +899,7 @@ static void pe_build_exports(struct pe_info *pe) for (sym_index = 1; sym_index < sym_end; ++sym_index) { sym = (ElfW(Sym)*)symtab_section->data + sym_index; name = pe_export_name(pe->s1, sym); - if ((sym->st_other & 1) + if ((sym->st_other & ST_PE_EXPORT) /* export only symbols from actually written sections */ && pe->s1->sections[sym->st_shndx]->sh_addr) { p = tcc_malloc(sizeof *p); @@ -908,9 +908,9 @@ static void pe_build_exports(struct pe_info *pe) dynarray_add((void***)&sorted, &sym_count, p); } #if 0 - if (sym->st_other & 1) + if (sym->st_other & ST_PE_EXPORT) printf("export: %s\n", name); - if (sym->st_other & 2) + if (sym->st_other & ST_PE_STDCALL) printf("stdcall: %s\n", name); #endif } @@ -1282,7 +1282,7 @@ static int pe_check_symbols(struct pe_info *pe) /* patch the original symbol */ sym->st_value = offset; sym->st_shndx = text_section->sh_num; - sym->st_other &= ~1; /* do not export */ + sym->st_other &= ~ST_PE_EXPORT; /* do not export */ continue; } @@ -1301,7 +1301,7 @@ static int pe_check_symbols(struct pe_info *pe) } else if (pe->s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { /* if -rdynamic option, then export all non local symbols */ - sym->st_other |= 1; + sym->st_other |= ST_PE_EXPORT; } } return ret; @@ -1463,7 +1463,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2) if (!sym->c) put_extern_sym(sym, NULL, 0, 0); esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; - if (!(esym->st_other & 4)) + if (!(esym->st_other & ST_PE_IMPORT)) return sv; // printf("import %04x %04x %04x %s\n", sv->type.t, sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL)); -- cgit v1.3.1