Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Jan 2017 20:54:24 +0100
From:      Roman Divacky <rdivacky@vlakno.cz>
To:        Mark Millard <markmi@dsl-only.net>
Cc:        Ed Maste <emaste@freebsd.org>, FreeBSD Toolchain <freebsd-toolchain@freebsd.org>
Subject:   Re: /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
Message-ID:  <20170117195424.GA89237@vlakno.cz>
In-Reply-To: <27422F1B-6906-4D37-860A-D1BC8DC83BBF@dsl-only.net>
References:  <EF97071B-AE4A-4520-A997-52249B8DAB5A@dsl-only.net> <20170112192223.GA49469@vlakno.cz> <932E3C38-B226-4BF1-B587-5A2D5EA19300@dsl-only.net> <F3923971-6FDF-4269-A7CA-3428249A128F@dsl-only.net> <20170116194035.GA20175@vlakno.cz> <2B1414C5-C56D-42F2-A1CB-4B1FE074667B@dsl-only.net> <43DBF7C7-6632-4906-BB37-FD00621AF857@dsl-only.net> <82402941-D1B2-4938-A43D-E21A390DE041@dsl-only.net> <F38C9607-5AB9-4BF9-BEC1-88EA2518A9CE@dsl-only.net> <27422F1B-6906-4D37-860A-D1BC8DC83BBF@dsl-only.net>

next in thread | previous in thread | raw e-mail | index | archive | help
Mark,

I wonder if it doesnt work because of my first patch (the one to turn GOT
reloc into PLT one).

LLD understands that we use GOT as TOC (which was true before my patch),
I wonder if something like this:

