aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-i386.c
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2008-07-28 18:07:05 +0000
committerAlexandre Oliva <aoliva@redhat.com>2008-07-28 18:07:05 +0000
commit9f03412ac677d4f228026de9174c23a4bc47dd74 (patch)
treed1bcbd579987a05ff60fb13cbdc695b18fb11c62 /bfd/elf32-i386.c
parent7f4b89d1b63f8ba812b911639f264b8e7ff51285 (diff)
downloadgdb-9f03412ac677d4f228026de9174c23a4bc47dd74.zip
gdb-9f03412ac677d4f228026de9174c23a4bc47dd74.tar.gz
gdb-9f03412ac677d4f228026de9174c23a4bc47dd74.tar.bz2
bfd/ChangeLog:
* elf32-i386.c (struct elf_i386_link_hash_table): Added field tls_module_base. (elf_i386_link_hash_table_create): Initialize it. (elf_i386_always_size_sections): Set it. (set_tls_module_base): New. (elf_i386_relocate_sections): Call it. * elf64-x86-64.c (struct elf64_x86_64_link_hash_table): Added field tls_module_base. (elf64_x86_64_link_hash_table_create): Initialize it. (elf64_x86_64_always_size_sections): Set it. (set_tls_module_base): New. (elf64_x86_64_relocate_sections): Call it. Reported by Cary Coutant <ccoutant@google.com> ld/testsuite/ChangeLog: * ld-i386/tlsbindesc.dd: Adjust incorrect expectations for LD to LE relaxation. * ld-x86-64/tlsbindesc.dd: Likewise. * ld-i386/tlsbindesc.rd: Adjust address of _TLS_MODULE_BASE_. * ld-x86-64/tlsbindesc.rd: Likewise. Reported by Cary Coutant <ccoutant@google.com>
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r--bfd/elf32-i386.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 578f595..9e96e21 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -692,6 +692,9 @@ struct elf_i386_link_hash_table
/* Small local sym to section mapping cache. */
struct sym_sec_cache sym_sec;
+
+ /* _TLS_MODULE_BASE_ symbol. */
+ struct bfd_link_hash_entry *tls_module_base;
};
/* Get the i386 ELF linker hash table from a link_info structure. */
@@ -767,6 +770,7 @@ elf_i386_link_hash_table_create (bfd *abfd)
ret->is_vxworks = 0;
ret->srelplt2 = NULL;
ret->plt0_pad_byte = 0;
+ ret->tls_module_base = NULL;
return &ret->elf.root;
}
@@ -2431,6 +2435,9 @@ elf_i386_always_size_sections (bfd *output_bfd,
tls_sec, 0, NULL, FALSE,
bed->collect, &bh)))
return FALSE;
+
+ elf_i386_hash_table (info)->tls_module_base = bh;
+
tlsbase = (struct elf_link_hash_entry *)bh;
tlsbase->def_regular = 1;
tlsbase->other = STV_HIDDEN;
@@ -2475,6 +2482,27 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
return TRUE;
}
+/* _TLS_MODULE_BASE_ needs to be treated especially when linking
+ executables. Rather than setting it to the beginning of the TLS
+ section, we have to set it to the end. This function may be called
+ multiple times, it is idempotent. */
+
+static void
+set_tls_module_base (struct bfd_link_info *info)
+{
+ struct bfd_link_hash_entry *base;
+
+ if (!info->executable)
+ return;
+
+ base = elf_i386_hash_table (info)->tls_module_base;
+
+ if (!base)
+ return;
+
+ base->u.def.value = elf_hash_table (info)->tls_size;
+}
+
/* Return the base VMA address which should be subtracted from real addresses
when resolving @dtpoff relocation.
This is PT_TLS segment p_vaddr. */
@@ -2536,6 +2564,8 @@ elf_i386_relocate_section (bfd *output_bfd,
&& !strcmp (input_section->output_section->name,
".tls_vars"));
+ set_tls_module_base (info);
+
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)