diff options
author | Charles Crayne <chuck@thor.crayne.org> | 2008-11-01 16:48:31 -0700 |
---|---|---|
committer | Charles Crayne <chuck@thor.crayne.org> | 2008-11-01 16:48:31 -0700 |
commit | 5fb6a39bc9b1f16f1223be448bb819e3424242db (patch) | |
tree | 992b91c2b85937be7f3d5ba140b279569f77c7f7 | |
parent | b6e36102e65814af1bc7cae8bed415c994563b05 (diff) | |
download | nasm-5fb6a39bc9b1f16f1223be448bb819e3424242db.tar.gz nasm-5fb6a39bc9b1f16f1223be448bb819e3424242db.tar.bz2 nasm-5fb6a39bc9b1f16f1223be448bb819e3424242db.zip |
ELF32 support for offset to IE GOT entry
Add new WRT type ..tlsie.
Generate R_386_TLS_IE relocation entries
for references to thread local variables.
-rw-r--r-- | output/outelf32.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/output/outelf32.c b/output/outelf32.c index 93af47d..7a7a904 100644 --- a/output/outelf32.c +++ b/output/outelf32.c @@ -39,6 +39,9 @@ enum reloc_type { R_386_RELATIVE = 8, /* ??? */ R_386_GOTOFF = 9, /* an offset from GOT base */ R_386_GOTPC = 10, /* a PC-relative offset _to_ GOT */ + R_386_TLS_TPOFF = 14, /* Offset in static TLS block */ + R_386_TLS_IE = 15, /* Address of GOT entry for static TLS + block offset */ /* These are GNU extensions, but useful */ R_386_16 = 20, /* A 16-bit absolute relocation */ R_386_PC16 = 21, /* A 16-bit PC-relative relocation */ @@ -287,12 +290,12 @@ void saa_wleb128s(struct SAA *, int); /* * Special section numbers which are used to define ELF special - * symbols, which can be used with WRT to provide PIC relocation - * types. + * symbols, which can be used with WRT to provide PIC and TLS + * relocation types. */ 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_sym_sect, elf_tlsie_sect; static void elf_init(FILE * fp, efunc errfunc, ldfunc ldef, evalfunc eval) { @@ -332,6 +335,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_elf32, error); + elf_tlsie_sect = seg_alloc(); + ldef("..tlsie", elf_tlsie_sect + 1, 0L, NULL, false, false, &of_elf32, + error); def_seg = seg_alloc(); } @@ -544,7 +550,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, "..tlsie")) error(ERR_NONFATAL, "unrecognised special symbol `%s'", name); return; } @@ -947,6 +953,9 @@ static void elf_out(int32_t segto, const void *data, elf_add_reloc(s, segment, R_386_GOTPC); } else if (wrt == elf_gotoff_sect + 1) { elf_add_reloc(s, segment, R_386_GOTOFF); + } else if (wrt == elf_tlsie_sect + 1) { + addr = elf_add_gsym_reloc(s, segment, addr, + R_386_TLS_IE, true); } else if (wrt == elf_got_sect + 1) { addr = elf_add_gsym_reloc(s, segment, addr, R_386_GOT32, true); |