/usr/bin/ld.lld on powerpc64: produces a.out for which: ld-elf.so.1: assert failed: /usr/src/libexec/rtld-elf/powerpc64/reloc.c:374
Mark Millard
markmi at dsl-only.net
Thu Jan 12 08:38:03 UTC 2017
On 2017-Jan-11, at 1:23 PM, Ed Maste <emaste at freebsd.org> wrote:
> On 11 January 2017 at 21:06, Roman Divacky <rdivacky at vlakno.cz> wrote:
>> Looks like a progress :) Three questions...
>>
>> Is the readelf -a reasonable now?
>
> FYI, I just committed an ELF Tool Chain fix (r311941) so readelf
> should display the relocation types properly now.
Thanks. I updated to -r311950 to pick this up.
>> If you compile with -g, does the
>> backtrace make a bit more sense? And finally, can you try to "nexti/stepi" in gdb from
>> _start to see where things go wrong? Possibly doing it both for ld linked a.out
>> and lld linked a.out and compare where things differ.
I had compiled with -g. It never gets to main. . .
# /usr/local/bin/gdb a.out
. . .
Reading symbols from a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x1001045c: file main.c, line 3.
Starting program: /root/c_tests/a.out
Program received signal SIGSEGV, Segmentation fault.
0x000000001001056c in ?? ()
Note that the temporary breakpoint is never hit.
(gdb) bt
#0 0x000000001001056c in ?? ()
#1 0x00000000100100d8 in ?? ()
#2 0x00000000500279b0 in ._rtld_start () at /usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:104
Backtrace stopped: frame did not save the PC
(gdb) up 2
#2 0x00000000500279b0 in ._rtld_start () at /usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:104
104 blrl /* _start(argc, argv, envp, obj, cleanup, ps_strings) */
(gdb) disass
Dump of assembler code for function ._rtld_start:
0x0000000050027930 <+0>: stdu r1,-144(r1)
0x0000000050027934 <+4>: std r3,96(r1)
0x0000000050027938 <+8>: std r4,104(r1)
0x000000005002793c <+12>: std r5,112(r1)
0x0000000050027940 <+16>: std r8,136(r1)
0x0000000050027944 <+20>: bl 0x50027950 <._rtld_start+32>
0x0000000050027948 <+24>: .long 0x0
0x000000005002794c <+28>: .long 0x30e40
0x0000000050027950 <+32>: mflr r3
0x0000000050027954 <+36>: ld r4,0(r3)
0x0000000050027958 <+40>: add r3,r4,r3
0x000000005002795c <+44>: ld r4,-32768(r2)
0x0000000050027960 <+48>: subf r4,r4,r2
0x0000000050027964 <+52>: bl 0x50027c64 <reloc_non_plt_self>
0x0000000050027968 <+56>: nop
0x000000005002796c <+60>: ld r4,104(r1)
0x0000000050027970 <+64>: addi r3,r4,-8
0x0000000050027974 <+68>: addi r4,r1,128
0x0000000050027978 <+72>: addi r5,r1,120
0x000000005002797c <+76>: bl 0x50028608 <_rtld>
0x0000000050027980 <+80>: nop
0x0000000050027984 <+84>: ld r2,8(r3)
0x0000000050027988 <+88>: ld r11,16(r3)
0x000000005002798c <+92>: ld r3,0(r3)
0x0000000050027990 <+96>: mtlr r3
0x0000000050027994 <+100>: ld r3,96(r1)
0x0000000050027998 <+104>: ld r4,104(r1)
0x000000005002799c <+108>: ld r5,112(r1)
0x00000000500279a0 <+112>: ld r6,120(r1)
0x00000000500279a4 <+116>: ld r7,128(r1)
0x00000000500279a8 <+120>: ld r8,136(r1)
0x00000000500279ac <+124>: blrl
=> 0x00000000500279b0 <+128>: li r0,1
0x00000000500279b4 <+132>: sc
0x00000000500279b8 <+136>: nop
0x00000000500279bc <+140>: nop
End of assembler dump.
So setting a breakpoint at 0x00000000500279ac and
trying again:
(gdb) run
Starting program: /root/c_tests/a.out
Breakpoint 3, ._rtld_start () at /usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:104
104 blrl /* _start(argc, argv, envp, obj, cleanup, ps_strings) */
(gdb) info registers
r0 0x50027980 1342339456
r1 0xffffffffffffdaf0 18446744073709542128
r2 0x10028138 268599608
r3 0x1 1
r4 0xffffffffffffdbb8 18446744073709542328
r5 0xffffffffffffdbc8 18446744073709542344
r6 0x5004c000 1342488576
r7 0x50058b30 1342540592
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0x20000000 536870912
r13 0x50057010 1342533648
r14 0x0 0
r15 0x0 0
r16 0x0 0
r17 0x0 0
r18 0x0 0
r19 0x0 0
r20 0x0 0
r21 0x0 0
r22 0x0 0
r23 0x0 0
r24 0x0 0
r25 0x0 0
r26 0x0 0
r27 0x0 0
r28 0x0 0
r29 0x0 0
r30 0x0 0
r31 0x0 0
pc 0x500279ac 0x500279ac <._rtld_start+124>
msr <unavailable>
cr 0x22000c00 570428416
lr 0x10010000 0x10010000
ctr 0x50043a80 1342454400
xer 0x20000000 536870912
(gdb) stepi
0x0000000010010000 in ?? ()
and that is effectively at ._start .
NOTE: There is no ._start name in the disassembly
listed by objdump.
By contrast for -fuse-ld=bfd building a.out objdump shows:
0000000010000438 <._start> mflr r0
000000001000043c <._start+0x4> mfcr r12
0000000010000440 <._start+0x8> std r31,-8(r1)
0000000010000444 <._start+0xc> std r0,16(r1)
0000000010000448 <._start+0x10> stw r12,8(r1)
000000001000044c <._start+0x14> stdu r1,-176(r1)
. . .
In gdb for ld.lld used:
Reading symbols from a.out...done.
(gdb) br *0x00000000500279ac
Breakpoint 1 at 0x500279ac
(gdb) run
Starting program: /root/c_tests/a.out
Breakpoint 1, ._rtld_start () at /usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:104
104 blrl /* _start(argc, argv, envp, obj, cleanup, ps_strings) */
(gdb) stepi
0x0000000010010000 in ?? ()
(gdb)
0x0000000010010004 in ?? ()
(gdb) display/i $pc
1: x/i $pc
=> 0x10010004: mfcr r12
(gdb) stepi
0x0000000010010008 in ?? ()
1: x/i $pc
=> 0x10010008: std r31,-8(r1)
(gdb)
0x000000001001000c in ?? ()
1: x/i $pc
=> 0x1001000c: std r0,16(r1)
. . .
(gdb)
0x00000000100100a0 in ?? ()
1: x/i $pc
=> 0x100100a0: beq 0x100100ac
(gdb)
0x00000000100100ac in ?? ()
1: x/i $pc
=> 0x100100ac: cmpldi r8,0
(gdb)
0x00000000100100b0 in ?? ()
1: x/i $pc
=> 0x100100b0: beq 0x100100c0
(gdb)
0x00000000100100c0 in ?? ()
1: x/i $pc
=> 0x100100c0: addis r3,r2,0
(gdb)
0x00000000100100c4 in ?? ()
1: x/i $pc
=> 0x100100c4: ld r3,32552(r3)
(gdb)
0x00000000100100c8 in ?? ()
1: x/i $pc
=> 0x100100c8: cmpldi r3,0
(gdb)
0x00000000100100cc in ?? ()
1: x/i $pc
=> 0x100100cc: beq 0x100100e0
(gdb)
0x00000000100100d0 in ?? ()
1: x/i $pc
=> 0x100100d0: mr r3,r7
(gdb)
0x00000000100100d4 in ?? ()
1: x/i $pc
=> 0x100100d4: bl 0x10010560
Note: Below is from plt :
Disassembly of section .plt:
0000000010010560 <.plt> std r2,40(r1)
0000000010010564 <.plt+0x4> addis r11,r2,0
0000000010010568 <.plt+0x8> ld r12,32512(r11)
000000001001056c <.plt+0xc> ld r11,0(r12) <<<<<===== Fails here.
0000000010010570 <.plt+0x10> mtctr r11
0000000010010574 <.plt+0x14> ld r2,8(r12)
0000000010010578 <.plt+0x18> ld r11,16(r12)
000000001001057c <.plt+0x1c> bctr
(By setting breakpoints in the 3 such .plt code blocks:
this is the first .plt code block executed and it fails.)
The .plt is different from what ld.bfd generates:
no __glink_PLTresolve or its use and the code does
not appear strictly equivalent to me.
Back to gdb based information:
(gdb) info registers
r0 0x500279b0 1342339504
r1 0xffffffffffffda40 18446744073709541952
r2 0x10028138 268599608
r3 0x50058b30 1342540592
r4 0x0 0
r5 0xffffffffffffdbc8 18446744073709542344
r6 0x5004c000 1342488576
r7 0x50058b30 1342540592
r8 0x0 0
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0x22000c00 570428416
r13 0x50057010 1342533648
r14 0x0 0
r15 0x0 0
r16 0x0 0
r17 0x0 0
r18 0x0 0
r19 0x0 0
r20 0x0 0
r21 0x0 0
r22 0x0 0
r23 0x0 0
r24 0x0 0
r25 0x10028138 268599608
r26 0x0 0
r27 0x0 0
r28 0x1 1
r29 0xffffffffffffdbb8 18446744073709542328
r30 0xffffffffffffdbc8 18446744073709542344
r31 0xffffffffffffda40 18446744073709541952
pc 0x10010560 0x10010560
msr <unavailable>
cr 0x42000c00 1107299328
lr 0x100100d8 0x100100d8
ctr 0x50043a80 1342454400
xer 0x20000000 536870912
(gdb)
0x0000000010010560 in ?? ()
1: x/i $pc
=> 0x10010560: std r2,40(r1)
(gdb)
0x0000000010010564 in ?? ()
1: x/i $pc
=> 0x10010564: addis r11,r2,0
(gdb)
0x0000000010010568 in ?? ()
1: x/i $pc
=> 0x10010568: ld r12,32512(r11)
(gdb)
0x000000001001056c in ?? ()
1: x/i $pc
=> 0x1001056c: ld r11,0(r12)
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0x000000001001056c in ?? ()
1: x/i $pc
=> 0x1001056c: ld r11,0(r12)
The source code (from lib/csu/powerpc64/crt1.c ) is:
void
_start(int argc, char **argv, char **env,
const struct Struct_Obj_Entry *obj __unused, void (*cleanup)(void),
struct ps_strings *ps_strings)
{
handle_argv(argc, argv, env);
if (ps_strings != (struct ps_strings *)0)
__ps_strings = ps_strings;
if (&_DYNAMIC != NULL)
atexit(cleanup);
else
_init_tls();
#ifdef GCRT
atexit(_mcleanup);
monstartup(&eprol, &etext);
#endif
handle_static_init(argc, argv, env);
exit(main(argc, argv, env));
}
The 3 plt code blocks are for:
atexit
_init_tls
exit
from what I can tell, possibly not in that order.
Overall: The plt handling seems to be broken.
> You can also build rtld with additional debugging by adding -DDEBUG to
> CFLAGS. In libexec/rtld-elf/Makefile there's an example command line
> for building it locally, but I've just added CFLAGS+=-DDEBUG to the
> Makefile in my test tree and built it along with the rest of my full
> cross build.
# svnlite diff /usr/src/libexec/rtld-elf/Makefile
Index: /usr/src/libexec/rtld-elf/Makefile
===================================================================
--- /usr/src/libexec/rtld-elf/Makefile (revision 311950)
+++ /usr/src/libexec/rtld-elf/Makefile (working copy)
@@ -17,6 +17,7 @@
malloc.c xmalloc.c debug.c libmap.c
MAN= rtld.1
CSTD?= gnu99
+CFLAGS+=-DDEBUG
CFLAGS+= -Wall -DFREEBSD_ELF -DIN_RTLD -ffreestanding
CFLAGS+= -I${SRCTOP}/lib/csu/common
.if exists(${.CURDIR}/${MACHINE_ARCH})
The above did not seem to make much of a difference for the
code involved, likely because crt1.c is from
lib/csu/powerpc64/ instead of from libexec/rtld-elf/ .
===
Mark Millard
markmi at dsl-only.net
More information about the freebsd-toolchain
mailing list