[llvm] r305106 - Rename llvm-pdbdump -> llvm-pdbutil.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 9 13:46:19 PDT 2017


Author: zturner
Date: Fri Jun  9 15:46:17 2017
New Revision: 305106

URL: http://llvm.org/viewvc/llvm-project?rev=305106&view=rev
Log:
Rename llvm-pdbdump -> llvm-pdbutil.

This is to reflect the evolving nature of the tool as being
useful for more than just dumping PDBs, as it can do many other
things.

Differential Revision: https://reviews.llvm.org/D34062

Added:
    llvm/trunk/tools/llvm-pdbutil/
    llvm/trunk/tools/llvm-pdbutil/Analyze.cpp
    llvm/trunk/tools/llvm-pdbutil/Analyze.h
    llvm/trunk/tools/llvm-pdbutil/CMakeLists.txt
    llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp
    llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.h
    llvm/trunk/tools/llvm-pdbutil/Diff.cpp
    llvm/trunk/tools/llvm-pdbutil/Diff.h
    llvm/trunk/tools/llvm-pdbutil/LLVMBuild.txt
    llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.h
    llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp
    llvm/trunk/tools/llvm-pdbutil/LinePrinter.h
    llvm/trunk/tools/llvm-pdbutil/OutputStyle.h
    llvm/trunk/tools/llvm-pdbutil/PdbYaml.cpp
    llvm/trunk/tools/llvm-pdbutil/PdbYaml.h
    llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.h
    llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.cpp
    llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.h
    llvm/trunk/tools/llvm-pdbutil/StreamUtil.cpp
    llvm/trunk/tools/llvm-pdbutil/StreamUtil.h
    llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.h
    llvm/trunk/tools/llvm-pdbutil/fuzzer/
    llvm/trunk/tools/llvm-pdbutil/fuzzer/CMakeLists.txt
    llvm/trunk/tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
Removed:
    llvm/trunk/tools/llvm-pdbdump/
Modified:
    llvm/trunk/docs/ReleaseNotes.rst
    llvm/trunk/test/CMakeLists.txt
    llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-flags.test
    llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-linenumbers.test
    llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
    llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-compilands.test
    llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-summary.test
    llvm/trunk/test/DebugInfo/PDB/pdb-longname-truncation.test
    llvm/trunk/test/DebugInfo/PDB/pdb-minimal-construct.test
    llvm/trunk/test/DebugInfo/PDB/pdb-yaml-symbols.test
    llvm/trunk/test/DebugInfo/PDB/pdb-yaml-types.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-mergeids.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-mergetypes.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-blocks.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-source-names.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-types.test
    llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test
    llvm/trunk/test/tools/llvm-pdbdump/class-layout.test
    llvm/trunk/test/tools/llvm-pdbdump/complex-padding-graphical.test
    llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test
    llvm/trunk/test/tools/llvm-pdbdump/load-address.test
    llvm/trunk/test/tools/llvm-pdbdump/raw-stream-data.test
    llvm/trunk/test/tools/llvm-pdbdump/regex-filter.test
    llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test
    llvm/trunk/test/tools/llvm-pdbdump/symbol-filters.test
    llvm/trunk/tools/LLVMBuild.txt

Modified: llvm/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ReleaseNotes.rst?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/docs/ReleaseNotes.rst (original)
+++ llvm/trunk/docs/ReleaseNotes.rst Fri Jun  9 15:46:17 2017
@@ -50,6 +50,10 @@ Non-comprehensive list of changes in thi
   structure and type definitions for DWARF, ELF, COFF, WASM, and MachO file
   formats.
   
+* The tool ``llvm-pdbdump`` has been renamed ``llvm-pdbutil`` to better reflect
+  its nature as a general purpose PDB manipulation / diagnostics tool that does
+  more than just dumping contents.
+  
 
 * ... next change ...
 

