[llvm] ce4fcfc - [llvm-jitlink] Make -show-addrs work without -check, fix fallout. (#175491)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 12 05:13:16 PST 2026
Author: Lang Hames
Date: 2026-01-13T00:13:12+11:00
New Revision: ce4fcfc9e4b391c24d89f24d9ef1fc1f6ed230ee
URL: https://github.com/llvm/llvm-project/commit/ce4fcfc9e4b391c24d89f24d9ef1fc1f6ed230ee
DIFF: https://github.com/llvm/llvm-project/commit/ce4fcfc9e4b391c24d89f24d9ef1fc1f6ed230ee.diff
LOG: [llvm-jitlink] Make -show-addrs work without -check, fix fallout. (#175491)
Ensures that the address scraping passes are added to the JIT linker pipeline
if either of the -check or -show-addrs are passed. Prior to this commit we only
considered -check, so passing -show-addrs on its own was printing an empty
(unpopulated) symbol table.
This change exposed bugs in RuntimeDyldChecker's `MemoryRegionInfo` type, aned
llvm-jitlink's symbol printing code:
- `MemoryRegionInfo` was assuming that zero-sized symbols wouldn't be defined
and was using Size == 0 as a proxy for "region info uninitialized". This was
triggering assertions for valid LinkGraphs containing zero-sized symbols.
- llvm-jitlink's symbol printing code was assuming that all defined symbols
contained content, and was not correctly handling zero-fill / absolute
symbols. This triggered assertions about requesting content addresses for
non-content symbols.
This commit fixes the issues above, and adds both a generic testcase for the
-show-addrs option, and an ELF-specific testcase with a zero-sized symbol to
check that the option works for such symbols.
Added:
llvm/test/ExecutionEngine/JITLink/AArch64/ELF_zero_sized_symbols_with_show_addrs.s
llvm/test/ExecutionEngine/JITLink/Generic/llvm-jitlink-option-show-addrs.test
Modified:
llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
llvm/tools/llvm-jitlink/llvm-jitlink.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index ec9bee8edb595..79e873c5f7219 100644
--- a/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -82,35 +82,41 @@ class RuntimeDyldChecker {
public:
class MemoryRegionInfo {
public:
- MemoryRegionInfo() = default;
+ MemoryRegionInfo() : Size(0), Initialized(false) {}
/// Constructor for symbols/sections with content and TargetFlag.
MemoryRegionInfo(ArrayRef<char> Content, JITTargetAddress TargetAddress,
TargetFlagsType TargetFlags)
: ContentPtr(Content.data()), Size(Content.size()),
- TargetAddress(TargetAddress), TargetFlags(TargetFlags) {}
+ TargetAddress(TargetAddress), TargetFlags(TargetFlags) {
+ Initialized = true;
+ }
/// Constructor for zero-fill symbols/sections.
MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
- : Size(Size), TargetAddress(TargetAddress) {}
+ : Size(Size), TargetAddress(TargetAddress) {
+ Initialized = true;
+ }
/// Returns true if this is a zero-fill symbol/section.
bool isZeroFill() const {
- assert(Size && "setContent/setZeroFill must be called first");
+ assert(Initialized && "setZeroFill / setContent not called");
return !ContentPtr;
}
/// Set the content for this memory region.
void setContent(ArrayRef<char> Content) {
- assert(!ContentPtr && !Size && "Content/zero-fill already set");
+ assert(!Initialized && "Content/zero-fill already set");
ContentPtr = Content.data();
Size = Content.size();
+ Initialized = true;
}
/// Set a zero-fill length for this memory region.
void setZeroFill(uint64_t Size) {
- assert(!ContentPtr && !this->Size && "Content/zero-fill already set");
+ assert(!Initialized && "Content/zero-fill already set");
this->Size = Size;
+ Initialized = true;
}
/// Returns the content for this section if there is any.
@@ -145,7 +151,8 @@ class RuntimeDyldChecker {
private:
const char *ContentPtr = nullptr;
- uint64_t Size = 0;
+ uint64_t Size : 63;
+ uint64_t Initialized : 1;
JITTargetAddress TargetAddress = 0;
TargetFlagsType TargetFlags = 0;
};
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_zero_sized_symbols_with_show_addrs.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_zero_sized_symbols_with_show_addrs.s
new file mode 100644
index 0000000000000..2ddd545de3953
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_zero_sized_symbols_with_show_addrs.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -triple=aarch64-unknown-linux-gnu \
+# RUN: -position-independent -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec -show-addrs %t.o | FileCheck %s
+
+# Check that show-addrs works with zero-sized symbols.
+
+# CHECK: main{{.*}}target addr =
+
+ .text
+ .globl main
+ .p2align 2
+ .type main, at function
+main:
+ mov w0, wzr
+ ret
+ .size main, 0
diff --git a/llvm/test/ExecutionEngine/JITLink/Generic/llvm-jitlink-option-show-addrs.test b/llvm/test/ExecutionEngine/JITLink/Generic/llvm-jitlink-option-show-addrs.test
new file mode 100644
index 0000000000000..96635f57a09f9
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/Generic/llvm-jitlink-option-show-addrs.test
@@ -0,0 +1,14 @@
+# RUN: llc -filetype=obj -o %t.o %S/Inputs/main-ret-0.ll
+# RUN: llvm-jitlink -noexec -show-addrs %t.o | FileCheck %s
+#
+# Check that the llvm-jitlink -show-addrs option reports an address for main.
+
+# Jitlink does not support ARM64 COFF files.
+# UNSUPPORTED: target=aarch64-{{.*}}-windows-{{.*}}
+
+# On MinGW targets, when compiling the main() function, it gets
+# an implicitly generated call to __main(), which is missing in
+# this context.
+# XFAIL: target={{.*}}-windows-gnu
+
+# CHECK: main{{.*}} target addr = 0x{{[[:xdigit:]]+}}, content:
\ No newline at end of file
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index 8bd17ebb6317a..0ba04eba89f47 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -176,6 +176,8 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) {
}
// Add symbol info for absolute symbols.
+ // MemoryRegionInfo doesn't support zero-sized symbols, so use a minimum of
+ // 1.
for (auto *Sym : G.absolute_symbols())
S.SymbolInfos[Sym->getName()] = {Sym->getSize(),
Sym->getAddress().getValue()};
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 7732992f77cb3..f6b86307798cc 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -418,11 +418,16 @@ namespace llvm {
static raw_ostream &
operator<<(raw_ostream &OS, const Session::MemoryRegionInfo &MRI) {
- return OS << "target addr = "
- << format("0x%016" PRIx64, MRI.getTargetAddress())
- << ", content: " << (const void *)MRI.getContent().data() << " -- "
- << (const void *)(MRI.getContent().data() + MRI.getContent().size())
- << " (" << MRI.getContent().size() << " bytes)";
+ OS << "target addr = " << format("0x%016" PRIx64, MRI.getTargetAddress());
+
+ if (MRI.isZeroFill())
+ OS << ", zero-fill: " << MRI.getZeroFillLength() << " bytes";
+ else
+ OS << ", content: " << (const void *)MRI.getContent().data() << " -- "
+ << (const void *)(MRI.getContent().data() + MRI.getContent().size())
+ << " (" << MRI.getContent().size() << " bytes)";
+
+ return OS;
}
static raw_ostream &
@@ -1396,7 +1401,7 @@ void Session::modifyPassConfig(LinkGraph &G, PassConfiguration &PassConfig) {
if (ShowLinkedFiles)
outs() << "Linking " << G.getName() << "\n";
- if (!CheckFiles.empty())
+ if (!CheckFiles.empty() || ShowAddrs)
PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) {
if (ES.getTargetTriple().getObjectFormat() == Triple::ELF)
return registerELFGraphInfo(*this, G);
More information about the llvm-commits
mailing list