summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2003-07-21 00:24:10 +0000
committerAlan Modra <amodra@bigpond.net.au>2003-07-21 00:24:10 +0000
commit23da08ec55f4cbc348d74933896ea7ca24936f3c (patch)
tree2db300896ad38ce70b7c8ac3091b5775e6fb31cb
parenteb9e06c95ec961bc07745dd33cf229574b0db87f (diff)
downloadbinutils-redhat-23da08ec55f4cbc348d74933896ea7ca24936f3c.tar.gz
* 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.
-rw-r--r--bfd/ChangeLog11
-rw-r--r--bfd/elf-bfd.h7
-rw-r--r--bfd/elf32-i386.c3
-rw-r--r--bfd/elf32-ppc.c11
-rw-r--r--bfd/elf64-ppc.c8
-rw-r--r--bfd/elf64-x86-64.c3
-rw-r--r--bfd/elflink.c49
7 files changed, 74 insertions, 18 deletions
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 <amodra@bigpond.net.au>
+
+ * 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 <hongjiu.lu@intel.com>
* 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;
+}