OSDN Git Service

[llvm-pdbutil] Add support for dumping detailed module stats.
authorZachary Turner <zturner@google.com>
Mon, 21 Aug 2017 14:53:25 +0000 (14:53 +0000)
committerZachary Turner <zturner@google.com>
Mon, 21 Aug 2017 14:53:25 +0000 (14:53 +0000)
This adds support for dumping a summary of module symbols
and CodeView debug chunks.  This option prints a table for
each module of all of the symbols that occurred in the module
and the number of times it occurred and total byte size.  Then
at the end it prints the totals for the entire file.

Additionally, this patch adds the -jmc (just my code) option,
which suppresses modules which are from external libraries or
linker imports, so that you can focus only on the object files
and libraries that originate from your own source code.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311338 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h
include/llvm/DebugInfo/PDB/Native/PDBFile.h
lib/DebugInfo/PDB/Native/PDBFile.cpp
test/DebugInfo/PDB/just-my-code.test [new file with mode: 0644]
test/DebugInfo/PDB/module-stats.test [new file with mode: 0644]
test/DebugInfo/PDB/pdbdump-headers.test
tools/llvm-pdbutil/BytesOutputStyle.cpp
tools/llvm-pdbutil/BytesOutputStyle.h
tools/llvm-pdbutil/Diff.cpp
tools/llvm-pdbutil/DumpOutputStyle.cpp
tools/llvm-pdbutil/DumpOutputStyle.h
tools/llvm-pdbutil/FormatUtil.cpp
tools/llvm-pdbutil/FormatUtil.h
tools/llvm-pdbutil/MinimalSymbolDumper.cpp
tools/llvm-pdbutil/StreamUtil.cpp
tools/llvm-pdbutil/StreamUtil.h
tools/llvm-pdbutil/llvm-pdbutil.cpp
tools/llvm-pdbutil/llvm-pdbutil.h

index f413fd1..5e81fbe 100644 (file)
@@ -32,6 +32,7 @@ public:
   ModuleDebugStreamRef(const DbiModuleDescriptor &Module,
                        std::unique_ptr<msf::MappedBlockStream> Stream);
   ModuleDebugStreamRef(ModuleDebugStreamRef &&Other) = default;
+  ModuleDebugStreamRef(const ModuleDebugStreamRef &Other) = default;
   ~ModuleDebugStreamRef();
 
   Error reload();
index a785ff3..285f6c4 100644 (file)
@@ -61,6 +61,7 @@ public:
   uint64_t getBlockMapOffset() const;
 
   uint32_t getNumStreams() const override;
+  uint32_t getMaxStreamSize() const;
   uint32_t getStreamByteSize(uint32_t StreamIndex) const override;
   ArrayRef<support::ulittle32_t>
   getStreamBlockList(uint32_t StreamIndex) const override;
@@ -83,6 +84,8 @@ public:
 
   ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
 
+  std::unique_ptr<msf::MappedBlockStream> createIndexedStream(uint16_t SN);
+
   msf::MSFStreamLayout getStreamLayout(uint32_t StreamIdx) const;
   msf::MSFStreamLayout getFpmStreamLayout() const;
 
index de460d0..414de7b 100644 (file)
@@ -85,6 +85,11 @@ uint32_t PDBFile::getNumStreams() const {
   return ContainerLayout.StreamSizes.size();
 }
 
+uint32_t PDBFile::getMaxStreamSize() const {
+  return *std::max_element(ContainerLayout.StreamSizes.begin(),
+                           ContainerLayout.StreamSizes.end());
+}
+
 uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
   return ContainerLayout.StreamSizes[StreamIndex];
 }
@@ -229,6 +234,13 @@ ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
   return ContainerLayout.DirectoryBlocks;
 }
 