Modified: llvm/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CMakeLists.txt?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/CMakeLists.txt (original)
+++ llvm/trunk/test/CMakeLists.txt Fri Jun  9 15:46:17 2017
@@ -61,7 +61,7 @@ set(LLVM_TEST_DEPENDS
           llvm-nm
           llvm-objdump
           llvm-opt-report
-          llvm-pdbdump
+          llvm-pdbutil
           llvm-profdata
           llvm-ranlib
           llvm-readobj

Modified: llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-flags.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-flags.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-flags.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-flags.test Fri Jun  9 15:46:17 2017
@@ -1,7 +1,7 @@
-; RUN: llvm-pdbdump pretty %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=NO_ARGS
-; RUN: llvm-pdbdump pretty -types %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=TYPES
-; RUN: llvm-pdbdump pretty -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=COMPILANDS
-; RUN: llvm-pdbdump pretty -types -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=MULTIPLE
+; RUN: llvm-pdbutil pretty %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=NO_ARGS
+; RUN: llvm-pdbutil pretty -types %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=TYPES
+; RUN: llvm-pdbutil pretty -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=COMPILANDS
+; RUN: llvm-pdbutil pretty -types -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=MULTIPLE
 
 ; Check that neither symbols nor compilands are dumped when neither argument specified.
 ; NO_ARGS: empty.pdb

Modified: llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-linenumbers.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-linenumbers.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-linenumbers.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-linenumbers.test Fri Jun  9 15:46:17 2017
@@ -1,5 +1,5 @@
-; RUN: llvm-pdbdump pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS_FPO %s
-; RUN: llvm-pdbdump pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS %s
+; RUN: llvm-pdbutil pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS_FPO %s
+; RUN: llvm-pdbutil pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS %s
 
 ; LINE_NUMS_FPO: llvm\test\debuginfo\pdb\inputs\symbolformat-fpo.cpp
 ; LINE_NUMS_FPO: Line 5, Address: [0x000011a0 - 0x000011a5] (6 bytes)

Modified: llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test Fri Jun  9 15:46:17 2017
@@ -1,11 +1,11 @@
-; RUN: llvm-pdbdump pretty -module-syms %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT_FPO %s
-; RUN: llvm-pdbdump pretty -module-syms %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT %s
-; RUN: llvm-pdbdump pretty -types %p/../Inputs/symbolformat.pdb > %t.types
+; RUN: llvm-pdbutil pretty -module-syms %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT_FPO %s
+; RUN: llvm-pdbutil pretty -module-syms %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT %s
+; RUN: llvm-pdbutil pretty -types %p/../Inputs/symbolformat.pdb > %t.types
 ; RUN: FileCheck --check-prefix=TYPES_FORMAT %s < %t.types
 ; RUN: FileCheck --check-prefix=TYPES_1 %s < %t.types
 ; RUN: FileCheck --check-prefix=TYPES_2 %s < %t.types
-; RUN: llvm-pdbdump pretty -types %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=TYPES_FORMAT %s
-; RUN: llvm-pdbdump pretty -globals %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=GLOBALS %s
+; RUN: llvm-pdbutil pretty -types %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=TYPES_FORMAT %s
+; RUN: llvm-pdbutil pretty -globals %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=GLOBALS %s
 
 ; The format is func [0x<rva_start>+<prologue_length> - 0x<rva_end>-<epilogue_length>]
 ; SYM_FORMAT_FPO: ---SYMBOLS---

Modified: llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-compilands.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-compilands.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-compilands.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-compilands.test Fri Jun  9 15:46:17 2017
@@ -1,7 +1,7 @@
 ; Test that the native PDB reader can enumerate the compilands.
-; RUN: llvm-pdbdump pretty -native -compilands %p/../Inputs/empty.pdb \
+; RUN: llvm-pdbutil pretty -native -compilands %p/../Inputs/empty.pdb \
 ; RUN:   | FileCheck -check-prefix=EMPTY %s
-; RUN: llvm-pdbdump pretty -native -compilands %p/../Inputs/big-read.pdb \
+; RUN: llvm-pdbutil pretty -native -compilands %p/../Inputs/big-read.pdb \
 ; RUN:   | FileCheck -check-prefix=BIGREAD %s
 
 ; Reference output was generated with the DIA reader to ensure that the

Modified: llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-summary.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-summary.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-summary.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/Native/pdb-native-summary.test Fri Jun  9 15:46:17 2017
@@ -1,5 +1,5 @@
 ; Test that the native PDB reader gets the PDB summary correct.
-; RUN: llvm-pdbdump pretty -native -color-output=false %p/../Inputs/empty.pdb \
+; RUN: llvm-pdbutil pretty -native -color-output=false %p/../Inputs/empty.pdb \
 ; RUN:   | FileCheck -check-prefix=EMPTY %s
 
 ; Reference output was generated with the DIA reader to ensure that the

Modified: llvm/trunk/test/DebugInfo/PDB/pdb-longname-truncation.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdb-longname-truncation.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdb-longname-truncation.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdb-longname-truncation.test Fri Jun  9 15:46:17 2017
@@ -1,3 +1,3 @@
 ; For now just verify that this doesn't cause an error.  Later we pdbdump can
 ; do type lookup, we can verify that the name matches what we expect.
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/longname-truncation.yaml
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/longname-truncation.yaml

Modified: llvm/trunk/test/DebugInfo/PDB/pdb-minimal-construct.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdb-minimal-construct.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdb-minimal-construct.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdb-minimal-construct.test Fri Jun  9 15:46:17 2017
@@ -6,6 +6,6 @@
 ; resulting PDB to go back to yaml, and verify that the resulting yaml
 ; is identical.
 
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/one-symbol.yaml
-; RUN: llvm-pdbdump pdb2yaml -minimal -module-syms -no-file-headers %t.pdb > %t.pdb.yaml
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/one-symbol.yaml
+; RUN: llvm-pdbutil pdb2yaml -minimal -module-syms -no-file-headers %t.pdb > %t.pdb.yaml
 ; RUN: diff -b %p/Inputs/one-symbol.yaml %t.pdb.yaml

Modified: llvm/trunk/test/DebugInfo/PDB/pdb-yaml-symbols.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdb-yaml-symbols.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdb-yaml-symbols.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdb-yaml-symbols.test Fri Jun  9 15:46:17 2017
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump pdb2yaml -module-syms %p/Inputs/empty.pdb \
+; RUN: llvm-pdbutil pdb2yaml -module-syms %p/Inputs/empty.pdb \
 ; RUN:   | FileCheck -check-prefix=YAML %s
 
 

Modified: llvm/trunk/test/DebugInfo/PDB/pdb-yaml-types.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdb-yaml-types.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdb-yaml-types.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdb-yaml-types.test Fri Jun  9 15:46:17 2017
@@ -1,7 +1,7 @@
-RUN: llvm-pdbdump pdb2yaml -tpi-stream %p/Inputs/big-read.pdb > %t.yaml
+RUN: llvm-pdbutil pdb2yaml -tpi-stream %p/Inputs/big-read.pdb > %t.yaml
 RUN: FileCheck -check-prefix=YAML %s < %t.yaml
-RUN: llvm-pdbdump yaml2pdb %t.yaml -pdb %t.pdb
-RUN: llvm-pdbdump raw -tpi-records %t.pdb | FileCheck %s --check-prefix=PDB
+RUN: llvm-pdbutil yaml2pdb %t.yaml -pdb %t.pdb
+RUN: llvm-pdbutil raw -tpi-records %t.pdb | FileCheck %s --check-prefix=PDB
 
 Only verify the beginning of the type stream.
 

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-debug-subsections.test Fri Jun  9 15:46:17 2017
@@ -1,6 +1,6 @@
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml
-; RUN: llvm-pdbdump pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s
-; RUN: llvm-pdbdump raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml
+; RUN: llvm-pdbutil pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s
+; RUN: llvm-pdbutil raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s
 
 YAML:      Modules:
 YAML-NEXT:   - Module:          Foo.obj

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test Fri Jun  9 15:46:17 2017
@@ -1,12 +1,12 @@
-; RUN: llvm-pdbdump raw -headers -string-table -tpi-records -tpi-record-bytes -module-syms \
+; RUN: llvm-pdbutil raw -headers -string-table -tpi-records -tpi-record-bytes -module-syms \
 ; RUN:              -sym-record-bytes -globals -publics -module-files \
 ; RUN:              -stream-summary -stream-blocks -ipi-records -ipi-record-bytes \
 ; RUN:              -section-contribs -section-map -section-headers -subsections=all \
 ; RUN:              -tpi-hash -fpo -page-stats %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
-; RUN: llvm-pdbdump raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
-; RUN: llvm-pdbdump raw -headers -modules -module-files \
+; RUN: llvm-pdbutil raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
+; RUN: llvm-pdbutil raw -headers -modules -module-files \
 ; RUN:              %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
-; RUN: not llvm-pdbdump raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
+; RUN: not llvm-pdbutil raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
 
 ; EMPTY:      FileHeaders {
 ; EMPTY-NEXT:   BlockSize: 4096

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test Fri Jun  9 15:46:17 2017
@@ -1,12 +1,12 @@
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-and-types-1.yaml
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-and-types-2.yaml
-; RUN: llvm-pdbdump merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
-; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-TYPES %s
-; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=INTMAIN %s
-; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=VOIDMAIN %s
-; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-TYPES %s
-; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-NAMES %s
-; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-UDT %s
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-and-types-1.yaml
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-and-types-2.yaml
+; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
+; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-TYPES %s
+; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=INTMAIN %s
+; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=VOIDMAIN %s
+; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-TYPES %s
+; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-NAMES %s
+; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-UDT %s
 
 TPI-TYPES:     Type Info Stream (TPI)
 TPI-TYPES:     Record count: 9

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-mergeids.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-mergeids.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-mergeids.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-mergeids.test Fri Jun  9 15:46:17 2017
@@ -1,9 +1,9 @@
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-1.yaml
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-2.yaml
-; RUN: llvm-pdbdump merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
-; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
-; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=SUBSTRS %s
-; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-EMPTY %s
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-1.yaml
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-2.yaml
+; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
+; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
+; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=SUBSTRS %s
+; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-EMPTY %s
 
 
 MERGED: Type Info Stream (IPI)

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-mergetypes.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-mergetypes.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-mergetypes.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-mergetypes.test Fri Jun  9 15:46:17 2017
@@ -1,8 +1,8 @@
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-types-1.yaml
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-types-2.yaml
-; RUN: llvm-pdbdump merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
-; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
-; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=ARGLIST %s
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-types-1.yaml
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-types-2.yaml
+; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
+; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
+; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=ARGLIST %s
 
 
 MERGED: Type Info Stream (TPI)

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-blocks.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-blocks.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-blocks.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-blocks.test Fri Jun  9 15:46:17 2017
@@ -1,8 +1,8 @@
-; RUN: llvm-pdbdump raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
-; RUN: llvm-pdbdump raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
-; RUN: not llvm-pdbdump raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
-; RUN: not llvm-pdbdump raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
-; RUN: not llvm-pdbdump raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
+; RUN: llvm-pdbutil raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
+; RUN: llvm-pdbutil raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
+; RUN: not llvm-pdbutil raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
+; RUN: not llvm-pdbutil raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
+; RUN: not llvm-pdbutil raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
 
 BLOCK0:      Block Data {
 BLOCK0-NEXT:   Block 0 (

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-raw-stream.test Fri Jun  9 15:46:17 2017
@@ -1,5 +1,5 @@
-; RUN: llvm-pdbdump raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM1 %s
-; RUN: not llvm-pdbdump raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s
+; RUN: llvm-pdbutil raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM1 %s
+; RUN: not llvm-pdbutil raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s
 
 STREAM1:      Stream Data {
 STREAM1-NEXT:   Stream {

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-readwrite.test Fri Jun  9 15:46:17 2017
@@ -1,10 +1,10 @@
-RUN: llvm-pdbdump pdb2yaml -modules -module-files -dbi-stream \
+RUN: llvm-pdbutil pdb2yaml -modules -module-files -dbi-stream \
 RUN:   -pdb-stream -string-table -tpi-stream -stream-directory \
 RUN:   -stream-metadata %p/Inputs/empty.pdb > %t.1
-RUN: llvm-pdbdump yaml2pdb -pdb=%t.2 %t.1
+RUN: llvm-pdbutil yaml2pdb -pdb=%t.2 %t.1
 
-RUN: llvm-pdbdump raw -headers -string-table -tpi-records %p/Inputs/empty.pdb | FileCheck %s
-RUN: llvm-pdbdump raw -headers -string-table -tpi-records %t.2 | FileCheck %s
+RUN: llvm-pdbutil raw -headers -string-table -tpi-records %p/Inputs/empty.pdb | FileCheck %s
+RUN: llvm-pdbutil raw -headers -string-table -tpi-records %t.2 | FileCheck %s
 
 CHECK:      FileHeaders {
 CHECK-NEXT:   BlockSize: 4096

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-source-names.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-source-names.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-source-names.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-source-names.test Fri Jun  9 15:46:17 2017
@@ -6,11 +6,11 @@
 # that differ by one byte, so that at least one of those will only
 # pass if alignment is implemented correctly.
 
-RUN: llvm-pdbdump yaml2pdb -pdb=%T/source-names-1.pdb %p/Inputs/source-names-1.yaml
-RUN: llvm-pdbdump pdb2yaml -module-files %T/source-names-1.pdb \
+RUN: llvm-pdbutil yaml2pdb -pdb=%T/source-names-1.pdb %p/Inputs/source-names-1.yaml
+RUN: llvm-pdbutil pdb2yaml -module-files %T/source-names-1.pdb \
 RUN:     | FileCheck -check-prefix=CHECK1 %s
-RUN: llvm-pdbdump yaml2pdb -pdb=%T/source-names-2.pdb %p/Inputs/source-names-2.yaml
-RUN: llvm-pdbdump pdb2yaml -module-files %T/source-names-2.pdb \
+RUN: llvm-pdbutil yaml2pdb -pdb=%T/source-names-2.pdb %p/Inputs/source-names-2.yaml
+RUN: llvm-pdbutil pdb2yaml -module-files %T/source-names-2.pdb \
 RUN:     | FileCheck -check-prefix=CHECK2 %s
 
 CHECK1: SourceFiles:

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-write.test Fri Jun  9 15:46:17 2017
@@ -10,11 +10,11 @@
 ; stream metadata, since the layout of the MSF file might be different
 ; (for example if we don't write the entire stream)
 ;
-; RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory \
+; RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory \
 ; RUN:   -pdb-stream -tpi-stream -module-syms %p/Inputs/empty.pdb > %t.1
-; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2 %t.1
-; RUN: llvm-pdbdump pdb2yaml -pdb-stream -tpi-stream \
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2 %t.1
+; RUN: llvm-pdbutil pdb2yaml -pdb-stream -tpi-stream \
 ; RUN:   -module-syms -no-file-headers %p/Inputs/empty.pdb > %t.3
-; RUN: llvm-pdbdump pdb2yaml -pdb-stream -tpi-stream \
+; RUN: llvm-pdbutil pdb2yaml -pdb-stream -tpi-stream \
 ; RUN:   -module-syms -no-file-headers %t.2 > %t.4
 ; RUN: diff %t.3 %t.4

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-types.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-types.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-types.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml-types.test Fri Jun  9 15:46:17 2017
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump pdb2yaml -tpi-stream %p/Inputs/empty.pdb \
+; RUN: llvm-pdbutil pdb2yaml -tpi-stream %p/Inputs/empty.pdb \
 ; RUN:   | FileCheck -check-prefix=YAML %s
 
 YAML: ---

Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test (original)
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-yaml.test Fri Jun  9 15:46:17 2017
@@ -1,6 +1,6 @@
-; RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory -string-table -pdb-stream \
+; RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -string-table -pdb-stream \
 ; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=YAML %s
-; RUN: llvm-pdbdump pdb2yaml -no-file-headers -stream-metadata -stream-directory -pdb-stream \
+; RUN: llvm-pdbutil pdb2yaml -no-file-headers -stream-metadata -stream-directory -pdb-stream \
 ; RUN:   %p/Inputs/empty.pdb | FileCheck -check-prefix=NO-HEADERS %s
 
 ; YAML:      ---

Modified: llvm/trunk/test/tools/llvm-pdbdump/class-layout.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/class-layout.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/class-layout.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/class-layout.test Fri Jun  9 15:46:17 2017
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump pretty -all -class-recurse-depth=1 \
+; RUN: llvm-pdbutil pretty -all -class-recurse-depth=1 \
 ; RUN:   %p/Inputs/ClassLayoutTest.pdb > %t
 ; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBALS_TEST
 ; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBERS_TEST

Modified: llvm/trunk/test/tools/llvm-pdbdump/complex-padding-graphical.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/complex-padding-graphical.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/complex-padding-graphical.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/complex-padding-graphical.test Fri Jun  9 15:46:17 2017
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump pretty -classes -class-definitions=layout \
+; RUN: llvm-pdbutil pretty -classes -class-definitions=layout \
 ; RUN:     -include-types=Test %p/Inputs/ComplexPaddingTest.pdb > %t
 
 ; RUN: FileCheck -input-file=%t %s -check-prefix=DIRECT_VB_ONLY

Modified: llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/enum-layout.test Fri Jun  9 15:46:17 2017
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump pretty -types %p/Inputs/ClassLayoutTest.pdb > %t
+; RUN: llvm-pdbutil pretty -types %p/Inputs/ClassLayoutTest.pdb > %t
 ; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBAL_ENUM
 ; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBER_ENUM
 

Modified: llvm/trunk/test/tools/llvm-pdbdump/load-address.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/load-address.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/load-address.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/load-address.test Fri Jun  9 15:46:17 2017
@@ -1,6 +1,6 @@
-; RUN: llvm-pdbdump pretty -externals %p/Inputs/LoadAddressTest.pdb \
+; RUN: llvm-pdbutil pretty -externals %p/Inputs/LoadAddressTest.pdb \
 ; RUN:    | FileCheck --check-prefix=RVA %s
-; RUN: llvm-pdbdump pretty -externals -load-address=0x40000000 \
+; RUN: llvm-pdbutil pretty -externals -load-address=0x40000000 \
 ; RUN: %p/Inputs/LoadAddressTest.pdb | FileCheck --check-prefix=VA %s
 
 ; RVA: ---EXTERNALS---

Modified: llvm/trunk/test/tools/llvm-pdbdump/raw-stream-data.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/raw-stream-data.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/raw-stream-data.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/raw-stream-data.test Fri Jun  9 15:46:17 2017
@@ -1,8 +1,8 @@
-; RUN: llvm-pdbdump raw -stream-data=8 %p/Inputs/LoadAddressTest.pdb \
+; RUN: llvm-pdbutil raw -stream-data=8 %p/Inputs/LoadAddressTest.pdb \
 ; RUN:   | FileCheck %s -check-prefix=FULL_STREAM
-; RUN: llvm-pdbdump raw -stream-data=8:4 %p/Inputs/LoadAddressTest.pdb \
+; RUN: llvm-pdbutil raw -stream-data=8:4 %p/Inputs/LoadAddressTest.pdb \
 ; RUN:   | FileCheck %s -check-prefix=OFFSET_STREAM
-; RUN: llvm-pdbdump raw -stream-data=8:4 at 24 %p/Inputs/LoadAddressTest.pdb \
+; RUN: llvm-pdbutil raw -stream-data=8:4 at 24 %p/Inputs/LoadAddressTest.pdb \
 ; RUN:   | FileCheck %s -check-prefix=OFFSET_AND_LENGTH
 
 FULL_STREAM:      Stream Data {

Modified: llvm/trunk/test/tools/llvm-pdbdump/regex-filter.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/regex-filter.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/regex-filter.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/regex-filter.test Fri Jun  9 15:46:17 2017
@@ -1,25 +1,25 @@
-; RUN: llvm-pdbdump pretty -module-syms -globals -types %p/Inputs/FilterTest.pdb \
+; RUN: llvm-pdbutil pretty -module-syms -globals -types %p/Inputs/FilterTest.pdb \
 ; RUN:    | FileCheck --check-prefix=NO_FILTER %s
 
-; RUN: llvm-pdbdump pretty -types -exclude-types="GlobalTypedef|NestedTypedef" \
+; RUN: llvm-pdbutil pretty -types -exclude-types="GlobalTypedef|NestedTypedef" \
 ; RUN:    %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_TYPEDEFS %s
-; RUN: llvm-pdbdump pretty -classes -enums %p/Inputs/FilterTest.pdb \
+; RUN: llvm-pdbutil pretty -classes -enums %p/Inputs/FilterTest.pdb \
 ; RUN:    | FileCheck --check-prefix=EXCLUDE_TYPEDEFS %s
 
-; RUN: llvm-pdbdump pretty -types -exclude-types="GlobalEnum|NestedEnum" \
+; RUN: llvm-pdbutil pretty -types -exclude-types="GlobalEnum|NestedEnum" \
 ; RUN:    %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_ENUMS %s
-; RUN: llvm-pdbdump pretty -classes -typedefs %p/Inputs/FilterTest.pdb \
+; RUN: llvm-pdbutil pretty -classes -typedefs %p/Inputs/FilterTest.pdb \
 ; RUN:    | FileCheck --check-prefix=EXCLUDE_ENUMS %s
 
-; RUN: llvm-pdbdump pretty -types -module-syms -globals -exclude-symbols="MemberVar|GlobalVar" \
+; RUN: llvm-pdbutil pretty -types -module-syms -globals -exclude-symbols="MemberVar|GlobalVar" \
 ; RUN:    %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_VARS %s
-; RUN: llvm-pdbdump pretty -types -exclude-types="FilterTestClass" \
+; RUN: llvm-pdbutil pretty -types -exclude-types="FilterTestClass" \
 ; RUN:    %p/Inputs/FilterTest.pdb | FileCheck  --check-prefix=EXCLUDE_WHOLE_CLASS %s
-; RUN: llvm-pdbdump pretty -module-syms -globals -exclude-compilands="FilterTest.obj"  \
+; RUN: llvm-pdbutil pretty -module-syms -globals -exclude-compilands="FilterTest.obj"  \
 ; RUN:    %p/Inputs/FilterTest.pdb | FileCheck  --check-prefix=EXCLUDE_COMPILAND %s
-; RUN: llvm-pdbdump pretty -types -include-types="FilterTestClass" \
+; RUN: llvm-pdbutil pretty -types -include-types="FilterTestClass" \
 ; RUN:    %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=INCLUDE_ONLY_TYPES %s
-; RUN: llvm-pdbdump pretty -types -module-syms -globals -include-symbols="[[:<:]](IntGlobalVar|DoubleGlobalVar)[[:>:]]" \
+; RUN: llvm-pdbutil pretty -types -module-syms -globals -include-symbols="[[:<:]](IntGlobalVar|DoubleGlobalVar)[[:>:]]" \
 ; RUN:    %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=INCLUDE_ONLY_VARS %s
 
 ; NO_FILTER: ---TYPES---

Modified: llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/simple-padding-graphical.test Fri Jun  9 15:46:17 2017
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump pretty -classes -class-definitions=layout \
+; RUN: llvm-pdbutil pretty -classes -class-definitions=layout \
 ; RUN:     -include-types=SimplePad %p/Inputs/SimplePaddingTest.pdb > %t
 
 ; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PADDING

Modified: llvm/trunk/test/tools/llvm-pdbdump/symbol-filters.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-pdbdump/symbol-filters.test?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-pdbdump/symbol-filters.test (original)
+++ llvm/trunk/test/tools/llvm-pdbdump/symbol-filters.test Fri Jun  9 15:46:17 2017
@@ -1,25 +1,25 @@
-; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=data %p/Inputs/FilterTest.pdb \
+; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=data %p/Inputs/FilterTest.pdb \
 ; RUN:    | FileCheck --check-prefix=ONLY_DATA %s
 
-; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=thunks %p/Inputs/FilterTest.pdb \
+; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=thunks %p/Inputs/FilterTest.pdb \
 ; RUN:    | FileCheck --check-prefix=ONLY_THUNKS %s
 
-; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=funcs %p/Inputs/FilterTest.pdb \
+; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=funcs %p/Inputs/FilterTest.pdb \
 ; RUN:    | FileCheck --check-prefix=ONLY_FUNCS %s
 
-; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=funcs -sym-types=data \
+; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=funcs -sym-types=data \
 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=TWO_TYPES %s
 
-; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=data \
+; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=data \
 ; RUN: -symbol-order=name %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=NAME_SORT_DATA %s
 
-; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=data \
+; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=data \
 ; RUN: -symbol-order=size %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=SIZE_SORT_DATA %s
 
-; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=funcs \
+; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=funcs \
 ; RUN: -symbol-order=name %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=NAME_SORT_FUNCS %s
 
-; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=funcs \
+; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=funcs \
 ; RUN: -symbol-order=size %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=SIZE_SORT_FUNCS %s
 
 ; ONLY_DATA-NOT: func

Modified: llvm/trunk/tools/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/LLVMBuild.txt?rev=305106&r1=305105&r2=305106&view=diff
==============================================================================
--- llvm/trunk/tools/LLVMBuild.txt (original)
+++ llvm/trunk/tools/LLVMBuild.txt Fri Jun  9 15:46:17 2017
@@ -40,7 +40,7 @@ subdirectories =
  llvm-modextract
  llvm-nm
  llvm-objdump
- llvm-pdbdump
+ llvm-pdbutil
  llvm-profdata
  llvm-rtdyld
  llvm-size

Added: llvm/trunk/tools/llvm-pdbutil/Analyze.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/Analyze.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/Analyze.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/Analyze.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,152 @@
+//===- Analyze.cpp - PDB analysis functions ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Analyze.h"
+
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <list>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static StringRef getLeafTypeName(TypeLeafKind LT) {
+  switch (LT) {
+#define TYPE_RECORD(ename, value, name)                                        \
+  case ename:                                                                  \
+    return #name;
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+  default:
+    break;
+  }
+  return "UnknownLeaf";
+}
+
+namespace {
+struct HashLookupVisitor : public TypeVisitorCallbacks {
+  struct Entry {
+    TypeIndex TI;
+    CVType Record;
+  };
+
+  explicit HashLookupVisitor(TpiStream &Tpi) : Tpi(Tpi) {}
+
+  Error visitTypeBegin(CVType &Record) override {
+    uint32_t H = Tpi.getHashValues()[I];
+    Record.Hash = H;
+    TypeIndex TI(I + TypeIndex::FirstNonSimpleIndex);
+    Lookup[H].push_back(Entry{TI, Record});
+    ++I;
+    return Error::success();
+  }
+
+  uint32_t I = 0;
+  DenseMap<uint32_t, std::list<Entry>> Lookup;
+  TpiStream &Tpi;
+};
+}
+
+AnalysisStyle::AnalysisStyle(PDBFile &File) : File(File) {}
+
+Error AnalysisStyle::dump() {
+  auto Tpi = File.getPDBTpiStream();
+  if (!Tpi)
+    return Tpi.takeError();
+
+  TypeDatabase TypeDB(Tpi->getNumTypeRecords());
+  TypeDatabaseVisitor DBV(TypeDB);
+  TypeVisitorCallbackPipeline Pipeline;
+  HashLookupVisitor Hasher(*Tpi);
+  // Add them to the database
+  Pipeline.addCallbackToPipeline(DBV);
+  // Store their hash values
+  Pipeline.addCallbackToPipeline(Hasher);
+
+  if (auto EC = codeview::visitTypeStream(Tpi->typeArray(), Pipeline))
+    return EC;
+
+  auto &Adjusters = Tpi->getHashAdjusters();
+  DenseSet<uint32_t> AdjusterSet;
+  for (const auto &Adj : Adjusters) {
+    assert(AdjusterSet.find(Adj.second) == AdjusterSet.end());
+    AdjusterSet.insert(Adj.second);
+  }
+
+  uint32_t Count = 0;
+  outs() << "Searching for hash collisions\n";
+  for (const auto &H : Hasher.Lookup) {
+    if (H.second.size() <= 1)
+      continue;
+    ++Count;
+    outs() << formatv("Hash: {0}, Count: {1} records\n", H.first,
+                      H.second.size());
+    for (const auto &R : H.second) {
+      auto Iter = AdjusterSet.find(R.TI.getIndex());
+      StringRef Prefix;
+      if (Iter != AdjusterSet.end()) {
+        Prefix = "[HEAD]";
+        AdjusterSet.erase(Iter);
+      }
+      StringRef LeafName = getLeafTypeName(R.Record.Type);
+      uint32_t TI = R.TI.getIndex();
+      StringRef TypeName = TypeDB.getTypeName(R.TI);
+      outs() << formatv("{0,-6} {1} ({2:x}) {3}\n", Prefix, LeafName, TI,
+                        TypeName);
+    }
+  }
+
+  outs() << "\n";
+  outs() << "Dumping hash adjustment chains\n";
+  for (const auto &A : Tpi->getHashAdjusters()) {
+    TypeIndex TI(A.second);
+    StringRef TypeName = TypeDB.getTypeName(TI);
+    const CVType &HeadRecord = TypeDB.getTypeRecord(TI);
+    assert(HeadRecord.Hash.hasValue());
+
+    auto CollisionsIter = Hasher.Lookup.find(*HeadRecord.Hash);
+    if (CollisionsIter == Hasher.Lookup.end())
+      continue;
+
+    const auto &Collisions = CollisionsIter->second;
+    outs() << TypeName << "\n";
+    outs() << formatv("    [HEAD] {0:x} {1} {2}\n", A.second,
+                      getLeafTypeName(HeadRecord.Type), TypeName);
+    for (const auto &Chain : Collisions) {
+      if (Chain.TI == TI)
+        continue;
+      const CVType &TailRecord = TypeDB.getTypeRecord(Chain.TI);
+      outs() << formatv("           {0:x} {1} {2}\n", Chain.TI.getIndex(),
+                        getLeafTypeName(TailRecord.Type),
+                        TypeDB.getTypeName(Chain.TI));
+    }
+  }
+  outs() << formatv("There are {0} orphaned hash adjusters\n",
+                    AdjusterSet.size());
+  for (const auto &Adj : AdjusterSet) {
+    outs() << formatv("    {0}\n", Adj);
+  }
+
+  uint32_t DistinctHashValues = Hasher.Lookup.size();
+  outs() << formatv("{0}/{1} hash collisions", Count, DistinctHashValues);
+  return Error::success();
+}

Added: llvm/trunk/tools/llvm-pdbutil/Analyze.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/Analyze.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/Analyze.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/Analyze.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,30 @@
+//===- Analyze.h - PDB analysis functions -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H
+#define LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H
+
+#include "OutputStyle.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+class AnalysisStyle : public OutputStyle {
+public:
+  explicit AnalysisStyle(PDBFile &File);
+
+  Error dump() override;
+
+private:
+  PDBFile &File;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/CMakeLists.txt?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/CMakeLists.txt (added)
+++ llvm/trunk/tools/llvm-pdbutil/CMakeLists.txt Fri Jun  9 15:46:17 2017
@@ -0,0 +1,34 @@
+set(LLVM_LINK_COMPONENTS
+  DebugInfoCodeView
+  DebugInfoMSF
+  DebugInfoPDB
+  Object
+  ObjectYAML
+  Support
+  )
+
+add_llvm_tool(llvm-pdbutil
+  Analyze.cpp
+  CompactTypeDumpVisitor.cpp
+  Diff.cpp
+  llvm-pdbutil.cpp
+  LinePrinter.cpp
+  LLVMOutputStyle.cpp
+  PdbYaml.cpp
+  PrettyBuiltinDumper.cpp
+  PrettyClassDefinitionDumper.cpp
+  PrettyClassLayoutGraphicalDumper.cpp
+  PrettyCompilandDumper.cpp
+  PrettyEnumDumper.cpp
+  PrettyExternalSymbolDumper.cpp
+  PrettyFunctionDumper.cpp
+  PrettyTypeDumper.cpp
+  PrettyTypedefDumper.cpp
+  PrettyVariableDumper.cpp
+  StreamUtil.cpp
+  YAMLOutputStyle.cpp
+  )
+
+if(LLVM_USE_SANITIZE_COVERAGE)
+  add_subdirectory(fuzzer)
+endif()

Added: llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,59 @@
+//===-- CompactTypeDumpVisitor.cpp - CodeView type info dumper --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompactTypeDumpVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
+#define CV_TYPE(enum, val) {#enum, enum},
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+};
+
+static StringRef getLeafName(TypeLeafKind K) {
+  for (const auto &E : LeafTypeNames) {
+    if (E.Value == K)
+      return E.Name;
+  }
+  return StringRef();
+}
+
+CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
+                                               ScopedPrinter *W)
+    : CompactTypeDumpVisitor(Types, TypeIndex(TypeIndex::FirstNonSimpleIndex),
+                             W) {}
+
+CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
+                                               TypeIndex FirstTI,
+                                               ScopedPrinter *W)
+    : W(W), TI(FirstTI), Offset(0), Types(Types) {}
+
+Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
+  return Error::success();
+}
+
+Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) {
+  uint32_t I = TI.getIndex();
+  StringRef Leaf = getLeafName(Record.Type);
+  StringRef Name = Types.getTypeName(TI);
+  W->printString(
+      llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I,
+                    Record.length(), Offset, Leaf, Name)
+          .str());
+
+  Offset += Record.length();
+  TI.setIndex(TI.getIndex() + 1);
+
+  return Error::success();
+}

Added: llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/CompactTypeDumpVisitor.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,49 @@
+//===-- CompactTypeDumpVisitor.h - CodeView type info dumper ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H
+
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+
+namespace llvm {
+class ScopedPrinter;
+namespace codeview {
+class TypeCollection;
+}
+
+namespace pdb {
+
+/// Dumper for CodeView type streams found in COFF object files and PDB files.
+/// Dumps records on a single line, and ignores member records.
+class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
+public:
+  CompactTypeDumpVisitor(codeview::TypeCollection &Types, ScopedPrinter *W);
+  CompactTypeDumpVisitor(codeview::TypeCollection &Types,
+                         codeview::TypeIndex FirstTI, ScopedPrinter *W);
+
+  /// Paired begin/end actions for all types. Receives all record data,
+  /// including the fixed-length record prefix.
+  Error visitTypeBegin(codeview::CVType &Record) override;
+  Error visitTypeEnd(codeview::CVType &Record) override;
+
+private:
+  ScopedPrinter *W;
+
+  codeview::TypeIndex TI;
+  uint32_t Offset;
+  codeview::TypeCollection &Types;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/Diff.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/Diff.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/Diff.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/Diff.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,537 @@
+//===- Diff.cpp - PDB diff utility ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Diff.h"
+
+#include "StreamUtil.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/Native/Formatters.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+namespace llvm {
+template <> struct format_provider<PdbRaw_FeatureSig> {
+  static void format(const PdbRaw_FeatureSig &Sig, raw_ostream &Stream,
+                     StringRef Style) {
+    switch (Sig) {
+    case PdbRaw_FeatureSig::MinimalDebugInfo:
+      Stream << "MinimalDebugInfo";
+      break;
+    case PdbRaw_FeatureSig::NoTypeMerge:
+      Stream << "NoTypeMerge";
+      break;
+    case PdbRaw_FeatureSig::VC110:
+      Stream << "VC110";
+      break;
+    case PdbRaw_FeatureSig::VC140:
+      Stream << "VC140";
+      break;
+    }
+  }
+};
+}
+
+template <typename R> using ValueOfRange = llvm::detail::ValueOfRange<R>;
+
+template <typename Range, typename Comp>
+static void set_differences(Range &&R1, Range &&R2,
+                            SmallVectorImpl<ValueOfRange<Range>> *OnlyLeft,
+                            SmallVectorImpl<ValueOfRange<Range>> *OnlyRight,
+                            SmallVectorImpl<ValueOfRange<Range>> *Intersection,
+                            Comp Comparator) {
+
+  std::sort(R1.begin(), R1.end(), Comparator);
+  std::sort(R2.begin(), R2.end(), Comparator);
+
+  if (OnlyLeft) {
+    OnlyLeft->reserve(R1.size());
+    auto End = std::set_difference(R1.begin(), R1.end(), R2.begin(), R2.end(),
+                                   OnlyLeft->begin(), Comparator);
+    OnlyLeft->set_size(std::distance(OnlyLeft->begin(), End));
+  }
+  if (OnlyRight) {
+    OnlyLeft->reserve(R2.size());
+    auto End = std::set_difference(R2.begin(), R2.end(), R1.begin(), R1.end(),
+                                   OnlyRight->begin(), Comparator);
+    OnlyRight->set_size(std::distance(OnlyRight->begin(), End));
+  }
+  if (Intersection) {
+    Intersection->reserve(std::min(R1.size(), R2.size()));
+    auto End = std::set_intersection(R1.begin(), R1.end(), R2.begin(), R2.end(),
+                                     Intersection->begin(), Comparator);
+    Intersection->set_size(std::distance(Intersection->begin(), End));
+  }
+}
+
+template <typename Range>
+static void
+set_differences(Range &&R1, Range &&R2,
+                SmallVectorImpl<ValueOfRange<Range>> *OnlyLeft,
+                SmallVectorImpl<ValueOfRange<Range>> *OnlyRight,
+                SmallVectorImpl<ValueOfRange<Range>> *Intersection = nullptr) {
+  std::less<ValueOfRange<Range>> Comp;
+  set_differences(std::forward<Range>(R1), std::forward<Range>(R2), OnlyLeft,
+                  OnlyRight, Intersection, Comp);
+}
+
+DiffStyle::DiffStyle(PDBFile &File1, PDBFile &File2)
+    : File1(File1), File2(File2) {}
+
+Error DiffStyle::dump() {
+  if (auto EC = diffSuperBlock())
+    return EC;
+
+  if (auto EC = diffFreePageMap())
+    return EC;
+
+  if (auto EC = diffStreamDirectory())
+    return EC;
+
+  if (auto EC = diffStringTable())
+    return EC;
+
+  if (auto EC = diffInfoStream())
+    return EC;
+
+  if (auto EC = diffDbiStream())
+    return EC;
+
+  if (auto EC = diffSectionContribs())
+    return EC;
+
+  if (auto EC = diffSectionMap())
+    return EC;
+
+  if (auto EC = diffFpoStream())
+    return EC;
+
+  if (auto EC = diffTpiStream(StreamTPI))
+    return EC;
+
+  if (auto EC = diffTpiStream(StreamIPI))
+    return EC;
+
+  if (auto EC = diffPublics())
+    return EC;
+
+  if (auto EC = diffGlobals())
+    return EC;
+
+  return Error::success();
+}
+
+template <typename T>
+static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2, T V1,
+                         T V2) {
+  if (V1 == V2) {
+    outs() << formatv("  {0}: No differences detected!\n", Label);
+    return false;
+  }
+
+  outs().indent(2) << Label << "\n";
+  outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(), V1);
+  outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(), V2);
+  return true;
+}
+
+template <typename T>
+static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2,
+                         ArrayRef<T> V1, ArrayRef<T> V2) {
+  if (V1 == V2) {
+    outs() << formatv("  {0}: No differences detected!\n", Label);
+    return false;
+  }
+
+  outs().indent(2) << Label << "\n";
+  outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(),
+                              make_range(V1.begin(), V1.end()));
+  outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(),
+                              make_range(V2.begin(), V2.end()));
+  return true;
+}
+
+template <typename T>
+static bool printSymmetricDifferences(PDBFile &File1, PDBFile &File2,
+                                      T &&OnlyRange1, T &&OnlyRange2,
+                                      StringRef Label) {
+  bool HasDiff = false;
+  if (!OnlyRange1.empty()) {
+    HasDiff = true;
+    outs() << formatv("  {0} {1}(s) only in ({2})\n", OnlyRange1.size(), Label,
+                      File1.getFilePath());
+    for (const auto &Item : OnlyRange1)
+      outs() << formatv("    {0}\n", Label, Item);
+  }
+  if (!OnlyRange2.empty()) {
+    HasDiff = true;
+    outs() << formatv("  {0} {1}(s) only in ({2})\n", OnlyRange2.size(),
+                      File2.getFilePath());
+    for (const auto &Item : OnlyRange2)
+      outs() << formatv("    {0}\n", Item);
+  }
+  return HasDiff;
+}
+
+Error DiffStyle::diffSuperBlock() {
+  outs() << "MSF Super Block: Searching for differences...\n";
+  bool Diffs = false;
+
+  Diffs |= diffAndPrint("Block Size", File1, File2, File1.getBlockSize(),
+                        File2.getBlockSize());
+  Diffs |= diffAndPrint("Block Count", File1, File2, File1.getBlockCount(),
+                        File2.getBlockCount());
+  Diffs |= diffAndPrint("Unknown 1", File1, File2, File1.getUnknown1(),
+                        File2.getUnknown1());
+
+  if (opts::diff::Pedantic) {
+    Diffs |= diffAndPrint("Free Block Map", File1, File2,
+                          File1.getFreeBlockMapBlock(),
+                          File2.getFreeBlockMapBlock());
+    Diffs |= diffAndPrint("Directory Size", File1, File2,
+                          File1.getNumDirectoryBytes(),
+                          File2.getNumDirectoryBytes());
+    Diffs |= diffAndPrint("Block Map Addr", File1, File2,
+                          File1.getBlockMapOffset(), File2.getBlockMapOffset());
+  }
+  if (!Diffs)
+    outs() << "MSF Super Block: No differences detected...\n";
+  return Error::success();
+}
+
+Error DiffStyle::diffStreamDirectory() {
+  SmallVector<std::string, 32> P;
+  SmallVector<std::string, 32> Q;
+  discoverStreamPurposes(File1, P);
+  discoverStreamPurposes(File2, Q);
+  outs() << "Stream Directory: Searching for differences...\n";
+
+  bool HasDifferences = false;
+  if (opts::diff::Pedantic) {
+    size_t Min = std::min(P.size(), Q.size());
+    for (size_t I = 0; I < Min; ++I) {
+      StringRef Names[] = {P[I], Q[I]};
+      uint32_t Sizes[] = {File1.getStreamByteSize(I),
+                          File2.getStreamByteSize(I)};
+      bool NamesDiffer = Names[0] != Names[1];
+      bool SizesDiffer = Sizes[0] != Sizes[1];
+      if (NamesDiffer) {
+        HasDifferences = true;
+        outs().indent(2) << formatv("Stream {0} - {1}: {2}, {3}: {4}\n", I,
+                                    File1.getFilePath(), Names[0],
+                                    File2.getFilePath(), Names[1]);
+        continue;
+      }
+      if (SizesDiffer) {
+        HasDifferences = true;
+        outs().indent(2) << formatv(
+            "Stream {0} ({1}): {2}: {3} bytes, {4}: {5} bytes\n", I, Names[0],
+            File1.getFilePath(), Sizes[0], File2.getFilePath(), Sizes[1]);
+        continue;
+      }
+    }
+
+    ArrayRef<std::string> MaxNames = (P.size() > Q.size() ? P : Q);
+    size_t Max = std::max(P.size(), Q.size());
+    PDBFile &MaxFile = (P.size() > Q.size() ? File1 : File2);
+    StringRef MinFileName =
+        (P.size() < Q.size() ? File1.getFilePath() : File2.getFilePath());
+    for (size_t I = Min; I < Max; ++I) {
+      HasDifferences = true;
+      StringRef StreamName = MaxNames[I];
+
+      outs().indent(2) << formatv(
+          "Stream {0} - {1}: <not present>, {2}: Index {3}, {4} bytes\n",
+          StreamName, MinFileName, MaxFile.getFilePath(), I,
+          MaxFile.getStreamByteSize(I));
+    }
+    if (!HasDifferences)
+      outs() << "Stream Directory: No differences detected...\n";
+  } else {
+    auto PI = to_vector<32>(enumerate(P));
+    auto QI = to_vector<32>(enumerate(Q));
+
+    typedef decltype(PI) ContainerType;
+    typedef typename ContainerType::value_type value_type;
+
+    auto Comparator = [](const value_type &I1, const value_type &I2) {
+      return I1.value() < I2.value();
+    };
+
+    decltype(PI) OnlyP;
+    decltype(QI) OnlyQ;
+    decltype(PI) Common;
+
+    set_differences(PI, QI, &OnlyP, &OnlyQ, &Common, Comparator);
+
+    if (!OnlyP.empty()) {
+      HasDifferences = true;
+      outs().indent(2) << formatv("{0} Stream(s) only in ({1})\n", OnlyP.size(),
+                                  File1.getFilePath());
+      for (auto &Item : OnlyP) {
+        outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(),
+                                    Item.value());
+      }
+    }
+
+    if (!OnlyQ.empty()) {
+      HasDifferences = true;
+      outs().indent(2) << formatv("{0} Streams(s) only in ({1})\n",
+                                  OnlyQ.size(), File2.getFilePath());
+      for (auto &Item : OnlyQ) {
+        outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(),
+                                    Item.value());
+      }
+    }
+    if (!Common.empty()) {
+      outs().indent(2) << formatv("Found {0} common streams.  Searching for "
+                                  "intra-stream differences.\n",
+                                  Common.size());
+      bool HasCommonDifferences = false;
+      for (const auto &Left : Common) {
+        // Left was copied from the first range so its index refers to a stream
+        // index in the first file.  Find the corresponding stream index in the
+        // second file.
+        auto Range =
+            std::equal_range(QI.begin(), QI.end(), Left,
+                             [](const value_type &L, const value_type &R) {
+                               return L.value() < R.value();
+                             });
+        const auto &Right = *Range.first;
+        assert(Left.value() == Right.value());
+        uint32_t LeftSize = File1.getStreamByteSize(Left.index());
+        uint32_t RightSize = File2.getStreamByteSize(Right.index());
+        if (LeftSize != RightSize) {
+          HasDifferences = true;
+          HasCommonDifferences = true;
+          outs().indent(4) << formatv("{0} ({1}: {2} bytes, {3}: {4} bytes)\n",
+                                      Left.value(), File1.getFilePath(),
+                                      LeftSize, File2.getFilePath(), RightSize);
+        }
+      }
+      if (!HasCommonDifferences)
+        outs().indent(2) << "Common Streams:  No differences detected!\n";
+    }
+    if (!HasDifferences)
+      outs() << "Stream Directory: No differences detected!\n";
+  }
+
+  return Error::success();
+}
+
+Error DiffStyle::diffStringTable() {
+  auto ExpectedST1 = File1.getStringTable();
+  auto ExpectedST2 = File2.getStringTable();
+  outs() << "String Table: Searching for differences...\n";
+  bool Has1 = !!ExpectedST1;
+  bool Has2 = !!ExpectedST2;
+  if (!(Has1 && Has2)) {
+    // If one has a string table and the other doesn't, we can print less
+    // output.
+    if (Has1 != Has2) {
+      if (Has1) {
+        outs() << formatv("  {0}: ({1} strings)\n", File1.getFilePath(),
+                          ExpectedST1->getNameCount());
+        outs() << formatv("  {0}: (string table not present)\n",
+                          File2.getFilePath());
+      } else {
+        outs() << formatv("  {0}: (string table not present)\n",
+                          File1.getFilePath());
+        outs() << formatv("  {0}: ({1})\n", File2.getFilePath(),
+                          ExpectedST2->getNameCount());
+      }
+    }
+    consumeError(ExpectedST1.takeError());
+    consumeError(ExpectedST2.takeError());
+    return Error::success();
+  }
+
+  bool HasDiff = false;
+  auto &ST1 = *ExpectedST1;
+  auto &ST2 = *ExpectedST2;
+
+  if (ST1.getByteSize() != ST2.getByteSize()) {
+    outs() << "  Stream Size\n";
+    outs() << formatv("    {0} - {1} byte(s)\n", File1.getFilePath(),
+                      ST1.getByteSize());
+    outs() << formatv("    {0} - {1} byte(s)\n", File2.getFilePath(),
+                      ST2.getByteSize());
+    outs() << formatv("    Difference: {0} bytes\n",
+                      AbsoluteDifference(ST1.getByteSize(), ST2.getByteSize()));
+    HasDiff = true;
+  }
+  HasDiff |= diffAndPrint("Hash Version", File1, File2, ST1.getHashVersion(),
+                          ST1.getHashVersion());
+  HasDiff |= diffAndPrint("Signature", File1, File2, ST1.getSignature(),
+                          ST1.getSignature());
+
+  // Both have a valid string table, dive in and compare individual strings.
+
+  auto IdList1 = ST1.name_ids();
+  auto IdList2 = ST2.name_ids();
+  if (opts::diff::Pedantic) {
+    // In pedantic mode, we compare index by index (i.e. the strings are in the
+    // same order
+    // in both tables.
+    uint32_t Max = std::max(IdList1.size(), IdList2.size());
+    for (uint32_t I = 0; I < Max; ++I) {
+      Optional<uint32_t> Id1, Id2;
+      StringRef S1, S2;
+      if (I < IdList1.size()) {
+        Id1 = IdList1[I];
+        if (auto Result = ST1.getStringForID(*Id1))
+          S1 = *Result;
+        else
+          return Result.takeError();
+      }
+      if (I < IdList2.size()) {
+        Id2 = IdList2[I];
+        if (auto Result = ST2.getStringForID(*Id2))
+          S2 = *Result;
+        else
+          return Result.takeError();
+      }
+      if (Id1 == Id2 && S1 == S2)
+        continue;
+
+      std::string OutId1 =
+          Id1 ? formatv("{0}", *Id1).str() : "(index not present)";
+      std::string OutId2 =
+          Id2 ? formatv("{0}", *Id2).str() : "(index not present)";
+      outs() << formatv("  String {0}\n", I);
+      outs() << formatv("    {0}: Hash - {1}, Value - {2}\n",
+                        File1.getFilePath(), OutId1, S1);
+      outs() << formatv("    {0}: Hash - {1}, Value - {2}\n",
+                        File2.getFilePath(), OutId2, S2);
+      HasDiff = true;
+    }
+  } else {
+    std::vector<StringRef> Strings1, Strings2;
+    Strings1.reserve(IdList1.size());
+    Strings2.reserve(IdList2.size());
+    for (auto ID : IdList1) {
+      auto S = ST1.getStringForID(ID);
+      if (!S)
+        return S.takeError();
+      Strings1.push_back(*S);
+    }
+    for (auto ID : IdList2) {
+      auto S = ST2.getStringForID(ID);
+      if (!S)
+        return S.takeError();
+      Strings2.push_back(*S);
+    }
+
+    SmallVector<StringRef, 64> OnlyP;
+    SmallVector<StringRef, 64> OnlyQ;
+    auto End1 = std::remove(Strings1.begin(), Strings1.end(), "");
+    auto End2 = std::remove(Strings2.begin(), Strings2.end(), "");
+    uint32_t Empty1 = std::distance(End1, Strings1.end());
+    uint32_t Empty2 = std::distance(End2, Strings2.end());
+    Strings1.erase(End1, Strings1.end());
+    Strings2.erase(End2, Strings2.end());
+    set_differences(Strings1, Strings2, &OnlyP, &OnlyQ);
+    printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "String");
+
+    if (Empty1 != Empty2) {
+      PDBFile &MoreF = (Empty1 > Empty2) ? File1 : File2;
+      PDBFile &LessF = (Empty1 < Empty2) ? File1 : File2;
+      uint32_t Difference = AbsoluteDifference(Empty1, Empty2);
+      outs() << formatv("  {0} had {1} more empty strings than {2}\n",
+                        MoreF.getFilePath(), Difference, LessF.getFilePath());
+    }
+  }
+  if (!HasDiff)
+    outs() << "String Table: No differences detected!\n";
+  return Error::success();
+}
+
+Error DiffStyle::diffFreePageMap() { return Error::success(); }
+
+Error DiffStyle::diffInfoStream() {
+  auto ExpectedInfo1 = File1.getPDBInfoStream();
+  auto ExpectedInfo2 = File2.getPDBInfoStream();
+
+  outs() << "PDB Stream: Searching for differences...\n";
+  bool Has1 = !!ExpectedInfo1;
+  bool Has2 = !!ExpectedInfo2;
+  if (!(Has1 && Has2)) {
+    if (Has1 != Has2)
+      outs() << formatv("{0} does not have a PDB Stream!\n",
+                        Has1 ? File1.getFilePath() : File2.getFilePath());
+    consumeError(ExpectedInfo2.takeError());
+    consumeError(ExpectedInfo2.takeError());
+    return Error::success();
+  }
+
+  bool HasDiff = false;
+  auto &IS1 = *ExpectedInfo1;
+  auto &IS2 = *ExpectedInfo2;
+  if (IS1.getStreamSize() != IS2.getStreamSize()) {
+    outs() << "  Stream Size\n";
+    outs() << formatv("    {0} - {1} byte(s)\n", File1.getFilePath(),
+                      IS1.getStreamSize());
+    outs() << formatv("    {0} - {1} byte(s)\n", File2.getFilePath(),
+                      IS2.getStreamSize());
+    outs() << formatv(
+        "    Difference: {0} bytes\n",
+        AbsoluteDifference(IS1.getStreamSize(), IS2.getStreamSize()));
+    HasDiff = true;
+  }
+  HasDiff |= diffAndPrint("Age", File1, File2, IS1.getAge(), IS2.getAge());
+  HasDiff |= diffAndPrint("Guid", File1, File2, IS1.getGuid(), IS2.getGuid());
+  HasDiff |= diffAndPrint("Signature", File1, File2, IS1.getSignature(),
+                          IS2.getSignature());
+  HasDiff |=
+      diffAndPrint("Version", File1, File2, IS1.getVersion(), IS2.getVersion());
+  HasDiff |= diffAndPrint("Features", File1, File2, IS1.getFeatureSignatures(),
+                          IS2.getFeatureSignatures());
+  HasDiff |= diffAndPrint("Named Stream Byte Size", File1, File2,
+                          IS1.getNamedStreamMapByteSize(),
+                          IS2.getNamedStreamMapByteSize());
+  SmallVector<StringRef, 4> NS1;
+  SmallVector<StringRef, 4> NS2;
+  for (const auto &X : IS1.getNamedStreams().entries())
+    NS1.push_back(X.getKey());
+  for (const auto &X : IS2.getNamedStreams().entries())
+    NS2.push_back(X.getKey());
+  SmallVector<StringRef, 4> OnlyP;
+  SmallVector<StringRef, 4> OnlyQ;
+  set_differences(NS1, NS2, &OnlyP, &OnlyQ);
+  printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "Named Streams");
+  if (!HasDiff)
+    outs() << "PDB Stream: No differences detected!\n";
+
+  return Error::success();
+}
+
+Error DiffStyle::diffDbiStream() { return Error::success(); }
+
+Error DiffStyle::diffSectionContribs() { return Error::success(); }
+
+Error DiffStyle::diffSectionMap() { return Error::success(); }
+
+Error DiffStyle::diffFpoStream() { return Error::success(); }
+
+Error DiffStyle::diffTpiStream(int Index) { return Error::success(); }
+
+Error DiffStyle::diffModuleInfoStream(int Index) { return Error::success(); }
+
+Error DiffStyle::diffPublics() { return Error::success(); }
+
+Error DiffStyle::diffGlobals() { return Error::success(); }

