summaryrefslogtreecommitdiff
path: root/tools/llvm-readobj/COFFDumper.cpp
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2014-05-25 20:26:45 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2014-05-25 20:26:45 +0000
commitb6a667f0335027a8ed673d29af11fc6653781c11 (patch)
tree608ef78554c440ee0d96e76d6017635bd95e13a3 /tools/llvm-readobj/COFFDumper.cpp
parent53046f3c5f5a747bfcb4e5700ed5e3b5b2506afe (diff)
downloadllvm-b6a667f0335027a8ed673d29af11fc6653781c11.tar.gz
llvm-b6a667f0335027a8ed673d29af11fc6653781c11.tar.bz2
llvm-b6a667f0335027a8ed673d29af11fc6653781c11.tar.xz
tools: split out Win64EHDumper from COFFDumper
Move the implementation of the Win64 EH printer from the COFFDumper into its own class. This is in preparation for adding support to print ARM EH information. The only real change here is in printUnwindInfo where we now lambda lift the implicit this parameter for the resolveFunction. Also setup the printing to handle ARM. This now has set the stage to introduce ARM EH printing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209606 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-readobj/COFFDumper.cpp')
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp344
1 files changed, 16 insertions, 328 deletions
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index 1a360f5bed..7b9595f84c 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -16,6 +16,7 @@
#include "Error.h"
#include "ObjDumper.h"
#include "StreamWriter.h"
+#include "Win64EHDumper.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Object/COFF.h"
@@ -58,35 +59,19 @@ private:
void printSymbol(const SymbolRef &Sym);
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
void printDataDirectory(uint32_t Index, const std::string &FieldName);
- void printX64UnwindInfo();
template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
void printBaseOfDataField(const pe32_header *Hdr);
void printBaseOfDataField(const pe32plus_header *Hdr);
- void printRuntimeFunction(const RuntimeFunction& RTF,
- const coff_section *Section,
- uint64_t SectionOffset);
-
- void printUnwindInfo(const Win64EH::UnwindInfo& UI,
- const coff_section *Section, uint64_t SectionOffset);
-
- void printUnwindCode(const Win64EH::UnwindInfo &UI, ArrayRef<UnwindCode> UCs);
-
void printCodeViewLineTables(const SectionRef &Section);
void cacheRelocations();
- error_code resolveRelocation(const coff_section *Section, uint64_t Offset,
- const coff_section *&ReesolvedSection,
- uint64_t &ResolvedAddress);
-
error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
SymbolRef &Sym);
error_code resolveSymbolName(const coff_section *Section, uint64_t Offset,
StringRef &Name);
- std::string formatSymbol(const coff_section *Section, uint64_t Offset,
- uint32_t Disp);
typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
@@ -111,66 +96,6 @@ error_code createCOFFDumper(const object::ObjectFile *Obj, StreamWriter &Writer,
} // namespace llvm
-
-// Returns the name of the unwind code.
-static StringRef getUnwindCodeTypeName(uint8_t Code) {
- switch(Code) {
- default: llvm_unreachable("Invalid unwind code");
- case UOP_PushNonVol: return "PUSH_NONVOL";
- case UOP_AllocLarge: return "ALLOC_LARGE";
- case UOP_AllocSmall: return "ALLOC_SMALL";
- case UOP_SetFPReg: return "SET_FPREG";
- case UOP_SaveNonVol: return "SAVE_NONVOL";
- case UOP_SaveNonVolBig: return "SAVE_NONVOL_FAR";
- case UOP_SaveXMM128: return "SAVE_XMM128";
- case UOP_SaveXMM128Big: return "SAVE_XMM128_FAR";
- case UOP_PushMachFrame: return "PUSH_MACHFRAME";
- }
-}
-
-// Returns the name of a referenced register.
-static StringRef getUnwindRegisterName(uint8_t Reg) {
- switch(Reg) {
- default: llvm_unreachable("Invalid register");
- case 0: return "RAX";
- case 1: return "RCX";
- case 2: return "RDX";
- case 3: return "RBX";
- case 4: return "RSP";
- case 5: return "RBP";
- case 6: return "RSI";
- case 7: return "RDI";
- case 8: return "R8";
- case 9: return "R9";
- case 10: return "R10";
- case 11: return "R11";
- case 12: return "R12";
- case 13: return "R13";
- case 14: return "R14";
- case 15: return "R15";
- }
-}
-
-// Calculates the number of array slots required for the unwind code.
-static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
- switch (UnwindCode.getUnwindOp()) {
- default: llvm_unreachable("Invalid unwind code");
- case UOP_PushNonVol:
- case UOP_AllocSmall:
- case UOP_SetFPReg:
- case UOP_PushMachFrame:
- return 1;
- case UOP_SaveNonVol:
- case UOP_SaveXMM128:
- return 2;
- case UOP_SaveNonVolBig:
- case UOP_SaveXMM128Big:
- return 3;
- case UOP_AllocLarge:
- return (UnwindCode.getOpInfo() == 0) ? 2 : 3;
- }
-}
-
// Given a a section and an offset into this section the function returns the
// symbol used for the relocation at the offset.
error_code COFFDumper::resolveSymbol(const coff_section *Section,
@@ -381,43 +306,6 @@ WeakExternalCharacteristics[] = {
{ "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS }
};
-static const EnumEntry<unsigned> UnwindFlags[] = {
- { "ExceptionHandler", Win64EH::UNW_ExceptionHandler },
- { "TerminateHandler", Win64EH::UNW_TerminateHandler },
- { "ChainInfo" , Win64EH::UNW_ChainInfo }
-};
-
-static const EnumEntry<unsigned> UnwindOpInfo[] = {
- { "RAX", 0 },
- { "RCX", 1 },
- { "RDX", 2 },
- { "RBX", 3 },
- { "RSP", 4 },
- { "RBP", 5 },
- { "RSI", 6 },
- { "RDI", 7 },
- { "R8", 8 },
- { "R9", 9 },
- { "R10", 10 },
- { "R11", 11 },
- { "R12", 12 },
- { "R13", 13 },
- { "R14", 14 },
- { "R15", 15 }
-};
-
-static uint64_t getOffsetOfLSDA(const Win64EH::UnwindInfo& UI) {
- return static_cast<const char*>(UI.getLanguageSpecificData())
- - reinterpret_cast<const char*>(&UI);
-}
-
-static uint32_t getLargeSlotValue(ArrayRef<UnwindCode> UCs) {
- if (UCs.size() < 3)
- return 0;
-
- return UCs[1].FrameOffset + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16);
-}
-
template<typename T>
static error_code getSymbolAuxData(const COFFObjectFile *Obj,
const coff_symbol *Symbol, const T* &Aux) {
@@ -426,46 +314,6 @@ static error_code getSymbolAuxData(const COFFObjectFile *Obj,
return readobj_error::success;
}
-std::string COFFDumper::formatSymbol(const coff_section *Section,
- uint64_t Offset, uint32_t Disp) {
- std::string Buffer;
- raw_string_ostream Str(Buffer);
-
- StringRef Sym;
- if (resolveSymbolName(Section, Offset, Sym)) {
- Str << format(" (0x%" PRIX64 ")", Offset);
- return Str.str();
- }
-
- Str << Sym;
- if (Disp > 0) {
- Str << format(" +0x%X (0x%" PRIX64 ")", Disp, Offset);
- } else {
- Str << format(" (0x%" PRIX64 ")", Offset);
- }
-
- return Str.str();
-}
-
-error_code COFFDumper::resolveRelocation(const coff_section *Section,
- uint64_t Offset,
- const coff_section *&ResolvedSection,
- uint64_t &ResolvedAddress) {
- SymbolRef Sym;
- if (error_code EC = resolveSymbol(Section, Offset, Sym))
- return EC;
-
- if (error_code EC = Sym.getAddress(ResolvedAddr))
- return EC;
-
- section_iterator SI(Obj->section_begin());
- if (error_code EC = Sym.getSection(SI))
- return EC;
-
- ResolvedSection = Obj->getCOFFSection(*SI);
- return object_error::success;
-}
-
void COFFDumper::cacheRelocations() {
for (const SectionRef &S : Obj->sections()) {
const coff_section *Section = Obj->getCOFFSection(S);
@@ -997,182 +845,22 @@ void COFFDumper::printUnwindInfo() {
return;
ListScope D(W, "UnwindInformation");
- if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
- W.startLine() << "Unsupported image machine type "
- "(currently only AMD64 is supported).\n";
- return;
- }
-
- printX64UnwindInfo();
-}
-
-void COFFDumper::printX64UnwindInfo() {
- for (const SectionRef &Section : Obj->sections()) {
- StringRef Name;
- if (error(Section.getName(Name)))
- continue;
- if (Name != ".pdata" && !Name.startswith(".pdata$"))
- continue;
-
- const coff_section *PData = Obj->getCOFFSection(Section);
-
- ArrayRef<uint8_t> Contents;
- if (error(Obj->getSectionContents(PData, Contents)) || Contents.empty())
- continue;
-
- ArrayRef<RuntimeFunction> RFs(
- reinterpret_cast<const RuntimeFunction *>(Contents.data()),
- Contents.size() / sizeof(RuntimeFunction));
-
- for (const RuntimeFunction *I = RFs.begin(), *E = RFs.end(); I < E; ++I) {
- const uint64_t OffsetInSection = std::distance(RFs.begin(), I)
- * sizeof(RuntimeFunction);
-
- printRuntimeFunction(*I, PData, OffsetInSection);
- }
- }
-}
-
-void COFFDumper::printRuntimeFunction(const RuntimeFunction& RTF,
- const coff_section *Section,
- uint64_t SectionOffset) {
-
- DictScope D(W, "RuntimeFunction");
- W.printString("StartAddress",
- formatSymbol(Section, SectionOffset + 0, RTF.StartAddress));
- W.printString("EndAddress",
- formatSymbol(Section, SectionOffset + 4, RTF.EndAddress));
- W.printString("UnwindInfoAddress",
- formatSymbol(Section, SectionOffset + 8, RTF.UnwindInfoOffset));
-
- const coff_section* XData = nullptr;
- uint64_t UnwindInfoOffset = 0;
- if (error(getSectionFromRelocation(Section, SectionOffset + 8,
- XData, UnwindInfoOffset)))
- return;
-
- ArrayRef<uint8_t> XContents;
- if (error(Obj->getSectionContents(XData, XContents)) || XContents.empty())
- return;
-
- UnwindInfoOffset += RTF.UnwindInfoOffset;
- if (UnwindInfoOffset > XContents.size())
- return;
-
- const Win64EH::UnwindInfo *UI =
- reinterpret_cast<const Win64EH::UnwindInfo *>(
- XContents.data() + UnwindInfoOffset);
-
- printUnwindInfo(*UI, XData, UnwindInfoOffset);
-}
-
-void COFFDumper::printUnwindInfo(const Win64EH::UnwindInfo& UI,
- const coff_section *Section,
- uint64_t SectionOffset) {
- DictScope D(W, "UnwindInfo");
- W.printNumber("Version", UI.getVersion());
- W.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags));
- W.printNumber("PrologSize", UI.PrologSize);
- if (UI.getFrameRegister() != 0) {
- W.printEnum("FrameRegister", UI.getFrameRegister(),
- makeArrayRef(UnwindOpInfo));
- W.printHex("FrameOffset", UI.getFrameOffset());
- } else {
- W.printString("FrameRegister", StringRef("-"));
- W.printString("FrameOffset", StringRef("-"));
- }
-
- W.printNumber("UnwindCodeCount", UI.NumCodes);
- {
- ListScope CodesD(W, "UnwindCodes");
- ArrayRef<UnwindCode> UCs(&UI.UnwindCodes[0], UI.NumCodes);
- for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ++I) {
- unsigned UsedSlots = getNumUsedSlots(*I);
- if (UsedSlots > UCs.size()) {
- errs() << "Corrupt unwind data";
- return;
- }
- printUnwindCode(UI, ArrayRef<UnwindCode>(I, E));
- I += UsedSlots - 1;
- }
- }
-
- uint64_t LSDAOffset = SectionOffset + getOffsetOfLSDA(UI);
- if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
- W.printString("Handler",
- formatSymbol(Section, LSDAOffset,
- UI.getLanguageSpecificHandlerOffset()));
- } else if (UI.getFlags() & UNW_ChainInfo) {
- const RuntimeFunction *Chained = UI.getChainedFunctionEntry();
- if (Chained) {
- DictScope D(W, "Chained");
- W.printString("StartAddress", formatSymbol(Section, LSDAOffset + 0,
- Chained->StartAddress));
- W.printString("EndAddress", formatSymbol(Section, LSDAOffset + 4,
- Chained->EndAddress));
- W.printString("UnwindInfoAddress",
- formatSymbol(Section, LSDAOffset + 8,
- Chained->UnwindInfoOffset));
- }
- }
-}
-
-// Prints one unwind code. Because an unwind code can occupy up to 3 slots in
-// the unwind codes array, this function requires that the correct number of
-// slots is provided.
-void COFFDumper::printUnwindCode(const Win64EH::UnwindInfo& UI,
- ArrayRef<UnwindCode> UCs) {
- assert(UCs.size() >= getNumUsedSlots(UCs[0]));
-
- W.startLine() << format("0x%02X: ", unsigned(UCs[0].u.CodeOffset))
- << getUnwindCodeTypeName(UCs[0].getUnwindOp());
-
- uint32_t AllocSize = 0;
-
- switch (UCs[0].getUnwindOp()) {
- case UOP_PushNonVol:
- outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo());
+ switch (Header->Machine) {
+ case COFF::IMAGE_FILE_MACHINE_AMD64: {
+ Win64EH::Dumper Dumper(W);
+ Win64EH::Dumper::SymbolResolver Resolver =
+ [this](const object::coff_section *Section, uint64_t Offset,
+ SymbolRef &Symbol) -> error_code {
+ return this->resolveSymbol(Section, Offset, Symbol);
+ };
+ Win64EH::Dumper::Context Ctx(*Obj, Resolver);
+ Dumper.printData(Ctx);
break;
-
- case UOP_AllocLarge:
- if (UCs[0].getOpInfo() == 0) {
- AllocSize = UCs[1].FrameOffset * 8;
- } else {
- AllocSize = getLargeSlotValue(UCs);
- }
- outs() << " size=" << AllocSize;
- break;
- case UOP_AllocSmall:
- outs() << " size=" << ((UCs[0].getOpInfo() + 1) * 8);
- break;
- case UOP_SetFPReg:
- if (UI.getFrameRegister() == 0) {
- outs() << " reg=<invalid>";
- } else {
- outs() << " reg=" << getUnwindRegisterName(UI.getFrameRegister())
- << format(", offset=0x%X", UI.getFrameOffset() * 16);
- }
- break;
- case UOP_SaveNonVol:
- outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo())
- << format(", offset=0x%X", UCs[1].FrameOffset * 8);
- break;
- case UOP_SaveNonVolBig:
- outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo())
- << format(", offset=0x%X", getLargeSlotValue(UCs));
- break;
- case UOP_SaveXMM128:
- outs() << " reg=XMM" << static_cast<uint32_t>(UCs[0].getOpInfo())
- << format(", offset=0x%X", UCs[1].FrameOffset * 16);
- break;
- case UOP_SaveXMM128Big:
- outs() << " reg=XMM" << static_cast<uint32_t>(UCs[0].getOpInfo())
- << format(", offset=0x%X", getLargeSlotValue(UCs));
- break;
- case UOP_PushMachFrame:
- outs() << " errcode=" << (UCs[0].getOpInfo() == 0 ? "no" : "yes");
+ }
+ default:
+ W.printEnum("unsupported Image Machine", Header->Machine,
+ makeArrayRef(ImageFileMachineType));
break;
}
-
- outs() << "\n";
}
+