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