]> granicus.if.org Git - yasm/commitdiff
Set ELF symbol type to TLS if either:
authorPeter Johnson <peter@tortall.net>
Thu, 21 Feb 2008 08:57:23 +0000 (08:57 -0000)
committerPeter Johnson <peter@tortall.net>
Thu, 21 Feb 2008 08:57:23 +0000 (08:57 -0000)
- symbol is defined in a TLS section
- symbol is used in a TLS relocation

This is required by the GNU linker, and matches GNU as behavior.
The implementation is not as clean as it perhaps should be, but it does
the job.

Reported by: Nils Weller <nils@gnulinux.nl>

svn path=/trunk/yasm/; revision=2040

modules/objfmts/elf/elf-machine.h
modules/objfmts/elf/elf-objfmt.c
modules/objfmts/elf/elf-x86-amd64.c
modules/objfmts/elf/elf-x86-x86.c
modules/objfmts/elf/elf.c
modules/objfmts/elf/elf.h
modules/objfmts/elf/tests/gas32/elf_gas32_ssym.hex
modules/objfmts/elf/tests/gas64/elf_gas64_ssym.hex

index 46cce2db2d13c4d75c9091e1b3e11bddd96b70f5..1742e444458d26888deee6b1d70dce61d76804c1 100644 (file)
@@ -71,7 +71,8 @@ typedef void (*func_write_proghead)(unsigned char **bufpp,
 
 enum {
     ELF_SSYM_SYM_RELATIVE = 1 << 0,
-    ELF_SSYM_CURPOS_ADJUST = 1 << 1
+    ELF_SSYM_CURPOS_ADJUST = 1 << 1,
+    ELF_SSYM_THREAD_LOCAL = 1 << 2
 };
 
 typedef struct {
index b91aec9e410d6e47f5af5df87c99f675fc3bfdc5..2dbed1f3adf20b9b6389190068b0dfdd8a8e9115 100644 (file)
@@ -1069,6 +1069,9 @@ elf_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
     } else if (strcmp(sectname, ".data") == 0) {
         data.type = SHT_PROGBITS;
         data.flags = SHF_ALLOC + SHF_WRITE;
+    } else if (strcmp(sectname, ".tdata") == 0) {
+        data.type = SHT_PROGBITS;
+        data.flags = SHF_ALLOC + SHF_WRITE;
     } else if (strcmp(sectname, ".rodata") == 0) {
         data.type = SHT_PROGBITS;
         data.flags = SHF_ALLOC;
@@ -1179,6 +1182,10 @@ dir_type(yasm_object *object, yasm_valparamhead *valparams,
             elf_sym_set_type(entry, STT_FUNC);
         else if (yasm__strcasecmp(type, "object") == 0)
             elf_sym_set_type(entry, STT_OBJECT);
+        else if (yasm__strcasecmp(type, "tls_object") == 0)
+            elf_sym_set_type(entry, STT_TLS);
+        else if (yasm__strcasecmp(type, "notype") == 0)
+            elf_sym_set_type(entry, STT_NOTYPE);
         else
             yasm_warn_set(YASM_WARN_GENERAL,
                           N_("unrecognized symbol type `%s'"), type);
index d95882843c499ac53fea107129c1b6fb512cd146..b99f089e3dd9b3e69bae7f474aae4496dec8c04c 100644 (file)
 static elf_machine_ssym elf_x86_amd64_ssyms[] = {
     {"plt",         ELF_SSYM_SYM_RELATIVE,  R_X86_64_PLT32,     32},
     {"gotpcrel",    ELF_SSYM_SYM_RELATIVE,  R_X86_64_GOTPCREL,  32},
-    {"tlsgd",       ELF_SSYM_SYM_RELATIVE,  R_X86_64_TLSGD,     32},
-    {"tlsld",       ELF_SSYM_SYM_RELATIVE,  R_X86_64_TLSLD,     32},
-    {"gottpoff",    ELF_SSYM_SYM_RELATIVE,  R_X86_64_GOTTPOFF,  32},
-    {"tpoff",       ELF_SSYM_SYM_RELATIVE,  R_X86_64_TPOFF32,   32},
-    {"dtpoff",      ELF_SSYM_SYM_RELATIVE,  R_X86_64_DTPOFF32,  32},
+    {"tlsgd",       ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_X86_64_TLSGD,     32},
+    {"tlsld",       ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_X86_64_TLSLD,     32},
+    {"gottpoff",    ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_X86_64_GOTTPOFF,  32},
+    {"tpoff",       ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_X86_64_TPOFF32,   32},
+    {"dtpoff",      ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_X86_64_DTPOFF32,  32},
     {"got",         ELF_SSYM_SYM_RELATIVE,  R_X86_64_GOT32,     32}
 };
 
@@ -141,8 +146,18 @@ elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc,
         size_t i;
         for (i=0; i<NELEMS(elf_x86_amd64_ssyms); i++) {
             if (reloc->wrt == ssyms[i] &&
-                reloc->valsize == elf_x86_amd64_ssyms[i].size)
+                reloc->valsize == elf_x86_amd64_ssyms[i].size) {
+                /* Force TLS type; this is required by the linker. */
+                if (elf_x86_amd64_ssyms[i].sym_rel & ELF_SSYM_THREAD_LOCAL) {
+                    elf_symtab_entry *esym;
+
+                    esym = yasm_symrec_get_data(reloc->reloc.sym,
+                                                &elf_symrec_data);
+                    if (esym)
+                        esym->type = STT_TLS;
+                }
                 return (unsigned char) elf_x86_amd64_ssyms[i].reloc;
+            }
         }
         yasm_internal_error(N_("Unsupported WRT"));
     } else if (reloc->rtype_rel) {
index 2a1ba14f8d431be72ed4997bbab5854ba960c864..07d60fd256041b86b880ee0485fd0937d605e655 100644 (file)
@@ -38,14 +38,22 @@ static const elf_machine_ssym elf_x86_x86_ssyms[] = {
     {"gotoff",      0,                      R_386_GOTOFF,       32},
     /* special one for NASM */
     {"gotpc",       ELF_SSYM_CURPOS_ADJUST, R_386_GOTPC,        32},
-    {"tlsgd",       ELF_SSYM_SYM_RELATIVE,  R_386_TLS_GD,       32},
-    {"tlsldm",      ELF_SSYM_SYM_RELATIVE,  R_386_TLS_LDM,      32},
-    {"gottpoff",    ELF_SSYM_SYM_RELATIVE,  R_386_TLS_IE_32,    32},
-    {"tpoff",       ELF_SSYM_SYM_RELATIVE,  R_386_TLS_LE_32,    32},
-    {"ntpoff",      ELF_SSYM_SYM_RELATIVE,  R_386_TLS_LE,       32},
-    {"dtpoff",      ELF_SSYM_SYM_RELATIVE,  R_386_TLS_LDO_32,   32},
-    {"gotntpoff",   ELF_SSYM_SYM_RELATIVE,  R_386_TLS_GOTIE,    32},
-    {"indntpoff",   ELF_SSYM_SYM_RELATIVE,  R_386_TLS_IE,       32},
+    {"tlsgd",       ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_386_TLS_GD,       32},
+    {"tlsldm",      ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_386_TLS_LDM,      32},
+    {"gottpoff",    ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_386_TLS_IE_32,    32},
+    {"tpoff",       ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_386_TLS_LE_32,    32},
+    {"ntpoff",      ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_386_TLS_LE,       32},
+    {"dtpoff",      ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_386_TLS_LDO_32,   32},
+    {"gotntpoff",   ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_386_TLS_GOTIE,    32},
+    {"indntpoff",   ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL,
+                    R_386_TLS_IE,       32},
     {"got",         ELF_SSYM_SYM_RELATIVE,  R_386_GOT32,        32}
 };
 
@@ -138,8 +146,18 @@ elf_x86_x86_map_reloc_info_to_type(elf_reloc_entry *reloc,
         size_t i;
         for (i=0; i<NELEMS(elf_x86_x86_ssyms); i++) {
             if (reloc->wrt == ssyms[i] &&
-                reloc->valsize == elf_x86_x86_ssyms[i].size)
+                reloc->valsize == elf_x86_x86_ssyms[i].size) {
+                /* Force TLS type; this is required by the linker. */
+                if (elf_x86_x86_ssyms[i].sym_rel & ELF_SSYM_THREAD_LOCAL) {
+                    elf_symtab_entry *esym;
+
+                    esym = yasm_symrec_get_data(reloc->reloc.sym,
+                                                &elf_symrec_data);
+                    if (esym)
+                        esym->type = STT_TLS;
+                }
                 return (unsigned char) elf_x86_x86_ssyms[i].reloc;
+            }
         }
         yasm_internal_error(N_("Unsupported WRT"));
     } else if (reloc->rtype_rel) {
index 807a3afe1267035719373962dbc3361721b4eeed..01c2fa5bcf80ee118a49746e27292dc12f952efa 100644 (file)
@@ -495,6 +495,18 @@ elf_symtab_write_to_file(FILE *f, elf_symtab_head *symtab,
         if (value_intn == NULL)
             value_intn = yasm_intnum_create_uint(entry->value);
 
+        /* If symbol is in a TLS section, force its type to TLS. */
+        if (entry->sym) {
+            yasm_bytecode *precbc;
+            yasm_section *sect;
+            elf_secthead *shead;
+            if (yasm_symrec_get_label(entry->sym, &precbc) &&
+                (sect = yasm_bc_get_section(precbc)) &&
+                (shead = yasm_section_get_data(sect, &elf_section_data)) &&
+                shead->flags & SHF_TLS) {
+                entry->type = STT_TLS;
+            }
+        }
 
         if (!elf_march->write_symtab_entry || !elf_march->symtab_entry_size)
             yasm_internal_error(N_("Unsupported machine for ELF output"));
index a10b0b4918bb47948b062a705b0473b7b405e14e..1fe18bd2f13716b5c943fd85ae7d79b92aed51a9 100644 (file)
@@ -191,6 +191,9 @@ typedef enum {
     STT_FUNC = 2,               /* a function or executable code */
     STT_SECTION = 3,            /* a section: often for relocation, STB_LOCAL */
     STT_FILE = 4,               /* often source filename: STB_LOCAL, SHN_ABS */
+    STT_COMMON = 5,             /* Uninitialized common block. */
+    STT_TLS = 6,                /* TLS object. */
+    STT_NUM = 7,
 
     STT_LOOS = 10,              /* Environment specific use */
     STT_HIOS = 12,
index a6fcecc4bdca226cf3b261ca3d9870ce5989771b..61057e2faf369bcc64e7db27b16e5825b0de94dc 100644 (file)
@@ -334,7 +334,7 @@ ff
 00 
 00 
 00 
-10 
+16 
 00 
 00 
 00 
index 698890fafdc6adc3b55d3f0e0032d7e3c391ebf9..06e4c13821148b98aa8905b09fc8b3ccde732545 100644 (file)
@@ -462,7 +462,7 @@ ff
 00 
 00 
 00 
-10 
+16 
 00 
 00 
 00