Added: llvm/trunk/tools/llvm-pdbutil/Diff.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/Diff.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/Diff.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/Diff.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,45 @@
+//===- Diff.h - PDB diff utility --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
+#define LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
+
+#include "OutputStyle.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+class DiffStyle : public OutputStyle {
+public:
+  explicit DiffStyle(PDBFile &File1, PDBFile &File2);
+
+  Error dump() override;
+
+private:
+  Error diffSuperBlock();
+  Error diffStreamDirectory();
+  Error diffStringTable();
+  Error diffFreePageMap();
+  Error diffInfoStream();
+  Error diffDbiStream();
+  Error diffSectionContribs();
+  Error diffSectionMap();
+  Error diffFpoStream();
+  Error diffTpiStream(int Index);
+  Error diffModuleInfoStream(int Index);
+  Error diffPublics();
+  Error diffGlobals();
+
+  PDBFile &File1;
+  PDBFile &File2;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/LLVMBuild.txt?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/LLVMBuild.txt (added)
+++ llvm/trunk/tools/llvm-pdbutil/LLVMBuild.txt Fri Jun  9 15:46:17 2017
@@ -0,0 +1,23 @@
+;===- ./tools/llvm-pdbutil/LLVMBuild.txt -----------------------*- Conf -*--===;
+;
+;                     The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+;   http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Tool
+name = llvm-pdbutil
+parent = Tools
+required_libraries = DebugInfoMSF DebugInfoPDB
+

Added: llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,1177 @@
+//===- LLVMOutputStyle.cpp ------------------------------------ *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLVMOutputStyle.h"
+
+#include "CompactTypeDumpVisitor.h"
+#include "StreamUtil.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/FormatVariadic.h"
+
+#include <unordered_map>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+namespace {
+struct PageStats {
+  explicit PageStats(const BitVector &FreePages)
+      : Upm(FreePages), ActualUsedPages(FreePages.size()),
+        MultiUsePages(FreePages.size()), UseAfterFreePages(FreePages.size()) {
+    const_cast<BitVector &>(Upm).flip();
+    // To calculate orphaned pages, we start with the set of pages that the
+    // MSF thinks are used.  Each time we find one that actually *is* used,
+    // we unset it.  Whichever bits remain set at the end are orphaned.
+    OrphanedPages = Upm;
+  }
+
+  // The inverse of the MSF File's copy of the Fpm.  The basis for which we
+  // determine the allocation status of each page.
+  const BitVector Upm;
+
+  // Pages which are marked as used in the FPM and are used at least once.
+  BitVector ActualUsedPages;
+
+  // Pages which are marked as used in the FPM but are used more than once.
+  BitVector MultiUsePages;
+
+  // Pages which are marked as used in the FPM but are not used at all.
+  BitVector OrphanedPages;
+
+  // Pages which are marked free in the FPM but are used.
+  BitVector UseAfterFreePages;
+};
+
+class C13RawVisitor : public DebugSubsectionVisitor {
+public:
+  C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &TPI,
+                LazyRandomTypeCollection &IPI)
+      : P(P), TPI(TPI), IPI(IPI) {}
+
+  Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::Unknown))
+      return Error::success();
+    DictScope DD(P, "Unknown");
+    P.printHex("Kind", static_cast<uint32_t>(Unknown.kind()));
+    ArrayRef<uint8_t> Data;
+    BinaryStreamReader Reader(Unknown.getData());
+    consumeError(Reader.readBytes(Data, Reader.bytesRemaining()));
+    P.printBinaryBlock("Data", Data);
+    return Error::success();
+  }
+
+  Error visitLines(DebugLinesSubsectionRef &Lines,
+                   const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::Lines))
+      return Error::success();
+
+    DictScope DD(P, "Lines");
+
+    P.printNumber("RelocSegment", Lines.header()->RelocSegment);
+    P.printNumber("RelocOffset", Lines.header()->RelocOffset);
+    P.printNumber("CodeSize", Lines.header()->CodeSize);
+    P.printBoolean("HasColumns", Lines.hasColumnInfo());
+
+    for (const auto &L : Lines) {
+      DictScope DDDD(P, "FileEntry");
+
+      if (auto EC = printFileName("FileName", L.NameIndex, State))
+        return EC;
+
+      for (const auto &N : L.LineNumbers) {
+        DictScope DDD(P, "Line");
+        LineInfo LI(N.Flags);
+        P.printNumber("Offset", N.Offset);
+        if (LI.isAlwaysStepInto())
+          P.printString("StepInto", StringRef("Always"));
+        else if (LI.isNeverStepInto())
+          P.printString("StepInto", StringRef("Never"));
+        else
+          P.printNumber("LineNumberStart", LI.getStartLine());
+        P.printNumber("EndDelta", LI.getLineDelta());
+        P.printBoolean("IsStatement", LI.isStatement());
+      }
+      for (const auto &C : L.Columns) {
+        DictScope DDD(P, "Column");
+        P.printNumber("Start", C.StartColumn);
+        P.printNumber("End", C.EndColumn);
+      }
+    }
+
+    return Error::success();
+  }
+
+  Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
+                           const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums))
+      return Error::success();
+
+    DictScope DD(P, "FileChecksums");
+    for (const auto &CS : Checksums) {
+      DictScope DDD(P, "Checksum");
+      if (auto Result = getNameFromStringTable(CS.FileNameOffset, State))
+        P.printString("FileName", *Result);
+      else
+        return Result.takeError();
+      P.printEnum("Kind", uint8_t(CS.Kind), getFileChecksumNames());
+      P.printBinaryBlock("Checksum", CS.Checksum);
+    }
+    return Error::success();
+  }
+
+  Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
+                          const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines))
+      return Error::success();
+
+    DictScope D(P, "InlineeLines");
+    P.printBoolean("HasExtraFiles", Inlinees.hasExtraFiles());
+    ListScope LS(P, "Lines");
+    for (const auto &L : Inlinees) {
+      DictScope DDD(P, "Inlinee");
+      if (auto EC = printFileName("FileName", L.Header->FileID, State))
+        return EC;
+
+      if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee))
+        return EC;
+      P.printNumber("SourceLine", L.Header->SourceLineNum);
+      if (Inlinees.hasExtraFiles()) {
+        ListScope DDDD(P, "ExtraFiles");
+        for (const auto &EF : L.ExtraFiles) {
+          if (auto EC = printFileName("File", EF, State))
+            return EC;
+        }
+      }
+    }
+    return Error::success();
+  }
+
+  Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
+                                const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports))
+      return Error::success();
+
+    ListScope D(P, "CrossModuleExports");
+    for (const auto &M : CSE) {
+      DictScope D(P, "Export");
+      P.printHex("Local", M.Local);
+      P.printHex("Global", M.Global);
+    }
+    return Error::success();
+  }
+
+  Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSI,
+                                const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports))
+      return Error::success();
+
+    ListScope L(P, "CrossModuleImports");
+    for (const auto &M : CSI) {
+      DictScope D(P, "ModuleImport");
+      auto Name = getNameFromStringTable(M.Header->ModuleNameOffset, State);
+      if (!Name)
+        return Name.takeError();
+      P.printString("Module", *Name);
+      P.printHexList("Imports", M.Imports);
+    }
+    return Error::success();
+  }
+
+  Error visitFrameData(DebugFrameDataSubsectionRef &FD,
+                       const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::FrameData))
+      return Error::success();
+
+    ListScope L(P, "FrameData");
+    for (const auto &Frame : FD) {
+      DictScope D(P, "Frame");
+      auto Name = getNameFromStringTable(Frame.FrameFunc, State);
+      if (!Name)
+        return joinErrors(make_error<RawError>(raw_error_code::invalid_format,
+                                               "Invalid Frame.FrameFunc index"),
+                          Name.takeError());
+      P.printNumber("Rva", Frame.RvaStart);
+      P.printNumber("CodeSize", Frame.CodeSize);
+      P.printNumber("LocalSize", Frame.LocalSize);
+      P.printNumber("ParamsSize", Frame.ParamsSize);
+      P.printNumber("MaxStackSize", Frame.MaxStackSize);
+      P.printString("FrameFunc", *Name);
+      P.printNumber("PrologSize", Frame.PrologSize);
+      P.printNumber("SavedRegsSize", Frame.SavedRegsSize);
+      P.printNumber("Flags", Frame.Flags);
+    }
+    return Error::success();
+  }
+
+  Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
+                     const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::Symbols))
+      return Error::success();
+    ListScope L(P, "Symbols");
+
+    // This section should not actually appear in a PDB file, it really only
+    // appears in object files.  But we support it here for testing.  So we
+    // specify the Object File container type.
+    codeview::CVSymbolDumper SD(P, TPI, CodeViewContainer::ObjectFile, nullptr,
+                                false);
+    for (auto S : Symbols) {
+      DictScope LL(P, "");
+      if (auto EC = SD.dump(S)) {
+        return make_error<RawError>(
+            raw_error_code::corrupt_file,
+            "DEBUG_S_SYMBOLS subsection contained corrupt symbol record");
+      }
+    }
+    return Error::success();
+  }
+
+  Error visitStringTable(DebugStringTableSubsectionRef &Strings,
+                         const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::StringTable))
+      return Error::success();
+
+    ListScope D(P, "String Table");
+    BinaryStreamReader Reader(Strings.getBuffer());
+    StringRef S;
+    consumeError(Reader.readCString(S));
+    while (Reader.bytesRemaining() > 0) {
+      consumeError(Reader.readCString(S));
+      if (S.empty() && Reader.bytesRemaining() < 4)
+        break;
+      P.printString(S);
+    }
+    return Error::success();
+  }
+
+private:
+  Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
+    CompactTypeDumpVisitor CTDV(IPI, Index, &P);
+    DictScope D(P, Label);
+    if (IPI.contains(Index)) {
+      CVType Type = IPI.getType(Index);
+      if (auto EC = codeview::visitTypeRecord(Type, CTDV))
+        return EC;
+    } else {
+      P.printString(
+          llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex())
+              .str());
+    }
+    return Error::success();
+  }
+  Error printFileName(StringRef Label, uint32_t Offset,
+                      const DebugSubsectionState &State) {
+    if (auto Result = getNameFromChecksumsBuffer(Offset, State)) {
+      P.printString(Label, *Result);
+      return Error::success();
+    } else
+      return Result.takeError();
+  }
+
+  Expected<StringRef>
+  getNameFromStringTable(uint32_t Offset, const DebugSubsectionState &State) {
+    return State.strings().getString(Offset);
+  }
+
+  Expected<StringRef>
+  getNameFromChecksumsBuffer(uint32_t Offset,
+                             const DebugSubsectionState &State) {
+    auto Array = State.checksums().getArray();
+    auto ChecksumIter = Array.at(Offset);
+    if (ChecksumIter == Array.end())
+      return make_error<RawError>(raw_error_code::invalid_format);
+    const auto &Entry = *ChecksumIter;
+    return getNameFromStringTable(Entry.FileNameOffset, State);
+  }
+
+  ScopedPrinter &P;
+  LazyRandomTypeCollection &TPI;
+  LazyRandomTypeCollection &IPI;
+};
+}
+
+static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) {
+  if (Stats.Upm.test(UsedIndex)) {
+    if (Stats.ActualUsedPages.test(UsedIndex))
+      Stats.MultiUsePages.set(UsedIndex);
+    Stats.ActualUsedPages.set(UsedIndex);
+    Stats.OrphanedPages.reset(UsedIndex);
+  } else {
+    // The MSF doesn't think this page is used, but it is.
+    Stats.UseAfterFreePages.set(UsedIndex);
+  }
+}
+
+static void printSectionOffset(llvm::raw_ostream &OS,
+                               const SectionOffset &Off) {
+  OS << Off.Off << ", " << Off.Isect;
+}
+
+LLVMOutputStyle::LLVMOutputStyle(PDBFile &File) : File(File), P(outs()) {}
+
+Error LLVMOutputStyle::dump() {
+  if (auto EC = dumpFileHeaders())
+    return EC;
+
+  if (auto EC = dumpStreamSummary())
+    return EC;
+
+  if (auto EC = dumpFreePageMap())
+    return EC;
+
+  if (auto EC = dumpStreamBlocks())
+    return EC;
+
+  if (auto EC = dumpBlockRanges())
+    return EC;
+
+  if (auto EC = dumpStreamBytes())
+    return EC;
+
+  if (auto EC = dumpStringTable())
+    return EC;
+
+  if (auto EC = dumpInfoStream())
+    return EC;
+
+  if (auto EC = dumpTpiStream(StreamTPI))
+    return EC;
+
+  if (auto EC = dumpTpiStream(StreamIPI))
+    return EC;
+
+  if (auto EC = dumpDbiStream())
+    return EC;
+
+  if (auto EC = dumpSectionContribs())
+    return EC;
+
+  if (auto EC = dumpSectionMap())
+    return EC;
+
+  if (auto EC = dumpGlobalsStream())
+    return EC;
+
+  if (auto EC = dumpPublicsStream())
+    return EC;
+
+  if (auto EC = dumpSectionHeaders())
+    return EC;
+
+  if (auto EC = dumpFpoStream())
+    return EC;
+
+  flush();
+
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpFileHeaders() {
+  if (!opts::raw::DumpHeaders)
+    return Error::success();
+
+  DictScope D(P, "FileHeaders");
+  P.printNumber("BlockSize", File.getBlockSize());
+  P.printNumber("FreeBlockMap", File.getFreeBlockMapBlock());
+  P.printNumber("NumBlocks", File.getBlockCount());
+  P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
+  P.printNumber("Unknown1", File.getUnknown1());
+  P.printNumber("BlockMapAddr", File.getBlockMapIndex());
+  P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
+
+  // The directory is not contiguous.  Instead, the block map contains a
+  // contiguous list of block numbers whose contents, when concatenated in
+  // order, make up the directory.
+  P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
+  P.printNumber("NumStreams", File.getNumStreams());
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpStreamSummary() {
+  if (!opts::raw::DumpStreamSummary)
+    return Error::success();
+
+  if (StreamPurposes.empty())
+    discoverStreamPurposes(File, StreamPurposes);
+
+  uint32_t StreamCount = File.getNumStreams();
+
+  ListScope L(P, "Streams");
+  for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+    std::string Label("Stream ");
+    Label += to_string(StreamIdx);
+
+    std::string Value = "[" + StreamPurposes[StreamIdx] + "] (";
+    Value += to_string(File.getStreamByteSize(StreamIdx));
+    Value += " bytes)";
+
+    P.printString(Label, Value);
+  }
+
+  P.flush();
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpFreePageMap() {
+  if (!opts::raw::DumpPageStats)
+    return Error::success();
+
+  // Start with used pages instead of free pages because
+  // the number of free pages is far larger than used pages.
+  BitVector FPM = File.getMsfLayout().FreePageMap;
+
+  PageStats PS(FPM);
+
+  recordKnownUsedPage(PS, 0); // MSF Super Block
+
+  uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout());
+  uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout());
+  for (uint32_t I = 0; I < NumSections; ++I) {
+    uint32_t Fpm0 = 1 + BlocksPerSection * I;
+    // 2 Fpm blocks spaced at `getBlockSize()` block intervals
+    recordKnownUsedPage(PS, Fpm0);
+    recordKnownUsedPage(PS, Fpm0 + 1);
+  }
+
+  recordKnownUsedPage(PS, File.getBlockMapIndex()); // Stream Table
+
+  for (auto DB : File.getDirectoryBlockArray())
+    recordKnownUsedPage(PS, DB);
+
+  // Record pages used by streams. Note that pages for stream 0
+  // are considered being unused because that's what MSVC tools do.
+  // Stream 0 doesn't contain actual data, so it makes some sense,
+  // though it's a bit confusing to us.
+  for (auto &SE : File.getStreamMap().drop_front(1))
+    for (auto &S : SE)
+      recordKnownUsedPage(PS, S);
+
+  dumpBitVector("Msf Free Pages", FPM);
+  dumpBitVector("Orphaned Pages", PS.OrphanedPages);
+  dumpBitVector("Multiply Used Pages", PS.MultiUsePages);
+  dumpBitVector("Use After Free Pages", PS.UseAfterFreePages);
+  return Error::success();
+}
+
+void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) {
+  std::vector<uint32_t> Vec;
+  for (uint32_t I = 0, E = V.size(); I != E; ++I)
+    if (V[I])
+      Vec.push_back(I);
+  P.printList(Name, Vec);
+}
+
+Error LLVMOutputStyle::dumpGlobalsStream() {
+  if (!opts::raw::DumpGlobals)
+    return Error::success();
+  if (!File.hasPDBGlobalsStream()) {
+    P.printString("Globals Stream not present");
+    return Error::success();
+  }
+
+  auto Globals = File.getPDBGlobalsStream();
+  if (!Globals)
+    return Globals.takeError();
+  DictScope D(P, "Globals Stream");
+
+  auto Dbi = File.getPDBDbiStream();
+  if (!Dbi)
+    return Dbi.takeError();
+
+  P.printNumber("Stream number", Dbi->getGlobalSymbolStreamIndex());
+  P.printNumber("Number of buckets", Globals->getNumBuckets());
+  P.printList("Hash Buckets", Globals->getHashBuckets());
+
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpStreamBlocks() {
+  if (!opts::raw::DumpStreamBlocks)
+    return Error::success();
+
+  ListScope L(P, "StreamBlocks");
+  uint32_t StreamCount = File.getNumStreams();
+  for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+    std::string Name("Stream ");
+    Name += to_string(StreamIdx);
+    auto StreamBlocks = File.getStreamBlockList(StreamIdx);
+    P.printList(Name, StreamBlocks);
+  }
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpBlockRanges() {
+  if (!opts::raw::DumpBlockRange.hasValue())
+    return Error::success();
+  auto &R = *opts::raw::DumpBlockRange;
+  uint32_t Max = R.Max.getValueOr(R.Min);
+
+  if (Max < R.Min)
+    return make_error<StringError>(
+        "Invalid block range specified.  Max < Min",
+        std::make_error_code(std::errc::bad_address));
+  if (Max >= File.getBlockCount())
+    return make_error<StringError>(
+        "Invalid block range specified.  Requested block out of bounds",
+        std::make_error_code(std::errc::bad_address));
+
+  DictScope D(P, "Block Data");
+  for (uint32_t I = R.Min; I <= Max; ++I) {
+    auto ExpectedData = File.getBlockData(I, File.getBlockSize());
+    if (!ExpectedData)
+      return ExpectedData.takeError();
+    std::string Label;
+    llvm::raw_string_ostream S(Label);
+    S << "Block " << I;
+    S.flush();
+    P.printBinaryBlock(Label, *ExpectedData);
+  }
+
+  return Error::success();
+}
+
+static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset,
+                             uint32_t &Size) {
+  if (Str.consumeInteger(0, SI))
+    return make_error<RawError>(raw_error_code::invalid_format,
+                                "Invalid Stream Specification");
+  if (Str.consume_front(":")) {
+    if (Str.consumeInteger(0, Offset))
+      return make_error<RawError>(raw_error_code::invalid_format,
+                                  "Invalid Stream Specification");
+  }
+  if (Str.consume_front("@")) {
+    if (Str.consumeInteger(0, Size))
+      return make_error<RawError>(raw_error_code::invalid_format,
+                                  "Invalid Stream Specification");
+  }
+  if (!Str.empty())
+    return make_error<RawError>(raw_error_code::invalid_format,
+                                "Invalid Stream Specification");
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpStreamBytes() {
+  if (opts::raw::DumpStreamData.empty())
+    return Error::success();
+
+  if (StreamPurposes.empty())
+    discoverStreamPurposes(File, StreamPurposes);
+
+  DictScope D(P, "Stream Data");
+  for (auto &Str : opts::raw::DumpStreamData) {
+    uint32_t SI = 0;
+    uint32_t Begin = 0;
+    uint32_t Size = 0;
+    uint32_t End = 0;
+
+    if (auto EC = parseStreamSpec(Str, SI, Begin, Size))
+      return EC;
+
+    if (SI >= File.getNumStreams())
+      return make_error<RawError>(raw_error_code::no_stream);
+
+    auto S = MappedBlockStream::createIndexedStream(
+        File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator());
+    if (!S)
+      continue;
+    DictScope DD(P, "Stream");
+    if (Size == 0)
+      End = S->getLength();
+    else {
+      End = Begin + Size;
+      if (End >= S->getLength())
+        return make_error<RawError>(raw_error_code::index_out_of_bounds,
+                                    "Stream is not long enough!");
+    }
+
+    P.printNumber("Index", SI);
+    P.printString("Type", StreamPurposes[SI]);
+    P.printNumber("Size", S->getLength());
+    auto Blocks = File.getMsfLayout().StreamMap[SI];
+    P.printList("Blocks", Blocks);
+
+    BinaryStreamReader R(*S);
+    ArrayRef<uint8_t> StreamData;
+    if (auto EC = R.readBytes(StreamData, S->getLength()))
+      return EC;
+    Size = End - Begin;
+    StreamData = StreamData.slice(Begin, Size);
+    P.printBinaryBlock("Data", StreamData, Begin);
+  }
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpStringTable() {
+  if (!opts::raw::DumpStringTable)
+    return Error::success();
+
+  auto IS = File.getStringTable();
+  if (!IS)
+    return IS.takeError();
+
+  DictScope D(P, "String Table");
+  for (uint32_t I : IS->name_ids()) {
+    auto ES = IS->getStringForID(I);
+    if (!ES)
+      return ES.takeError();
+
+    if (ES->empty())
+      continue;
+    llvm::SmallString<32> Str;
+    Str.append("'");
+    Str.append(*ES);
+    Str.append("'");
+    P.printString(Str);
+  }
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpInfoStream() {
+  if (!opts::raw::DumpHeaders)
+    return Error::success();
+  if (!File.hasPDBInfoStream()) {
+    P.printString("PDB Stream not present");
+    return Error::success();
+  }
+  auto IS = File.getPDBInfoStream();
+  if (!IS)
+    return IS.takeError();
+
+  DictScope D(P, "PDB Stream");
+  P.printNumber("Version", IS->getVersion());
+  P.printHex("Signature", IS->getSignature());
+  P.printNumber("Age", IS->getAge());
+  P.printObject("Guid", IS->getGuid());
+  P.printHex("Features", IS->getFeatures());
+  {
+    DictScope DD(P, "Named Streams");
+    for (const auto &S : IS->getNamedStreams().entries())
+      P.printObject(S.getKey(), S.getValue());
+  }
+  return Error::success();
+}
+
+namespace {
+class RecordBytesVisitor : public TypeVisitorCallbacks {
+public:
+  explicit RecordBytesVisitor(ScopedPrinter &P) : P(P) {}
+
+  Error visitTypeEnd(CVType &Record) override {
+    P.printBinaryBlock("Bytes", Record.content());
+    return Error::success();
+  }
+
+private:
+  ScopedPrinter &P;
+};
+}
+
+Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
+  assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
+
+  bool DumpRecordBytes = false;
+  bool DumpRecords = false;
+  bool DumpTpiHash = false;
+  StringRef Label;
+  StringRef VerLabel;
+  if (StreamIdx == StreamTPI) {
+    if (!File.hasPDBTpiStream()) {
+      P.printString("Type Info Stream (TPI) not present");
+      return Error::success();
+    }
+    DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
+    DumpRecords = opts::raw::DumpTpiRecords;
+    DumpTpiHash = opts::raw::DumpTpiHash;
+    Label = "Type Info Stream (TPI)";
+    VerLabel = "TPI Version";
+  } else if (StreamIdx == StreamIPI) {
+    if (!File.hasPDBIpiStream()) {
+      P.printString("Type Info Stream (IPI) not present");
+      return Error::success();
+    }
+    DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
+    DumpRecords = opts::raw::DumpIpiRecords;
+    Label = "Type Info Stream (IPI)";
+    VerLabel = "IPI Version";
+  }
+
+  auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
+                                      : File.getPDBIpiStream();
+  if (!Tpi)
+    return Tpi.takeError();
+
+  auto ExpectedTypes = initializeTypeDatabase(StreamIdx);
+  if (!ExpectedTypes)
+    return ExpectedTypes.takeError();
+  auto &Types = *ExpectedTypes;
+
+  if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
+    return Error::success();
+
+  std::unique_ptr<DictScope> StreamScope;
+  std::unique_ptr<ListScope> RecordScope;
+
+  StreamScope = llvm::make_unique<DictScope>(P, Label);
+  P.printNumber(VerLabel, Tpi->getTpiVersion());
+  P.printNumber("Record count", Tpi->getNumTypeRecords());
+
+  std::vector<std::unique_ptr<TypeVisitorCallbacks>> Visitors;
+
+  // If we're in dump mode, add a dumper with the appropriate detail level.
+  if (DumpRecords) {
+    std::unique_ptr<TypeVisitorCallbacks> Dumper;
+    if (opts::raw::CompactRecords)
+      Dumper = make_unique<CompactTypeDumpVisitor>(Types, &P);
+    else {
+      assert(TpiTypes);
+
+      auto X = make_unique<TypeDumpVisitor>(*TpiTypes, &P, false);
+      if (StreamIdx == StreamIPI)
+        X->setIpiTypes(*IpiTypes);
+      Dumper = std::move(X);
+    }
+    Visitors.push_back(std::move(Dumper));
+  }
+  if (DumpRecordBytes)
+    Visitors.push_back(make_unique<RecordBytesVisitor>(P));
+
+  // We always need to deserialize and add it to the type database.  This is
+  // true if even if we're not dumping anything, because we could need the
+  // type database for the purposes of dumping symbols.
+  TypeVisitorCallbackPipeline Pipeline;
+  for (const auto &V : Visitors)
+    Pipeline.addCallbackToPipeline(*V);
+
+  if (DumpRecords || DumpRecordBytes)
+    RecordScope = llvm::make_unique<ListScope>(P, "Records");
+
+  Optional<TypeIndex> I = Types.getFirst();
+  while (I) {
+    std::unique_ptr<DictScope> OneRecordScope;
+
+    if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords)
+      OneRecordScope = llvm::make_unique<DictScope>(P, "");
+
+    auto T = Types.getType(*I);
+    if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline))
+      return EC;
+    I = Types.getNext(*I);
+  }
+
+  if (DumpTpiHash) {
+    DictScope DD(P, "Hash");
+    P.printNumber("Number of Hash Buckets", Tpi->getNumHashBuckets());
+    P.printNumber("Hash Key Size", Tpi->getHashKeySize());
+    P.printList("Values", Tpi->getHashValues());
+
+    ListScope LHA(P, "Adjusters");
+    auto ExpectedST = File.getStringTable();
+    if (!ExpectedST)
+      return ExpectedST.takeError();
+    const auto &ST = *ExpectedST;
+    for (const auto &E : Tpi->getHashAdjusters()) {
+      DictScope DHA(P);
+      auto Name = ST.getStringForID(E.first);
+      if (!Name)
+        return Name.takeError();
+
+      P.printString("Type", *Name);
+      P.printHex("TI", E.second);
+    }
+  }
+
+  ListScope L(P, "TypeIndexOffsets");
+  for (const auto &IO : Tpi->getTypeIndexOffsets()) {
+    P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(),
+                          (uint32_t)IO.Offset)
+                      .str());
+  }
+
+  P.flush();
+  return Error::success();
+}
+
+Expected<codeview::LazyRandomTypeCollection &>
+LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) {
+  auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
+  auto Tpi =
+      (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
+  if (!Tpi)
+    return Tpi.takeError();
+
+  if (!TypeCollection) {
+    // Initialize the type collection, even if we're not going to dump it.  This
+    // way if some other part of the dumper decides it wants to use some or all
+    // of the records for whatever purposes, it can still access them lazily.
+    auto &Types = Tpi->typeArray();
+    uint32_t Count = Tpi->getNumTypeRecords();
+    auto Offsets = Tpi->getTypeIndexOffsets();
+    TypeCollection =
+        llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
+  }
+
+  return *TypeCollection;
+}
+
+Error LLVMOutputStyle::dumpDbiStream() {
+  bool DumpModules = opts::shared::DumpModules ||
+                     opts::shared::DumpModuleSyms ||
+                     opts::shared::DumpModuleFiles ||
+                     !opts::shared::DumpModuleSubsections.empty();
+  if (!opts::raw::DumpHeaders && !DumpModules)
+    return Error::success();
+  if (!File.hasPDBDbiStream()) {
+    P.printString("DBI Stream not present");
+    return Error::success();
+  }
+
+  auto DS = File.getPDBDbiStream();
+  if (!DS)
+    return DS.takeError();
+
+  DictScope D(P, "DBI Stream");
+  P.printNumber("Dbi Version", DS->getDbiVersion());
+  P.printNumber("Age", DS->getAge());
+  P.printBoolean("Incremental Linking", DS->isIncrementallyLinked());
+  P.printBoolean("Has CTypes", DS->hasCTypes());
+  P.printBoolean("Is Stripped", DS->isStripped());
+  P.printObject("Machine Type", DS->getMachineType());
+  P.printNumber("Symbol Record Stream Index", DS->getSymRecordStreamIndex());
+  P.printNumber("Public Symbol Stream Index", DS->getPublicSymbolStreamIndex());
+  P.printNumber("Global Symbol Stream Index", DS->getGlobalSymbolStreamIndex());
+
+  uint16_t Major = DS->getBuildMajorVersion();
+  uint16_t Minor = DS->getBuildMinorVersion();
+  P.printVersion("Toolchain Version", Major, Minor);
+
+  std::string DllName;
+  raw_string_ostream DllStream(DllName);
+  DllStream << "mspdb" << Major << Minor << ".dll version";
+  DllStream.flush();
+  P.printVersion(DllName, Major, Minor, DS->getPdbDllVersion());
+
+  if (DumpModules) {
+    ListScope L(P, "Modules");
+    const DbiModuleList &Modules = DS->modules();
+    for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
+      const DbiModuleDescriptor &Modi = Modules.getModuleDescriptor(I);
+      DictScope DD(P);
+      P.printString("Name", Modi.getModuleName().str());
+      P.printNumber("Debug Stream Index", Modi.getModuleStreamIndex());
+      P.printString("Object File Name", Modi.getObjFileName().str());
+      P.printNumber("Num Files", Modi.getNumberOfFiles());
+      P.printNumber("Source File Name Idx", Modi.getSourceFileNameIndex());
+      P.printNumber("Pdb File Name Idx", Modi.getPdbFilePathNameIndex());
+      P.printNumber("Line Info Byte Size", Modi.getC11LineInfoByteSize());
+      P.printNumber("C13 Line Info Byte Size", Modi.getC13LineInfoByteSize());
+      P.printNumber("Symbol Byte Size", Modi.getSymbolDebugInfoByteSize());
+      P.printNumber("Type Server Index", Modi.getTypeServerIndex());
+      P.printBoolean("Has EC Info", Modi.hasECInfo());
+      if (opts::shared::DumpModuleFiles) {
+        std::string FileListName = to_string(Modules.getSourceFileCount(I)) +
+                                   " Contributing Source Files";
+        ListScope LL(P, FileListName);
+        for (auto File : Modules.source_files(I))
+          P.printString(File);
+      }
+      bool HasModuleDI = (Modi.getModuleStreamIndex() < File.getNumStreams());
+      bool ShouldDumpSymbols =
+          (opts::shared::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
+      if (HasModuleDI &&
+          (ShouldDumpSymbols || !opts::shared::DumpModuleSubsections.empty())) {
+        auto ModStreamData = MappedBlockStream::createIndexedStream(
+            File.getMsfLayout(), File.getMsfBuffer(),
+            Modi.getModuleStreamIndex(), File.getAllocator());
+
+        ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
+        if (auto EC = ModS.reload())
+          return EC;
+
+        auto ExpectedTpi = initializeTypeDatabase(StreamTPI);
+        if (!ExpectedTpi)
+          return ExpectedTpi.takeError();
+        auto &Tpi = *ExpectedTpi;
+        if (ShouldDumpSymbols) {
+
+          ListScope SS(P, "Symbols");
+          codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr,
+                                      false);
+          bool HadError = false;
+          for (auto S : ModS.symbols(&HadError)) {
+            DictScope LL(P, "");
+            if (opts::shared::DumpModuleSyms) {
+              if (auto EC = SD.dump(S)) {
+                llvm::consumeError(std::move(EC));
+                HadError = true;
+                break;
+              }
+            }
+            if (opts::raw::DumpSymRecordBytes)
+              P.printBinaryBlock("Bytes", S.content());
+          }
+          if (HadError)
+            return make_error<RawError>(
+                raw_error_code::corrupt_file,
+                "DBI stream contained corrupt symbol record");
+        }
+        if (!opts::shared::DumpModuleSubsections.empty()) {
+          ListScope SS(P, "Subsections");
+          auto ExpectedIpi = initializeTypeDatabase(StreamIPI);
+          if (!ExpectedIpi)
+            return ExpectedIpi.takeError();
+          auto &Ipi = *ExpectedIpi;
+          auto ExpectedStrings = File.getStringTable();
+          if (!ExpectedStrings)
+            return joinErrors(
+                make_error<RawError>(raw_error_code::no_stream,
+                                     "Could not get string table!"),
+                ExpectedStrings.takeError());
+
+          C13RawVisitor V(P, Tpi, Ipi);
+          if (auto EC = codeview::visitDebugSubsections(
+                  ModS.subsections(), V, ExpectedStrings->getStringTable()))
+            return EC;
+        }
+      }
+    }
+  }
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpSectionContribs() {
+  if (!opts::raw::DumpSectionContribs)
+    return Error::success();
+  if (!File.hasPDBDbiStream()) {
+    P.printString("DBI Stream not present");
+    return Error::success();
+  }
+
+  auto Dbi = File.getPDBDbiStream();
+  if (!Dbi)
+    return Dbi.takeError();
+
+  ListScope L(P, "Section Contributions");
+  class Visitor : public ISectionContribVisitor {
+  public:
+    Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {}
+    void visit(const SectionContrib &SC) override {
+      DictScope D(P, "Contribution");
+      P.printNumber("ISect", SC.ISect);
+      P.printNumber("Off", SC.Off);
+      P.printNumber("Size", SC.Size);
+      P.printFlags("Characteristics", SC.Characteristics,
+                   codeview::getImageSectionCharacteristicNames(),
+                   COFF::SectionCharacteristics(0x00F00000));
+      {
+        DictScope DD(P, "Module");
+        P.printNumber("Index", SC.Imod);
+        const DbiModuleList &Modules = DS.modules();
+        if (Modules.getModuleCount() > SC.Imod) {
+          P.printString("Name",
+                        Modules.getModuleDescriptor(SC.Imod).getModuleName());
+        }
+      }
+      P.printNumber("Data CRC", SC.DataCrc);
+      P.printNumber("Reloc CRC", SC.RelocCrc);
+      P.flush();
+    }
+    void visit(const SectionContrib2 &SC) override {
+      visit(SC.Base);
+      P.printNumber("ISect Coff", SC.ISectCoff);
+      P.flush();
+    }
+
+  private:
+    ScopedPrinter &P;
+    DbiStream &DS;
+  };
+  Visitor V(P, *Dbi);
+  Dbi->visitSectionContributions(V);
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpSectionMap() {
+  if (!opts::raw::DumpSectionMap)
+    return Error::success();
+  if (!File.hasPDBDbiStream()) {
+    P.printString("DBI Stream not present");
+    return Error::success();
+  }
+
+  auto Dbi = File.getPDBDbiStream();
+  if (!Dbi)
+    return Dbi.takeError();
+
+  ListScope L(P, "Section Map");
+  for (auto &M : Dbi->getSectionMap()) {
+    DictScope D(P, "Entry");
+    P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
+    P.printNumber("Ovl", M.Ovl);
+    P.printNumber("Group", M.Group);
+    P.printNumber("Frame", M.Frame);
+    P.printNumber("SecName", M.SecName);
+    P.printNumber("ClassName", M.ClassName);
+    P.printNumber("Offset", M.Offset);
+    P.printNumber("SecByteLength", M.SecByteLength);
+    P.flush();
+  }
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpPublicsStream() {
+  if (!opts::raw::DumpPublics)
+    return Error::success();
+  if (!File.hasPDBPublicsStream()) {
+    P.printString("Publics Stream not present");
+    return Error::success();
+  }
+
+  auto Publics = File.getPDBPublicsStream();
+  if (!Publics)
+    return Publics.takeError();
+  DictScope D(P, "Publics Stream");
+
+  auto Dbi = File.getPDBDbiStream();
+  if (!Dbi)
+    return Dbi.takeError();
+
+  P.printNumber("Stream number", Dbi->getPublicSymbolStreamIndex());
+  P.printNumber("SymHash", Publics->getSymHash());
+  P.printNumber("AddrMap", Publics->getAddrMap());
+  P.printNumber("Number of buckets", Publics->getNumBuckets());
+  P.printList("Hash Buckets", Publics->getHashBuckets());
+  P.printList("Address Map", Publics->getAddressMap());
+  P.printList("Thunk Map", Publics->getThunkMap());
+  P.printList("Section Offsets", Publics->getSectionOffsets(),
+              printSectionOffset);
+  ListScope L(P, "Symbols");
+  auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
+  if (!ExpectedTypes)
+    return ExpectedTypes.takeError();
+  auto &Tpi = *ExpectedTypes;
+
+  codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr, false);
+  bool HadError = false;
+  for (auto S : Publics->getSymbols(&HadError)) {
+    DictScope DD(P, "");
+
+    if (auto EC = SD.dump(S)) {
+      HadError = true;
+      break;
+    }
+    if (opts::raw::DumpSymRecordBytes)
+      P.printBinaryBlock("Bytes", S.content());
+  }
+  if (HadError)
+    return make_error<RawError>(
+        raw_error_code::corrupt_file,
+        "Public symbol stream contained corrupt record");
+
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpSectionHeaders() {
+  if (!opts::raw::DumpSectionHeaders)
+    return Error::success();
+  if (!File.hasPDBDbiStream()) {
+    P.printString("DBI Stream not present");
+    return Error::success();
+  }
+
+  auto Dbi = File.getPDBDbiStream();
+  if (!Dbi)
+    return Dbi.takeError();
+
+  ListScope D(P, "Section Headers");
+  for (const object::coff_section &Section : Dbi->getSectionHeaders()) {
+    DictScope DD(P, "");
+
+    // If a name is 8 characters long, there is no NUL character at end.
+    StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name)));
+    P.printString("Name", Name);
+    P.printNumber("Virtual Size", Section.VirtualSize);
+    P.printNumber("Virtual Address", Section.VirtualAddress);
+    P.printNumber("Size of Raw Data", Section.SizeOfRawData);
+    P.printNumber("File Pointer to Raw Data", Section.PointerToRawData);
+    P.printNumber("File Pointer to Relocations", Section.PointerToRelocations);
+    P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers);
+    P.printNumber("Number of Relocations", Section.NumberOfRelocations);
+    P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers);
+    P.printFlags("Characteristics", Section.Characteristics,
+                 getImageSectionCharacteristicNames());
+  }
+  return Error::success();
+}
+
+Error LLVMOutputStyle::dumpFpoStream() {
+  if (!opts::raw::DumpFpo)
+    return Error::success();
+  if (!File.hasPDBDbiStream()) {
+    P.printString("DBI Stream not present");
+    return Error::success();
+  }
+
+  auto Dbi = File.getPDBDbiStream();
+  if (!Dbi)
+    return Dbi.takeError();
+
+  ListScope D(P, "New FPO");
+  for (const object::FpoData &Fpo : Dbi->getFpoRecords()) {
+    DictScope DD(P, "");
+    P.printNumber("Offset", Fpo.Offset);
+    P.printNumber("Size", Fpo.Size);
+    P.printNumber("Number of locals", Fpo.NumLocals);
+    P.printNumber("Number of params", Fpo.NumParams);
+    P.printNumber("Size of Prolog", Fpo.getPrologSize());
+    P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs());
+    P.printBoolean("Has SEH", Fpo.hasSEH());
+    P.printBoolean("Use BP", Fpo.useBP());
+    P.printNumber("Frame Pointer", Fpo.getFP());
+  }
+  return Error::success();
+}
+
+void LLVMOutputStyle::flush() { P.flush(); }

