[llvm] [llvm-readobj][COFF] Implement --coff-pseudoreloc in llvm-readobj to dump runtime pseudo-relocation records (PR #151816)
Martin Storsjö via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 4 04:56:43 PDT 2025
================
@@ -2000,6 +2001,122 @@ void COFFDumper::printCOFFBaseReloc() {
}
}
+void COFFDumper::printCOFFPseudoReloc() {
+ 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";
+ return;
+ }
+ for (auto i = 0u;
+ i < Count && (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()); ++i) {
+ auto Sym = Obj->getSymbol(i);
+ if (Sym.takeError())
+ continue;
+ auto Name = Obj->getSymbolName(*Sym);
+ if (Name.takeError())
+ continue;
+ if (*Name == RelocBeginName) {
+ if (Sym->getSectionNumber() > 0)
+ RelocBegin = *Sym;
+ } else if (*Name == RelocEndName) {
+ if (Sym->getSectionNumber() > 0)
+ RelocEnd = *Sym;
+ }
+ }
+ if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {
+ W.startLine()
+ << "The symbols for runtime pseudo-relocation are not found\n";
+ return;
+ }
+
+ ArrayRef<uint8_t> Data;
+ auto Section = Obj->getSection(RelocBegin.getSectionNumber());
+ if (auto E = Section.takeError()) {
+ reportError(std::move(E), Obj->getFileName());
+ return;
+ }
+ if (auto E = Obj->getSectionContents(*Section, Data)) {
+ reportError(std::move(E), Obj->getFileName());
+ return;
+ }
+ ArrayRef<uint8_t> RawRelocs =
+ Data.take_front(RelocEnd.getValue()).drop_front(RelocBegin.getValue());
+ struct alignas(4) PseudoRelocationHeader {
+ PseudoRelocationHeader(uint32_t Signature)
+ : Zero1(0), Zero2(0), Signature(Signature) {}
+ support::ulittle32_t Zero1;
+ support::ulittle32_t Zero2;
+ support::ulittle32_t Signature;
+ };
+ const PseudoRelocationHeader HeaderV2(1);
+ if (RawRelocs.size() < sizeof(HeaderV2) ||
+ (memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) {
+ reportWarning(
+ createStringError("Invalid runtime pseudo-relocation records"),
+ Obj->getFileName());
+ return;
+ }
+ struct alignas(4) PseudoRelocationRecord {
+ support::ulittle32_t Symbol;
+ support::ulittle32_t Target;
+ support::ulittle32_t BitSize;
+ };
+ ArrayRef<PseudoRelocationRecord> RelocRecords(
+ reinterpret_cast<const PseudoRelocationRecord *>(
+ RawRelocs.data() + sizeof(PseudoRelocationHeader)),
+ (RawRelocs.size() - sizeof(PseudoRelocationHeader)) /
+ sizeof(PseudoRelocationRecord));
+
+ struct CachingImportedSymbolLookup {
+ const StringRef *find(const COFFObjectFile *Obj, uint32_t EntryRVA) {
+ if (auto Ite = ImportedSymbols.find(EntryRVA);
+ Ite != ImportedSymbols.end())
+ return &Ite->second;
+
+ for (auto D : Obj->import_directories()) {
+ uint32_t RVA;
+ if (auto E = D.getImportAddressTableRVA(RVA))
+ reportError(std::move(E), Obj->getFileName());
+ if (EntryRVA < RVA)
+ continue;
----------------
mstorsjo wrote:
Is there a similar check we could do, `if (EntryRVA > RVA + ImportAddressTableSize)` to avoid iterating over the table, if we easily could see that the address is past the end of this table?
https://github.com/llvm/llvm-project/pull/151816
More information about the llvm-commits
mailing list