[llvm] [llvm-readobj][COFF] Implement --coff-pseudoreloc in llvm-readobj to dump runtime pseudo-relocation records (PR #151816)

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 22 02:21:51 PDT 2025


================
@@ -2002,52 +2002,125 @@ void COFFDumper::printCOFFBaseReloc() {
 }
 
 void COFFDumper::printCOFFPseudoReloc() {
+  ListScope D(W, "PseudoReloc");
+
+  // Pseudo-relocations are only meaningful with PE image files.
+  if (!Obj->getDOSHeader())
+    return;
+
   const StringRef RelocBeginName = Obj->getArch() == Triple::x86
                                        ? "___RUNTIME_PSEUDO_RELOC_LIST__"
                                        : "__RUNTIME_PSEUDO_RELOC_LIST__";
   const StringRef RelocEndName = Obj->getArch() == Triple::x86
                                      ? "___RUNTIME_PSEUDO_RELOC_LIST_END__"
                                      : "__RUNTIME_PSEUDO_RELOC_LIST_END__";
 
-  COFFSymbolRef RelocBegin, RelocEnd;
-  auto Count = Obj->getNumberOfSymbols();
-  if (Count == 0) {
-    W.startLine() << "The symbol table has been stripped\n";
+  const uint32_t Count = Obj->getNumberOfSymbols();
+  // Skip if no symbol was found (maybe stripped).
+  if (Count == 0)
     return;
-  }
-  for (auto i = 0u;
-       i < Count && (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()); ++i) {
-    auto Sym = Obj->getSymbol(i);
-    if (Sym.takeError())
+
+  struct SymbolEntry {
+    uint32_t RVA;
+    COFFSymbolRef Symbol;
+    const coff_section *Section;
+    StringRef SymbolName;
+  };
+  SmallVector<SymbolEntry> RVASymbolMap;
+  COFFSymbolRef RelocBegin, RelocEnd;
+  for (uint32_t i = 0; i < Count; ++i) {
+    COFFSymbolRef Sym;
+    if (Expected<COFFSymbolRef> SymOrErr = Obj->getSymbol(i)) {
+      Sym = *SymOrErr;
+    } else {
+      reportUniqueWarning(SymOrErr.takeError());
+      continue;
+    }
+
+    i += Sym.getNumberOfAuxSymbols();
+
+    if (Sym.getSectionNumber() <= 0)
+      continue;
+
+    StringRef Name;
+    if (Expected<StringRef> NameOrErr = Obj->getSymbolName(Sym)) {
+      Name = *NameOrErr;
+    } else {
+      reportUniqueWarning(NameOrErr.takeError());
       continue;
-    auto Name = Obj->getSymbolName(*Sym);
-    if (Name.takeError())
+    }
+
+    if (Name == RelocBeginName)
+      RelocBegin = Sym;
+    else if (Name == RelocEndName)
+      RelocEnd = Sym;
+
+    const coff_section *Sec = nullptr;
+    if (Expected<const coff_section *> SecOrErr =
+            Obj->getSection(Sym.getSectionNumber())) {
+      Sec = *SecOrErr;
+    } else {
+      reportUniqueWarning(SecOrErr.takeError());
       continue;
-    if (*Name == RelocBeginName) {
-      if (Sym->getSectionNumber() > 0)
-        RelocBegin = *Sym;
-    } else if (*Name == RelocEndName) {
-      if (Sym->getSectionNumber() > 0)
-        RelocEnd = *Sym;
     }
+
+    RVASymbolMap.push_back(
+        {Sec->VirtualAddress + Sym.getValue(), Sym, Sec, Name});
   }
+
   if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
-    W.startLine()
-        << "The symbols for runtime pseudo-relocation are not found\n";
+    reportUniqueWarning(createStringError(
+        "the marker symbols for runtime pseudo-relocation were not found"));
+    return;
+  }
+
+  const coff_section *Section = nullptr;
+  if (Expected<const coff_section *> SecOrErr =
+          Obj->getSection(RelocBegin.getSectionNumber())) {
+    Section = *SecOrErr;
+  } else {
+    reportUniqueWarning(SecOrErr.takeError());
+    return;
+  }
+
+  if (RelocBegin.getSectionNumber() != RelocEnd.getSectionNumber()) {
+    reportUniqueWarning(createStringError(
+        "the end marker symbol for runtime pseudo-relocation must "
+        "point to the same section where the begin marker points to: "
+        "expected %d, but got %d",
+        RelocBegin.getSectionNumber(), RelocEnd.getSectionNumber()));
+    return;
+  }
+
+  // Skip if the relocation list is empty.
+  if (RelocBegin.getValue() == RelocEnd.getValue())
+    return;
+
+  if (RelocEnd.getValue() < RelocBegin.getValue()) {
+    reportUniqueWarning(createStringError(
+        "the end marker symbol for runtime pseudo-relocation must point "
+        "to a higher address than where the begin marker points to: "
+        "expected >=0x%x, but got 0x%x",
+        RelocBegin.getValue(), RelocEnd.getValue()));
     return;
   }
 
   ArrayRef<uint8_t> Data;
-  auto Section = Obj->getSection(RelocBegin.getSectionNumber());
-  if (auto E = Section.takeError()) {
-    reportError(std::move(E), Obj->getFileName());
+  if (auto E = Obj->getSectionContents(Section, Data)) {
+    reportUniqueWarning(std::move(E));
     return;
   }
-  if (auto E = Obj->getSectionContents(*Section, Data)) {
-    reportError(std::move(E), Obj->getFileName());
+
+  if (const uint32_t Begin = RelocBegin.getValue(), End = RelocEnd.getValue();
+      Begin >= Data.size() || End > Data.size()) {
+    reportUniqueWarning(
+        createStringError("the marker symbol of runtime pseudo-relocation "
+                          "points past the end of the section: 0x%x",
----------------
jh7370 wrote:

I don't think it's 100% obvious that this value is the actual offset or the section end offset. Perhaps both should be present?

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


More information about the llvm-commits mailing list