From: H.J. Lu Date: Sat, 8 Apr 2006 22:57:22 +0000 (+0000) Subject: 2006-04-08 H.J. Lu X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cb878726df95ae9effe3b5b06a519bf2f2786226;p=binutils-gdb.git 2006-04-08 H.J. Lu 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 67e9fd27da4..661bda42416 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2006-04-08 H.J. Lu + + 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. + 2006-04-07 Randolph Chung * elf64-hppa.c (elf64_hppa_grok_prstatus): New function. diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index bc44cba972c..754aa52254d 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; }