From: Zachary Turner Date: Mon, 26 Jun 2017 17:22:36 +0000 (+0000) Subject: [llvm-pdbutil] Add a mode to `bytes` for dumping split debug chunks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7226719a52dcf3eaad971668ea6e121077eb77fa;p=llvm [llvm-pdbutil] Add a mode to `bytes` for dumping split debug chunks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306309 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Support/BinaryStreamRef.h b/include/llvm/Support/BinaryStreamRef.h index 499d91cfb11..6d5135cb258 100644 --- a/include/llvm/Support/BinaryStreamRef.h +++ b/include/llvm/Support/BinaryStreamRef.h @@ -174,6 +174,16 @@ struct BinarySubstreamRef { BinaryStreamRef SubSub = StreamData.slice(Off, Size); return {Off + Offset, SubSub}; } + BinarySubstreamRef drop_front(uint32_t N) const { + return slice(N, size() - N); + } + BinarySubstreamRef keep_front(uint32_t N) const { return slice(0, N); } + + std::pair + split(uint32_t Offset) const { + return std::make_pair(keep_front(Offset), drop_front(Offset)); + } + uint32_t size() const { return StreamData.getLength(); } bool empty() const { return size() == 0; } }; diff --git a/test/DebugInfo/PDB/module-bytes.test b/test/DebugInfo/PDB/module-bytes.test index 164ed204ea9..f325331ac53 100644 --- a/test/DebugInfo/PDB/module-bytes.test +++ b/test/DebugInfo/PDB/module-bytes.test @@ -1,5 +1,6 @@ ; RUN: llvm-pdbutil bytes -chunks %p/Inputs/empty.pdb | FileCheck --check-prefix=CHUNKS %s ; RUN: llvm-pdbutil bytes -chunks -mod=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=FILTERED-CHUNKS %s +; RUN: llvm-pdbutil bytes -chunks -split-chunks -mod=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=SPLIT-CHUNKS %s ; RUN: llvm-pdbutil bytes -syms %p/Inputs/empty.pdb | FileCheck --check-prefix=SYMS %s ; RUN: llvm-pdbutil bytes -syms -mod=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=FILTERED-SYMS %s @@ -26,6 +27,17 @@ FILTERED-CHUNKS-NEXT: 6110: 56000000 1001A0A5 BD0D3ECD 93FC29D1 9DE826FB FILTERED-CHUNKS-NEXT: ) FILTERED-CHUNKS-NOT: Mod 0001 +SPLIT-CHUNKS: Debug Chunks +SPLIT-CHUNKS-NEXT: ============================================================ +SPLIT-CHUNKS-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: +SPLIT-CHUNKS-NEXT: lines ( +SPLIT-CHUNKS-NEXT: 60D0: F2000000 30000000 10000000 01000000 0A000000 00000000 03000000 24000000 |....0.......................$...| +SPLIT-CHUNKS-NEXT: 60F0: 00000000 05000080 03000000 06000080 08000000 07000080 |........................| +SPLIT-CHUNKS-NEXT: ) +SPLIT-CHUNKS-NEXT: checksums ( +SPLIT-CHUNKS-NEXT: 6108: F4000000 18000000 56000000 1001A0A5 BD0D3ECD 93FC29D1 9DE826FB F4BC0000 |........V.........>...)...&.....| +SPLIT-CHUNKS-NEXT: ) + SYMS: Module Symbols SYMS-NEXT: ============================================================ SYMS-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: diff --git a/tools/llvm-pdbutil/BytesOutputStyle.cpp b/tools/llvm-pdbutil/BytesOutputStyle.cpp index da29ac02063..9e5a28c2b98 100644 --- a/tools/llvm-pdbutil/BytesOutputStyle.cpp +++ b/tools/llvm-pdbutil/BytesOutputStyle.cpp @@ -319,14 +319,22 @@ static void iterateOneModule(PDBFile &File, LinePrinter &P, const DbiModuleList &Modules, uint32_t I, uint32_t Digits, uint32_t IndentLevel, CallbackT Callback) { + if (I >= Modules.getModuleCount()) { + P.formatLine("Mod {0:4} | Invalid module index ", + fmt_align(I, AlignStyle::Right, std::max(Digits, 4U))); + return; + } + auto Modi = Modules.getModuleDescriptor(I); P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, std::max(Digits, 4U)), Modi.getModuleName()); uint16_t ModiStream = Modi.getModuleStreamIndex(); - AutoIndent Indent2(P, IndentLevel); + if (ModiStream == kInvalidStreamIndex) + return; + auto ModStreamData = MappedBlockStream::createIndexedStream( File.getMsfLayout(), File.getMsfBuffer(), ModiStream, File.getAllocator()); @@ -393,17 +401,48 @@ void BytesOutputStyle::dumpModuleC11() { }); } +static std::string formatChunkKind(DebugSubsectionKind Kind) { + switch (Kind) { + RETURN_CASE(DebugSubsectionKind, None, "none"); + RETURN_CASE(DebugSubsectionKind, Symbols, "symbols"); + RETURN_CASE(DebugSubsectionKind, Lines, "lines"); + RETURN_CASE(DebugSubsectionKind, StringTable, "strings"); + RETURN_CASE(DebugSubsectionKind, FileChecksums, "checksums"); + RETURN_CASE(DebugSubsectionKind, FrameData, "frames"); + RETURN_CASE(DebugSubsectionKind, InlineeLines, "inlinee lines"); + RETURN_CASE(DebugSubsectionKind, CrossScopeImports, "xmi"); + RETURN_CASE(DebugSubsectionKind, CrossScopeExports, "xme"); + RETURN_CASE(DebugSubsectionKind, ILLines, "il lines"); + RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap, "func md token map"); + RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap, "type md token map"); + RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput, + "merged assembly input"); + RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA, "coff symbol rva"); + } + return formatUnknownEnum(Kind); +} + void BytesOutputStyle::dumpModuleC13() { printHeader(P, "Debug Chunks"); AutoIndent Indent(P); - iterateModules(File, P, 2, - [this](uint32_t Modi, const ModuleDebugStreamRef &Stream, - const MSFStreamLayout &Layout) { - auto Chunks = Stream.getC13LinesSubstream(); - P.formatMsfStreamData("Debug Chunks", File, Layout, Chunks); - }); + iterateModules( + File, P, 2, + [this](uint32_t Modi, const ModuleDebugStreamRef &Stream, + const MSFStreamLayout &Layout) { + auto Chunks = Stream.getC13LinesSubstream(); + if (opts::bytes::SplitChunks) { + for (const auto &SS : Stream.subsections()) { + BinarySubstreamRef ThisChunk; + std::tie(ThisChunk, Chunks) = Chunks.split(SS.getRecordLength()); + P.formatMsfStreamData(formatChunkKind(SS.kind()), File, Layout, + ThisChunk); + } + } else { + P.formatMsfStreamData("Debug Chunks", File, Layout, Chunks); + } + }); } void BytesOutputStyle::dumpByteRanges(uint32_t Min, uint32_t Max) { diff --git a/tools/llvm-pdbutil/llvm-pdbutil.cpp b/tools/llvm-pdbutil/llvm-pdbutil.cpp index cb064c70f15..4a176fb1359 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ b/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -114,6 +114,31 @@ cl::OptionCategory TypeCategory("Symbol Type Options"); cl::OptionCategory FilterCategory("Filtering and Sorting Options"); cl::OptionCategory OtherOptions("Other Options"); +cl::ValuesClass ChunkValues = cl::values( + clEnumValN(ModuleSubsection::CrossScopeExports, "cme", + "Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"), + clEnumValN(ModuleSubsection::CrossScopeImports, "cmi", + "Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"), + clEnumValN(ModuleSubsection::FileChecksums, "fc", + "File checksums (DEBUG_S_CHECKSUMS subsection)"), + clEnumValN(ModuleSubsection::InlineeLines, "ilines", + "Inlinee lines (DEBUG_S_INLINEELINES subsection)"), + clEnumValN(ModuleSubsection::Lines, "lines", + "Lines (DEBUG_S_LINES subsection)"), + clEnumValN(ModuleSubsection::StringTable, "strings", + "String Table (DEBUG_S_STRINGTABLE subsection) (not " + "typically present in PDB file)"), + clEnumValN(ModuleSubsection::FrameData, "frames", + "Frame Data (DEBUG_S_FRAMEDATA subsection)"), + clEnumValN(ModuleSubsection::Symbols, "symbols", + "Symbols (DEBUG_S_SYMBOLS subsection) (not typically " + "present in PDB file)"), + clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas", + "COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"), + clEnumValN(ModuleSubsection::Unknown, "unknown", + "Any subsection not covered by another option"), + clEnumValN(ModuleSubsection::All, "all", "All known subsections")); + namespace pretty { cl::list InputFilenames(cl::Positional, cl::desc(""), @@ -328,9 +353,14 @@ cl::opt ModuleSyms("syms", cl::desc("Dump symbol record substream"), cl::opt ModuleC11("c11-chunks", cl::Hidden, cl::desc("Dump C11 CodeView debug chunks"), cl::sub(BytesSubcommand), cl::cat(ModuleCategory)); -cl::opt ModuleC13("chunks", cl::desc("Dump C13 CodeView debug chunks"), +cl::opt ModuleC13("chunks", + cl::desc("Dump C13 CodeView debug chunk subsection"), cl::sub(BytesSubcommand), cl::cat(ModuleCategory)); - +cl::opt SplitChunks( + "split-chunks", + cl::desc( + "When dumping debug chunks, show a different section for each chunk"), + cl::sub(BytesSubcommand), cl::cat(ModuleCategory)); cl::list InputFilenames(cl::Positional, cl::desc(""), cl::OneOrMore, cl::sub(BytesSubcommand)); @@ -501,33 +531,7 @@ cl::opt DumpModuleFiles("module-files", cl::desc("dump file information"), cl::sub(PdbToYamlSubcommand)); cl::list DumpModuleSubsections( "subsections", cl::ZeroOrMore, cl::CommaSeparated, - cl::desc("dump subsections from each module's debug stream"), - cl::values( - clEnumValN( - ModuleSubsection::CrossScopeExports, "cme", - "Cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"), - clEnumValN( - ModuleSubsection::CrossScopeImports, "cmi", - "Cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"), - clEnumValN(ModuleSubsection::FileChecksums, "fc", - "File checksums (DEBUG_S_CHECKSUMS subsection)"), - clEnumValN(ModuleSubsection::InlineeLines, "ilines", - "Inlinee lines (DEBUG_S_INLINEELINES subsection)"), - clEnumValN(ModuleSubsection::Lines, "lines", - "Lines (DEBUG_S_LINES subsection)"), - clEnumValN(ModuleSubsection::StringTable, "strings", - "String Table (DEBUG_S_STRINGTABLE subsection) (not " - "typically present in PDB file)"), - clEnumValN(ModuleSubsection::FrameData, "frames", - "Frame Data (DEBUG_S_FRAMEDATA subsection)"), - clEnumValN(ModuleSubsection::Symbols, "symbols", - "Symbols (DEBUG_S_SYMBOLS subsection) (not typically " - "present in PDB file)"), - clEnumValN(ModuleSubsection::CoffSymbolRVAs, "rvas", - "COFF Symbol RVAs (DEBUG_S_COFF_SYMBOL_RVA subsection)"), - clEnumValN(ModuleSubsection::Unknown, "unknown", - "Any subsection not covered by another option"), - clEnumValN(ModuleSubsection::All, "all", "All known subsections")), + cl::desc("dump subsections from each module's debug stream"), ChunkValues, cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand)); cl::opt DumpModuleSyms("module-syms", cl::desc("dump module symbols"), cl::cat(FileOptions), @@ -980,6 +984,15 @@ static bool parseRange(StringRef Str, return true; } +static void simplifyChunkList(llvm::cl::list &Chunks) { + // If this list contains "All" plus some other stuff, remove the other stuff + // and just keep "All" in the list. + if (!llvm::is_contained(Chunks, opts::ModuleSubsection::All)) + return; + Chunks.reset(); + Chunks.push_back(opts::ModuleSubsection::All); +} + int main(int argc_, const char *argv_[]) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv_[0]); @@ -1050,13 +1063,8 @@ int main(int argc_, const char *argv_[]) { opts::pdb2yaml::DumpModuleSyms = true; opts::pdb2yaml::DumpModuleSubsections.push_back( opts::ModuleSubsection::All); - if (llvm::is_contained(opts::pdb2yaml::DumpModuleSubsections, - opts::ModuleSubsection::All)) { - opts::pdb2yaml::DumpModuleSubsections.reset(); - opts::pdb2yaml::DumpModuleSubsections.push_back( - opts::ModuleSubsection::All); - } } + simplifyChunkList(opts::pdb2yaml::DumpModuleSubsections); if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles) opts::pdb2yaml::DumpModules = true; diff --git a/tools/llvm-pdbutil/llvm-pdbutil.h b/tools/llvm-pdbutil/llvm-pdbutil.h index ea62f18e2e1..837d8ebbaf9 100644 --- a/tools/llvm-pdbutil/llvm-pdbutil.h +++ b/tools/llvm-pdbutil/llvm-pdbutil.h @@ -117,7 +117,7 @@ extern llvm::cl::opt ModuleIndex; extern llvm::cl::opt ModuleSyms; extern llvm::cl::opt ModuleC11; extern llvm::cl::opt ModuleC13; - +extern llvm::cl::opt SplitChunks; } // namespace bytes namespace dump {