diff options
author | Charles Crayne <chuck@thor.crayne.org> | 2008-10-26 17:32:38 -0700 |
---|---|---|
committer | Charles Crayne <chuck@thor.crayne.org> | 2008-10-26 17:32:38 -0700 |
commit | 10a863d87e2ed8e93b681c886c2d2e1c799d4a48 (patch) | |
tree | 65a5cf23b14c38fe2d55eddb41b20d986b32657d /output/outelf64.c | |
parent | b0e0718267c13f49971b23d56eae65863de58d40 (diff) | |
download | nasm-10a863d87e2ed8e93b681c886c2d2e1c799d4a48.tar.gz |
ELF64 support for PC relative offset to IE GOT entry
Add new WRT type ..gottpoff.
Generate R_X86_64_GOTTPOFF relocation entries
for references to thread local variables.
Diffstat (limited to 'output/outelf64.c')
-rw-r--r-- | output/outelf64.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/output/outelf64.c b/output/outelf64.c index 891f25a5..d2bf3c47 100644 --- a/output/outelf64.c +++ b/output/outelf64.c @@ -335,6 +335,7 @@ void dwarf64_findsect(const int); static int32_t elf_gotpc_sect, elf_gotoff_sect; static int32_t elf_got_sect, elf_plt_sect; static int32_t elf_sym_sect; +static int32_t elf_gottpoff_sect; static void elf_init(FILE * fp, efunc errfunc, ldfunc ldef, evalfunc eval) { @@ -373,6 +374,9 @@ static void elf_init(FILE * fp, efunc errfunc, ldfunc ldef, evalfunc eval) elf_sym_sect = seg_alloc(); ldef("..sym", elf_sym_sect + 1, 0L, NULL, false, false, &of_elf64, error); + elf_gottpoff_sect = seg_alloc(); + ldef("..gottpoff", elf_gottpoff_sect + 1, 0L, NULL, false, false, &of_elf64, + error); def_seg = seg_alloc(); @@ -587,7 +591,7 @@ static void elf_deflabel(char *name, int32_t segment, int64_t offset, */ if (strcmp(name, "..gotpc") && strcmp(name, "..gotoff") && strcmp(name, "..got") && strcmp(name, "..plt") && - strcmp(name, "..sym")) + strcmp(name, "..sym") && strcmp(name, "..gottpoff")) error(ERR_NONFATAL, "unrecognised special symbol `%s'", name); return; } @@ -776,7 +780,6 @@ static void elf_deflabel(char *name, int32_t segment, int64_t offset, * If TLS segment, mark symbol accordingly. */ if (sects[sym->section - 1]->flags & SHF_TLS) { - error(ERR_DEBUG, "marked %s as TLS",name); sym->type &= 0xf0; sym->type |= STT_TLS; } @@ -1028,7 +1031,7 @@ static void elf_out(int32_t segto, const void *data, } else if (wrt == elf_gotoff_sect + 1) { if (size != 8) { error(ERR_NONFATAL, "ELF64 requires ..gotoff " - "references to be qword absolute"); + "references to be qword"); } else { elf_add_reloc(s, segment, addr, R_X86_64_GOTOFF64); addr = 0; @@ -1129,6 +1132,10 @@ static void elf_out(int32_t segto, const void *data, wrt == elf_got_sect + 1) { error(ERR_NONFATAL, "ELF64 requires ..gotoff references to be " "qword absolute"); + } else if (wrt == elf_gottpoff_sect + 1) { + elf_add_gsym_reloc(s, segment, addr+size, size, + R_X86_64_GOTTPOFF, true); + addr = 0; } else { error(ERR_NONFATAL, "ELF64 format does not support this" " use of WRT"); @@ -1156,7 +1163,10 @@ static void elf_out(int32_t segto, const void *data, } else if (wrt == elf_gotoff_sect + 1 || wrt == elf_got_sect + 1) { error(ERR_NONFATAL, "ELF64 requires ..gotoff references to be " - "qword absolute"); + "absolute"); + } else if (wrt == elf_gottpoff_sect + 1) { + error(ERR_NONFATAL, "ELF64 requires ..gottpoff references to be " + "dword"); } else { error(ERR_NONFATAL, "ELF64 format does not support this" " use of WRT"); |