From 8f6fcb709ae7b2379866c292ce478ab95dc75b48 Mon Sep 17 00:00:00 2001 From: grischka Date: Thu, 31 May 2018 23:51:51 +0200 Subject: [PATCH] misc fixes misc fixes including: - tcc.c: fix "tcc -vv" for libtcc1.a on win32/PE - tccelf.c: fix a crash when GOT has no relocs (witn -nostdlib) - tccelf.c: fix stab linkage for zero n_strx - tccgen.c: fix stdcall decoration for array parameters int __stdcall func(char buf[10]) is _func@4 (was _func@12) - tccgen.c: fix static variables with nocode/nodata_wanted see tests2/96_nodata_wanted.c - tccrun.c: align sections using sh_addralign (for reliable function_alignment) - tests2/Makefile sort 100 after 99 - win32/include/sys/stat.h fix _stat and _wstat - x86_64-gen.c: win64/gfunc_call: fix a bug with xmmN register args previously overwrote valid other xmmN registers eventually --- tcc.c | 4 ++- tccelf.c | 9 ++++-- tccgen.c | 19 +++++++----- tccrun.c | 44 +++++++++++++--------------- tests/tests2/96_nodata_wanted.c | 24 +++++++++++---- tests/tests2/96_nodata_wanted.expect | 3 ++ tests/tests2/Makefile | 4 ++- win32/include/sys/stat.h | 4 +-- x86_64-gen.c | 11 ++++--- 9 files changed, 73 insertions(+), 49 deletions(-) diff --git a/tcc.c b/tcc.c index 8850089..88a441d 100644 --- a/tcc.c +++ b/tcc.c @@ -182,8 +182,10 @@ static void print_search_dirs(TCCState *s) /* print_dirs("programs", NULL, 0); */ print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); print_dirs("libraries", s->library_paths, s->nb_library_paths); +#ifdef TCC_TARGET_PE + printf("libtcc1:\n %s/lib/"TCC_LIBTCC1"\n", s->tcc_lib_path); +#else printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path); -#ifndef TCC_TARGET_PE print_dirs("crt", s->crt_paths, s->nb_crt_paths); printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); #endif diff --git a/tccelf.c b/tccelf.c index f3dc1f3..ead8eed 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1364,6 +1364,8 @@ ST_FUNC void fill_got(TCCState *s1) static void fill_local_got_entries(TCCState *s1) { ElfW_Rel *rel; + if (!s1->got->reloc) + return; for_each_elem(s1->got->reloc, 0, rel, ElfW_Rel) { if (ELFW(R_TYPE)(rel->r_info) == R_RELATIVE) { int sym_index = ELFW(R_SYM) (rel->r_info); @@ -2443,8 +2445,11 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, a = (Stab_Sym *)(s->data + sm_table[stab_index].offset); b = (Stab_Sym *)(s->data + s->data_offset); o = sm_table[stabstr_index].offset; - while (a < b) - a->n_strx += o, a++; + while (a < b) { + if (a->n_strx) + a->n_strx += o; + a++; + } } /* second short pass to update sh_link and sh_info fields of new diff --git a/tccgen.c b/tccgen.c index ba79f1f..9ffe91c 100644 --- a/tccgen.c +++ b/tccgen.c @@ -4294,7 +4294,6 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT); if ((pt.t & VT_BTYPE) == VT_VOID) tcc_error("parameter declared as void"); - arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE; } else { n = tok; if (n < TOK_UIDENT) @@ -4303,6 +4302,7 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) next(); } convert_parameter_type(&pt); + arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE; s = sym_push(n | SYM_FIELD, &pt, 0, 0); *plast = s; plast = &s->next; @@ -6856,11 +6856,16 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, Sym *sym = NULL; int saved_nocode_wanted = nocode_wanted; #ifdef CONFIG_TCC_BCHECK - int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; + int bcheck; #endif - if (type->t & VT_STATIC) - nocode_wanted |= NODATA_WANTED ? 0x40000000 : 0x80000000; + /* Always allocate static or global variables */ + if (v && (r & VT_VALMASK) == VT_CONST) + nocode_wanted |= 0x80000000; + +#ifdef CONFIG_TCC_BCHECK + bcheck = tcc_state->do_bounds_check && !NODATA_WANTED; +#endif flexible_array = NULL; if ((type->t & VT_BTYPE) == VT_STRUCT) { @@ -6926,7 +6931,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, align = 1; } - if (NODATA_WANTED) + if (!v && NODATA_WANTED) size = 0, align = 1; if ((r & VT_VALMASK) == VT_LOCAL) { @@ -7088,9 +7093,7 @@ static void gen_function(Sym *sym) if (sym->a.aligned) { size_t newoff = section_add(cur_text_section, 0, 1 << (sym->a.aligned - 1)); - if (ind != newoff) - gen_fill_nops(newoff - ind); - ind = newoff; + gen_fill_nops(newoff - ind); } /* NOTE: we patch the symbol size later */ put_extern_sym(sym, cur_text_section, ind, 0); diff --git a/tccrun.c b/tccrun.c index 9360164..155c8dd 100644 --- a/tccrun.c +++ b/tccrun.c @@ -169,9 +169,12 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) } #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 +/* To avoid that x86 processors would reload cached instructions + each time when data is written in the near, we need to make + sure that code and data do not share the same 64 byte unit */ #define RUN_SECTION_ALIGNMENT 63 #else - #define RUN_SECTION_ALIGNMENT 15 + #define RUN_SECTION_ALIGNMENT 0 #endif /* relocate code. Return -1 on error, required size if ptr is NULL, @@ -179,8 +182,8 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) { Section *s; - unsigned offset, length, fill, i, k; - addr_t mem; + unsigned offset, length, align, max_align, i, k, f; + addr_t mem, addr; if (NULL == ptr) { s1->nb_errors = 0; @@ -195,39 +198,32 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) return -1; } - offset = 0, mem = (addr_t)ptr; - fill = -mem & RUN_SECTION_ALIGNMENT; + offset = max_align = 0, mem = (addr_t)ptr; #ifdef _WIN64 - offset += sizeof (void*); + offset += sizeof (void*); /* space for function_table pointer */ #endif for (k = 0; k < 2; ++k) { + f = 0, addr = k ? mem : mem + ptr_diff; for(i = 1; i < s1->nb_sections; i++) { s = s1->sections[i]; if (0 == (s->sh_flags & SHF_ALLOC)) continue; if (k != !(s->sh_flags & SHF_EXECINSTR)) continue; - offset += fill; - if (!mem) - s->sh_addr = 0; - else if (s->sh_flags & SHF_EXECINSTR) - s->sh_addr = mem + offset + ptr_diff; - else - s->sh_addr = mem + offset; + align = s->sh_addralign - 1; + if (++f == 1 && align < RUN_SECTION_ALIGNMENT) + align = RUN_SECTION_ALIGNMENT; + if (max_align < align) + max_align = align; + offset += -(addr + offset) & align; + s->sh_addr = mem ? addr + offset : 0; + offset += s->data_offset; #if 0 if (mem) - printf("%-16s +%02lx %p %04x\n", - s->name, fill, (void*)s->sh_addr, (unsigned)s->data_offset); + printf("%-16s %p len %04x align %2d\n", + s->name, (void*)s->sh_addr, (unsigned)s->data_offset, align + 1); #endif - offset += s->data_offset; - fill = -(mem + offset) & 15; } -#if RUN_SECTION_ALIGNMENT > 15 - /* To avoid that x86 processors would reload cached instructions each time - when data is written in the near, we need to make sure that code and data - do not share the same 64 byte unit */ - fill = -(mem + offset) & RUN_SECTION_ALIGNMENT; -#endif } /* relocate symbols */ @@ -236,7 +232,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff) return -1; if (0 == mem) - return offset + RUN_SECTION_ALIGNMENT; + return offset + max_align; #ifdef TCC_TARGET_PE s1->pe_imagebase = mem; diff --git a/tests/tests2/96_nodata_wanted.c b/tests/tests2/96_nodata_wanted.c index cc211d3..790b431 100644 --- a/tests/tests2/96_nodata_wanted.c +++ b/tests/tests2/96_nodata_wanted.c @@ -55,11 +55,10 @@ te0:; static char ds1 = 0; ts1:; if (!SKIP) { - static void *p = (void*)&main; - static char cc[] = "static string"; - static double d = 8.0; - - static struct __attribute__((packed)) { + void *p = (void*)&main; + char cc[] = "static string"; + double d = 8.0; + struct __attribute__((packed)) { unsigned x : 12; unsigned char y : 7; unsigned z : 28, a: 4, b: 5; @@ -81,4 +80,19 @@ te1:; /*printf("# %d/%d\n", dl, tl);*/ } +#elif defined test_static_data + +#include +int main(int argc, char **argv) +{ + goto there; + if (0) { + static int a = 1; + printf("hello\n"); /* the "hello\n" string is still suppressed */ +there: + printf("a = %d\n", a); + } + return 0; +} + #endif diff --git a/tests/tests2/96_nodata_wanted.expect b/tests/tests2/96_nodata_wanted.expect index 2749109..499b36e 100644 --- a/tests/tests2/96_nodata_wanted.expect +++ b/tests/tests2/96_nodata_wanted.expect @@ -21,3 +21,6 @@ size of data/text: [test_data_suppression_on] size of data/text: zero/zero + +[test_static_data] +a = 1 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 190b2d9..a5789c9 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -3,7 +3,9 @@ include $(TOP)/Makefile SRC = $(TOPSRC)/tests/tests2 VPATH = $(SRC) -TESTS = $(patsubst %.c,%.test,$(sort $(notdir $(wildcard $(SRC)/*.c)))) +TESTS = $(patsubst %.c,%.test,\ + $(sort $(notdir $(wildcard $(SRC)/??_*.c)))\ + $(sort $(notdir $(wildcard $(SRC)/???_*.c)))) # some tests do not pass on all platforms, remove them for now SKIP = 34_array_assignment.test # array assignment is not in C standard diff --git a/win32/include/sys/stat.h b/win32/include/sys/stat.h index 344d4a2..4a95e65 100644 --- a/win32/include/sys/stat.h +++ b/win32/include/sys/stat.h @@ -81,9 +81,9 @@ extern "C" { #else #define _fstat _fstat64i32 #define _fstati64 _fstat64 -#define _stat _stat64i32 +#define _stat _stat64 #define _stati64 _stat64 -#define _wstat _wstat64i32 +#define _wstat _wstat64 #define _wstati64 _wstat64 #endif diff --git a/x86_64-gen.c b/x86_64-gen.c index 9ca5c11..c41bc93 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -877,19 +877,18 @@ void gfunc_call(int nb_args) if (is_sse_float(vtop->type.t)) { if (tcc_state->nosse) tcc_error("SSE disabled"); - gv(RC_XMM0); /* only use one float register */ if (arg >= REGN) { + gv(RC_XMM0); /* movq %xmm0, j*8(%rsp) */ gen_offs_sp(0xd60f66, 0x100, arg*8); } else { - /* movaps %xmm0, %xmmN */ - o(0x280f); - o(0xc0 + (arg << 3)); + /* Load directly to xmmN register */ + gv(RC_XMM0 << arg); d = arg_prepare_reg(arg); - /* mov %xmm0, %rxx */ + /* mov %xmmN, %rxx */ o(0x66); orex(1,d,0, 0x7e0f); - o(0xc0 + REG_VALUE(d)); + o(0xc0 + arg*8 + REG_VALUE(d)); } } else { if (bt == VT_STRUCT) {