[llvm] fea987b - [ORC] Fix unchecked Expected<T> in ELFDebugObjectPlugin::FinalizePromise (#172904)

via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 20 08:11:41 PST 2025


Author: Stefan Gränitz
Date: 2025-12-20T17:11:36+01:00
New Revision: fea987b5eee274357b5ee99d33f1a95ad934fd3a

URL: https://github.com/llvm/llvm-project/commit/fea987b5eee274357b5ee99d33f1a95ad934fd3a
DIFF: https://github.com/llvm/llvm-project/commit/fea987b5eee274357b5ee99d33f1a95ad934fd3a.diff

LOG: [ORC] Fix unchecked Expected<T> in ELFDebugObjectPlugin::FinalizePromise (#172904)

If `Alloc.finalize()` fails in the post-allocation pass, we store the
error in `FinalizePromise`. If we don't reach the post-fixup pass
afterwards the error will leak. This patch adds another case in the
DebugObject destructor that will check the `Expected<T>` and report the
error.

Added: 
    

Modified: 
    llvm/lib/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.cpp
index 5ffc6326938b3..e67eb323c3540 100644
--- a/llvm/lib/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.cpp
@@ -54,15 +54,12 @@ class DebugObject {
         MemMgr(Ctx.getMemoryManager()), ES(ES) {}
 
   ~DebugObject() {
+    assert(!FinalizeFuture.valid());
     if (Alloc) {
       std::vector<FinalizedAlloc> Allocs;
       Allocs.push_back(std::move(Alloc));
       if (Error Err = MemMgr.deallocate(std::move(Allocs)))
         ES.reportError(std::move(Err));
-    } else if (!FinalizeFuture.valid()) {
-      // WorkingMem was not finalized
-      WorkingMem.abandon(
-          [ES = &this->ES](Error Err) { ES->reportError(std::move(Err)); });
     }
   }
 
@@ -71,7 +68,7 @@ class DebugObject {
     return SegInfo.WorkingMem;
   }
 
-  SimpleSegmentAlloc takeTargetAlloc() {
+  SimpleSegmentAlloc collectTargetAlloc() {
     FinalizeFuture = FinalizePromise.get_future();
     return std::move(WorkingMem);
   }
@@ -88,6 +85,19 @@ class DebugObject {
     FinalizePromise.set_value(std::move(Err));
   }
 
+  void releasePendingResources() {
+    if (FinalizeFuture.valid()) {
+      // Error before step 4: Finalization error was not reported
+      Expected<ExecutorAddrRange> TargetMem = FinalizeFuture.get();
+      if (!TargetMem)
+        ES.reportError(TargetMem.takeError());
+    } else {
+      // Error before step 3: WorkingMem was not collected
+      WorkingMem.abandon(
+          [ES = &this->ES](Error Err) { ES->reportError(std::move(Err)); });
+    }
+  }
+
   using GetLoadAddressFn = llvm::unique_function<ExecutorAddr(StringRef)>;
   Error visitSections(GetLoadAddressFn Callback);
 
@@ -296,7 +306,7 @@ void ELFDebugObjectPlugin::modifyPassConfig(MaterializationResponsibility &MR,
     }
 
     // Step 3: We start copying the debug object into target memory
-    SimpleSegmentAlloc Alloc = DebugObj->takeTargetAlloc();
+    SimpleSegmentAlloc Alloc = DebugObj->collectTargetAlloc();
 
     // FIXME: FA->getAddress() below is supposed to be the address of the memory
     // range on the target, but InProcessMemoryManager returns the address of a
@@ -304,7 +314,16 @@ void ELFDebugObjectPlugin::modifyPassConfig(MaterializationResponsibility &MR,
     auto ROSeg = Alloc.getSegInfo(MemProt::Read);
     ExecutorAddrRange R(ROSeg.Addr, ROSeg.WorkingMem.size());
     Alloc.finalize([this, R, &MR](Expected<DebugObject::FinalizedAlloc> FA) {
-      DebugObject *DebugObj = getPendingDebugObj(MR);
+      // Bail out if materialization failed in the meantime
+      std::lock_guard<std::mutex> Lock(PendingObjsLock);
+      auto It = PendingObjs.find(&MR);
+      if (It == PendingObjs.end()) {
+        if (!FA)
+          ES.reportError(FA.takeError());
+        return;
+      }
+
+      DebugObject *DebugObj = It->second.get();
       if (!FA)
         DebugObj->failMaterialization(FA.takeError());
 
@@ -355,7 +374,9 @@ void ELFDebugObjectPlugin::modifyPassConfig(MaterializationResponsibility &MR,
 
 Error ELFDebugObjectPlugin::notifyFailed(MaterializationResponsibility &MR) {
   std::lock_guard<std::mutex> Lock(PendingObjsLock);
-  PendingObjs.erase(&MR);
+  auto It = PendingObjs.find(&MR);
+  It->second->releasePendingResources();
+  PendingObjs.erase(It);
   return Error::success();
 }
 


        


More information about the llvm-commits mailing list