diff options
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r-- | bfd/elf32-ppc.c | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 69bb0d676e..1e1ab8cce3 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -147,27 +147,6 @@ static bfd_boolean ppc_elf_grok_psinfo #define TP_OFFSET 0x7000 #define DTP_OFFSET 0x8000 -/* Will references to this symbol always reference the symbol - in this object? STV_PROTECTED is excluded from the visibility test - here so that function pointer comparisons work properly. Since - function symbols not defined in an app are set to their .plt entry, - it's necessary for shared libs to also reference the .plt even - though the symbol is really local to the shared lib. */ -#define SYMBOL_REFERENCES_LOCAL(INFO, H) \ - ((! INFO->shared \ - || INFO->symbolic \ - || H->dynindx == -1 \ - || ELF_ST_VISIBILITY (H->other) == STV_INTERNAL \ - || ELF_ST_VISIBILITY (H->other) == STV_HIDDEN) \ - && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) - -/* Will _calls_ to this symbol always call the version in this object? */ -#define SYMBOL_CALLS_LOCAL(INFO, H) \ - ((! INFO->shared \ - || INFO->symbolic \ - || H->dynindx == -1 \ - || ELF_ST_VISIBILITY (H->other) != STV_DEFAULT) \ - && (H->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) /* The PPC linker needs to keep track of the number of relocs that it decides to copy as dynamic relocs in check_relocs for each symbol. @@ -1735,9 +1714,9 @@ ppc_elf_relax_section (abfd, isec, link_info, again) /* Get a copy of the native relocations. */ internal_relocs - = _bfd_elf32_link_read_relocs (abfd, isec, (PTR) NULL, - (Elf_Internal_Rela *) NULL, - link_info->keep_memory); + = _bfd_elf_link_read_relocs (abfd, isec, (PTR) NULL, + (Elf_Internal_Rela *) NULL, + link_info->keep_memory); if (internal_relocs == NULL) goto error_return; if (! link_info->keep_memory) @@ -2516,19 +2495,21 @@ ppc_elf_adjust_dynamic_symbol (info, h) { /* Clear procedure linkage table information for any symbol that won't need a .plt entry. */ - if (! htab->elf.dynamic_sections_created + if (h->plt.refcount <= 0 || SYMBOL_CALLS_LOCAL (info, h) - || h->plt.refcount <= 0) + || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + && h->root.type == bfd_link_hash_undefweak)) { /* A PLT entry is not required/allowed when: - 1. We are not using ld.so; because then the PLT entry - can't be set up, so we can't use one. + 1. We are not using ld.so; because then the PLT entry + can't be set up, so we can't use one. In this case, + ppc_elf_adjust_dynamic_symbol won't even be called. - 2. We know for certain that a call to this symbol - will go to this object. + 2. GC has rendered the entry unused. - 3. GC has rendered the entry unused. */ + 3. We know for certain that a call to this symbol + will go to this object, or will remain undefined. */ h->plt.offset = (bfd_vma) -1; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } @@ -2789,8 +2770,10 @@ allocate_dynrelocs (h, inf) else htab->got->_raw_size += 4; dyn = htab->elf.dynamic_sections_created; - if (info->shared - || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf)) + if ((info->shared + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf)) + && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT + || eh->elf.root.type != bfd_link_hash_undefweak)) { /* All the entries we allocated need relocs. */ htab->relgot->_raw_size @@ -2813,11 +2796,16 @@ allocate_dynrelocs (h, inf) defined in regular objects. For the normal shared case, discard space for relocs that have become local due to symbol visibility changes. */ + if (info->shared) { - if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 - && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 - || info->symbolic)) + /* Relocs that use pc_count are those that appear on a call insn, + or certain REL relocs (see MUST_BE_DYN_RELOC) that can be + generated via assembly. We want calls to protected symbols to + resolve directly to the function rather than going via the plt. + If people want function pointer comparisons to work as expected + then they should avoid writing weird assembly. */ + if (SYMBOL_CALLS_LOCAL (info, h)) { struct ppc_elf_dyn_relocs **pp; @@ -2831,6 +2819,12 @@ allocate_dynrelocs (h, inf) pp = &p->next; } } + + /* Also discard relocs on undefined weak syms with non-default + visibility. */ + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + && h->root.type == bfd_link_hash_undefweak) + eh->dyn_relocs = NULL; } else if (ELIMINATE_COPY_RELOCS) { @@ -3850,9 +3844,9 @@ ppc_elf_tls_optimize (obfd, info) int expecting_tls_get_addr; /* Read the relocations. */ - relstart = _bfd_elf32_link_read_relocs (ibfd, sec, (PTR) NULL, - (Elf_Internal_Rela *) NULL, - info->keep_memory); + relstart = _bfd_elf_link_read_relocs (ibfd, sec, (PTR) NULL, + (Elf_Internal_Rela *) NULL, + info->keep_memory); if (relstart == NULL) return FALSE; @@ -4793,7 +4787,10 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, } /* Generate relocs for the dynamic linker. */ - if (info->shared || indx != 0) + if ((info->shared || indx != 0) + && (h == NULL + || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak)) { outrel.r_offset = (htab->got->output_section->vma + htab->got->output_offset @@ -4995,12 +4992,12 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* Fall thru. */ if ((info->shared + && (h == NULL + || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak) && (MUST_BE_DYN_RELOC (r_type) || (h != NULL - && h->dynindx != -1 - && (!info->symbolic - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + && !SYMBOL_CALLS_LOCAL (info, h)))) || (ELIMINATE_COPY_RELOCS && !info->shared && (input_section->flags & SEC_ALLOC) != 0 |