[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