Bug in gas generating sh PIC, or is it me?
Graeme Peterson
gp@qnx.com
Fri Nov 29 15:33:00 GMT 2002
Hi, all.
I think I may have found a bug in the sh PIC stuff in gas. Or I may have
a bug in the QNX sh-nto support. Not sure which, and so this e-mail. ;-)
Basically it looks like an "off by 2" bug to me. If I have a source
file which I compile PIC into a shared object, any function calls from
that shared object into other PIC code blows up. I can call from main()
into the shared object fine if the .so does not call any other PIC
code, like printf(), or other functions in the same .so.
I think the following assembly gets converted to values that are 2 bigger
than they used to be with binutils-2.10.1:
.long bar@PLT+.-2-.L4
This causes a 'bsrf r8' to jump one instruction too far into the .plt, and try
to use a register that has had it's initialization skipped.
If I hex edit either the .o or the .so and reduce the appropriate value by 2,
then things work.
I have spent some time trying to boot strap the sh-linux tools from the
head branch, and have so far succeeded with binutils, and failed with gcc,
so I have only been able to check this in the .o, which does not tell me
all I need to know. If someone can check this out, that would be great.
Any and all input appreciated. Details below.
Oh, and I have spent some time stepping through .libs/as-new, and have not yet
found where that instruction gets converted into the data value in question.
Anyone?
;-)
Thanks, as always. Now back to single stepping as-new in gdb...
Cheers.
GP
--------------------------
Consider the following source (foo.c):
void bar(void)
{
return;
}
void foo(void)
{
bar();
return;
}
Stepping through it on sh-qnx-nto, I see that the call into 'bar' from 'foo'
looks like (objdump -d libfoo.so):
000004c0 <foo>:
...
...
4d2: 08 d2 mov.l 4f4 <foo+0x34>,r2 ! 0xffffff8c
4d4: 23 68 mov r2,r8
4d6: 03 08 bsrf r8
...
...
4f4: 8c ff .word 0xff8c
4f6: ff ff .word 0xffff
This ultimately results in 'bsrf r8' jumping to
<_do_global_ctors_aux+114>, which is in the .plt, but one instruction too
far (466, below). It should be going to <_do_global_ctors_aux+112> (464, below):
000003f4 <__do_global_ctors_aux>:
..
..
00000448 <.plt>:
..
..
464: 04 d0 mov.l 478 <__do_global_ctors_aux+0x84>,r0 ! 0xc
466: ce 00 mov.l @(r0,r12),r0
468: 2b 40 jmp @r0
46a: 09 00 nop
My gcc-2.95.3 generates the following assembly, which looks like valid assembly,
so it coming from an older gcc version should not matter (I think):
.file "foo.c"
.little
gcc2_compiled.:
.text
.align 5
.global bar
.type bar,@function
bar:
mov.l r14,@-r15
mov r15,r14
bra .L2
nop
.align 5
.L2:
mov r14,r15
mov.l @r15+,r14
rts
nop
.Lfe1:
.size bar,.Lfe1-bar
.align 5
.global foo
.type foo,@function
foo:
mov.l r8,@-r15
mov.l r12,@-r15
mov.l r14,@-r15
sts.l pr,@-r15
mova .L5,r0
mov.l .L5,r12
add r0,r12
mov r15,r14
mov r15,r1
mov.l .L6,r2
mov r2,r8
bsrf r8
.L4:
nop
bra .L3
nop
.align 5
.L3:
mov r14,r15
lds.l @r15+,pr
mov.l @r15+,r14
mov.l @r15+,r12
mov.l @r15+,r8
rts
nop
.L7:
.align 2
.L5:
.long _GLOBAL_OFFSET_TABLE_
.L6:
.long bar@PLT+.-2-.L4
.Lfe2:
.size foo,.Lfe2-foo
.ident "GCC: (GNU) 2.95.3 20010315 (release)"
Then I assemble it into foo.o as follows:
as --defsym __PIC__=1 -pic -little foo.s -o foo.o
The '-pic' arg for 2.10.1 only.
With binutils 2.10.1 the line after '.L6:' ends up as a data value that is smaller by 2
than it is with 2.12.1 or the current head branch.
objdump -d foo.o (See below "74: 1c 00" is the line that
fails. "74: 1a 00" works):
foo.o: file format elf32-shl
Disassembly of section .text:
00000000 <bar>:
0: e6 2f mov.l r14,@-r15
2: f3 6e mov r15,r14
4: 0c a0 bra 20 <bar+0x20>
6: 09 00 nop
8: 09 00 nop
a: 09 00 nop
c: 09 00 nop
e: 09 00 nop
10: 09 00 nop
12: 09 00 nop
14: 09 00 nop
16: 09 00 nop
18: 09 00 nop
1a: 09 00 nop
1c: 09 00 nop
1e: 09 00 nop
20: e3 6f mov r14,r15
22: f6 6e mov.l @r15+,r14
24: 0b 00 rts
26: 09 00 nop
28: 09 00 nop
2a: 09 00 nop
2c: 09 00 nop
2e: 09 00 nop
30: 09 00 nop
32: 09 00 nop
34: 09 00 nop
36: 09 00 nop
38: 09 00 nop
3a: 09 00 nop
3c: 09 00 nop
3e: 09 00 nop
00000040 <foo>:
40: 86 2f mov.l r8,@-r15
42: c6 2f mov.l r12,@-r15
44: e6 2f mov.l r14,@-r15
46: 22 4f sts.l pr,@-r15
48: 09 c7 mova 70 <foo+0x30>,r0
4a: 09 dc mov.l 70 <foo+0x30>,r12 ! 0x0
4c: 0c 3c add r0,r12
4e: f3 6e mov r15,r14
50: f3 61 mov r15,r1
52: 08 d2 mov.l 74 <foo+0x34>,r2 ! 0x1c
54: 23 68 mov r2,r8
56: 03 08 bsrf r8
58: 09 00 nop
5a: 01 a0 bra 60 <foo+0x20>
5c: 09 00 nop
5e: 09 00 nop
60: e3 6f mov r14,r15
62: 26 4f lds.l @r15+,pr
64: f6 6e mov.l @r15+,r14
66: f6 6c mov.l @r15+,r12
68: f6 68 mov.l @r15+,r8
6a: 0b 00 rts
6c: 09 00 nop
6e: 09 00 nop
70: 00 00 .word 0x0000
72: 00 00 .word 0x0000
74: 1c 00 .word 0x001c
76: 00 00 .word 0x0000
78: 09 00 nop
7a: 09 00 nop
7c: 09 00 nop
7e: 09 00 nop
Thanks to anyone who gets this far!
GP
More information about the Binutils
mailing list