diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-02 18:30:13 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-02 18:30:13 +0000 |
commit | a303c417bbdb53703c2c17398b08486bde78f1f6 (patch) | |
tree | 98366d6b93d863cefdc53f16c66c0c5ae7fb2261 /tools/llvm-readobj/COFFDumper.cpp | |
parent | 12f3ca4cdb95b193af905a00e722a4dcb40b3de3 (diff) |
Notes
Diffstat (limited to 'tools/llvm-readobj/COFFDumper.cpp')
-rw-r--r-- | tools/llvm-readobj/COFFDumper.cpp | 204 |
1 files changed, 97 insertions, 107 deletions
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index 9836c137ed2ca..a7088c1c7419a 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -25,6 +25,9 @@ #include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" @@ -38,11 +41,12 @@ #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataExtractor.h" -#include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/SourceMgr.h" @@ -78,6 +82,7 @@ public: void printCOFFDirectives() override; void printCOFFBaseReloc() override; void printCOFFDebugDirectory() override; + void printCOFFResources() override; void printCodeViewDebugInfo() override; void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVIDs, llvm::codeview::TypeTableBuilder &CVTypes) override; @@ -496,19 +501,19 @@ WeakExternalCharacteristics[] = { }; static const EnumEntry<uint32_t> SubSectionTypes[] = { - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Symbols), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Lines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, StringTable), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FileChecksums), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FrameData), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, InlineeLines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeImports), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeExports), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, ILLines), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FuncMDTokenMap), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, TypeMDTokenMap), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, MergedAssemblyInput), - LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CoffSymbolRVA), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, Symbols), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, Lines), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, StringTable), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FileChecksums), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FrameData), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, InlineeLines), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CrossScopeImports), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CrossScopeExports), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, ILLines), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, FuncMDTokenMap), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, TypeMDTokenMap), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, MergedAssemblyInput), + LLVM_READOBJ_ENUM_CLASS_ENT(ModuleDebugFragmentKind, CoffSymbolRVA), }; static const EnumEntry<uint32_t> FrameDataFlags[] = { @@ -730,11 +735,11 @@ void COFFDumper::initializeFileAndStringTables(StringRef Data) { error(consume(Data, SubSectionSize)); if (SubSectionSize > Data.size()) return error(object_error::parse_failed); - switch (ModuleSubstreamKind(SubType)) { - case ModuleSubstreamKind::FileChecksums: + switch (ModuleDebugFragmentKind(SubType)) { + case ModuleDebugFragmentKind::FileChecksums: CVFileChecksumTable = Data.substr(0, SubSectionSize); break; - case ModuleSubstreamKind::StringTable: + case ModuleDebugFragmentKind::StringTable: CVStringTable = Data.substr(0, SubSectionSize); break; default: @@ -800,20 +805,20 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, printBinaryBlockWithRelocs("SubSectionContents", Section, SectionContents, Contents); - switch (ModuleSubstreamKind(SubType)) { - case ModuleSubstreamKind::Symbols: + switch (ModuleDebugFragmentKind(SubType)) { + case ModuleDebugFragmentKind::Symbols: printCodeViewSymbolsSubsection(Contents, Section, SectionContents); break; - case ModuleSubstreamKind::InlineeLines: + case ModuleDebugFragmentKind::InlineeLines: printCodeViewInlineeLines(Contents); break; - case ModuleSubstreamKind::FileChecksums: + case ModuleDebugFragmentKind::FileChecksums: printCodeViewFileChecksums(Contents); break; - case ModuleSubstreamKind::Lines: { + case ModuleDebugFragmentKind::Lines: { // Holds a PC to file:line table. Some data to parse this subsection is // stored in the other subsections, so just check sanity and store the // pointers for deferred processing. @@ -839,7 +844,7 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, FunctionNames.push_back(LinkageName); break; } - case ModuleSubstreamKind::FrameData: { + case ModuleDebugFragmentKind::FrameData: { // First four bytes is a relocation against the function. BinaryByteStream S(Contents, llvm::support::little); BinaryStreamReader SR(S); @@ -890,45 +895,29 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, ListScope S(W, "FunctionLineTable"); W.printString("LinkageName", Name); - DataExtractor DE(FunctionLineTables[Name], true, 4); - uint32_t Offset = 6; // Skip relocations. - uint16_t Flags = DE.getU16(&Offset); - W.printHex("Flags", Flags); - bool HasColumnInformation = Flags & codeview::LineFlags::HaveColumns; - uint32_t FunctionSize = DE.getU32(&Offset); - W.printHex("CodeSize", FunctionSize); - while (DE.isValidOffset(Offset)) { - // For each range of lines with the same filename, we have a segment - // in the line table. The filename string is accessed using double - // indirection to the string table subsection using the index subsection. - uint32_t OffsetInIndex = DE.getU32(&Offset), - NumLines = DE.getU32(&Offset), - FullSegmentSize = DE.getU32(&Offset); - - uint32_t ColumnOffset = Offset + 8 * NumLines; - DataExtractor ColumnDE(DE.getData(), true, 4); - - if (FullSegmentSize != - 12 + 8 * NumLines + (HasColumnInformation ? 4 * NumLines : 0)) { - error(object_error::parse_failed); - return; - } + BinaryByteStream LineTableInfo(FunctionLineTables[Name], support::little); + BinaryStreamReader Reader(LineTableInfo); + + ModuleDebugLineFragmentRef LineInfo; + error(LineInfo.initialize(Reader)); + + W.printHex("Flags", LineInfo.header()->Flags); + W.printHex("CodeSize", LineInfo.header()->CodeSize); + for (const auto &Entry : LineInfo) { ListScope S(W, "FilenameSegment"); - printFileNameForOffset("Filename", OffsetInIndex); - for (unsigned LineIdx = 0; - LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) { - // Then go the (PC, LineNumber) pairs. The line number is stored in the - // least significant 31 bits of the respective word in the table. - uint32_t PC = DE.getU32(&Offset), LineData = DE.getU32(&Offset); - if (PC >= FunctionSize) { + printFileNameForOffset("Filename", Entry.NameIndex); + uint32_t ColumnIndex = 0; + for (const auto &Line : Entry.LineNumbers) { + if (Line.Offset >= LineInfo.header()->CodeSize) { error(object_error::parse_failed); return; } - char Buffer[32]; - format("+0x%X", PC).snprint(Buffer, 32); - ListScope PCScope(W, Buffer); - LineInfo LI(LineData); + + std::string PC = formatv("+{0:X}", uint32_t(Line.Offset)); + ListScope PCScope(W, PC); + codeview::LineInfo LI(Line.Flags); + if (LI.isAlwaysStepInto()) W.printString("StepInto", StringRef("Always")); else if (LI.isNeverStepInto()) @@ -937,19 +926,10 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, W.printNumber("LineNumberStart", LI.getStartLine()); W.printNumber("LineNumberEndDelta", LI.getLineDelta()); W.printBoolean("IsStatement", LI.isStatement()); - if (HasColumnInformation && - ColumnDE.isValidOffsetForDataOfSize(ColumnOffset, 4)) { - uint16_t ColStart = ColumnDE.getU16(&ColumnOffset); - W.printNumber("ColStart", ColStart); - uint16_t ColEnd = ColumnDE.getU16(&ColumnOffset); - W.printNumber("ColEnd", ColEnd); - } - } - // Skip over the column data. - if (HasColumnInformation) { - for (unsigned LineIdx = 0; - LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) { - DE.getU32(&Offset); + if (LineInfo.hasColumnInfo()) { + W.printNumber("ColStart", Entry.Columns[ColumnIndex].StartColumn); + W.printNumber("ColEnd", Entry.Columns[ColumnIndex].EndColumn); + ++ColumnIndex; } } } @@ -985,56 +965,42 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { BinaryByteStream S(Subsection, llvm::support::little); BinaryStreamReader SR(S); - while (!SR.empty()) { + ModuleDebugFileChecksumFragmentRef Checksums; + error(Checksums.initialize(SR)); + + for (auto &FC : Checksums) { DictScope S(W, "FileChecksum"); - const FileChecksum *FC; - error(SR.readObject(FC)); - if (FC->FileNameOffset >= CVStringTable.size()) + + if (FC.FileNameOffset >= CVStringTable.size()) error(object_error::parse_failed); StringRef Filename = - CVStringTable.drop_front(FC->FileNameOffset).split('\0').first; - W.printHex("Filename", Filename, FC->FileNameOffset); - W.printHex("ChecksumSize", FC->ChecksumSize); - W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind), + CVStringTable.drop_front(FC.FileNameOffset).split('\0').first; + W.printHex("Filename", Filename, FC.FileNameOffset); + W.printHex("ChecksumSize", FC.Checksum.size()); + W.printEnum("ChecksumKind", uint8_t(FC.Kind), makeArrayRef(FileChecksumKindNames)); - if (FC->ChecksumSize >= SR.bytesRemaining()) - error(object_error::parse_failed); - ArrayRef<uint8_t> ChecksumBytes; - error(SR.readBytes(ChecksumBytes, FC->ChecksumSize)); - W.printBinary("ChecksumBytes", ChecksumBytes); - unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) - - sizeof(FileChecksum); - PaddedSize -= ChecksumBytes.size(); - if (PaddedSize > SR.bytesRemaining()) - error(object_error::parse_failed); - error(SR.skip(PaddedSize)); + + W.printBinary("ChecksumBytes", FC.Checksum); } } void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) { BinaryByteStream S(Subsection, llvm::support::little); BinaryStreamReader SR(S); - uint32_t Signature; - error(SR.readInteger(Signature)); - bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles); + ModuleDebugInlineeLineFragmentRef Lines; + error(Lines.initialize(SR)); - while (!SR.empty()) { - const InlineeSourceLine *ISL; - error(SR.readObject(ISL)); + for (auto &Line : Lines) { DictScope S(W, "InlineeSourceLine"); - printTypeIndex("Inlinee", ISL->Inlinee); - printFileNameForOffset("FileID", ISL->FileID); - W.printNumber("SourceLineNum", ISL->SourceLineNum); - - if (HasExtraFiles) { - uint32_t ExtraFileCount; - error(SR.readInteger(ExtraFileCount)); - W.printNumber("ExtraFileCount", ExtraFileCount); + printTypeIndex("Inlinee", Line.Header->Inlinee); + printFileNameForOffset("FileID", Line.Header->FileID); + W.printNumber("SourceLineNum", Line.Header->SourceLineNum); + + if (Lines.hasExtraFiles()) { + W.printNumber("ExtraFileCount", Line.ExtraFiles.size()); ListScope ExtraFiles(W, "ExtraFiles"); - for (unsigned I = 0; I < ExtraFileCount; ++I) { - uint32_t FileID; - error(SR.readInteger(FileID)); - printFileNameForOffset("FileID", FileID); + for (const auto &FID : Line.ExtraFiles) { + printFileNameForOffset("FileID", FID); } } } @@ -1527,6 +1493,30 @@ void COFFDumper::printCOFFBaseReloc() { } } +void COFFDumper::printCOFFResources() { + ListScope ResourcesD(W, "Resources"); + for (const SectionRef &S : Obj->sections()) { + StringRef Name; + error(S.getName(Name)); + if (!Name.startswith(".rsrc")) + continue; + + StringRef Ref; + error(S.getContents(Ref)); + + if ((Name == ".rsrc") || (Name == ".rsrc$01")) { + auto Table = + reinterpret_cast<const coff_resource_dir_table *>(Ref.data()); + char FormattedTime[20]; + time_t TDS = time_t(Table->TimeDateStamp); + strftime(FormattedTime, sizeof(FormattedTime), "%Y-%m-%d %H:%M:%S", + gmtime(&TDS)); + W.printHex("Time/Date Stamp", FormattedTime, Table->TimeDateStamp); + } + W.printBinaryBlock(Name.str() + " Data", Ref); + } +} + void COFFDumper::printStackMap() const { object::SectionRef StackMapSection; for (auto Sec : Obj->sections()) { |