diff options
author | Alan Modra <amodra@gmail.com> | 2008-11-20 08:47:10 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2008-11-20 08:47:10 +0000 |
commit | d6e14abcef18288d8d0ec8e204c777611b58c19a (patch) | |
tree | 92b4bb5f0d959dbac8aba1d6fa0e8f119cc4b552 /bfd/elf32-ppc.c | |
parent | 63cb8e5fe546be8cdb6594822672c937e11f52ec (diff) | |
download | gdb-d6e14abcef18288d8d0ec8e204c777611b58c19a.zip gdb-d6e14abcef18288d8d0ec8e204c777611b58c19a.tar.gz gdb-d6e14abcef18288d8d0ec8e204c777611b58c19a.tar.bz2 |
* elf32-ppc.c (allocate_dynrelocs): Always use tlsld_got for
TLS_LD even when symbol is used with other TLS reloc types.
(ppc_elf_relocate_section): Bypass symbol checks when using tlsld_got.
Leave addend zero on LD DTPMOD dynamic reloc.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r-- | bfd/elf32-ppc.c | 82 |
1 files changed, 43 insertions, 39 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 83a9274..55348ae 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -5024,6 +5024,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) eh = (struct ppc_elf_link_hash_entry *) h; if (eh->elf.got.refcount > 0) { + bfd_boolean dyn; + unsigned int need; + /* Make sure this symbol is output as a dynamic symbol. */ if (eh->elf.dynindx == -1 && !eh->elf.forced_local @@ -5033,30 +5036,32 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return FALSE; } - if (eh->tls_mask == (TLS_TLS | TLS_LD) - && !eh->elf.def_dynamic) - { - /* If just an LD reloc, we'll just use htab->tlsld_got.offset. */ - htab->tlsld_got.refcount += 1; - eh->elf.got.offset = (bfd_vma) -1; - } - else + need = 0; + if ((eh->tls_mask & TLS_TLS) != 0) { - bfd_boolean dyn; - unsigned int need = 0; - if ((eh->tls_mask & TLS_TLS) != 0) + if ((eh->tls_mask & TLS_LD) != 0) { - if ((eh->tls_mask & TLS_LD) != 0) - need += 8; - if ((eh->tls_mask & TLS_GD) != 0) + if (!eh->elf.def_dynamic) + /* We'll just use htab->tlsld_got.offset. This should + always be the case. It's a little odd if we have + a local dynamic reloc against a non-local symbol. */ + htab->tlsld_got.refcount += 1; + else need += 8; - if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0) - need += 4; - if ((eh->tls_mask & TLS_DTPREL) != 0) - need += 4; } - else + if ((eh->tls_mask & TLS_GD) != 0) + need += 8; + if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0) + need += 4; + if ((eh->tls_mask & TLS_DTPREL) != 0) need += 4; + } + else + need += 4; + if (need == 0) + eh->elf.got.offset = (bfd_vma) -1; + else + { eh->elf.got.offset = allocate_got (htab, need); dyn = htab->elf.dynamic_sections_created; if ((info->shared @@ -5066,7 +5071,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { /* All the entries we allocated need relocs. Except LD only needs one. */ - if ((eh->tls_mask & TLS_LD) != 0) + if ((eh->tls_mask & TLS_LD) != 0 + && eh->elf.def_dynamic) need -= 4; htab->relgot->size += need * (sizeof (Elf32_External_Rela) / 4); } @@ -5302,27 +5308,24 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, for (; local_got < end_local_got; ++local_got, ++lgot_masks) if (*local_got > 0) { - if (*lgot_masks == (TLS_TLS | TLS_LD)) + unsigned int need = 0; + if ((*lgot_masks & TLS_TLS) != 0) { - /* If just an LD reloc, we'll just use - htab->tlsld_got.offset. */ - htab->tlsld_got.refcount += 1; - *local_got = (bfd_vma) -1; + if ((*lgot_masks & TLS_GD) != 0) + need += 8; + if ((*lgot_masks & TLS_LD) != 0) + htab->tlsld_got.refcount += 1; + if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0) + need += 4; + if ((*lgot_masks & TLS_DTPREL) != 0) + need += 4; } else + need += 4; + if (need == 0) + *local_got = (bfd_vma) -1; + else { - unsigned int need = 0; - if ((*lgot_masks & TLS_TLS) != 0) - { - if ((*lgot_masks & TLS_GD) != 0) - need += 8; - if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0) - need += 4; - if ((*lgot_masks & TLS_DTPREL) != 0) - need += 4; - } - else - need += 4; *local_got = allocate_got (htab, need); if (info->shared) htab->relgot->size += (need @@ -6587,7 +6590,8 @@ ppc_elf_relocate_section (bfd *output_bfd, /* Generate relocs for the dynamic linker. */ if ((info->shared || indx != 0) - && (h == NULL + && (offp == &htab->tlsld_got.offset + || h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) { @@ -6618,7 +6622,7 @@ ppc_elf_relocate_section (bfd *output_bfd, outrel.r_info = ELF32_R_INFO (indx, R_PPC_RELATIVE); else outrel.r_info = ELF32_R_INFO (indx, R_PPC_GLOB_DAT); - if (indx == 0) + if (indx == 0 && tls_ty != (TLS_TLS | TLS_LD)) { outrel.r_addend += relocation; if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL)) |