Added: llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/LLVMOutputStyle.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,70 @@
+//===- LLVMOutputStyle.h -------------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H
+
+#include "OutputStyle.h"
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+#include <string>
+
+namespace llvm {
+class BitVector;
+
+namespace codeview {
+class LazyRandomTypeCollection;
+}
+
+namespace pdb {
+class LLVMOutputStyle : public OutputStyle {
+public:
+  LLVMOutputStyle(PDBFile &File);
+
+  Error dump() override;
+
+private:
+  Expected<codeview::LazyRandomTypeCollection &>
+  initializeTypeDatabase(uint32_t SN);
+
+  Error dumpFileHeaders();
+  Error dumpStreamSummary();
+  Error dumpFreePageMap();
+  Error dumpBlockRanges();
+  Error dumpGlobalsStream();
+  Error dumpStreamBytes();
+  Error dumpStreamBlocks();
+  Error dumpStringTable();
+  Error dumpInfoStream();
+  Error dumpTpiStream(uint32_t StreamIdx);
+  Error dumpDbiStream();
+  Error dumpSectionContribs();
+  Error dumpSectionMap();
+  Error dumpPublicsStream();
+  Error dumpSectionHeaders();
+  Error dumpFpoStream();
+
+  void dumpBitVector(StringRef Name, const BitVector &V);
+
+  void flush();
+
+  PDBFile &File;
+  ScopedPrinter P;
+  std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
+  std::unique_ptr<codeview::LazyRandomTypeCollection> IpiTypes;
+  SmallVector<std::string, 32> StreamPurposes;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/LinePrinter.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,145 @@
+//===- LinePrinter.cpp ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LinePrinter.h"
+
+#include "llvm-pdbutil.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/Support/Regex.h"
+
+#include <algorithm>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+namespace {
+bool IsItemExcluded(llvm::StringRef Item,
+                    std::list<llvm::Regex> &IncludeFilters,
+                    std::list<llvm::Regex> &ExcludeFilters) {
+  if (Item.empty())
+    return false;
+
+  auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); };
+
+  // Include takes priority over exclude.  If the user specified include
+  // filters, and none of them include this item, them item is gone.
+  if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred))
+    return true;
+
+  if (any_of(ExcludeFilters, match_pred))
+    return true;
+
+  return false;
+}
+}
+
+using namespace llvm;
+
+LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream)
+    : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor) {
+  SetFilters(ExcludeTypeFilters, opts::pretty::ExcludeTypes.begin(),
+             opts::pretty::ExcludeTypes.end());
+  SetFilters(ExcludeSymbolFilters, opts::pretty::ExcludeSymbols.begin(),
+             opts::pretty::ExcludeSymbols.end());
+  SetFilters(ExcludeCompilandFilters, opts::pretty::ExcludeCompilands.begin(),
+             opts::pretty::ExcludeCompilands.end());
+
+  SetFilters(IncludeTypeFilters, opts::pretty::IncludeTypes.begin(),
+             opts::pretty::IncludeTypes.end());
+  SetFilters(IncludeSymbolFilters, opts::pretty::IncludeSymbols.begin(),
+             opts::pretty::IncludeSymbols.end());
+  SetFilters(IncludeCompilandFilters, opts::pretty::IncludeCompilands.begin(),
+             opts::pretty::IncludeCompilands.end());
+}
+
+void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
+
+void LinePrinter::Unindent() {
+  CurrentIndent = std::max(0, CurrentIndent - IndentSpaces);
+}
+
+void LinePrinter::NewLine() {
+  OS << "\n";
+  OS.indent(CurrentIndent);
+}
+
+bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {
+  if (IsTypeExcluded(Class.getName(), Class.getSize()))
+    return true;
+  if (Class.deepPaddingSize() < opts::pretty::PaddingThreshold)
+    return true;
+  return false;
+}
+
+bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) {
+  if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
+    return true;
+  if (Size < opts::pretty::SizeThreshold)
+    return true;
+  return false;
+}
+
+bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {
+  return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters);
+}
+
+bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) {
+  return IsItemExcluded(CompilandName, IncludeCompilandFilters,
+                        ExcludeCompilandFilters);
+}
+
+WithColor::WithColor(LinePrinter &P, PDB_ColorItem C)
+    : OS(P.OS), UseColor(P.hasColor()) {
+  if (UseColor)
+    applyColor(C);
+}
+
+WithColor::~WithColor() {
+  if (UseColor)
+    OS.resetColor();
+}
+
+void WithColor::applyColor(PDB_ColorItem C) {
+  switch (C) {
+  case PDB_ColorItem::None:
+    OS.resetColor();
+    return;
+  case PDB_ColorItem::Comment:
+    OS.changeColor(raw_ostream::GREEN, false);
+    return;
+  case PDB_ColorItem::Address:
+    OS.changeColor(raw_ostream::YELLOW, /*bold=*/true);
+    return;
+  case PDB_ColorItem::Keyword:
+    OS.changeColor(raw_ostream::MAGENTA, true);
+    return;
+  case PDB_ColorItem::Register:
+  case PDB_ColorItem::Offset:
+    OS.changeColor(raw_ostream::YELLOW, false);
+    return;
+  case PDB_ColorItem::Type:
+    OS.changeColor(raw_ostream::CYAN, true);
+    return;
+  case PDB_ColorItem::Identifier:
+    OS.changeColor(raw_ostream::CYAN, false);
+    return;
+  case PDB_ColorItem::Path:
+    OS.changeColor(raw_ostream::CYAN, false);
+    return;
+  case PDB_ColorItem::Padding:
+  case PDB_ColorItem::SectionHeader:
+    OS.changeColor(raw_ostream::RED, true);
+    return;
+  case PDB_ColorItem::LiteralValue:
+    OS.changeColor(raw_ostream::GREEN, true);
+    return;
+  }
+}

Added: llvm/trunk/tools/llvm-pdbutil/LinePrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/LinePrinter.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/LinePrinter.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/LinePrinter.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,102 @@
+//===- LinePrinter.h ------------------------------------------ *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Regex.h"
+
+#include <list>
+
+namespace llvm {
+namespace pdb {
+
+class ClassLayout;
+
+class LinePrinter {
+  friend class WithColor;
+
+public:
+  LinePrinter(int Indent, bool UseColor, raw_ostream &Stream);
+
+  void Indent();
+  void Unindent();
+  void NewLine();
+
+  bool hasColor() const { return UseColor; }
+  raw_ostream &getStream() { return OS; }
+  int getIndentLevel() const { return CurrentIndent; }
+
+  bool IsClassExcluded(const ClassLayout &Class);
+  bool IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size);
+  bool IsSymbolExcluded(llvm::StringRef SymbolName);
+  bool IsCompilandExcluded(llvm::StringRef CompilandName);
+
+private:
+  template <typename Iter>
+  void SetFilters(std::list<Regex> &List, Iter Begin, Iter End) {
+    List.clear();
+    for (; Begin != End; ++Begin)
+      List.emplace_back(StringRef(*Begin));
+  }
+
+  raw_ostream &OS;
+  int IndentSpaces;
+  int CurrentIndent;
+  bool UseColor;
+
+  std::list<Regex> ExcludeCompilandFilters;
+  std::list<Regex> ExcludeTypeFilters;
+  std::list<Regex> ExcludeSymbolFilters;
+
+  std::list<Regex> IncludeCompilandFilters;
+  std::list<Regex> IncludeTypeFilters;
+  std::list<Regex> IncludeSymbolFilters;
+};
+
+template <class T>
+inline raw_ostream &operator<<(LinePrinter &Printer, const T &Item) {
+  Printer.getStream() << Item;
+  return Printer.getStream();
+}
+
+enum class PDB_ColorItem {
+  None,
+  Address,
+  Type,
+  Comment,
+  Padding,
+  Keyword,
+  Offset,
+  Identifier,
+  Path,
+  SectionHeader,
+  LiteralValue,
+  Register,
+};
+
+class WithColor {
+public:
+  WithColor(LinePrinter &P, PDB_ColorItem C);
+  ~WithColor();
+
+  raw_ostream &get() { return OS; }
+
+private:
+  void applyColor(PDB_ColorItem C);
+  raw_ostream &OS;
+  bool UseColor;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/OutputStyle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/OutputStyle.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/OutputStyle.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/OutputStyle.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,28 @@
+//===- OutputStyle.h ------------------------------------------ *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+
+class OutputStyle {
+public:
+  virtual ~OutputStyle() {}
+
+  virtual Error dump() = 0;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PdbYaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PdbYaml.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PdbYaml.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PdbYaml.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,227 @@
+//===- PdbYAML.cpp -------------------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PdbYaml.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
+#include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+using namespace llvm::pdb::yaml;
+using namespace llvm::yaml;
+
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::pdb::PdbRaw_FeatureSig)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct ScalarTraits<llvm::pdb::PDB_UniqueId> {
+  static void output(const llvm::pdb::PDB_UniqueId &S, void *,
+                     llvm::raw_ostream &OS) {
+    OS << S;
+  }
+
+  static StringRef input(StringRef Scalar, void *Ctx,
+                         llvm::pdb::PDB_UniqueId &S) {
+    if (Scalar.size() != 38)
+      return "GUID strings are 38 characters long";
+    if (Scalar[0] != '{' || Scalar[37] != '}')
+      return "GUID is not enclosed in {}";
+    if (Scalar[9] != '-' || Scalar[14] != '-' || Scalar[19] != '-' ||
+        Scalar[24] != '-')
+      return "GUID sections are not properly delineated with dashes";
+
+    uint8_t *OutBuffer = S.Guid;
+    for (auto Iter = Scalar.begin(); Iter != Scalar.end();) {
+      if (*Iter == '-' || *Iter == '{' || *Iter == '}') {
+        ++Iter;
+        continue;
+      }
+      uint8_t Value = (llvm::hexDigitValue(*Iter) << 4);
+      ++Iter;
+      Value |= llvm::hexDigitValue(*Iter);
+      ++Iter;
+      *OutBuffer++ = Value;
+    }
+
+    return "";
+  }
+
+  static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PDB_Machine> {
+  static void enumeration(IO &io, llvm::pdb::PDB_Machine &Value) {
+    io.enumCase(Value, "Invalid", PDB_Machine::Invalid);
+    io.enumCase(Value, "Am33", PDB_Machine::Am33);
+    io.enumCase(Value, "Amd64", PDB_Machine::Amd64);
+    io.enumCase(Value, "Arm", PDB_Machine::Arm);
+    io.enumCase(Value, "ArmNT", PDB_Machine::ArmNT);
+    io.enumCase(Value, "Ebc", PDB_Machine::Ebc);
+    io.enumCase(Value, "x86", PDB_Machine::x86);
+    io.enumCase(Value, "Ia64", PDB_Machine::Ia64);
+    io.enumCase(Value, "M32R", PDB_Machine::M32R);
+    io.enumCase(Value, "Mips16", PDB_Machine::Mips16);
+    io.enumCase(Value, "MipsFpu", PDB_Machine::MipsFpu);
+    io.enumCase(Value, "MipsFpu16", PDB_Machine::MipsFpu16);
+    io.enumCase(Value, "PowerPCFP", PDB_Machine::PowerPCFP);
+    io.enumCase(Value, "R4000", PDB_Machine::R4000);
+    io.enumCase(Value, "SH3", PDB_Machine::SH3);
+    io.enumCase(Value, "SH3DSP", PDB_Machine::SH3DSP);
+    io.enumCase(Value, "Thumb", PDB_Machine::Thumb);
+    io.enumCase(Value, "WceMipsV2", PDB_Machine::WceMipsV2);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_DbiVer> {
+  static void enumeration(IO &io, llvm::pdb::PdbRaw_DbiVer &Value) {
+    io.enumCase(Value, "V41", llvm::pdb::PdbRaw_DbiVer::PdbDbiVC41);
+    io.enumCase(Value, "V50", llvm::pdb::PdbRaw_DbiVer::PdbDbiV50);
+    io.enumCase(Value, "V60", llvm::pdb::PdbRaw_DbiVer::PdbDbiV60);
+    io.enumCase(Value, "V70", llvm::pdb::PdbRaw_DbiVer::PdbDbiV70);
+    io.enumCase(Value, "V110", llvm::pdb::PdbRaw_DbiVer::PdbDbiV110);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_ImplVer> {
+  static void enumeration(IO &io, llvm::pdb::PdbRaw_ImplVer &Value) {
+    io.enumCase(Value, "VC2", llvm::pdb::PdbRaw_ImplVer::PdbImplVC2);
+    io.enumCase(Value, "VC4", llvm::pdb::PdbRaw_ImplVer::PdbImplVC4);
+    io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_ImplVer::PdbImplVC41);
+    io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_ImplVer::PdbImplVC50);
+    io.enumCase(Value, "VC98", llvm::pdb::PdbRaw_ImplVer::PdbImplVC98);
+    io.enumCase(Value, "VC70Dep", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70Dep);
+    io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70);
+    io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_ImplVer::PdbImplVC80);
+    io.enumCase(Value, "VC110", llvm::pdb::PdbRaw_ImplVer::PdbImplVC110);
+    io.enumCase(Value, "VC140", llvm::pdb::PdbRaw_ImplVer::PdbImplVC140);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_TpiVer> {
+  static void enumeration(IO &io, llvm::pdb::PdbRaw_TpiVer &Value) {
+    io.enumCase(Value, "VC40", llvm::pdb::PdbRaw_TpiVer::PdbTpiV40);
+    io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_TpiVer::PdbTpiV41);
+    io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_TpiVer::PdbTpiV50);
+    io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_TpiVer::PdbTpiV70);
+    io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_TpiVer::PdbTpiV80);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_FeatureSig> {
+  static void enumeration(IO &io, PdbRaw_FeatureSig &Features) {
+    io.enumCase(Features, "MinimalDebugInfo",
+                PdbRaw_FeatureSig::MinimalDebugInfo);
+    io.enumCase(Features, "NoTypeMerge", PdbRaw_FeatureSig::NoTypeMerge);
+    io.enumCase(Features, "VC110", PdbRaw_FeatureSig::VC110);
+    io.enumCase(Features, "VC140", PdbRaw_FeatureSig::VC140);
+  }
+};
+}
+}
+
+void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
+  IO.mapOptional("MSF", Obj.Headers);
+  IO.mapOptional("StreamSizes", Obj.StreamSizes);
+  IO.mapOptional("StreamMap", Obj.StreamMap);
+  IO.mapOptional("StringTable", Obj.StringTable);
+  IO.mapOptional("PdbStream", Obj.PdbStream);
+  IO.mapOptional("DbiStream", Obj.DbiStream);
+  IO.mapOptional("TpiStream", Obj.TpiStream);
+  IO.mapOptional("IpiStream", Obj.IpiStream);
+}
+
+void MappingTraits<MSFHeaders>::mapping(IO &IO, MSFHeaders &Obj) {
+  IO.mapOptional("SuperBlock", Obj.SuperBlock);
+  IO.mapOptional("NumDirectoryBlocks", Obj.NumDirectoryBlocks);
+  IO.mapOptional("DirectoryBlocks", Obj.DirectoryBlocks);
+  IO.mapOptional("NumStreams", Obj.NumStreams);
+  IO.mapOptional("FileSize", Obj.FileSize);
+}
+
+void MappingTraits<msf::SuperBlock>::mapping(IO &IO, msf::SuperBlock &SB) {
+  if (!IO.outputting()) {
+    ::memcpy(SB.MagicBytes, msf::Magic, sizeof(msf::Magic));
+  }
+
+  using u32 = support::ulittle32_t;
+  IO.mapOptional("BlockSize", SB.BlockSize, u32(4096U));
+  IO.mapOptional("FreeBlockMap", SB.FreeBlockMapBlock, u32(0U));
+  IO.mapOptional("NumBlocks", SB.NumBlocks, u32(0U));
+  IO.mapOptional("NumDirectoryBytes", SB.NumDirectoryBytes, u32(0U));
+  IO.mapOptional("Unknown1", SB.Unknown1, u32(0U));
+  IO.mapOptional("BlockMapAddr", SB.BlockMapAddr, u32(0U));
+}
+
+void MappingTraits<StreamBlockList>::mapping(IO &IO, StreamBlockList &SB) {
+  IO.mapRequired("Stream", SB.Blocks);
+}
+
+void MappingTraits<PdbInfoStream>::mapping(IO &IO, PdbInfoStream &Obj) {
+  IO.mapOptional("Age", Obj.Age, 1U);
+  IO.mapOptional("Guid", Obj.Guid);
+  IO.mapOptional("Signature", Obj.Signature, 0U);
+  IO.mapOptional("Features", Obj.Features);
+  IO.mapOptional("Version", Obj.Version, PdbImplVC70);
+}
+
+void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) {
+  IO.mapOptional("VerHeader", Obj.VerHeader, PdbDbiV70);
+  IO.mapOptional("Age", Obj.Age, 1U);
+  IO.mapOptional("BuildNumber", Obj.BuildNumber, uint16_t(0U));
+  IO.mapOptional("PdbDllVersion", Obj.PdbDllVersion, 0U);
+  IO.mapOptional("PdbDllRbld", Obj.PdbDllRbld, uint16_t(0U));
+  IO.mapOptional("Flags", Obj.Flags, uint16_t(1U));
+  IO.mapOptional("MachineType", Obj.MachineType, PDB_Machine::x86);
+  IO.mapOptional("Modules", Obj.ModInfos);
+}
+
+void MappingTraits<PdbTpiStream>::mapping(IO &IO,
+                                          pdb::yaml::PdbTpiStream &Obj) {
+  IO.mapOptional("Version", Obj.Version, PdbTpiV80);
+  IO.mapRequired("Records", Obj.Records);
+}
+
+void MappingTraits<NamedStreamMapping>::mapping(IO &IO,
+                                                NamedStreamMapping &Obj) {
+  IO.mapRequired("Name", Obj.StreamName);
+  IO.mapRequired("StreamNum", Obj.StreamNumber);
+}
+
+void MappingTraits<PdbModiStream>::mapping(IO &IO, PdbModiStream &Obj) {
+  IO.mapOptional("Signature", Obj.Signature, 4U);
+  IO.mapRequired("Records", Obj.Symbols);
+}
+
+void MappingTraits<PdbDbiModuleInfo>::mapping(IO &IO, PdbDbiModuleInfo &Obj) {
+  IO.mapRequired("Module", Obj.Mod);
+  IO.mapOptional("ObjFile", Obj.Obj, Obj.Mod);
+  IO.mapOptional("SourceFiles", Obj.SourceFiles);
+  IO.mapOptional("Subsections", Obj.Subsections);
+  IO.mapOptional("Modi", Obj.Modi);
+}