+std::unique_ptr<MappedBlockStream> PDBFile::createIndexedStream(uint16_t SN) {
+  if (SN == kInvalidStreamIndex)
+    return nullptr;
+  return MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, SN,
+                                                Allocator);
+}
+
 MSFStreamLayout PDBFile::getStreamLayout(uint32_t StreamIdx) const {
   MSFStreamLayout Result;
   auto Blocks = getStreamBlockList(StreamIdx);
diff --git a/test/DebugInfo/PDB/just-my-code.test b/test/DebugInfo/PDB/just-my-code.test
new file mode 100644 (file)
index 0000000..f0a1f7f
--- /dev/null
@@ -0,0 +1,20 @@
+; RUN: llvm-pdbutil dump -modules %p/Inputs/big-read.pdb | FileCheck --check-prefix=ALL %s
+; RUN: llvm-pdbutil dump -modules -jmc %p/Inputs/big-read.pdb | FileCheck --check-prefix=JMC %s
+
+ALL:       Mod 0000 |
+ALL:       Mod 0001 |
+ALL:       Mod 0002 |
+ALL:       Mod 0003 |
+ALL:       Mod 0004 |
+ALL:       Mod 0005 |
+ALL:       Mod 0006 |
+ALL:       Mod 0047 |
+
+JMC:       Mod 0000
+JMC-NOT:   Mod 0001
+JMC-NOT:   Mod 0002
+JMC-NOT:   Mod 0003
+JMC-NOT:   Mod 0004
+JMC-NOT:   Mod 0005
+JMC-NOT:   Mod 0006
+JMC-NOT:   Mod 0047
diff --git a/test/DebugInfo/PDB/module-stats.test b/test/DebugInfo/PDB/module-stats.test
new file mode 100644 (file)
index 0000000..8178709
--- /dev/null
@@ -0,0 +1,81 @@
+; RUN: llvm-pdbutil dump -mod-stats %p/Inputs/empty.pdb | FileCheck --check-prefix=ALL %s
+; RUN: llvm-pdbutil dump -mod-stats -modi=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=ONE %s
+
+ALL:        Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
+ALL-NEXT:     Stream 12, 308 bytes
+ALL:            Symbols
+ALL-NEXT:                                          Total:       6 entries (     204 bytes)
+ALL-NEXT:       --------------------------------------------------------------------------
+ALL-NEXT:                                      S_GPROC32:       1 entries (      44 bytes)
+ALL-NEXT:                                    S_FRAMEPROC:       1 entries (      32 bytes)
+ALL-NEXT:                                          S_END:       1 entries (       4 bytes)
+ALL-NEXT:                                      S_OBJNAME:       1 entries (      56 bytes)
+ALL-NEXT:                                     S_COMPILE3:       1 entries (      60 bytes)
+ALL-NEXT:                                    S_BUILDINFO:       1 entries (       8 bytes)
+ALL:            Chunks
+ALL-NEXT:                                          Total:       2 entries (      88 bytes)
+ALL-NEXT:       --------------------------------------------------------------------------
+ALL-NEXT:                             DEBUG_S_FILECHKSMS:       1 entries (      32 bytes)
+ALL-NEXT:                                  DEBUG_S_LINES:       1 entries (      56 bytes)
+ALL-NEXT:   Mod 0001 | `* Linker *`:
+ALL-NEXT:     Stream 14, 520 bytes
+ALL:            Symbols
+ALL-NEXT:                                          Total:      13 entries (     512 bytes)
+ALL-NEXT:       --------------------------------------------------------------------------
+ALL-NEXT:                                      S_SECTION:       4 entries (     112 bytes)
+ALL-NEXT:                                     S_ENVBLOCK:       1 entries (     172 bytes)
+ALL-NEXT:                                   S_TRAMPOLINE:       1 entries (      20 bytes)
+ALL-NEXT:                                      S_OBJNAME:       1 entries (      20 bytes)
+ALL-NEXT:                                     S_COMPILE3:       1 entries (      48 bytes)
+ALL-NEXT:                                    S_COFFGROUP:       5 entries (     140 bytes)
+ALL:            Chunks
+ALL-NEXT:                                          Total:       0 entries (       0 bytes)
+ALL-NEXT:       --------------------------------------------------------------------------
+ALL-NEXT:   Summary |
+ALL:            Symbols
+ALL-NEXT:                                          Total:      19 entries (     716 bytes)
+ALL-NEXT:       --------------------------------------------------------------------------
+ALL-NEXT:                                      S_SECTION:       4 entries (     112 bytes)
+ALL-NEXT:                                      S_GPROC32:       1 entries (      44 bytes)
+ALL-NEXT:                                     S_ENVBLOCK:       1 entries (     172 bytes)
+ALL-NEXT:                                    S_FRAMEPROC:       1 entries (      32 bytes)
+ALL-NEXT:                                   S_TRAMPOLINE:       1 entries (      20 bytes)
+ALL-NEXT:                                          S_END:       1 entries (       4 bytes)
+ALL-NEXT:                                      S_OBJNAME:       2 entries (      76 bytes)
+ALL-NEXT:                                     S_COMPILE3:       2 entries (     108 bytes)
+ALL-NEXT:                                    S_COFFGROUP:       5 entries (     140 bytes)
+ALL-NEXT:                                    S_BUILDINFO:       1 entries (       8 bytes)
+ALL:            Chunks
+ALL-NEXT:                                          Total:       2 entries (      88 bytes)
+ALL-NEXT:       --------------------------------------------------------------------------
+ALL-NEXT:                             DEBUG_S_FILECHKSMS:       1 entries (      32 bytes)
+ALL-NEXT:                                  DEBUG_S_LINES:       1 entries (      56 bytes)
+
+ONE-NOT:      Mod 0000
+ONE:          Mod 0001 | `* Linker *`:
+ONE-NEXT:     Stream 14, 520 bytes
+ONE:            Symbols
+ONE-NEXT:                                          Total:      13 entries (     512 bytes)
+ONE-NEXT:       --------------------------------------------------------------------------
+ONE-NEXT:                                      S_SECTION:       4 entries (     112 bytes)
+ONE-NEXT:                                     S_ENVBLOCK:       1 entries (     172 bytes)
+ONE-NEXT:                                   S_TRAMPOLINE:       1 entries (      20 bytes)
+ONE-NEXT:                                      S_OBJNAME:       1 entries (      20 bytes)
+ONE-NEXT:                                     S_COMPILE3:       1 entries (      48 bytes)
+ONE-NEXT:                                    S_COFFGROUP:       5 entries (     140 bytes)
+ONE:            Chunks
+ONE-NEXT:                                          Total:       0 entries (       0 bytes)
+ONE-NEXT:       --------------------------------------------------------------------------
+ONE-NEXT:   Summary |
+ONE:            Symbols
+ONE-NEXT:                                          Total:      13 entries (     512 bytes)
+ONE-NEXT:       --------------------------------------------------------------------------
+ONE-NEXT:                                      S_SECTION:       4 entries (     112 bytes)
+ONE-NEXT:                                     S_ENVBLOCK:       1 entries (     172 bytes)
+ONE-NEXT:                                   S_TRAMPOLINE:       1 entries (      20 bytes)
+ONE-NEXT:                                      S_OBJNAME:       1 entries (      20 bytes)
+ONE-NEXT:                                     S_COMPILE3:       1 entries (      48 bytes)
+ONE-NEXT:                                    S_COFFGROUP:       5 entries (     140 bytes)
+ONE:            Chunks
+ONE-NEXT:                                          Total:       0 entries (       0 bytes)
+ONE-NEXT:       --------------------------------------------------------------------------
index 1896809..23a250e 100644 (file)
@@ -22,39 +22,39 @@ ALL-NEXT:   Has conflicting types: false
 ALL-NEXT:   Is stripped: false
 ALL:                                  Streams
 ALL-NEXT: ============================================================
-ALL-NEXT:     Stream  0: [Old MSF Directory] (40 bytes)
+ALL-NEXT:     Stream  0 (  40 bytes): [Old MSF Directory]
 ALL-NEXT:                Blocks: [8]
-ALL-NEXT:     Stream  1: [PDB Stream] (118 bytes)
+ALL-NEXT:     Stream  1 ( 118 bytes): [PDB Stream]
 ALL-NEXT:                Blocks: [19]
-ALL-NEXT:     Stream  2: [TPI Stream] (5392 bytes)
+ALL-NEXT:     Stream  2 (5392 bytes): [TPI Stream]
 ALL-NEXT:                Blocks: [18, 17]
-ALL-NEXT:     Stream  3: [DBI Stream] (739 bytes)
+ALL-NEXT:     Stream  3 ( 739 bytes): [DBI Stream]
 ALL-NEXT:                Blocks: [14]
-ALL-NEXT:     Stream  4: [IPI Stream] (784 bytes)
+ALL-NEXT:     Stream  4 ( 784 bytes): [IPI Stream]
 ALL-NEXT:                Blocks: [20]
-ALL-NEXT:     Stream  5: [Named Stream "/LinkInfo"] (0 bytes)
+ALL-NEXT:     Stream  5 (   0 bytes): [Named Stream "/LinkInfo"]
 ALL-NEXT:                Blocks: []
-ALL-NEXT:     Stream  6: [Global Symbol Hash] (556 bytes)
+ALL-NEXT:     Stream  6 ( 556 bytes): [Global Symbol Hash]
 ALL-NEXT:                Blocks: [11]
-ALL-NEXT:     Stream  7: [Public Symbol Hash] (604 bytes)
+ALL-NEXT:     Stream  7 ( 604 bytes): [Public Symbol Hash]
 ALL-NEXT:                Blocks: [13]
-ALL-NEXT:     Stream  8: [Public Symbol Records] (104 bytes)
+ALL-NEXT:     Stream  8 ( 104 bytes): [Symbol Records]
 ALL-NEXT:                Blocks: [12]
-ALL-NEXT:     Stream  9: [Named Stream "/src/headerblock"] (0 bytes)
+ALL-NEXT:     Stream  9 (   0 bytes): [Named Stream "/src/headerblock"]
 ALL-NEXT:                Blocks: []
-ALL-NEXT:     Stream 10: [Section Header Data] (160 bytes)
+ALL-NEXT:     Stream 10 ( 160 bytes): [Section Header Data]
 ALL-NEXT:                Blocks: [10]
-ALL-NEXT:     Stream 11: [New FPO Data] (32 bytes)
+ALL-NEXT:     Stream 11 (  32 bytes): [New FPO Data]
 ALL-NEXT:                Blocks: [15]
-ALL-NEXT:     Stream 12: [Module "d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj"] (308 bytes)
+ALL-NEXT:     Stream 12 ( 308 bytes): [Module "d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj"]
 ALL-NEXT:                Blocks: [6]
-ALL-NEXT:     Stream 13: [Named Stream "/names"] (239 bytes)
+ALL-NEXT:     Stream 13 ( 239 bytes): [Named Stream "/names"]
 ALL-NEXT:                Blocks: [16]
-ALL-NEXT:     Stream 14: [Module "* Linker *"] (520 bytes)
+ALL-NEXT:     Stream 14 ( 520 bytes): [Module "* Linker *"]
 ALL-NEXT:                Blocks: [7]
-ALL-NEXT:     Stream 15: [TPI Hash] (308 bytes)
+ALL-NEXT:     Stream 15 ( 308 bytes): [TPI Hash]
 ALL-NEXT:                Blocks: [21]
-ALL-NEXT:     Stream 16: [IPI Hash] (68 bytes)
+ALL-NEXT:     Stream 16 (  68 bytes): [IPI Hash]
 ALL-NEXT:                Blocks: [22]
 ALL:                                String Table
 ALL-NEXT: ============================================================
@@ -64,11 +64,11 @@ ALL-NEXT:    86 | 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
 ALL-NEXT:   134 | '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = '
 ALL:                                       Modules
 ALL-NEXT: ============================================================
-ALL-NEXT:   Mod 0000 | Name: `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
+ALL-NEXT:   Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
 ALL-NEXT:              Obj: `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
 ALL-NEXT:              debug stream: 12, # files: 1, has ec info: false
 ALL-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-ALL-NEXT:   Mod 0001 | Name: `* Linker *`:
+ALL-NEXT:   Mod 0001 |  `* Linker *`:
 ALL-NEXT:              Obj: ``:
 ALL-NEXT:              debug stream: 14, # files: 0, has ec info: false
 ALL-NEXT:              pdb file ni: 1 `{{.*empty.pdb}}`, src file ni: 0 ``
@@ -605,195 +605,195 @@ BIG-NEXT:   Has conflicting types: false
 BIG-NEXT:   Is stripped: false
 BIG:                              Modules
 BIG-NEXT: ============================================================
-BIG-NEXT:   Mod 0000 | Name: `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`:
+BIG-NEXT:   Mod 0000 | `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`:
 BIG-NEXT:              Obj: `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`:
 BIG-NEXT:              debug stream: 12, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0001 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_cpu_disp_.obj`:
+BIG-NEXT:   Mod 0001 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_cpu_disp_.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 14, # files: 14, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0002 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_initsect_.obj`:
+BIG-NEXT:   Mod 0002 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_initsect_.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 15, # files: 19, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0003 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_sehprolg4_.obj`:
+BIG-NEXT:   Mod 0003 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_sehprolg4_.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 16, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 1 `f:\dd\vctools\crt\vcstartup\src\eh\i386\sehprolg4.asm`
-BIG-NEXT:   Mod 0004 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_chandler4gs_.obj`:
+BIG-NEXT:   Mod 0004 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_chandler4gs_.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 17, # files: 14, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0005 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_secchk_.obj`:
+BIG-NEXT:   Mod 0005 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_secchk_.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 18, # files: 14, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0006 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_cookie.obj`:
+BIG-NEXT:   Mod 0006 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_cookie.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 19, # files: 9, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0007 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_report.obj`:
+BIG-NEXT:   Mod 0007 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_report.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 20, # files: 14, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0008 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_support.obj`:
+BIG-NEXT:   Mod 0008 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_support.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 21, # files: 10, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0009 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\checkcfg.obj`:
+BIG-NEXT:   Mod 0009 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\checkcfg.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 22, # files: 14, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0010 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\guard_support.obj`:
+BIG-NEXT:   Mod 0010 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\guard_support.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 23, # files: 10, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0011 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\loadcfg.obj`:
+BIG-NEXT:   Mod 0011 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\loadcfg.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 24, # files: 9, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0012 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_dtor.obj`:
+BIG-NEXT:   Mod 0012 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_dtor.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 25, # files: 11, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0013 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_init.obj`:
+BIG-NEXT:   Mod 0013 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_init.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 26, # files: 10, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0014 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr_detection.obj`:
+BIG-NEXT:   Mod 0014 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr_detection.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 27, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0015 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_detection.obj`:
+BIG-NEXT:   Mod 0015 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_detection.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 28, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0016 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\argv_mode.obj`:
+BIG-NEXT:   Mod 0016 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\argv_mode.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 29, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0017 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\commit_mode.obj`:
+BIG-NEXT:   Mod 0017 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\commit_mode.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 30, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0018 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_local_stdio_options.obj`:
+BIG-NEXT:   Mod 0018 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_local_stdio_options.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 31, # files: 24, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0019 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\denormal_control.obj`:
+BIG-NEXT:   Mod 0019 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\denormal_control.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 32, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0020 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\env_mode.obj`:
+BIG-NEXT:   Mod 0020 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\env_mode.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 33, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0021 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\file_mode.obj`:
+BIG-NEXT:   Mod 0021 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\file_mode.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 34, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0022 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\invalid_parameter_handler.obj`:
+BIG-NEXT:   Mod 0022 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\invalid_parameter_handler.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 35, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0023 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr.obj`:
+BIG-NEXT:   Mod 0023 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 36, # files: 2, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0024 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\new_mode.obj`:
+BIG-NEXT:   Mod 0024 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\new_mode.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 37, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0025 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\thread_locale.obj`:
+BIG-NEXT:   Mod 0025 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\thread_locale.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 38, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0026 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\tncleanup.obj`:
+BIG-NEXT:   Mod 0026 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\tncleanup.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 39, # files: 21, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0027 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\exe_main.obj`:
+BIG-NEXT:   Mod 0027 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\exe_main.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 40, # files: 26, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0028 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\initializers.obj`:
+BIG-NEXT:   Mod 0028 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\initializers.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 41, # files: 20, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0029 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility.obj`:
+BIG-NEXT:   Mod 0029 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 42, # files: 20, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0030 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_stubs.obj`:
+BIG-NEXT:   Mod 0030 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_stubs.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 43, # files: 1, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0031 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility_desktop.obj`:
+BIG-NEXT:   Mod 0031 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility_desktop.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 44, # files: 20, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0032 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_precision.obj`:
+BIG-NEXT:   Mod 0032 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_precision.obj`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
 BIG-NEXT:              debug stream: 45, # files: 20, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0033 | Name: `Import:KERNEL32.dll`:
+BIG-NEXT:   Mod 0033 | `Import:KERNEL32.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib`:
 BIG-NEXT:              debug stream: 47, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0034 | Name: `KERNEL32.dll`:
+BIG-NEXT:   Mod 0034 | `KERNEL32.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib`:
 BIG-NEXT:              debug stream: 46, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0035 | Name: `Import:VCRUNTIME140.dll`:
+BIG-NEXT:   Mod 0035 | `Import:VCRUNTIME140.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib`:
 BIG-NEXT:              debug stream: 49, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0036 | Name: `VCRUNTIME140.dll`:
+BIG-NEXT:   Mod 0036 | `VCRUNTIME140.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib`:
 BIG-NEXT:              debug stream: 48, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0037 | Name: `Import:api-ms-win-crt-stdio-l1-1-0.dll`:
+BIG-NEXT:   Mod 0037 | `Import:api-ms-win-crt-stdio-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 59, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0038 | Name: `api-ms-win-crt-stdio-l1-1-0.dll`:
+BIG-NEXT:   Mod 0038 | `api-ms-win-crt-stdio-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 58, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0039 | Name: `Import:api-ms-win-crt-runtime-l1-1-0.dll`:
+BIG-NEXT:   Mod 0039 | `Import:api-ms-win-crt-runtime-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 57, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0040 | Name: `api-ms-win-crt-runtime-l1-1-0.dll`:
+BIG-NEXT:   Mod 0040 | `api-ms-win-crt-runtime-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 56, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0041 | Name: `Import:api-ms-win-crt-math-l1-1-0.dll`:
+BIG-NEXT:   Mod 0041 | `Import:api-ms-win-crt-math-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 55, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0042 | Name: `api-ms-win-crt-math-l1-1-0.dll`:
+BIG-NEXT:   Mod 0042 | `api-ms-win-crt-math-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 54, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0043 | Name: `Import:api-ms-win-crt-locale-l1-1-0.dll`:
+BIG-NEXT:   Mod 0043 | `Import:api-ms-win-crt-locale-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 53, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0044 | Name: `api-ms-win-crt-locale-l1-1-0.dll`:
+BIG-NEXT:   Mod 0044 | `api-ms-win-crt-locale-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 52, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0045 | Name: `Import:api-ms-win-crt-heap-l1-1-0.dll`:
+BIG-NEXT:   Mod 0045 | `Import:api-ms-win-crt-heap-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 51, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0046 | Name: `api-ms-win-crt-heap-l1-1-0.dll`:
+BIG-NEXT:   Mod 0046 | `api-ms-win-crt-heap-l1-1-0.dll`:
 BIG-NEXT:              Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
 BIG-NEXT:              debug stream: 50, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 0 ``, src file ni: 0 ``
-BIG-NEXT:   Mod 0047 | Name: `* Linker *`:
+BIG-NEXT:   Mod 0047 |  `* Linker *`:
 BIG-NEXT:              Obj: ``:
 BIG-NEXT:              debug stream: 60, # files: 0, has ec info: false
 BIG-NEXT:              pdb file ni: 55 `{{.*test.pdb}}`, src file ni: 0 ``
index a50da5c..2b96c8f 100644 (file)
@@ -407,27 +407,6 @@ 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");
 
@@ -508,7 +487,8 @@ void BytesOutputStyle::dumpStreamBytes() {
       P.formatLine("Stream {0}: Not present", Spec.SI);
       continue;
     }
-    P.formatMsfStreamData("Data", File, Spec.SI, StreamPurposes[Spec.SI],
-                          Spec.Begin, Spec.Size);
+    P.formatMsfStreamData("Data", File, Spec.SI,
+                          StreamPurposes[Spec.SI].getShortName(), Spec.Begin,
+                          Spec.Size);
   }
 }
