diff options
Diffstat (limited to 'llvm/tools/llvm-objdump')
-rw-r--r-- | llvm/tools/llvm-objdump/MachODump.cpp | 264 | ||||
-rw-r--r-- | llvm/tools/llvm-objdump/llvm-objdump.cpp | 14 | ||||
-rw-r--r-- | llvm/tools/llvm-objdump/llvm-objdump.h | 2 |
3 files changed, 21 insertions, 259 deletions
diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index 258c0b520a3..fbb116b4e12 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -1214,6 +1214,12 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF, printLazyBindTable(MachOOF); if (WeakBind) printWeakBindTable(MachOOF); + + if (DwarfDumpType != DIDT_Null) { + std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*MachOOF)); + // Dump the complete DWARF structure. + DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */); + } } // printUnknownCPUType() helps print_fat_headers for unknown CPU's. @@ -6750,262 +6756,6 @@ static void printMachOUnwindInfoSection(const MachOObjectFile *Obj, } } -static unsigned getSizeForEncoding(bool is64Bit, - unsigned symbolEncoding) { - unsigned format = symbolEncoding & 0x0f; - switch (format) { - default: llvm_unreachable("Unknown Encoding"); - case dwarf::DW_EH_PE_absptr: - case dwarf::DW_EH_PE_signed: - return is64Bit ? 8 : 4; - case dwarf::DW_EH_PE_udata2: - case dwarf::DW_EH_PE_sdata2: - return 2; - case dwarf::DW_EH_PE_udata4: - case dwarf::DW_EH_PE_sdata4: - return 4; - case dwarf::DW_EH_PE_udata8: - case dwarf::DW_EH_PE_sdata8: - return 8; - } -} - -static uint64_t readPointer(const char *&Pos, bool is64Bit, unsigned Encoding) { - switch (getSizeForEncoding(is64Bit, Encoding)) { - case 2: - return readNext<uint16_t>(Pos); - break; - case 4: - return readNext<uint32_t>(Pos); - break; - case 8: - return readNext<uint64_t>(Pos); - break; - default: - llvm_unreachable("Illegal data size"); - } -} - -static void printMachOEHFrameSection(const MachOObjectFile *Obj, - std::map<uint64_t, SymbolRef> &Symbols, - const SectionRef &EHFrame) { - if (!Obj->isLittleEndian()) { - outs() << "warning: cannot handle big endian __eh_frame section\n"; - return; - } - - bool is64Bit = Obj->is64Bit(); - - outs() << "Contents of __eh_frame section:\n"; - - StringRef Contents; - EHFrame.getContents(Contents); - - /// A few fields of the CIE are used when decoding the FDE's. This struct - /// will cache those fields we need so that we don't have to decode it - /// repeatedly for each FDE that references it. - struct DecodedCIE { - Optional<uint32_t> FDEPointerEncoding; - Optional<uint32_t> LSDAPointerEncoding; - bool hasAugmentationLength; - }; - - // Map from the start offset of the CIE to the cached data for that CIE. - DenseMap<uint64_t, DecodedCIE> CachedCIEs; - - for (const char *Pos = Contents.data(), *End = Contents.end(); Pos != End; ) { - - const char *EntryStartPos = Pos; - - uint64_t Length = readNext<uint32_t>(Pos); - if (Length == 0xffffffff) - Length = readNext<uint64_t>(Pos); - - // Save the Pos so that we can check the length we encoded against what we - // end up decoding. - const char *PosAfterLength = Pos; - const char *EntryEndPos = PosAfterLength + Length; - - assert(EntryEndPos <= End && - "__eh_frame entry length exceeds section size"); - - uint32_t ID = readNext<uint32_t>(Pos); - if (ID == 0) { - // This is a CIE. - - uint32_t Version = readNext<uint8_t>(Pos); - - // Parse a null terminated augmentation string - SmallString<8> AugmentationString; - for (uint8_t Char = readNext<uint8_t>(Pos); Char; - Char = readNext<uint8_t>(Pos)) - AugmentationString.push_back(Char); - - // Optionally parse the EH data if the augmentation string says it's there. - Optional<uint64_t> EHData; - if (StringRef(AugmentationString).count("eh")) - EHData = is64Bit ? readNext<uint64_t>(Pos) : readNext<uint32_t>(Pos); - - unsigned ULEBByteCount; - uint64_t CodeAlignmentFactor = decodeULEB128((const uint8_t *)Pos, - &ULEBByteCount); - Pos += ULEBByteCount; - - int64_t DataAlignmentFactor = decodeSLEB128((const uint8_t *)Pos, - &ULEBByteCount); - Pos += ULEBByteCount; - - uint32_t ReturnAddressRegister = readNext<uint8_t>(Pos); - - Optional<uint64_t> AugmentationLength; - Optional<uint32_t> LSDAPointerEncoding; - Optional<uint32_t> PersonalityEncoding; - Optional<uint64_t> Personality; - Optional<uint32_t> FDEPointerEncoding; - if (!AugmentationString.empty() && AugmentationString.front() == 'z') { - AugmentationLength = decodeULEB128((const uint8_t *)Pos, - &ULEBByteCount); - Pos += ULEBByteCount; - - // Walk the augmentation string to get all the augmentation data. - for (unsigned i = 1, e = AugmentationString.size(); i != e; ++i) { - char Char = AugmentationString[i]; - switch (Char) { - case 'e': - assert((i + 1) != e && AugmentationString[i + 1] == 'h' && - "Expected 'eh' in augmentation string"); - break; - case 'L': - assert(!LSDAPointerEncoding && "Duplicate LSDA encoding"); - LSDAPointerEncoding = readNext<uint8_t>(Pos); - break; - case 'P': { - assert(!Personality && "Duplicate personality"); - PersonalityEncoding = readNext<uint8_t>(Pos); - Personality = readPointer(Pos, is64Bit, *PersonalityEncoding); - break; - } - case 'R': - assert(!FDEPointerEncoding && "Duplicate FDE encoding"); - FDEPointerEncoding = readNext<uint8_t>(Pos); - break; - case 'z': - llvm_unreachable("'z' must be first in the augmentation string"); - } - } - } - - outs() << "CIE:\n"; - outs() << " Length: " << Length << "\n"; - outs() << " CIE ID: " << ID << "\n"; - outs() << " Version: " << Version << "\n"; - outs() << " Augmentation String: " << AugmentationString << "\n"; - if (EHData) - outs() << " EHData: " << *EHData << "\n"; - outs() << " Code Alignment Factor: " << CodeAlignmentFactor << "\n"; - outs() << " Data Alignment Factor: " << DataAlignmentFactor << "\n"; - outs() << " Return Address Register: " << ReturnAddressRegister << "\n"; - if (AugmentationLength) { - outs() << " Augmentation Data Length: " << *AugmentationLength << "\n"; - if (LSDAPointerEncoding) { - outs() << " FDE LSDA Pointer Encoding: " - << *LSDAPointerEncoding << "\n"; - } - if (Personality) { - outs() << " Personality Encoding: " << *PersonalityEncoding << "\n"; - outs() << " Personality: " << *Personality << "\n"; - } - if (FDEPointerEncoding) { - outs() << " FDE Address Pointer Encoding: " - << *FDEPointerEncoding << "\n"; - } - } - // FIXME: Handle instructions. - // For now just emit some bytes - outs() << " Instructions:\n "; - dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos), - outs()); - outs() << "\n"; - Pos = EntryEndPos; - - // Cache this entry. - uint64_t Offset = EntryStartPos - Contents.data(); - CachedCIEs[Offset] = { FDEPointerEncoding, LSDAPointerEncoding, - AugmentationLength.hasValue() }; - continue; - } - - // This is an FDE. - // The CIE pointer for an FDE is the same location as the ID which we - // already read. - uint32_t CIEPointer = ID; - - const char *CIEStart = PosAfterLength - CIEPointer; - assert(CIEStart >= Contents.data() && - "FDE points to CIE before the __eh_frame start"); - - uint64_t CIEOffset = CIEStart - Contents.data(); - auto CIEIt = CachedCIEs.find(CIEOffset); - if (CIEIt == CachedCIEs.end()) - llvm_unreachable("Couldn't find CIE at offset in to __eh_frame section"); - - const DecodedCIE &CIE = CIEIt->getSecond(); - assert(CIE.FDEPointerEncoding && - "FDE references CIE which did not set pointer encoding"); - - uint64_t PCPointerSize = getSizeForEncoding(is64Bit, - *CIE.FDEPointerEncoding); - - uint64_t PCBegin = readPointer(Pos, is64Bit, *CIE.FDEPointerEncoding); - uint64_t PCRange = readPointer(Pos, is64Bit, *CIE.FDEPointerEncoding); - - Optional<uint64_t> AugmentationLength; - uint32_t LSDAPointerSize; - Optional<uint64_t> LSDAPointer; - if (CIE.hasAugmentationLength) { - unsigned ULEBByteCount; - AugmentationLength = decodeULEB128((const uint8_t *)Pos, - &ULEBByteCount); - Pos += ULEBByteCount; - - // Decode the LSDA if the CIE augmentation string said we should. - if (CIE.LSDAPointerEncoding) { - LSDAPointerSize = getSizeForEncoding(is64Bit, *CIE.LSDAPointerEncoding); - LSDAPointer = readPointer(Pos, is64Bit, *CIE.LSDAPointerEncoding); - } - } - - outs() << "FDE:\n"; - outs() << " Length: " << Length << "\n"; - outs() << " CIE Offset: " << CIEOffset << "\n"; - - if (PCPointerSize == 8) { - outs() << format(" PC Begin: %016" PRIx64, PCBegin) << "\n"; - outs() << format(" PC Range: %016" PRIx64, PCRange) << "\n"; - } else { - outs() << format(" PC Begin: %08" PRIx64, PCBegin) << "\n"; - outs() << format(" PC Range: %08" PRIx64, PCRange) << "\n"; - } - if (AugmentationLength) { - outs() << " Augmentation Data Length: " << *AugmentationLength << "\n"; - if (LSDAPointer) { - if (LSDAPointerSize == 8) - outs() << format(" LSDA Pointer: %016\n" PRIx64, *LSDAPointer); - else - outs() << format(" LSDA Pointer: %08\n" PRIx64, *LSDAPointer); - } - } - - // FIXME: Handle instructions. - // For now just emit some bytes - outs() << " Instructions:\n "; - dumpBytes(makeArrayRef((const uint8_t*)Pos, (const uint8_t*)EntryEndPos), - outs()); - outs() << "\n"; - Pos = EntryEndPos; - } -} - void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { std::map<uint64_t, SymbolRef> Symbols; for (const SymbolRef &SymRef : Obj->symbols()) { @@ -7026,8 +6776,6 @@ void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) { printMachOCompactUnwindSection(Obj, Symbols, Section); else if (SectName == "__unwind_info") printMachOUnwindInfoSection(Obj, Symbols, Section); - else if (SectName == "__eh_frame") - printMachOEHFrameSection(Obj, Symbols, Section); } } diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index d5ae5de4b5a..83ad0e11180 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/FaultMaps.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" @@ -181,6 +182,11 @@ cl::opt<bool> cl::opt<bool> PrintFaultMaps("fault-map-section", cl::desc("Display contents of faultmap section")); +cl::opt<DIDumpType> llvm::DwarfDumpType( + "dwarf", cl::init(DIDT_Null), cl::desc("Dump of dwarf debug sections:"), + cl::values(clEnumValN(DIDT_Frames, "frames", ".debug_frame"), + clEnumValEnd)); + static StringRef ToolName; namespace { @@ -1561,6 +1567,11 @@ static void DumpObject(const ObjectFile *o) { printRawClangAST(o); if (PrintFaultMaps) printFaultMaps(o); + if (DwarfDumpType != DIDT_Null) { + std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*o)); + // Dump the complete DWARF structure. + DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */); + } } /// @brief Dump each object file in \a a; @@ -1654,7 +1665,8 @@ int main(int argc, char **argv) { && !(DylibId && MachOOpt) && !(ObjcMetaData && MachOOpt) && !(FilterSections.size() != 0 && MachOOpt) - && !PrintFaultMaps) { + && !PrintFaultMaps + && DwarfDumpType == DIDT_Null) { cl::PrintHelpMessage(); return 2; } diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h index 60cabbc98e2..c50caae5b58 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.h +++ b/llvm/tools/llvm-objdump/llvm-objdump.h @@ -10,6 +10,7 @@ #define LLVM_TOOLS_LLVM_OBJDUMP_LLVM_OBJDUMP_H #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" @@ -55,6 +56,7 @@ extern cl::opt<bool> SectionContents; extern cl::opt<bool> SymbolTable; extern cl::opt<bool> UnwindInfo; extern cl::opt<bool> PrintImmHex; +extern cl::opt<DIDumpType> DwarfDumpType; // Various helper functions. void error(std::error_code ec); |