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]

[PATCH v2 1/3] [BFD][COFF] Fix linker error when using NT weak externals


Lets take the following example:

a.c:
	void foo(void);

	int main()
	{
		foo();
			return 0;
	}

b.c:
	#include <stdio.h>

	void __attribute__((weak)) foo(void)
	{
		printf("%s weak\n", __func__);
	}

Compiling this with mingw will trigger the following linker error:

$ i686-w64-mingw32-gcc -o a.exe a.c b.c
/tmp/ccZ6Yw7O.o:a.c:(.text+0xc): undefined reference to `foo'
collect2: error: ld returned 1 exit status

Depending on the order in which a.c and b.c are linked the following
is happening in _bfd_generic_link_add_one_symbol:

1. If we link in a.c b.c order then foo will be added in as an
undefined symbol from a.c. Then it will be added as a weak undefined*
symbol from b.c (section undefined, flags BSF_WEAK) and the action
taken will be no action, i.e. keep the symbol undefined.

2. If we link in b.c a.c order then foo will first be added as an
undefined weak symbol from b.c. Then it will be added as undefined
from a.c and the action taken will be to make the symbol undefined.

To fix this issue, this patch checks for an weak external symbol when
doing relocations even if the symbol is undefined. In order to do so,
we also have to also populate the symbol_class and aux members when
adding a weak external symbol over an undefined or weak defined
symbol.

*In PE COFF case defined weak symbols are implemented as weak
externals which requires them to be seen as undefined (weak) symbols.

bfd/

2015-10-26  Octavian Purdila  <octavian.purdila@intel.com>

    * cofflink.c: Move weak external relocation code to a new function
    (_bfd_coff_relocate_weak_externals)
    * cofflink.c (_bfd_coff_generic_relocate_section): Check if we
    need to relocate a weak external even if the symbol is undefined
    * cofflink.c (coff_link_add_symbols): Fill in the class and aux
    when adding a weak external over an undefined or weakly defined
    symbol
---
 bfd/ChangeLog  | 10 +++++++++
 bfd/cofflink.c | 65 ++++++++++++++++++++++++++++++++--------------------------
 2 files changed, 46 insertions(+), 29 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index db6fe6b..75c98e5 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2015-10-26  Octavian Purdila  <octavian.purdila@intel.com>
+
+	* cofflink.c: Move weak external relocation code to a new function
+	(_bfd_coff_relocate_weak_externals)
+	* cofflink.c (_bfd_coff_generic_relocate_section): Check if we
+	need to relocate a weak external even if the symbol is undefined
+	* cofflink.c (coff_link_add_symbols): Fill in the class and aux
+	when adding a weak external over an undefined or weakly defined
+	symbol
+
 2015-10-05  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/18914
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 8d98fec..8f76b4d 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -426,7 +426,7 @@ coff_link_add_symbols (bfd *abfd,
   	      if (((*sym_hash)->symbol_class == C_NULL
   		   && (*sym_hash)->type == T_NULL)
   		  || sym.n_scnum != 0
-  		  || (sym.n_value != 0
+  		  || ((sym.n_value != 0 || IS_WEAK_EXTERNAL(abfd, sym))
   		      && (*sym_hash)->root.type != bfd_link_hash_defined
   		      && (*sym_hash)->root.type != bfd_link_hash_defweak))
   		{
@@ -2890,6 +2890,37 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
   return TRUE;
 }
 
+/* See _Microsoft Portable Executable and Common Object File Format
+   Specification_, section 5.5.3.  Note that weak symbols without aux records
+   are a GNU extension.
+
+   FIXME: All weak externals are treated as having characteristic
+   IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY (1).  These behave as per SVR4 ABI: A
+   library member will resolve a weak external only if a normal external causes
+   the library member to be linked.  See also linker.c:
+   generic_link_check_archive_element. */
+
+static void _bfd_coff_relocate_weak_externals(struct coff_link_hash_entry *h,
+					      bfd_vma *val, asection **sec)
+{
+  long aux_index = h->aux->x_sym.x_tagndx.l;
+  struct coff_tdata *cdata = h->auxbfd->tdata.coff_obj_data;
+  struct coff_link_hash_entry *h2 = cdata->sym_hashes[aux_index];
+
+  if (!h2 || h2->root.type == bfd_link_hash_undefined)
+    {
+      *sec = bfd_abs_section_ptr;
+      *val = 0;
+    }
+  else
+    {
+      *sec = h2->root.u.def.section;
+      *val = h2->root.u.def.value + (*sec)->output_section->vma +
+	      (*sec)->output_offset;
+    }
+}
+
+
 /* A basic reloc handling routine which may be used by processors with
    simple relocs.  */
 
@@ -2999,38 +3030,14 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
 	  else if (h->root.type == bfd_link_hash_undefweak)
 	    {
               if (h->symbol_class == C_NT_WEAK && h->numaux == 1)
-		{
-		  /* See _Microsoft Portable Executable and Common Object
-                     File Format Specification_, section 5.5.3.
-		     Note that weak symbols without aux records are a GNU
-		     extension.
-		     FIXME: All weak externals are treated as having
-		     characteristic IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY (1).
-		     These behave as per SVR4 ABI:  A library member
-		     will resolve a weak external only if a normal
-		     external causes the library member to be linked.
-		     See also linker.c: generic_link_check_archive_element. */
-		  struct coff_link_hash_entry *h2 =
-		    h->auxbfd->tdata.coff_obj_data->sym_hashes[
-		    h->aux->x_sym.x_tagndx.l];
-
-		  if (!h2 || h2->root.type == bfd_link_hash_undefined)
-		    {
-		      sec = bfd_abs_section_ptr;
-		      val = 0;
-		    }
-		  else
-		    {
-		      sec = h2->root.u.def.section;
-		      val = h2->root.u.def.value
-			+ sec->output_section->vma + sec->output_offset;
-		    }
-		}
+	        _bfd_coff_relocate_weak_externals(h, &val, &sec);
 	      else
                 /* This is a GNU extension.  */
 		val = 0;
 	    }
-
+	  else if (h->root.type == bfd_link_hash_undefined &&
+		   h->symbol_class == C_NT_WEAK && h->numaux == 1)
+	    _bfd_coff_relocate_weak_externals(h, &val, &sec);
 	  else if (! bfd_link_relocatable (info))
 	    {
 	      if (! ((*info->callbacks->undefined_symbol)
-- 
2.1.0


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