ndex: tools/lld/ELF/Target.cpp
===================================================================
--- tools/lld/ELF/Target.cpp	(revision 292071)
+++ tools/lld/ELF/Target.cpp	(working copy)
@@ -1070,7 +1070,8 @@
 }
 
 PPC64TargetInfo::PPC64TargetInfo() {
-  PltRel = GotRel = R_PPC64_GLOB_DAT;
+  GotRel = R_PPC64_GLOB_DAT;
+  PltRel = R_PPC64_JMP_SLOT;
   RelativeRel = R_PPC64_RELATIVE;
   GotEntrySize = 8;
   GotPltEntrySize = 8;
@@ -1099,7 +1100,7 @@
   // TOC starts where the first of these sections starts. We always create a
   // .got when we see a relocation that uses it, so for us the start is always
   // the .got.
-  uint64_t TocVA = In<ELF64BE>::Got->getVA();
+  uint64_t TocVA = In<ELF64BE>::Plt->getVA();
 
   // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
   // thus permitting a full 64 Kbytes segment. Note that the glibc startup


would make any difference? It's not correct but might shed some light on what needs to be done
if I am right.

Could you explore this please?

Thanks, Roman

On Mon, Jan 16, 2017 at 05:18:34PM -0800, Mark Millard wrote:
> I found some wording relating older-style .got to newer style .got/.got.plt
> pair of sections (that need not be near each other). . .
> 
> https://sourceware.org/ml/binutils/2004-03/msg00350.html
> 
> says that the .got has been split in two: in essence the RELRO part
> and the non-RELRO part. Quoting:
> 
> > .got.plt section contains the 3 reserved entries plus the GOT entries
> > corresponding to the .plt stubs.  The point of separating this from
> > .got (where this lived at the beginning of .got, i.e.
> > .got : ( *(.got.plt) *(.got) ) in the linker script) is to put the reminder
> > of .got to an area which can be write protected after relocation is
> > finished because it is constant after relocation is finished.  This is not
> > true for .got.plt, which is written to during lazy binding.
> 
> That fits with what I've read about the end result that involves .got.plt .
> 
> ===
> Mark Millard
> markmi at dsl-only.net
> 
> On 2017-Jan-16, at 3:39 PM, Mark Millard <markmi at dsl-only.net> wrote:
> 
> > [Correcting a poor wording/interpetatation.]
> > 
> > On 2017-Jan-16, at 3:28 PM, Mark Millard <markmi@dsl-only.net> wrote:
> > 
> >> Looking up definitions of the section naming
> >> (using http://www.cs.stevens.edu/~jschauma/810/elf.html ). . .
> >> (Intel context)
> >> 
> >> 
> >> It looks like the RELRO segment (program header information) requires
> >> the .got section to be with the .ctors, .dtros, .jcr and such sections:
> >> .got is supposed to be inside the RELRO region. ld.lld output was using
> >> RELRO. Quoting the description of RELRO:
> >> 
> >> GNU_RELRO:
> >> 
> >> This segment indicates the memory region which should be made Read-Only after relocation is done. This segment usually appears in a dynamic link library and it contains .ctors, .dtors, .dynamic, .got sections. See paragraph below.
> >> 
> >> BUT NOTE: The ld.lld output has .jcr section in the RELRO segment and the .dynamic just after it.
> > 
> > That "BUT NOTE" is wrong because both .dynamic and .got were empty and so are not really outside
> > the RELRO region: just at the boundary. If they had some positive size then the end of RELRO
> > would be after those sections start and would include their content.
> > 
> >> Showing the objdump output for RELRO:
> >> 
> >>  RELRO off    0x0000000000020000 vaddr 0x0000000010020000 paddr 0x0000000010020000 align 2**0
> >>        filesz 0x0000000000000138 memsz 0x0000000000000138 flags r--
> >> 
> >> .got.plt and .toc do not go in the RELRO segment.
> >> 
> >> 
> >> Quoting section descriptions. . .
> >> 
> >> 
> >> .rela.plt:
> >> 
> >> Runtime/Dynamic relocation table.
> >> This relocation table is similar to the one in .rela.dyn section; the difference is this one is for functions, not variables.
> >> 
> >> The relocation type of entries in this table is R_386_JMP_SLOT or R_X86_64_JUMP_SLOT and the "offset" refers to memory addresses which are inside .got.plt section.
> >> 
> >> Simply put, this table holds information to relocate entries in .got.plt section.
> >> 
> >> 
> >> .got:
> >> For dynamic binaries, this Global Offset Table holds the addresses of variables which are relocated upon loading.
> >> 
> >> [Note: .got was empty because of a lack of global variables. But it
> >> was still present.]
> >> 
> >> 
> >> .got.plt:
> >> 
> >> For dynamic binaries, this Global Offset Table holds the addresses of functions in dynamic libraries. They are used by trampoline code in .plt section. If .got.plt section is present, it contains at least three entries, which have special meanings.
> >> 
> >> 
> >> .toc:
> >> 
> >> Was not listed. (Likely powerpc64 and/or powerpc specific.)
> >> 
> >> 
> >> 
> >> So ld.lld is keeping the .got with the other RELRO materials,
> >> as it is supposed to.
> >> 
> >> And is setting up to allow lazy binding (.got.plt).
> >> 
> >> It did keep the non-RELRO materials .got.plt and .toc together.
> >> But .plt is off by itself, before both the RELRO segment and the
> >> .got.plt/.toc pair.
> >> 
> >> 
> >> 
> >> As far as I can tell the powerpc and powerpc64 FreeBSD code is
> >> not set up for any variation of such things.
> >> 
> >> It may be that changes are needed to allow RELRO with the .got
> >> inside, for example.
> >> 
> >> It is not obvious that disabling RELRO in ld.lld would change
> >> the order and contiguity in memory to what powerpc and powerpc64
> >> FreeBSD expect.
> > 
> > 
> > ===
> > Mark Millard
> > markmi at dsl-only.net
> 
> On 2017-Jan-16, at 2:32 PM, Mark Millard <markmi at dsl-only.net> wrote:
> 
> Here is a more direct list of section addresse rangess from gdb
> for ld.lld output:
> (I've added comments on the right.)
> 
> (gdb) info file
> Symbols from "/root/c_tests/a.out".
> Local exec file:
> 	`/root/c_tests/a.out', file type elf64-powerpc-freebsd.
> 	Entry point: 0x100300a0
> 	0x0000000010000270 - 0x0000000010000285 is .interp
> 	0x0000000010000288 - 0x00000000100002b8 is .note.tag
> 	0x00000000100002b8 - 0x00000000100002b9 is .rodata
> 	0x00000000100002bc - 0x00000000100002bc is .eh_frame
> 	0x00000000100002c0 - 0x0000000010000368 is .dynsym
> 	0x0000000010000368 - 0x0000000010000376 is .gnu.version
> 	0x0000000010000378 - 0x0000000010000398 is .gnu.version_r
> 	0x0000000010000398 - 0x00000000100003d8 is .hash
> 	0x00000000100003d8 - 0x000000001000041a is .dynstr
> 	0x0000000010000420 - 0x0000000010000468 is .rela.plt     <<<<<===== note
> 	0x0000000010000468 - 0x0000000010000474 is .eh_frame_hdr
> 	0x0000000010010000 - 0x00000000100104f8 is .text
> 	0x0000000010010500 - 0x000000001001052c is .init
> 	0x0000000010010530 - 0x0000000010010554 is .fini
> 	0x0000000010010560 - 0x00000000100105c0 is .plt          <<<<<===== NOTE!!!!
> 	0x0000000010020000 - 0x0000000010020010 is .ctors
> 	0x0000000010020010 - 0x0000000010020020 is .dtors
> 	0x0000000010020020 - 0x0000000010020028 is .jcr
> 	0x0000000010020028 - 0x0000000010020138 is .dynamic
> 	0x0000000010020138 - 0x0000000010020138 is .got          <<<<<===== NOTE!!!!
> 	0x0000000010030000 - 0x0000000010030019 is .data
> 	0x0000000010030020 - 0x0000000010030050 is .got.plt      <<<<<===== NOTE!!!!
> 	0x0000000010030050 - 0x00000000100300a0 is .toc          <<<<<===== NOTE!!!!
> 	0x00000000100300a0 - 0x0000000010030160 is .opd
> 	0x0000000010030160 - 0x0000000010030170 is .bss
> 
> It matches the readelf and objdump output reports.
> 
> ===
> Mark Millard
> markmi at dsl-only.net
> 
> On 2017-Jan-16, at 1:39 PM, Mark Millard <markmiat dsl-only.net> wrote:
> 
> > On 2017-Jan-16, at 11:40 AM, Roman Divacky <rdivacky at vlakno.cz> wrote:
> > 
> >> I think the TOC (.got + .plt) has to be contiguous in memory. The on-disk
> >> layout is not that important.
> > 
> > I showed the address column that I would expect to accurately reflect addresses
> > to load to in the process. I also showed the Offset Align which would be relative
> > to whatever base was used (even if different) as far as I can tell.
> > 
> > (Later in repsonse t your question I show what I expect is a sufficient
> > confirmation.)
> > 
> > Note: objdump and readelf agree (VMA and LMA). Here is the objdump
> > equivalent:
> > 
> > Sections:
> > Idx Name          Size      VMA               LMA               File off  Algn
> > . . .
> > 9 .rela.plt     00000048  0000000010000420  0000000010000420  00000420  2**3
> >               CONTENTS, ALLOC, LOAD, READONLY, DATA
> > . . .
> > 14 .plt          00000060  0000000010010560  0000000010010560  00010560  2**4
> >               CONTENTS, ALLOC, LOAD, READONLY, CODE
> > . . .
> > 19 .got          00000000  0000000010020138  0000000010020138  00020138  2**3
> >               CONTENTS, ALLOC, LOAD, DATA
> > . . .
> > 21 .got.plt      00000030  0000000010030020  0000000010030020  00030020  2**3
> >               CONTENTS, ALLOC, LOAD, DATA
> > 22 .toc          00000050  0000000010030050  0000000010030050  00030050  2**3
> >               CONTENTS, ALLOC, LOAD, DATA
> > . . .
> > 
> > 
> >> Can you check whats the difference of the in-memory TOC between lld and ld.bfd?
> > 
> > gdb reports agreement with the addresses listed by the likes of objdump for
> > the symbols it reports. There are examples from sections .note.tag, .eh_frame,
> > .ctors, .dtors, .jcr, .dynamic, .data, .pod, and .bss . None of these sections
> > move. So I expect the other sections do not move either.
> > 
> > Below I compare objdump symbols reporting to gdb reporting of what symbol is
> > at an address, at least one address for each one of those sections with a
> > symbol.
> > 
> > Here is what objdump shows for assigned symbols (sorted):
> > (I've inserted some comments about some other sections
> > that have no symbols based on the addresses from objdump
> > and readelf.)
> > 
> > 0000000010000288 l     O .note.tag      0000000000000018              abitag
> > 00000000100002a0 l     O .note.tag      0000000000000018              crt_noinit_tag
> > 00000000100002bb l     O .eh_frame      0000000000000004              __FRAME_END__
> > .rela.plt fits between here: 0000000010000420 (start)
> > .plt fits between here     : 0000000010010560 (start)
> > 0000000010020000 l     O .ctors 0000000000000008              __CTOR_LIST__
> > 0000000010020008 l     O .ctors 0000000000000008              __CTOR_END__
> > 0000000010020010 l     O .dtors 0000000000000008              __DTOR_LIST__
> > 0000000010020018 l     O .dtors 0000000000000008              __DTOR_END__
> > 0000000010020020 l     O .jcr   0000000000000000              __JCR_LIST__
> > 0000000010020020 l     O .jcr   0000000000000008              __JCR_END__
> > 0000000010020028 l       .dynamic       0000000000000000              .hidden _DYNAMIC
> > .got fits between here     : 0000000010020138 (start and end: size zero)
> > 0000000010030000 g     O .data  0000000000000008              __progname
> > 0000000010030008 l     O .data  0000000000000008              .hidden __dso_handle
> > 0000000010030010 l     O .data  0000000000000008              __do_global_dtors_aux.p
> > 0000000010030018 l     O .data  0000000000000001              __do_global_dtors_aux.completed
> > .got.plt fits between here : 0000000010030020 (start)
> > .toc fits between here     : 0000000010030050 (start)
> > 00000000100300a0 g     F .opd   0000000000000264              _start
> > 00000000100300b8 l     F .opd   00000000000000d0              finalizer
> > 00000000100300d0 l     F .opd   0000000000000000              .hidden _init
> > 00000000100300e8 l     F .opd   0000000000000000              .hidden _fini
> > 0000000010030100 l     F .opd   00000000000000a4              __do_global_dtors_aux
> > 0000000010030118 l     F .opd   000000000000007c              frame_dummy
> > 0000000010030130 g     F .opd   000000000000001c              main
> > 0000000010030148 l     F .opd   0000000000000088              __do_global_ctors_aux
> > 0000000010030160 g     O .bss   0000000000000008              __ps_strings
> > 0000000010030168 g     O .bss   0000000000000008              environ
> > 0000000010030170 g       *ABS*  0000000000000000              _end
> > 
> > Examples of gdb reporting symbol information for some of those addresses:
> > 
> > (gdb) info symbol 0x0000000010000288
> > abitag in section .note.tag
> > (gdb) info symbol 0x00000000100002a0
> > crt_noinit_tag in section .note.tag
> > (gdb) info symbol 0x00000000100002a4
> > crt_noinit_tag + 4 in section .note.tag
> > (gdb) info symbol 0x0000000010020008
> > __CTOR_END__ in section .ctors
> > (gdb) info symbol 0x0000000010020010
> > __DTOR_LIST__ in section .dtors
> > (gdb) info symbol 0x0000000010020020
> > __JCR_END__ in section .jcr
> > (gdb) info symbol 0x0000000010020028
> > _DYNAMIC in section .dynamic
> > (gdb) info symbol 0x0000000010030010
> > __do_global_dtors_aux.p in section .data
> > (gdb) info symbol 0x00000000100300a0
> > _start in section .opd
> > (gdb) info symbol 0x0000000010030130
> > main in section .opd
> > (gdb) info symbol 0x0000000010030160
> > __ps_strings in section .bss
> > 
> > ld.lld (as configured?) just does not set up for the sections to have
> > the property:
> > 
> > .got, .toc, .tocbss, .plt in that order
> > 
> > (in memory) and ld.lld (as configured?) puts out sections that ld.bfd
> > does not:
> > 
> > .got.plt
> > .toc
> > 
> > I'd guess that ld.lld has build-time and/or run-time configuration
> > requirements in order for its results to basically match what ld.bfd
> > does for the same input files --if it even can.
> > 
> ===
> Mark Millard
> markmi at dsl-only.net
> 
> On Fri, Jan 13, 2017 at 02:07:00PM -0800, Mark Millard wrote:
> > Just an FYI:
> > 
> > elfdump -a (from -r311950) does not dump .plt or .got.plt or .toc :
> > 
> > # elfdump -a a.out | egrep "(got|toc|plt|:$)" | more
> > elf header:
> > program header:
> > section header:
> >    sh_name: .rela.plt
> >    sh_name: .plt
> >    sh_name: .got
> >    sh_name: .got.plt
> >    sh_name: .toc
> > interp:
> > symbol table (.dynsym):
> > relocation with addend (.rela.plt):
> > dynamic:
> > global offset table:
> > symbol table (.symtab):
> > 
> > (The "global offset table" was empty but its title was listed.)
> > 
> > ===
> > Mark Millard
> > markmi at dsl-only.net
> > 
> > On 2017-Jan-12, at 5:58 PM, Mark Millard <markmi at dsl-only.net> wrote:
> > 
> > On 2017-Jan-12, at 11:22 AM, Roman Divacky <rdivacky at vlakno.cz> wrote:
> > 
> >> Can you check if the TOC is correct? LLD assumes this:
> >> 
> >> static uint64_t PPC64TocOffset = 0x8000;
> >> 
> >> uint64_t getPPC64TocBase() {
> >> // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The
> >> // TOC starts where the first of these sections starts. We always create a
> >> // .got when we see a relocation that uses it, so for us the start is always
> >> // the .got.
> >> uint64_t TocVA = In<ELF64BE>::Got->getVA();
> >> 
> >> // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
> >> // thus permitting a full 64 Kbytes segment. Note that the glibc startup
> >> // code (crt1.o) assumes that you can get from the TOC base to the
> >> // start of the .toc section with only a single (signed) 16-bit relocation.
> >> return TocVA + PPC64TocOffset;
> >> }
> > 
> > [I warn that I'm outside familiar territory here.]
> > 
> > If I understand the 1st comment right the following does not look
> > like a match for -fuse-dl=lld (readelf -a output):
> > 
> > Section Headers:
> > [Nr] Name              Type             Address           Offset
> >  Size              EntSize          Flags  Link  Info  Align
> > [ 0]                   NULL             0000000000000000  00000000
> >  0000000000000000  0000000000000000           0     0     0
> > . . .
> > [10] .rela.plt         RELA             0000000010000420  00000420
> >  0000000000000048  0000000000000018   A       5     0     8
> > . . .
> > [15] .plt              PROGBITS         0000000010010560  00010560
> >  0000000000000060  0000000000000000  AX       0     0     16
> > . . .
> > [20] .got              PROGBITS         0000000010020138  00020138
> >  0000000000000000  0000000000000000  WA       0     0     8
> > . . .
> > [22] .got.plt          PROGBITS         0000000010030020  00030020
> >  0000000000000030  0000000000000000  WA       0     0     8
> > . . .
> > [23] .toc              PROGBITS         0000000010030050  00030050
> >  0000000000000050  0000000000000000  WA       0     0     8
> > 
> > Possibly contributing reasons:
> > 
> > A) .got is not "first" of the 4 sections (by Address or by [Nr]).
> > (.got is listed as zero size as well)
> > B) There is no reference to .got.plt in the comment.
> > C) .got and .toc have .got.plt and other things between
> > -- and .got and .got.plt have stuff between.
> > D) There is no .tocbss at all (guess: optional so possibly okay).
> > E) .plt is before .got by address and by [Nr]
> > (it is als not next to .got or .got.plt or .toc).
> > F) There is no reference to .got.plt in the comment.
> > G) In general there are other things between the sections
> > making them spread over a wider address range.
> > 
> > [I guess that .rela.plt does not matter but I showed it
> > in case I'm wrong.]
> > 
> > Another potential issue is .plt being PROGBITS instead of
> > NOBITS (see below). Related is AX flags above vs. WA
> > flags below being a potential issue.
> > 
> > 
> > By contrast for -fuse-dl-bfd I see:
> > 
> > Section Headers:
> > [Nr] Name              Type             Address           Offset
> >  Size              EntSize          Flags  Link  Info  Align
> > [ 0]                   NULL             0000000000000000  00000000
> >  0000000000000000  0000000000000000           0     0     0
> > . . .
> > [ 8] .rela.plt         RELA             0000000010000370  00000370
> >  0000000000000048  0000000000000018   A       4    22     8
> > . . .
> > [21] .got              PROGBITS         0000000010010c48  00000c48
> >  0000000000000058  0000000000000008  WA       0     0     8
> > [22] .plt              NOBITS           0000000010010ca0  00000ca0
> >  0000000000000060  0000000000000018  WA       0     0     8
> > 
> > So no .toc or .tocbase sections.
> > 
> > But .got and .plt are next to each other with .got first
> > (by address and by [Nr]). This would fit the comments if
> > .toc and .tocbss are optional --and apparently they are.
> > 
> > So my guess is that -fuse-dl-bfd looks to be as expected,
> > unlike -fuse-dl=lld .
> > 
> > 
> >> Perhaps thats not true on FreeBSD? Especially the hardcoded constant seems suspicious.
> >> When it comes to the actual PLT entry, there's this comment in the code:
> >> 
> >> // FIXME: What we should do, in theory, is get the offset of the function
> >> // descriptor in the .opd section, and use that as the offset from %r2 (the
> >> // TOC-base pointer). Instead, we have the GOT-entry offset, and that will
> >> // be a pointer to the function descriptor in the .opd section. Using
> >> // this scheme is simpler, but requires an extra indirection per PLT dispatch.
> >> 
> >> So I think that while it's different it might not be wrong. What might be wrong
> >> is the TOC entry (either it's content or it's position).
> >> 
> >> I suspect there might be some Linux vs FreeBSD difference that prevents this from working.
> >> 
> >> Roman
> > 
> > ===
> > Mark Millard
> > markmi at dsl-only.net
> > 
> > On Thu, Jan 12, 2017 at 12:37:53AM -0800, Mark Millard wrote:
> >> 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
> > 
> > _______________________________________________
> > freebsd-toolchain@freebsd.org mailing list
> > https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
> > To unsubscribe, send any mail to "freebsd-toolchain-unsubscribe@freebsd.org"
> 
> _______________________________________________
> freebsd-toolchain@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
> To unsubscribe, send any mail to "freebsd-toolchain-unsubscribe@freebsd.org"
> 
> _______________________________________________
> freebsd-toolchain@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
> To unsubscribe, send any mail to "freebsd-toolchain-unsubscribe@freebsd.org"
> 
> _______________________________________________
> freebsd-toolchain@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
> To unsubscribe, send any mail to "freebsd-toolchain-unsubscribe@freebsd.org"
> 
> _______________________________________________
> freebsd-toolchain@freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
> To unsubscribe, send any mail to "freebsd-toolchain-unsubscribe@freebsd.org"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20170117195424.GA89237>