From 95dcb8b49dd3bb0fcb9f020fe931632a0ddf4994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= Date: Fri, 24 Nov 2023 21:41:00 +0100 Subject: [llvm-jitlink] Support plain AArch32 stubs in jitlink-check's stub_addr() expressions (#73268) We want to use regular `stub_addr()` expressions in `jitlink-check` lines to test the generation of stubs in AArch32, but we don't want this to require a standardized GOT-based PLT implementation. In terms of performance and binary size it doesn't seem beneficial. And in terms of patching branch targets, we should be able to handle range-extension- and interworking-stubs without a lot of extra logic. In order to allow such AArch32 stubs we add a separate path for `stub_addr()` expressions in `llvm-jitlink-elf`. The relocations in our stubs are not pointing to the GOT, but to the external symbol directly. Thus, we have to avoid access to the block of the edge target. Instead we only return the symbol name, which is enough to use `stub_addr()` expressions in tests. The name of the AArch32 stubs section differs from the conventional `$__STUBS` on purpose. It allows to add a regular PLT/GOT implementation as an orthogonal feature in the future. In order to also allow decoding of stub target addresses in the future, we mention the stub flavor in the section name as well. --- llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'llvm/tools/llvm-jitlink') diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp index 4b7b3f9..a024687 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp @@ -24,6 +24,10 @@ static bool isELFGOTSection(Section &S) { return S.getName() == "$__GOT"; } static bool isELFStubsSection(Section &S) { return S.getName() == "$__STUBS"; } +static bool isELFAArch32StubsSection(Section &S) { + return S.getName().starts_with("__llvm_jitlink_aarch32_STUBS_"); +} + static Expected getFirstRelocationEdge(LinkGraph &G, Block &B) { auto EItr = llvm::find_if(B.edges(), [](Edge &E) { return E.isRelocation(); }); @@ -68,6 +72,15 @@ static Expected getELFStubTarget(LinkGraph &G, Block &B) { return getELFGOTTarget(G, GOTSym.getBlock()); } +static Expected getELFAArch32StubTargetName(LinkGraph &G, + Block &B) { + auto E = getFirstRelocationEdge(G, B); + if (!E) + return E.takeError(); + Symbol &StubTarget = E->getTarget(); + return StubTarget.getName().str(); +} + namespace llvm { Error registerELFGraphInfo(Session &S, LinkGraph &G) { @@ -102,6 +115,7 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) { bool isGOTSection = isELFGOTSection(Sec); bool isStubsSection = isELFStubsSection(Sec); + bool isAArch32StubsSection = isELFAArch32StubsSection(Sec); bool SectionContainsContent = false; bool SectionContainsZeroFill = false; @@ -142,6 +156,18 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) { else return TS.takeError(); SectionContainsContent = true; + } else if (isAArch32StubsSection) { + if (Sym->isSymbolZeroFill()) + return make_error("zero-fill atom in Stub section", + inconvertibleErrorCode()); + + if (auto Name = getELFAArch32StubTargetName(G, Sym->getBlock())) + FileInfo.StubInfos[*Name] = {Sym->getSymbolContent(), + Sym->getAddress().getValue(), + Sym->getTargetFlags()}; + else + return Name.takeError(); + SectionContainsContent = true; } if (Sym->hasName()) { -- cgit v1.1