Browse Source

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
grischka 1 year ago
parent
commit
8f6fcb709a
9 changed files with 73 additions and 49 deletions
  1. 3 1
      tcc.c
  2. 7 2
      tccelf.c
  3. 11 8
      tccgen.c
  4. 20 24
      tccrun.c
  5. 19 5
      tests/tests2/96_nodata_wanted.c
  6. 3 0
      tests/tests2/96_nodata_wanted.expect
  7. 3 1
      tests/tests2/Makefile
  8. 2 2
      win32/include/sys/stat.h
  9. 5 6
      x86_64-gen.c

+ 3 - 1
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

+ 7 - 2
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

+ 11 - 8
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);

+ 20 - 24
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;

+ 19 - 5
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 <stdio.h>
+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

+ 3 - 0
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

+ 3 - 1
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

+ 2 - 2
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
 

+ 5 - 6
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) {