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
On 2017-Jan-20, at 3:19 PM, Mark Millard wrote: > 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 = 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. > > write32be(Buf, 0xf8410028); // std %r2, 40(%r1) > write32be(Buf + 4, 0x3d62 | applyPPCHa(Off)); // addis %r11, %r2, X@ha > write32be(Buf + 8, 0xe98b | applyPPCLo(Off)); // ld %r12, X@l(%r11) > write32be(Buf + 12, 0xe96c); // 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). It looks like the other side of this that is not establishing space for function descriptors is in the code in: /usr/src/contrib/llvm/tools/lld/ELF/Relocations.cpp in its scanRelocs : // At this point we are done with the relocated position. Some relocations // also require us to create a got or plt entry. // If a relocation needs PLT, we create a PLT and a GOT slot for the symbol. if (needsPlt(Expr)) { if (Body.isInPlt()) continue; Out::Plt->addEntry(Body); uint32_t Rel; if (Body.isGnuIFunc() && !Preemptible) Rel = Target->IRelativeRel; else Rel = Target->PltRel; Out::GotPlt->addEntry(Body); Out::RelaPlt->addReloc({Rel, Out::GotPlt, Body.getGotPltOffset(), !Preemptible, , 0}); continue; } The code is explicitly targeting creating GotPlt space, not .opd space, as well. The effect of such code and the wrtPlt code need to be correctly matching but currently are not. [I'm likely telling you want you already know. But for me these are finds that took a fair amount of time to discover: very unfamiliar source code.] === Mark Millard markmi at dsl-only.net On 2017-Jan-20, at 12:54 AM, Mark Millard wrote: > I did a bunch more investigation and have 4 major points > that I think I've established: > > 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). > > 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. > > 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. > > Fourthly: Got is correct and the GotPlt and Plt > alternatives are wrong for in uint64_t getPPC64TocBase() . > (Sorry I
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
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 = 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. write32be(Buf, 0xf8410028); // std %r2, 40(%r1) write32be(Buf + 4, 0x3d62 | applyPPCHa(Off)); // addis %r11, %r2, X@ha write32be(Buf + 8, 0xe98b | applyPPCLo(Off)); // ld %r12, X@l(%r11) write32be(Buf + 12, 0xe96c); // 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). === Mark Millard markmi at dsl-only.net On 2017-Jan-20, at 12:54 AM, Mark Millard wrote: > I did a bunch more investigation and have 4 major points > that I think I've established: > > 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). > > 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. > > 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. > > 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.) > > The rest of this note is related the "fourthly" and > "thirdly" above but is only relevant if more detail > is wanted. > > > I deal with "fourthly" first. . . > > I was wrong about Got vs. Plt vs. GotPlt in: > > uint64_t getPPC64TocBase() > > 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: > > 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 > > The Got case executed the rtld_start.S:83 related code correctly > and later fails. (I've traced relevant code under gdb.) > > So the below is based on analyzing the Got variant. > > > Now for "thirdly" (lack of function descriptors in .plt). . . > > 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. . . > > For ld.bfd's generated a.out: > > Relocation section with addend (.rela.plt): > r_offset r_info
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
I did a bunch more investigation and have 4 major points that I think I've established: 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). 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. 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. 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.) The rest of this note is related the "fourthly" and "thirdly" above but is only relevant if more detail is wanted. I deal with "fourthly" first. . . I was wrong about Got vs. Plt vs. GotPlt in: uint64_t getPPC64TocBase() 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: 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 The Got case executed the rtld_start.S:83 related code correctly and later fails. (I've traced relevant code under gdb.) So the below is based on analyzing the Got variant. Now for "thirdly" (lack of function descriptors in .plt). . . 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. . . For ld.bfd's generated a.out: Relocation section with addend (.rela.plt): r_offset r_info r_type st_value st_name + r_addend 100218b0 00030015 R_PPC64_JMP_SLOT atexit + 0 100218c8 00040015 R_PPC64_JMP_SLOT _init_tls + 0 100218e0 00060015 R_PPC64_JMP_SLOT exit + 0 is an increment of 0x18 between entries (room for the function descriptors). The r_offset's are from the ld.bfd generated .plt section: 0x10021898 - 0x100218f8 is .plt (gdb) x/12gx 0x10021898 0x10021898: 0x500189f0 0x50058f00 0x100218a8: 0x5003d000 0x5021a7e0 0x100218b8: 0x50299900 0x 0x100218c8: 0x1988 0x 0x100218d8: 0x 0x1990 0x100218e8: 0x 0x (gdb) info symbol 0x5021a7e0 .atexit in section .text of /lib/libc.so.7 (gdb) info symbol 0x1988 _init_tls@plt in section .text of /root/c_tests/a.out (gdb) info symbol 0x1990 exit@plt in section .text of /root/c_tests/a.out NOTE: The .plt contains no code, just function descriptors. By comparison for what ld.lld generated: Relocation section with addend (.rela.plt): r_offset r_info r_type st_value st_name + r_addend 10030038 00030015 R_PPC64_JMP_SLOT atexit + 0 10030040 00020015 R_PPC64_JMP_SLOT _init_tls + 0 10030048 00050015 R_PPC64_JMP_SLOT exit + 0 These r_offset's are in the .got.plt area, not in the .plt area: 0x10030020 - 0x10030050 is .got.plt The increment is 0x8 between entries, not 0x18. There are no function descriptor here. The actual content from the /usr/src/libexec/rtld-elf/powerpc64/reloc.c code results ends up being as shown: (gdb) x/6gx 0x10030038 0x10030038: 0x0020 0x0028 0x10030048: 0x0030 0x10030168 0x10030058: 0x10030160 0x10020028 which appears to be incorrect for how the 0(r12) code is used buy the .plt code (shown below) and leads to the crash.
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
Type = 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 ? On Thu, Jan 19, 2017 at 01:46:02AM -0800, Mark Millard wrote: > I should have noted that -pie gets the same sort of > readonly segment errors as -shared did: > > # clang -fuse-ld=lld -g -pie empty_src.c > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 10 > Type = 10 > Type = 50 > Type = 64 > Type = 50 > Type = 48 > Type = 10 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 50 > Type = 48 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 50 > Type = 48 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 10 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 50 > Type = 48 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 10 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 64 > Type = 50 > Type = 48 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 50 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 50 > Type = 48 > Type = 50 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 38 > Unhandled type = 38 > Type = 51 > undefined symbol: main in /usr/lib/Scrt1.o > clang: error: linker command failed with exit code 1 (use -v to see > invocation) > > # more main.c > int main () > { > } > # clang -fuse-ld=lld -g -pie main.c > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 10 > Type = 10 > Type = 50 > Type = 64 > Type = 50 > Type = 48 > Type = 10 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 50 > Type = 48 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 50 > Type = 48 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 10 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 50 > Type = 50 > Type = 48 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 50 > Type = 48 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 10 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 64 > Type = 50 > Type = 48 > Type = 50 > Type = 64 > Type = 50 > Type = 64 > Type = 50 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 38 > Unhandled type = 38 > Type = 51 > Type = 50 > Type = 48 > Type = 50 > Type = 48 > Type = 10 > can't create dynamic relocation R_PPC64_REL24 against readonly segment > Type = 38 > Unhandled type = 38 > Type = 51 > clang: error: linker command failed with exit code 1 (use -v to see > invocation) > > > So making something with a relocatable global variable is problematical > via lld. > > === > Mark Millard > markmi at dsl-only.net > > On 2017-Jan-18, at 10:48 PM, Mark Millard wrote: > > The log messages code does not work because of Assertion failures: > > # clang -fuse-ld=lld -g main.c > Type = 50, name =
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
I should have noted that -pie gets the same sort of readonly segment errors as -shared did: # clang -fuse-ld=lld -g -pie empty_src.c Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 64 Type = 10 Type = 10 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 Type = 50 Type = 50 Type = 48 Type = 48 Type = 50 Type = 48 Type = 50 Type = 50 Type = 48 Type = 48 Type = 50 Type = 50 Type = 48 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 50 Type = 48 Type = 50 Type = 50 Type = 48 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 10 Type = 50 Type = 50 Type = 48 Type = 48 Type = 50 Type = 50 Type = 48 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 10 Type = 50 Type = 64 Type = 50 Type = 64 Type = 64 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 50 Type = 48 Type = 50 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 38 Unhandled type = 38 Type = 51 undefined symbol: main in /usr/lib/Scrt1.o clang: error: linker command failed with exit code 1 (use -v to see invocation) # more main.c int main () { } # clang -fuse-ld=lld -g -pie main.c Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 64 Type = 10 Type = 10 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 Type = 50 Type = 50 Type = 48 Type = 48 Type = 50 Type = 48 Type = 50 Type = 50 Type = 48 Type = 48 Type = 50 Type = 50 Type = 48 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 50 Type = 48 Type = 50 Type = 50 Type = 48 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 10 Type = 50 Type = 50 Type = 48 Type = 48 Type = 50 Type = 50 Type = 48 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 10 Type = 50 Type = 64 Type = 50 Type = 64 Type = 64 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 51 Type = 50 Type = 48 Type = 50 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 38 Unhandled type = 38 Type = 51 clang: error: linker command failed with exit code 1 (use -v to see invocation) So making something with a relocatable global variable is problematical via lld. === Mark Millard markmi at dsl-only.net On 2017-Jan-18, at 10:48 PM, Mark Millard wrote: The log messages code does not work because of Assertion failures: # clang -fuse-ld=lld -g main.c Type = 50, name = Assertion failed: (!isLocal()), function getName, file /usr/src/contrib/llvm/tools/lld/ELF/Symbols.cpp, line 100. clang: error: unable to execute command: Abort trap (core dumped) clang: error: linker command failed due to signal (use -v to see invocation) So for now I've disabled the name part of the line. At least we will see the numeric type of each and the reports of any "unhandled" values. I decided to use the Got variation instead of the Plt variant first. Some examples: # more empty_src.c # clang -fuse-ld=lld -g -shared -o empty_src.so empty_src.c Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 10 Type = 50 Type = 64 Type = 50 Type = 64 Type = 64 Type = 50 Type = 48
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
The log messages code does not work because of Assertion failures: # clang -fuse-ld=lld -g main.c Type = 50, name = Assertion failed: (!isLocal()), function getName, file /usr/src/contrib/llvm/tools/lld/ELF/Symbols.cpp, line 100. clang: error: unable to execute command: Abort trap (core dumped) clang: error: linker command failed due to signal (use -v to see invocation) So for now I've disabled the name part of the line. At least we will see the numeric type of each and the reports of any "unhandled" values. I decided to use the Got variation instead of the Plt variant first. Some examples: # more empty_src.c # clang -fuse-ld=lld -g -shared -o empty_src.so empty_src.c Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 10 Type = 50 Type = 64 Type = 50 Type = 64 Type = 64 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 50 Type = 48 Type = 50 Type = 48 Type = 10 can't create dynamic relocation R_PPC64_REL24 against readonly segment Type = 38 Unhandled type = 38 Type = 51 clang: error: linker command failed with exit code 1 (use -v to see invocation) # clang -fuse-ld=lld -g empty_src.c Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 64 Type = 10 Type = 10 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 Type = 50 Type = 50 Type = 64 Type = 64 Type = 50 Type = 64 Type = 50 Type = 50 Type = 64 Type = 64 Type = 50 Type = 50 Type = 64 Type = 64 Type = 10 Type = 50 Type = 64 Type = 50 Type = 50 Type = 64 Type = 64 Type = 10 Type = 10 Type = 50 Type = 50 Type = 64 Type = 64 Type = 50 Type = 50 Type = 64 Type = 64 Type = 10 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 64 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 Type = 10 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 50 Type = 48 Type = 50 Type = 48 Type = 10 Type = 38 Unhandled type = 38 Type = 51 undefined symbol: main in /usr/lib/crt1.o clang: error: linker command failed with exit code 1 (use -v to see invocation) # more main.c volatile void* gblvar = 0; int main () { gblvar = } # clang -fuse-ld=lld -g main.c Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 64 Type = 10 Type = 10 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 Type = 50 Type = 50 Type = 64 Type = 64 Type = 50 Type = 64 Type = 50 Type = 50 Type = 64 Type = 64 Type = 50 Type = 50 Type = 64 Type = 64 Type = 10 Type = 50 Type = 64 Type = 50 Type = 50 Type = 64 Type = 64 Type = 10 Type = 10 Type = 50 Type = 50 Type = 64 Type = 64 Type = 50 Type = 50 Type = 64 Type = 64 Type = 10 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 64 Type = 50 Type = 48 Type = 50 Type = 64 Type = 50 Type = 64 Type = 50 Type = 48 Type = 10 Type = 10 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 51 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 50 Type = 48 Type = 38 Unhandled type = 38 Type = 51 Type = 50 Type = 48 Type = 50 Type = 48 Type = 10 Type = 38 Unhandled type = 38 Type = 51 Type = 1 Unhandled type = 1 Type = 1 Unhandled type = 1 Type = 1 Unhandled type = 1 Type = 1 Unhandled type = 1 Type = 1 Unhandled type = 1 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 1 Unhandled type = 1 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 38 Unhandled type = 38 Type = 1 Unhandled type = 1 Type = 1 Unhandled
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
Well trying to have the global variable in various forms produced more information when I tried having it in a shared object: (This was before your changes to add log messages.) # more gblvar.c volatile long gblvar = 1; # clang -g -fuse-ld=lld -shared -o gblvar.so gblvar.c can't create dynamic relocation R_PPC64_REL24 against readonly segment can't create dynamic relocation R_PPC64_REL24 against readonly segment can't create dynamic relocation R_PPC64_REL24 against readonly segment clang: error: linker command failed with exit code 1 (use -v to see invocation) By contrast: # clang -g -fuse-ld=bfd -shared -o gblvar.so gblvar.c # (so no problem reported). === Mark Millard markmi at dsl-only.net On 2017-Jan-18, at 3:41 PM, Mark Millardwrote: On 2017-Jan-18, at 1:54 PM, Roman Divacky wrote: > I think I got it all wrong. I think what lld is trying to achieve > is to have the PLT entry to jump to GOT which references the real symbol. >From what I've read: for code references the .got.plt section would be involved when it exists, not the .got section. > For some reason, GOT is empty, in our case. I think that I've already explained this: lld produces two different sections instead of just one .got section: .got and .got.plt . .got is now for only global variables. (These can be in the RELRO region: read-only after upfront relocation.) My program had no global variables. If you want I can change it to have one and use it so that the .got will not be empty. .got.plt is for code references that allow lazy relocation. (These can not being the the RELRO region.) Having the global variable would not change this from what I can tell. In the older toolchain these were both in the .got section and the global variable relocations could not be in the RELRO region because of the mixing in one section. > I believe this might be caused > by a relocation thats wrongly mapped to R_ABS in > PPC64TargetInfo::getRelExpr(). That is not it from what I can tell reading about what the .got.plt section is for and why it was split from the .got section. I think I'll add a global variable and use it so that their is no question what goes in the .got section instead of having no examples. I think you are not going in the right direction now for what the .got section is for as lld is producing things for powerpc64 (not that I'm an expert in the older or newer techniques). > Mark, can you apply this patch and rerun the linking and send me back what > relocations are applied to what symbols? Or even, if there's an unhandled > relocation, try to adjust the switch and rerun your test? I think that I will first add the global variable and its use and show what the last change with Plt instead of Got ends up looking like --but with your log notices added. Then I'll retry with the Plt use reverted. > Thanks > > Index: ../tools/lld/ELF/Target.cpp > === > --- ../tools/lld/ELF/Target.cpp (revision 292428) > +++ ../tools/lld/ELF/Target.cpp (working copy) > @@ -1075,7 +1075,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; > @@ -1114,8 +1115,10 @@ > } > > RelExpr PPC64TargetInfo::getRelExpr(uint32_t Type, const SymbolBody ) const > { > + llvm::outs() << "Type = " << Type << ", name = " << S.getName() << "\n"; > switch (Type) { > default: > +llvm::outs() << "Unhandled type = " << Type << "\n"; >return R_ABS; > case R_PPC64_TOC16: > case R_PPC64_TOC16_DS: It may be a bit before I get the Plt and/or Got examples done. I might report the Plt case first and separately, later report the Got case. === Mark Millard markmi at dsl-only.net On Tue, Jan 17, 2017 at 09:38:07PM -0800, Mark Millard wrote: > Using the new changed line (Plt use now): > > uint64_t TocVA = Out::Plt->getVA(); > > changed the behavior and it gets farther for > -fuse-ld=lld based linking. But it is r2 leading > to r3 content that is dereferenced and 8(r3) fails > this time. This was in the process of finding > the new r2 value for the following bctrl. > r2==0x10018560 initially in __do_global_ctors_aux > seems wrong. If so then objlist_call_init produced > a wrong r2 value. > > [I've no clue if this is what you expected from > the Plt experiment or not.] > > Details. . . > > # /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 > > Program received signal SIGSEGV, Segmentation fault. > 0x100104a8 in .__do_global_ctors_aux () > (gdb) bt > #0 0x100104a8 in .__do_global_ctors_aux () > #1 0x10010518 in ._init () > #2 0x5002ac78 in objlist_call_init (list=, > lockstate=) at
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
Using the new changed line (Plt use now): uint64_t TocVA = Out::Plt->getVA(); changed the behavior and it gets farther for -fuse-ld=lld based linking. But it is r2 leading to r3 content that is dereferenced and 8(r3) fails this time. This was in the process of finding the new r2 value for the following bctrl. r2==0x10018560 initially in __do_global_ctors_aux seems wrong. If so then objlist_call_init produced a wrong r2 value. [I've no clue if this is what you expected from the Plt experiment or not.] Details. . . # /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 Program received signal SIGSEGV, Segmentation fault. 0x100104a8 in .__do_global_ctors_aux () (gdb) bt #0 0x100104a8 in .__do_global_ctors_aux () #1 0x10010518 in ._init () #2 0x5002ac78 in objlist_call_init (list=, lockstate=) at /usr/src/libexec/rtld-elf/rtld.c:2541 #3 0x50029fa8 in _rtld (sp=, exit_proc=, objp=) at /usr/src/libexec/rtld-elf/rtld.c:668 #4 0x500279b0 in ._rtld_start () at /usr/src/libexec/rtld-elf/powerpc64/rtld_start.S:83 Backtrace stopped: frame did not save the PC (gdb) disass Dump of assembler code for function .__do_global_ctors_aux: 0x10010470 <+0>: mflrr0 0x10010474 <+4>: std r31,-8(r1) 0x10010478 <+8>: std r0,16(r1) 0x1001047c <+12>:stdur1,-128(r1) 0x10010480 <+16>:addis r3,r2,-1 < Note: r3 derives from r2 0x10010484 <+20>:mr r31,r1 0x10010488 <+24>:addir3,r3,32464 0x1001048c <+28>:std r30,112(r31) 0x10010490 <+32>:ld r3,-8(r3) 0x10010494 <+36>:cmpdi r3,-1 0x10010498 <+40>:beq 0x100104d4 <.__do_global_ctors_aux+100> 0x1001049c <+44>:addis r4,r2,-1 0x100104a0 <+48>:addir4,r4,32464 0x100104a4 <+52>:addir30,r4,-8 => 0x100104a8 <+56>:ld r4,8(r3) < Note: 8(r3) fails. 0x100104ac <+60>:ld r11,16(r3) 0x100104b0 <+64>:ld r3,0(r3) 0x100104b4 <+68>:std r2,40(r1) 0x100104b8 <+72>:mr r2,r4< Note: 8(r3) result should have been the new r2 value 0x100104bc <+76>:mtctr r3 0x100104c0 <+80>:bctrl 0x100104c4 <+84>:ld r2,40(r1) 0x100104c8 <+88>:ldu r3,-8(r30) 0x100104cc <+92>:cmpdi r3,-1 0x100104d0 <+96>:bne 0x100104a8 <.__do_global_ctors_aux+56> 0x100104d4 <+100>: ld r30,112(r31) 0x100104d8 <+104>: addir1,r1,128 0x100104dc <+108>: ld r0,16(r1) 0x100104e0 <+112>: ld r31,-8(r1) 0x100104e4 <+116>: mtlrr0 0x100104e8 <+120>: blr 0x100104ec <+124>: .long 0x0 0x100104f0 <+128>: .long 0x0 0x100104f4 <+132>: .long 0x0 End of assembler dump. (gdb) info registers r0 0x10010518 268502296 r1 0xcbf0 18446744073709538288 r2 0x10018560 268535136 r3 0x7ca903a64e800421 8982714944583631905 r4 0x10010430 268502064 r5 0x100300d0 268632272 r6 0x50043ab0 1342454448 r7 0x50067f00 1342603008 r8 0xdfcc 18446744073709543372 r9 0x0 0 r100x0 0 r110x0 0 r120xdfd0 18446744073709543376 r130x50057010 1342533648 r140x0 0 r150x0 0 r160x50047f00 1342471936 r170x500613e0 1342575584 r180x50253388 1344615304 r190x2 2 r200x0 0 r210x9 9 r220x0 0 r230x40 18014398509481984 r240x5004a100 1342480640 r250x5004c400 1342489600 r260xcd18 18446744073709538584 r270xcd3c 18446744073709538620 r280xcd3c 18446744073709538620 r290x0 0 r300x10010428 268502056 r310xcbf0 18446744073709538288 pc 0x100104a8 0x100104a8 <.__do_global_ctors_aux+56> msr cr 0x48200c00 1210059776 lr 0x10010518 0x10010518 <._init+24> ctr0x10010500 268502272 xer0x2000 536870912 (gdb) info file Symbols from "/root/c_tests/a.out". Native process: Using the running image of child LWP 100093 of process 1091. While running this, GDB does not access memory
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
Go with Out. On Tue, Jan 17, 2017 at 01:53:14PM -0800, Mark Millard wrote: > On 2017-Jan-17, at 11:54 AM, Roman Divacky wrote: > > . . . > > 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::Got->getVA(); > > + uint64_t TocVA = In::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 > > The modern 3.9.1 source does not match for the last. Note the > "Out" vs. "In" below ("svnlite status" does not show my source > as different in this area): > > 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 = Out::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; > } > > [Also the "// TOC . . ." comment is at line 1005 (given the prior > GotRel vs. PltRel split into separate lines).] > > Which should I use?: In vs. Out > > > would make any difference? It's not correct but might shed some light on > > what needs to be done > > if I am right. > > Separately if I understand the change you are picking out which section > is first of .got, .toc, .tocbss, .plt (.got.plt as well?). But for the > order of things that would still make the .ctors, .dtors, .jcr, .dynamic, > and .data sections as being inside the TOC and taking TOC address range > space: > > 0x10010560 - 0x100105c0 is .plt <= > NOTE > 0x1002 - 0x10020010 is .ctors > 0x10020010 - 0x10020020 is .dtors > 0x10020020 - 0x10020028 is .jcr > 0x10020028 - 0x10020138 is .dynamic > 0x10020138 - 0x10020138 is .got <= > NOTE > 0x1003 - 0x10030019 is .data > 0x10030020 - 0x10030050 is .got.plt <= > NOTE > 0x10030050 - 0x100300a0 is .toc <= > NOTE > > Is that expected/desired/allowed? > > > Could you explore this please? > > After you report for sure for In vs. Out I'll take a stab > at it. > > === > 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-unsubscr...@freebsd.org"
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
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::Got->getVA(); + uint64_t TocVA = In::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 wrote: > > > [Correcting a poor wording/interpetatation.] > > > > On 2017-Jan-16, at 3:28 PM, Mark Millardwrote: > > > >> 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 off0x0002 vaddr 0x1002 paddr > >> 0x1002 align 2**0 > >>filesz 0x0138 memsz 0x0138 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
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
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 wrote: > [Correcting a poor wording/interpetatation.] > > On 2017-Jan-16, at 3:28 PM, Mark Millardwrote: > >> 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 off0x0002 vaddr 0x1002 paddr >> 0x1002 align 2**0 >>filesz 0x0138 memsz 0x0138 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 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 0x1270 - 0x1285 is .interp 0x1288 - 0x12b8 is .note.tag 0x12b8 - 0x12b9 is .rodata 0x12bc - 0x12bc is .eh_frame 0x12c0 - 0x1368 is .dynsym 0x1368 - 0x1376 is .gnu.version
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
[Correcting a poor wording/interpetatation.] On 2017-Jan-16, at 3:28 PM, Mark Millardwrote: > 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 off0x0002 vaddr 0x1002 paddr > 0x1002 align 2**0 > filesz 0x0138 memsz 0x0138 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 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 0x1270 - 0x1285 is .interp 0x1288 - 0x12b8 is .note.tag 0x12b8 - 0x12b9 is .rodata 0x12bc - 0x12bc is .eh_frame 0x12c0 - 0x1368 is .dynsym 0x1368 - 0x1376 is .gnu.version 0x1378 - 0x1398 is .gnu.version_r 0x1398 - 0x13d8 is .hash 0x13d8 - 0x141a is .dynstr 0x1420 - 0x1468 is .rela.plt <= note 0x1468 - 0x1474 is .eh_frame_hdr 0x1001 - 0x100104f8 is .text 0x10010500 - 0x1001052c is .init 0x10010530 - 0x10010554 is .fini 0x10010560 - 0x100105c0 is .plt <= NOTE 0x1002 - 0x10020010 is .ctors 0x10020010 - 0x10020020 is .dtors 0x10020020 - 0x10020028 is .jcr 0x10020028 - 0x10020138 is .dynamic 0x10020138 - 0x10020138 is .got <= NOTE 0x1003 - 0x10030019 is .data 0x10030020 - 0x10030050 is .got.plt <= NOTE 0x10030050 -
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
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. Showing the objdump output for RELRO: RELRO off0x0002 vaddr 0x1002 paddr 0x1002 align 2**0 filesz 0x0138 memsz 0x0138 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 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 0x1270 - 0x1285 is .interp 0x1288 - 0x12b8 is .note.tag 0x12b8 - 0x12b9 is .rodata 0x12bc - 0x12bc is .eh_frame 0x12c0 - 0x1368 is .dynsym 0x1368 - 0x1376 is .gnu.version 0x1378 - 0x1398 is .gnu.version_r 0x1398 - 0x13d8 is .hash 0x13d8 - 0x141a is .dynstr 0x1420 - 0x1468 is .rela.plt <= note 0x1468 - 0x1474 is .eh_frame_hdr 0x1001 - 0x100104f8 is .text 0x10010500 - 0x1001052c is .init 0x10010530 - 0x10010554 is .fini 0x10010560 - 0x100105c0 is .plt <= NOTE 0x1002 - 0x10020010 is .ctors 0x10020010 - 0x10020020 is .dtors 0x10020020 - 0x10020028 is .jcr 0x10020028 - 0x10020138 is .dynamic 0x10020138 - 0x10020138 is .got <= NOTE 0x1003 - 0x10030019 is .data 0x10030020 - 0x10030050 is .got.plt <= NOTE 0x10030050 - 0x100300a0 is .toc <= NOTE 0x100300a0 - 0x10030160 is .opd 0x10030160 - 0x10030170 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 wrote: > On 2017-Jan-16, at 11:40 AM, Roman Divacky 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 >
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
On 2017-Jan-16, at 11:40 AM, Roman Divacky 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 0048 1420 1420 0420 2**3 CONTENTS, ALLOC, LOAD, READONLY, DATA . . . 14 .plt 0060 10010560 10010560 00010560 2**4 CONTENTS, ALLOC, LOAD, READONLY, CODE . . . 19 .got 10020138 10020138 00020138 2**3 CONTENTS, ALLOC, LOAD, DATA . . . 21 .got.plt 0030 10030020 10030020 00030020 2**3 CONTENTS, ALLOC, LOAD, DATA 22 .toc 0050 10030050 10030050 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.) 1288 l O .note.tag 0018 abitag 12a0 l O .note.tag 0018 crt_noinit_tag 12bb l O .eh_frame 0004 __FRAME_END__ .rela.plt fits between here: 1420 (start) .plt fits between here : 10010560 (start) 1002 l O .ctors 0008 __CTOR_LIST__ 10020008 l O .ctors 0008 __CTOR_END__ 10020010 l O .dtors 0008 __DTOR_LIST__ 10020018 l O .dtors 0008 __DTOR_END__ 10020020 l O .jcr __JCR_LIST__ 10020020 l O .jcr 0008 __JCR_END__ 10020028 l .dynamic .hidden _DYNAMIC .got fits between here : 10020138 (start and end: size zero) 1003 g O .data 0008 __progname 10030008 l O .data 0008 .hidden __dso_handle 10030010 l O .data 0008 __do_global_dtors_aux.p 10030018 l O .data 0001 __do_global_dtors_aux.completed .got.plt fits between here : 10030020 (start) .toc fits between here : 10030050 (start) 100300a0 g F .opd 0264 _start 100300b8 l F .opd 00d0 finalizer 100300d0 l F .opd .hidden _init 100300e8 l F .opd .hidden _fini 10030100 l F .opd 00a4 __do_global_dtors_aux 10030118 l F .opd 007c frame_dummy 10030130 g F .opd 001c main 10030148 l F .opd 0088 __do_global_ctors_aux 10030160 g O .bss 0008 __ps_strings 10030168 g O .bss 0008 environ 10030170 g *ABS* _end Examples of gdb reporting symbol information for some of those addresses: (gdb) info symbol 0x1288 abitag in section .note.tag (gdb) info symbol 0x12a0 crt_noinit_tag in section .note.tag (gdb) info symbol 0x12a4 crt_noinit_tag + 4 in section .note.tag (gdb) info symbol 0x10020008 __CTOR_END__ in section .ctors (gdb) info symbol 0x10020010 __DTOR_LIST__ in section .dtors (gdb) info symbol 0x10020020 __JCR_END__ in section .jcr (gdb) info symbol 0x10020028 _DYNAMIC in section .dynamic (gdb) info symbol 0x10030010 __do_global_dtors_aux.p in section .data (gdb) info symbol 0x100300a0 _start in section .opd (gdb) info symbol
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
Mark, I think the TOC (.got + .plt) has to be contiguous in memory. The on-disk layout is not that important. Can you check whats the difference of the in-memory TOC between lld and ld.bfd? Thanks, Roman 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 wrote: > > On 2017-Jan-12, at 11:22 AM, Roman Divacky 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::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 > 0 0 0 > . . . > [10] .rela.plt RELA 1420 0420 > 0048 0018 A 5 0 8 > . . . > [15] .plt PROGBITS 10010560 00010560 > 0060 AX 0 0 16 > . . . > [20] .got PROGBITS 10020138 00020138 > WA 0 0 8 > . . . > [22] .got.plt PROGBITS 10030020 00030020 > 0030 WA 0 0 8 > . . . > [23] .toc PROGBITS 10030050 00030050 > 0050 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 > 0 0 0 > . . . > [ 8] .rela.plt RELA 1370 0370 > 0048 0018 A 422 8 > . . . > [21] .got PROGBITS 10010c48 0c48 > 0058 0008 WA 0 0 8 > [22] .plt NOBITS 10010ca0 0ca0 > 0060 0018 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 >
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
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 wrote: On 2017-Jan-12, at 11:22 AM, Roman Divacky 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::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 0 0 0 . . . [10] .rela.plt RELA 1420 0420 0048 0018 A 5 0 8 . . . [15] .plt PROGBITS 10010560 00010560 0060 AX 0 0 16 . . . [20] .got PROGBITS 10020138 00020138 WA 0 0 8 . . . [22] .got.plt PROGBITS 10030020 00030020 0030 WA 0 0 8 . . . [23] .toc PROGBITS 10030050 00030050 0050 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 0 0 0 . . . [ 8] .rela.plt RELA 1370 0370 0048 0018 A 422 8 . . . [21] .got PROGBITS 10010c48 0c48 0058 0008 WA 0 0 8 [22] .plt NOBITS 10010ca0 0ca0 0060 0018 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
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
On 2017-Jan-12, at 11:22 AM, Roman Divacky 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::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 0 0 0 . . . [10] .rela.plt RELA 1420 0420 0048 0018 A 5 0 8 . . . [15] .plt PROGBITS 10010560 00010560 0060 AX 0 0 16 . . . [20] .got PROGBITS 10020138 00020138 WA 0 0 8 . . . [22] .got.plt PROGBITS 10030020 00030020 0030 WA 0 0 8 . . . [23] .toc PROGBITS 10030050 00030050 0050 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 0 0 0 . . . [ 8] .rela.plt RELA 1370 0370 0048 0018 A 422 8 . . . [21] .got PROGBITS 10010c48 0c48 0058 0008 WA 0 0 8 [22] .plt NOBITS 10010ca0 0ca0 0060 0018 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 wrote: > >> On 11 January 2017 at 21:06, Roman Divacky wrote: >>> Looks like a progress :) Three questions... >>> >>> Is the readelf -a reasonable now? >> >> FYI, I
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
On 2017-Jan-11, at 1:23 PM, Ed Maste wrote: > On 11 January 2017 at 21:06, Roman Divacky 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. 0x1001056c in ?? () Note that the temporary breakpoint is never hit. (gdb) bt #0 0x1001056c in ?? () #1 0x100100d8 in ?? () #2 0x500279b0 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 0x500279b0 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: 0x50027930 <+0>: stdur1,-144(r1) 0x50027934 <+4>: std r3,96(r1) 0x50027938 <+8>: std r4,104(r1) 0x5002793c <+12>:std r5,112(r1) 0x50027940 <+16>:std r8,136(r1) 0x50027944 <+20>:bl 0x50027950 <._rtld_start+32> 0x50027948 <+24>:.long 0x0 0x5002794c <+28>:.long 0x30e40 0x50027950 <+32>:mflrr3 0x50027954 <+36>:ld r4,0(r3) 0x50027958 <+40>:add r3,r4,r3 0x5002795c <+44>:ld r4,-32768(r2) 0x50027960 <+48>:subfr4,r4,r2 0x50027964 <+52>:bl 0x50027c64 0x50027968 <+56>:nop 0x5002796c <+60>:ld r4,104(r1) 0x50027970 <+64>:addir3,r4,-8 0x50027974 <+68>:addir4,r1,128 0x50027978 <+72>:addir5,r1,120 0x5002797c <+76>:bl 0x50028608 <_rtld> 0x50027980 <+80>:nop 0x50027984 <+84>:ld r2,8(r3) 0x50027988 <+88>:ld r11,16(r3) 0x5002798c <+92>:ld r3,0(r3) 0x50027990 <+96>:mtlrr3 0x50027994 <+100>: ld r3,96(r1) 0x50027998 <+104>: ld r4,104(r1) 0x5002799c <+108>: ld r5,112(r1) 0x500279a0 <+112>: ld r6,120(r1) 0x500279a4 <+116>: ld r7,128(r1) 0x500279a8 <+120>: ld r8,136(r1) 0x500279ac <+124>: blrl => 0x500279b0 <+128>: li r0,1 0x500279b4 <+132>: sc 0x500279b8 <+136>: nop 0x500279bc <+140>: nop End of assembler dump. So setting a breakpoint at 0x500279ac 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 0xdaf0 18446744073709542128 r2 0x10028138 268599608 r3 0x1 1 r4 0xdbb8 18446744073709542328 r5 0xdbc8 18446744073709542344 r6 0x5004c000 1342488576 r7 0x50058b30 1342540592 r8 0x0 0 r9 0x0 0 r100x0 0 r110x0 0 r120x2000 536870912 r130x50057010 1342533648 r140x0 0 r150x0 0 r160x0 0 r170x0 0 r180x0 0 r190x0 0 r200x0 0 r210x0 0 r220x0 0 r230x0 0 r240x0 0 r250x0 0 r260x0 0 r270x0 0 r280x0 0 r290x0 0 r300x0 0 r310x0 0 pc 0x500279ac 0x500279ac <._rtld_start+124> msr cr 0x22000c00 570428416 lr 0x1001 0x1001 ctr0x50043a80 1342454400 xer0x2000 536870912 (gdb) stepi 0x1001 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
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
Can you try this patch? Index: tools/lld/ELF/Target.cpp === --- tools/lld/ELF/Target.cpp(revision 291691) +++ tools/lld/ELF/Target.cpp(working copy) @@ -1062,7 +1062,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; On Wed, Jan 11, 2017 at 09:47:34AM -0800, Mark Millard wrote: > > On 2017-Jan-11, at 8:07 AM, Ed Maste wrote: > > > On 11 January 2017 at 04:15, Mark Millard wrote: > >> > >> # ./a.out > >> ld-elf.so.1: assert failed: /usr/src/libexec/rtld-elf/powerpc64/reloc.c:374 > >> Abort trap (core dumped) > > > > Would you paste the output of `readelf -r a.out`? > > Here you go, for ld.lld and for ld.bfd . . . > > For -fuse-ld=lld : > > # readelf -r a.out > > Relocation section with addend (.rela.plt): > r_offset r_info r_type st_value st_name + > r_addend > 10030038 00030014 atexit + 0 > 10030040 00020014 _init_tls + 0 > 10030048 00050014 exit + 0 > > For -fuse-ld=bfd : > > # readelf -r a.out > > Relocation section with addend (.rela.plt): > r_offset r_info r_type st_value st_name + > r_addend > 10010cb8 00030015 atexit + 0 > 10010cd0 00040015 _init_tls + 0 > 10010ce8 00060015 exit + 0 > > These were done on the powerpc64 machine (native). > > > === > 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-unsubscr...@freebsd.org" ___ freebsd-toolchain@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"
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
On 2017-Jan-11, at 8:07 AM, Ed Maste wrote: > On 11 January 2017 at 04:15, Mark Millard wrote: >> >> # ./a.out >> ld-elf.so.1: assert failed: /usr/src/libexec/rtld-elf/powerpc64/reloc.c:374 >> Abort trap (core dumped) > > Would you paste the output of `readelf -r a.out`? Here you go, for ld.lld and for ld.bfd . . . For -fuse-ld=lld : # readelf -r a.out Relocation section with addend (.rela.plt): r_offset r_info r_type st_value st_name + r_addend 10030038 00030014 atexit + 0 10030040 00020014 _init_tls + 0 10030048 00050014 exit + 0 For -fuse-ld=bfd : # readelf -r a.out Relocation section with addend (.rela.plt): r_offset r_info r_type st_value st_name + r_addend 10010cb8 00030015 atexit + 0 10010cd0 00040015 _init_tls + 0 10010ce8 00060015 exit + 0 These were done on the powerpc64 machine (native). === 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-unsubscr...@freebsd.org"
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
On 11 January 2017 at 04:15, Mark Millardwrote: > > # ./a.out > ld-elf.so.1: assert failed: /usr/src/libexec/rtld-elf/powerpc64/reloc.c:374 > Abort trap (core dumped) Would you paste the output of `readelf -r a.out`? ___ freebsd-toolchain@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"