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]

[RFC PATCH 2/4] Fix relocations for NT weak external symbols


Relocations are currently broken for weak eternals. This can be
observed with 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-gcc -o a.exe a.c b.c
$ wine ./a.exe
Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00000000).
Register dump:
 CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b
 EIP:00000000 ESP:0061fd7c EBP:0061fd88 EFLAGS:00010202(  R- --  I   - - - )
 EAX:00000001 EBX:00000001 ECX:0061fd20 EDX:00115b50
 ESI:00113738 EDI:0000001d
Stack dump:
0x0061fd7c:  00401570 00000000 7b83a376 0061fe50
0x0061fd8c:  004013e2 00000001 00113738 00115b50
0x0061fd9c:  3b503f44 0061fe20 00000000 0061fdc8
0x0061fdac:  7bc854b1 cccccccc cccccccc cccccccc
0x0061fdbc:  cccccccc cccccccc cccccccc cccccccc
0x0061fdcc:  cccccccc 0061fdf0 7b8ae000 7b8263e1
000c: sel=0067 base=00000000 limit=00000000 32-bit r-x
Backtrace:
=>0 0x00000000 (0x0061fd88)
  1 0x004013e2 in a (+0x13e1) (0x0061fe50)
  2 0x7b85a75c call_process_entry+0xb() in kernel32 (0x0061fe68)

$ objdump -x a.exe
...
00401560 <_main>:
  401560:       55                      push   %ebp
  401561:       89 e5                   mov    %esp,%ebp
  401563:       83 e4 f0                and    $0xfffffff0,%esp
  401566:       e8 95 01 00 00          call   401700 <___main>
  40156b:       e8 90 ea bf ff          call   0 <_DeleteCriticalSection@4>
  401570:       b8 00 00 00 00          mov    $0x0,%eax
  401575:       c9                      leave
  401576:       c3                      ret
  401577:       90                      nop

00401578 <.weak._foo.>:
  401578:       55                      push   %ebp
  401579:       89 e5                   mov    %esp,%ebp
  40157b:       83 ec 18                sub    $0x18,%esp
  40157e:       c7 44 24 04 2d 40 40    movl   $0x40402d,0x4(%esp)
  401585:       00
  401586:       c7 04 24 24 40 40 00    movl   $0x404024,(%esp)
  40158d:       e8 b2 11 00 00          call   402744 <_printf>
  401592:       c9                      leave
  401593:       c3                      ret

Notice how if we change the link order things work as expected:

$ i686-w64-mingw32-gcc -o a.exe a.c b.c
$ objdump -x a.exe
...
00401560 <.weak._foo.>:
  401560:       55                      push   %ebp
  401561:       89 e5                   mov    %esp,%ebp
  401563:       83 ec 18                sub    $0x18,%esp
  401566:       c7 44 24 04 2d 40 40    movl   $0x40402d,0x4(%esp)
  40156d:       00
  40156e:       c7 04 24 24 40 40 00    movl   $0x404024,(%esp)
  401575:       e8 ca 11 00 00          call   402744 <_printf>
  40157a:       c9                      leave
  40157b:       c3                      ret

0040157c <_main>:
  40157c:       55                      push   %ebp
  40157d:       89 e5                   mov    %esp,%ebp
  40157f:       83 e4 f0                and    $0xfffffff0,%esp
  401582:       e8 79 01 00 00          call   401700 <___main>
  401587:       e8 d4 ff ff ff          call   401560 <.weak._foo.>
  40158c:       b8 00 00 00 00          mov    $0x0,%eax
  401591:       c9                      leave
  401592:       c3                      ret

This patch requires changes in both the gas coff generator and the
coff linker.

The first change is propagating the type of external weak symbols to
its .weak. counterpart symbol so that the linker can add the
.weak. counterpart symbol before processing the weak symbol
relocations (see the ISFCN() statement in _bfd_coff_link_input_bfd).

The second change is to fixup the symbol class and load the aux
information for weak externals. This is needed to relocate the NT weak
symbols in _bfd_coff_generic_relocate_section.

gas/

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

   * obj-coff.c (coff_frob_symbol): propagate the type of external
     weak symbol to its .weak. counterpart

bfd/

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

   * cofflink.c (coff_link_add_symbols): fixup the symbol class and
     load the aux information for weak externals
---
 bfd/ChangeLog         | 5 +++++
 bfd/cofflink.c        | 3 ++-
 gas/ChangeLog         | 5 +++++
 gas/config/obj-coff.c | 1 +
 4 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 3241ccd..e7b117c 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-22 Octavian Purdila <octavian.purdila@intel.com>
+
+	* cofflink.c (coff_link_add_symbols): fixup the symbol class and
+	load the aux information for weak externals
+
 2015-10-22  Octavian Purdila <octavian.purdila@intel.com>
 
 	* linker.c: update the link_action table to correctly deal with NT
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 8d98fec..7f539fa 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -428,7 +428,8 @@ coff_link_add_symbols (bfd *abfd,
   		  || sym.n_scnum != 0
   		  || (sym.n_value != 0
   		      && (*sym_hash)->root.type != bfd_link_hash_defined
-  		      && (*sym_hash)->root.type != bfd_link_hash_defweak))
+  		      && (*sym_hash)->root.type != bfd_link_hash_defweak)
+		  || (sym.n_sclass == C_NT_WEAK && sym.n_numaux == 1))
   		{
   		  (*sym_hash)->symbol_class = sym.n_sclass;
   		  if (sym.n_type != T_NULL)
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 2ece5c0..c7dafe4 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-22 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]