Added: llvm/trunk/tools/llvm-pdbutil/PdbYaml.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PdbYaml.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PdbYaml.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PdbYaml.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,125 @@
+//===- PdbYAML.h ---------------------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
+
+#include "OutputStyle.h"
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
+#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
+#include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/YAMLTraits.h"
+
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+class DebugStringTableSubsection;
+}
+namespace pdb {
+
+namespace yaml {
+struct SerializationContext;
+
+struct MSFHeaders {
+  msf::SuperBlock SuperBlock;
+  uint32_t NumDirectoryBlocks = 0;
+  std::vector<uint32_t> DirectoryBlocks;
+  uint32_t NumStreams = 0;
+  uint32_t FileSize = 0;
+};
+
+struct StreamBlockList {
+  std::vector<uint32_t> Blocks;
+};
+
+struct NamedStreamMapping {
+  StringRef StreamName;
+  uint32_t StreamNumber;
+};
+
+struct PdbInfoStream {
+  PdbRaw_ImplVer Version = PdbImplVC70;
+  uint32_t Signature = 0;
+  uint32_t Age = 1;
+  PDB_UniqueId Guid;
+  std::vector<PdbRaw_FeatureSig> Features;
+  std::vector<NamedStreamMapping> NamedStreams;
+};
+
+struct PdbModiStream {
+  uint32_t Signature;
+  std::vector<CodeViewYAML::SymbolRecord> Symbols;
+};
+
+struct PdbDbiModuleInfo {
+  StringRef Obj;
+  StringRef Mod;
+  std::vector<StringRef> SourceFiles;
+  std::vector<CodeViewYAML::YAMLDebugSubsection> Subsections;
+  Optional<PdbModiStream> Modi;
+};
+
+struct PdbDbiStream {
+  PdbRaw_DbiVer VerHeader = PdbDbiV70;
+  uint32_t Age = 1;
+  uint16_t BuildNumber = 0;
+  uint32_t PdbDllVersion = 0;
+  uint16_t PdbDllRbld = 0;
+  uint16_t Flags = 1;
+  PDB_Machine MachineType = PDB_Machine::x86;
+
+  std::vector<PdbDbiModuleInfo> ModInfos;
+};
+
+struct PdbTpiStream {
+  PdbRaw_TpiVer Version = PdbTpiV80;
+  std::vector<CodeViewYAML::LeafRecord> Records;
+};
+
+struct PdbObject {
+  explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {}
+
+  Optional<MSFHeaders> Headers;
+  Optional<std::vector<uint32_t>> StreamSizes;
+  Optional<std::vector<StreamBlockList>> StreamMap;
+  Optional<PdbInfoStream> PdbStream;
+  Optional<PdbDbiStream> DbiStream;
+  Optional<PdbTpiStream> TpiStream;
+  Optional<PdbTpiStream> IpiStream;
+
+  Optional<std::vector<StringRef>> StringTable;
+
+  BumpPtrAllocator &Allocator;
+};
+}
+}
+}
+
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbObject)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::MSFHeaders)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(msf::SuperBlock)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::StreamBlockList)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbInfoStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbTpiStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::NamedStreamMapping)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbModiStream)
+LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiModuleInfo)
+
+#endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H

