I have submitted llvm bugzilla 31716 for lld 3.9.1's incoherent .plt vs. .got.plt content for powerpc64
Mark Millard
markmi at dsl-only.net
Sat Jan 21 20:19:30 UTC 2017
I've copied the submittal information later below.
I've also added 31716 to llvm bugzilla 25780 (the
meta-submittal for using clang as the FreeBSD/ppc
system context). If this is wrong for some reason
fell free to delete the item from the Depends On
list.
I did reference:
> I've not found any powerpc family documentation
> for .got.plt use: No such powerpc64 ABI yet?
What I wrote in the submittal was:
> powerpc64 context for:
>
> # more main.c
> static volatile char big_area[67001] = "This is a test";
>
> int main ()
> {
> big_area[67000] = '9';
> }
>
> via:
>
> clang -fuse-ld=lld -g main.c
>
> 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, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X at ha
> write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X at 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
> }
>
> But what ld.lld generated for relocation was:
>
> 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
>
> These r_offset's are in the .got.plt area, not in the .plt area:
>
> 0x0000000010030020 - 0x0000000010030050 is .got.plt
>
> The increment is 0x8 between entries, not 0x18 (or more) that
> would be needed for function descriptors: There is no
> function descriptor space here.
>
> 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<ELFT>::Plt->addEntry(Body);
>
> uint32_t Rel;
> if (Body.isGnuIFunc() && !Preemptible)
> Rel = Target->IRelativeRel;
> else
> Rel = Target->PltRel;
>
> Out<ELFT>::GotPlt->addEntry(Body);
> Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
> Body.getGotPltOffset<ELFT>(), !Preemptible,
> &Body, 0});
> continue;
> }
>
> The code is explicitly targeting creating GotPlt space, not
> .opd space, as well., not matching the earlier comment in
> PPC64TargetInfo::writePlt .
>
> The effect of such code and the wrtPlt code need to be
> correctly matching but currently are not.
>
> For ld.lld's a.out its .plt (not .got.plt) is code,
> unlike in the ld.bfd generated a.out:
>
> 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==0x000010030038 results
> 000000001001055c <.plt+0xc> ld r11,0(r12)
> 0000000010010560 <.plt+0x10> mtctr r11
> 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
>
> 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.
>
> 0000000010010570 <.plt+0x20> std r2,40(r1)
> 0000000010010574 <.plt+0x24> addis r11,r2,0
> 0000000010010578 <.plt+0x28> ld r12,32520(r11) Note: r12==0x000010030040 results
> 000000001001057c <.plt+0x2c> ld r11,0(r12)
> 0000000010010580 <.plt+0x30> mtctr r11
> 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
>
> Note: 0x000010030050 is from:
>
> 0x0000000010030050 - 0x00000000100300a0 is .toc
>
> 0000000010010590 <.plt+0x40> std r2,40(r1)
> 0000000010010594 <.plt+0x44> addis r11,r2,0
> 0000000010010598 <.plt+0x48> ld r12,32528(r11) Note: r12==0x000010030048 results
> 000000001001059c <.plt+0x4c> ld r11,0(r12)
> 00000000100105a0 <.plt+0x50> mtctr r11
> 00000000100105a4 <.plt+0x54> ld r2,8(r12) Note: accesses 0x000010030050
> 00000000100105a8 <.plt+0x58> ld r11,16(r12) Note: accesses 0x000010030058
> 00000000100105ac <.plt+0x5c> bctr
>
> Note: 0x000010030050 and 0x000010030058 are from:
>
> 0x0000000010030050 - 0x00000000100300a0 is .toc
>
> Either the .got.plt entry layout changes to have room
> for 8(r12) and 16(r12) positions (size change to 0x18
> Bytes per entry) 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: No such powerpc64 ABI yet?)
>
> By contrast the -fuse-ld=bfd ends up with:
>
> 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
>
> is an increment of 0x18 between entries (room for the
> function descriptors). The r_offset's are from the
> ld.bfd generated .plt section:
>
> 0x0000000010021898 - 0x00000000100218f8 is .plt
>
> NOTE: For the FreeBSD ld.bfd context the .plt does not have
> blocks of code for such, just the function descriptors.
===
Mark Millard
markmi at dsl-only.net
More information about the freebsd-toolchain
mailing list