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-ppc mailing list