diff options
author | Stephen Hines <srhines@google.com> | 2014-05-29 02:49:00 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-05-29 02:49:00 -0700 |
commit | dce4a407a24b04eebc6a376f8e62b41aaa7b071f (patch) | |
tree | dcebc53f2b182f145a2e659393bf9a0472cedf23 /tools/llvm-readobj | |
parent | 220b921aed042f9e520c26cffd8282a94c66c3d5 (diff) | |
download | external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.zip external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.gz external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.bz2 |
Update LLVM for 3.5 rebase (r209712).
Change-Id: I149556c940fb7dc92d075273c87ff584f400941f
Diffstat (limited to 'tools/llvm-readobj')
-rw-r--r-- | tools/llvm-readobj/ARMAttributeParser.cpp | 102 | ||||
-rw-r--r-- | tools/llvm-readobj/ARMEHABIPrinter.h | 13 | ||||
-rw-r--r-- | tools/llvm-readobj/CMakeLists.txt | 9 | ||||
-rw-r--r-- | tools/llvm-readobj/COFFDumper.cpp | 464 | ||||
-rw-r--r-- | tools/llvm-readobj/ELFDumper.cpp | 94 | ||||
-rw-r--r-- | tools/llvm-readobj/StreamWriter.h | 29 | ||||
-rw-r--r-- | tools/llvm-readobj/Win64EHDumper.cpp | 328 | ||||
-rw-r--r-- | tools/llvm-readobj/Win64EHDumper.h | 62 |
8 files changed, 620 insertions, 481 deletions
diff --git a/tools/llvm-readobj/ARMAttributeParser.cpp b/tools/llvm-readobj/ARMAttributeParser.cpp index 5857547..d35cd14 100644 --- a/tools/llvm-readobj/ARMAttributeParser.cpp +++ b/tools/llvm-readobj/ARMAttributeParser.cpp @@ -9,6 +9,7 @@ #include "ARMAttributeParser.h" #include "StreamWriter.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/LEB128.h" @@ -22,11 +23,6 @@ static const EnumEntry<unsigned> TagNames[] = { { "Tag_Symbol", ARMBuildAttrs::Symbol }, }; -template <typename type_, size_t size_> -size_t countof(const type_ (&)[size_]) { - return size_; -} - namespace llvm { #define ATTRIBUTE_HANDLER(Attr_) \ { ARMBuildAttrs::Attr_, &ARMAttributeParser::Attr_ } @@ -129,7 +125,8 @@ void ARMAttributeParser::CPU_arch(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -155,7 +152,8 @@ void ARMAttributeParser::ARM_ISA_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -164,7 +162,8 @@ void ARMAttributeParser::THUMB_ISA_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Thumb-1", "Thumb-2" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -176,7 +175,8 @@ void ARMAttributeParser::FP_arch(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -185,7 +185,8 @@ void ARMAttributeParser::WMMX_arch(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "WMMXv1", "WMMXv2" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -196,7 +197,8 @@ void ARMAttributeParser::Advanced_SIMD_arch(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -208,7 +210,8 @@ void ARMAttributeParser::PCS_config(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -217,7 +220,8 @@ void ARMAttributeParser::ABI_PCS_R9_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "v6", "Static Base", "TLS", "Unused" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -228,7 +232,8 @@ void ARMAttributeParser::ABI_PCS_RW_data(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -237,7 +242,8 @@ void ARMAttributeParser::ABI_PCS_RO_data(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Absolute", "PC-relative", "Not Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -246,7 +252,8 @@ void ARMAttributeParser::ABI_PCS_GOT_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Direct", "GOT-Indirect" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -257,7 +264,8 @@ void ARMAttributeParser::ABI_PCS_wchar_t(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -266,7 +274,8 @@ void ARMAttributeParser::ABI_FP_rounding(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "IEEE-754", "Runtime" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -275,7 +284,8 @@ void ARMAttributeParser::ABI_FP_denormal(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Unsupported", "IEEE-754", "Sign Only" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -284,7 +294,8 @@ void ARMAttributeParser::ABI_FP_exceptions(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "IEEE-754" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -294,7 +305,8 @@ void ARMAttributeParser::ABI_FP_user_exceptions(AttrType Tag, static const char *Strings[] = { "Not Permitted", "IEEE-754" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -305,7 +317,8 @@ void ARMAttributeParser::ABI_FP_number_model(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -318,7 +331,7 @@ void ARMAttributeParser::ABI_align_needed(AttrType Tag, const uint8_t *Data, uint64_t Value = ParseInteger(Data, Offset); std::string Description; - if (Value < countof(Strings)) + if (Value < array_lengthof(Strings)) Description = std::string(Strings[Value]); else if (Value <= 12) Description = std::string("8-byte alignment, ") + utostr(1 << Value) @@ -339,7 +352,7 @@ void ARMAttributeParser::ABI_align_preserved(AttrType Tag, const uint8_t *Data, uint64_t Value = ParseInteger(Data, Offset); std::string Description; - if (Value < countof(Strings)) + if (Value < array_lengthof(Strings)) Description = std::string(Strings[Value]); else if (Value <= 12) Description = std::string("8-byte stack alignment, ") + utostr(1 << Value) @@ -357,7 +370,8 @@ void ARMAttributeParser::ABI_enum_size(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -368,7 +382,8 @@ void ARMAttributeParser::ABI_HardFP_use(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -379,7 +394,8 @@ void ARMAttributeParser::ABI_VFP_args(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -388,7 +404,8 @@ void ARMAttributeParser::ABI_WMMX_args(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "AAPCS", "iWMMX", "Custom" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -401,7 +418,8 @@ void ARMAttributeParser::ABI_optimization_goals(AttrType Tag, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -414,7 +432,8 @@ void ARMAttributeParser::ABI_FP_optimization_goals(AttrType Tag, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -445,7 +464,8 @@ void ARMAttributeParser::CPU_unaligned_access(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "v6-style" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -454,7 +474,8 @@ void ARMAttributeParser::FP_HP_extension(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "If Available", "Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -463,7 +484,8 @@ void ARMAttributeParser::ABI_FP_16bit_format(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "IEEE-754", "VFPv3" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -472,7 +494,8 @@ void ARMAttributeParser::MPextension_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -483,7 +506,8 @@ void ARMAttributeParser::DIV_use(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -492,7 +516,8 @@ void ARMAttributeParser::T2EE_use(AttrType Tag, const uint8_t *Data, static const char *Strings[] = { "Not Permitted", "Permitted" }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -504,7 +529,8 @@ void ARMAttributeParser::Virtualization_use(AttrType Tag, const uint8_t *Data, }; uint64_t Value = ParseInteger(Data, Offset); - StringRef ValueDesc = (Value < countof(Strings)) ? Strings[Value] : NULL; + StringRef ValueDesc = + (Value < array_lengthof(Strings)) ? Strings[Value] : nullptr; PrintAttribute(Tag, Value, ValueDesc); } @@ -534,7 +560,7 @@ void ARMAttributeParser::ParseAttributeList(const uint8_t *Data, Offset += Length; bool Handled = false; - for (unsigned AHI = 0, AHE = countof(DisplayRoutines); + for (unsigned AHI = 0, AHE = array_lengthof(DisplayRoutines); AHI != AHE && !Handled; ++AHI) { if (DisplayRoutines[AHI].Attribute == Tag) { (this->*DisplayRoutines[AHI].Routine)(ARMBuildAttrs::AttrType(Tag), diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h index 75e2bee..7608cfb 100644 --- a/tools/llvm-readobj/ARMEHABIPrinter.h +++ b/tools/llvm-readobj/ARMEHABIPrinter.h @@ -12,6 +12,7 @@ #include "Error.h" #include "StreamWriter.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ELFTypes.h" #include "llvm/Support/ARMEHABI.h" @@ -20,13 +21,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/type_traits.h" -namespace { -template <typename type_, size_t N> -size_t countof(const type_ (&)[N]) { - return N; -} -} - namespace llvm { namespace ARM { namespace EHABI { @@ -296,7 +290,8 @@ void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) { void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length) { for (unsigned OCI = Offset; OCI < Length + Offset; ) { bool Decoded = false; - for (unsigned REI = 0, REE = countof(Ring); REI != REE && !Decoded; ++REI) { + for (unsigned REI = 0, REE = array_lengthof(Ring); + REI != REE && !Decoded; ++REI) { if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) { (this->*Ring[REI].Routine)(Opcodes, OCI); Decoded = true; @@ -390,7 +385,7 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex, } } } - return NULL; + return nullptr; } template <typename ET> diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt index 036185d..b057dcd 100644 --- a/tools/llvm-readobj/CMakeLists.txt +++ b/tools/llvm-readobj/CMakeLists.txt @@ -5,12 +5,13 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_tool(llvm-readobj - llvm-readobj.cpp - ObjDumper.cpp + ARMAttributeParser.cpp COFFDumper.cpp ELFDumper.cpp - MachODumper.cpp Error.cpp + llvm-readobj.cpp + MachODumper.cpp + ObjDumper.cpp StreamWriter.cpp - ARMAttributeParser.cpp + Win64EHDumper.cpp ) diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index cd40da7..91f2a57 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,45 +59,24 @@ 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, - uint64_t OffsetInSection, - const std::vector<RelocationRef> &Rels); - - void printUnwindInfo( - const Win64EH::UnwindInfo& UI, - uint64_t OffsetInSection, - const std::vector<RelocationRef> &Rels); - - void printUnwindCode(const Win64EH::UnwindInfo &UI, ArrayRef<UnwindCode> UCs); - void printCodeViewLineTables(const SectionRef &Section); void cacheRelocations(); - error_code getSectionContents( - const std::vector<RelocationRef> &Rels, - uint64_t Offset, - ArrayRef<uint8_t> &Contents, - uint64_t &Addr); - - error_code getSection( - const std::vector<RelocationRef> &Rels, - uint64_t Offset, - const coff_section **Section, - uint64_t *AddrPtr); + error_code resolveSymbol(const coff_section *Section, uint64_t Offset, + SymbolRef &Sym); + error_code resolveSymbolName(const coff_section *Section, uint64_t Offset, + StringRef &Name); typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy; const llvm::object::COFFObjectFile *Obj; RelocMapTy RelocMap; - std::vector<RelocationRef> EmptyRelocs; }; } // namespace @@ -116,110 +96,33 @@ 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 symbol sym this functions returns the address and section of it. -static error_code resolveSectionAndAddress(const COFFObjectFile *Obj, - const SymbolRef &Sym, - const coff_section *&ResolvedSection, - uint64_t &ResolvedAddr) { - if (error_code EC = Sym.getAddress(ResolvedAddr)) - return EC; - - section_iterator iter(Obj->section_begin()); - if (error_code EC = Sym.getSection(iter)) - return EC; - - ResolvedSection = Obj->getCOFFSection(*iter); - return object_error::success; -} - -// Given a vector of relocations for a section and an offset into this section -// the function returns the symbol used for the relocation at the offset. -static error_code resolveSymbol(const std::vector<RelocationRef> &Rels, - uint64_t Offset, SymbolRef &Sym) { - for (std::vector<RelocationRef>::const_iterator RelI = Rels.begin(), - RelE = Rels.end(); - RelI != RelE; ++RelI) { - uint64_t Ofs; - if (error_code EC = RelI->getOffset(Ofs)) +// 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, + uint64_t Offset, SymbolRef &Sym) { + const auto &Relocations = RelocMap[Section]; + for (const auto &Relocation : Relocations) { + uint64_t RelocationOffset; + if (error_code EC = Relocation.getOffset(RelocationOffset)) return EC; - if (Ofs == Offset) { - Sym = *RelI->getSymbol(); + if (RelocationOffset == Offset) { + Sym = *Relocation.getSymbol(); return readobj_error::success; } } - return readobj_error::unknown_symbol; } -// Given a vector of relocations for a section and an offset into this section -// the function returns the name of the symbol used for the relocation at the -// offset. -static error_code resolveSymbolName(const std::vector<RelocationRef> &Rels, - uint64_t Offset, StringRef &Name) { - SymbolRef Sym; - if (error_code EC = resolveSymbol(Rels, Offset, Sym)) return EC; - if (error_code EC = Sym.getName(Name)) return EC; +// Given a section and an offset into this section the function returns the name +// of the symbol used for the relocation at the offset. +error_code COFFDumper::resolveSymbolName(const coff_section *Section, + uint64_t Offset, StringRef &Name) { + SymbolRef Symbol; + if (error_code EC = resolveSymbol(Section, Offset, Symbol)) + return EC; + if (error_code EC = Symbol.getName(Name)) + return EC; return object_error::success; } @@ -403,50 +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 } -}; - -// Some additional COFF structures not defined by llvm::object. -namespace { - struct coff_aux_file_record { - char FileName[18]; - }; -} // namespace - -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) { @@ -455,69 +314,6 @@ static error_code getSymbolAuxData(const COFFObjectFile *Obj, return readobj_error::success; } -static std::string formatSymbol(const std::vector<RelocationRef> &Rels, - uint64_t Offset, uint32_t Disp) { - std::string Buffer; - raw_string_ostream Str(Buffer); - - StringRef Sym; - if (resolveSymbolName(Rels, 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(); -} - -// Given a vector of relocations for a section and an offset into this section -// the function resolves the symbol used for the relocation at the offset and -// returns the section content and the address inside the content pointed to -// by the symbol. -error_code COFFDumper::getSectionContents( - const std::vector<RelocationRef> &Rels, uint64_t Offset, - ArrayRef<uint8_t> &Contents, uint64_t &Addr) { - - SymbolRef Sym; - const coff_section *Section; - - if (error_code EC = resolveSymbol(Rels, Offset, Sym)) - return EC; - if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr)) - return EC; - if (error_code EC = Obj->getSectionContents(Section, Contents)) - return EC; - - return object_error::success; -} - -error_code COFFDumper::getSection( - const std::vector<RelocationRef> &Rels, uint64_t Offset, - const coff_section **SectionPtr, uint64_t *AddrPtr) { - - SymbolRef Sym; - if (error_code EC = resolveSymbol(Rels, Offset, Sym)) - return EC; - - const coff_section *Section; - uint64_t Addr; - if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr)) - return EC; - - if (SectionPtr) - *SectionPtr = Section; - if (AddrPtr) - *AddrPtr = Addr; - - return object_error::success; -} - void COFFDumper::cacheRelocations() { for (const SectionRef &S : Obj->sections()) { const coff_section *Section = Obj->getCOFFSection(S); @@ -541,7 +337,7 @@ void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName void COFFDumper::printFileHeaders() { // Print COFF header - const coff_file_header *COFFHeader = 0; + const coff_file_header *COFFHeader = nullptr; if (error(Obj->getCOFFHeader(COFFHeader))) return; @@ -564,13 +360,13 @@ void COFFDumper::printFileHeaders() { // Print PE header. This header does not exist if this is an object file and // not an executable. - const pe32_header *PEHeader = 0; + const pe32_header *PEHeader = nullptr; if (error(Obj->getPE32Header(PEHeader))) return; if (PEHeader) printPEHeader<pe32_header>(PEHeader); - const pe32plus_header *PEPlusHeader = 0; + const pe32plus_header *PEPlusHeader = nullptr; if (error(Obj->getPE32PlusHeader(PEPlusHeader))) return; if (PEPlusHeader) @@ -685,8 +481,8 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { } StringRef FunctionName; - if (error(resolveSymbolName(RelocMap[Obj->getCOFFSection(Section)], - Offset, FunctionName))) + if (error(resolveSymbolName(Obj->getCOFFSection(Section), Offset, + FunctionName))) return; W.printString("FunctionName", FunctionName); if (FunctionLineTables.count(FunctionName) != 0) { @@ -700,7 +496,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { break; } case COFF::DEBUG_STRING_TABLE_SUBSECTION: - if (PayloadSize == 0 || StringTable.data() != 0 || + if (PayloadSize == 0 || StringTable.data() != nullptr || Contents.back() != '\0') { // Empty or duplicate or non-null-terminated subsection. error(object_error::parse_failed); @@ -712,7 +508,8 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { // Holds the translation table from file indices // to offsets in the string table. - if (PayloadSize == 0 || FileIndexToStringOffsetTable.data() != 0) { + if (PayloadSize == 0 || + FileIndexToStringOffsetTable.data() != nullptr) { // Empty or duplicate subsection. error(object_error::parse_failed); return; @@ -979,13 +776,16 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printBinary("Unused", makeArrayRef(Aux->Unused)); } else if (Symbol->isFileRecord()) { - const coff_aux_file_record *Aux; + const coff_aux_file *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) break; DictScope AS(W, "AuxFileRecord"); - W.printString("FileName", StringRef(Aux->FileName)); + StringRef Name(Aux->FileName, + Symbol->NumberOfAuxSymbols * COFF::SymbolSize); + W.printString("FileName", Name.rtrim(StringRef("\0", 1))); + break; } else if (Symbol->isSectionDefinition()) { const coff_aux_section_definition *Aux; if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) @@ -1045,181 +845,23 @@ 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, OffsetInSection, RelocMap[PData]); - } - } -} - -void COFFDumper::printRuntimeFunction( - const RuntimeFunction& RTF, - uint64_t OffsetInSection, - const std::vector<RelocationRef> &Rels) { - - DictScope D(W, "RuntimeFunction"); - W.printString("StartAddress", - formatSymbol(Rels, OffsetInSection + 0, RTF.StartAddress)); - W.printString("EndAddress", - formatSymbol(Rels, OffsetInSection + 4, RTF.EndAddress)); - W.printString("UnwindInfoAddress", - formatSymbol(Rels, OffsetInSection + 8, RTF.UnwindInfoOffset)); - - const coff_section* XData = 0; - uint64_t UnwindInfoOffset = 0; - if (error(getSection(Rels, OffsetInSection + 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, UnwindInfoOffset, RelocMap[XData]); -} - -void COFFDumper::printUnwindInfo( - const Win64EH::UnwindInfo& UI, - uint64_t OffsetInSection, - const std::vector<RelocationRef> &Rels) { - 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 = OffsetInSection + getOffsetOfLSDA(UI); - if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { - W.printString("Handler", formatSymbol(Rels, LSDAOffset, - UI.getLanguageSpecificHandlerOffset())); - } else if (UI.getFlags() & UNW_ChainInfo) { - const RuntimeFunction *Chained = UI.getChainedFunctionEntry(); - if (Chained) { - DictScope D(W, "Chained"); - W.printString("StartAddress", formatSymbol(Rels, LSDAOffset + 0, - Chained->StartAddress)); - W.printString("EndAddress", formatSymbol(Rels, LSDAOffset + 4, - Chained->EndAddress)); - W.printString("UnwindInfoAddress", formatSymbol(Rels, 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 = + [](const object::coff_section *Section, uint64_t Offset, + SymbolRef &Symbol, void *user_data) -> error_code { + COFFDumper *Dumper = reinterpret_cast<COFFDumper*>(user_data); + return Dumper->resolveSymbol(Section, Offset, Symbol); + }; + Win64EH::Dumper::Context Ctx(*Obj, Resolver, this); + 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"; } + diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 4cd3393..de4c207 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -437,6 +437,29 @@ static const EnumEntry<unsigned> ElfSegmentFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, PF_R) }; +static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NOREORDER), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_PIC), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_4), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_5), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R2), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_32R6), + LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_64R6) +}; + template<class ELFT> void ELFDumper<ELFT>::printFileHeaders() { const typename ELFO::Elf_Ehdr *Header = Obj->getHeader(); @@ -464,7 +487,11 @@ void ELFDumper<ELFT>::printFileHeaders() { W.printHex ("Entry", Header->e_entry); W.printHex ("ProgramHeaderOffset", Header->e_phoff); W.printHex ("SectionHeaderOffset", Header->e_shoff); - W.printFlags ("Flags", Header->e_flags); + if (Header->e_machine == EM_MIPS) + W.printFlags("Flags", Header->e_flags, makeArrayRef(ElfHeaderMipsFlags), + unsigned(ELF::EF_MIPS_ARCH)); + else + W.printFlags("Flags", Header->e_flags); W.printNumber("HeaderSize", Header->e_ehsize); W.printNumber("ProgramHeaderEntrySize", Header->e_phentsize); W.printNumber("ProgramHeaderCount", Header->e_phnum); @@ -652,7 +679,8 @@ void ELFDumper<ELFT>::printSymbol(typename ELFO::Elf_Sym_Iter Symbol) { std::string FullSymbolName(SymbolName); if (Symbol.isDynamic()) { bool IsDefault; - ErrorOr<StringRef> Version = Obj->getSymbolVersion(0, &*Symbol, IsDefault); + ErrorOr<StringRef> Version = Obj->getSymbolVersion(nullptr, &*Symbol, + IsDefault); if (Version) { FullSymbolName += (IsDefault ? "@@" : "@"); FullSymbolName += *Version; @@ -712,6 +740,8 @@ static const char *getTypeString(uint64_t Type) { LLVM_READOBJ_TYPE_CASE(VERNEED); LLVM_READOBJ_TYPE_CASE(VERNEEDNUM); LLVM_READOBJ_TYPE_CASE(VERSYM); + LLVM_READOBJ_TYPE_CASE(RELCOUNT); + LLVM_READOBJ_TYPE_CASE(GNU_HASH); LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION); LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS); LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS); @@ -727,6 +757,57 @@ static const char *getTypeString(uint64_t Type) { #undef LLVM_READOBJ_TYPE_CASE +#define LLVM_READOBJ_DT_FLAG_ENT(prefix, enum) \ + { #enum, prefix##_##enum } + +static const EnumEntry<unsigned> ElfDynamicDTFlags[] = { + LLVM_READOBJ_DT_FLAG_ENT(DF, ORIGIN), + LLVM_READOBJ_DT_FLAG_ENT(DF, SYMBOLIC), + LLVM_READOBJ_DT_FLAG_ENT(DF, TEXTREL), + LLVM_READOBJ_DT_FLAG_ENT(DF, BIND_NOW), + LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS) +}; + +static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = { + LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE), + LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART), + LLVM_READOBJ_DT_FLAG_ENT(RHF, NOTPOT), + LLVM_READOBJ_DT_FLAG_ENT(RHS, NO_LIBRARY_REPLACEMENT), + LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_MOVE), + LLVM_READOBJ_DT_FLAG_ENT(RHF, SGI_ONLY), + LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_INIT), + LLVM_READOBJ_DT_FLAG_ENT(RHF, DELTA_C_PLUS_PLUS), + LLVM_READOBJ_DT_FLAG_ENT(RHF, GUARANTEE_START_INIT), + LLVM_READOBJ_DT_FLAG_ENT(RHF, PIXIE), + LLVM_READOBJ_DT_FLAG_ENT(RHF, DEFAULT_DELAY_LOAD), + LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTART), + LLVM_READOBJ_DT_FLAG_ENT(RHF, REQUICKSTARTED), + LLVM_READOBJ_DT_FLAG_ENT(RHF, CORD), + LLVM_READOBJ_DT_FLAG_ENT(RHF, NO_UNRES_UNDEF), + LLVM_READOBJ_DT_FLAG_ENT(RHF, RLD_ORDER_SAFE) +}; + +#undef LLVM_READOBJ_DT_FLAG_ENT + +template <typename T, typename TFlag> +void printFlags(T Value, ArrayRef<EnumEntry<TFlag>> Flags, raw_ostream &OS) { + typedef EnumEntry<TFlag> FlagEntry; + typedef SmallVector<FlagEntry, 10> FlagVector; + FlagVector SetFlags; + + for (const auto &Flag : Flags) { + if (Flag.Value == 0) + continue; + + if ((Value & Flag.Value) == Flag.Value) + SetFlags.push_back(Flag); + } + + for (const auto &Flag : SetFlags) { + OS << Flag.Name << " "; + } +} + template <class ELFT> static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value, bool Is64, raw_ostream &OS) { @@ -755,14 +836,15 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value, case DT_DEBUG: case DT_VERNEED: case DT_VERSYM: + case DT_GNU_HASH: case DT_NULL: - case DT_MIPS_FLAGS: case DT_MIPS_BASE_ADDRESS: case DT_MIPS_GOTSYM: case DT_MIPS_RLD_MAP: case DT_MIPS_PLTGOT: OS << format("0x%" PRIX64, Value); break; + case DT_RELCOUNT: case DT_VERNEEDNUM: case DT_MIPS_RLD_VERSION: case DT_MIPS_LOCAL_GOTNO: @@ -792,6 +874,12 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value, case DT_RUNPATH: OS << O->getDynamicString(Value); break; + case DT_MIPS_FLAGS: + printFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags), OS); + break; + case DT_FLAGS: + printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS); + break; } } diff --git a/tools/llvm-readobj/StreamWriter.h b/tools/llvm-readobj/StreamWriter.h index c40077a..9282dcc 100644 --- a/tools/llvm-readobj/StreamWriter.h +++ b/tools/llvm-readobj/StreamWriter.h @@ -81,9 +81,9 @@ public: ArrayRef<EnumEntry<TEnum> > EnumValues) { StringRef Name; bool Found = false; - for (size_t i = 0; i < EnumValues.size(); ++i) { - if (EnumValues[i].Value == Value) { - Name = EnumValues[i].Name; + for (const auto &EnumItem : EnumValues) { + if (EnumItem.Value == Value) { + Name = EnumItem.Name; Found = true; break; } @@ -103,25 +103,22 @@ public: typedef SmallVector<FlagEntry, 10> FlagVector; FlagVector SetFlags; - for (typename ArrayRef<FlagEntry>::const_iterator I = Flags.begin(), - E = Flags.end(); I != E; ++I) { - if (I->Value == 0) + for (const auto &Flag : Flags) { + if (Flag.Value == 0) continue; - bool IsEnum = (I->Value & EnumMask) != 0; - if ((!IsEnum && (Value & I->Value) == I->Value) || - (IsEnum && (Value & EnumMask) == I->Value)) { - SetFlags.push_back(*I); + bool IsEnum = (Flag.Value & EnumMask) != 0; + if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || + (IsEnum && (Value & EnumMask) == Flag.Value)) { + SetFlags.push_back(Flag); } } std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); startLine() << Label << " [ (" << hex(Value) << ")\n"; - for (typename FlagVector::const_iterator I = SetFlags.begin(), - E = SetFlags.end(); - I != E; ++I) { - startLine() << " " << I->Name << " (" << hex(I->Value) << ")\n"; + for (const auto &Flag : SetFlags) { + startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; } startLine() << "]\n"; } @@ -176,10 +173,10 @@ public: void printList(StringRef Label, const SmallVectorImpl<T_> &List) { startLine() << Label << ": ["; bool Comma = false; - for (unsigned LI = 0, LE = List.size(); LI != LE; ++LI) { + for (const auto &Item : List) { if (Comma) OS << ", "; - OS << List[LI]; + OS << Item; Comma = true; } OS << "]\n"; diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp new file mode 100644 index 0000000..c64d362 --- /dev/null +++ b/tools/llvm-readobj/Win64EHDumper.cpp @@ -0,0 +1,328 @@ +//===- Win64EHDumper.cpp - Win64 EH Printer ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Win64EHDumper.h" +#include "llvm-readobj.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::Win64EH; + +static const EnumEntry<unsigned> UnwindFlags[] = { + { "ExceptionHandler", UNW_ExceptionHandler }, + { "TerminateHandler", UNW_TerminateHandler }, + { "ChainInfo" , 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 UnwindInfo& UI) { + return static_cast<const char*>(UI.getLanguageSpecificData()) + - reinterpret_cast<const char*>(&UI); +} + +static uint32_t getLargeSlotValue(ArrayRef<UnwindCode> UC) { + if (UC.size() < 3) + return 0; + return UC[1].FrameOffset + (static_cast<uint32_t>(UC[2].FrameOffset) << 16); +} + +// 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; + } +} + +static std::string formatSymbol(const Dumper::Context &Ctx, + const coff_section *Section, uint64_t Offset, + uint32_t Displacement) { + std::string Buffer; + raw_string_ostream OS(Buffer); + + StringRef Name; + SymbolRef Symbol; + if (Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData) || + Symbol.getName(Name)) { + OS << format(" (0x%" PRIX64 ")", Offset); + return OS.str(); + } + + OS << Name; + if (Displacement > 0) + OS << format(" +0x%X (0x%" PRIX64 ")", Displacement, Offset); + else + OS << format(" (0x%" PRIX64 ")", Offset); + return OS.str(); +} + +static error_code resolveRelocation(const Dumper::Context &Ctx, + const coff_section *Section, + uint64_t Offset, + const coff_section *&ResolvedSection, + uint64_t &ResolvedAddress) { + SymbolRef Symbol; + if (error_code EC = Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData)) + return EC; + + if (error_code EC = Symbol.getAddress(ResolvedAddress)) + return EC; + + section_iterator SI = Ctx.COFF.section_begin(); + if (error_code EC = Symbol.getSection(SI)) + return EC; + + ResolvedSection = Ctx.COFF.getCOFFSection(*SI); + return object_error::success; +} + +namespace llvm { +namespace Win64EH { +void Dumper::printRuntimeFunctionEntry(const Context &Ctx, + const coff_section *Section, + uint64_t Offset, + const RuntimeFunction &RF) { + SW.printString("StartAddress", + formatSymbol(Ctx, Section, Offset + 0, RF.StartAddress)); + SW.printString("EndAddress", + formatSymbol(Ctx, Section, Offset + 4, RF.EndAddress)); + SW.printString("UnwindInfoAddress", + formatSymbol(Ctx, Section, Offset + 8, RF.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 Dumper::printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC) { + assert(UC.size() >= getNumUsedSlots(UC[0])); + + SW.startLine() << format("0x%02X: ", unsigned(UC[0].u.CodeOffset)) + << getUnwindCodeTypeName(UC[0].getUnwindOp()); + + switch (UC[0].getUnwindOp()) { + case UOP_PushNonVol: + OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()); + break; + + case UOP_AllocLarge: + OS << " size=" + << ((UC[0].getOpInfo() == 0) ? UC[1].FrameOffset * 8 + : getLargeSlotValue(UC)); + break; + + case UOP_AllocSmall: + OS << " size=" << (UC[0].getOpInfo() + 1) * 8; + break; + + case UOP_SetFPReg: + if (UI.getFrameRegister() == 0) + OS << " reg=<invalid>"; + else + OS << " reg=" << getUnwindRegisterName(UI.getFrameRegister()) + << format(", offset=0x%X", UI.getFrameOffset() * 16); + break; + + case UOP_SaveNonVol: + OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()) + << format(", offset=0x%X", UC[1].FrameOffset * 8); + break; + + case UOP_SaveNonVolBig: + OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()) + << format(", offset=0x%X", getLargeSlotValue(UC)); + break; + + case UOP_SaveXMM128: + OS << " reg=XMM" << static_cast<uint32_t>(UC[0].getOpInfo()) + << format(", offset=0x%X", UC[1].FrameOffset * 16); + break; + + case UOP_SaveXMM128Big: + OS << " reg=XMM" << static_cast<uint32_t>(UC[0].getOpInfo()) + << format(", offset=0x%X", getLargeSlotValue(UC)); + break; + + case UOP_PushMachFrame: + OS << " errcode=" << (UC[0].getOpInfo() == 0 ? "no" : "yes"); + break; + } + + OS << "\n"; +} + +void Dumper::printUnwindInfo(const Context &Ctx, const coff_section *Section, + off_t Offset, const UnwindInfo &UI) { + DictScope UIS(SW, "UnwindInfo"); + SW.printNumber("Version", UI.getVersion()); + SW.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags)); + SW.printNumber("PrologSize", UI.PrologSize); + if (UI.getFrameRegister()) { + SW.printEnum("FrameRegister", UI.getFrameRegister(), + makeArrayRef(UnwindOpInfo)); + SW.printHex("FrameOffset", UI.getFrameOffset()); + } else { + SW.printString("FrameRegister", StringRef("-")); + SW.printString("FrameOffset", StringRef("-")); + } + + SW.printNumber("UnwindCodeCount", UI.NumCodes); + { + ListScope UCS(SW, "UnwindCodes"); + ArrayRef<UnwindCode> UC(&UI.UnwindCodes[0], UI.NumCodes); + for (const UnwindCode *UCI = UC.begin(), *UCE = UC.end(); UCI < UCE; ++UCI) { + unsigned UsedSlots = getNumUsedSlots(*UCI); + if (UsedSlots > UC.size()) { + errs() << "corrupt unwind data"; + return; + } + + printUnwindCode(UI, ArrayRef<UnwindCode>(UCI, UCE)); + UCI = UCI + UsedSlots - 1; + } + } + + uint64_t LSDAOffset = Offset + getOffsetOfLSDA(UI); + if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { + SW.printString("Handler", + formatSymbol(Ctx, Section, LSDAOffset, + UI.getLanguageSpecificHandlerOffset())); + } else if (UI.getFlags() & UNW_ChainInfo) { + if (const RuntimeFunction *Chained = UI.getChainedFunctionEntry()) { + DictScope CS(SW, "Chained"); + printRuntimeFunctionEntry(Ctx, Section, LSDAOffset, *Chained); + } + } +} + +void Dumper::printRuntimeFunction(const Context &Ctx, + const coff_section *Section, + uint64_t SectionOffset, + const RuntimeFunction &RF) { + DictScope RFS(SW, "RuntimeFunction"); + printRuntimeFunctionEntry(Ctx, Section, SectionOffset, RF); + + const coff_section *XData; + uint64_t Offset; + if (error(resolveRelocation(Ctx, Section, SectionOffset + 8, XData, Offset))) + return; + + ArrayRef<uint8_t> Contents; + if (error(Ctx.COFF.getSectionContents(XData, Contents)) || Contents.empty()) + return; + + Offset = Offset + RF.UnwindInfoOffset; + if (Offset > Contents.size()) + return; + + const auto UI = reinterpret_cast<const UnwindInfo*>(Contents.data() + Offset); + printUnwindInfo(Ctx, XData, Offset, *UI); +} + +void Dumper::printData(const Context &Ctx) { + for (const auto &Section : Ctx.COFF.sections()) { + StringRef Name; + if (error(Section.getName(Name))) + continue; + + if (Name != ".pdata" && !Name.startswith(".pdata$")) + continue; + + const coff_section *PData = Ctx.COFF.getCOFFSection(Section); + ArrayRef<uint8_t> Contents; + if (error(Ctx.COFF.getSectionContents(PData, Contents)) || Contents.empty()) + continue; + + const RuntimeFunction *Entries = + reinterpret_cast<const RuntimeFunction *>(Contents.data()); + const size_t Count = Contents.size() / sizeof(RuntimeFunction); + ArrayRef<RuntimeFunction> RuntimeFunctions(Entries, Count); + + size_t Index = 0; + for (const auto &RF : RuntimeFunctions) { + printRuntimeFunction(Ctx, Ctx.COFF.getCOFFSection(Section), + Index * sizeof(RuntimeFunction), RF); + ++Index; + } + } +} +} +} + diff --git a/tools/llvm-readobj/Win64EHDumper.h b/tools/llvm-readobj/Win64EHDumper.h new file mode 100644 index 0000000..2eac810 --- /dev/null +++ b/tools/llvm-readobj/Win64EHDumper.h @@ -0,0 +1,62 @@ +//===- Win64EHDumper.h - Win64 EH Printing ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_READOBJ_WIN64EHPRINTER_H +#define LLVM_TOOLS_READOBJ_WIN64EHPRINTER_H + +#include "StreamWriter.h" +#include "llvm/Support/Win64EH.h" + +namespace llvm { +namespace object { +class COFFObjectFile; +class SymbolRef; +struct coff_section; +} + +namespace Win64EH { +class Dumper { + StreamWriter &SW; + raw_ostream &OS; + +public: + typedef error_code (*SymbolResolver)(const object::coff_section *, uint64_t, + object::SymbolRef &, void *); + + struct Context { + const object::COFFObjectFile &COFF; + SymbolResolver ResolveSymbol; + void *UserData; + + Context(const object::COFFObjectFile &COFF, SymbolResolver Resolver, + void *UserData) + : COFF(COFF), ResolveSymbol(Resolver), UserData(UserData) {} + }; + +private: + void printRuntimeFunctionEntry(const Context &Ctx, + const object::coff_section *Section, + uint64_t SectionOffset, + const RuntimeFunction &RF); + void printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC); + void printUnwindInfo(const Context &Ctx, const object::coff_section *Section, + off_t Offset, const UnwindInfo &UI); + void printRuntimeFunction(const Context &Ctx, + const object::coff_section *Section, + uint64_t SectionOffset, const RuntimeFunction &RF); + +public: + Dumper(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {} + + void printData(const Context &Ctx); +}; +} +} + +#endif |