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
This commit is contained in:
Peter Johnson 2008-02-21 08:57:23 +00:00
parent 40a06385d5
commit b49c080965
8 changed files with 74 additions and 18 deletions

View 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 {

View 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);

View file

@ -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) {

View 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) {

View 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"));

View 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,

View file

@ -334,7 +334,7 @@ ff
00
00
00
10
16
00
00
00

View file

@ -462,7 +462,7 @@ ff
00
00
00
10
16
00
00
00