[llvm] [JITLink][AArch32] Implement R_ARM_PREL31 and process .ARM.exidx sections (PR #79044)
Stefan Gränitz via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 22 11:54:59 PST 2024
https://github.com/weliveindetail created https://github.com/llvm/llvm-project/pull/79044
`R_ARM_PREL31` is a 31-bits relative data relocation where the most-significant bit is preserved. It's used primarily in `.ARM.exidx` sections, which we skipped processing until now, because we didn't support the relocation type. This was implemented in RuntimeDyld with https://reviews.llvm.org/D25069 and I implemented it in a similar way in JITLink in order to reach feature parity.
>From 1eb3193da0a581e562da2c2f52391c86f1b0a875 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Sat, 20 Jan 2024 16:00:51 +0100
Subject: [PATCH] [JITLink][AArch32] Implement R_ARM_PREL31 and process
.ARM.exidx sections
---
.../llvm/ExecutionEngine/JITLink/aarch32.h | 2 ++
.../JITLink/ELFLinkGraphBuilder.h | 5 +++++
.../ExecutionEngine/JITLink/ELF_aarch32.cpp | 14 ++++---------
llvm/lib/ExecutionEngine/JITLink/aarch32.cpp | 21 ++++++++++++++++---
.../JITLink/AArch32/ELF_relocations_data.s | 20 ++++++++++++++----
5 files changed, 45 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index 081f77a85e182a..24448e35f7bbd3 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -41,6 +41,8 @@ enum EdgeKind_aarch32 : Edge::Kind {
/// Absolute 32-bit value relocation
Data_Pointer32,
+ Data_PRel31,
+
/// Create GOT entry and store offset
Data_RequestGOTAndTransformToDelta32,
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
index 56d1efa4bdef70..e4e0c2555215c2 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
@@ -397,6 +397,11 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySections() {
orc::ExecutorAddr(Sec.sh_addr),
Sec.sh_addralign, 0);
+ if (Sec.sh_type == ELF::SHT_ARM_EXIDX) {
+ // Add live symbol to avoid dead-stripping for .ARM.exidx sections
+ G->addAnonymousSymbol(*B, orc::ExecutorAddrDiff(), orc::ExecutorAddrDiff(), false, true);
+ }
+
setGraphBlock(SecIndex, B);
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
index 15c209e1ebe5bf..dfe6ab14adc279 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
@@ -50,6 +50,8 @@ getJITLinkEdgeKind(uint32_t ELFType, const aarch32::ArmConfig &ArmCfg) {
return aarch32::Arm_MovtAbs;
case ELF::R_ARM_NONE:
return aarch32::None;
+ case ELF::R_ARM_PREL31:
+ return aarch32::Data_PRel31;
case ELF::R_ARM_TARGET1:
return (ArmCfg.Target1Rel) ? aarch32::Data_Delta32
: aarch32::Data_Pointer32;
@@ -79,6 +81,8 @@ Expected<uint32_t> getELFRelocationType(Edge::Kind Kind) {
return ELF::R_ARM_REL32;
case aarch32::Data_Pointer32:
return ELF::R_ARM_ABS32;
+ case aarch32::Data_PRel31:
+ return ELF::R_ARM_PREL31;
case aarch32::Data_RequestGOTAndTransformToDelta32:
return ELF::R_ARM_GOT_PREL;
case aarch32::Arm_Call:
@@ -140,16 +144,6 @@ class ELFLinkGraphBuilder_aarch32
using ELFT = ELFType<DataEndianness, false>;
using Base = ELFLinkGraphBuilder<ELFT>;
- bool excludeSection(const typename ELFT::Shdr &Sect) const override {
- // TODO: An .ARM.exidx (Exception Index table) entry is 8-bytes in size and
- // consists of 2 words. It might be sufficient to process only relocations
- // in the the second word (offset 4). Please find more details in: Exception
- // Handling ABI for the Arm® Architecture -> Index table entries
- if (Sect.sh_type == ELF::SHT_ARM_EXIDX)
- return true;
- return false;
- }
-
Error addRelocations() override {
LLVM_DEBUG(dbgs() << "Processing relocations:\n");
using Self = ELFLinkGraphBuilder_aarch32<DataEndianness>;
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
index 1797a0068cd7cd..57835102ce2b68 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -397,6 +397,8 @@ Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
case Data_Pointer32:
case Data_RequestGOTAndTransformToDelta32:
return SignExtend64<32>(support::endian::read32(FixupPtr, Endian));
+ case Data_PRel31:
+ return SignExtend64<31>(support::endian::read32(FixupPtr, Endian));
default:
return make_error<JITLinkError>(
"In graph " + G.getName() + ", section " + B.getSection().getName() +
@@ -471,9 +473,8 @@ Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
Symbol &TargetSymbol = E.getTarget();
uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
- // Regular data relocations have size 4, alignment 1 and write the full 32-bit
- // result to the place; no need for overflow checking. There are three
- // exceptions: R_ARM_ABS8, R_ARM_ABS16, R_ARM_PREL31
+ // Data relocations have alignment 1, size 4 (except R_ARM_ABS8 and
+ // R_ARM_ABS16) and write the full 32-bit result (except R_ARM_PREL31).
switch (Kind) {
case Data_Delta32: {
int64_t Value = TargetAddress - FixupAddress + Addend;
@@ -495,6 +496,19 @@ Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
endian::write32be(FixupPtr, Value);
return Error::success();
}
+ case Data_PRel31: {
+ int64_t Value = TargetAddress - FixupAddress + Addend;
+ if (!isInt<31>(Value))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (LLVM_LIKELY(G.getEndianness() == endianness::little)) {
+ uint32_t MSB = endian::read32le(FixupPtr) & 0x80000000;
+ endian::write32le(FixupPtr, MSB | (Value & ~0x80000000));
+ } else {
+ uint32_t MSB = endian::read32be(FixupPtr) & 0x80000000;
+ endian::write32be(FixupPtr, MSB | (Value & ~0x80000000));
+ }
+ return Error::success();
+ }
case Data_RequestGOTAndTransformToDelta32:
llvm_unreachable("Should be transformed");
default:
@@ -755,6 +769,7 @@ const char *getEdgeKindName(Edge::Kind K) {
switch (K) {
KIND_NAME_CASE(Data_Delta32)
KIND_NAME_CASE(Data_Pointer32)
+ KIND_NAME_CASE(Data_PRel31)
KIND_NAME_CASE(Data_RequestGOTAndTransformToDelta32)
KIND_NAME_CASE(Arm_Call)
KIND_NAME_CASE(Arm_Jump24)
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_relocations_data.s b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_relocations_data.s
index 7bd59f8a52de6d..544e8c259d2868 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_relocations_data.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_relocations_data.s
@@ -64,7 +64,7 @@ got_prel_offset:
.size got_prel_offset, .-got_prel_offset
.size got_prel, .-got_prel
-# EH personality routine
+# EH personality routine in .ARM.exidx
# CHECK-TYPE: {{[0-9a-f]+}} R_ARM_NONE __aeabi_unwind_cpp_pr0
.globl __aeabi_unwind_cpp_pr0
.type __aeabi_unwind_cpp_pr0,%function
@@ -72,8 +72,19 @@ got_prel_offset:
__aeabi_unwind_cpp_pr0:
bx lr
-# Generate reference to EH personality (right now we ignore the resulting
-# R_ARM_PREL31 relocation since it's in .ARM.exidx)
+# CHECK-TYPE: {{[0-9a-f]+}} R_ARM_PREL31 .text
+#
+# An .ARM.exidx table entry is 8-bytes in size, made up of 2 4-byte entries.
+# First word contains offset to function for this entry:
+# jitlink-check: (*{4}section_addr(out.o, .ARM.exidx))[31:0] = prel31 - section_addr(out.o, .ARM.exidx)
+#
+# Most-significant bit in second word denotes inline entry when set (and
+# relocation to .ARM.extab otherwise). Inline entry with compact model index 0:
+# 0x9b vsp = r11
+# 0x84 0x80 pop {r11, r14}
+#
+# jitlink-check: *{4}(section_addr(out.o, .ARM.exidx) + 4) = 0x809b8480
+#
.globl prel31
.type prel31,%function
.align 2
@@ -85,8 +96,8 @@ prel31:
mov r11, sp
pop {r11, lr}
mov pc, lr
- .size prel31,.-prel31
.fnend
+ .size prel31,.-prel31
# This test is executable with any 4-byte external target:
# > echo "unsigned target = 42;" | clang -target armv7-linux-gnueabihf -o target.o -c -xc -
@@ -98,5 +109,6 @@ prel31:
main:
push {lr}
bl got_prel
+ bl prel31
pop {pc}
.size main, .-main
More information about the llvm-commits
mailing list