Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 Jan 2017 15:19:47 -0800
From:      Mark Millard <markmi@dsl-only.net>
To:        Roman Divacky <rdivacky@vlakno.cz>
Cc:        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:  <DF5A46F0-4EFC-4E4A-81D1-7F8972BCF6E7@dsl-only.net>
In-Reply-To: <401EB857-2C19-4CC3-A9F1-8353759B51F5@dsl-only.net>
References:  <27422F1B-6906-4D37-860A-D1BC8DC83BBF@dsl-only.net> <20170117195424.GA89237@vlakno.cz> <237EB920-0795-4B18-94D4-2EAC0FC76F01@dsl-only.net> <20170117215613.GA95258@vlakno.cz> <45D0BB1C-490A-4809-BAB1-F4E552FECEDD@dsl-only.net> <20170118215420.GA65399@vlakno.cz> <9023794B-0999-4F50-95DE-2D4156BC6E75@dsl-only.net> <DDC0F517-C606-402C-80D0-BE3C941D97CB@dsl-only.net> <545CE5A1-9E7F-46C0-8355-0C32B60D1C72@dsl-only.net> <278EB6CA-6A04-43D6-A9F2-84FF11A367C7@dsl-only.net> <20170119200530.GA58089@vlakno.cz> <41DE5AA2-5794-4BE6-8BDD-C3C7C84F9C83@dsl-only.net> <401EB857-2C19-4CC3-A9F1-8353759B51F5@dsl-only.net>

next in thread | previous in thread | raw e-mail | index | archive | help
FYI: The code that is put in the .plt that does not
match the .got.plt layout used (expecting function
descriptors when there are only single addresses per
function as a .got.plt entry) is:

