summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorPeter Johnson <peter@tortall.net>2008-02-21 08:57:23 +0000
committerPeter Johnson <peter@tortall.net>2008-02-21 08:57:23 +0000
commitb49c080965494b4f829bc77fb43bd6fa83893725 (patch)
tree2bff181dd313c5658eec8b8d6f5d418dbac67dcd /modules
parent40a06385d570134260d4fe56327a7e2bc6125097 (diff)
downloadyasm-b49c080965494b4f829bc77fb43bd6fa83893725.tar.gz
Set ELF symbol type to TLS if either:
- 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
Diffstat (limited to 'modules')
-rw-r--r--modules/objfmts/elf/elf-machine.h3
-rw-r--r--modules/objfmts/elf/elf-objfmt.c7
-rw-r--r--modules/objfmts/elf/elf-x86-amd64.c27
-rw-r--r--modules/objfmts/elf/elf-x86-x86.c36
-rw-r--r--modules/objfmts/elf/elf.c12
-rw-r--r--modules/objfmts/elf/elf.h3
-rw-r--r--modules/objfmts/elf/tests/gas32/elf_gas32_ssym.hex2
-rw-r--r--modules/objfmts/elf/tests/gas64/elf_gas64_ssym.hex2
8 files changed, 74 insertions, 18 deletions
diff --git a/modules/objfmts/elf/elf-machine.h b/modules/objfmts/elf/elf-machine.h
index 46cce2db..1742e444 100644
--- a/modules/objfmts/elf/elf-machine.h
+++ b/modules/objfmts/elf/elf-machine.h
@@ -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 {
diff --git a/modules/objfmts/elf/elf-objfmt.c b/modules/objfmts/elf/elf-objfmt.c
index b91aec9e..2dbed1f3 100644
--- a/modules/objfmts/elf/elf-objfmt.c
+++ b/modules/objfmts/elf/elf-objfmt.c
@@ -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);
diff --git a/modules/objfmts/elf/elf-x86-amd64.c b/modules/objfmts/elf/elf-x86-amd64.c
index d9588284..b99f089e 100644
--- a/modules/objfmts/elf/elf-x86-amd64.c
+++ b/modules/objfmts/elf/elf-x86-amd64.c
@@ -36,11 +36,16 @@
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) {
diff --git a/modules/objfmts/elf/elf-x86-x86.c b/modules/objfmts/elf/elf-x86-x86.c
index 2a1ba14f..07d60fd2 100644
--- a/modules/objfmts/elf/elf-x86-x86.c
+++ b/modules/objfmts/elf/elf-x86-x86.c
@@ -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) {
diff --git a/modules/objfmts/elf/elf.c b/modules/objfmts/elf/elf.c
index 807a3afe..01c2fa5b 100644
--- a/modules/objfmts/elf/elf.c
+++ b/modules/objfmts/elf/elf.c
@@ -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"));
diff --git a/modules/objfmts/elf/elf.h b/modules/objfmts/elf/elf.h
index a10b0b49..1fe18bd2 100644
--- a/modules/objfmts/elf/elf.h
+++ b/modules/objfmts/elf/elf.h
@@ -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,
diff --git a/modules/objfmts/elf/tests/gas32/elf_gas32_ssym.hex b/modules/objfmts/elf/tests/gas32/elf_gas32_ssym.hex
index a6fcecc4..61057e2f 100644
--- a/modules/objfmts/elf/tests/gas32/elf_gas32_ssym.hex
+++ b/modules/objfmts/elf/tests/gas32/elf_gas32_ssym.hex
@@ -334,7 +334,7 @@ ff
00
00
00
-10
+16
00
00
00
diff --git a/modules/objfmts/elf/tests/gas64/elf_gas64_ssym.hex b/modules/objfmts/elf/tests/gas64/elf_gas64_ssym.hex
index 698890fa..06e4c138 100644
--- a/modules/objfmts/elf/tests/gas64/elf_gas64_ssym.hex
+++ b/modules/objfmts/elf/tests/gas64/elf_gas64_ssym.hex
@@ -462,7 +462,7 @@ ff
00
00
00
-10
+16
00
00
00