diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2006-04-08 22:57:22 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2006-04-08 22:57:22 +0000 |
commit | cb878726df95ae9effe3b5b06a519bf2f2786226 (patch) | |
tree | be50e49bc285bc8cee79690a5aecdfbcd903add9 /bfd/elf32-i386.c | |
parent | 07c5f590ae27c60e498282c40414f6c77dccc39a (diff) | |
download | gdb-cb878726df95ae9effe3b5b06a519bf2f2786226.zip gdb-cb878726df95ae9effe3b5b06a519bf2f2786226.tar.gz gdb-cb878726df95ae9effe3b5b06a519bf2f2786226.tar.bz2 |
2006-04-08 H.J. Lu <hongjiu.lu@intel.com>
PR ld/2513
* elf32-i386.c (GOT_TLS_MASK): New macro for tls_type.
(GOT_TLS_IE_IE): Likewise.
(GOT_TLS_IE_GD): Likewise.
(GOT_TLS_IE_MASK): Likewise.
(elf_i386_check_relocs): For global symbols, set GOT_TLS_IE_GD
and GOT_TLS_IE_IE for R_386_TLS_GD and R_386_TLS_IE
respectively.
(allocate_dynrelocs): If both GOT_TLS_IE_IE and GOT_TLS_IE_GD
are set, treat tls_type as GOT_TLS_IE_BOTH.
(elf_i386_relocate_section): Likewise.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index bc44cba..754aa52 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -582,6 +582,10 @@ struct elf_i386_link_hash_entry #define GOT_TLS_IE_NEG 6 #define GOT_TLS_IE_BOTH 7 #define GOT_TLS_GDESC 8 +#define GOT_TLS_MASK 0x0f +#define GOT_TLS_IE_IE 0x10 +#define GOT_TLS_IE_GD 0x20 +#define GOT_TLS_IE_MASK 0x30 #define GOT_TLS_GD_BOTH_P(type) \ ((type) == (GOT_TLS_GD | GOT_TLS_GDESC)) #define GOT_TLS_GD_P(type) \ @@ -1007,12 +1011,25 @@ elf_i386_check_relocs (bfd *abfd, case R_386_TLS_IE_32: if (ELF32_R_TYPE (rel->r_info) == r_type) tls_type = GOT_TLS_IE_NEG; + else if (h + && ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) + /* If this is a GD->IE transition, we may use either + of R_386_TLS_TPOFF and R_386_TLS_TPOFF32. But if + we may have both R_386_TLS_IE and R_386_TLS_GD, + we can't share the same R_386_TLS_TPOFF since + they require different offsets. So we remember + it comes from R_386_TLS_GD. */ + tls_type = GOT_TLS_IE | GOT_TLS_IE_GD; else - /* If this is a GD->IE transition, we may use either of - R_386_TLS_TPOFF and R_386_TLS_TPOFF32. */ tls_type = GOT_TLS_IE; break; case R_386_TLS_IE: + if (h) + { + /* We remember it comes from R_386_TLS_IE. */ + tls_type = GOT_TLS_IE_POS | GOT_TLS_IE_IE; + break; + } case R_386_TLS_GOTIE: tls_type = GOT_TLS_IE_POS; break; } @@ -1052,7 +1069,8 @@ elf_i386_check_relocs (bfd *abfd, tls_type |= old_tls_type; /* If a TLS symbol is accessed using IE at least once, there is no point to use dynamic model for it. */ - else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN + else if (old_tls_type != tls_type + && old_tls_type != GOT_UNKNOWN && (! GOT_TLS_GD_ANY_P (old_tls_type) || (tls_type & GOT_TLS_IE) == 0)) { @@ -1682,6 +1700,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) asection *s; bfd_boolean dyn; int tls_type = elf_i386_hash_entry(h)->tls_type; + + /* If we have both R_386_TLS_IE and R_386_TLS_GD, GOT_TLS_IE_BOTH + should be used. */ + if ((tls_type & GOT_TLS_IE_MASK) + == (GOT_TLS_IE_IE | GOT_TLS_IE_GD)) + tls_type = GOT_TLS_IE_BOTH; + else + tls_type &= GOT_TLS_MASK; /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ @@ -2685,6 +2711,13 @@ elf_i386_relocate_section (bfd *output_bfd, else if (h != NULL) { tls_type = elf_i386_hash_entry(h)->tls_type; + /* If we have both R_386_TLS_IE and R_386_TLS_GD, + GOT_TLS_IE_BOTH should be used. */ + if ((tls_type & GOT_TLS_IE_MASK) + == (GOT_TLS_IE_IE | GOT_TLS_IE_GD)) + tls_type = GOT_TLS_IE_BOTH; + else + tls_type &= GOT_TLS_MASK; if (!info->shared && h->dynindx == -1 && (tls_type & GOT_TLS_IE)) r_type = R_386_TLS_LE_32; } |