Added: llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,94 @@
+//===- PrettyBuiltinDumper.cpp ---------------------------------- *- C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyBuiltinDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+BuiltinDumper::BuiltinDumper(LinePrinter &P)
+    : PDBSymDumper(false), Printer(P) {}
+
+void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
+  if (Symbol.isConstType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+  if (Symbol.isVolatileType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+  WithColor(Printer, PDB_ColorItem::Type).get() << getTypeName(Symbol);
+}
+
+StringRef BuiltinDumper::getTypeName(const PDBSymbolTypeBuiltin &Symbol) {
+  PDB_BuiltinType Type = Symbol.getBuiltinType();
+  switch (Type) {
+  case PDB_BuiltinType::Float:
+    if (Symbol.getLength() == 4)
+      return "float";
+    return "double";
+  case PDB_BuiltinType::UInt:
+    switch (Symbol.getLength()) {
+    case 8:
+      return "unsigned __int64";
+    case 4:
+      return "unsigned int";
+    case 2:
+      return "unsigned short";
+    case 1:
+      return "unsigned char";
+    default:
+      return "unsigned";
+    }
+  case PDB_BuiltinType::Int:
+    switch (Symbol.getLength()) {
+    case 8:
+      return "__int64";
+    case 4:
+      return "int";
+    case 2:
+      return "short";
+    case 1:
+      return "char";
+    default:
+      return "int";
+    }
+  case PDB_BuiltinType::Char:
+    return "char";
+  case PDB_BuiltinType::WCharT:
+    return "wchar_t";
+  case PDB_BuiltinType::Void:
+    return "void";
+  case PDB_BuiltinType::Long:
+    return "long";
+  case PDB_BuiltinType::ULong:
+    return "unsigned long";
+  case PDB_BuiltinType::Bool:
+    return "bool";
+  case PDB_BuiltinType::Currency:
+    return "CURRENCY";
+  case PDB_BuiltinType::Date:
+    return "DATE";
+  case PDB_BuiltinType::Variant:
+    return "VARIANT";
+  case PDB_BuiltinType::Complex:
+    return "complex";
+  case PDB_BuiltinType::Bitfield:
+    return "bitfield";
+  case PDB_BuiltinType::BSTR:
+    return "BSTR";
+  case PDB_BuiltinType::HResult:
+    return "HRESULT";
+  case PDB_BuiltinType::BCD:
+    return "HRESULT";
+  default:
+    return "void";
+  }
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyBuiltinDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,35 @@
+//===- PrettyBuiltinDumper.h ---------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+class BuiltinDumper : public PDBSymDumper {
+public:
+  BuiltinDumper(LinePrinter &P);
+
+  void start(const PDBSymbolTypeBuiltin &Symbol);
+
+private:
+  StringRef getTypeName(const PDBSymbolTypeBuiltin &Symbol);
+
+  LinePrinter &Printer;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,108 @@
+//===- PrettyClassDefinitionDumper.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyClassDefinitionDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyClassLayoutGraphicalDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
+    : PDBSymDumper(true), Printer(P) {}
+
+void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
+  assert(opts::pretty::ClassFormat !=
+         opts::pretty::ClassDefinitionFormat::None);
+
+  ClassLayout Layout(Class);
+  start(Layout);
+}
+
+void ClassDefinitionDumper::start(const ClassLayout &Layout) {
+  prettyPrintClassIntro(Layout);
+
+  PrettyClassLayoutGraphicalDumper Dumper(Printer, 1, 0);
+  DumpedAnything |= Dumper.start(Layout);
+
+  prettyPrintClassOutro(Layout);
+}
+
+void ClassDefinitionDumper::prettyPrintClassIntro(const ClassLayout &Layout) {
+  DumpedAnything = false;
+  Printer.NewLine();
+
+  uint32_t Size = Layout.getSize();
+  const PDBSymbolTypeUDT &Class = Layout.getClass();
+
+  WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
+  WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
+  WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size
+                                                   << "]";
+  uint32_t BaseCount = Layout.bases().size();
+  if (BaseCount > 0) {
+    Printer.Indent();
+    char NextSeparator = ':';
+    for (auto BC : Layout.bases()) {
+      const auto &Base = BC->getBase();
+      if (Base.isIndirectVirtualBaseClass())
+        continue;
+
+      Printer.NewLine();
+      Printer << NextSeparator << " ";
+      WithColor(Printer, PDB_ColorItem::Keyword).get() << Base.getAccess();
+      if (BC->isVirtualBase())
+        WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
+
+      WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base.getName();
+      NextSeparator = ',';
+    }
+
+    Printer.Unindent();
+  }
+
+  Printer << " {";
+  Printer.Indent();
+}
+
+void ClassDefinitionDumper::prettyPrintClassOutro(const ClassLayout &Layout) {
+  Printer.Unindent();
+  if (DumpedAnything)
+    Printer.NewLine();
+  Printer << "}";
+  Printer.NewLine();
+  if (Layout.deepPaddingSize() > 0) {
+    APFloat Pct(100.0 * (double)Layout.deepPaddingSize() /
+                (double)Layout.getSize());
+    SmallString<8> PctStr;
+    Pct.toString(PctStr, 4);
+    WithColor(Printer, PDB_ColorItem::Padding).get()
+        << "Total padding " << Layout.deepPaddingSize() << " bytes (" << PctStr
+        << "% of class size)";
+    Printer.NewLine();
+    APFloat Pct2(100.0 * (double)Layout.immediatePadding() /
+                 (double)Layout.getSize());
+    PctStr.clear();
+    Pct2.toString(PctStr, 4);
+    WithColor(Printer, PDB_ColorItem::Padding).get()
+        << "Immediate padding " << Layout.immediatePadding() << " bytes ("
+        << PctStr << "% of class size)";
+    Printer.NewLine();
+  }
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,47 @@
+//===- PrettyClassDefinitionDumper.h ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H
+
+#include "llvm/ADT/BitVector.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+
+#include <list>
+#include <memory>
+#include <unordered_map>
+
+namespace llvm {
+class BitVector;
+
+namespace pdb {
+
+class ClassLayout;
+class LinePrinter;
+
+class ClassDefinitionDumper : public PDBSymDumper {
+public:
+  ClassDefinitionDumper(LinePrinter &P);
+
+  void start(const PDBSymbolTypeUDT &Class);
+  void start(const ClassLayout &Class);
+
+private:
+  void prettyPrintClassIntro(const ClassLayout &Class);
+  void prettyPrintClassOutro(const ClassLayout &Class);
+
+  LinePrinter &Printer;
+  bool DumpedAnything = false;
+};
+}
+}
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,216 @@
+//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyClassLayoutGraphicalDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyClassDefinitionDumper.h"
+#include "PrettyEnumDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "PrettyTypedefDumper.h"
+#include "PrettyVariableDumper.h"
+#include "PrettyVariableDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
+    LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)
+    : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),
+      ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}
+
+bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
+
+  if (RecursionLevel == 1 &&
+      opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {
+    for (auto &Other : Layout.other_items())
+      Other->dump(*this);
+    for (auto &Func : Layout.funcs())
+      Func->dump(*this);
+  }
+
+  const BitVector &UseMap = Layout.usedBytes();
+  int NextPaddingByte = UseMap.find_first_unset();
+
+  for (auto &Item : Layout.layout_items()) {
+    // Calculate the absolute offset of the first byte of the next field.
+    uint32_t RelativeOffset = Item->getOffsetInParent();
+    CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
+
+    // Since there is storage there, it should be set!  However, this might
+    // be an empty base, in which case it could extend outside the bounds of
+    // the parent class.
+    if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
+      assert(UseMap.test(RelativeOffset));
+
+      // If there is any remaining padding in this class, and the offset of the
+      // new item is after the padding, then we must have just jumped over some
+      // padding.  Print a padding row and then look for where the next block
+      // of padding begins.
+      if ((NextPaddingByte >= 0) &&
+          (RelativeOffset > uint32_t(NextPaddingByte))) {
+        printPaddingRow(RelativeOffset - NextPaddingByte);
+        NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
+      }
+    }
+
+    CurrentItem = Item;
+    if (Item->isVBPtr()) {
+      VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
+
+      VariableDumper VarDumper(Printer);
+      VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());
+    } else {
+      if (auto Sym = Item->getSymbol())
+        Sym->dump(*this);
+    }
+
+    if (Item->getLayoutSize() > 0) {
+      uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;
+      if (Prev < UseMap.size())
+        NextPaddingByte = UseMap.find_next_unset(Prev);
+    }
+  }
+
+  auto TailPadding = Layout.tailPadding();
+  if (TailPadding > 0) {
+    if (TailPadding != 1 || Layout.getSize() != 1) {
+      Printer.NewLine();
+      WithColor(Printer, PDB_ColorItem::Padding).get()
+          << "<padding> (" << TailPadding << " bytes)";
+      DumpedAnything = true;
+    }
+  }
+
+  return DumpedAnything;
+}
+
+void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
+  if (Amount == 0)
+    return;
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
+                                                   << " bytes)";
+  DumpedAnything = true;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(
+    const PDBSymbolTypeBaseClass &Symbol) {
+  assert(CurrentItem != nullptr);
+
+  Printer.NewLine();
+  BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
+
+  std::string Label = "base";
+  if (Layout.isVirtualBase()) {
+    Label.insert(Label.begin(), 'v');
+    if (Layout.getBase().isIndirectVirtualBaseClass())
+      Label.insert(Label.begin(), 'i');
+  }
+  Printer << Label << " ";
+
+  uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();
+
+  WithColor(Printer, PDB_ColorItem::Offset).get()
+      << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size
+      << "] ";
+
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
+
+  if (shouldRecurse()) {
+    Printer.Indent();
+    uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
+    PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1,
+                                                ChildOffsetZero);
+    DumpedAnything |= BaseDumper.start(Layout);
+    Printer.Unindent();
+  }
+
+  DumpedAnything = true;
+}
+
+bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {
+  uint32_t Limit = opts::pretty::ClassRecursionDepth;
+  if (Limit == 0)
+    return true;
+  return RecursionLevel < Limit;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
+  assert(CurrentItem != nullptr);
+
+  DataMemberLayoutItem &Layout =
+      static_cast<DataMemberLayoutItem &>(*CurrentItem);
+
+  VariableDumper VarDumper(Printer);
+  VarDumper.start(Symbol, ClassOffsetZero);
+
+  if (Layout.hasUDTLayout() && shouldRecurse()) {
+    uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
+    Printer.Indent();
+    PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
+                                                ChildOffsetZero);
+    TypeDumper.start(Layout.getUDTLayout());
+    Printer.Unindent();
+  }
+
+  DumpedAnything = true;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
+  assert(CurrentItem != nullptr);
+
+  VariableDumper VarDumper(Printer);
+  VarDumper.start(Symbol, ClassOffsetZero);
+
+  DumpedAnything = true;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+  DumpedAnything = true;
+  Printer.NewLine();
+  EnumDumper Dumper(Printer);
+  Dumper.start(Symbol);
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(
+    const PDBSymbolTypeTypedef &Symbol) {
+  DumpedAnything = true;
+  Printer.NewLine();
+  TypedefDumper Dumper(Printer);
+  Dumper.start(Symbol);
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(
+    const PDBSymbolTypeBuiltin &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {
+  if (Printer.IsSymbolExcluded(Symbol.getName()))
+    return;
+  if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
+    return;
+  if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
+      !Symbol.isIntroVirtualFunction())
+    return;
+
+  DumpedAnything = true;
+  Printer.NewLine();
+  FunctionDumper Dumper(Printer);
+  Dumper.start(Symbol, FunctionDumper::PointerType::None);
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,58 @@
+//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H
+
+#include "llvm/ADT/BitVector.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+namespace pdb {
+
+class UDTLayoutBase;
+class LayoutItemBase;
+class LinePrinter;
+
+class PrettyClassLayoutGraphicalDumper : public PDBSymDumper {
+public:
+  PrettyClassLayoutGraphicalDumper(LinePrinter &P, uint32_t RecurseLevel,
+                                   uint32_t InitialOffset);
+
+  bool start(const UDTLayoutBase &Layout);
+
+  // Layout based symbol types.
+  void dump(const PDBSymbolTypeBaseClass &Symbol) override;
+  void dump(const PDBSymbolData &Symbol) override;
+  void dump(const PDBSymbolTypeVTable &Symbol) override;
+
+  // Non layout-based symbol types.
+  void dump(const PDBSymbolTypeEnum &Symbol) override;
+  void dump(const PDBSymbolFunc &Symbol) override;
+  void dump(const PDBSymbolTypeTypedef &Symbol) override;
+  void dump(const PDBSymbolTypeUDT &Symbol) override;
+  void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+
+private:
+  bool shouldRecurse() const;
+  void printPaddingRow(uint32_t Amount);
+
+  LinePrinter &Printer;
+
+  LayoutItemBase *CurrentItem = nullptr;
+  uint32_t RecursionLevel = 0;
+  uint32_t ClassOffsetZero = 0;
+  uint32_t CurrentAbsoluteOffset = 0;
+  bool DumpedAnything = false;
+};
+}
+}
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,207 @@
+//===- PrettyCompilandDumper.cpp - llvm-pdbutil compiland dumper -*- C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyCompilandDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyFunctionDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+CompilandDumper::CompilandDumper(LinePrinter &P)
+    : PDBSymDumper(true), Printer(P) {}
+
+void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol) {}
+
+void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol) {}
+
+void CompilandDumper::start(const PDBSymbolCompiland &Symbol,
+                            CompilandDumpFlags opts) {
+  std::string FullName = Symbol.getName();
+  if (Printer.IsCompilandExcluded(FullName))
+    return;
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Path).get() << FullName;
+
+  if (opts & Flags::Lines) {
+    const IPDBSession &Session = Symbol.getSession();
+    auto Files = Session.getSourceFilesForCompiland(Symbol);
+    Printer.Indent();
+    while (auto File = Files->getNext()) {
+      Printer.NewLine();
+      WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName();
+
+      auto Lines = Session.findLineNumbers(Symbol, *File);
+      Printer.Indent();
+      while (auto Line = Lines->getNext()) {
+        Printer.NewLine();
+        uint32_t LineStart = Line->getLineNumber();
+        uint32_t LineEnd = Line->getLineNumberEnd();
+
+        Printer << "Line ";
+        PDB_ColorItem StatementColor = Line->isStatement()
+                                           ? PDB_ColorItem::Keyword
+                                           : PDB_ColorItem::LiteralValue;
+        WithColor(Printer, StatementColor).get() << LineStart;
+        if (LineStart != LineEnd)
+          WithColor(Printer, StatementColor).get() << " - " << LineEnd;
+
+        uint32_t ColumnStart = Line->getColumnNumber();
+        uint32_t ColumnEnd = Line->getColumnNumberEnd();
+        if (ColumnStart != 0 || ColumnEnd != 0) {
+          Printer << ", Column: ";
+          WithColor(Printer, StatementColor).get() << ColumnStart;
+          if (ColumnEnd != ColumnStart)
+            WithColor(Printer, StatementColor).get() << " - " << ColumnEnd;
+        }
+
+        Printer << ", Address: ";
+        if (Line->getLength() > 0) {
+          uint64_t AddrStart = Line->getVirtualAddress();
+          uint64_t AddrEnd = AddrStart + Line->getLength() - 1;
+          WithColor(Printer, PDB_ColorItem::Address).get()
+              << "[" << format_hex(AddrStart, 10) << " - "
+              << format_hex(AddrEnd, 10) << "]";
+          Printer << " (" << Line->getLength() << " bytes)";
+        } else {
+          uint64_t AddrStart = Line->getVirtualAddress();
+          WithColor(Printer, PDB_ColorItem::Address).get()
+              << "[" << format_hex(AddrStart, 10) << "] ";
+          Printer << "(0 bytes)";
+        }
+      }
+      Printer.Unindent();
+    }
+    Printer.Unindent();
+  }
+
+  if (opts & Flags::Children) {
+    auto ChildrenEnum = Symbol.findAllChildren();
+    Printer.Indent();
+    while (auto Child = ChildrenEnum->getNext())
+      Child->dump(*this);
+    Printer.Unindent();
+  }
+}
+
+void CompilandDumper::dump(const PDBSymbolData &Symbol) {
+  if (!shouldDumpSymLevel(opts::pretty::SymLevel::Data))
+    return;
+  if (Printer.IsSymbolExcluded(Symbol.getName()))
+    return;
+
+  Printer.NewLine();
+
+  switch (auto LocType = Symbol.getLocationType()) {
+  case PDB_LocType::Static:
+    Printer << "data: ";
+    WithColor(Printer, PDB_ColorItem::Address).get()
+        << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "]";
+
+    WithColor(Printer, PDB_ColorItem::Comment).get()
+        << " [sizeof = " << getTypeLength(Symbol) << "]";
+
+    break;
+  case PDB_LocType::Constant:
+    Printer << "constant: ";
+    WithColor(Printer, PDB_ColorItem::LiteralValue).get()
+        << "[" << Symbol.getValue() << "]";
+    WithColor(Printer, PDB_ColorItem::Comment).get()
+        << " [sizeof = " << getTypeLength(Symbol) << "]";
+    break;
+  default:
+    Printer << "data(unexpected type=" << LocType << ")";
+  }
+
+  Printer << " ";
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+}
+
+void CompilandDumper::dump(const PDBSymbolFunc &Symbol) {
+  if (!shouldDumpSymLevel(opts::pretty::SymLevel::Functions))
+    return;
+  if (Symbol.getLength() == 0)
+    return;
+  if (Printer.IsSymbolExcluded(Symbol.getName()))
+    return;
+
+  Printer.NewLine();
+  FunctionDumper Dumper(Printer);
+  Dumper.start(Symbol, FunctionDumper::PointerType::None);
+}
+
+void CompilandDumper::dump(const PDBSymbolLabel &Symbol) {
+  if (Printer.IsSymbolExcluded(Symbol.getName()))
+    return;
+
+  Printer.NewLine();
+  Printer << "label ";
+  WithColor(Printer, PDB_ColorItem::Address).get()
+      << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "] ";
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+}
+
+void CompilandDumper::dump(const PDBSymbolThunk &Symbol) {
+  if (!shouldDumpSymLevel(opts::pretty::SymLevel::Thunks))
+    return;
+  if (Printer.IsSymbolExcluded(Symbol.getName()))
+    return;
+
+  Printer.NewLine();
+  Printer << "thunk ";
+  codeview::ThunkOrdinal Ordinal = Symbol.getThunkOrdinal();
+  uint64_t VA = Symbol.getVirtualAddress();
+  if (Ordinal == codeview::ThunkOrdinal::TrampIncremental) {
+    uint64_t Target = Symbol.getTargetVirtualAddress();
+    WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(VA, 10);
+    Printer << " -> ";
+    WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Target, 10);
+  } else {
+    WithColor(Printer, PDB_ColorItem::Address).get()
+        << "[" << format_hex(VA, 10) << " - "
+        << format_hex(VA + Symbol.getLength(), 10) << "]";
+  }
+  Printer << " (";
+  WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
+  Printer << ") ";
+  std::string Name = Symbol.getName();
+  if (!Name.empty())
+    WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
+}
+
+void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol) {}
+
+void CompilandDumper::dump(const PDBSymbolUnknown &Symbol) {
+  Printer.NewLine();
+  Printer << "unknown (" << Symbol.getSymTag() << ")";
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyCompilandDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,44 @@
+//===- PrettyCompilandDumper.h - llvm-pdbutil compiland dumper -*- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCOMPILANDDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCOMPILANDDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+typedef int CompilandDumpFlags;
+class CompilandDumper : public PDBSymDumper {
+public:
+  enum Flags { None = 0x0, Children = 0x1, Symbols = 0x2, Lines = 0x4 };
+
+  CompilandDumper(LinePrinter &P);
+
+  void start(const PDBSymbolCompiland &Symbol, CompilandDumpFlags flags);
+
+  void dump(const PDBSymbolCompilandDetails &Symbol) override;
+  void dump(const PDBSymbolCompilandEnv &Symbol) override;
+  void dump(const PDBSymbolData &Symbol) override;
+  void dump(const PDBSymbolFunc &Symbol) override;
+  void dump(const PDBSymbolLabel &Symbol) override;
+  void dump(const PDBSymbolThunk &Symbol) override;
+  void dump(const PDBSymbolTypeTypedef &Symbol) override;
+  void dump(const PDBSymbolUnknown &Symbol) override;
+
+private:
+  LinePrinter &Printer;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,53 @@
+//===- PrettyEnumDumper.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyEnumDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+EnumDumper::EnumDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) {
+  WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
+  WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+  if (!opts::pretty::NoEnumDefs) {
+    auto BuiltinType = Symbol.getUnderlyingType();
+    if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int ||
+        BuiltinType->getLength() != 4) {
+      Printer << " : ";
+      BuiltinDumper Dumper(Printer);
+      Dumper.start(*BuiltinType);
+    }
+    Printer << " {";
+    Printer.Indent();
+    auto EnumValues = Symbol.findAllChildren<PDBSymbolData>();
+    while (auto EnumValue = EnumValues->getNext()) {
+      if (EnumValue->getDataKind() != PDB_DataKind::Constant)
+        continue;
+      Printer.NewLine();
+      WithColor(Printer, PDB_ColorItem::Identifier).get()
+          << EnumValue->getName();
+      Printer << " = ";
+      WithColor(Printer, PDB_ColorItem::LiteralValue).get()
+          << EnumValue->getValue();
+    }
+    Printer.Unindent();
+    Printer.NewLine();
+    Printer << "}";
+  }
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyEnumDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,31 @@
+//===- PrettyEnumDumper.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYENUMDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYENUMDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+class EnumDumper : public PDBSymDumper {
+public:
+  EnumDumper(LinePrinter &P);
+
+  void start(const PDBSymbolTypeEnum &Symbol);
+
+private:
+  LinePrinter &Printer;
+};
+}
+}
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,41 @@
+//===- PrettyExternalSymbolDumper.cpp -------------------------- *- C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyExternalSymbolDumper.h"
+#include "LinePrinter.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+ExternalSymbolDumper::ExternalSymbolDumper(LinePrinter &P)
+    : PDBSymDumper(true), Printer(P) {}
+
+void ExternalSymbolDumper::start(const PDBSymbolExe &Symbol) {
+  auto Vars = Symbol.findAllChildren<PDBSymbolPublicSymbol>();
+  while (auto Var = Vars->getNext())
+    Var->dump(*this);
+}
+
+void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
+  std::string LinkageName = Symbol.getName();
+  if (Printer.IsSymbolExcluded(LinkageName))
+    return;
+
+  Printer.NewLine();
+  uint64_t Addr = Symbol.getVirtualAddress();
+
+  Printer << "[";
+  WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10);
+  Printer << "] ";
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName;
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyExternalSymbolDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,34 @@
+//===- PrettyExternalSymbolDumper.h --------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYEXTERNALSYMBOLDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYEXTERNALSYMBOLDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+class ExternalSymbolDumper : public PDBSymDumper {
+public:
+  ExternalSymbolDumper(LinePrinter &P);
+
+  void start(const PDBSymbolExe &Symbol);
+
+  void dump(const PDBSymbolPublicSymbol &Symbol) override;
+
+private:
+  LinePrinter &Printer;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,259 @@
+//===- PrettyFunctionDumper.cpp --------------------------------- *- C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyFunctionDumper.h"
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+namespace {
+template <class T>
+void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer,
+                                      FunctionDumper &Dumper) {
+  uint32_t ClassParentId = Symbol.getClassParentId();
+  auto ClassParent =
+      Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
+          ClassParentId);
+  if (!ClassParent)
+    return;
+
+  WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName();
+  Printer << "::";
+}
+}
+
+FunctionDumper::FunctionDumper(LinePrinter &P)
+    : PDBSymDumper(true), Printer(P) {}
+
+void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
+                           const char *Name, PointerType Pointer) {
+  auto ReturnType = Symbol.getReturnType();
+  ReturnType->dump(*this);
+  Printer << " ";
+  uint32_t ClassParentId = Symbol.getClassParentId();
+  auto ClassParent =
+      Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+          ClassParentId);
+
+  PDB_CallingConv CC = Symbol.getCallingConvention();
+  bool ShouldDumpCallingConvention = true;
+  if ((ClassParent && CC == CallingConvention::ThisCall) ||
+      (!ClassParent && CC == CallingConvention::NearStdCall)) {
+    ShouldDumpCallingConvention = false;
+  }
+
+  if (Pointer == PointerType::None) {
+    if (ShouldDumpCallingConvention)
+      WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
+    if (ClassParent) {
+      Printer << "(";
+      WithColor(Printer, PDB_ColorItem::Identifier).get()
+          << ClassParent->getName();
+      Printer << "::)";
+    }
+  } else {
+    Printer << "(";
+    if (ShouldDumpCallingConvention)
+      WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
+    if (ClassParent) {
+      WithColor(Printer, PDB_ColorItem::Identifier).get()
+          << ClassParent->getName();
+      Printer << "::";
+    }
+    if (Pointer == PointerType::Reference)
+      Printer << "&";
+    else
+      Printer << "*";
+    if (Name)
+      WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
+    Printer << ")";
+  }
+
+  Printer << "(";
+  if (auto ChildEnum = Symbol.getArguments()) {
+    uint32_t Index = 0;
+    while (auto Arg = ChildEnum->getNext()) {
+      Arg->dump(*this);
+      if (++Index < ChildEnum->getChildCount())
+        Printer << ", ";
+    }
+  }
+  Printer << ")";
+
+  if (Symbol.isConstType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
+  if (Symbol.isVolatileType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+}
+
+void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
+  uint64_t FuncStart = Symbol.getVirtualAddress();
+  uint64_t FuncEnd = FuncStart + Symbol.getLength();
+
+  Printer << "func [";
+  WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
+  if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
+    uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart;
+    WithColor(Printer, PDB_ColorItem::Offset).get()
+        << formatv("+{0,2}", Prologue);
+  }
+  Printer << " - ";
+  WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
+  if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
+    uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress();
+    WithColor(Printer, PDB_ColorItem::Offset).get()
+        << formatv("-{0,2}", Epilogue);
+  }
+
+  WithColor(Printer, PDB_ColorItem::Comment).get()
+      << formatv(" | sizeof={0,3}", Symbol.getLength());
+  Printer << "] (";
+
+  if (Symbol.hasFramePointer()) {
+    WithColor(Printer, PDB_ColorItem::Register).get()
+        << Symbol.getLocalBasePointerRegisterId();
+  } else {
+    WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
+  }
+  Printer << ") ";
+
+  if (Symbol.isVirtual() || Symbol.isPureVirtual())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
+
+  auto Signature = Symbol.getSignature();
+  if (!Signature) {
+    WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+    if (Pointer == PointerType::Pointer)
+      Printer << "*";
+    else if (Pointer == FunctionDumper::PointerType::Reference)
+      Printer << "&";
+    return;
+  }
+
+  auto ReturnType = Signature->getReturnType();
+  ReturnType->dump(*this);
+  Printer << " ";
+
+  auto ClassParent = Symbol.getClassParent();
+  CallingConvention CC = Signature->getCallingConvention();
+  if (Pointer != FunctionDumper::PointerType::None)
+    Printer << "(";
+
+  if ((ClassParent && CC != CallingConvention::ThisCall) ||
+      (!ClassParent && CC != CallingConvention::NearStdCall)) {
+    WithColor(Printer, PDB_ColorItem::Keyword).get()
+        << Signature->getCallingConvention() << " ";
+  }
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+  if (Pointer != FunctionDumper::PointerType::None) {
+    if (Pointer == PointerType::Pointer)
+      Printer << "*";
+    else if (Pointer == FunctionDumper::PointerType::Reference)
+      Printer << "&";
+    Printer << ")";
+  }
+
+  Printer << "(";
+  if (auto Arguments = Symbol.getArguments()) {
+    uint32_t Index = 0;
+    while (auto Arg = Arguments->getNext()) {
+      auto ArgType = Arg->getType();
+      ArgType->dump(*this);
+      WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
+                                                          << Arg->getName();
+      if (++Index < Arguments->getChildCount())
+        Printer << ", ";
+    }
+  }
+  Printer << ")";
+  if (Symbol.isConstType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
+  if (Symbol.isVolatileType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+  if (Symbol.isPureVirtual())
+    Printer << " = 0";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) {
+  auto ElementType = Symbol.getElementType();
+
+  ElementType->dump(*this);
+  Printer << "[";
+  WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength();
+  Printer << "]";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+  BuiltinDumper Dumper(Printer);
+  Dumper.start(Symbol);
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+  dumpClassParentWithScopeOperator(Symbol, Printer, *this);
+  WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
+  // PDBSymbolTypeFunctionArg is just a shim over the real argument.  Just drill
+  // through to the real thing and dump it.
+  uint32_t TypeId = Symbol.getTypeId();
+  auto Type = Symbol.getSession().getSymbolById(TypeId);
+  if (!Type)
+    return;
+  Type->dump(*this);
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+  dumpClassParentWithScopeOperator(Symbol, Printer, *this);
+  WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {
+  auto PointeeType = Symbol.getPointeeType();
+  if (!PointeeType)
+    return;
+
+  if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
+    FunctionDumper NestedDumper(Printer);
+    PointerType Pointer =
+        Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
+    NestedDumper.start(*FuncSig, nullptr, Pointer);
+  } else {
+    if (Symbol.isConstType())
+      WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+    if (Symbol.isVolatileType())
+      WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+    PointeeType->dump(*this);
+    Printer << (Symbol.isReference() ? "&" : "*");
+  }
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+  WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyFunctionDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,43 @@
+//===- PrettyFunctionDumper.h --------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYFUNCTIONDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYFUNCTIONDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+class LinePrinter;
+
+class FunctionDumper : public PDBSymDumper {
+public:
+  FunctionDumper(LinePrinter &P);
+
+  enum class PointerType { None, Pointer, Reference };
+
+  void start(const PDBSymbolTypeFunctionSig &Symbol, const char *Name,
+             PointerType Pointer);
+  void start(const PDBSymbolFunc &Symbol, PointerType Pointer);
+
+  void dump(const PDBSymbolTypeArray &Symbol) override;
+  void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+  void dump(const PDBSymbolTypeEnum &Symbol) override;
+  void dump(const PDBSymbolTypeFunctionArg &Symbol) override;
+  void dump(const PDBSymbolTypePointer &Symbol) override;
+  void dump(const PDBSymbolTypeTypedef &Symbol) override;
+  void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+private:
+  LinePrinter &Printer;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,255 @@
+//===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyTypeDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "PrettyClassDefinitionDumper.h"
+#include "PrettyEnumDumper.h"
+#include "PrettyTypedefDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+using LayoutPtr = std::unique_ptr<ClassLayout>;
+
+typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);
+
+static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {
+  return S1->getName() < S2->getName();
+}
+
+static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {
+  return S1->getSize() < S2->getSize();
+}
+
+static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {
+  return S1->deepPaddingSize() < S2->deepPaddingSize();
+}
+
+static bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) {
+  double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize();
+  double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize();
+  return Pct1 < Pct2;
+}
+
+static bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) {
+  return S1->immediatePadding() < S2->immediatePadding();
+}
+
+static bool ComparePaddingPctImmediate(const LayoutPtr &S1,
+                                       const LayoutPtr &S2) {
+  double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize();
+  double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize();
+  return Pct1 < Pct2;
+}
+
+static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {
+  switch (Mode) {
+  case opts::pretty::ClassSortMode::Name:
+    return CompareNames;
+  case opts::pretty::ClassSortMode::Size:
+    return CompareSizes;
+  case opts::pretty::ClassSortMode::Padding:
+    return ComparePadding;
+  case opts::pretty::ClassSortMode::PaddingPct:
+    return ComparePaddingPct;
+  case opts::pretty::ClassSortMode::PaddingImmediate:
+    return ComparePaddingImmediate;
+  case opts::pretty::ClassSortMode::PaddingPctImmediate:
+    return ComparePaddingPctImmediate;
+  default:
+    return nullptr;
+  }
+}
+
+template <typename Enumerator>
+static std::vector<std::unique_ptr<ClassLayout>>
+filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,
+                       uint32_t UnfilteredCount) {
+  std::vector<std::unique_ptr<ClassLayout>> Filtered;
+
+  Filtered.reserve(UnfilteredCount);
+  CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);
+
+  if (UnfilteredCount > 10000) {
+    errs() << formatv("Filtering and sorting {0} types", UnfilteredCount);
+    errs().flush();
+  }
+  uint32_t Examined = 0;
+  uint32_t Discarded = 0;
+  while (auto Class = E.getNext()) {
+    ++Examined;
+    if (Examined % 10000 == 0) {
+      errs() << formatv("Examined {0}/{1} items.  {2} items discarded\n",
+                        Examined, UnfilteredCount, Discarded);
+      errs().flush();
+    }
+
+    if (Class->getUnmodifiedTypeId() != 0) {
+      ++Discarded;
+      continue;
+    }
+
+    if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {
+      ++Discarded;
+      continue;
+    }
+
+    auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
+    if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {
+      ++Discarded;
+      continue;
+    }
+    if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) {
+      ++Discarded;
+      continue;
+    }
+
+    Filtered.push_back(std::move(Layout));
+  }
+
+  if (Comp)
+    std::sort(Filtered.begin(), Filtered.end(), Comp);
+  return Filtered;
+}
+
+TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+void TypeDumper::start(const PDBSymbolExe &Exe) {
+  auto Children = Exe.findAllChildren();
+  if (opts::pretty::Enums) {
+    if (auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>()) {
+      Printer.NewLine();
+      WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums";
+      Printer << ": (" << Enums->getChildCount() << " items)";
+      Printer.Indent();
+      while (auto Enum = Enums->getNext())
+        Enum->dump(*this);
+      Printer.Unindent();
+    }
+  }
+
+  if (opts::pretty::Typedefs) {
+    if (auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>()) {
+      Printer.NewLine();
+      WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs";
+      Printer << ": (" << Typedefs->getChildCount() << " items)";
+      Printer.Indent();
+      while (auto Typedef = Typedefs->getNext())
+        Typedef->dump(*this);
+      Printer.Unindent();
+    }
+  }
+
+  if (opts::pretty::Classes) {
+    if (auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>()) {
+      uint32_t All = Classes->getChildCount();
+
+      Printer.NewLine();
+      WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
+
+      bool Precompute = false;
+      Precompute =
+          (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);
+
+      // If we're using no sort mode, then we can start getting immediate output
+      // from the tool by just filtering as we go, rather than processing
+      // everything up front so that we can sort it.  This makes the tool more
+      // responsive.  So only precompute the filtered/sorted set of classes if
+      // necessary due to the specified options.
+      std::vector<LayoutPtr> Filtered;
+      uint32_t Shown = All;
+      if (Precompute) {
+        Filtered = filterAndSortClassDefs(Printer, *Classes, All);
+
+        Shown = Filtered.size();
+      }
+
+      Printer << ": (Showing " << Shown << " items";
+      if (Shown < All)
+        Printer << ", " << (All - Shown) << " filtered";
+      Printer << ")";
+      Printer.Indent();
+
+      // If we pre-computed, iterate the filtered/sorted list, otherwise iterate
+      // the DIA enumerator and filter on the fly.
+      if (Precompute) {
+        for (auto &Class : Filtered)
+          dumpClassLayout(*Class);
+      } else {
+        while (auto Class = Classes->getNext()) {
+          if (Class->getUnmodifiedTypeId() != 0)
+            continue;
+
+          if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))
+            continue;
+
+          auto Layout = llvm::make_unique<ClassLayout>(std::move(Class));
+          if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)
+            continue;
+
+          dumpClassLayout(*Layout);
+        }
+      }
+
+      Printer.Unindent();
+    }
+  }
+}
+
+void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+  assert(opts::pretty::Enums);
+
+  if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
+    return;
+  // Dump member enums when dumping their class definition.
+  if (nullptr != Symbol.getClassParent())
+    return;
+
+  Printer.NewLine();
+  EnumDumper Dumper(Printer);
+  Dumper.start(Symbol);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+  assert(opts::pretty::Typedefs);
+
+  if (Printer.IsTypeExcluded(Symbol.getName(), Symbol.getLength()))
+    return;
+
+  Printer.NewLine();
+  TypedefDumper Dumper(Printer);
+  Dumper.start(Symbol);
+}
+
+void TypeDumper::dumpClassLayout(const ClassLayout &Class) {
+  assert(opts::pretty::Classes);
+
+  if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
+    WithColor(Printer, PDB_ColorItem::Identifier).get() << Class.getName();
+  } else {
+    ClassDefinitionDumper Dumper(Printer);
+    Dumper.start(Class);
+  }
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyTypeDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,36 @@
+//===- PrettyTypeDumper.h - PDBSymDumper implementation for types *- C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+class LinePrinter;
+class ClassLayout;
+
+class TypeDumper : public PDBSymDumper {
+public:
+  TypeDumper(LinePrinter &P);
+
+  void start(const PDBSymbolExe &Exe);
+
+  void dump(const PDBSymbolTypeEnum &Symbol) override;
+  void dump(const PDBSymbolTypeTypedef &Symbol) override;
+
+  void dumpClassLayout(const ClassLayout &Class);
+
+private:
+  LinePrinter &Printer;
+};
+}
+}
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,77 @@
+//===- PrettyTypedefDumper.cpp - PDBSymDumper impl for typedefs -- * C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyTypedefDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+TypedefDumper::TypedefDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) {
+  WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
+  uint32_t TargetId = Symbol.getTypeId();
+  if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
+    TypeSymbol->dump(*this);
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
+                                                      << Symbol.getName();
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {}
+
+void TypedefDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+  BuiltinDumper Dumper(Printer);
+  Dumper.start(Symbol);
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+  WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
+  WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
+}
+
+void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) {
+  if (Symbol.isConstType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+  if (Symbol.isVolatileType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+  auto PointeeType = Symbol.getPointeeType();
+  if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
+    FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer;
+    if (Symbol.isReference())
+      Pointer = FunctionDumper::PointerType::Reference;
+    FunctionDumper NestedDumper(Printer);
+    NestedDumper.start(*FuncSig, nullptr, Pointer);
+  } else {
+    PointeeType->dump(*this);
+    Printer << ((Symbol.isReference()) ? "&" : "*");
+  }
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
+  FunctionDumper Dumper(Printer);
+  Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+  WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
+  WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyTypedefDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,39 @@
+//===- PrettyTypedefDumper.h - llvm-pdbutil typedef dumper ---*- C++ ----*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDEFDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYTYPEDEFDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+namespace pdb {
+
+class LinePrinter;
+
+class TypedefDumper : public PDBSymDumper {
+public:
+  TypedefDumper(LinePrinter &P);
+
+  void start(const PDBSymbolTypeTypedef &Symbol);
+
+  void dump(const PDBSymbolTypeArray &Symbol) override;
+  void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+  void dump(const PDBSymbolTypeEnum &Symbol) override;
+  void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
+  void dump(const PDBSymbolTypePointer &Symbol) override;
+  void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+private:
+  LinePrinter &Printer;
+};
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,220 @@
+//===- PrettyVariableDumper.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyVariableDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyBuiltinDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+VariableDumper::VariableDumper(LinePrinter &P)
+    : PDBSymDumper(true), Printer(P) {}
+
+void VariableDumper::start(const PDBSymbolData &Var, uint32_t Offset) {
+  if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
+    return;
+  if (Printer.IsSymbolExcluded(Var.getName()))
+    return;
+
+  auto VarType = Var.getType();
+
+  uint64_t Length = VarType->getRawSymbol().getLength();
+
+  switch (auto LocType = Var.getLocationType()) {
+  case PDB_LocType::Static:
+    Printer.NewLine();
+    Printer << "data [";
+    WithColor(Printer, PDB_ColorItem::Address).get()
+        << format_hex(Var.getVirtualAddress(), 10);
+    Printer << ", sizeof=" << Length << "] ";
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
+    dumpSymbolTypeAndName(*VarType, Var.getName());
+    break;
+  case PDB_LocType::Constant:
+    if (isa<PDBSymbolTypeEnum>(*VarType))
+      break;
+    Printer.NewLine();
+    Printer << "data [sizeof=" << Length << "] ";
+    dumpSymbolTypeAndName(*VarType, Var.getName());
+    Printer << " = ";
+    WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
+    break;
+  case PDB_LocType::ThisRel:
+    Printer.NewLine();
+    Printer << "data ";
+    WithColor(Printer, PDB_ColorItem::Offset).get()
+        << "+" << format_hex(Offset + Var.getOffset(), 4)
+        << " [sizeof=" << Length << "] ";
+    dumpSymbolTypeAndName(*VarType, Var.getName());
+    break;
+  case PDB_LocType::BitField:
+    Printer.NewLine();
+    Printer << "data ";
+    WithColor(Printer, PDB_ColorItem::Offset).get()
+        << "+" << format_hex(Offset + Var.getOffset(), 4)
+        << " [sizeof=" << Length << "] ";
+    dumpSymbolTypeAndName(*VarType, Var.getName());
+    Printer << " : ";
+    WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
+    break;
+  default:
+    Printer.NewLine();
+    Printer << "data [sizeof=" << Length << "] ";
+    Printer << "unknown(" << LocType << ") ";
+    WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
+    break;
+  }
+}
+
+void VariableDumper::startVbptr(uint32_t Offset, uint32_t Size) {
+  Printer.NewLine();
+  Printer << "vbptr ";
+
+  WithColor(Printer, PDB_ColorItem::Offset).get()
+      << "+" << format_hex(Offset, 4) << " [sizeof=" << Size << "] ";
+}
+
+void VariableDumper::start(const PDBSymbolTypeVTable &Var, uint32_t Offset) {
+  Printer.NewLine();
+  Printer << "vfptr ";
+  auto VTableType = cast<PDBSymbolTypePointer>(Var.getType());
+  uint32_t PointerSize = VTableType->getLength();
+
+  WithColor(Printer, PDB_ColorItem::Offset).get()
+      << "+" << format_hex(Offset + Var.getOffset(), 4)
+      << " [sizeof=" << PointerSize << "] ";
+}
+
+void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) {
+  auto ElementType = Symbol.getElementType();
+  assert(ElementType);
+  if (!ElementType)
+    return;
+  ElementType->dump(*this);
+}
+
+void VariableDumper::dumpRight(const PDBSymbolTypeArray &Symbol) {
+  auto ElementType = Symbol.getElementType();
+  assert(ElementType);
+  if (!ElementType)
+    return;
+  Printer << '[' << Symbol.getCount() << ']';
+  ElementType->dumpRight(*this);
+}
+
+void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+  BuiltinDumper Dumper(Printer);
+  Dumper.start(Symbol);
+}
+
+void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+  WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
+  auto ReturnType = Symbol.getReturnType();
+  ReturnType->dump(*this);
+  Printer << " ";
+
+  uint32_t ClassParentId = Symbol.getClassParentId();
+  auto ClassParent =
+      Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+          ClassParentId);
+
+  if (ClassParent) {
+    WithColor(Printer, PDB_ColorItem::Identifier).get()
+      << ClassParent->getName();
+    Printer << "::";
+  }
+}
+
+void VariableDumper::dumpRight(const PDBSymbolTypeFunctionSig &Symbol) {
+  Printer << "(";
+  if (auto Arguments = Symbol.getArguments()) {
+    uint32_t Index = 0;
+    while (auto Arg = Arguments->getNext()) {
+      Arg->dump(*this);
+      if (++Index < Arguments->getChildCount())
+        Printer << ", ";
+    }
+  }
+  Printer << ")";
+
+  if (Symbol.isConstType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
+  if (Symbol.isVolatileType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+}
+
+void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) {
+  auto PointeeType = Symbol.getPointeeType();
+  if (!PointeeType)
+    return;
+  PointeeType->dump(*this);
+  if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
+    // A hack to get the calling convention in the right spot.
+    Printer << " (";
+    PDB_CallingConv CC = FuncSig->getCallingConvention();
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
+  } else if (isa<PDBSymbolTypeArray>(PointeeType)) {
+    Printer << " (";
+  }
+  Printer << (Symbol.isReference() ? "&" : "*");
+  if (Symbol.isConstType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " const ";
+  if (Symbol.isVolatileType())
+    WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile ";
+}
+
+void VariableDumper::dumpRight(const PDBSymbolTypePointer &Symbol) {
+  auto PointeeType = Symbol.getPointeeType();
+  assert(PointeeType);
+  if (!PointeeType)
+    return;
+  if (isa<PDBSymbolTypeFunctionSig>(PointeeType) ||
+      isa<PDBSymbolTypeArray>(PointeeType)) {
+    Printer << ")";
+  }
+  PointeeType->dumpRight(*this);
+}
+
+void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+  WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
+  WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+  WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type,
+                                           StringRef Name) {
+  Type.dump(*this);
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name;
+  Type.dumpRight(*this);
+}

Added: llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/PrettyVariableDumper.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,50 @@
+//===- PrettyVariableDumper.h - PDBSymDumper variable dumper ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYVARIABLEDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYVARIABLEDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class StringRef;
+
+namespace pdb {
+
+class LinePrinter;
+
+class VariableDumper : public PDBSymDumper {
+public:
+  VariableDumper(LinePrinter &P);
+
+  void start(const PDBSymbolData &Var, uint32_t Offset = 0);
+  void start(const PDBSymbolTypeVTable &Var, uint32_t Offset = 0);
+  void startVbptr(uint32_t Offset, uint32_t Size);
+
+  void dump(const PDBSymbolTypeArray &Symbol) override;
+  void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+  void dump(const PDBSymbolTypeEnum &Symbol) override;
+  void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
+  void dump(const PDBSymbolTypePointer &Symbol) override;
+  void dump(const PDBSymbolTypeTypedef &Symbol) override;
+  void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+  void dumpRight(const PDBSymbolTypeArray &Symbol) override;
+  void dumpRight(const PDBSymbolTypeFunctionSig &Symbol) override;
+  void dumpRight(const PDBSymbolTypePointer &Symbol) override;
+
+private:
+  void dumpSymbolTypeAndName(const PDBSymbol &Type, StringRef Name);
+
+  LinePrinter &Printer;
+};
+}
+}
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/StreamUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/StreamUtil.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/StreamUtil.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/StreamUtil.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,139 @@
+//===- StreamUtil.cpp - PDB stream utilities --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StreamUtil.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+namespace llvm {
+namespace pdb {
+void discoverStreamPurposes(PDBFile &File,
+                            SmallVectorImpl<std::string> &Purposes) {
+
+  // It's OK if we fail to load some of these streams, we still attempt to print
+  // what we can.
+  auto Dbi = File.getPDBDbiStream();
+  auto Tpi = File.getPDBTpiStream();
+  auto Ipi = File.getPDBIpiStream();
+  auto Info = File.getPDBInfoStream();
+
+  uint32_t StreamCount = File.getNumStreams();
+  DenseMap<uint16_t, DbiModuleDescriptor> 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();
+      if (SN != kInvalidStreamIndex)
+        ModStreams[SN] = Descriptor;
+    }
+  }
+  if (Info) {
+    for (auto &NSE : Info->named_streams()) {
+      if (NSE.second != kInvalidStreamIndex)
+        NamedStreams[NSE.second] = NSE.first();
+    }
+  }
+
+  Purposes.resize(StreamCount);
+  for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+    std::string Value;
+    if (StreamIdx == OldMSFDirectory)
+      Value = "Old MSF Directory";
+    else if (StreamIdx == StreamPDB)
+      Value = "PDB Stream";
+    else if (StreamIdx == StreamDBI)
+      Value = "DBI Stream";
+    else if (StreamIdx == StreamTPI)
+      Value = "TPI Stream";
+    else if (StreamIdx == StreamIPI)
+      Value = "IPI Stream";
+    else if (Dbi && StreamIdx == Dbi->getGlobalSymbolStreamIndex())
+      Value = "Global Symbol Hash";
+    else if (Dbi && StreamIdx == Dbi->getPublicSymbolStreamIndex())
+      Value = "Public Symbol Hash";
+    else if (Dbi && StreamIdx == Dbi->getSymRecordStreamIndex())
+      Value = "Public Symbol Records";
+    else if (Tpi && StreamIdx == Tpi->getTypeHashStreamIndex())
+      Value = "TPI Hash";
+    else if (Tpi && StreamIdx == Tpi->getTypeHashStreamAuxIndex())
+      Value = "TPI Aux Hash";
+    else if (Ipi && StreamIdx == Ipi->getTypeHashStreamIndex())
+      Value = "IPI Hash";
+    else if (Ipi && StreamIdx == Ipi->getTypeHashStreamAuxIndex())
+      Value = "IPI Aux Hash";
+    else if (Dbi &&
+             StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Exception))
+      Value = "Exception Data";
+    else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Fixup))
+      Value = "Fixup Data";
+    else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::FPO))
+      Value = "FPO Data";
+    else if (Dbi &&
+             StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::NewFPO))
+      Value = "New FPO Data";
+    else if (Dbi &&
+             StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapFromSrc))
+      Value = "Omap From Source Data";
+    else if (Dbi &&
+             StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::OmapToSrc))
+      Value = "Omap To Source Data";
+    else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Pdata))
+      Value = "Pdata";
+    else if (Dbi &&
+             StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdr))
+      Value = "Section Header Data";
+    else if (Dbi &&
+             StreamIdx ==
+                 Dbi->getDebugStreamIndex(DbgHeaderType::SectionHdrOrig))
+      Value = "Section Header Original Data";
+    else if (Dbi &&
+             StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::TokenRidMap))
+      Value = "Token Rid Data";
+    else if (Dbi && StreamIdx == Dbi->getDebugStreamIndex(DbgHeaderType::Xdata))
+      Value = "Xdata";
+    else {
+      auto ModIter = ModStreams.find(StreamIdx);
+      auto NSIter = NamedStreams.find(StreamIdx);
+      if (ModIter != ModStreams.end()) {
+        Value = "Module \"";
+        Value += ModIter->second.getModuleName();
+        Value += "\"";
+      } else if (NSIter != NamedStreams.end()) {
+        Value = "Named Stream \"";
+        Value += NSIter->second;
+        Value += "\"";
+      } else {
+        Value = "???";
+      }
+    }
+    Purposes[StreamIdx] = Value;
+  }
+
+  // Consume errors from missing streams.
+  if (!Dbi)
+    consumeError(Dbi.takeError());
+  if (!Tpi)
+    consumeError(Tpi.takeError());
+  if (!Ipi)
+    consumeError(Ipi.takeError());
+  if (!Info)
+    consumeError(Info.takeError());
+}
+}
+}

