[llvm] Reland: [ORC] Tailor ELF debugger support plugin to load-address patching only (PR #169482)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 17 01:52:27 PST 2025


Stefan =?utf-8?q?Gränitz?= <stefan.graenitz at gmail.com>,
Stefan =?utf-8?q?Gränitz?= <stefan.graenitz at gmail.com>,
Stefan =?utf-8?q?Gränitz?= <stefan.graenitz at gmail.com>,
Stefan =?utf-8?q?Gränitz?= <stefan.graenitz at gmail.com>,
Stefan =?utf-8?q?Gränitz?= <stefan.graenitz at gmail.com>,
Stefan =?utf-8?q?Gränitz?= <stefan.graenitz at gmail.com>,
Stefan =?utf-8?q?Gränitz?= <stefan.graenitz at gmail.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/169482 at github.com>


================
@@ -419,91 +186,165 @@ ELFDebugObjectPlugin::ELFDebugObjectPlugin(ExecutionSession &ES,
 
 ELFDebugObjectPlugin::~ELFDebugObjectPlugin() = default;
 
+static const std::set<StringRef> DwarfSectionNames = {
+#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
+  ELF_NAME,
+#include "llvm/BinaryFormat/Dwarf.def"
+#undef HANDLE_DWARF_SECTION
+};
+
+static bool isDwarfSection(StringRef SectionName) {
+  return DwarfSectionNames.count(SectionName) == 1;
+}
+
 void ELFDebugObjectPlugin::notifyMaterializing(
     MaterializationResponsibility &MR, LinkGraph &G, JITLinkContext &Ctx,
-    MemoryBufferRef ObjBuffer) {
-  std::lock_guard<std::mutex> Lock(PendingObjsLock);
-  assert(PendingObjs.count(&MR) == 0 &&
-         "Cannot have more than one pending debug object per "
-         "MaterializationResponsibility");
-
-  if (auto DebugObj = createDebugObjectFromBuffer(ES, G, Ctx, ObjBuffer)) {
-    // Not all link artifacts allow debugging.
-    if (*DebugObj == nullptr)
-      return;
-    if (RequireDebugSections && !(**DebugObj).hasFlags(HasDebugSections)) {
-      LLVM_DEBUG(dbgs() << "Skipping debug registration for LinkGraph '"
-                        << G.getName() << "': no debug info\n");
-      return;
-    }
-    PendingObjs[&MR] = std::move(*DebugObj);
-  } else {
-    ES.reportError(DebugObj.takeError());
+    MemoryBufferRef InputObj) {
+  if (InputObj.getBufferSize() == 0)
+    return;
+  if (G.getTargetTriple().getObjectFormat() != Triple::ELF)
+    return;
+
+  unsigned char Class, Endian;
+  std::tie(Class, Endian) = getElfArchType(InputObj.getBuffer());
+  if (Class != ELF::ELFCLASS64 && Class != ELF::ELFCLASS32)
+    return ES.reportError(
+        createStringError(object_error::invalid_file_type,
+                          "Skipping debug object registration: Invalid arch "
+                          "0x%02x in ELF LinkGraph %s",
+                          Class, G.getName().c_str()));
+  if (Endian != ELF::ELFDATA2LSB && Endian != ELF::ELFDATA2MSB)
+    return ES.reportError(
+        createStringError(object_error::invalid_file_type,
+                          "Skipping debug object registration: Invalid endian "
+                          "0x%02x in ELF LinkGraph %s",
+                          Endian, G.getName().c_str()));
+
+  // Step 1: We copy the raw input object into the working memory of a
+  // single-segment read-only allocation
+  size_t Size = InputObj.getBufferSize();
+  auto Alignment = sys::Process::getPageSizeEstimate();
+  SimpleSegmentAlloc::Segment Segment{Size, Align(Alignment)};
+
+  auto Alloc = SimpleSegmentAlloc::Create(
+      Ctx.getMemoryManager(), ES.getSymbolStringPool(), ES.getTargetTriple(),
+      Ctx.getJITLinkDylib(), {{MemProt::Read, Segment}});
+  if (!Alloc) {
+    ES.reportError(Alloc.takeError());
+    return;
   }
+
+  std::lock_guard<std::mutex> Lock(PendingObjsLock);
+  assert(PendingObjs.count(&MR) == 0 && "One debug object per materialization");
+  PendingObjs[&MR] = std::make_unique<DebugObject>(
+      InputObj.getBufferIdentifier(), std::move(*Alloc), Ctx, ES);
+
+  MutableArrayRef<char> Buffer = PendingObjs[&MR]->getBuffer();
+  memcpy(Buffer.data(), InputObj.getBufferStart(), Size);
+}
+
+DebugObject *
+ELFDebugObjectPlugin::getPendingDebugObj(MaterializationResponsibility &MR) {
+  std::lock_guard<std::mutex> Lock(PendingObjsLock);
+  auto It = PendingObjs.find(&MR);
+  return It == PendingObjs.end() ? nullptr : It->second.get();
 }
 
 void ELFDebugObjectPlugin::modifyPassConfig(MaterializationResponsibility &MR,
                                             LinkGraph &G,
                                             PassConfiguration &PassConfig) {
-  // Not all link artifacts have associated debug objects.
-  std::lock_guard<std::mutex> Lock(PendingObjsLock);
-  auto It = PendingObjs.find(&MR);
-  if (It == PendingObjs.end())
+  if (!getPendingDebugObj(MR))
     return;
 
-  DebugObject &DebugObj = *It->second;
-  if (DebugObj.hasFlags(ReportFinalSectionLoadAddresses)) {
-    PassConfig.PostAllocationPasses.push_back(
-        [&DebugObj](LinkGraph &Graph) -> Error {
-          for (const Section &GraphSection : Graph.sections())
-            DebugObj.reportSectionTargetMemoryRange(GraphSection.getName(),
-                                                    SectionRange(GraphSection));
-          return Error::success();
+  PassConfig.PostAllocationPasses.push_back([this, &MR](LinkGraph &G) -> Error {
+    size_t SectionsPatched = 0;
+    bool HasDebugSections = false;
+    DebugObject *DebugObj = getPendingDebugObj(MR);
+    assert(DebugObj && "Don't inject passes if we have no debug object");
+
+    // Step 2: Once the target memory layout is ready, we write the
+    // addresses of the LinkGraph sections into the load-address fields of the
+    // section headers in our debug object allocation
+    Error Err = DebugObj->visitSections(
+        [&G, &SectionsPatched, &HasDebugSections](StringRef Name) {
+          SectionsPatched += 1;
+          if (isDwarfSection(Name))
+            HasDebugSections = true;
+          Section *S = G.findSectionByName(Name);
+          assert(S && "No graph section for object section");
----------------
nikic wrote:

I think the right fix here is probably to just replace the assert with a check? I took a stab at that here: https://github.com/llvm/llvm-project/pull/172622

https://github.com/llvm/llvm-project/pull/169482


More information about the llvm-commits mailing list