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 2/3] [BFD/GAS] Relocate aux entries for NT weak externals


Currently the tagndx for NT weak externals are not relocated when
creating a relocatable object which breaks relocations when doing the
final link of the relocatable object.

For 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__);
            }

$ i686-w64-mingw32-ld -r -o r.o a.o b.o

This is how the symbol table looks for b.o:

$ i686-w64-mingw32-objdump -x b.o | grep -A 1 foo
[ 23](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 .weak._foo.
[ 24](sec  0)(fl 0x00)(ty  20)(scl 105) (nx 1) 0x00000000 _foo

And this is how the symbol table table looks for r.o:

$ i686-w64-mingw32-objdump -x r.o | grep -A 1 foo
[ 45](sec  0)(fl 0x00)(ty  20)(scl 105) (nx 1) 0x00000000 _foo
AUX lnno 1 size 0x0 tagndx 23
...
[ 48](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 .weak._foo.

As you can see the AUX entry for _foo is wrong in r.o, it should be 48
but it is 23.

The patch uses the sym_indices array to relocate the AUX entries for
weak externals in _bfd_coff_link_input_bfd.

In order to do so we need the .weak. counterpart symbol to be loaded
before the weak external symbol. This is prevented by by the ISFCN()
check _bfd_coff_link_input_bfd and is caused by the fact that the AUX
entry type is 0. To fix this issue we patch gas to propagate the type
of external weak symbols to its .weak. counterpart symbol.

Note that we perform the AUX tag relocations only int the case of
relocatable output because weak external relocation handling
(_bfd_coff_generic_relocate_section) uses the tagndx relative to the
input object.

bfd/

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

    * cofflink.c (_bfd_coff_link_input_bfd): relocate AUX entries for
    weak externals when generating relocatable objects

gas/

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

    * obj-coff.c (coff_frob_symbol): propagate the type of external
    weak symbol to its .weak. counterpart
---
 bfd/ChangeLog         |  5 +++++
 bfd/cofflink.c        | 14 +++++++++++---
 gas/ChangeLog         |  5 +++++
 gas/config/obj-coff.c |  1 +
 4 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 75c98e5..10dc476 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,10 @@
 2015-10-26  Octavian Purdila  <octavian.purdila@intel.com>
 
+	* cofflink.c (_bfd_coff_link_input_bfd): relocate AUX entries for
+	weak externals when generating relocatable objects
+
+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
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 8f76b4d..f9b591a 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -1944,7 +1944,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
       if ((*indexp < 0
 	   || (bfd_size_type) *indexp < syment_base)
 	  && (*sym_hash == NULL
-	      || (*sym_hash)->auxbfd != input_bfd))
+	      || (*sym_hash)->auxbfd != input_bfd)
+	  && isymp->n_sclass != C_NT_WEAK)
 	esym += add * isymesz;
       else
 	{
@@ -2014,8 +2015,15 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
 		      auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
 		    }
 		}
-	      else if ((isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
-		       && isymp->n_sclass != C_NT_WEAK)
+	      else if (isymp->n_sclass == C_NT_WEAK)
+	        {
+		    long *tagndx = &auxp->x_sym.x_tagndx.l;
+
+		    if (bfd_link_relocatable (flaginfo->info) &&
+			flaginfo->sym_indices[*tagndx] > 0)
+		      *tagndx = flaginfo->sym_indices[*tagndx];
+		}
+	      else if (isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
 		{
 		  unsigned long indx;
 
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 2ece5c0..48eaa9e 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-26 Octavian Purdila  <octavian.purdila@intel.com>
+
+	* obj-coff.c (coff_frob_symbol): propagate the type of external
+	weak symbol to its .weak. counterpart
+
 2015-10-02  Renlin Li <renlin.li@arm.com>
 
 	* config/tc-aarch64.c (s_tlsdescadd): New.
diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c
index c0a3f1f..ac2310c 100644
--- a/gas/config/obj-coff.c
+++ b/gas/config/obj-coff.c
@@ -1277,6 +1277,7 @@ coff_frob_symbol (symbolS *symp, int *punt)
 					   symbol_get_value_expression (weakp));
 	      symbol_set_frag (symp, symbol_get_frag (weakp));
 	      S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp));
+	      S_SET_DATA_TYPE (symp, S_GET_DATA_TYPE (weakp));
 	    }
 	  else
 	    {
-- 
2.1.0


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