_bfd_elf_dynamic_symbol_p vs. _bfd_elf_symbol_refs_local_p
Alan Modra
amodra@gmail.com
Sat Aug 28 09:25:00 GMT 2010
A patch committed on 2004-07-21 corrected _bfd_elf_symbol_refs_local_p's
treatment of common symbols. The same fix really should have been
applied to _bfd_elf_dynamic_symbol_p, as I do in the following patch.
This came up when I was looking at these two function to see whether
we can write _bfd_elf_dynamic_symbol_p as !_bfd_elf_symbol_refs_local_p.
It turns out you can't. The ia64 backend segfaults.
Inspecting _bfd_elf_dynamic_symbol_p, we can see the result boils down
to
!(h == NULL
|| h->dynindx == -1
|| h->forced_local
|| ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
|| ELF_ST_VISIBILITY (h->other) == STV_HIDDEN)
&& (!h->def_regular && !ELF_COMMON_DEF_P (h))
|| !(info->executable
|| SYMBOLIC_BIND (info, h)
|| (ELF_ST_VISIBILITY (h->other) != STV_PROTECTED
&& (!not_local_protected
|| !bed->is_function_type (h->type)))))
or simplifying a little
!(h == NULL
|| h->dynindx == -1
|| h->forced_local
|| ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
|| ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
|| ((ELF_COMMON_DEF_P (h)
|| h->def_regular)
&& (info->executable
|| SYMBOLIC_BIND (info, h)
|| (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED
&& (!bed->is_function_type (h->type)
|| !not_local_protected)))))
whereas _bfd_elf_symbol_refs_local_p is
(h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
|| ELF_ST_VISIBILITY (h->other) == STV_INTERNAL
|| ((ELF_COMMON_DEF_P (h)
|| h->def_regular)
&& (h->forced_local
|| h->dynindx == -1
|| info->executable
|| SYMBOLIC_BIND (info, h)
|| (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED
&& (!bed->is_function_type (h->type)
|| local_protected)))))
So the only real difference is where forced_local and dynindx are
tested. When either of these tests are true, dynamic_p will say the
symbol is local, while refs_local_p only says so for defined symbols.
Non-weak undefined symbols that don't turn out to be dynamic generally
cause a link error so the difference there doesn't matter, but
undefined weaks are allowed and for them it's possible that both
predicates return false.
* elflink.c (_bfd_elf_dynamic_symbol_p): Rename param. Make
common syms local.
(_bfd_elf_symbol_refs_local_p): Expand comment.
(elf_link_output_extsym): Fix style nit.
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.376
diff -u -p -r1.376 elflink.c
--- bfd/elflink.c 25 Aug 2010 20:35:58 -0000 1.376
+++ bfd/elflink.c 28 Aug 2010 00:56:12 -0000
@@ -2770,7 +2770,7 @@ _bfd_elf_link_sec_merge_syms (struct elf
bfd_boolean
_bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
struct bfd_link_info *info,
- bfd_boolean ignore_protected)
+ bfd_boolean not_local_protected)
{
bfd_boolean binding_stays_local_p;
const struct elf_backend_data *bed;
@@ -2809,7 +2809,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_li
/* Proper resolution for function pointer equality may require
that these symbols perhaps be resolved dynamically, even though
we should be resolving them to the current module. */
- if (!ignore_protected || !bed->is_function_type (h->type))
+ if (!not_local_protected || !bed->is_function_type (h->type))
binding_stays_local_p = TRUE;
break;
@@ -2818,7 +2818,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_li
}
/* If it isn't defined locally, then clearly it's dynamic. */
- if (!h->def_regular)
+ if (!h->def_regular && !ELF_COMMON_DEF_P (h))
return TRUE;
/* Otherwise, the symbol is dynamic if binding rules don't tell
@@ -2829,7 +2829,15 @@ _bfd_elf_dynamic_symbol_p (struct elf_li
/* 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. */
+ undefined symbols. The two functions are vitually identical except
+ for the place where forced_local and dynindx == -1 are tested. If
+ either of those tests are true, _bfd_elf_dynamic_symbol_p will say
+ the symbol is local, while _bfd_elf_symbol_refs_local_p will say
+ the symbol is local only for defined symbols.
+ It might seem that _bfd_elf_dynamic_symbol_p could be rewritten as
+ !_bfd_elf_symbol_refs_local_p, except that targets differ in their
+ treatment of undefined weak symbols. For those that do not make
+ undefined weak symbols dynamic, both functions may return false. */
bfd_boolean
_bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
@@ -8635,7 +8643,7 @@ elf_link_output_extsym (struct elf_link_
ignore_undef = bed->elf_backend_ignore_undef_symbol (h);
/* If we are reporting errors for this situation then do so now. */
- if (ignore_undef == FALSE
+ if (!ignore_undef
&& h->ref_dynamic
&& (!h->ref_regular || finfo->info->gc_sections)
&& ! elf_link_check_versioned_symbol (finfo->info, bed, h)
--
Alan Modra
Australia Development Lab, IBM
More information about the Binutils
mailing list