[llvm] [BOLT][JITLink] Respect block alignment when assigning addresses (PR #227324)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 03:36:34 PDT 2026
https://github.com/maksimra updated https://github.com/llvm/llvm-project/pull/227324
>From e6808961b0b491c89b7fa29099b0538fc262658a Mon Sep 17 00:00:00 2001
From: Maksim <rachinskii.mv at phystech.edu>
Date: Wed, 23 Sep 2026 13:10:44 +0300
Subject: [PATCH 1/2] [BOLT][JITLink] Respect block alignment when assigning
addresses
BOLT's JITLink memory manager sizes and copies blocks using section-relative aligned offsets. Section address reassignment instead packed blocks contiguously, which could make LinkGraph addresses disagree with the locations of their contents.
Use the same section-relative packing when assigning block addresses. Add unit coverage for a non-zero alignment offset and an end-to-end AArch64 test that verifies a JUMP26 relocation reaches the physically aligned second block.
---
bolt/include/bolt/Rewrite/JITLinkLinker.h | 1 +
bolt/lib/Rewrite/JITLinkLinker.cpp | 22 ++++----
bolt/test/AArch64/jitlink-block-alignment.s | 61 +++++++++++++++++++++
bolt/unittests/Core/CMakeLists.txt | 1 +
bolt/unittests/Core/JITLinkLinker.cpp | 34 ++++++++++++
5 files changed, 109 insertions(+), 10 deletions(-)
create mode 100644 bolt/test/AArch64/jitlink-block-alignment.s
create mode 100644 bolt/unittests/Core/JITLinkLinker.cpp
diff --git a/bolt/include/bolt/Rewrite/JITLinkLinker.h b/bolt/include/bolt/Rewrite/JITLinkLinker.h
index 1c41a26ac2563..fff60709c3374 100644
--- a/bolt/include/bolt/Rewrite/JITLinkLinker.h
+++ b/bolt/include/bolt/Rewrite/JITLinkLinker.h
@@ -47,6 +47,7 @@ class JITLinkLinker : public BOLTLinker {
static SmallVector<jitlink::Block *, 2>
orderedBlocks(const jitlink::Section &Section);
static size_t sectionSize(const jitlink::Section &Section);
+ static void assignBlockAddresses(jitlink::Section &Section, uint64_t Address);
};
} // namespace bolt
diff --git a/bolt/lib/Rewrite/JITLinkLinker.cpp b/bolt/lib/Rewrite/JITLinkLinker.cpp
index c287dc002623d..1952d5499db33 100644
--- a/bolt/lib/Rewrite/JITLinkLinker.cpp
+++ b/bolt/lib/Rewrite/JITLinkLinker.cpp
@@ -59,16 +59,7 @@ void reassignSectionAddress(jitlink::LinkGraph &LG,
auto *JLSection = LG.findSectionByName(BinSection.getSectionID());
assert(JLSection && "cannot find section in LinkGraph");
- auto BlockAddress = Address;
- for (auto *Block : JITLinkLinker::orderedBlocks(*JLSection)) {
- // FIXME it would seem to make sense to align here. However, in
- // non-relocation mode, we simply use the original address of functions
- // which might not be aligned with the minimum alignment used by
- // BinaryFunction (2). Example failing test when aligning:
- // bolt/test/X86/addr32.s
- Block->setAddress(orc::ExecutorAddr(BlockAddress));
- BlockAddress += Block->getSize();
- }
+ JITLinkLinker::assignBlockAddresses(*JLSection, Address);
}
} // anonymous namespace
@@ -237,5 +228,16 @@ size_t JITLinkLinker::sectionSize(const jitlink::Section &Section) {
return Size;
}
+void JITLinkLinker::assignBlockAddresses(jitlink::Section &Section,
+ uint64_t Address) {
+ uint64_t BlockOffset = 0;
+ for (auto *Block : orderedBlocks(Section)) {
+ // Mirror the memory manager's section-relative packing.
+ BlockOffset = jitlink::alignToBlock(BlockOffset, *Block);
+ Block->setAddress(orc::ExecutorAddr(Address + BlockOffset));
+ BlockOffset += Block->getSize();
+ }
+}
+
} // namespace bolt
} // namespace llvm
diff --git a/bolt/test/AArch64/jitlink-block-alignment.s b/bolt/test/AArch64/jitlink-block-alignment.s
new file mode 100644
index 0000000000000..88a689fe42d5e
--- /dev/null
+++ b/bolt/test/AArch64/jitlink-block-alignment.s
@@ -0,0 +1,61 @@
+## Verify that BOLT assigns target addresses using the same block alignment as
+## ExecutableFileMemoryManager uses when laying out the section contents.
+
+# REQUIRES: system-linux
+
+## Build a regular executable for BOLT. Keep a text relocation so that BOLT
+## runs in relocation mode.
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux \
+# RUN: -defsym=MAIN=1 %s -o %t.main.o
+# RUN: ld.lld --emit-relocs -e _start %t.main.o -o %t.exe
+
+## Build a minimal hugify runtime with two input sections, then give the
+## sections the same name so that ELFLinkGraphBuilder represents them as two
+## blocks in one JITLink section. Their input addresses make the block order
+## deterministic.
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s \
+# RUN: -o %t.runtime.pre.o
+# RUN: llvm-objcopy --remove-section .text \
+# RUN: --change-section-address .text.first=0x1000 \
+# RUN: --change-section-address .text.second=0x2000 \
+# RUN: --rename-section .text.first=.text \
+# RUN: --rename-section .text.second=.text \
+# RUN: %t.runtime.pre.o %t.runtime.o
+
+## The first block is four bytes long and the second is 16-byte aligned. The
+## memory manager therefore places the second block at section offset 16. The
+## branch displacement must be 16 bytes. Assigning block addresses without the
+## alignment padding would incorrectly encode a four-byte displacement.
+# RUN: llvm-bolt %t.exe -o %t.bolt --lite=0 --hugify \
+# RUN: --runtime-hugify-lib=%t.runtime.o
+# RUN: llvm-objdump -d --section=.text.bolt.extra.1 %t.bolt | FileCheck %s
+
+# CHECK: 14000004 {{.*}}b
+# CHECK: d65f03c0 {{.*}}ret
+
+.ifdef MAIN
+ .text
+ .globl _start
+ .type _start, %function
+_start:
+ bl target
+ ret
+ .size _start, .-_start
+
+ .globl target
+ .type target, %function
+target:
+ ret
+ .size target, .-target
+.else
+ .section .text.first,"ax", at progbits
+ b __bolt_hugify_self
+
+ .section .text.second,"ax", at progbits
+ .p2align 4
+ .globl __bolt_hugify_self
+ .type __bolt_hugify_self, %function
+__bolt_hugify_self:
+ ret
+ .size __bolt_hugify_self, .-__bolt_hugify_self
+.endif
diff --git a/bolt/unittests/Core/CMakeLists.txt b/bolt/unittests/Core/CMakeLists.txt
index 6b9b73bd16052..53d081dedebaf 100644
--- a/bolt/unittests/Core/CMakeLists.txt
+++ b/bolt/unittests/Core/CMakeLists.txt
@@ -10,6 +10,7 @@ set(LLVM_LINK_COMPONENTS
add_bolt_unittest(CoreTests
BinaryContext.cpp
ClusteredRows.cpp
+ JITLinkLinker.cpp
MCPlusBuilder.cpp
MemoryMaps.cpp
DynoStats.cpp
diff --git a/bolt/unittests/Core/JITLinkLinker.cpp b/bolt/unittests/Core/JITLinkLinker.cpp
new file mode 100644
index 0000000000000..68d1a7d171aa1
--- /dev/null
+++ b/bolt/unittests/Core/JITLinkLinker.cpp
@@ -0,0 +1,34 @@
+//===- bolt/unittest/Core/JITLinkLinker.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "bolt/Rewrite/JITLinkLinker.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::bolt;
+using namespace llvm::jitlink;
+
+TEST(JITLinkLinkerTest, AssignBlockAddressesRespectsAlignment) {
+ LinkGraph G("test", std::make_shared<orc::SymbolStringPool>(),
+ Triple("x86_64-unknown-linux"), SubtargetFeatures(),
+ getGenericEdgeKindName);
+ auto &Section =
+ G.createSection(".data", orc::MemProt::Read | orc::MemProt::Write);
+
+ auto &First = G.createContentBlock(Section, ArrayRef<char>("aaaaa", 5),
+ orc::ExecutorAddr(0), 16, 0);
+ auto &Second = G.createContentBlock(Section, ArrayRef<char>("bbbb", 4),
+ orc::ExecutorAddr(20), 16, 4);
+
+ JITLinkLinker::assignBlockAddresses(Section, 0);
+ EXPECT_EQ(First.getAddress().getValue() % First.getAlignment(),
+ First.getAlignmentOffset());
+ EXPECT_EQ(Second.getAddress().getValue() % Second.getAlignment(),
+ Second.getAlignmentOffset());
+}
>From e17710dab4fe0963399a84179956fb4fe7692aeb Mon Sep 17 00:00:00 2001
From: Maksim <rachinskii.mv at phystech.edu>
Date: Wed, 30 Sep 2026 13:32:38 +0300
Subject: [PATCH 2/2] Make lit-test more independent from final layout
---
bolt/test/AArch64/jitlink-block-alignment.s | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/bolt/test/AArch64/jitlink-block-alignment.s b/bolt/test/AArch64/jitlink-block-alignment.s
index 88a689fe42d5e..14a93eabde659 100644
--- a/bolt/test/AArch64/jitlink-block-alignment.s
+++ b/bolt/test/AArch64/jitlink-block-alignment.s
@@ -28,10 +28,11 @@
## alignment padding would incorrectly encode a four-byte displacement.
# RUN: llvm-bolt %t.exe -o %t.bolt --lite=0 --hugify \
# RUN: --runtime-hugify-lib=%t.runtime.o
-# RUN: llvm-objdump -d --section=.text.bolt.extra.1 %t.bolt | FileCheck %s
+# RUN: llvm-objdump -d --no-show-raw-insn --no-symbolize-operands \
+# RUN: --section=.text.bolt.extra.1 %t.bolt | FileCheck %s
-# CHECK: 14000004 {{.*}}b
-# CHECK: d65f03c0 {{.*}}ret
+# CHECK: b 0x[[DEST:[0-9a-f]+]]
+# CHECK: {{^ *0*}}[[DEST]]:{{.*}}ret
.ifdef MAIN
.text
More information about the llvm-commits
mailing list