index 876178d..aa53429 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "LinePrinter.h"
 #include "OutputStyle.h"
+#include "StreamUtil.h"
 
 #include "llvm/Support/Error.h"
 
@@ -60,7 +61,7 @@ private:
   PDBFile &File;
   LinePrinter P;
   ExitOnError Err;
-  SmallVector<std::string, 8> StreamPurposes;
+  SmallVector<StreamInfo, 8> StreamPurposes;
 };
 } // namespace pdb
 } // namespace llvm
index fb52545..bd07049 100644 (file)
@@ -135,29 +135,28 @@ struct BinaryPathProvider {
 struct StreamPurposeProvider {
   explicit StreamPurposeProvider(uint32_t MaxLen) : MaxLen(MaxLen) {}
 
-  DiffResult compare(const std::pair<StreamPurpose, std::string> &L,
-                     const std::pair<StreamPurpose, std::string> &R) {
-    if (L.first != R.first)
+  DiffResult compare(const StreamInfo &L, const StreamInfo &R) {
+    if (L.getPurpose() != R.getPurpose())
       return DiffResult::DIFFERENT;
-    if (L.first == StreamPurpose::ModuleStream) {
+    if (L.getPurpose() == StreamPurpose::ModuleStream) {
       BinaryPathProvider PathProvider(MaxLen);
-      return PathProvider.compare(L.second, R.second);
+      return PathProvider.compare(L.getShortName(), R.getShortName());
     }
-    return (L.second == R.second) ? DiffResult::IDENTICAL
-                                  : DiffResult::DIFFERENT;
+    return (L.getShortName() == R.getShortName()) ? DiffResult::IDENTICAL
+                                                  : DiffResult::DIFFERENT;
   }
 
-  std::string format(const std::pair<StreamPurpose, std::string> &P,
-                     bool Right) {
-    if (P.first == StreamPurpose::Other)
-      return truncateStringBack(P.second, MaxLen);
-    if (P.first == StreamPurpose::NamedStream)
-      return truncateQuotedNameBack("Named Stream", P.second, MaxLen);
+  std::string format(const StreamInfo &P, bool Right) {
+    if (P.getPurpose() == StreamPurpose::Other ||
+        P.getPurpose() == StreamPurpose::Symbols)
+      return truncateStringBack(P.getShortName(), MaxLen);
+    if (P.getPurpose() == StreamPurpose::NamedStream)
+      return truncateQuotedNameBack("Named Stream", P.getShortName(), MaxLen);
 
-    assert(P.first == StreamPurpose::ModuleStream);
+    assert(P.getPurpose() == StreamPurpose::ModuleStream);
     uint32_t ExtraChars = strlen("Module \"\"");
     BinaryPathProvider PathProvider(MaxLen - ExtraChars);
-    std::string Result = PathProvider.format(P.second, Right);
+    std::string Result = PathProvider.format(P.getShortName(), Right);
     return formatv("Module \"{0}\"", Result);
   }
 
@@ -256,8 +255,8 @@ Error DiffStyle::diffStreamDirectory() {
                   truncateStringFront(File1.getFilePath(), 18),
                   truncateStringFront(File2.getFilePath(), 18));
 
-  SmallVector<std::pair<StreamPurpose, std::string>, 32> P;
-  SmallVector<std::pair<StreamPurpose, std::string>, 32> Q;
+  SmallVector<StreamInfo, 32> P;
+  SmallVector<StreamInfo, 32> Q;
   discoverStreamPurposes(File1, P);
   discoverStreamPurposes(File2, Q);
   D.print("Stream Count", File1.getNumStreams(), File2.getNumStreams());
@@ -486,10 +485,10 @@ static void diffOneModule(DiffPrinter &D, const IndexedModuleDescriptor &Item,
                           IndexedModuleDescriptorList &Other,
                           bool ItemIsRight) {
   StreamPurposeProvider HeaderProvider(70);
-  std::pair<StreamPurpose, std::string> Header;
-  Header.first = StreamPurpose::ModuleStream;
-  Header.second = Item.second.getModuleName();
-  D.printFullRow(HeaderProvider.format(Header, ItemIsRight));
+  StreamInfo Info = StreamInfo::createModuleStream(
+      Item.second.getModuleName(), Item.second.getModuleStreamIndex(),
+      Item.first);
+  D.printFullRow(HeaderProvider.format(Info, ItemIsRight));
 
   const auto *L = &Item;
 
index 1e3e8e4..c573f60 100644 (file)
@@ -82,6 +82,12 @@ Error DumpOutputStyle::dump() {
     P.NewLine();
   }
 
+  if (opts::dump::DumpModuleStats.getNumOccurrences() > 0) {
+    if (auto EC = dumpModuleStats())
+      return EC;
+    P.NewLine();
+  }
+
   if (opts::dump::DumpStringTable) {
     if (auto EC = dumpStringTable())
       return EC;
@@ -199,6 +205,77 @@ Error DumpOutputStyle::dumpFileSummary() {
   return Error::success();
 }
 
+static StatCollection getSymbolStats(ModuleDebugStreamRef MDS,
+                                     StatCollection &CumulativeStats) {
+  StatCollection Stats;
+  for (const auto &S : MDS.symbols(nullptr)) {
+    Stats.update(S.kind(), S.length());
+    CumulativeStats.update(S.kind(), S.length());
+  }
+  return Stats;
+}
+
+static StatCollection getChunkStats(ModuleDebugStreamRef MDS,
+                                    StatCollection &CumulativeStats) {
+  StatCollection Stats;
+  for (const auto &Chunk : MDS.subsections()) {
+    Stats.update(uint32_t(Chunk.kind()), Chunk.getRecordLength());
+    CumulativeStats.update(uint32_t(Chunk.kind()), Chunk.getRecordLength());
+  }
+  return Stats;
+}
+
+static inline std::string formatModuleDetailKind(DebugSubsectionKind K) {
+  return formatChunkKind(K, false);
+}
+
+static inline std::string formatModuleDetailKind(SymbolKind K) {
+  return formatSymbolKind(K);
+}
+
+template <typename Kind>
+static void printModuleDetailStats(LinePrinter &P, StringRef Label,
+                                   const StatCollection &Stats) {
+  P.NewLine();
+  P.formatLine("  {0}", Label);
+  AutoIndent Indent(P);
+  P.formatLine("{0,40}: {1,7} entries ({2,8} bytes)", "Total",
+               Stats.Totals.Count, Stats.Totals.Size);
+  P.formatLine("{0}", fmt_repeat('-', 74));
+  for (const auto &K : Stats.Individual) {
+    std::string KindName = formatModuleDetailKind(Kind(K.first));
+    P.formatLine("{0,40}: {1,7} entries ({2,8} bytes)", KindName,
+                 K.second.Count, K.second.Size);
+  }
+}
+
+static bool isMyCode(const DbiModuleDescriptor &Desc) {
+  StringRef Name = Desc.getModuleName();
+  if (Name.startswith("Import:"))
+    return false;
+  if (Name.endswith_lower(".dll"))
+    return false;
+  if (Name.equals_lower("* linker *"))
+    return false;
+  if (Name.startswith_lower("f:\\binaries\\Intermediate\\vctools"))
+    return false;
+  if (Name.startswith_lower("f:\\dd\\vctools\\crt"))
+    return false;
+  return true;
+}
+
+static bool shouldDumpModule(uint32_t Modi, const DbiModuleDescriptor &Desc) {
+  if (opts::dump::JustMyCode && !isMyCode(Desc))
+    return false;
+
+  // If the arg was not specified on the command line, always dump all modules.
+  if (opts::dump::DumpModi.getNumOccurrences() == 0)
+    return true;
+
+  // Otherwise, only dump if this is the same module specified.
+  return (opts::dump::DumpModi == Modi);
+}
+
 Error DumpOutputStyle::dumpStreamSummary() {
   printHeader(P, "Streams");
 
@@ -207,12 +284,16 @@ Error DumpOutputStyle::dumpStreamSummary() {
 
   AutoIndent Indent(P);
   uint32_t StreamCount = File.getNumStreams();
+  uint32_t MaxStreamSize = File.getMaxStreamSize();
 
   for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
     P.formatLine(
-        "Stream {0}: [{1}] ({2} bytes)",
+        "Stream {0} ({1} bytes): [{2}]",
         fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
-        StreamPurposes[StreamIdx], File.getStreamByteSize(StreamIdx));
+        fmt_align(File.getStreamByteSize(StreamIdx), AlignStyle::Right,
+                  NumDigits(MaxStreamSize)),
+        StreamPurposes[StreamIdx].getLongName());
+
     if (opts::dump::DumpStreamBlocks) {
       auto Blocks = File.getStreamBlockList(StreamIdx);
       std::vector<uint32_t> BV(Blocks.begin(), Blocks.end());
@@ -389,8 +470,10 @@ static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
   uint32_t Count = Modules.getModuleCount();
   uint32_t Digits = NumDigits(Count);
   for (uint32_t I = 0; I < Count; ++I) {
-    auto Descriptor = Modules.getModuleDescriptor(I);
-    iterateOneModule(File, P, Descriptor, I, IndentLevel, Digits, Callback);
+    auto Desc = Modules.getModuleDescriptor(I);
+    if (!shouldDumpModule(I, Desc))
+      continue;
+    iterateOneModule(File, P, Desc, I, IndentLevel, Digits, Callback);
   }
 }
 
@@ -438,24 +521,21 @@ Error DumpOutputStyle::dumpModules() {
   auto &Stream = Err(File.getPDBDbiStream());
 
   const DbiModuleList &Modules = Stream.modules();
-  uint32_t Count = Modules.getModuleCount();
-  uint32_t Digits = NumDigits(Count);
-  for (uint32_t I = 0; I < Count; ++I) {
-    auto Modi = Modules.getModuleDescriptor(I);
-    P.formatLine("Mod {0:4} | Name: `{1}`: ",
-                 fmt_align(I, AlignStyle::Right, Digits), Modi.getModuleName());
-    P.formatLine("           Obj: `{0}`: ", Modi.getObjFileName());
-    P.formatLine("           debug stream: {0}, # files: {1}, has ec info: {2}",
-                 Modi.getModuleStreamIndex(), Modi.getNumberOfFiles(),
-                 Modi.hasECInfo());
-    StringRef PdbFilePath =
-        Err(Stream.getECName(Modi.getPdbFilePathNameIndex()));
-    StringRef SrcFilePath =
-        Err(Stream.getECName(Modi.getSourceFileNameIndex()));
-    P.formatLine("           pdb file ni: {0} `{1}`, src file ni: {2} `{3}`",
-                 Modi.getPdbFilePathNameIndex(), PdbFilePath,
-                 Modi.getSourceFileNameIndex(), SrcFilePath);
-  }
+  iterateModules(
+      File, P, 11, [&](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
+        auto Desc = Modules.getModuleDescriptor(Modi);
+        P.formatLine("Obj: `{0}`: ", Desc.getObjFileName());
+        P.formatLine("debug stream: {0}, # files: {1}, has ec info: {2}",
+                     Desc.getModuleStreamIndex(), Desc.getNumberOfFiles(),
+                     Desc.hasECInfo());
+        StringRef PdbFilePath =
+            Err(Stream.getECName(Desc.getPdbFilePathNameIndex()));
+        StringRef SrcFilePath =
+            Err(Stream.getECName(Desc.getSourceFileNameIndex()));
+        P.formatLine("pdb file ni: {0} `{1}`, src file ni: {2} `{3}`",
+                     Desc.getPdbFilePathNameIndex(), PdbFilePath,
+                     Desc.getSourceFileNameIndex(), SrcFilePath);
+      });
   return Error::success();
 }
 
@@ -477,6 +557,56 @@ Error DumpOutputStyle::dumpModuleFiles() {
   return Error::success();
 }
 
+Error DumpOutputStyle::dumpModuleStats() {
+  printHeader(P, "Module Stats");
+
+  ExitOnError Err("Unexpected error processing modules: ");
+
+  StatCollection SymStats;
+  StatCollection ChunkStats;
+  auto &Stream = Err(File.getPDBDbiStream());
+
+  const DbiModuleList &Modules = Stream.modules();
+  uint32_t ModCount = Modules.getModuleCount();
+
+  iterateModules(File, P, 0, [&](uint32_t Modi,
+                                 StringsAndChecksumsPrinter &Strings) {
+    DbiModuleDescriptor Desc = Modules.getModuleDescriptor(Modi);
+    uint32_t StreamIdx = Desc.getModuleStreamIndex();
+
+    if (StreamIdx == kInvalidStreamIndex) {
+      P.formatLine("Mod {0} (debug info not present): [{1}]",
+                   fmt_align(Modi, AlignStyle::Right, NumDigits(ModCount)),
+                   Desc.getModuleName());
+      return;
+    }
+
+    P.formatLine("Stream {0}, {1} bytes", StreamIdx,
+                 File.getStreamByteSize(StreamIdx));
+
+    ModuleDebugStreamRef MDS(Desc, File.createIndexedStream(StreamIdx));
+    if (auto EC = MDS.reload()) {
+      P.printLine("- Error parsing debug info stream");
+      consumeError(std::move(EC));
+      return;
+    }
+
+    printModuleDetailStats<SymbolKind>(P, "Symbols",
+                                       getSymbolStats(MDS, SymStats));
+    printModuleDetailStats<DebugSubsectionKind>(P, "Chunks",
+                                                getChunkStats(MDS, ChunkStats));
+  });
+
+  P.printLine("  Summary |");
+  AutoIndent Indent(P, 4);
+  if (SymStats.Totals.Count > 0) {
+    printModuleDetailStats<SymbolKind>(P, "Symbols", SymStats);
+    printModuleDetailStats<DebugSubsectionKind>(P, "Chunks", ChunkStats);
+  }
+
+  return Error::success();
+}
+
 static void typesetLinesAndColumns(PDBFile &File, LinePrinter &P,
                                    uint32_t Start, const LineColumnEntry &E) {
   const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
index 383388f..497c51f 100644 (file)
@@ -12,7 +12,9 @@
 
 #include "LinePrinter.h"
 #include "OutputStyle.h"
+#include "StreamUtil.h"
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
@@ -29,7 +31,31 @@ class LazyRandomTypeCollection;
 namespace pdb {
 class GSIHashTable;
 
+struct StatCollection {
+  struct Stat {
+    Stat() {}
+    Stat(uint32_t Count, uint32_t Size) : Count(Count), Size(Size) {}
+    uint32_t Count = 0;
+    uint32_t Size = 0;
+
+    void update(uint32_t RecordSize) {
+      ++Count;
+      Size += RecordSize;
+    }
+  };
+
+  void update(uint32_t Kind, uint32_t RecordSize) {
+    Totals.update(RecordSize);
+    auto Iter = Individual.try_emplace(Kind, 1, RecordSize);
+    if (!Iter.second)
+      Iter.first->second.update(RecordSize);
+  }
+  Stat Totals;
+  DenseMap<uint32_t, Stat> Individual;
+};
+
 class DumpOutputStyle : public OutputStyle {
+
 public:
   DumpOutputStyle(PDBFile &File);
 
@@ -40,6 +66,7 @@ private:
 
   Error dumpFileSummary();
   Error dumpStreamSummary();
+  Error dumpModuleStats();
   Error dumpStringTable();
   Error dumpLines();
   Error dumpInlineeLines();
@@ -62,7 +89,7 @@ private:
   LinePrinter P;
   std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
   std::unique_ptr<codeview::LazyRandomTypeCollection> IpiTypes;
-  SmallVector<std::string, 32> StreamPurposes;
+  SmallVector<StreamInfo, 32> StreamPurposes;
 };
 } // namespace pdb
 } // namespace llvm
index 039b1b9..eca0751 100644 (file)
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/BinaryFormat/COFF.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/Support/FormatAdapters.h"
 #include "llvm/Support/FormatVariadic.h"
 
 using namespace llvm;
+using namespace llvm::codeview;
 using namespace llvm::pdb;
 
 std::string llvm::pdb::truncateStringBack(StringRef S, uint32_t MaxLen) {
@@ -97,6 +99,64 @@ std::string llvm::pdb::typesetStringList(uint32_t IndentLevel,
   return Result;
 }
 
+std::string llvm::pdb::formatChunkKind(DebugSubsectionKind Kind,
+                                       bool Friendly) {
+  if (Friendly) {
+    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");
+    }
+  } else {
+    switch (Kind) {
+      RETURN_CASE(DebugSubsectionKind, None, "none");
+      RETURN_CASE(DebugSubsectionKind, Symbols, "DEBUG_S_SYMBOLS");
+      RETURN_CASE(DebugSubsectionKind, Lines, "DEBUG_S_LINES");
+      RETURN_CASE(DebugSubsectionKind, StringTable, "DEBUG_S_STRINGTABLE");
+      RETURN_CASE(DebugSubsectionKind, FileChecksums, "DEBUG_S_FILECHKSMS");
+      RETURN_CASE(DebugSubsectionKind, FrameData, "DEBUG_S_FRAMEDATA");
+      RETURN_CASE(DebugSubsectionKind, InlineeLines, "DEBUG_S_INLINEELINES");
+      RETURN_CASE(DebugSubsectionKind, CrossScopeImports,
+                  "DEBUG_S_CROSSSCOPEIMPORTS");
+      RETURN_CASE(DebugSubsectionKind, CrossScopeExports,
+                  "DEBUG_S_CROSSSCOPEEXPORTS");
+      RETURN_CASE(DebugSubsectionKind, ILLines, "DEBUG_S_IL_LINES");
+      RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap,
+                  "DEBUG_S_FUNC_MDTOKEN_MAP");
+      RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap,
+                  "DEBUG_S_TYPE_MDTOKEN_MAP");
+      RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput,
+                  "DEBUG_S_MERGED_ASSEMBLYINPUT");
+      RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA,
+                  "DEBUG_S_COFF_SYMBOL_RVA");
+    }
+  }
+  return formatUnknownEnum(Kind);
+}
+
+std::string llvm::pdb::formatSymbolKind(SymbolKind K) {
+  switch (uint32_t(K)) {
+#define SYMBOL_RECORD(EnumName, value, name)                                   \
+  case EnumName:                                                               \
+    return #EnumName;
+#define CV_SYMBOL(EnumName, value) SYMBOL_RECORD(EnumName, value, EnumName)
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+  }
+  return formatUnknownEnum(K);
+}
+
 std::string llvm::pdb::formatSegmentOffset(uint16_t Segment, uint32_t Offset) {
   return formatv("{0:4}:{1:4}", Segment, Offset);
 }
index 34fe4ee..7804a1f 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/FormatAdapters.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -64,6 +65,10 @@ std::string typesetItemList(ArrayRef<std::string> Opts, uint32_t IndentLevel,
 std::string typesetStringList(uint32_t IndentLevel,
                               ArrayRef<StringRef> Strings);
 
+std::string formatChunkKind(codeview::DebugSubsectionKind Kind,
+                            bool Friendly = true);
+std::string formatSymbolKind(codeview::SymbolKind K);
+
 /// Returns the number of digits in the given integer.
 inline int NumDigits(uint64_t N) {
   if (N < 10ULL)
index 2413abf..0d7c588 100644 (file)
@@ -24,17 +24,6 @@ using namespace llvm;
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
-static std::string getSymbolKindName(SymbolKind K) {
-  switch (uint32_t(K)) {
-#define SYMBOL_RECORD(EnumName, value, name)                                   \
-  case EnumName:                                                               \
-    return #EnumName;
-#define CV_SYMBOL(EnumName, value) SYMBOL_RECORD(EnumName, value, EnumName)
-#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
-  }
-  return "";
-}
-
 static std::string formatLocalSymFlags(uint32_t IndentLevel,
                                        LocalSymFlags Flags) {
   std::vector<std::string> Opts;
@@ -378,7 +367,7 @@ Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record,
   // append to the existing line.
   P.formatLine("{0} | {1} [size = {2}]",
                fmt_align(Offset, AlignStyle::Right, 6),
-               getSymbolKindName(Record.Type), Record.length());
+               formatSymbolKind(Record.Type), Record.length());
   P.Indent();
   return Error::success();
 }
index 4d35200..991c99a 100644 (file)
 using namespace llvm;
 using namespace llvm::pdb;
 
-void llvm::pdb::discoverStreamPurposes(
-    PDBFile &File,
-    SmallVectorImpl<std::pair<StreamPurpose, std::string>> &Purposes) {
+std::string StreamInfo::getLongName() const {
+  if (Purpose == StreamPurpose::NamedStream)
+    return formatv("Named Stream \"{0}\"", Name).str();
+  if (Purpose == StreamPurpose::ModuleStream)
+    return formatv("Module \"{0}\"", Name).str();
+  return Name;
+}
+
+StreamInfo StreamInfo::createStream(StreamPurpose Purpose, StringRef Name,
+                                    uint32_t StreamIndex) {
+  StreamInfo Result;
+  Result.Name = Name;
+  Result.StreamIndex = StreamIndex;
+  Result.Purpose = Purpose;
+  return Result;
+}
+
+StreamInfo StreamInfo::createModuleStream(StringRef Module,
+                                          uint32_t StreamIndex, uint32_t Modi) {
+  StreamInfo Result;
+  Result.Name = Module;
+  Result.StreamIndex = StreamIndex;
+  Result.ModuleIndex = Modi;
+  Result.Purpose = StreamPurpose::ModuleStream;
+  return Result;
+}
+
+static inline StreamInfo otherStream(StringRef Label, uint32_t Idx) {
+  return StreamInfo::createStream(StreamPurpose::Other, Label, Idx);
+}
+
+static inline StreamInfo namedStream(StringRef Label, uint32_t Idx) {
+  return StreamInfo::createStream(StreamPurpose::NamedStream, Label, Idx);
+}
+
+static inline StreamInfo symbolStream(StringRef Label, uint32_t Idx) {
+  return StreamInfo::createStream(StreamPurpose::Symbols, Label, Idx);
+}
+
+static inline StreamInfo moduleStream(StringRef Label, uint32_t StreamIdx,
+                                      uint32_t Modi) {
+  return StreamInfo::createModuleStream(Label, StreamIdx, Modi);
+}
+
+struct IndexedModuleDescriptor {
+  uint32_t Modi;
+  DbiModuleDescriptor Descriptor;
+};
+
+void llvm::pdb::discoverStreamPurposes(PDBFile &File,
+                                       SmallVectorImpl<StreamInfo> &Streams) {
   // It's OK if we fail to load some of these streams, we still attempt to print
   // what we can.
   auto Dbi = File.getPDBDbiStream();
@@ -33,16 +81,18 @@ void llvm::pdb::discoverStreamPurposes(
   auto Info = File.getPDBInfoStream();
 
   uint32_t StreamCount = File.getNumStreams();
-  DenseMap<uint16_t, DbiModuleDescriptor> ModStreams;
+  DenseMap<uint16_t, IndexedModuleDescriptor> ModStreams;
   DenseMap<uint16_t, std::string> NamedStreams;
 
   if (Dbi) {
     const DbiModuleList &Modules = Dbi->modules();
     for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
-      DbiModuleDescriptor Descriptor = Modules.getModuleDescriptor(I);
-      uint16_t SN = Descriptor.getModuleStreamIndex();
+      IndexedModuleDescriptor IMD;
+      IMD.Modi = I;
+      IMD.Descriptor = Modules.getModuleDescriptor(I);
+      uint16_t SN = IMD.Descriptor.getModuleStreamIndex();
       if (SN != kInvalidStreamIndex)
-        ModStreams[SN] = Descriptor;
+        ModStreams[SN] = IMD;
     }
   }
   if (Info) {
@@ -52,77 +102,76 @@ void llvm::pdb::discoverStreamPurposes(
     }
   }
 
-  Purposes.resize(StreamCount);
+  Streams.resize(StreamCount);
   for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
-    std::pair<StreamPurpose, std::string> Value;
     if (StreamIdx == OldMSFDirectory)
-      Value = std::make_pair(StreamPurpose::Other, "Old MSF Directory");
+      Streams[StreamIdx] = otherStream("Old MSF Directory", StreamIdx);
     else if (StreamIdx == StreamPDB)
-      Value = std::make_pair(StreamPurpose::Other, "PDB Stream");
+      Streams[StreamIdx] = otherStream("PDB Stream", StreamIdx);
     else if (StreamIdx == StreamDBI)
-      Value = std::make_pair(StreamPurpose::Other, "DBI Stream");
+      Streams[StreamIdx] = otherStream("DBI Stream", StreamIdx);
     else if (StreamIdx == StreamTPI)
-      Value = std::make_pair(StreamPurpose::Other, "TPI Stream");
+      Streams[StreamIdx] = otherStream("TPI Stream", StreamIdx);
     else if (StreamIdx == StreamIPI)
-      Value = std::make_pair(StreamPurpose::Other, "IPI Stream");
+      Streams[StreamIdx] = otherStream("IPI Stream", StreamIdx);
     else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
-      Value = std::make_pair(StreamPurpose::Other, "Global Symbol Hash");
+      Streams[StreamIdx] = otherStream("Global Symbol Hash", StreamIdx);
     else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
-      Value = std::make_pair(StreamPurpose::Other, "Public Symbol Hash");
+      Streams[StreamIdx] = otherStream("Public Symbol Hash", StreamIdx);
     else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
-      Value = std::make_pair(StreamPurpose::Other, "Public Symbol Records");
+      Streams[StreamIdx] = symbolStream("Symbol Records", StreamIdx);
     else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
-      Value = std::make_pair(StreamPurpose::Other, "TPI Hash");
+      Streams[StreamIdx] = otherStream("TPI Hash", StreamIdx);
     else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
-      Value = std::make_pair(StreamPurpose::Other, "TPI Aux Hash");
+      Streams[StreamIdx] = otherStream("TPI Aux Hash", StreamIdx);
     else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
-      Value = std::make_pair(StreamPurpose::Other, "IPI Hash");
+      Streams[StreamIdx] = otherStream("IPI Hash", StreamIdx);
     else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
-      Value = std::make_pair(StreamPurpose::Other, "IPI Aux Hash");
+      Streams[StreamIdx] = otherStream("IPI Aux Hash", StreamIdx);
     else if (Dbi &&
              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
-      Value = std::make_pair(StreamPurpose::Other, "Exception Data");
+      Streams[StreamIdx] = otherStream("Exception Data", StreamIdx);
     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
-      Value = std::make_pair(StreamPurpose::Other, "Fixup Data");
+      Streams[StreamIdx] = otherStream("Fixup Data", StreamIdx);
     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
-      Value = std::make_pair(StreamPurpose::Other, "FPO Data");
+      Streams[StreamIdx] = otherStream("FPO Data", StreamIdx);
     else if (Dbi &&
              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
-      Value = std::make_pair(StreamPurpose::Other, "New FPO Data");
+      Streams[StreamIdx] = otherStream("New FPO Data", StreamIdx);
     else if (Dbi &&
              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
-      Value = std::make_pair(StreamPurpose::Other, "Omap From Source Data");
+      Streams[StreamIdx] = otherStream("Omap From Source Data", StreamIdx);
     else if (Dbi &&
              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
-      Value = std::make_pair(StreamPurpose::Other, "Omap To Source Data");
+      Streams[StreamIdx] = otherStream("Omap To Source Data", StreamIdx);
     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
-      Value = std::make_pair(StreamPurpose::Other, "Pdata");
+      Streams[StreamIdx] = otherStream("Pdata", StreamIdx);
     else if (Dbi &&
              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
-      Value = std::make_pair(StreamPurpose::Other, "Section Header Data");
+      Streams[StreamIdx] = otherStream("Section Header Data", StreamIdx);
     else if (Dbi &&
              StreamIdx ==
                  Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
-      Value =
-          std::make_pair(StreamPurpose::Other, "Section Header Original Data");
+      Streams[StreamIdx] =
+          otherStream("Section Header Original Data", StreamIdx);
     else if (Dbi &&
              StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
-      Value = std::make_pair(StreamPurpose::Other, "Token Rid Data");
+      Streams[StreamIdx] = otherStream("Token Rid Data", StreamIdx);
     else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
-      Value = std::make_pair(StreamPurpose::Other, "Xdata");
+      Streams[StreamIdx] = otherStream("Xdata", StreamIdx);
     else {
       auto ModIter = ModStreams.find(StreamIdx);
       auto NSIter = NamedStreams.find(StreamIdx);
       if (ModIter != ModStreams.end()) {
-        Value = std::make_pair(StreamPurpose::ModuleStream,
-                               ModIter->second.getModuleName());
+        Streams[StreamIdx] =
+            moduleStream(ModIter->second.Descriptor.getModuleName(), StreamIdx,
+                         ModIter->second.Modi);
       } else if (NSIter != NamedStreams.end()) {
-        Value = std::make_pair(StreamPurpose::NamedStream, NSIter->second);
+        Streams[StreamIdx] = namedStream(NSIter->second, StreamIdx);
       } else {
-        Value = std::make_pair(StreamPurpose::Other, "???");
+        Streams[StreamIdx] = otherStream("???", StreamIdx);
       }
     }
-    Purposes[StreamIdx] = Value;
   }
 
   // Consume errors from missing streams.
@@ -135,18 +184,3 @@ void llvm::pdb::discoverStreamPurposes(
   if (!Info)
     consumeError(Info.takeError());
 }
-
-void llvm::pdb::discoverStreamPurposes(PDBFile &File,
-                                       SmallVectorImpl<std::string> &Purposes) {
-  SmallVector<std::pair<StreamPurpose, std::string>, 24> SP;
-  discoverStreamPurposes(File, SP);
-  Purposes.reserve(SP.size());
-  for (const auto &P : SP) {
-    if (P.first == StreamPurpose::NamedStream)
-      Purposes.push_back(formatv("Named Stream \"{0}\"", P.second));
-    else if (P.first == StreamPurpose::ModuleStream)
-      Purposes.push_back(formatv("Module \"{0}\"", P.second));
-    else
-      Purposes.push_back(P.second);
-  }
-}
index f49c0a0..443267c 100644 (file)
 #ifndef LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
 #define LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
 
+#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 
 #include <string>
 
 namespace llvm {
 namespace pdb {
 class PDBFile;
-enum class StreamPurpose { NamedStream, ModuleStream, Other };
+enum class StreamPurpose { NamedStream, ModuleStream, Symbols, Other };
+
+struct StreamInfo {
+public:
+  StreamInfo() {}
+
+  uint32_t getModuleIndex() const { return *ModuleIndex; }
+  StreamPurpose getPurpose() const { return Purpose; }
+  StringRef getShortName() const { return Name; }
+  uint32_t getStreamIndex() const { return StreamIndex; }
+  std::string getLongName() const;
+
+  static StreamInfo createStream(StreamPurpose Purpose, StringRef Name,
+                                 uint32_t StreamIndex);
+  static StreamInfo createModuleStream(StringRef Module, uint32_t StreamIndex,
+                                       uint32_t Modi);
+
+private:
+  StreamPurpose Purpose;
+  uint32_t StreamIndex;
+  std::string Name;
+  Optional<uint32_t> ModuleIndex;
+};
 
 void discoverStreamPurposes(PDBFile &File,
-                            SmallVectorImpl<std::string> &Purposes);
-void discoverStreamPurposes(
-    PDBFile &File,
-    SmallVectorImpl<std::pair<StreamPurpose, std::string>> &Purposes);
+                            SmallVectorImpl<StreamInfo> &Streams);
 }
 }
 
index 75560b3..045eb71 100644 (file)
@@ -29,6 +29,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/config.h"
@@ -70,6 +71,7 @@
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/LineIterator.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
@@ -80,6 +82,8 @@
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
 
+#include <set>
+
 using namespace llvm;
 using namespace llvm::codeview;
 using namespace llvm::msf;
@@ -418,6 +422,10 @@ cl::opt<bool> DumpStreamBlocks(
     "stream-blocks",
     cl::desc("Add block information to the output of -streams"),
     cl::cat(MsfOptions), cl::sub(DumpSubcommand));
+cl::opt<bool>
+    DumpModuleStats("mod-stats",
+                    cl::desc("Dump a detailed size breakdown for each module"),
+                    cl::cat(MsfOptions), cl::sub(DumpSubcommand));
 
 // TYPE OPTIONS
 cl::opt<bool> DumpTypes("types",
@@ -507,6 +515,10 @@ cl::opt<uint32_t> DumpModi("modi", cl::Optional,
                            cl::desc("For all options that iterate over "
                                     "modules, limit to the specified module"),
                            cl::cat(FileOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> JustMyCode("jmc", cl::Optional,
+                         cl::desc("For all options that iterate over modules, "
+                                  "ignore modules from system libraries"),
+                         cl::cat(FileOptions), cl::sub(DumpSubcommand));
 
 // MISCELLANEOUS OPTIONS
 cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
index 621c9fa..901d2a8 100644 (file)
@@ -127,6 +127,7 @@ namespace dump {
 extern llvm::cl::opt<bool> DumpSummary;
 extern llvm::cl::opt<bool> DumpFpm;
 extern llvm::cl::opt<bool> DumpStreams;
+extern llvm::cl::opt<bool> DumpModuleStats;
 extern llvm::cl::opt<bool> DumpStreamBlocks;
 
 extern llvm::cl::opt<bool> DumpLines;
@@ -146,6 +147,7 @@ extern llvm::cl::opt<bool> DumpIdData;
 extern llvm::cl::opt<bool> DumpIdExtras;
 extern llvm::cl::list<uint32_t> DumpIdIndex;
 extern llvm::cl::opt<uint32_t> DumpModi;
+extern llvm::cl::opt<bool> JustMyCode;
 extern llvm::cl::opt<bool> DumpSymbols;
 extern llvm::cl::opt<bool> DumpSymRecordBytes;
 extern llvm::cl::opt<bool> DumpGlobals;