Bug 2946 - jmp to a weak symbol jumps to a wrong address
Summary: jmp to a weak symbol jumps to a wrong address
Status: RESOLVED INVALID
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-07-20 19:38 UTC by Vincent Rivière
Modified: 2006-08-15 18:13 UTC (History)
1 user (show)

See Also:
Host: all
Target: i?86-linux, m68k-*-*
Build: all
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vincent Rivière 2006-07-20 19:38:24 UTC
Same bug on different platforms and versions of gas :
* gas 2.15 on i386-linux (Debian stable)
* gas 2.17 on i386-linux (Debian testing)
* cross-compiled gas 2.17 for target m68k-*-*
But NO BUG on Cygwin gas 2.16.91 20050610

The source : bug.s
        jmp     mylabel
        nop
        .weak mylabel
mylabel:
        nop

$ as bug.s -o bug.o
$ objdump -d bug.o

bug.o:     file format elf32-i386

Disassembly of section .text:

00000000 <mylabel-0x6>:
   0:   e9 fc ff ff ff          jmp    1 <mylabel-0x5>
   5:   90                      nop

00000006 <mylabel>:
   6:   90                      nop

The value of the jump is wrong.
It should be <mylabel>, bug it's <mylabel-0x5>
Comment 1 Alan Modra 2006-07-20 22:34:46 UTC
Not a bug.  Look at the relocs.
Comment 2 Vincent Rivière 2006-07-22 12:52:34 UTC
Sorry, you're right.
The jump is relocated.

But I'm very surprised.

Without the "weak" keyword, gas generates a relative jump and no relocation 
entry. Good.

With the "weak" keyword, gas generates an absolute jump and a relocation entry. 
In the special case described here, the jump and the weak symbol are in the 
same object file, so gas could generate a relative jump.

It seems that there is still a bug on m68k-*-netbsd (a.out format).

I'm going to post a detailed report.
Comment 3 Alan Modra 2006-07-22 13:00:15 UTC
No, gas should not resolve this branch.  There may be a strong symbol "mylabel"
in another file, in which case the branch should go to that symbol.
Comment 4 Vincent Rivière 2006-07-22 15:00:23 UTC
Here are detailed tests.

############################################################
# target i686-pc-cygwin ####################################
# gas 2.16.91 20050610 on host Windows XP SP2 ##############

$ as bug.s -o bug.o
$ objdump -d bug.o

bug.o:     file format pe-i386

Disassembly of section .text:

00000000 <.text>:
   0:   eb 01                   jmp    3 <.weak.mylabel.>
   2:   90                      nop

00000003 <.weak.mylabel.>:
   3:   90                      nop
   4:   90                      nop
        ...

$ objdump -r bug.o

bug.o:     file format pe-i386

$ ld bug.o -o bug
ld: warning: cannot find entry symbol _mainCRTStartup; defaulting to 00401000
$ objdump -d bug

bug:     file format pei-i386

Disassembly of section .text:

00401000 <__RUNTIME_PSEUDO_RELOC_LIST_END__>:
  401000:       eb 01                   jmp    401003 <.weak.mylabel.>
  401002:       90                      nop

00401003 <.weak.mylabel.>:
  401003:       90                      nop
  401004:       90                      nop
        ...

$ objdump -r bug

bug:     file format pei-i386


Everything is perfect here.
There is a short relative jump and no relocation.


############################################################
# target i386-pc-linux #####################################
# gas 2.17 on host Debian Sarge (stable) ###################

$ as bug.s -o bug.o
$ objdump -d bug.o

bug.o:     file format elf32-i386

Disassembly of section .text:

00000000 <mylabel-0x6>:
   0:   e9 fc ff ff ff          jmp    1 <mylabel-0x5>
   5:   90                      nop

00000006 <mylabel>:
   6:   90                      nop

$ objdump -r bug.o

bug.o:     file format elf32-i386

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
00000001 R_386_PC32        mylabel

$ ld bug.o -o bug
ld: warning: cannot find entry symbol _start; defaulting to 08048074
$ objdump -d bug

