mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
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:
parent
40a06385d5
commit
b49c080965
8 changed files with 74 additions and 18 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ ff
|
|||
00
|
||||
00
|
||||
00
|
||||
10
|
||||
16
|
||||
00
|
||||
00
|
||||
00
|
||||
|
|
|
|||
|
|
@ -462,7 +462,7 @@ ff
|
|||
00
|
||||
00
|
||||
00
|
||||
10
|
||||
16
|
||||
00
|
||||
00
|
||||
00
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue