diff options
author | Martin Storsjö <martin@martin.st> | 2019-11-25 15:26:13 +0200 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2019-12-11 10:20:34 +0200 |
commit | af39708c2d48beedc6721fe25676789cc6719f7b (patch) | |
tree | 74a56c0042818cb0fef4e71fd2077978ae235c1c /llvm/tools/llvm-readobj | |
parent | f99297176cd9507393b69029406080de01ae41c7 (diff) | |
download | llvm-af39708c2d48beedc6721fe25676789cc6719f7b.zip llvm-af39708c2d48beedc6721fe25676789cc6719f7b.tar.gz llvm-af39708c2d48beedc6721fe25676789cc6719f7b.tar.bz2 |
[llvm-readobj] Fix/improve printing WinEH unwind info for linked PE images
ARMWinEHPrinter was already designed to handle linked PE images
(since d2941b43f40d), but resolving symbols didn't consistently
take the image base into account (as linked images seldom have a
symbol table, except for in MinGW setups).
Win64EHDumper wasn't really designed to handle linked images (it would
crash if executed on such a file), but a few concepts (getSymbol,
taking a virtual address instead of a relocation, and
getSectionContaining for finding the section containing a certain
virtual address) can be borrowed from ARMWinEHPrinter.
Adjust ARMWinEHPrinter to print the address of the exception handler
routine as a VA instead of an RVA, consistently with other addresses
in the same printout, and make Win64EHDumper print addresses similarly
for image cases.
Differential Revision: https://reviews.llvm.org/D71303
Diffstat (limited to 'llvm/tools/llvm-readobj')
-rw-r--r-- | llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp | 8 | ||||
-rw-r--r-- | llvm/tools/llvm-readobj/Win64EHDumper.cpp | 54 |
2 files changed, 56 insertions, 6 deletions
diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp index 3e026f5..8f365c5 100644 --- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp +++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp @@ -884,7 +884,7 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, } if (XData.X()) { - const uint32_t Address = XData.ExceptionHandlerRVA(); + const uint64_t Address = COFF.getImageBase() + XData.ExceptionHandlerRVA(); const uint32_t Parameter = XData.ExceptionHandlerParameter(); const size_t HandlerOffset = HeaderWords(XData) + (XData.E() ? 0 : XData.EpilogueCount()) @@ -896,7 +896,8 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true); if (!Symbol) { ListScope EHS(SW, "ExceptionHandler"); - SW.printString("Routine", "(null)"); + SW.printHex("Routine", Address); + SW.printHex("Parameter", Parameter); return true; } @@ -925,7 +926,8 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF, ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset); if (!Function) - Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true); + Function = getSymbol(COFF, COFF.getImageBase() + RF.BeginAddress, + /*FunctionOnly=*/true); ErrorOr<SymbolRef> XDataRecord = getRelocatedSymbol(COFF, Section, Offset + 4); if (!XDataRecord) diff --git a/llvm/tools/llvm-readobj/Win64EHDumper.cpp b/llvm/tools/llvm-readobj/Win64EHDumper.cpp index fa268ce..380baae 100644 --- a/llvm/tools/llvm-readobj/Win64EHDumper.cpp +++ b/llvm/tools/llvm-readobj/Win64EHDumper.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "Win64EHDumper.h" +#include "Error.h" #include "llvm-readobj.h" #include "llvm/Object/COFF.h" #include "llvm/Support/ErrorHandling.h" @@ -111,6 +112,20 @@ static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) { } } +static std::error_code getSymbol(const COFFObjectFile &COFF, uint64_t VA, + object::SymbolRef &Sym) { + for (const auto &Symbol : COFF.symbols()) { + Expected<uint64_t> Address = Symbol.getAddress(); + if (!Address) + return errorToErrorCode(Address.takeError()); + if (*Address == VA) { + Sym = Symbol; + return readobj_error::success; + } + } + return readobj_error::unknown_symbol; +} + static std::string formatSymbol(const Dumper::Context &Ctx, const coff_section *Section, uint64_t Offset, uint32_t Displacement) { @@ -131,9 +146,22 @@ static std::string formatSymbol(const Dumper::Context &Ctx, // TODO: Actually report errors helpfully. consumeError(Name.takeError()); } + } else if (!getSymbol(Ctx.COFF, Ctx.COFF.getImageBase() + Displacement, + Symbol)) { + Expected<StringRef> Name = Symbol.getName(); + if (Name) { + OS << *Name; + OS << format(" (0x%" PRIX64 ")", Ctx.COFF.getImageBase() + Displacement); + return OS.str(); + } else { + consumeError(Name.takeError()); + } } - OS << format(" (0x%" PRIX64 ")", Offset); + if (Displacement > 0) + OS << format("(0x%" PRIX64 ")", Ctx.COFF.getImageBase() + Displacement); + else + OS << format("(0x%" PRIX64 ")", Offset); return OS.str(); } @@ -159,6 +187,18 @@ static std::error_code resolveRelocation(const Dumper::Context &Ctx, return std::error_code(); } +static const object::coff_section * +getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) { + for (const auto &Section : COFF.sections()) { + uint64_t Address = Section.getAddress(); + uint64_t Size = Section.getSize(); + + if (VA >= Address && (VA - Address) <= Size) + return COFF.getCOFFSection(Section); + } + return nullptr; +} + namespace llvm { namespace Win64EH { void Dumper::printRuntimeFunctionEntry(const Context &Ctx, @@ -284,9 +324,18 @@ void Dumper::printRuntimeFunction(const Context &Ctx, DictScope RFS(SW, "RuntimeFunction"); printRuntimeFunctionEntry(Ctx, Section, SectionOffset, RF); - const coff_section *XData; + const coff_section *XData = nullptr; uint64_t Offset; resolveRelocation(Ctx, Section, SectionOffset + 8, XData, Offset); + Offset = Offset + RF.UnwindInfoOffset; + + if (!XData) { + uint64_t Address = Ctx.COFF.getImageBase() + RF.UnwindInfoOffset; + XData = getSectionContaining(Ctx.COFF, Address); + if (!XData) + return; + Offset = RF.UnwindInfoOffset - XData->VirtualAddress; + } ArrayRef<uint8_t> Contents; if (Error E = Ctx.COFF.getSectionContents(XData, Contents)) @@ -295,7 +344,6 @@ void Dumper::printRuntimeFunction(const Context &Ctx, if (Contents.empty()) return; - Offset = Offset + RF.UnwindInfoOffset; if (Offset > Contents.size()) return; |