[llvm] [llvm-jitlink] Support plain AArch32 range extension stubs in jitlink-check's stub_addr() expressions (PR #73268)
Stefan Gränitz via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 24 05:39:04 PST 2023
https://github.com/weliveindetail updated https://github.com/llvm/llvm-project/pull/73268
>From ada456bfe5eb372d38402fdd69234841c1ec0680 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Thu, 23 Nov 2023 22:46:19 +0100
Subject: [PATCH 1/2] [llvm-jitlink] Support plain AArch32 range extension
stubs in rtdyld-check's stub_addr() expressions
---
.../llvm/ExecutionEngine/JITLink/aarch32.h | 6 ++-
.../JITLink/AArch32/ELF_thumb_stubs.s | 44 +++++++++++++++++++
llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp | 27 ++++++++++++
3 files changed, 76 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index 94669e0bceb836d..ec28db415c04625 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -295,7 +295,7 @@ class StubsManager : public TableManager<StubsManager<Flavor>> {
StubsManager() = default;
/// Name of the object file section that will contain all our stubs.
- static StringRef getSectionName() { return "__llvm_jitlink_STUBS"; }
+ static StringRef getSectionName();
/// Implements link-graph traversal via visitExistingEdges().
bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
@@ -345,6 +345,10 @@ class StubsManager : public TableManager<StubsManager<Flavor>> {
template <>
Symbol &StubsManager<Thumbv7>::createEntry(LinkGraph &G, Symbol &Target);
+template <> inline StringRef StubsManager<Thumbv7>::getSectionName() {
+ return "__llvm_jitlink_aarch32_STUBS_Thumbv7";
+}
+
} // namespace aarch32
} // namespace jitlink
} // namespace llvm
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s
new file mode 100644
index 000000000000000..d1bb39f949efa87
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s
@@ -0,0 +1,44 @@
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=thumbv7-linux-gnueabi -arm-add-build-attributes \
+# RUN: -filetype=obj -filetype=obj -o %t/elf_stubs.o %s
+# RUN: llvm-jitlink -noexec -slab-address 0x76ff0000 \
+# RUN: -slab-allocate 10Kb -slab-page-size 4096 \
+# RUN: -abs external_func=0x76bbe880 \
+# RUN: -check %s %t/elf_stubs.o
+
+ .text
+ .syntax unified
+
+# Check that calls/jumps to external functions trigger the generation of stubs
+# and GOT entries. The GOT entry contains the absolute address of the external
+# function. The stub loads it and branches there.
+#
+# jitlink-check: decode_operand(test_external_call, 2) = stub_addr(elf_stubs.o, external_func) - next_pc(test_external_call)
+# jitlink-check: decode_operand(test_external_jump, 0) = stub_addr(elf_stubs.o, external_func) - next_pc(test_external_jump)
+ .globl test_external_call
+ .type test_external_call,%function
+ .p2align 1
+ .code 16
+ .thumb_func
+test_external_call:
+ bl external_func
+ .size test_external_call, .-test_external_call
+
+ .globl test_external_jump
+ .type test_external_call,%function
+ .p2align 1
+ .code 16
+ .thumb_func
+test_external_jump:
+ b external_func
+ .size test_external_jump, .-test_external_jump
+
+# Empty main function for jitlink to be happy
+ .globl main
+ .type main,%function
+ .p2align 1
+ .code 16
+ .thumb_func
+main:
+ bx lr
+ .size main, .-main
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index 7881660d1a73851..9ed73a8c45a9a9c 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -12,6 +12,7 @@
#include "llvm-jitlink.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Path.h"
@@ -24,6 +25,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(); });
@@ -64,6 +69,15 @@ static Expected<Symbol &> getELFStubTarget(LinkGraph &G, Block &B) {
return getELFGOTTarget(G, GOTSym.getBlock());
}
+static Expected<std::string>
+getELFAArch32StubTargetName(LinkGraph &G, Block &B, orc::ExecutionSession &ES) {
+ 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) {
@@ -98,6 +112,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;
@@ -138,6 +153,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(), S.ES))
+ FileInfo.StubInfos[*Name] = {Sym->getSymbolContent(),
+ Sym->getAddress().getValue(),
+ Sym->getTargetFlags()};
+ else
+ return Name.takeError();
+ SectionContainsContent = true;
}
if (Sym->hasName()) {
>From 9e93ba074455e15ef4d70051034b7deecfadb9a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Fri, 24 Nov 2023 14:37:24 +0100
Subject: [PATCH 2/2] [llvm-jitlink] Address feedback and polish comments
---
.../test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s | 7 ++++---
llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp | 5 ++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s
index d1bb39f949efa87..bd95c375279246a 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_thumb_stubs.s
@@ -9,9 +9,10 @@
.text
.syntax unified
-# Check that calls/jumps to external functions trigger the generation of stubs
-# and GOT entries. The GOT entry contains the absolute address of the external
-# function. The stub loads it and branches there.
+# Check that calls/jumps to external functions trigger the generation of
+# branch-range extension stubs. These stubs don't follow the default PLT model
+# where the branch-target address is loaded from a GOT entry. Instead, they
+# hard-code it in the immediate field.
#
# jitlink-check: decode_operand(test_external_call, 2) = stub_addr(elf_stubs.o, external_func) - next_pc(test_external_call)
# jitlink-check: decode_operand(test_external_jump, 0) = stub_addr(elf_stubs.o, external_func) - next_pc(test_external_jump)
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index 9ed73a8c45a9a9c..a6bd5733dd55367 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -12,7 +12,6 @@
#include "llvm-jitlink.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Path.h"
@@ -70,7 +69,7 @@ static Expected<Symbol &> getELFStubTarget(LinkGraph &G, Block &B) {
}
static Expected<std::string>
-getELFAArch32StubTargetName(LinkGraph &G, Block &B, orc::ExecutionSession &ES) {
+getELFAArch32StubTargetName(LinkGraph &G, Block &B) {
auto E = getFirstRelocationEdge(G, B);
if (!E)
return E.takeError();
@@ -158,7 +157,7 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) {
return make_error<StringError>("zero-fill atom in Stub section",
inconvertibleErrorCode());
- if (auto Name = getELFAArch32StubTargetName(G, Sym->getBlock(), S.ES))
+ if (auto Name = getELFAArch32StubTargetName(G, Sym->getBlock()))
FileInfo.StubInfos[*Name] = {Sym->getSymbolContent(),
Sym->getAddress().getValue(),
Sym->getTargetFlags()};
More information about the llvm-commits
mailing list