Added: llvm/trunk/tools/llvm-pdbutil/StreamUtil.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/StreamUtil.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/StreamUtil.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/StreamUtil.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,25 @@
+//===- Streamutil.h - PDB stream utilities ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
+#define LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
+
+#include "llvm/ADT/SmallVector.h"
+
+#include <string>
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+void discoverStreamPurposes(PDBFile &File,
+                            SmallVectorImpl<std::string> &Purposes);
+}
+}
+
+#endif

Added: llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,317 @@
+//===- YAMLOutputStyle.cpp ------------------------------------ *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "YAMLOutputStyle.h"
+
+#include "PdbYaml.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)
+    : File(File), Out(outs()), Obj(File.getAllocator()) {
+  Out.setWriteDefaultValues(!opts::pdb2yaml::Minimal);
+}
+
+Error YAMLOutputStyle::dump() {
+  if (opts::pdb2yaml::StreamDirectory)
+    opts::pdb2yaml::StreamMetadata = true;
+
+  if (auto EC = dumpFileHeaders())
+    return EC;
+
+  if (auto EC = dumpStreamMetadata())
+    return EC;
+
+  if (auto EC = dumpStreamDirectory())
+    return EC;
+
+  if (auto EC = dumpStringTable())
+    return EC;
+
+  if (auto EC = dumpPDBStream())
+    return EC;
+
+  if (auto EC = dumpDbiStream())
+    return EC;
+
+  if (auto EC = dumpTpiStream())
+    return EC;
+
+  if (auto EC = dumpIpiStream())
+    return EC;
+
+  flush();
+  return Error::success();
+}
+
+
+Error YAMLOutputStyle::dumpFileHeaders() {
+  if (opts::pdb2yaml::NoFileHeaders)
+    return Error::success();
+
+  yaml::MSFHeaders Headers;
+  Obj.Headers.emplace();
+  Obj.Headers->SuperBlock.NumBlocks = File.getBlockCount();
+  Obj.Headers->SuperBlock.BlockMapAddr = File.getBlockMapIndex();
+  Obj.Headers->SuperBlock.BlockSize = File.getBlockSize();
+  auto Blocks = File.getDirectoryBlockArray();
+  Obj.Headers->DirectoryBlocks.assign(Blocks.begin(), Blocks.end());
+  Obj.Headers->NumDirectoryBlocks = File.getNumDirectoryBlocks();
+  Obj.Headers->SuperBlock.NumDirectoryBytes = File.getNumDirectoryBytes();
+  Obj.Headers->NumStreams =
+      opts::pdb2yaml::StreamMetadata ? File.getNumStreams() : 0;
+  Obj.Headers->SuperBlock.FreeBlockMapBlock = File.getFreeBlockMapBlock();
+  Obj.Headers->SuperBlock.Unknown1 = File.getUnknown1();
+  Obj.Headers->FileSize = File.getFileSize();
+
+  return Error::success();
+}
+
+Error YAMLOutputStyle::dumpStringTable() {
+  bool RequiresStringTable = opts::shared::DumpModuleFiles ||
+                             !opts::shared::DumpModuleSubsections.empty();
+  bool RequestedStringTable = opts::pdb2yaml::StringTable;
+  if (!RequiresStringTable && !RequestedStringTable)
+    return Error::success();
+
+  auto ExpectedST = File.getStringTable();
+  if (!ExpectedST)
+    return ExpectedST.takeError();
+
+  Obj.StringTable.emplace();
+  const auto &ST = ExpectedST.get();
+  for (auto ID : ST.name_ids()) {
+    auto S = ST.getStringForID(ID);
+    if (!S)
+      return S.takeError();
+    if (S->empty())
+      continue;
+    Obj.StringTable->push_back(*S);
+  }
+  return Error::success();
+}
+
+Error YAMLOutputStyle::dumpStreamMetadata() {
+  if (!opts::pdb2yaml::StreamMetadata)
+    return Error::success();
+
+  Obj.StreamSizes.emplace();
+  Obj.StreamSizes->assign(File.getStreamSizes().begin(),
+                          File.getStreamSizes().end());
+  return Error::success();
+}
+
+Error YAMLOutputStyle::dumpStreamDirectory() {
+  if (!opts::pdb2yaml::StreamDirectory)
+    return Error::success();
+
+  auto StreamMap = File.getStreamMap();
+  Obj.StreamMap.emplace();
+  for (auto &Stream : StreamMap) {
+    pdb::yaml::StreamBlockList BlockList;
+    BlockList.Blocks.assign(Stream.begin(), Stream.end());
+    Obj.StreamMap->push_back(BlockList);
+  }
+
+  return Error::success();
+}
+
+Error YAMLOutputStyle::dumpPDBStream() {
+  if (!opts::pdb2yaml::PdbStream)
+    return Error::success();
+
+  auto IS = File.getPDBInfoStream();
+  if (!IS)
+    return IS.takeError();
+
+  auto &InfoS = IS.get();
+  Obj.PdbStream.emplace();
+  Obj.PdbStream->Age = InfoS.getAge();
+  Obj.PdbStream->Guid = InfoS.getGuid();
+  Obj.PdbStream->Signature = InfoS.getSignature();
+  Obj.PdbStream->Version = InfoS.getVersion();
+  Obj.PdbStream->Features = InfoS.getFeatureSignatures();
+
+  return Error::success();
+}
+
+static opts::ModuleSubsection convertSubsectionKind(DebugSubsectionKind K) {
+  switch (K) {
+  case DebugSubsectionKind::CrossScopeExports:
+    return opts::ModuleSubsection::CrossScopeExports;
+  case DebugSubsectionKind::CrossScopeImports:
+    return opts::ModuleSubsection::CrossScopeImports;
+  case DebugSubsectionKind::FileChecksums:
+    return opts::ModuleSubsection::FileChecksums;
+  case DebugSubsectionKind::InlineeLines:
+    return opts::ModuleSubsection::InlineeLines;
+  case DebugSubsectionKind::Lines:
+    return opts::ModuleSubsection::Lines;
+  case DebugSubsectionKind::Symbols:
+    return opts::ModuleSubsection::Symbols;
+  case DebugSubsectionKind::StringTable:
+    return opts::ModuleSubsection::StringTable;
+  case DebugSubsectionKind::FrameData:
+    return opts::ModuleSubsection::FrameData;
+  default:
+    return opts::ModuleSubsection::Unknown;
+  }
+  llvm_unreachable("Unreachable!");
+}
+
+Error YAMLOutputStyle::dumpDbiStream() {
+  if (!opts::pdb2yaml::DbiStream)
+    return Error::success();
+
+  auto DbiS = File.getPDBDbiStream();
+  if (!DbiS)
+    return DbiS.takeError();
+
+  auto &DS = DbiS.get();
+  Obj.DbiStream.emplace();
+  Obj.DbiStream->Age = DS.getAge();
+  Obj.DbiStream->BuildNumber = DS.getBuildNumber();
+  Obj.DbiStream->Flags = DS.getFlags();
+  Obj.DbiStream->MachineType = DS.getMachineType();
+  Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld();
+  Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();
+  Obj.DbiStream->VerHeader = DS.getDbiVersion();
+  if (opts::shared::DumpModules) {
+    const auto &Modules = DS.modules();
+    for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
+      DbiModuleDescriptor MI = Modules.getModuleDescriptor(I);
+
+      Obj.DbiStream->ModInfos.emplace_back();
+      yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back();
+
+      DMI.Mod = MI.getModuleName();
+      DMI.Obj = MI.getObjFileName();
+      if (opts::shared::DumpModuleFiles) {
+        auto Files = Modules.source_files(I);
+        DMI.SourceFiles.assign(Files.begin(), Files.end());
+      }
+
+      uint16_t ModiStream = MI.getModuleStreamIndex();
+      if (ModiStream == kInvalidStreamIndex)
+        continue;
+
+      auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
+          File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
+          File.getAllocator());
+
+      pdb::ModuleDebugStreamRef ModS(MI, std::move(ModStreamData));
+      if (auto EC = ModS.reload())
+        return EC;
+
+      auto ExpectedST = File.getStringTable();
+      if (!ExpectedST)
+        return ExpectedST.takeError();
+      if (!opts::shared::DumpModuleSubsections.empty() &&
+          ModS.hasDebugSubsections()) {
+        auto ExpectedChecksums = ModS.findChecksumsSubsection();
+        if (!ExpectedChecksums)
+          return ExpectedChecksums.takeError();
+
+        for (const auto &SS : ModS.subsections()) {
+          opts::ModuleSubsection OptionKind = convertSubsectionKind(SS.kind());
+          if (!opts::checkModuleSubsection(OptionKind))
+            continue;
+
+          auto Converted =
+              CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection(
+                  ExpectedST->getStringTable(), *ExpectedChecksums, SS);
+          if (!Converted)
+            return Converted.takeError();
+          DMI.Subsections.push_back(*Converted);
+        }
+      }
+
+      if (opts::shared::DumpModuleSyms) {
+        DMI.Modi.emplace();
+
+        DMI.Modi->Signature = ModS.signature();
+        bool HadError = false;
+        for (auto &Sym : ModS.symbols(&HadError)) {
+          auto ES = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
+          if (!ES)
+            return ES.takeError();
+
+          DMI.Modi->Symbols.push_back(*ES);
+        }
+      }
+    }
+  }
+  return Error::success();
+}
+
+Error YAMLOutputStyle::dumpTpiStream() {
+  if (!opts::pdb2yaml::TpiStream)
+    return Error::success();
+
+  auto TpiS = File.getPDBTpiStream();
+  if (!TpiS)
+    return TpiS.takeError();
+
+  auto &TS = TpiS.get();
+  Obj.TpiStream.emplace();
+  Obj.TpiStream->Version = TS.getTpiVersion();
+  for (auto &Record : TS.types(nullptr)) {
+    auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record);
+    if (!ExpectedRecord)
+      return ExpectedRecord.takeError();
+    Obj.TpiStream->Records.push_back(*ExpectedRecord);
+  }
+
+  return Error::success();
+}
+
+Error YAMLOutputStyle::dumpIpiStream() {
+  if (!opts::pdb2yaml::IpiStream)
+    return Error::success();
+
+  auto IpiS = File.getPDBIpiStream();
+  if (!IpiS)
+    return IpiS.takeError();
+
+  auto &IS = IpiS.get();
+  Obj.IpiStream.emplace();
+  Obj.IpiStream->Version = IS.getTpiVersion();
+  for (auto &Record : IS.types(nullptr)) {
+    auto ExpectedRecord = CodeViewYAML::LeafRecord::fromCodeViewRecord(Record);
+    if (!ExpectedRecord)
+      return ExpectedRecord.takeError();
+
+    Obj.IpiStream->Records.push_back(*ExpectedRecord);
+  }
+
+  return Error::success();
+}
+
+void YAMLOutputStyle::flush() {
+  Out << Obj;
+  outs().flush();
+}