void PPC64TargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
                               uint64_t PltEntryAddr, int32_t Index,
                               unsigned RelOff) const {
  uint64_t Off =3D GotEntryAddr - getPPC64TocBase();

  // 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.
 =20
  write32be(Buf,      0xf8410028);                   // std %r2, 40(%r1)
  write32be(Buf + 4,  0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, =
X@ha
  write32be(Buf + 8,  0xe98b0000 | applyPPCLo(Off)); // ld %r12, =
X@l(%r11)
  write32be(Buf + 12, 0xe96c0000);                   // ld %r11,0(%r12)
  write32be(Buf + 16, 0x7d6903a6);                   // mtctr %r11
  write32be(Buf + 20, 0xe84c0008);                   // ld %r2,8(%r12)
  write32be(Buf + 24, 0xe96c0010);                   // ld %r11,16(%r12)
  write32be(Buf + 28, 0x4e800420);                   // bctr
}

Either the .got.plt entry layout changes to have room
for 8(r12) and 16(r12) positions (size change to 0x18
Bytes per entryr) or this code (and possibly other
code) changes --presuming .got.plt style is used at
all. (I've not found any powerpc family documentation
for .got.plt use.)

Unlike what the comment says this code does not reference
the .opd section at all as things are right now. See the
prior Email content below for the details as in the
example used. It references the .got.plt and the .toc
section via r12 in the example (the size mismatch
from the layout mismatch).


=3D=3D=3D
Mark Millard
markmi at dsl-only.net

On 2017-Jan-20, at 12:54 AM, Mark Millard <markmi at dsl-only.net> =
wrote:

> I did a bunch more investigation and have 4 major points
> that I think I've established:
>=20
> First off: I've still not found a single example
> of a document's coverage of powerpc64 (or powerpc) that
> deals with the .got vs. .got.plt split [.got in RELRO region
> but .got.plt possibly not (lazy relocation then allowed)].
> Everything that I have found is specific to Intel architecture
> for that split. There may be no defined powerpc64 ABI that uses
> .got.plt. If so then ld.lld's use of .got.plt for powerpc64 may
> be an ABI violation (for all powerpc64 ABIs).
>=20
> Secondly: The (nonppc) references that I've found indicate
> that RELRO+-PIE+-fPIE sorts of contexts for .got.plt usage.
> .got.plt may be in the RELRO region if lazy relocation
> is t be disallowed but .got.plt is not in the RELRO
> region when lazy relocation is allowed. I've not
> found references to .got.plt for when there is no RELRO.
> Nor when there is no PIE.
>=20
> Thirdly: a.out from ld.lld is not using function
> descriptors or its 3 fields. The .plt is blocks
> of code and the relocated addresses are in the
> .got.plt --without room for the function
> descriptors. /usr/src/libexec/rtld-elf/powerpc64/reloc.c
> has no code for the ld.lld .plt / .got.plt pairing
> that ld.lld outputs in a.out, not in the likes of its
> reloc_jmpslots, reloc_jmpslot, or reloc_plt. reloc.c
> is trashing memory by putting function descriptor
> content in place when it should not from what I can
> tell.
>=20
> Fourthly: Got is correct and the GotPlt and Plt
> alternatives are wrong for in uint64_t getPPC64TocBase() .
> (Sorry I sent you in the wrong direction for this area.)
>=20
> The rest of this note is related the "fourthly" and
> "thirdly" above but is only relevant if more detail
> is wanted.
>=20
>=20
> I deal with "fourthly" first. . .
>=20
> I was wrong about Got vs. Plt vs. GotPlt in:
>=20
> uint64_t getPPC64TocBase()
>=20
> as for as what the code should reference: I've solid
> evidence that Got is correct. One part of that is
> what I'll present here as it should be sufficient:
>=20
> Got stops during /usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:104 =
called code
> Plt stops during /usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:83 =
called code
> GotPlt stops during =
/usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:83 called code
>=20
> The Got case executed the rtld_start.S:83 related code correctly
> and later fails. (I've traced relevant code under gdb.)
>=20
> So the below is based on analyzing the Got variant.
>=20
>=20
> Now for "thirdly" (lack of function descriptors in .plt). . .
>=20
> A ld.bfd vs. ld.lld difference is the r_offset differences
> are smaller in ld.bfd and larger in ld.lld and the relocations are
> in different sections: a.out from ld.lld is not using function
> descriptors or its 3 fields. . .
>=20
> For ld.bfd's generated a.out:
>=20
> Relocation section with addend (.rela.plt):
> r_offset     r_info       r_type              st_value         st_name =
+ r_addend
> 0000100218b0 000300000015 R_PPC64_JMP_SLOT    0000000000000000 atexit =
+ 0
> 0000100218c8 000400000015 R_PPC64_JMP_SLOT    0000000000000000 =
_init_tls + 0
> 0000100218e0 000600000015 R_PPC64_JMP_SLOT    0000000000000000 exit + =
0
>=20
> is an increment of 0x18 between entries (room for the
> function descriptors). The r_offset's are from the
> ld.bfd generated .plt section:
>=20
> 	0x0000000010021898 - 0x00000000100218f8 is .plt
>=20
> (gdb) x/12gx 0x0000000010021898
> 0x10021898:	0x00000000500189f0	0x0000000050058f00
> 0x100218a8:	0x000000005003d000	0x000000005021a7e0
> 0x100218b8:	0x0000000050299900	0x0000000000000000
> 0x100218c8:	0x0000000010000988	0x0000000000000000
> 0x100218d8:	0x0000000000000000	0x0000000010000990
> 0x100218e8:	0x0000000000000000	0x0000000000000000
> (gdb) info symbol 0x000000005021a7e0
> .atexit in section .text of /lib/libc.so.7
> (gdb) info symbol 0x0000000010000988
> _init_tls@plt in section .text of /root/c_tests/a.out
> (gdb) info symbol 0x0000000010000990
> exit@plt in section .text of /root/c_tests/a.out
>=20
> NOTE: The .plt contains no code, just function descriptors.
>=20
> By comparison for what ld.lld generated:
>=20
> Relocation section with addend (.rela.plt):
> r_offset     r_info       r_type              st_value         st_name =
+ r_addend
> 000010030038 000300000015 R_PPC64_JMP_SLOT    0000000000000000 atexit =
+ 0
> 000010030040 000200000015 R_PPC64_JMP_SLOT    0000000000000000 =
_init_tls + 0
> 000010030048 000500000015 R_PPC64_JMP_SLOT    0000000000000000 exit + =
0
>=20
> These r_offset's are in the .got.plt area, not in the .plt area:
>=20
> 	0x0000000010030020 - 0x0000000010030050 is .got.plt
>=20
> The increment is 0x8 between entries, not 0x18. There are no
> function descriptor here.
>=20
> The actual content from the =
/usr/src/libexec/rtld-elf/powerpc64/reloc.c
> code results ends up being as shown:
>=20
> (gdb) x/6gx 0x10030038
> 0x10030038:	0x0000000000000020	0x0000000000000028
> 0x10030048:	0x0000000000000030	0x0000000010030168
> 0x10030058:	0x0000000010030160	0x0000000010020028
>=20
> which appears to be incorrect for how the 0(r12) code is used
> buy the .plt code (shown below) and leads to the crash. For
> another the .plt code below expects to compute r12 and then
> use 0(1r12), 8(r12), and 16(r12) for the function descriptor
> entries --but there is no room for such.
>=20
> For ld.lld's a.out its .plt (not .got.plt) is code,
> unlike in the ld.bfd generated a.out:
>=20
> Disassembly of section .plt:
> 0000000010010550 <.plt> std     r2,40(r1)
> 0000000010010554 <.plt+0x4> addis   r11,r2,0
> 0000000010010558 <.plt+0x8> ld      r12,32512(r11) Note: =
r12=3D=3D0x000010030038 results
> 000000001001055c <.plt+0xc> ld      r11,0(r12)     Note: r11=3D=3D0x20 =
results
> 0000000010010560 <.plt+0x10> mtctr   r11           Note: ctr=3D=3D0x20 =
results
> 0000000010010564 <.plt+0x14> ld      r2,8(r12)     Note: accesses =
0x000010030040 see .plt+0x28
> 0000000010010568 <.plt+0x18> ld      r11,16(r12)   Note: accesses =
0x000010030048 see .plt+0x48
> 000000001001056c <.plt+0x1c> bctr
>=20
> Note: The code expects 0(12), 8(12), and 16(r12) storage
> but not such structure is present: 8(r12) above is
> equivalent to 0(r12) below as an example.
>=20
> 0000000010010570 <.plt+0x20> std     r2,40(r1)
> 0000000010010574 <.plt+0x24> addis   r11,r2,0
> 0000000010010578 <.plt+0x28> ld      r12,32520(r11) Note: =
r12=3D=3D0x000010030040 results
> 000000001001057c <.plt+0x2c> ld      r11,0(r12)     Note: r11=3D=3D0x28 =
results
> 0000000010010580 <.plt+0x30> mtctr   r11            Note: ctr=3D=3D0x28 =
results
> 0000000010010584 <.plt+0x34> ld      r2,8(r12)      Note: accesses =
0x000010030048 see .plt+0x48
> 0000000010010588 <.plt+0x38> ld      r11,16(r12)    Note: accesses =
0x000010030050
> 000000001001058c <.plt+0x3c> bctr
>=20
> Note: 0x000010030050 is from:
>=20
> 	0x0000000010030050 - 0x00000000100300a0 is .toc
>=20
> 0000000010010590 <.plt+0x40> std     r2,40(r1)
> 0000000010010594 <.plt+0x44> addis   r11,r2,0
> 0000000010010598 <.plt+0x48> ld      r12,32528(r11) Note: =
r12=3D=3D0x000010030048 results
> 000000001001059c <.plt+0x4c> ld      r11,0(r12)     Note: r11=3D=3D0x30 =
results
> 00000000100105a0 <.plt+0x50> mtctr   r11            Note: ctr=3D=3D0x30 =
results
> 00000000100105a4 <.plt+0x54> ld      r2,8(r12)      Note: accesses =
0x000010030050
> 00000000100105a8 <.plt+0x58> ld      r11,16(r12)    Note: accesses =
0x000010030058
> 00000000100105ac <.plt+0x5c> bctr
>=20
> Note: 0x000010030050 and 0x000010030058 are from:
>=20
> 	0x0000000010030050 - 0x00000000100300a0 is .toc
>=20
> This code seems to expect function descriptors [8(r12) and 16(r12) =
accesses]
> but no such function descriptors or space for them is set up.
>=20
> =3D=3D=3D
> Mark Millard
> markmi at dsl-only.net
>=20
> On 2017-Jan-19, at 3:14 PM, Mark Millard <markmi at dsl-only.net> =
wrote:
>=20
>> On 2017-Jan-19, at 12:05 PM, Roman Divacky <rdivacky at vlakno.cz> =
wrote:
>>=20
>>> Type =3D 38 should be R_ABS so thats fine. If what I expected to be =
in .got
>>> is in .got.plt, what happens if you modify the getPPC64TocBase() to
>>> use ::GotPlt instead of ::Got ?
>>=20
>> For using GotPlt. . .
>>=20
>> -pie use still gets the notices:
>>=20
>> can't create dynamic relocation R_PPC64_REL24 against readonly =
segment
>>=20
>> The log messages do not change at all for GotPlt being in use: Plt, =
Got,
>> and GotPlt all output the same messages during the compile/link based
>> on ld.lld (other options being the same). (I diff'd the outputs.)
>>=20
>> # /usr/local/bin/gdb a.out
>> GNU gdb (GDB) 7.11.1 [GDB v7.11.1 for FreeBSD]
>> . . .
>> Reading symbols from a.out...done.
>> (gdb) run
>> Starting program: /root/c_tests/a.out=20
>>=20
>> Program received signal SIGSEGV, Segmentation fault.
>> 0x00000000100104a0 in .__do_global_ctors_aux ()
>> (gdb) bt
>> #0  0x00000000100104a0 in .__do_global_ctors_aux ()
>> #1  0x0000000010010508 in ._init ()
>> #2  0x000000005002ad1c in objlist_call_init (list=3D<optimized out>, =
lockstate=3D<optimized out>) at /usr/src/libexec/rtld-elf/rtld.c:2546
>> #3  0x0000000050029fe4 in _rtld (sp=3D<optimized out>, =
exit_proc=3D<optimized out>, objp=3D<optimized out>) at =
/usr/src/libexec/rtld-elf/rtld.c:673
>> #4  0x00000000500279b0 in ._rtld_start () at =
/usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:83
>> Backtrace stopped: frame did not save the PC
>>=20
>> In other words: the same as when Plt was used.
>>=20
>> And the code does not get near executing main.
>>=20
>> The difference in:
>>=20
>> /usr/local/powerpc64-freebsd/bin/objdump -d --prefix-addresses a.out
>>=20
>> output for Got vs. GotPlt is:
>> (<: Got, >: GotPlt)
>>=20
>> < 0000000010010558 <.plt+0x8> ld      r12,32512(r11)
>> ---
>>> 0000000010010558 <.plt+0x8> ld      r12,-32744(r11)
>> 346c346
>> < 0000000010010578 <.plt+0x28> ld      r12,32520(r11)
>> ---
>>> 0000000010010578 <.plt+0x28> ld      r12,-32736(r11)
>> 354c354
>> < 0000000010010598 <.plt+0x48> ld      r12,32528(r11)
>> ---
>>> 0000000010010598 <.plt+0x48> ld      r12,-32728(r11)
>>=20
>> The GotPlt offset figures look better to me: near the beginning
>> of the 64K range with zero offset being near the middle. (That
>> does not of itself imply that r11 would be appropriate for the
>> figures if the execution got this far.)
>>=20
>> Of course the .plt section is far before what you call
>> the TOC, unlike in what the bfd linker does. (See below.)
>>=20
>> The following includes:
>>=20
>> 	0x0000000010010550 - 0x00000000100105b0 is .plt
>> . . .
>> 	0x0000000010030020 - 0x0000000010030050 is .got.plt
>> 	0x0000000010030050 - 0x00000000100300a0 is .toc
>> . . .
>> 	0x000000005005ff00 - 0x000000005005ff08 is .got in =
/libexec/ld-elf.so.1
>> . . .
>> 	0x000000005026f900 - 0x0000000050271f98 is .got in =
/lib/libc.so.7
>> 	0x0000000050272000 - 0x0000000050277208 is .plt in =
/lib/libc.so.7
>>=20
>> (A mix of ld.lld and ld.bfd styles.)
>>=20
>> (gdb) info file
>> Symbols from "/root/c_tests/a.out".
>> Native process:
>> 	Using the running image of child LWP 100168 of process 78109.
>> 	While running this, GDB does not access memory from...
>> 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
>> 	0x0000000010000468 - 0x0000000010000474 is .eh_frame_hdr
>> 	0x0000000010010000 - 0x00000000100104f0 is .text
>> 	0x00000000100104f0 - 0x000000001001051c is .init
>> 	0x0000000010010520 - 0x0000000010010544 is .fini
>> 	0x0000000010010550 - 0x00000000100105b0 is .plt
>> 	0x0000000010020000 - 0x0000000010020010 is .ctors
>> 	0x0000000010020010 - 0x0000000010020020 is .dtors
>> 	0x0000000010020020 - 0x0000000010020028 is .jcr
>> 	0x0000000010020028 - 0x0000000010020138 is .dynamic
>> 	0x0000000010020138 - 0x0000000010020138 is .got
>> 	0x0000000010030000 - 0x0000000010030019 is .data
>> 	0x0000000010030020 - 0x0000000010030050 is .got.plt
>> 	0x0000000010030050 - 0x00000000100300a0 is .toc
>> 	0x00000000100300a0 - 0x0000000010030160 is .opd
>> 	0x0000000010030160 - 0x0000000010030170 is .bss
>> 	0x0000000050020158 - 0x0000000050020228 is .hash in =
/libexec/ld-elf.so.1
>> 	0x0000000050020228 - 0x0000000050020540 is .dynsym in =
/libexec/ld-elf.so.1
>> 	0x0000000050020540 - 0x00000000500206b6 is .dynstr in =
/libexec/ld-elf.so.1
>> 	0x00000000500206b6 - 0x00000000500206f8 is .gnu.version in =
/libexec/ld-elf.so.1
>> 	0x00000000500206f8 - 0x0000000050020808 is .gnu.version_d in =
/libexec/ld-elf.so.1
>> 	0x0000000050020808 - 0x0000000050027960 is .rela.dyn in =
/libexec/ld-elf.so.1
>> 	0x0000000050027960 - 0x0000000050045ab4 is .text in =
/libexec/ld-elf.so.1
>> 	0x0000000050045ab4 - 0x000000005004856b is .rodata in =
/libexec/ld-elf.so.1
>> 	0x000000005004856c - 0x000000005004856c is .eh_frame in =
/libexec/ld-elf.so.1
>> 	0x000000005005cf50 - 0x000000005005cf58 is .fini_array in =
/libexec/ld-elf.so.1
>> 	0x000000005005cf58 - 0x000000005005d260 is .data.rel.ro in =
/libexec/ld-elf.so.1
>> 	0x000000005005d260 - 0x000000005005d3b0 is .dynamic in =
/libexec/ld-elf.so.1
>> 	0x000000005005d3b0 - 0x000000005005ff00 is .opd in =
/libexec/ld-elf.so.1
>> 	0x000000005005ff00 - 0x000000005005ff08 is .got in =
/libexec/ld-elf.so.1
>> 	0x0000000050060000 - 0x0000000050060628 is .data in =
/libexec/ld-elf.so.1
>> 	0x0000000050060628 - 0x0000000050061478 is .bss in =
/libexec/ld-elf.so.1
>> 	0x00000000500621c8 - 0x00000000500672b0 is .hash in =
/lib/libc.so.7
>> 	0x00000000500672b0 - 0x0000000050079778 is .dynsym in =
/lib/libc.so.7
>> 	0x0000000050079778 - 0x0000000050080846 is .dynstr in =
/lib/libc.so.7
>> 	0x0000000050080846 - 0x00000000500820ac is .gnu.version in =
/lib/libc.so.7
>> 	0x00000000500820b0 - 0x00000000500821c0 is .gnu.version_d in =
/lib/libc.so.7
>> 	0x00000000500821c0 - 0x00000000500c2678 is .rela.dyn in =
/lib/libc.so.7
>> 	0x00000000500c2678 - 0x00000000500c7868 is .rela.plt in =
/lib/libc.so.7
>> 	0x00000000500c7870 - 0x00000000500c789c is .init in =
/lib/libc.so.7
>> 	0x00000000500c78a0 - 0x0000000050227ca0 is .text in =
/lib/libc.so.7
>> 	0x0000000050227ca0 - 0x0000000050227cc4 is .fini in =
/lib/libc.so.7
>> 	0x0000000050227d00 - 0x000000005023b606 is .rodata in =
/lib/libc.so.7
>> 	0x000000005023b608 - 0x000000005023b6ec is .eh_frame_hdr in =
/lib/libc.so.7
>> 	0x000000005023b6f0 - 0x000000005023bad4 is .eh_frame in =
/lib/libc.so.7
>> 	0x0000000050253318 - 0x0000000050253380 is .tdata in =
/lib/libc.so.7
>> 	0x0000000050253380 - 0x0000000050253390 is .tbss in =
/lib/libc.so.7
>> 	0x0000000050253380 - 0x0000000050253390 is .init_array in =
/lib/libc.so.7
>> 	0x0000000050253390 - 0x0000000050253398 is .fini_array in =
/lib/libc.so.7
>> 	0x0000000050253398 - 0x00000000502533a8 is .ctors in =
/lib/libc.so.7
>> 	0x00000000502533a8 - 0x00000000502533b8 is .dtors in =
/lib/libc.so.7
>> 	0x00000000502533b8 - 0x00000000502533c0 is .jcr in =
/lib/libc.so.7
>> 	0x00000000502533c0 - 0x0000000050258a90 is .data.rel.ro in =
/lib/libc.so.7
>> 	0x0000000050258a90 - 0x0000000050258c60 is .dynamic in =
/lib/libc.so.7
>> 	0x0000000050258c60 - 0x000000005026f8f8 is .opd in =
/lib/libc.so.7
>> 	0x000000005026f900 - 0x0000000050271f98 is .got in =
/lib/libc.so.7
>> 	0x0000000050272000 - 0x0000000050277208 is .plt in =
/lib/libc.so.7
>> 	0x0000000050277208 - 0x000000005027b0b0 is .data in =
/lib/libc.so.7
>> 	0x000000005027b0b0 - 0x0000000050294738 is .bss in =
/lib/libc.so.7
>>=20
>>=20
>> =3D=3D=3D
>> Mark Millard
>> markmi at dsl-only.net




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?DF5A46F0-4EFC-4E4A-81D1-7F8972BCF6E7>