This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

_bfd_elf_dynamic_symbol_p vs. _bfd_elf_symbol_refs_local_p


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]