bug:     file format elf32-i386

Disassembly of section .text:

08048074 <mylabel-0x6>:
 8048074:       e9 01 00 00 00          jmp    804807a <mylabel>
 8048079:       90                      nop

0804807a <mylabel>:
 804807a:       90                      nop

$ objdump -r bug

bug:     file format elf32-i386


In this case, gas generates a long relative jump AND a 32-bit relocation.
I didn't see that detail on my first post.
In the object file, the value of the jump looks quite strange. It is -4, in 
fact the address to relocate relative to the instruction just after the jump. 
Maybe this behavior is required by the elf object format ?
Anyway, the relocation entry is here and right.
After linking, the relative jump has the correct value and the executable has 
no more relocation.
Even though it would be more optimal with a short jump and without a 
relocation, the result is perfectly correct.


############################################################
# target m68k-unknown-linux ################################
# gas 2.17 on host Debian Sarge (stable) ###################

$ as bug.s -o bug.o
$ objdump -d bug.o

bug.o:     file format elf32-m68k

Disassembly of section .text:

00000000 <mylabel-0x8>:
   0:   4ef9 0000 0000  jmp 0 <mylabel-0x8>
   6:   4e71            nop

00000008 <mylabel>:
   8:   4e71            nop

$ objdump -r bug.o

bug.o:     file format elf32-m68k

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
00000002 R_68K_32          mylabel

$ ld bug.o -o bug
ld: warning: cannot find entry symbol _start; defaulting to 80000074
$ objdump -d bug

bug:     file format elf32-m68k

Disassembly of section .text:

80000074 <mylabel-0x8>:
80000074:       4ef9 8000 007c  jmp 8000007c <mylabel>
8000007a:       4e71            nop

8000007c <mylabel>:
8000007c:       4e71            nop

$ objdump -r bug

bug:     file format elf32-m68k


Here, gas generates an absolute long jump and a 32-bit relocation.
The value of the jump and the relocation are correct.
The linked executable contains the right jump value.
There is no relocation in the final executable, I suppose that it's normal for 
that target.


############################################################
# target m68k-unknown-netbsd ###############################
# gas 2.17 on host Debian Sarge (stable) ###################

$ as bug.s -o bug.o
$ objdump -d bug.o

bug.o:     file format a.out-m68k-netbsd

Disassembly of section .text:

00000000 <mylabel-0x6>:
   0:   4efa 000a       jmp %pc@(c <mylabel+0x6>)
   4:   4e71            nop

00000006 <mylabel>:
   6:   4e71            nop

$ obj.netbsd/binutils/objdump -r bug.o

bug.o:     file format a.out-m68k-netbsd

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
00000002 DISP16            .text

$ ld bug.o -o bug
$ objdump -d bug

bug:     file format a.out-m68k-netbsd

Disassembly of section .text:

00002020 <bug.o>:
    2020:       4efa 000a       jmp %pc@(202c <__etext+0x4>)
    2024:       4e71            nop

00002026 <mylabel>:
    2026:       4e71            nop

00002028 <__etext>:
        ...

$ objdump -r bug

bug:     file format a.out-m68k-netbsd


This time, gas generates a 16-bit relative jump and a relocation.
The relocation in the object file seems to be bad : the offset is good (2) but 
the value is bogus (.text)
After linking, there is no more relocation, but the value of the jump is 
clearly bad (__etext+0x4 instead of mylabel).

If I remove the "weak" keyword in the source, everything becomes OK : there is 
still a 16-bit relative jump, but no relocation, and no bug.


############################################################
# Conclusion ###############################################

I compiled my test program on different targets with different file formats.
The generated jump was different every time : relative, absolute, short, long, 
without relocation, with relocation...
The final result was always correct except for m68k-unknown-netbsd.

m68k-unknown-netbsd seems broken in this very special case, I think that all 
m68k-*-aout targets may be affected.

Could someone check this and eventually reopen the bug ?

Vincent

PS: Alan: I've just read your Comment #3
Is it compatible with the results I obtained on Cygwin ?