aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-jitlink
diff options
context:
space:
mode:
authorStefan Gränitz <stefan.graenitz@gmail.com>2023-11-24 21:41:00 +0100
committerGitHub <noreply@github.com>2023-11-24 21:41:00 +0100
commit95dcb8b49dd3bb0fcb9f020fe931632a0ddf4994 (patch)
treef68aead1ae6d8393c751808e3401a2e168968121 /llvm/tools/llvm-jitlink
parent20f634f275b431ff256ba45cbcbb6dc5bd945fb3 (diff)
downloadllvm-95dcb8b49dd3bb0fcb9f020fe931632a0ddf4994.zip
llvm-95dcb8b49dd3bb0fcb9f020fe931632a0ddf4994.tar.gz
llvm-95dcb8b49dd3bb0fcb9f020fe931632a0ddf4994.tar.bz2
[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.
Diffstat (limited to 'llvm/tools/llvm-jitlink')
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp26
1 files changed, 26 insertions, 0 deletions
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<Edge &> getFirstRelocationEdge(LinkGraph &G, Block &B) {
auto EItr =
llvm::find_if(B.edges(), [](Edge &E) { return E.isRelocation(); });
@@ -68,6 +72,15 @@ static Expected<Symbol &> getELFStubTarget(LinkGraph &G, Block &B) {
return getELFGOTTarget(G, GOTSym.getBlock());
}
+static Expected<std::string> 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<StringError>("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()) {