This is an archive of the discontinued LLVM Phabricator instance.

[JITLink][PowerPC] Correct handling of R_PPC64_REL24_NOTOC
ClosedPublic

Authored by lkail on Jul 18 2023, 10:43 PM.

Details

Summary

According to the ELFv2 ABI

This relocation type is used to specify a function call where the TOC pointer is not initialized. It is similar to R_PPC64_REL24 in that it specifies a symbol to be resolved. If the symbol resolves to a function that requires a TOC pointer (as determined by st_other bits) then a link editor must arrange for the call to be via the global entry point of the called function. Any stub code must not rely on a valid TOC base address in r2.

This patch fixes handling of R_PPC64_REL24_NOTOC by using the same stub code sequence as lld.

Diff Detail

Event Timeline

lkail created this revision.Jul 18 2023, 10:43 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 18 2023, 10:43 PM
lkail requested review of this revision.Jul 18 2023, 10:43 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 18 2023, 10:43 PM
lkail edited the summary of this revision. (Show Details)Jul 18 2023, 10:44 PM
lkail updated this revision to Diff 541847.Jul 18 2023, 11:23 PM
lhames accepted this revision.Jul 21 2023, 10:39 PM

LGTM. Thanks @lkail!

llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
54–102

You could further unify some of the code paths using a pair of template variables:

template <support::endianness Endianness>
ArrayRef<char> PtrJumpStubContent;

template<>
ArrayRef<char> PtrJumpStubContent<support::endianness::big> =
    PtrJumpStubContent_big;
template<>
ArrayRef<char> PtrJumpStubContent<support::endianness::litttle> =
    PtrJumpStubContent_little;

template <support::endianness Endianness>
ArrayRef<char> PtrJumpStubNotTOCContent;

template<>
ArrayRef<char> PtrJumpStubNoTOCContent<support::endianness::big> =
    PtrJumpStubNoTOCContent_big;
template<>
ArrayRef<char> PtrJumpStubNoTOCContent<support::endianness::litttle> =
    PtrJumpStubNoTOCContent_little;

pickStub's cases then look like:

template <support::endianness Endianness>
inline PLTCallStubInfo pickStub(PLTCallStubKind StubKind) {
  switch (StubKind) {
  case LongBranch: {
    auto Content = PointerJumpStubContent<Endianness>;
    // Skip save r2.
    Content = Content.slice(4);
    return PLTCallStubInfo{
        Content,
        {{TOCDelta16HA, 0, 0}, {TOCDelta16LO, 4, 0}},
    };
  }
  case LongBranchSaveR2: {
    auto Content = PointerJumpStub<Endianness>;
    return PLTCallStubInfo{
        Content,
        {{TOCDelta16HA, 4, 0}, {TOCDelta16LO, 8, 0}},
    };
  }
  case LongBranchNoTOC: {
    auto Content = PointerJumpStubNoTOCContent<Endianness>;
    return PLTCallStubInfo{
        Content,
        {{Delta16HA, 16, 8}, {Delta16LO, 20, 12}},
    };
  }
  }
}
...

If other clients are likely to use the stub content arrays this may be worth it. If everyone is going to use pickStub then I think it's fine either way.

This revision is now accepted and ready to land.Jul 21 2023, 10:39 PM
lkail added inline comments.Jul 23 2023, 8:20 PM
llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
54–102

Looks great.

lkail updated this revision to Diff 543353.Jul 23 2023, 8:21 PM
lkail updated this revision to Diff 543365.Jul 23 2023, 9:35 PM

I tried using templated variable, but premerge bot of windows looks unhappy. It might be due to cl's behavior is different. I'll land the original version.

This revision was automatically updated to reflect the committed changes.

PLTTableManager::StubKind (which was introduced in this patch) is uninitialized in the constructor. Is the PLTTableManager::visitEdge function guaranteed to be called before any call to PLTTableManager::createEntry?