aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-readobj
diff options
context:
space:
mode:
authorMartin Storsjö <martin@martin.st>2019-11-25 15:26:13 +0200
committerMartin Storsjö <martin@martin.st>2019-12-11 10:20:34 +0200
commitaf39708c2d48beedc6721fe25676789cc6719f7b (patch)
tree74a56c0042818cb0fef4e71fd2077978ae235c1c /llvm/tools/llvm-readobj
parentf99297176cd9507393b69029406080de01ae41c7 (diff)
downloadllvm-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.cpp8
-rw-r--r--llvm/tools/llvm-readobj/Win64EHDumper.cpp54
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;