diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 845ae1da23..a5b33c884c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2003-07-21 Alan Modra + + * elf-bfd.h (SYMBOL_REFERENCES_LOCAL, SYMBOL_CALLS_LOCAL): Use.. + (_bfd_elf_symbol_refs_local_p): ..this. Declare. + * elflink.c (_bfd_elf_symbol_refs_local_p): New function. + * elf32-i386.c (elf_i386_relocate_section): Remove h NULL test + now done in _bfd_elf_symbol_refs_local_p. + * elf32-ppc.c (ppc_elf_relocate_section): Likewise. + * elf64-ppc.c (ppc64_elf_relocate_section): Likewise. + * elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise. + 2003-07-18 H.J. Lu * elflink.c (_bfd_elf_dynamic_symbol_p): Undo the last change. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 2fc64abb7e..2aa0c597e6 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -212,11 +212,11 @@ struct elf_link_hash_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) \ - !_bfd_elf_dynamic_symbol_p (H, INFO, 1) + _bfd_elf_symbol_refs_local_p (H, INFO, 0) /* Will _calls_ to this symbol always call the version in this object? */ #define SYMBOL_CALLS_LOCAL(INFO, H) \ - !_bfd_elf_dynamic_symbol_p (H, INFO, 0) + _bfd_elf_symbol_refs_local_p (H, INFO, 1) /* Records local symbols to be emitted in the dynamic symbol table. */ @@ -1498,6 +1498,9 @@ extern bfd_boolean _bfd_elf_link_sec_merge_syms extern bfd_boolean _bfd_elf_dynamic_symbol_p PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean)); +extern bfd_boolean _bfd_elf_symbol_refs_local_p + PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean)); + extern const bfd_target *bfd_elf32_object_p PARAMS ((bfd *)); extern const bfd_target *bfd_elf32_core_file_p diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 0ddd5078fc..60bccb8078 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -2338,8 +2338,7 @@ elf_i386_relocate_section (bfd *output_bfd, || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) && (r_type != R_386_PC32 - || (h != NULL - && !SYMBOL_CALLS_LOCAL (info, h)))) + || !SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index a2eec938b9..ebf9dc0589 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -5175,9 +5175,8 @@ ppc_elf_relocate_section (bfd *output_bfd, case R_PPC_REL14_BRNTAKEN: /* If these relocations are not to a named symbol, they can be handled right here, no need to bother the dynamic linker. */ - if (h == NULL - || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 - || SYMBOL_REFERENCES_LOCAL (info, h)) + if (SYMBOL_REFERENCES_LOCAL (info, h) + || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) break; /* fall through */ @@ -5207,8 +5206,7 @@ ppc_elf_relocate_section (bfd *output_bfd, || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) && (MUST_BE_DYN_RELOC (r_type) - || (h != NULL - && !SYMBOL_CALLS_LOCAL (info, h)))) + || !SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS && !info->shared && (input_section->flags & SEC_ALLOC) != 0 @@ -5263,8 +5261,7 @@ ppc_elf_relocate_section (bfd *output_bfd, if (skip) memset (&outrel, 0, sizeof outrel); - else if (h != NULL - && !SYMBOL_REFERENCES_LOCAL (info, h)) + else if (!SYMBOL_REFERENCES_LOCAL (info, h)) { unresolved_reloc = FALSE; outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 0334d84c9b..a052cd0d95 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -8159,8 +8159,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) && (MUST_BE_DYN_RELOC (r_type) - || (h != NULL - && !SYMBOL_CALLS_LOCAL (info, h)))) + || !SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL @@ -8206,8 +8205,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, if (skip) memset (&outrel, 0, sizeof outrel); - else if (h != NULL - && !SYMBOL_REFERENCES_LOCAL (info, h) + else if (!SYMBOL_REFERENCES_LOCAL (info, h) && !is_opd && r_type != R_PPC64_TOC) outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); @@ -8758,7 +8756,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd, s->_raw_size)) return FALSE; } - + return TRUE; } diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 542f83f5f1..09a072b5b8 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2015,8 +2015,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, && ((r_type != R_X86_64_PC8 && r_type != R_X86_64_PC16 && r_type != R_X86_64_PC32) - || (h != NULL - && !SYMBOL_CALLS_LOCAL (info, h)))) + || !SYMBOL_CALLS_LOCAL (info, h))) || (ELIMINATE_COPY_RELOCS && !info->shared && h != NULL diff --git a/bfd/elflink.c b/bfd/elflink.c index 2fd588ae11..322bb3d3fe 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2534,3 +2534,52 @@ _bfd_elf_dynamic_symbol_p (h, info, ignore_protected) us that it remains local. */ return !binding_stays_local_p; } + +/* Return true if the symbol referred to by H should be considered + to resolve local to the current module, and false otherwise. Differs + from (the inverse of) _bfd_elf_dynamic_symbol_p in the treatment of + undefined symbols and weak symbols. */ + +bfd_boolean +_bfd_elf_symbol_refs_local_p (h, info, local_protected) + struct elf_link_hash_entry *h; + struct bfd_link_info *info; + bfd_boolean local_protected; +{ + /* If it's a local sym, of course we resolve locally. */ + if (h == NULL) + return TRUE; + + /* If we don't have a definition in a regular file, then we can't + resolve locally. The sym is either undefined or dynamic. */ + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + return FALSE; + + /* Forced local symbols resolve locally. */ + if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0) + return TRUE; + + /* As do non-dynamic symbols. */ + if (h->dynindx == -1) + return TRUE; + + /* At this point, we know the symbol is defined and dynamic. In an + executable it must resolve locally, likewise when building symbolic + shared libraries. */ + if (info->executable || info->symbolic) + return TRUE; + + /* Now deal with defined dynamic symbols in shared libraries. Ones + with default visibility might not resolve locally. */ + if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) + return FALSE; + + /* However, STV_HIDDEN or STV_INTERNAL ones must be local. */ + if (ELF_ST_VISIBILITY (h->other) != STV_PROTECTED) + return TRUE; + + /* Function pointer equality tests may require that STV_PROTECTED + symbols be treated as dynamic symbols, even when we know that the + dynamic linker will resolve them locally. */ + return local_protected; +}