Added: llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/YAMLOutputStyle.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,49 @@
+//===- YAMLOutputStyle.h -------------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H
+
+#include "OutputStyle.h"
+#include "PdbYaml.h"
+
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/YAMLTraits.h"
+
+namespace llvm {
+namespace pdb {
+class ModuleDebugStreamRef;
+
+class YAMLOutputStyle : public OutputStyle {
+public:
+  YAMLOutputStyle(PDBFile &File);
+
+  Error dump() override;
+
+private:
+  Error dumpStringTable();
+  Error dumpFileHeaders();
+  Error dumpStreamMetadata();
+  Error dumpStreamDirectory();
+  Error dumpPDBStream();
+  Error dumpDbiStream();
+  Error dumpTpiStream();
+  Error dumpIpiStream();
+
+  void flush();
+
+  PDBFile &File;
+  llvm::yaml::Output Out;
+
+  yaml::PdbObject Obj;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVMPDBDUMP_YAMLOUTPUTSTYLE_H

Added: llvm/trunk/tools/llvm-pdbutil/fuzzer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/fuzzer/CMakeLists.txt?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/fuzzer/CMakeLists.txt (added)
+++ llvm/trunk/tools/llvm-pdbutil/fuzzer/CMakeLists.txt Fri Jun  9 15:46:17 2017
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+  DebugInfoCodeView
+  DebugInfoPDB
+  Object
+  Support
+  )
+
+add_llvm_executable(llvm-pdbutil-fuzzer
+  EXCLUDE_FROM_ALL
+  llvm-pdbutil-fuzzer.cpp
+  )
+
+target_link_libraries(llvm-pdbutil-fuzzer
+  LLVMFuzzer
+  )

Added: llvm/trunk/tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/fuzzer/llvm-pdbutil-fuzzer.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,105 @@
+//===-- llvm-pdbutil-fuzzer.cpp - Fuzz the llvm-pdbutil tool --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file implements a function that runs llvm-pdbutil
+///  on a single input. This function is then linked into the Fuzzer library.
+///
+//===----------------------------------------------------------------------===//
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/BinaryByteStream.h"
+#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
+#include "llvm/DebugInfo/CodeView/TypeDumper.h"
+#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h"
+#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Raw/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+
+namespace {
+// We need a class which behaves like an immutable BinaryByteStream, but whose
+// data
+// is backed by an llvm::MemoryBuffer.  It also needs to own the underlying
+// MemoryBuffer, so this simple adapter is a good way to achieve that.
+class InputByteStream : public codeview::BinaryByteStream<false> {
+public:
+  explicit InputByteStream(std::unique_ptr<MemoryBuffer> Buffer)
+      : BinaryByteStream(ArrayRef<uint8_t>(Buffer->getBuffer().bytes_begin(),
+                                           Buffer->getBuffer().bytes_end())),
+        MemBuffer(std::move(Buffer)) {}
+
+  std::unique_ptr<MemoryBuffer> MemBuffer;
+};
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+  std::unique_ptr<MemoryBuffer> Buff = MemoryBuffer::getMemBuffer(
+      StringRef((const char *)data, size), "", false);
+
+  ScopedPrinter P(nulls());
+  codeview::CVTypeDumper TD(&P, false);
+
+  auto InputStream = llvm::make_unique<InputByteStream>(std::move(Buff));
+  std::unique_ptr<pdb::PDBFile> File(new pdb::PDBFile(std::move(InputStream)));
+  if (auto E = File->parseFileHeaders()) {
+    consumeError(std::move(E));
+    return 0;
+  }
+  if (auto E = File->parseStreamData()) {
+    consumeError(std::move(E));
+    return 0;
+  }
+
+  auto DbiS = File->getPDBDbiStream();
+  if (auto E = DbiS.takeError()) {
+    consumeError(std::move(E));
+    return 0;
+  }
+  auto TpiS = File->getPDBTpiStream();
+  if (auto E = TpiS.takeError()) {
+    consumeError(std::move(E));
+    return 0;
+  }
+  auto IpiS = File->getPDBIpiStream();
+  if (auto E = IpiS.takeError()) {
+    consumeError(std::move(E));
+    return 0;
+  }
+  auto InfoS = File->getPDBInfoStream();
+  if (auto E = InfoS.takeError()) {
+    consumeError(std::move(E));
+    return 0;
+  }
+  pdb::DbiStream &DS = DbiS.get();
+
+  for (auto &Modi : DS.modules()) {
+    auto ModStreamData = pdb::MappedBlockStream::createIndexedStream(
+        Modi.Info.getModuleStreamIndex(), *File, File->getAllocator());
+    if (!ModStreamData) {
+      consumeError(ModStreamData.takeError());
+      return 0;
+    }
+    pdb::ModuleDebugStreamRef ModS(Modi.Info, std::move(*ModStreamData));
+    if (auto E = ModS.reload()) {
+      consumeError(std::move(E));
+      return 0;
+    }
+    codeview::CVSymbolDumper SD(P, TD, nullptr, false);
+    bool HadError = false;
+    for (auto &S : ModS.symbols(&HadError)) {
+      SD.dump(S);
+    }
+  }
+  return 0;
+}

Added: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp (added)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp Fri Jun  9 15:46:17 2017
@@ -0,0 +1,1023 @@
+//===- llvm-pdbutil.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Dumps debug information present in PDB files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-pdbutil.h"
+
+#include "Analyze.h"
+#include "Diff.h"
+#include "LLVMOutputStyle.h"
+#include "LinePrinter.h"
+#include "OutputStyle.h"
+#include "PrettyCompilandDumper.h"
+#include "PrettyExternalSymbolDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "PrettyTypeDumper.h"
+#include "PrettyVariableDumper.h"
+#include "YAMLOutputStyle.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/DebugInfo/PDB/GenericError.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/COM.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+namespace opts {
+
+cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file");
+cl::SubCommand
+    PrettySubcommand("pretty",
+                     "Dump semantic information about types and symbols");
+
+cl::SubCommand DiffSubcommand("diff", "Diff the contents of 2 PDB files");
+
+cl::SubCommand
+    YamlToPdbSubcommand("yaml2pdb",
+                        "Generate a PDB file from a YAML description");
+cl::SubCommand
+    PdbToYamlSubcommand("pdb2yaml",
+                        "Generate a detailed YAML description of a PDB File");
+
+cl::SubCommand
+    AnalyzeSubcommand("analyze",
+                      "Analyze various aspects of a PDB's structure");
+
+cl::SubCommand MergeSubcommand("merge",
+                               "Merge multiple PDBs into a single PDB");
+
+cl::OptionCategory TypeCategory("Symbol Type Options");
+cl::OptionCategory FilterCategory("Filtering and Sorting Options");
+cl::OptionCategory OtherOptions("Other Options");
+
+namespace pretty {
+cl::list<std::string> InputFilenames(cl::Positional,
+                                     cl::desc("<input PDB files>"),
+                                     cl::OneOrMore, cl::sub(PrettySubcommand));
+
+cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
+                         cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Symbols("module-syms",
+                      cl::desc("Display symbols for each compiland"),
+                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
+                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
+                        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::list<SymLevel> SymTypes(
+    "sym-types", cl::desc("Type of symbols to dump (default all)"),
+    cl::cat(TypeCategory), cl::sub(PrettySubcommand), cl::ZeroOrMore,
+    cl::values(
+        clEnumValN(SymLevel::Thunks, "thunks", "Display thunk symbols"),
+        clEnumValN(SymLevel::Data, "data", "Display data symbols"),
+        clEnumValN(SymLevel::Functions, "funcs", "Display function symbols"),
+        clEnumValN(SymLevel::All, "all", "Display all symbols (default)")));
+
+cl::opt<bool>
+    Types("types",
+          cl::desc("Display all types (implies -classes, -enums, -typedefs)"),
+          cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Classes("classes", cl::desc("Display class types"),
+                      cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Enums("enums", cl::desc("Display enum types"),
+                    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Typedefs("typedefs", cl::desc("Display typedef types"),
+                       cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<SymbolSortMode> SymbolOrder(
+    "symbol-order", cl::desc("symbol sort order"),
+    cl::init(SymbolSortMode::None),
+    cl::values(clEnumValN(SymbolSortMode::None, "none",
+                          "Undefined / no particular sort order"),
+               clEnumValN(SymbolSortMode::Name, "name", "Sort symbols by name"),
+               clEnumValN(SymbolSortMode::Size, "size",
+                          "Sort symbols by size")),
+    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<ClassSortMode> ClassOrder(
+    "class-order", cl::desc("Class sort order"), cl::init(ClassSortMode::None),
+    cl::values(
+        clEnumValN(ClassSortMode::None, "none",
+                   "Undefined / no particular sort order"),
+        clEnumValN(ClassSortMode::Name, "name", "Sort classes by name"),
+        clEnumValN(ClassSortMode::Size, "size", "Sort classes by size"),
+        clEnumValN(ClassSortMode::Padding, "padding",
+                   "Sort classes by amount of padding"),
+        clEnumValN(ClassSortMode::PaddingPct, "padding-pct",
+                   "Sort classes by percentage of space consumed by padding"),
+        clEnumValN(ClassSortMode::PaddingImmediate, "padding-imm",
+                   "Sort classes by amount of immediate padding"),
+        clEnumValN(ClassSortMode::PaddingPctImmediate, "padding-pct-imm",
+                   "Sort classes by percentage of space consumed by immediate "
+                   "padding")),
+    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<ClassDefinitionFormat> ClassFormat(
+    "class-definitions", cl::desc("Class definition format"),
+    cl::init(ClassDefinitionFormat::All),
+    cl::values(
+        clEnumValN(ClassDefinitionFormat::All, "all",
+                   "Display all class members including data, constants, "
+                   "typedefs, functions, etc"),
+        clEnumValN(ClassDefinitionFormat::Layout, "layout",
+                   "Only display members that contribute to class size."),
+        clEnumValN(ClassDefinitionFormat::None, "none",
+                   "Don't display class definitions")),
+    cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> ClassRecursionDepth(
+    "class-recurse-depth", cl::desc("Class recursion depth (0=no limit)"),
+    cl::init(0), cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
+                    cl::sub(PrettySubcommand));
+cl::opt<bool>
+    All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
+        cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+
+cl::opt<uint64_t> LoadAddress(
+    "load-address",
+    cl::desc("Assume the module is loaded at the specified address"),
+    cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::opt<bool> Native("native", cl::desc("Use native PDB reader instead of DIA"),
+                     cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::opt<cl::boolOrDefault>
+    ColorOutput("color-output",
+                cl::desc("Override use of color (default = isatty)"),
+                cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeTypes(
+    "exclude-types", cl::desc("Exclude types by regular expression"),
+    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeSymbols(
+    "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
+    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeCompilands(
+    "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
+    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+
+cl::list<std::string> IncludeTypes(
+    "include-types",
+    cl::desc("Include only types which match a regular expression"),
+    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> IncludeSymbols(
+    "include-symbols",
+    cl::desc("Include only symbols which match a regular expression"),
+    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> IncludeCompilands(
+    "include-compilands",
+    cl::desc("Include only compilands those which match a regular expression"),
+    cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> SizeThreshold(
+    "min-type-size", cl::desc("Displays only those types which are greater "
+                              "than or equal to the specified size."),
+    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> PaddingThreshold(
+    "min-class-padding", cl::desc("Displays only those classes which have at "
+                                  "least the specified amount of padding."),
+    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<uint32_t> ImmediatePaddingThreshold(
+    "min-class-padding-imm",
+    cl::desc("Displays only those classes which have at least the specified "
+             "amount of immediate padding, ignoring padding internal to bases "
+             "and aggregates."),
+    cl::init(0), cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+
+cl::opt<bool> ExcludeCompilerGenerated(
+    "no-compiler-generated",
+    cl::desc("Don't show compiler generated types and symbols"),
+    cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<bool>
+    ExcludeSystemLibraries("no-system-libs",
+                           cl::desc("Don't show symbols from system libraries"),
+                           cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+
+cl::opt<bool> NoEnumDefs("no-enum-definitions",
+                         cl::desc("Don't display full enum definitions"),
+                         cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+}
+
+namespace diff {
+cl::opt<bool> Pedantic("pedantic",
+                       cl::desc("Finds all differences (even structural ones "
+                                "that produce otherwise identical PDBs)"),
+                       cl::sub(DiffSubcommand));
+
+cl::list<std::string> InputFilenames(cl::Positional,
+                                     cl::desc("<first> <second>"),
+                                     cl::OneOrMore, cl::sub(DiffSubcommand));
+}
+
+namespace raw {
+
+cl::OptionCategory MsfOptions("MSF Container Options");
+cl::OptionCategory TypeOptions("Type Record Options");
+cl::OptionCategory SymbolOptions("Symbol Options");
+cl::OptionCategory MiscOptions("Miscellaneous Options");
+
+// MSF OPTIONS
+cl::opt<bool> DumpHeaders("headers", cl::desc("dump PDB headers"),
+                          cl::cat(MsfOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpStreamBlocks("stream-blocks",
+                               cl::desc("dump PDB stream blocks"),
+                               cl::cat(MsfOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpStreamSummary("stream-summary",
+                                cl::desc("dump summary of the PDB streams"),
+                                cl::cat(MsfOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpPageStats(
+    "page-stats",
+    cl::desc("dump allocation stats of the pages in the MSF file"),
+    cl::cat(MsfOptions), cl::sub(RawSubcommand));
+cl::opt<std::string>
+    DumpBlockRangeOpt("block-data", cl::value_desc("start[-end]"),
+                      cl::desc("Dump binary data from specified range."),
+                      cl::cat(MsfOptions), cl::sub(RawSubcommand));
+llvm::Optional<BlockRange> DumpBlockRange;
+
+cl::list<std::string>
+    DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore,
+                   cl::desc("Dump binary data from specified streams.  Format "
+                            "is SN[:Start][@Size]"),
+                   cl::cat(MsfOptions), cl::sub(RawSubcommand));
+
+// TYPE OPTIONS
+cl::opt<bool>
+    CompactRecords("compact-records",
+                   cl::desc("Dump type and symbol records with less detail"),
+                   cl::cat(TypeOptions), cl::sub(RawSubcommand));
+
+cl::opt<bool>
+    DumpTpiRecords("tpi-records",
+                   cl::desc("dump CodeView type records from TPI stream"),
+                   cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpTpiRecordBytes(
+    "tpi-record-bytes",
+    cl::desc("dump CodeView type record raw bytes from TPI stream"),
+    cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"),
+                          cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool>
+    DumpIpiRecords("ipi-records",
+                   cl::desc("dump CodeView type records from IPI stream"),
+                   cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpIpiRecordBytes(
+    "ipi-record-bytes",
+    cl::desc("dump CodeView type record raw bytes from IPI stream"),
+    cl::cat(TypeOptions), cl::sub(RawSubcommand));
+
+// SYMBOL OPTIONS
+cl::opt<bool> DumpGlobals("globals", cl::desc("dump globals stream data"),
+                          cl::cat(SymbolOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
+                          cl::cat(SymbolOptions), cl::sub(RawSubcommand));
+cl::opt<bool>
+    DumpSymRecordBytes("sym-record-bytes",
+                       cl::desc("dump CodeView symbol record raw bytes"),
+                       cl::cat(SymbolOptions), cl::sub(RawSubcommand));
+
+// MISCELLANEOUS OPTIONS
+cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
+                              cl::cat(MiscOptions), cl::sub(RawSubcommand));
+
+cl::opt<bool> DumpSectionContribs("section-contribs",
+                                  cl::desc("dump section contributions"),
+                                  cl::cat(MiscOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
+                             cl::cat(MiscOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpSectionHeaders("section-headers",
+                                 cl::desc("dump section headers"),
+                                 cl::cat(MiscOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions),
+                      cl::sub(RawSubcommand));
+
+cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
+                     cl::cat(MiscOptions), cl::sub(RawSubcommand));
+
+cl::list<std::string> InputFilenames(cl::Positional,
+                                     cl::desc("<input PDB files>"),
+                                     cl::OneOrMore, cl::sub(RawSubcommand));
+}
+
+namespace yaml2pdb {
+cl::opt<std::string>
+    YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
+                      cl::sub(YamlToPdbSubcommand));
+
+cl::opt<std::string> InputFilename(cl::Positional,
+                                   cl::desc("<input YAML file>"), cl::Required,
+                                   cl::sub(YamlToPdbSubcommand));
+}
+
+namespace pdb2yaml {
+cl::opt<bool> All("all",
+                  cl::desc("Dump everything we know how to dump."),
+                  cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> NoFileHeaders("no-file-headers",
+                            cl::desc("Do not dump MSF file headers"),
+                            cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> Minimal("minimal",
+                      cl::desc("Don't write fields with default values"),
+                      cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> StreamMetadata(
+    "stream-metadata",
+    cl::desc("Dump the number of streams and each stream's size"),
+    cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> StreamDirectory(
+    "stream-directory",
+    cl::desc("Dump each stream's block map (implies -stream-metadata)"),
+    cl::sub(PdbToYamlSubcommand), cl::init(false));
+cl::opt<bool> PdbStream("pdb-stream",
+                        cl::desc("Dump the PDB Stream (Stream 1)"),
+                        cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> StringTable("string-table", cl::desc("Dump the PDB String Table"),
+                          cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> DbiStream("dbi-stream",
+                        cl::desc("Dump the DBI Stream Headers (Stream 2)"),
+                        cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> TpiStream("tpi-stream",
+                        cl::desc("Dump the TPI Stream (Stream 3)"),
+                        cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::opt<bool> IpiStream("ipi-stream",
+                        cl::desc("Dump the IPI Stream (Stream 5)"),
+                        cl::sub(PdbToYamlSubcommand), cl::init(false));
+
+cl::list<std::string> InputFilename(cl::Positional,
+                                    cl::desc("<input PDB file>"), cl::Required,
+                                    cl::sub(PdbToYamlSubcommand));
+}
+
+namespace shared {
+cl::OptionCategory FileOptions("Module & File Options");
+
+// MODULE & FILE OPTIONS
+cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
+                          cl::cat(FileOptions), cl::sub(RawSubcommand),
+                          cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
+                              cl::cat(FileOptions), cl::sub(RawSubcommand),
+                              cl::sub(PdbToYamlSubcommand));
+cl::list<ModuleSubsection> 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::Unknown, "unknown",
+                   "Any subsection not covered by another option"),
+        clEnumValN(ModuleSubsection::All, "all", "All known subsections")),
+    cl::cat(FileOptions), cl::sub(RawSubcommand), cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
+                             cl::cat(FileOptions), cl::sub(RawSubcommand),
+                             cl::sub(PdbToYamlSubcommand));
+} // namespace shared
+
+namespace analyze {
+cl::opt<bool> StringTable("hash-collisions", cl::desc("Find hash collisions"),
+                          cl::sub(AnalyzeSubcommand), cl::init(false));
+cl::list<std::string> InputFilename(cl::Positional,
+                                    cl::desc("<input PDB file>"), cl::Required,
+                                    cl::sub(AnalyzeSubcommand));
+}
+
+namespace merge {
+cl::list<std::string> InputFilenames(cl::Positional,
+                                     cl::desc("<input PDB files>"),
+                                     cl::OneOrMore, cl::sub(MergeSubcommand));
+cl::opt<std::string>
+    PdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
+                  cl::sub(MergeSubcommand));
+}
+}
+
+static ExitOnError ExitOnErr;
+
+bool opts::checkModuleSubsection(opts::ModuleSubsection MS) {
+  return any_of(opts::shared::DumpModuleSubsections,
+                [=](opts::ModuleSubsection M) {
+                  return M == MS || M == opts::ModuleSubsection::All;
+                });
+}
+
+static void yamlToPdb(StringRef Path) {
+  BumpPtrAllocator Allocator;
+  ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
+      MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
+                                   /*RequiresNullTerminator=*/false);
+
+  if (ErrorOrBuffer.getError()) {
+    ExitOnErr(make_error<GenericError>(generic_error_code::invalid_path, Path));
+  }
+
+  std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
+
+  llvm::yaml::Input In(Buffer->getBuffer());
+  pdb::yaml::PdbObject YamlObj(Allocator);
+  In >> YamlObj;
+
+  PDBFileBuilder Builder(Allocator);
+
+  uint32_t BlockSize = 4096;
+  if (YamlObj.Headers.hasValue())
+    BlockSize = YamlObj.Headers->SuperBlock.BlockSize;
+  ExitOnErr(Builder.initialize(BlockSize));
+  // Add each of the reserved streams.  We ignore stream metadata in the
+  // yaml, because we will reconstruct our own view of the streams.  For
+  // example, the YAML may say that there were 20 streams in the original
+  // PDB, but maybe we only dump a subset of those 20 streams, so we will
+  // have fewer, and the ones we do have may end up with different indices
+  // than the ones in the original PDB.  So we just start with a clean slate.
+  for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
+    ExitOnErr(Builder.getMsfBuilder().addStream(0));
+
+  if (YamlObj.StringTable.hasValue()) {
+    auto &Strings = Builder.getStringTableBuilder();
+    for (auto S : *YamlObj.StringTable)
+      Strings.insert(S);
+  }
+
+  pdb::yaml::PdbInfoStream DefaultInfoStream;
+  pdb::yaml::PdbDbiStream DefaultDbiStream;
+  pdb::yaml::PdbTpiStream DefaultTpiStream;
+  pdb::yaml::PdbTpiStream DefaultIpiStream;
+
+  const auto &Info = YamlObj.PdbStream.getValueOr(DefaultInfoStream);
+
+  auto &InfoBuilder = Builder.getInfoBuilder();
+  InfoBuilder.setAge(Info.Age);
+  InfoBuilder.setGuid(Info.Guid);
+  InfoBuilder.setSignature(Info.Signature);
+  InfoBuilder.setVersion(Info.Version);
+  for (auto F : Info.Features)
+    InfoBuilder.addFeature(F);
+
+  auto &Strings = Builder.getStringTableBuilder().getStrings();
+
+  const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream);
+  auto &DbiBuilder = Builder.getDbiBuilder();
+  DbiBuilder.setAge(Dbi.Age);
+  DbiBuilder.setBuildNumber(Dbi.BuildNumber);
+  DbiBuilder.setFlags(Dbi.Flags);
+  DbiBuilder.setMachineType(Dbi.MachineType);
+  DbiBuilder.setPdbDllRbld(Dbi.PdbDllRbld);
+  DbiBuilder.setPdbDllVersion(Dbi.PdbDllVersion);
+  DbiBuilder.setVersionHeader(Dbi.VerHeader);
+  for (const auto &MI : Dbi.ModInfos) {
+    auto &ModiBuilder = ExitOnErr(DbiBuilder.addModuleInfo(MI.Mod));
+    ModiBuilder.setObjFileName(MI.Obj);
+
+    for (auto S : MI.SourceFiles)
+      ExitOnErr(DbiBuilder.addModuleSourceFile(MI.Mod, S));
+    if (MI.Modi.hasValue()) {
+      const auto &ModiStream = *MI.Modi;
+      for (auto Symbol : ModiStream.Symbols) {
+        ModiBuilder.addSymbol(
+            Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb));
+      }
+    }
+
+    auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
+        Allocator, MI.Subsections, Strings));
+    for (auto &SS : CodeViewSubsections) {
+      ModiBuilder.addDebugSubsection(std::move(SS));
+    }
+  }
+
+  auto &TpiBuilder = Builder.getTpiBuilder();
+  const auto &Tpi = YamlObj.TpiStream.getValueOr(DefaultTpiStream);
+  TpiBuilder.setVersionHeader(Tpi.Version);
+  for (const auto &R : Tpi.Records) {
+    CVType Type = R.toCodeViewRecord(Allocator);
+    TpiBuilder.addTypeRecord(Type.RecordData, None);
+  }
+
+  const auto &Ipi = YamlObj.IpiStream.getValueOr(DefaultIpiStream);
+  auto &IpiBuilder = Builder.getIpiBuilder();
+  IpiBuilder.setVersionHeader(Ipi.Version);
+  for (const auto &R : Ipi.Records) {
+    CVType Type = R.toCodeViewRecord(Allocator);
+    IpiBuilder.addTypeRecord(Type.RecordData, None);
+  }
+
+  ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile));
+}
+
+static PDBFile &loadPDB(StringRef Path, std::unique_ptr<IPDBSession> &Session) {
+  ExitOnErr(loadDataForPDB(PDB_ReaderType::Native, Path, Session));
+
+  NativeSession *NS = static_cast<NativeSession *>(Session.get());
+  return NS->getPDBFile();
+}
+
+static void pdb2Yaml(StringRef Path) {
+  std::unique_ptr<IPDBSession> Session;
+  auto &File = loadPDB(Path, Session);
+
+  auto O = llvm::make_unique<YAMLOutputStyle>(File);
+  O = llvm::make_unique<YAMLOutputStyle>(File);
+
+  ExitOnErr(O->dump());
+}
+
+static void dumpRaw(StringRef Path) {
+  std::unique_ptr<IPDBSession> Session;
+  auto &File = loadPDB(Path, Session);
+
+  auto O = llvm::make_unique<LLVMOutputStyle>(File);
+
+  ExitOnErr(O->dump());
+}
+
+static void dumpAnalysis(StringRef Path) {
+  std::unique_ptr<IPDBSession> Session;
+  auto &File = loadPDB(Path, Session);
+  auto O = llvm::make_unique<AnalysisStyle>(File);
+
+  ExitOnErr(O->dump());
+}
+
+static void diff(StringRef Path1, StringRef Path2) {
+  std::unique_ptr<IPDBSession> Session1;
+  std::unique_ptr<IPDBSession> Session2;
+
+  auto &File1 = loadPDB(Path1, Session1);
+  auto &File2 = loadPDB(Path2, Session2);
+
+  auto O = llvm::make_unique<DiffStyle>(File1, File2);
+
+  ExitOnErr(O->dump());
+}
+
+bool opts::pretty::shouldDumpSymLevel(SymLevel Search) {
+  if (SymTypes.empty())
+    return true;
+  if (llvm::find(SymTypes, Search) != SymTypes.end())
+    return true;
+  if (llvm::find(SymTypes, SymLevel::All) != SymTypes.end())
+    return true;
+  return false;
+}
+
+uint32_t llvm::pdb::getTypeLength(const PDBSymbolData &Symbol) {
+  auto SymbolType = Symbol.getType();
+  const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();
+
+  return RawType.getLength();
+}
+
+bool opts::pretty::compareFunctionSymbols(
+    const std::unique_ptr<PDBSymbolFunc> &F1,
+    const std::unique_ptr<PDBSymbolFunc> &F2) {
+  assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
+
+  if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
+    return F1->getName() < F2->getName();
+
+  // Note that we intentionally sort in descending order on length, since
+  // long functions are more interesting than short functions.
+  return F1->getLength() > F2->getLength();
+}
+
+bool opts::pretty::compareDataSymbols(
+    const std::unique_ptr<PDBSymbolData> &F1,
+    const std::unique_ptr<PDBSymbolData> &F2) {
+  assert(opts::pretty::SymbolOrder != opts::pretty::SymbolSortMode::None);
+
+  if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::Name)
+    return F1->getName() < F2->getName();
+
+  // Note that we intentionally sort in descending order on length, since
+  // large types are more interesting than short ones.
+  return getTypeLength(*F1) > getTypeLength(*F2);
+}
+
+static void dumpPretty(StringRef Path) {
+  std::unique_ptr<IPDBSession> Session;
+
+  const auto ReaderType =
+      opts::pretty::Native ? PDB_ReaderType::Native : PDB_ReaderType::DIA;
+  ExitOnErr(loadDataForPDB(ReaderType, Path, Session));
+
+  if (opts::pretty::LoadAddress)
+    Session->setLoadAddress(opts::pretty::LoadAddress);
+
+  auto &Stream = outs();
+  const bool UseColor = opts::pretty::ColorOutput == cl::BOU_UNSET
+                            ? Stream.has_colors()
+                            : opts::pretty::ColorOutput == cl::BOU_TRUE;
+  LinePrinter Printer(2, UseColor, Stream);
+
+  auto GlobalScope(Session->getGlobalScope());
+  std::string FileName(GlobalScope->getSymbolsFileName());
+
+  WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
+  WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
+  Printer.Indent();
+  uint64_t FileSize = 0;
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
+  if (!sys::fs::file_size(FileName, FileSize)) {
+    Printer << ": " << FileSize << " bytes";
+  } else {
+    Printer << ": (Unable to obtain file size)";
+  }
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
+  Printer << ": " << GlobalScope->getGuid();
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
+  Printer << ": " << GlobalScope->getAge();
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
+  Printer << ": ";
+  if (GlobalScope->hasCTypes())
+    outs() << "HasCTypes ";
+  if (GlobalScope->hasPrivateSymbols())
+    outs() << "HasPrivateSymbols ";
+  Printer.Unindent();
+
+  if (opts::pretty::Compilands) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+        << "---COMPILANDS---";
+    Printer.Indent();
+    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
+    CompilandDumper Dumper(Printer);
+    CompilandDumpFlags options = CompilandDumper::Flags::None;
+    if (opts::pretty::Lines)
+      options = options | CompilandDumper::Flags::Lines;
+    while (auto Compiland = Compilands->getNext())
+      Dumper.start(*Compiland, options);
+    Printer.Unindent();
+  }
+
+  if (opts::pretty::Classes || opts::pretty::Enums || opts::pretty::Typedefs) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
+    Printer.Indent();
+    TypeDumper Dumper(Printer);
+    Dumper.start(*GlobalScope);
+    Printer.Unindent();
+  }
+
+  if (opts::pretty::Symbols) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
+    Printer.Indent();
+    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
+    CompilandDumper Dumper(Printer);
+    while (auto Compiland = Compilands->getNext())
+      Dumper.start(*Compiland, true);
+    Printer.Unindent();
+  }
+
+  if (opts::pretty::Globals) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
+    Printer.Indent();
+    if (shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) {
+      FunctionDumper Dumper(Printer);
+      auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
+      if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
+        while (auto Function = Functions->getNext()) {
+          Printer.NewLine();
+          Dumper.start(*Function, FunctionDumper::PointerType::None);
+        }
+      } else {
+        std::vector<std::unique_ptr<PDBSymbolFunc>> Funcs;
+        while (auto Func = Functions->getNext())
+          Funcs.push_back(std::move(Func));
+        std::sort(Funcs.begin(), Funcs.end(),
+                  opts::pretty::compareFunctionSymbols);
+        for (const auto &Func : Funcs) {
+          Printer.NewLine();
+          Dumper.start(*Func, FunctionDumper::PointerType::None);
+        }
+      }
+    }
+    if (shouldDumpSymLevel(opts::pretty::SymLevel::Data)) {
+      auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
+      VariableDumper Dumper(Printer);
+      if (opts::pretty::SymbolOrder == opts::pretty::SymbolSortMode::None) {
+        while (auto Var = Vars->getNext())
+          Dumper.start(*Var);
+      } else {
+        std::vector<std::unique_ptr<PDBSymbolData>> Datas;
+        while (auto Var = Vars->getNext())
+          Datas.push_back(std::move(Var));
+        std::sort(Datas.begin(), Datas.end(), opts::pretty::compareDataSymbols);
+        for (const auto &Var : Datas)
+          Dumper.start(*Var);
+      }
+    }
+    if (shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) {
+      auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
+      CompilandDumper Dumper(Printer);
+      while (auto Thunk = Thunks->getNext())
+        Dumper.dump(*Thunk);
+    }
+    Printer.Unindent();
+  }
+  if (opts::pretty::Externals) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
+    Printer.Indent();
+    ExternalSymbolDumper Dumper(Printer);
+    Dumper.start(*GlobalScope);
+  }
+  if (opts::pretty::Lines) {
+    Printer.NewLine();
+  }
+  outs().flush();
+}
+
+static void mergePdbs() {
+  BumpPtrAllocator Allocator;
+  TypeTableBuilder MergedTpi(Allocator);
+  TypeTableBuilder MergedIpi(Allocator);
+
+  // Create a Tpi and Ipi type table with all types from all input files.
+  for (const auto &Path : opts::merge::InputFilenames) {
+    std::unique_ptr<IPDBSession> Session;
+    auto &File = loadPDB(Path, Session);
+    SmallVector<TypeIndex, 128> TypeMap;
+    SmallVector<TypeIndex, 128> IdMap;
+    if (File.hasPDBTpiStream()) {
+      auto &Tpi = ExitOnErr(File.getPDBTpiStream());
+      ExitOnErr(codeview::mergeTypeRecords(MergedTpi, TypeMap, nullptr,
+                                           Tpi.typeArray()));
+    }
+    if (File.hasPDBIpiStream()) {
+      auto &Ipi = ExitOnErr(File.getPDBIpiStream());
+      ExitOnErr(codeview::mergeIdRecords(MergedIpi, TypeMap, IdMap,
+                                         Ipi.typeArray()));
+    }
+  }
+
+  // Then write the PDB.
+  PDBFileBuilder Builder(Allocator);
+  ExitOnErr(Builder.initialize(4096));
+  // Add each of the reserved streams.  We might not put any data in them,
+  // but at least they have to be present.
+  for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
+    ExitOnErr(Builder.getMsfBuilder().addStream(0));
+
+  auto &DestTpi = Builder.getTpiBuilder();
+  auto &DestIpi = Builder.getIpiBuilder();
+  MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, ArrayRef<uint8_t> Data) {
+    DestTpi.addTypeRecord(Data, None);
+  });
+  MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, ArrayRef<uint8_t> Data) {
+    DestIpi.addTypeRecord(Data, None);
+  });
+
+  SmallString<64> OutFile(opts::merge::PdbOutputFile);
+  if (OutFile.empty()) {
+    OutFile = opts::merge::InputFilenames[0];
+    llvm::sys::path::replace_extension(OutFile, "merged.pdb");
+  }
+  ExitOnErr(Builder.commit(OutFile));
+}
+
+int main(int argc_, const char *argv_[]) {
+  // Print a stack trace if we signal out.
+  sys::PrintStackTraceOnErrorSignal(argv_[0]);
+  PrettyStackTraceProgram X(argc_, argv_);
+
+  ExitOnErr.setBanner("llvm-pdbutil: ");
+
+  SmallVector<const char *, 256> argv;
+  SpecificBumpPtrAllocator<char> ArgAllocator;
+  ExitOnErr(errorCodeToError(sys::Process::GetArgumentVector(
+      argv, makeArrayRef(argv_, argc_), ArgAllocator)));
+
+  llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+  cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
+  if (!opts::raw::DumpBlockRangeOpt.empty()) {
+    llvm::Regex R("^([0-9]+)(-([0-9]+))?$");
+    llvm::SmallVector<llvm::StringRef, 2> Matches;
+    if (!R.match(opts::raw::DumpBlockRangeOpt, &Matches)) {
+      errs() << "Argument '" << opts::raw::DumpBlockRangeOpt
+             << "' invalid format.\n";
+      errs().flush();
+      exit(1);
+    }
+    opts::raw::DumpBlockRange.emplace();
+    Matches[1].getAsInteger(10, opts::raw::DumpBlockRange->Min);
+    if (!Matches[3].empty()) {
+      opts::raw::DumpBlockRange->Max.emplace();
+      Matches[3].getAsInteger(10, *opts::raw::DumpBlockRange->Max);
+    }
+  }
+
+  if ((opts::RawSubcommand && opts::raw::RawAll) ||
+      (opts::PdbToYamlSubcommand && opts::pdb2yaml::All)) {
+    opts::shared::DumpModules = true;
+    opts::shared::DumpModuleFiles = true;
+    opts::shared::DumpModuleSyms = true;
+    opts::shared::DumpModuleSubsections.push_back(opts::ModuleSubsection::All);
+    if (llvm::is_contained(opts::shared::DumpModuleSubsections,
+                           opts::ModuleSubsection::All)) {
+      opts::shared::DumpModuleSubsections.reset();
+      opts::shared::DumpModuleSubsections.push_back(
+          opts::ModuleSubsection::All);
+    }
+  }
+
+  if (opts::shared::DumpModuleSyms || opts::shared::DumpModuleFiles)
+    opts::shared::DumpModules = true;
+
+  if (opts::shared::DumpModules)
+    opts::pdb2yaml::DbiStream = true;
+
+  if (opts::RawSubcommand) {
+    if (opts::raw::RawAll) {
+      opts::raw::DumpHeaders = true;
+      opts::raw::DumpGlobals = true;
+      opts::raw::DumpPublics = true;
+      opts::raw::DumpSectionHeaders = true;
+      opts::raw::DumpStreamSummary = true;
+      opts::raw::DumpPageStats = true;
+      opts::raw::DumpStreamBlocks = true;
+      opts::raw::DumpTpiRecords = true;
+      opts::raw::DumpTpiHash = true;
+      opts::raw::DumpIpiRecords = true;
+      opts::raw::DumpSectionMap = true;
+      opts::raw::DumpSectionContribs = true;
+      opts::raw::DumpFpo = true;
+      opts::raw::DumpStringTable = true;
+    }
+
+    if (opts::raw::CompactRecords &&
+        (opts::raw::DumpTpiRecordBytes || opts::raw::DumpIpiRecordBytes)) {
+      errs() << "-compact-records is incompatible with -tpi-record-bytes and "
+                "-ipi-record-bytes.\n";
+      exit(1);
+    }
+  }
+  if (opts::PdbToYamlSubcommand) {
+    if (opts::pdb2yaml::All) {
+      opts::pdb2yaml::StreamMetadata = true;
+      opts::pdb2yaml::StreamDirectory = true;
+      opts::pdb2yaml::PdbStream = true;
+      opts::pdb2yaml::StringTable = true;
+      opts::pdb2yaml::DbiStream = true;
+      opts::pdb2yaml::TpiStream = true;
+      opts::pdb2yaml::IpiStream = true;
+    }
+  }
+
+  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
+
+  if (opts::PdbToYamlSubcommand) {
+    pdb2Yaml(opts::pdb2yaml::InputFilename.front());
+  } else if (opts::YamlToPdbSubcommand) {
+    if (opts::yaml2pdb::YamlPdbOutputFile.empty()) {
+      SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue());
+      sys::path::replace_extension(OutputFilename, ".pdb");
+      opts::yaml2pdb::YamlPdbOutputFile = OutputFilename.str();
+    }
+    yamlToPdb(opts::yaml2pdb::InputFilename);
+  } else if (opts::AnalyzeSubcommand) {
+    dumpAnalysis(opts::analyze::InputFilename.front());
+  } else if (opts::PrettySubcommand) {
+    if (opts::pretty::Lines)
+      opts::pretty::Compilands = true;
+
+    if (opts::pretty::All) {
+      opts::pretty::Compilands = true;
+      opts::pretty::Symbols = true;
+      opts::pretty::Globals = true;
+      opts::pretty::Types = true;
+      opts::pretty::Externals = true;
+      opts::pretty::Lines = true;
+    }
+
+    if (opts::pretty::Types) {
+      opts::pretty::Classes = true;
+      opts::pretty::Typedefs = true;
+      opts::pretty::Enums = true;
+    }
+
+    // When adding filters for excluded compilands and types, we need to
+    // remember that these are regexes.  So special characters such as * and \
+    // need to be escaped in the regex.  In the case of a literal \, this means
+    // it needs to be escaped again in the C++.  So matching a single \ in the
+    // input requires 4 \es in the C++.
+    if (opts::pretty::ExcludeCompilerGenerated) {
+      opts::pretty::ExcludeTypes.push_back("__vc_attributes");
+      opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
+    }
+    if (opts::pretty::ExcludeSystemLibraries) {
+      opts::pretty::ExcludeCompilands.push_back(
+          "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
+      opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
+      opts::pretty::ExcludeCompilands.push_back(
+          "d:\\\\th.obj.x86fre\\\\minkernel");
+    }
+    std::for_each(opts::pretty::InputFilenames.begin(),
+                  opts::pretty::InputFilenames.end(), dumpPretty);
+  } else if (opts::RawSubcommand) {
+    std::for_each(opts::raw::InputFilenames.begin(),
+                  opts::raw::InputFilenames.end(), dumpRaw);
+  } else if (opts::DiffSubcommand) {
+    if (opts::diff::InputFilenames.size() != 2) {
+      errs() << "diff subcommand expects exactly 2 arguments.\n";
+      exit(1);
+    }
+    diff(opts::diff::InputFilenames[0], opts::diff::InputFilenames[1]);
+  } else if (opts::MergeSubcommand) {
+    if (opts::merge::InputFilenames.size() < 2) {
+      errs() << "merge subcommand requires at least 2 input files.\n";
+      exit(1);
+    }
+    mergePdbs();
+  }
+
+  outs().flush();
+  return 0;
+}

Added: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h?rev=305106&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h (added)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h Fri Jun  9 15:46:17 2017
@@ -0,0 +1,156 @@
+//===- llvm-pdbutil.h ----------------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <memory>
+#include <stdint.h>
+
+namespace llvm {
+namespace pdb {
+class PDBSymbolData;
+class PDBSymbolFunc;
+uint32_t getTypeLength(const PDBSymbolData &Symbol);
+}
+}
+
+namespace opts {
+
+enum class ModuleSubsection {
+  Unknown,
+  Lines,
+  FileChecksums,
+  InlineeLines,
+  CrossScopeImports,
+  CrossScopeExports,
+  StringTable,
+  Symbols,
+  FrameData,
+  All
+};
+
+bool checkModuleSubsection(ModuleSubsection Kind);
+
+template <typename... Ts>
+bool checkModuleSubsection(ModuleSubsection K1, ModuleSubsection K2,
+                           Ts &&... Rest) {
+  return checkModuleSubsection(K1) ||
+         checkModuleSubsection(K2, std::forward<Ts>(Rest)...);
+}
+
+namespace pretty {
+
+enum class ClassDefinitionFormat { None, Layout, All };
+enum class ClassSortMode {
+  None,
+  Name,
+  Size,
+  Padding,
+  PaddingPct,
+  PaddingImmediate,
+  PaddingPctImmediate
+};
+
+enum class SymbolSortMode { None, Name, Size };
+
+enum class SymLevel { Functions, Data, Thunks, All };
+
+bool shouldDumpSymLevel(SymLevel Level);
+bool compareFunctionSymbols(
+    const std::unique_ptr<llvm::pdb::PDBSymbolFunc> &F1,
+    const std::unique_ptr<llvm::pdb::PDBSymbolFunc> &F2);
+bool compareDataSymbols(const std::unique_ptr<llvm::pdb::PDBSymbolData> &F1,
+                        const std::unique_ptr<llvm::pdb::PDBSymbolData> &F2);
+
+extern llvm::cl::opt<bool> Compilands;
+extern llvm::cl::opt<bool> Symbols;
+extern llvm::cl::opt<bool> Globals;
+extern llvm::cl::opt<bool> Classes;
+extern llvm::cl::opt<bool> Enums;
+extern llvm::cl::opt<bool> Typedefs;
+extern llvm::cl::opt<bool> All;
+extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
+
+extern llvm::cl::opt<bool> NoEnumDefs;
+extern llvm::cl::list<std::string> ExcludeTypes;
+extern llvm::cl::list<std::string> ExcludeSymbols;
+extern llvm::cl::list<std::string> ExcludeCompilands;
+extern llvm::cl::list<std::string> IncludeTypes;
+extern llvm::cl::list<std::string> IncludeSymbols;
+extern llvm::cl::list<std::string> IncludeCompilands;
+extern llvm::cl::opt<SymbolSortMode> SymbolOrder;
+extern llvm::cl::opt<ClassSortMode> ClassOrder;
+extern llvm::cl::opt<uint32_t> SizeThreshold;
+extern llvm::cl::opt<uint32_t> PaddingThreshold;
+extern llvm::cl::opt<uint32_t> ImmediatePaddingThreshold;
+extern llvm::cl::opt<ClassDefinitionFormat> ClassFormat;
+extern llvm::cl::opt<uint32_t> ClassRecursionDepth;
+}
+
+namespace raw {
+struct BlockRange {
+  uint32_t Min;
+  llvm::Optional<uint32_t> Max;
+};
+
+extern llvm::Optional<BlockRange> DumpBlockRange;
+extern llvm::cl::list<std::string> DumpStreamData;
+
+extern llvm::cl::opt<bool> CompactRecords;
+extern llvm::cl::opt<bool> DumpGlobals;
+extern llvm::cl::opt<bool> DumpHeaders;
+extern llvm::cl::opt<bool> DumpStreamBlocks;
+extern llvm::cl::opt<bool> DumpStreamSummary;
+extern llvm::cl::opt<bool> DumpPageStats;
+extern llvm::cl::opt<bool> DumpTpiHash;
+extern llvm::cl::opt<bool> DumpTpiRecordBytes;
+extern llvm::cl::opt<bool> DumpTpiRecords;
+extern llvm::cl::opt<bool> DumpIpiRecords;
+extern llvm::cl::opt<bool> DumpIpiRecordBytes;
+extern llvm::cl::opt<bool> DumpPublics;
+extern llvm::cl::opt<bool> DumpSectionContribs;
+extern llvm::cl::opt<bool> DumpSectionMap;
+extern llvm::cl::opt<bool> DumpSymRecordBytes;
+extern llvm::cl::opt<bool> DumpSectionHeaders;
+extern llvm::cl::opt<bool> DumpFpo;
+extern llvm::cl::opt<bool> DumpStringTable;
+}
+
+namespace diff {
+extern llvm::cl::opt<bool> Pedantic;
+}
+
+namespace pdb2yaml {
+extern llvm::cl::opt<bool> All;
+extern llvm::cl::opt<bool> NoFileHeaders;
+extern llvm::cl::opt<bool> Minimal;
+extern llvm::cl::opt<bool> StreamMetadata;
+extern llvm::cl::opt<bool> StreamDirectory;
+extern llvm::cl::opt<bool> StringTable;
+extern llvm::cl::opt<bool> PdbStream;
+extern llvm::cl::opt<bool> DbiStream;
+extern llvm::cl::opt<bool> TpiStream;
+extern llvm::cl::opt<bool> IpiStream;
+extern llvm::cl::list<std::string> InputFilename;
+}
+
+namespace shared {
+extern llvm::cl::opt<bool> DumpModules;
+extern llvm::cl::opt<bool> DumpModuleFiles;
+extern llvm::cl::list<ModuleSubsection> DumpModuleSubsections;
+extern llvm::cl::opt<bool> DumpModuleSyms;
+} // namespace shared
+}
+
+#endif




More information about the llvm-commits mailing list