[llvm] [Orc] Initial version of ELFSymtabStaticGenerator (PR #135591)

via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 13 23:25:42 PDT 2025


https://github.com/stmonty created https://github.com/llvm/llvm-project/pull/135591

Hello! This is my first contribution attempt here.  I have been working with on [jank](https://github.com/jank-lang/jank) which uses the Orcv2 machinery for the JIT compilation. I think @lhames might know about this.

One problem we have encountered was that when the Jank binary was fully statically built no symbols were able to be found. This PR ties to remedy that for ELF binaries by opening the current binary and using the `symtab` portion of the ELF binary to find missing symbols.

Any comments for improvements are greatly appreciated!

>From e459e5db7c6960381fb7452b4d40f2a065527fe2 Mon Sep 17 00:00:00 2001
From: stmonty <stmontydev at gmail.com>
Date: Sun, 13 Apr 2025 23:16:00 -0700
Subject: [PATCH] Initial version of ELFSymtabStaticGenerator

Modified-by: stmonty <stmontydev at gmail.com>
---
 .../Orc/ELFStaticSymtabGenerator.h            | 26 +++++++
 .../Orc/ELFStaticSymtabGenerator.cpp          | 78 +++++++++++++++++++
 2 files changed, 104 insertions(+)
 create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/ELFStaticSymtabGenerator.h
 create mode 100644 llvm/lib/ExecutionEngine/Orc/ELFStaticSymtabGenerator.cpp

diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ELFStaticSymtabGenerator.h b/llvm/include/llvm/ExecutionEngine/Orc/ELFStaticSymtabGenerator.h
new file mode 100644
index 0000000000000..0010babb72aff
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ELFStaticSymtabGenerator.h
@@ -0,0 +1,26 @@
+#ifndef LLVM_EXECUTIONENGINE_ORC_ELFSTATICSYMTABGENERATOR_H
+#define LLVM_EXECUTIONENGINE_ORC_ELFSTATICSYMTABGENERATOR_H
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Mangling.h"
+
+namespace llvm {
+namespace orc {
+
+class ELFStaticSymtabGenerator : public DefinitionGenerator {
+public:
+  ELFStaticSymtabGenerator(ExecutionSession &ES);
+  
+  Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
+                      JITDylibLookupFlags JDLookupFlags,
+                      const SymbolLookupSet &Symbols) override;
+private:
+  ExecutionSession &ES;
+  std::map<SymbolStringPtr, JITTargetAddress> StaticSymbols;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_ELFSTATICSYMTABGENERATOR_H
diff --git a/llvm/lib/ExecutionEngine/Orc/ELFStaticSymtabGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/ELFStaticSymtabGenerator.cpp
new file mode 100644
index 0000000000000..8df6c3763facd
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/ELFStaticSymtabGenerator.cpp
@@ -0,0 +1,78 @@
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/ExecutionEngine/Orc/ELFStaticSymtabGenerator.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Error.h"
+
+#define DEBUG_TYPE "orc"
+
+namespace llvm {
+namespace orc {
+
+ELFStaticSymtabGenerator::ELFStaticSymtabGenerator(ExecutionSession &ES) : ES(ES) {
+  auto MBOrErr = MemoryBuffer::getFile("/proc/self/exe");
+  if (!MBOrErr) {
+    return;
+  }
+  std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
+  auto ObjOrErr = object::ObjectFile::createObjectFile(MB->getMemBufferRef());
+  if (!ObjOrErr) {
+    consumeError(ObjOrErr.takeError());
+    return;
+  }
+  auto *Obj = ObjOrErr->get();
+
+  for (const auto &Sym : Obj->symbols()) {
+    Expected<StringRef> NameOrErr = Sym.getName();
+    if (!NameOrErr) {
+      consumeError(NameOrErr.takeError());
+      continue;
+    }
+    StringRef Name = *NameOrErr;
+
+    // Retrieve the symbol flags.
+    Expected<uint32_t> FlagsOrErr = Sym.getFlags();
+    if (!FlagsOrErr) {
+      consumeError(FlagsOrErr.takeError());
+      continue;
+    }
+    uint32_t Flags = *FlagsOrErr;
+
+    // Only add symbols that are defined.
+    if (!(Flags & object::BasicSymbolRef::SF_Undefined)) {
+      Expected<uint64_t> AddrOrErr = Sym.getAddress();
+      if (!AddrOrErr) {
+        consumeError(AddrOrErr.takeError());
+        continue;
+      }
+      JITTargetAddress Addr = *AddrOrErr;
+      // Intern the symbol name using the ExecutionSession's symbol pool.
+      SymbolStringPtr SSP = ES.getSymbolStringPool()->intern(Name);
+      StaticSymbols[SSP] = Addr;
+    }
+  }
+}
+
+Error ELFStaticSymtabGenerator::tryToGenerate(LookupState &LS, LookupKind K,
+                                              JITDylib &JD,
+                                              JITDylibLookupFlags JDLookupFlags,
+                                              const SymbolLookupSet &Symbols) {
+
+  SymbolMap NewSymbols;
+  for (auto &KV : Symbols) {
+    SymbolStringPtr Name = KV.first;
+    if (auto It = StaticSymbols.find(Name); It != StaticSymbols.end()) {
+      JITEvaluatedSymbol Sym(It->second, JITSymbolFlags::Exported);
+      NewSymbols[Name] = ExecutorSymbolDef(ExecutorAddr(It->second), JITSymbolFlags::Exported);
+    }
+  }
+  // If any symbols were found, add them to the JITDylib.
+  if (!NewSymbols.empty())
+    return JD.define(absoluteSymbols(std::move(NewSymbols)));
+  return Error::success();
+}
+  
+} // end namespace orc
+} // end namespace llvm
+



More information about the llvm-commits mailing list