llvm.org GIT mirror llvm / cfb1356
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305106 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 2 years ago
118 changed file(s) with 6682 addition(s) and 6678 deletion(s). Raw diff Collapse all Expand all
4848 ``file_magic`` structure and ``identify_magic`` functions, as well as all the
4949 structure and type definitions for DWARF, ELF, COFF, WASM, and MachO file
5050 formats.
51
52 * The tool ``llvm-pdbdump`` has been renamed ``llvm-pdbutil`` to better reflect
53 its nature as a general purpose PDB manipulation / diagnostics tool that does
54 more than just dumping contents.
5155
5256
5357 * ... next change ...
6060 llvm-nm
6161 llvm-objdump
6262 llvm-opt-report
63 llvm-pdbdump
63 llvm-pdbutil
6464 llvm-profdata
6565 llvm-ranlib
6666 llvm-readobj
None ; RUN: llvm-pdbdump pretty %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=NO_ARGS
1 ; RUN: llvm-pdbdump pretty -types %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=TYPES
2 ; RUN: llvm-pdbdump pretty -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=COMPILANDS
3 ; RUN: llvm-pdbdump pretty -types -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=MULTIPLE
0 ; RUN: llvm-pdbutil pretty %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=NO_ARGS
1 ; RUN: llvm-pdbutil pretty -types %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=TYPES
2 ; RUN: llvm-pdbutil pretty -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=COMPILANDS
3 ; RUN: llvm-pdbutil pretty -types -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=MULTIPLE
44
55 ; Check that neither symbols nor compilands are dumped when neither argument specified.
66 ; NO_ARGS: empty.pdb
None ; RUN: llvm-pdbdump pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS_FPO %s
1 ; RUN: llvm-pdbdump pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS %s
0 ; RUN: llvm-pdbutil pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS_FPO %s
1 ; RUN: llvm-pdbutil pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS %s
22
33 ; LINE_NUMS_FPO: llvm\test\debuginfo\pdb\inputs\symbolformat-fpo.cpp
44 ; LINE_NUMS_FPO: Line 5, Address: [0x000011a0 - 0x000011a5] (6 bytes)
None ; RUN: llvm-pdbdump pretty -module-syms %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT_FPO %s
1 ; RUN: llvm-pdbdump pretty -module-syms %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT %s
2 ; RUN: llvm-pdbdump pretty -types %p/../Inputs/symbolformat.pdb > %t.types
0 ; RUN: llvm-pdbutil pretty -module-syms %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT_FPO %s
1 ; RUN: llvm-pdbutil pretty -module-syms %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT %s
2 ; RUN: llvm-pdbutil pretty -types %p/../Inputs/symbolformat.pdb > %t.types
33 ; RUN: FileCheck --check-prefix=TYPES_FORMAT %s < %t.types
44 ; RUN: FileCheck --check-prefix=TYPES_1 %s < %t.types
55 ; RUN: FileCheck --check-prefix=TYPES_2 %s < %t.types
6 ; RUN: llvm-pdbdump pretty -types %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=TYPES_FORMAT %s
7 ; RUN: llvm-pdbdump pretty -globals %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=GLOBALS %s
6 ; RUN: llvm-pdbutil pretty -types %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=TYPES_FORMAT %s
7 ; RUN: llvm-pdbutil pretty -globals %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=GLOBALS %s
88
99 ; The format is func [0x+ - 0x-]
1010 ; SYM_FORMAT_FPO: ---SYMBOLS---
0 ; Test that the native PDB reader can enumerate the compilands.
1 ; RUN: llvm-pdbdump pretty -native -compilands %p/../Inputs/empty.pdb \
1 ; RUN: llvm-pdbutil pretty -native -compilands %p/../Inputs/empty.pdb \
22 ; RUN: | FileCheck -check-prefix=EMPTY %s
3 ; RUN: llvm-pdbdump pretty -native -compilands %p/../Inputs/big-read.pdb \
3 ; RUN: llvm-pdbutil pretty -native -compilands %p/../Inputs/big-read.pdb \
44 ; RUN: | FileCheck -check-prefix=BIGREAD %s
55
66 ; Reference output was generated with the DIA reader to ensure that the
0 ; Test that the native PDB reader gets the PDB summary correct.
1 ; RUN: llvm-pdbdump pretty -native -color-output=false %p/../Inputs/empty.pdb \
1 ; RUN: llvm-pdbutil pretty -native -color-output=false %p/../Inputs/empty.pdb \
22 ; RUN: | FileCheck -check-prefix=EMPTY %s
33
44 ; Reference output was generated with the DIA reader to ensure that the
0 ; For now just verify that this doesn't cause an error. Later we pdbdump can
11 ; do type lookup, we can verify that the name matches what we expect.
2 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/longname-truncation.yaml
2 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/longname-truncation.yaml
55 ; resulting PDB to go back to yaml, and verify that the resulting yaml
66 ; is identical.
77
8 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/one-symbol.yaml
9 ; RUN: llvm-pdbdump pdb2yaml -minimal -module-syms -no-file-headers %t.pdb > %t.pdb.yaml
8 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/one-symbol.yaml
9 ; RUN: llvm-pdbutil pdb2yaml -minimal -module-syms -no-file-headers %t.pdb > %t.pdb.yaml
1010 ; RUN: diff -b %p/Inputs/one-symbol.yaml %t.pdb.yaml
None ; RUN: llvm-pdbdump pdb2yaml -module-syms %p/Inputs/empty.pdb \
0 ; RUN: llvm-pdbutil pdb2yaml -module-syms %p/Inputs/empty.pdb \
11 ; RUN: | FileCheck -check-prefix=YAML %s
22
33
None RUN: llvm-pdbdump pdb2yaml -tpi-stream %p/Inputs/big-read.pdb > %t.yaml
0 RUN: llvm-pdbutil pdb2yaml -tpi-stream %p/Inputs/big-read.pdb > %t.yaml
11 RUN: FileCheck -check-prefix=YAML %s < %t.yaml
2 RUN: llvm-pdbdump yaml2pdb %t.yaml -pdb %t.pdb
3 RUN: llvm-pdbdump raw -tpi-records %t.pdb | FileCheck %s --check-prefix=PDB
2 RUN: llvm-pdbutil yaml2pdb %t.yaml -pdb %t.pdb
3 RUN: llvm-pdbutil raw -tpi-records %t.pdb | FileCheck %s --check-prefix=PDB
44
55 Only verify the beginning of the type stream.
66
None ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml
1 ; RUN: llvm-pdbdump pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s
2 ; RUN: llvm-pdbdump raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s
0 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml
1 ; RUN: llvm-pdbutil pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s
2 ; RUN: llvm-pdbutil raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s
33
44 YAML: Modules:
55 YAML-NEXT: - Module: Foo.obj
None ; RUN: llvm-pdbdump raw -headers -string-table -tpi-records -tpi-record-bytes -module-syms \
0 ; RUN: llvm-pdbutil raw -headers -string-table -tpi-records -tpi-record-bytes -module-syms \
11 ; RUN: -sym-record-bytes -globals -publics -module-files \
22 ; RUN: -stream-summary -stream-blocks -ipi-records -ipi-record-bytes \
33 ; RUN: -section-contribs -section-map -section-headers -subsections=all \
44 ; RUN: -tpi-hash -fpo -page-stats %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
5 ; RUN: llvm-pdbdump raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
6 ; RUN: llvm-pdbdump raw -headers -modules -module-files \
5 ; RUN: llvm-pdbutil raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
6 ; RUN: llvm-pdbutil raw -headers -modules -module-files \
77 ; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
8 ; RUN: not llvm-pdbdump raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
8 ; RUN: not llvm-pdbutil raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
99
1010 ; EMPTY: FileHeaders {
1111 ; EMPTY-NEXT: BlockSize: 4096
None ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-and-types-1.yaml
1 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-and-types-2.yaml
2 ; RUN: llvm-pdbdump merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
3 ; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-TYPES %s
4 ; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=INTMAIN %s
5 ; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=VOIDMAIN %s
6 ; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-TYPES %s
7 ; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-NAMES %s
8 ; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-UDT %s
0 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-and-types-1.yaml
1 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-and-types-2.yaml
2 ; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
3 ; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-TYPES %s
4 ; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=INTMAIN %s
5 ; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=VOIDMAIN %s
6 ; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-TYPES %s
7 ; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-NAMES %s
8 ; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-UDT %s
99
1010 TPI-TYPES: Type Info Stream (TPI)
1111 TPI-TYPES: Record count: 9
None ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-1.yaml
1 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-2.yaml
2 ; RUN: llvm-pdbdump merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
3 ; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
4 ; RUN: llvm-pdbdump raw -ipi-records %t.3.pdb | FileCheck -check-prefix=SUBSTRS %s
5 ; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-EMPTY %s
0 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-1.yaml
1 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-2.yaml
2 ; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
3 ; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
4 ; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=SUBSTRS %s
5 ; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-EMPTY %s
66
77
88 MERGED: Type Info Stream (IPI)
None ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-types-1.yaml
1 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-types-2.yaml
2 ; RUN: llvm-pdbdump merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
3 ; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
4 ; RUN: llvm-pdbdump raw -tpi-records %t.3.pdb | FileCheck -check-prefix=ARGLIST %s
0 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-types-1.yaml
1 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-types-2.yaml
2 ; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
3 ; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
4 ; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=ARGLIST %s
55
66
77 MERGED: Type Info Stream (TPI)
None ; RUN: llvm-pdbdump raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
1 ; RUN: llvm-pdbdump raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
2 ; RUN: not llvm-pdbdump raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
3 ; RUN: not llvm-pdbdump raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
4 ; RUN: not llvm-pdbdump raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
0 ; RUN: llvm-pdbutil raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
1 ; RUN: llvm-pdbutil raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
2 ; RUN: not llvm-pdbutil raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
3 ; RUN: not llvm-pdbutil raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
4 ; RUN: not llvm-pdbutil raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
55
66 BLOCK0: Block Data {
77 BLOCK0-NEXT: Block 0 (
None ; RUN: llvm-pdbdump raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM1 %s
1 ; RUN: not llvm-pdbdump raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s
0 ; RUN: llvm-pdbutil raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM1 %s
1 ; RUN: not llvm-pdbutil raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s
22
33 STREAM1: Stream Data {
44 STREAM1-NEXT: Stream {
None RUN: llvm-pdbdump pdb2yaml -modules -module-files -dbi-stream \
0 RUN: llvm-pdbutil pdb2yaml -modules -module-files -dbi-stream \
11 RUN: -pdb-stream -string-table -tpi-stream -stream-directory \
22 RUN: -stream-metadata %p/Inputs/empty.pdb > %t.1
3 RUN: llvm-pdbdump yaml2pdb -pdb=%t.2 %t.1
3 RUN: llvm-pdbutil yaml2pdb -pdb=%t.2 %t.1
44
5 RUN: llvm-pdbdump raw -headers -string-table -tpi-records %p/Inputs/empty.pdb | FileCheck %s
6 RUN: llvm-pdbdump raw -headers -string-table -tpi-records %t.2 | FileCheck %s
5 RUN: llvm-pdbutil raw -headers -string-table -tpi-records %p/Inputs/empty.pdb | FileCheck %s
6 RUN: llvm-pdbutil raw -headers -string-table -tpi-records %t.2 | FileCheck %s
77
88 CHECK: FileHeaders {
99 CHECK-NEXT: BlockSize: 4096
55 # that differ by one byte, so that at least one of those will only
66 # pass if alignment is implemented correctly.
77
8 RUN: llvm-pdbdump yaml2pdb -pdb=%T/source-names-1.pdb %p/Inputs/source-names-1.yaml
9 RUN: llvm-pdbdump pdb2yaml -module-files %T/source-names-1.pdb \
8 RUN: llvm-pdbutil yaml2pdb -pdb=%T/source-names-1.pdb %p/Inputs/source-names-1.yaml
9 RUN: llvm-pdbutil pdb2yaml -module-files %T/source-names-1.pdb \
1010 RUN: | FileCheck -check-prefix=CHECK1 %s
11 RUN: llvm-pdbdump yaml2pdb -pdb=%T/source-names-2.pdb %p/Inputs/source-names-2.yaml
12 RUN: llvm-pdbdump pdb2yaml -module-files %T/source-names-2.pdb \
11 RUN: llvm-pdbutil yaml2pdb -pdb=%T/source-names-2.pdb %p/Inputs/source-names-2.yaml
12 RUN: llvm-pdbutil pdb2yaml -module-files %T/source-names-2.pdb \
1313 RUN: | FileCheck -check-prefix=CHECK2 %s
1414
1515 CHECK1: SourceFiles:
99 ; stream metadata, since the layout of the MSF file might be different
1010 ; (for example if we don't write the entire stream)
1111 ;
12 ; RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory \
12 ; RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory \
1313 ; RUN: -pdb-stream -tpi-stream -module-syms %p/Inputs/empty.pdb > %t.1
14 ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.2 %t.1
15 ; RUN: llvm-pdbdump pdb2yaml -pdb-stream -tpi-stream \
14 ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2 %t.1
15 ; RUN: llvm-pdbutil pdb2yaml -pdb-stream -tpi-stream \
1616 ; RUN: -module-syms -no-file-headers %p/Inputs/empty.pdb > %t.3
17 ; RUN: llvm-pdbdump pdb2yaml -pdb-stream -tpi-stream \
17 ; RUN: llvm-pdbutil pdb2yaml -pdb-stream -tpi-stream \
1818 ; RUN: -module-syms -no-file-headers %t.2 > %t.4
1919 ; RUN: diff %t.3 %t.4
None ; RUN: llvm-pdbdump pdb2yaml -tpi-stream %p/Inputs/empty.pdb \
0 ; RUN: llvm-pdbutil pdb2yaml -tpi-stream %p/Inputs/empty.pdb \
11 ; RUN: | FileCheck -check-prefix=YAML %s
22
33 YAML: ---
None ; RUN: llvm-pdbdump pdb2yaml -stream-metadata -stream-directory -string-table -pdb-stream \
0 ; RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -string-table -pdb-stream \
11 ; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=YAML %s
2 ; RUN: llvm-pdbdump pdb2yaml -no-file-headers -stream-metadata -stream-directory -pdb-stream \
2 ; RUN: llvm-pdbutil pdb2yaml -no-file-headers -stream-metadata -stream-directory -pdb-stream \
33 ; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=NO-HEADERS %s
44
55 ; YAML: ---
None ; RUN: llvm-pdbdump pretty -all -class-recurse-depth=1 \
0 ; RUN: llvm-pdbutil pretty -all -class-recurse-depth=1 \
11 ; RUN: %p/Inputs/ClassLayoutTest.pdb > %t
22 ; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBALS_TEST
33 ; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBERS_TEST
None ; RUN: llvm-pdbdump pretty -classes -class-definitions=layout \
0 ; RUN: llvm-pdbutil pretty -classes -class-definitions=layout \
11 ; RUN: -include-types=Test %p/Inputs/ComplexPaddingTest.pdb > %t
22
33 ; RUN: FileCheck -input-file=%t %s -check-prefix=DIRECT_VB_ONLY
None ; RUN: llvm-pdbdump pretty -types %p/Inputs/ClassLayoutTest.pdb > %t
0 ; RUN: llvm-pdbutil pretty -types %p/Inputs/ClassLayoutTest.pdb > %t
11 ; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBAL_ENUM
22 ; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBER_ENUM
33
None ; RUN: llvm-pdbdump pretty -externals %p/Inputs/LoadAddressTest.pdb \
0 ; RUN: llvm-pdbutil pretty -externals %p/Inputs/LoadAddressTest.pdb \
11 ; RUN: | FileCheck --check-prefix=RVA %s
2 ; RUN: llvm-pdbdump pretty -externals -load-address=0x40000000 \
2 ; RUN: llvm-pdbutil pretty -externals -load-address=0x40000000 \
33 ; RUN: %p/Inputs/LoadAddressTest.pdb | FileCheck --check-prefix=VA %s
44
55 ; RVA: ---EXTERNALS---
None ; RUN: llvm-pdbdump raw -stream-data=8 %p/Inputs/LoadAddressTest.pdb \
0 ; RUN: llvm-pdbutil raw -stream-data=8 %p/Inputs/LoadAddressTest.pdb \
11 ; RUN: | FileCheck %s -check-prefix=FULL_STREAM
2 ; RUN: llvm-pdbdump raw -stream-data=8:4 %p/Inputs/LoadAddressTest.pdb \
2 ; RUN: llvm-pdbutil raw -stream-data=8:4 %p/Inputs/LoadAddressTest.pdb \
33 ; RUN: | FileCheck %s -check-prefix=OFFSET_STREAM
4 ; RUN: llvm-pdbdump raw -stream-data=8:4@24 %p/Inputs/LoadAddressTest.pdb \
4 ; RUN: llvm-pdbutil raw -stream-data=8:4@24 %p/Inputs/LoadAddressTest.pdb \
55 ; RUN: | FileCheck %s -check-prefix=OFFSET_AND_LENGTH
66
77 FULL_STREAM: Stream Data {
None ; RUN: llvm-pdbdump pretty -module-syms -globals -types %p/Inputs/FilterTest.pdb \
0 ; RUN: llvm-pdbutil pretty -module-syms -globals -types %p/Inputs/FilterTest.pdb \
11 ; RUN: | FileCheck --check-prefix=NO_FILTER %s
22
3 ; RUN: llvm-pdbdump pretty -types -exclude-types="GlobalTypedef|NestedTypedef" \
3 ; RUN: llvm-pdbutil pretty -types -exclude-types="GlobalTypedef|NestedTypedef" \
44 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_TYPEDEFS %s
5 ; RUN: llvm-pdbdump pretty -classes -enums %p/Inputs/FilterTest.pdb \
5 ; RUN: llvm-pdbutil pretty -classes -enums %p/Inputs/FilterTest.pdb \
66 ; RUN: | FileCheck --check-prefix=EXCLUDE_TYPEDEFS %s
77
8 ; RUN: llvm-pdbdump pretty -types -exclude-types="GlobalEnum|NestedEnum" \
8 ; RUN: llvm-pdbutil pretty -types -exclude-types="GlobalEnum|NestedEnum" \
99 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_ENUMS %s
10 ; RUN: llvm-pdbdump pretty -classes -typedefs %p/Inputs/FilterTest.pdb \
10 ; RUN: llvm-pdbutil pretty -classes -typedefs %p/Inputs/FilterTest.pdb \
1111 ; RUN: | FileCheck --check-prefix=EXCLUDE_ENUMS %s
1212
13 ; RUN: llvm-pdbdump pretty -types -module-syms -globals -exclude-symbols="MemberVar|GlobalVar" \
13 ; RUN: llvm-pdbutil pretty -types -module-syms -globals -exclude-symbols="MemberVar|GlobalVar" \
1414 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_VARS %s
15 ; RUN: llvm-pdbdump pretty -types -exclude-types="FilterTestClass" \
15 ; RUN: llvm-pdbutil pretty -types -exclude-types="FilterTestClass" \
1616 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_WHOLE_CLASS %s
17 ; RUN: llvm-pdbdump pretty -module-syms -globals -exclude-compilands="FilterTest.obj" \
17 ; RUN: llvm-pdbutil pretty -module-syms -globals -exclude-compilands="FilterTest.obj" \
1818 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_COMPILAND %s
19 ; RUN: llvm-pdbdump pretty -types -include-types="FilterTestClass" \
19 ; RUN: llvm-pdbutil pretty -types -include-types="FilterTestClass" \
2020 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=INCLUDE_ONLY_TYPES %s
21 ; RUN: llvm-pdbdump pretty -types -module-syms -globals -include-symbols="[[:<:]](IntGlobalVar|DoubleGlobalVar)[[:>:]]" \
21 ; RUN: llvm-pdbutil pretty -types -module-syms -globals -include-symbols="[[:<:]](IntGlobalVar|DoubleGlobalVar)[[:>:]]" \
2222 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=INCLUDE_ONLY_VARS %s
2323
2424 ; NO_FILTER: ---TYPES---
None ; RUN: llvm-pdbdump pretty -classes -class-definitions=layout \
0 ; RUN: llvm-pdbutil pretty -classes -class-definitions=layout \
11 ; RUN: -include-types=SimplePad %p/Inputs/SimplePaddingTest.pdb > %t
22
33 ; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PADDING
None ; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=data %p/Inputs/FilterTest.pdb \
0 ; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=data %p/Inputs/FilterTest.pdb \
11 ; RUN: | FileCheck --check-prefix=ONLY_DATA %s
22
3 ; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=thunks %p/Inputs/FilterTest.pdb \
3 ; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=thunks %p/Inputs/FilterTest.pdb \
44 ; RUN: | FileCheck --check-prefix=ONLY_THUNKS %s
55
6 ; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=funcs %p/Inputs/FilterTest.pdb \
6 ; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=funcs %p/Inputs/FilterTest.pdb \
77 ; RUN: | FileCheck --check-prefix=ONLY_FUNCS %s
88
9 ; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=funcs -sym-types=data \
9 ; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=funcs -sym-types=data \
1010 ; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=TWO_TYPES %s
1111
12 ; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=data \
12 ; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=data \
1313 ; RUN: -symbol-order=name %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=NAME_SORT_DATA %s
1414
15 ; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=data \
15 ; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=data \
1616 ; RUN: -symbol-order=size %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=SIZE_SORT_DATA %s
1717
18 ; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=funcs \
18 ; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=funcs \
1919 ; RUN: -symbol-order=name %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=NAME_SORT_FUNCS %s
2020
21 ; RUN: llvm-pdbdump pretty -globals -module-syms -sym-types=funcs \
21 ; RUN: llvm-pdbutil pretty -globals -module-syms -sym-types=funcs \
2222 ; RUN: -symbol-order=size %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=SIZE_SORT_FUNCS %s
2323
2424 ; ONLY_DATA-NOT: func
3939 llvm-modextract
4040 llvm-nm
4141 llvm-objdump
42 llvm-pdbdump
42 llvm-pdbutil
4343 llvm-profdata
4444 llvm-rtdyld
4545 llvm-size
+0
-152
tools/llvm-pdbdump/Analyze.cpp less more
None //===- Analyze.cpp - PDB analysis functions ---------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "Analyze.h"
10
11 #include "llvm/ADT/DenseSet.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
14 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
15 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
18 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
19 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
20 #include "llvm/DebugInfo/PDB/Native/RawError.h"
21 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
22
23 #include "llvm/Support/FormatVariadic.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 #include
27
28 using namespace llvm;
29 using namespace llvm::codeview;
30 using namespace llvm::pdb;
31
32 static StringRef getLeafTypeName(TypeLeafKind LT) {
33 switch (LT) {
34 #define TYPE_RECORD(ename, value, name) \
35 case ename: \
36 return #name;
37 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
38 default:
39 break;
40 }
41 return "UnknownLeaf";
42 }
43
44 namespace {
45 struct HashLookupVisitor : public TypeVisitorCallbacks {
46 struct Entry {
47 TypeIndex TI;
48 CVType Record;
49 };
50
51 explicit HashLookupVisitor(TpiStream &Tpi) : Tpi(Tpi) {}
52
53 Error visitTypeBegin(CVType &Record) override {
54 uint32_t H = Tpi.getHashValues()[I];
55 Record.Hash = H;
56 TypeIndex TI(I + TypeIndex::FirstNonSimpleIndex);
57 Lookup[H].push_back(Entry{TI, Record});
58 ++I;
59 return Error::success();
60 }
61
62 uint32_t I = 0;
63 DenseMap> Lookup;
64 TpiStream &Tpi;
65 };
66 }
67
68 AnalysisStyle::AnalysisStyle(PDBFile &File) : File(File) {}
69
70 Error AnalysisStyle::dump() {
71 auto Tpi = File.getPDBTpiStream();
72 if (!Tpi)
73 return Tpi.takeError();
74
75 TypeDatabase TypeDB(Tpi->getNumTypeRecords());
76 TypeDatabaseVisitor DBV(TypeDB);
77 TypeVisitorCallbackPipeline Pipeline;
78 HashLookupVisitor Hasher(*Tpi);
79 // Add them to the database
80 Pipeline.addCallbackToPipeline(DBV);
81 // Store their hash values
82 Pipeline.addCallbackToPipeline(Hasher);
83
84 if (auto EC = codeview::visitTypeStream(Tpi->typeArray(), Pipeline))
85 return EC;
86
87 auto &Adjusters = Tpi->getHashAdjusters();
88 DenseSet AdjusterSet;
89 for (const auto &Adj : Adjusters) {
90 assert(AdjusterSet.find(Adj.second) == AdjusterSet.end());
91 AdjusterSet.insert(Adj.second);
92 }
93
94 uint32_t Count = 0;
95 outs() << "Searching for hash collisions\n";
96 for (const auto &H : Hasher.Lookup) {
97 if (H.second.size() <= 1)
98 continue;
99 ++Count;
100 outs() << formatv("Hash: {0}, Count: {1} records\n", H.first,
101 H.second.size());
102 for (const auto &R : H.second) {
103 auto Iter = AdjusterSet.find(R.TI.getIndex());
104 StringRef Prefix;
105 if (Iter != AdjusterSet.end()) {
106 Prefix = "[HEAD]";
107 AdjusterSet.erase(Iter);
108 }
109 StringRef LeafName = getLeafTypeName(R.Record.Type);
110 uint32_t TI = R.TI.getIndex();
111 StringRef TypeName = TypeDB.getTypeName(R.TI);
112 outs() << formatv("{0,-6} {1} ({2:x}) {3}\n", Prefix, LeafName, TI,
113 TypeName);
114 }
115 }
116
117 outs() << "\n";
118 outs() << "Dumping hash adjustment chains\n";
119 for (const auto &A : Tpi->getHashAdjusters()) {
120 TypeIndex TI(A.second);
121 StringRef TypeName = TypeDB.getTypeName(TI);
122 const CVType &HeadRecord = TypeDB.getTypeRecord(TI);
123 assert(HeadRecord.Hash.hasValue());
124
125 auto CollisionsIter = Hasher.Lookup.find(*HeadRecord.Hash);
126 if (CollisionsIter == Hasher.Lookup.end())
127 continue;
128
129 const auto &Collisions = CollisionsIter->second;
130 outs() << TypeName << "\n";
131 outs() << formatv(" [HEAD] {0:x} {1} {2}\n", A.second,
132 getLeafTypeName(HeadRecord.Type), TypeName);
133 for (const auto &Chain : Collisions) {
134 if (Chain.TI == TI)
135 continue;
136 const CVType &TailRecord = TypeDB.getTypeRecord(Chain.TI);
137 outs() << formatv(" {0:x} {1} {2}\n", Chain.TI.getIndex(),
138 getLeafTypeName(TailRecord.Type),
139 TypeDB.getTypeName(Chain.TI));
140 }
141 }
142 outs() << formatv("There are {0} orphaned hash adjusters\n",
143 AdjusterSet.size());
144 for (const auto &Adj : AdjusterSet) {
145 outs() << formatv(" {0}\n", Adj);
146 }
147
148 uint32_t DistinctHashValues = Hasher.Lookup.size();
149 outs() << formatv("{0}/{1} hash collisions", Count, DistinctHashValues);
150 return Error::success();
151 }
+0
-30
tools/llvm-pdbdump/Analyze.h less more
None //===- Analyze.h - PDB analysis functions -----------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_ANALYSIS_H
11
12 #include "OutputStyle.h"
13
14 namespace llvm {
15 namespace pdb {
16 class PDBFile;
17 class AnalysisStyle : public OutputStyle {
18 public:
19 explicit AnalysisStyle(PDBFile &File);
20
21 Error dump() override;
22
23 private:
24 PDBFile &File;
25 };
26 }
27 }
28
29 #endif
+0
-34
tools/llvm-pdbdump/CMakeLists.txt less more
None set(LLVM_LINK_COMPONENTS
1 DebugInfoCodeView
2 DebugInfoMSF
3 DebugInfoPDB
4 Object
5 ObjectYAML
6 Support
7 )
8
9 add_llvm_tool(llvm-pdbdump
10 Analyze.cpp
11 CompactTypeDumpVisitor.cpp
12 Diff.cpp
13 llvm-pdbdump.cpp
14 LinePrinter.cpp
15 LLVMOutputStyle.cpp
16 PdbYaml.cpp
17 PrettyBuiltinDumper.cpp
18 PrettyClassDefinitionDumper.cpp
19 PrettyClassLayoutGraphicalDumper.cpp
20 PrettyCompilandDumper.cpp
21 PrettyEnumDumper.cpp
22 PrettyExternalSymbolDumper.cpp
23 PrettyFunctionDumper.cpp
24 PrettyTypeDumper.cpp
25 PrettyTypedefDumper.cpp
26 PrettyVariableDumper.cpp
27 StreamUtil.cpp
28 YAMLOutputStyle.cpp
29 )
30
31 if(LLVM_USE_SANITIZE_COVERAGE)
32 add_subdirectory(fuzzer)
33 endif()
+0
-59
tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp less more
None //===-- CompactTypeDumpVisitor.cpp - CodeView type info dumper --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "CompactTypeDumpVisitor.h"
10 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
11 #include "llvm/Support/FormatVariadic.h"
12 #include "llvm/Support/ScopedPrinter.h"
13
14 using namespace llvm;
15 using namespace llvm::codeview;
16 using namespace llvm::pdb;
17
18 static const EnumEntry LeafTypeNames[] = {
19 #define CV_TYPE(enum, val) {#enum, enum},
20 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
21 };
22
23 static StringRef getLeafName(TypeLeafKind K) {
24 for (const auto &E : LeafTypeNames) {
25 if (E.Value == K)
26 return E.Name;
27 }
28 return StringRef();
29 }
30
31 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
32 ScopedPrinter *W)
33 : CompactTypeDumpVisitor(Types, TypeIndex(TypeIndex::FirstNonSimpleIndex),
34 W) {}
35
36 CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types,
37 TypeIndex FirstTI,
38 ScopedPrinter *W)
39 : W(W), TI(FirstTI), Offset(0), Types(Types) {}
40
41 Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
42 return Error::success();
43 }
44
45 Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) {
46 uint32_t I = TI.getIndex();
47 StringRef Leaf = getLeafName(Record.Type);
48 StringRef Name = Types.getTypeName(TI);
49 W->printString(
50 llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I,
51 Record.length(), Offset, Leaf, Name)
52 .str());
53
54 Offset += Record.length();
55 TI.setIndex(TI.getIndex() + 1);
56
57 return Error::success();
58 }
+0
-49
tools/llvm-pdbdump/CompactTypeDumpVisitor.h less more
None //===-- CompactTypeDumpVisitor.h - CodeView type info dumper ----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H
10 #define LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H
11
12 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
13 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
14 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
15
16 namespace llvm {
17 class ScopedPrinter;
18 namespace codeview {
19 class TypeCollection;
20 }
21
22 namespace pdb {
23
24 /// Dumper for CodeView type streams found in COFF object files and PDB files.
25 /// Dumps records on a single line, and ignores member records.
26 class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
27 public:
28 CompactTypeDumpVisitor(codeview::TypeCollection &Types, ScopedPrinter *W);
29 CompactTypeDumpVisitor(codeview::TypeCollection &Types,
30 codeview::TypeIndex FirstTI, ScopedPrinter *W);
31
32 /// Paired begin/end actions for all types. Receives all record data,
33 /// including the fixed-length record prefix.
34 Error visitTypeBegin(codeview::CVType &Record) override;
35 Error visitTypeEnd(codeview::CVType &Record) override;
36
37 private:
38 ScopedPrinter *W;
39
40 codeview::TypeIndex TI;
41 uint32_t Offset;
42 codeview::TypeCollection &Types;
43 };
44
45 } // end namespace pdb
46 } // end namespace llvm
47
48 #endif
+0
-537
tools/llvm-pdbdump/Diff.cpp less more
None //===- Diff.cpp - PDB diff utility ------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "Diff.h"
10
11 #include "StreamUtil.h"
12 #include "llvm-pdbdump.h"
13
14 #include "llvm/DebugInfo/PDB/Native/Formatters.h"
15 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
16 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
17 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
18 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
19
20 #include "llvm/Support/FormatAdapters.h"
21 #include "llvm/Support/FormatProviders.h"
22 #include "llvm/Support/FormatVariadic.h"
23
24 using namespace llvm;
25 using namespace llvm::pdb;
26
27 namespace llvm {
28 template <> struct format_provider {
29 static void format(const PdbRaw_FeatureSig &Sig, raw_ostream &Stream,
30 StringRef Style) {
31 switch (Sig) {
32 case PdbRaw_FeatureSig::MinimalDebugInfo:
33 Stream << "MinimalDebugInfo";
34 break;
35 case PdbRaw_FeatureSig::NoTypeMerge:
36 Stream << "NoTypeMerge";
37 break;
38 case PdbRaw_FeatureSig::VC110:
39 Stream << "VC110";
40 break;
41 case PdbRaw_FeatureSig::VC140:
42 Stream << "VC140";
43 break;
44 }
45 }
46 };
47 }
48
49 template using ValueOfRange = llvm::detail::ValueOfRange;
50
51 template
52 static void set_differences(Range &&R1, Range &&R2,
53 SmallVectorImpl> *OnlyLeft,
54 SmallVectorImpl> *OnlyRight,
55 SmallVectorImpl> *Intersection,
56 Comp Comparator) {
57
58 std::sort(R1.begin(), R1.end(), Comparator);
59 std::sort(R2.begin(), R2.end(), Comparator);
60
61 if (OnlyLeft) {
62 OnlyLeft->reserve(R1.size());
63 auto End = std::set_difference(R1.begin(), R1.end(), R2.begin(), R2.end(),
64 OnlyLeft->begin(), Comparator);
65 OnlyLeft->set_size(std::distance(OnlyLeft->begin(), End));
66 }
67 if (OnlyRight) {
68 OnlyLeft->reserve(R2.size());
69 auto End = std::set_difference(R2.begin(), R2.end(), R1.begin(), R1.end(),
70 OnlyRight->begin(), Comparator);
71 OnlyRight->set_size(std::distance(OnlyRight->begin(), End));
72 }
73 if (Intersection) {
74 Intersection->reserve(std::min(R1.size(), R2.size()));
75 auto End = std::set_intersection(R1.begin(), R1.end(), R2.begin(), R2.end(),
76 Intersection->begin(), Comparator);
77 Intersection->set_size(std::distance(Intersection->begin(), End));
78 }
79 }
80
81 template
82 static void
83 set_differences(Range &&R1, Range &&R2,
84 SmallVectorImpl> *OnlyLeft,
85 SmallVectorImpl> *OnlyRight,
86 SmallVectorImpl> *Intersection = nullptr) {
87 std::less> Comp;
88 set_differences(std::forward(R1), std::forward(R2), OnlyLeft,
89 OnlyRight, Intersection, Comp);
90 }
91
92 DiffStyle::DiffStyle(PDBFile &File1, PDBFile &File2)
93 : File1(File1), File2(File2) {}
94
95 Error DiffStyle::dump() {
96 if (auto EC = diffSuperBlock())
97 return EC;
98
99 if (auto EC = diffFreePageMap())
100 return EC;
101
102 if (auto EC = diffStreamDirectory())
103 return EC;
104
105 if (auto EC = diffStringTable())
106 return EC;
107
108 if (auto EC = diffInfoStream())
109 return EC;
110
111 if (auto EC = diffDbiStream())
112 return EC;
113
114 if (auto EC = diffSectionContribs())
115 return EC;
116
117 if (auto EC = diffSectionMap())
118 return EC;
119
120 if (auto EC = diffFpoStream())
121 return EC;
122
123 if (auto EC = diffTpiStream(StreamTPI))
124 return EC;
125
126 if (auto EC = diffTpiStream(StreamIPI))
127 return EC;
128
129 if (auto EC = diffPublics())
130 return EC;
131
132 if (auto EC = diffGlobals())
133 return EC;
134
135 return Error::success();
136 }
137
138 template
139 static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2, T V1,
140 T V2) {
141 if (V1 == V2) {
142 outs() << formatv(" {0}: No differences detected!\n", Label);
143 return false;
144 }
145
146 outs().indent(2) << Label << "\n";
147 outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(), V1);
148 outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(), V2);
149 return true;
150 }
151
152 template
153 static bool diffAndPrint(StringRef Label, PDBFile &File1, PDBFile &File2,
154 ArrayRef V1, ArrayRef V2) {
155 if (V1 == V2) {
156 outs() << formatv(" {0}: No differences detected!\n", Label);
157 return false;
158 }
159
160 outs().indent(2) << Label << "\n";
161 outs().indent(4) << formatv("{0}: {1}\n", File1.getFilePath(),
162 make_range(V1.begin(), V1.end()));
163 outs().indent(4) << formatv("{0}: {1}\n", File2.getFilePath(),
164 make_range(V2.begin(), V2.end()));
165 return true;
166 }
167
168 template
169 static bool printSymmetricDifferences(PDBFile &File1, PDBFile &File2,
170 T &&OnlyRange1, T &&OnlyRange2,
171 StringRef Label) {
172 bool HasDiff = false;
173 if (!OnlyRange1.empty()) {
174 HasDiff = true;
175 outs() << formatv(" {0} {1}(s) only in ({2})\n", OnlyRange1.size(), Label,
176 File1.getFilePath());
177 for (const auto &Item : OnlyRange1)
178 outs() << formatv(" {0}\n", Label, Item);
179 }
180 if (!OnlyRange2.empty()) {
181 HasDiff = true;
182 outs() << formatv(" {0} {1}(s) only in ({2})\n", OnlyRange2.size(),
183 File2.getFilePath());
184 for (const auto &Item : OnlyRange2)
185 outs() << formatv(" {0}\n", Item);
186 }
187 return HasDiff;
188 }
189
190 Error DiffStyle::diffSuperBlock() {
191 outs() << "MSF Super Block: Searching for differences...\n";
192 bool Diffs = false;
193
194 Diffs |= diffAndPrint("Block Size", File1, File2, File1.getBlockSize(),
195 File2.getBlockSize());
196 Diffs |= diffAndPrint("Block Count", File1, File2, File1.getBlockCount(),
197 File2.getBlockCount());
198 Diffs |= diffAndPrint("Unknown 1", File1, File2, File1.getUnknown1(),
199 File2.getUnknown1());
200
201 if (opts::diff::Pedantic) {
202 Diffs |= diffAndPrint("Free Block Map", File1, File2,
203 File1.getFreeBlockMapBlock(),
204 File2.getFreeBlockMapBlock());
205 Diffs |= diffAndPrint("Directory Size", File1, File2,
206 File1.getNumDirectoryBytes(),
207 File2.getNumDirectoryBytes());
208 Diffs |= diffAndPrint("Block Map Addr", File1, File2,
209 File1.getBlockMapOffset(), File2.getBlockMapOffset());
210 }
211 if (!Diffs)
212 outs() << "MSF Super Block: No differences detected...\n";
213 return Error::success();
214 }
215
216 Error DiffStyle::diffStreamDirectory() {
217 SmallVector P;
218 SmallVector Q;
219 discoverStreamPurposes(File1, P);
220 discoverStreamPurposes(File2, Q);
221 outs() << "Stream Directory: Searching for differences...\n";
222
223 bool HasDifferences = false;
224 if (opts::diff::Pedantic) {
225 size_t Min = std::min(P.size(), Q.size());
226 for (size_t I = 0; I < Min; ++I) {
227 StringRef Names[] = {P[I], Q[I]};
228 uint32_t Sizes[] = {File1.getStreamByteSize(I),
229 File2.getStreamByteSize(I)};
230 bool NamesDiffer = Names[0] != Names[1];
231 bool SizesDiffer = Sizes[0] != Sizes[1];
232 if (NamesDiffer) {
233 HasDifferences = true;
234 outs().indent(2) << formatv("Stream {0} - {1}: {2}, {3}: {4}\n", I,
235 File1.getFilePath(), Names[0],
236 File2.getFilePath(), Names[1]);
237 continue;
238 }
239 if (SizesDiffer) {
240 HasDifferences = true;
241 outs().indent(2) << formatv(
242 "Stream {0} ({1}): {2}: {3} bytes, {4}: {5} bytes\n", I, Names[0],
243 File1.getFilePath(), Sizes[0], File2.getFilePath(), Sizes[1]);
244 continue;
245 }
246 }
247
248 ArrayRef MaxNames = (P.size() > Q.size() ? P : Q);
249 size_t Max = std::max(P.size(), Q.size());
250 PDBFile &MaxFile = (P.size() > Q.size() ? File1 : File2);
251 StringRef MinFileName =
252 (P.size() < Q.size() ? File1.getFilePath() : File2.getFilePath());
253 for (size_t I = Min; I < Max; ++I) {
254 HasDifferences = true;
255 StringRef StreamName = MaxNames[I];
256
257 outs().indent(2) << formatv(
258 "Stream {0} - {1}: , {2}: Index {3}, {4} bytes\n",
259 StreamName, MinFileName, MaxFile.getFilePath(), I,
260 MaxFile.getStreamByteSize(I));
261 }
262 if (!HasDifferences)
263 outs() << "Stream Directory: No differences detected...\n";
264 } else {
265 auto PI = to_vector<32>(enumerate(P));
266 auto QI = to_vector<32>(enumerate(Q));
267
268 typedef decltype(PI) ContainerType;
269 typedef typename ContainerType::value_type value_type;
270
271 auto Comparator = [](const value_type &I1, const value_type &I2) {
272 return I1.value() < I2.value();
273 };
274
275 decltype(PI) OnlyP;
276 decltype(QI) OnlyQ;
277 decltype(PI) Common;
278
279 set_differences(PI, QI, &OnlyP, &OnlyQ, &Common, Comparator);
280
281 if (!OnlyP.empty()) {
282 HasDifferences = true;
283 outs().indent(2) << formatv("{0} Stream(s) only in ({1})\n", OnlyP.size(),
284 File1.getFilePath());
285 for (auto &Item : OnlyP) {
286 outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(),
287 Item.value());
288 }
289 }
290
291 if (!OnlyQ.empty()) {
292 HasDifferences = true;
293 outs().indent(2) << formatv("{0} Streams(s) only in ({1})\n",
294 OnlyQ.size(), File2.getFilePath());
295 for (auto &Item : OnlyQ) {
296 outs().indent(4) << formatv("Stream {0} - {1}\n", Item.index(),
297 Item.value());
298 }
299 }
300 if (!Common.empty()) {
301 outs().indent(2) << formatv("Found {0} common streams. Searching for "
302 "intra-stream differences.\n",
303 Common.size());
304 bool HasCommonDifferences = false;
305 for (const auto &Left : Common) {
306 // Left was copied from the first range so its index refers to a stream
307 // index in the first file. Find the corresponding stream index in the
308 // second file.
309 auto Range =
310 std::equal_range(QI.begin(), QI.end(), Left,
311 [](const value_type &L, const value_type &R) {
312 return L.value() < R.value();
313 });
314 const auto &Right = *Range.first;
315 assert(Left.value() == Right.value());
316 uint32_t LeftSize = File1.getStreamByteSize(Left.index());
317 uint32_t RightSize = File2.getStreamByteSize(Right.index());
318 if (LeftSize != RightSize) {
319 HasDifferences = true;
320 HasCommonDifferences = true;
321 outs().indent(4) << formatv("{0} ({1}: {2} bytes, {3}: {4} bytes)\n",
322 Left.value(), File1.getFilePath(),
323 LeftSize, File2.getFilePath(), RightSize);
324 }
325 }
326 if (!HasCommonDifferences)
327 outs().indent(2) << "Common Streams: No differences detected!\n";
328 }
329 if (!HasDifferences)
330 outs() << "Stream Directory: No differences detected!\n";
331 }
332
333 return Error::success();
334 }
335
336 Error DiffStyle::diffStringTable() {
337 auto ExpectedST1 = File1.getStringTable();
338 auto ExpectedST2 = File2.getStringTable();
339 outs() << "String Table: Searching for differences...\n";
340 bool Has1 = !!ExpectedST1;
341 bool Has2 = !!ExpectedST2;
342 if (!(Has1 && Has2)) {
343 // If one has a string table and the other doesn't, we can print less
344 // output.
345 if (Has1 != Has2) {
346 if (Has1) {
347 outs() << formatv(" {0}: ({1} strings)\n", File1.getFilePath(),
348 ExpectedST1->getNameCount());
349 outs() << formatv(" {0}: (string table not present)\n",
350 File2.getFilePath());
351 } else {
352 outs() << formatv(" {0}: (string table not present)\n",
353 File1.getFilePath());
354 outs() << formatv(" {0}: ({1})\n", File2.getFilePath(),
355 ExpectedST2->getNameCount());
356 }
357 }
358 consumeError(ExpectedST1.takeError());
359 consumeError(ExpectedST2.takeError());
360 return Error::success();
361 }
362
363 bool HasDiff = false;
364 auto &ST1 = *ExpectedST1;
365 auto &ST2 = *ExpectedST2;
366
367 if (ST1.getByteSize() != ST2.getByteSize()) {
368 outs() << " Stream Size\n";
369 outs() << formatv(" {0} - {1} byte(s)\n", File1.getFilePath(),
370 ST1.getByteSize());
371 outs() << formatv(" {0} - {1} byte(s)\n", File2.getFilePath(),
372 ST2.getByteSize());
373 outs() << formatv(" Difference: {0} bytes\n",
374 AbsoluteDifference(ST1.getByteSize(), ST2.getByteSize()));
375 HasDiff = true;
376 }
377 HasDiff |= diffAndPrint("Hash Version", File1, File2, ST1.getHashVersion(),
378 ST1.getHashVersion());
379 HasDiff |= diffAndPrint("Signature", File1, File2, ST1.getSignature(),
380 ST1.getSignature());
381
382 // Both have a valid string table, dive in and compare individual strings.
383
384 auto IdList1 = ST1.name_ids();
385 auto IdList2 = ST2.name_ids();
386 if (opts::diff::Pedantic) {
387 // In pedantic mode, we compare index by index (i.e. the strings are in the
388 // same order
389 // in both tables.
390 uint32_t Max = std::max(IdList1.size(), IdList2.size());
391 for (uint32_t I = 0; I < Max; ++I) {
392 Optional Id1, Id2;
393 StringRef S1, S2;
394 if (I < IdList1.size()) {
395 Id1 = IdList1[I];
396 if (auto Result = ST1.getStringForID(*Id1))
397 S1 = *Result;
398 else
399 return Result.takeError();
400 }
401 if (I < IdList2.size()) {
402 Id2 = IdList2[I];
403 if (auto Result = ST2.getStringForID(*Id2))
404 S2 = *Result;
405 else
406 return Result.takeError();
407 }
408 if (Id1 == Id2 && S1 == S2)
409 continue;
410
411 std::string OutId1 =
412 Id1 ? formatv("{0}", *Id1).str() : "(index not present)";
413 std::string OutId2 =
414 Id2 ? formatv("{0}", *Id2).str() : "(index not present)";
415 outs() << formatv(" String {0}\n", I);
416 outs() << formatv(" {0}: Hash - {1}, Value - {2}\n",
417 File1.getFilePath(), OutId1, S1);
418 outs() << formatv(" {0}: Hash - {1}, Value - {2}\n",
419 File2.getFilePath(), OutId2, S2);
420 HasDiff = true;
421 }
422 } else {
423 std::vector Strings1, Strings2;
424 Strings1.reserve(IdList1.size());
425 Strings2.reserve(IdList2.size());
426 for (auto ID : IdList1) {
427 auto S = ST1.getStringForID(ID);
428 if (!S)
429 return S.takeError();
430 Strings1.push_back(*S);
431 }
432 for (auto ID : IdList2) {
433 auto S = ST2.getStringForID(ID);
434 if (!S)
435 return S.takeError();
436 Strings2.push_back(*S);
437 }
438
439 SmallVector OnlyP;
440 SmallVector OnlyQ;
441 auto End1 = std::remove(Strings1.begin(), Strings1.end(), "");
442 auto End2 = std::remove(Strings2.begin(), Strings2.end(), "");
443 uint32_t Empty1 = std::distance(End1, Strings1.end());
444 uint32_t Empty2 = std::distance(End2, Strings2.end());
445 Strings1.erase(End1, Strings1.end());
446 Strings2.erase(End2, Strings2.end());
447 set_differences(Strings1, Strings2, &OnlyP, &OnlyQ);
448 printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "String");
449
450 if (Empty1 != Empty2) {
451 PDBFile &MoreF = (Empty1 > Empty2) ? File1 : File2;
452 PDBFile &LessF = (Empty1 < Empty2) ? File1 : File2;
453 uint32_t Difference = AbsoluteDifference(Empty1, Empty2);
454 outs() << formatv(" {0} had {1} more empty strings than {2}\n",
455 MoreF.getFilePath(), Difference, LessF.getFilePath());
456 }
457 }
458 if (!HasDiff)
459 outs() << "String Table: No differences detected!\n";
460 return Error::success();
461 }
462
463 Error DiffStyle::diffFreePageMap() { return Error::success(); }
464
465 Error DiffStyle::diffInfoStream() {
466 auto ExpectedInfo1 = File1.getPDBInfoStream();
467 auto ExpectedInfo2 = File2.getPDBInfoStream();
468
469 outs() << "PDB Stream: Searching for differences...\n";
470 bool Has1 = !!ExpectedInfo1;
471 bool Has2 = !!ExpectedInfo2;
472 if (!(Has1 && Has2)) {
473 if (Has1 != Has2)
474 outs() << formatv("{0} does not have a PDB Stream!\n",
475 Has1 ? File1.getFilePath() : File2.getFilePath());
476 consumeError(ExpectedInfo2.takeError());
477 consumeError(ExpectedInfo2.takeError());
478 return Error::success();
479 }
480
481 bool HasDiff = false;
482 auto &IS1 = *ExpectedInfo1;
483 auto &IS2 = *ExpectedInfo2;
484 if (IS1.getStreamSize() != IS2.getStreamSize()) {
485 outs() << " Stream Size\n";
486 outs() << formatv(" {0} - {1} byte(s)\n", File1.getFilePath(),
487 IS1.getStreamSize());
488 outs() << formatv(" {0} - {1} byte(s)\n", File2.getFilePath(),
489 IS2.getStreamSize());
490 outs() << formatv(
491 " Difference: {0} bytes\n",
492 AbsoluteDifference(IS1.getStreamSize(), IS2.getStreamSize()));
493 HasDiff = true;
494 }
495 HasDiff |= diffAndPrint("Age", File1, File2, IS1.getAge(), IS2.getAge());
496 HasDiff |= diffAndPrint("Guid", File1, File2, IS1.getGuid(), IS2.getGuid());
497 HasDiff |= diffAndPrint("Signature", File1, File2, IS1.getSignature(),
498 IS2.getSignature());
499 HasDiff |=
500 diffAndPrint("Version", File1, File2, IS1.getVersion(), IS2.getVersion());
501 HasDiff |= diffAndPrint("Features", File1, File2, IS1.getFeatureSignatures(),
502 IS2.getFeatureSignatures());
503 HasDiff |= diffAndPrint("Named Stream Byte Size", File1, File2,
504 IS1.getNamedStreamMapByteSize(),
505 IS2.getNamedStreamMapByteSize());
506 SmallVector NS1;
507 SmallVector NS2;
508 for (const auto &X : IS1.getNamedStreams().entries())
509 NS1.push_back(X.getKey());
510 for (const auto &X : IS2.getNamedStreams().entries())
511 NS2.push_back(X.getKey());
512 SmallVector OnlyP;
513 SmallVector OnlyQ;
514 set_differences(NS1, NS2, &OnlyP, &OnlyQ);
515 printSymmetricDifferences(File1, File2, OnlyP, OnlyQ, "Named Streams");
516 if (!HasDiff)
517 outs() << "PDB Stream: No differences detected!\n";
518
519 return Error::success();
520 }
521
522 Error DiffStyle::diffDbiStream() { return Error::success(); }
523
524 Error DiffStyle::diffSectionContribs() { return Error::success(); }
525
526 Error DiffStyle::diffSectionMap() { return Error::success(); }
527
528 Error DiffStyle::diffFpoStream() { return Error::success(); }
529
530 Error DiffStyle::diffTpiStream(int Index) { return Error::success(); }
531
532 Error DiffStyle::diffModuleInfoStream(int Index) { return Error::success(); }
533
534 Error DiffStyle::diffPublics() { return Error::success(); }
535
536 Error DiffStyle::diffGlobals() { return Error::success(); }
+0
-45
tools/llvm-pdbdump/Diff.h less more
None //===- Diff.h - PDB diff utility --------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_DIFF_H
11
12 #include "OutputStyle.h"
13
14 namespace llvm {
15 namespace pdb {
16 class PDBFile;
17 class DiffStyle : public OutputStyle {
18 public:
19 explicit DiffStyle(PDBFile &File1, PDBFile &File2);
20
21 Error dump() override;
22
23 private:
24 Error diffSuperBlock();
25 Error diffStreamDirectory();
26 Error diffStringTable();
27 Error diffFreePageMap();
28 Error diffInfoStream();
29 Error diffDbiStream();
30 Error diffSectionContribs();
31 Error diffSectionMap();
32 Error diffFpoStream();
33 Error diffTpiStream(int Index);
34 Error diffModuleInfoStream(int Index);
35 Error diffPublics();
36 Error diffGlobals();
37
38 PDBFile &File1;
39 PDBFile &File2;
40 };
41 }
42 }
43
44 #endif
+0
-23
tools/llvm-pdbdump/LLVMBuild.txt less more
None ;===- ./tools/llvm-pdbdump/LLVMBuild.txt -----------------------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [component_0]
18 type = Tool
19 name = llvm-pdbdump
20 parent = Tools
21 required_libraries = DebugInfoMSF DebugInfoPDB
22
+0
-1177
tools/llvm-pdbdump/LLVMOutputStyle.cpp less more
None //===- LLVMOutputStyle.cpp ------------------------------------ *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "LLVMOutputStyle.h"
10
11 #include "CompactTypeDumpVisitor.h"
12 #include "StreamUtil.h"
13 #include "llvm-pdbdump.h"
14
15 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
16 #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
17 #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
18 #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
19 #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
20 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
21 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
22 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
23 #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
24 #include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
25 #include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
26 #include "llvm/DebugInfo/CodeView/EnumTables.h"
27 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
28 #include "llvm/DebugInfo/CodeView/Line.h"
29 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
30 #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
31 #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
32 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
33 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
34 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
35 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
36 #include "llvm/DebugInfo/PDB/Native/EnumTables.h"
37 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
38 #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
39 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
40 #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
41 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
42 #include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
43 #include "llvm/DebugInfo/PDB/Native/RawError.h"
44 #include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
45 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
46 #include "llvm/DebugInfo/PDB/PDBExtras.h"
47 #include "llvm/Object/COFF.h"
48 #include "llvm/Support/BinaryStreamReader.h"
49 #include "llvm/Support/FormatVariadic.h"
50
51 #include
52
53 using namespace llvm;
54 using namespace llvm::codeview;
55 using namespace llvm::msf;
56 using namespace llvm::pdb;
57
58 namespace {
59 struct PageStats {
60 explicit PageStats(const BitVector &FreePages)
61 : Upm(FreePages), ActualUsedPages(FreePages.size()),
62 MultiUsePages(FreePages.size()), UseAfterFreePages(FreePages.size()) {
63 const_cast(Upm).flip();
64 // To calculate orphaned pages, we start with the set of pages that the
65 // MSF thinks are used. Each time we find one that actually *is* used,
66 // we unset it. Whichever bits remain set at the end are orphaned.
67 OrphanedPages = Upm;
68 }
69
70 // The inverse of the MSF File's copy of the Fpm. The basis for which we
71 // determine the allocation status of each page.
72 const BitVector Upm;
73
74 // Pages which are marked as used in the FPM and are used at least once.
75 BitVector ActualUsedPages;
76
77 // Pages which are marked as used in the FPM but are used more than once.
78 BitVector MultiUsePages;
79
80 // Pages which are marked as used in the FPM but are not used at all.
81 BitVector OrphanedPages;
82
83 // Pages which are marked free in the FPM but are used.
84 BitVector UseAfterFreePages;
85 };
86
87 class C13RawVisitor : public DebugSubsectionVisitor {
88 public:
89 C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &TPI,
90 LazyRandomTypeCollection &IPI)
91 : P(P), TPI(TPI), IPI(IPI) {}
92
93 Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override {
94 if (!opts::checkModuleSubsection(opts::ModuleSubsection::Unknown))
95 return Error::success();
96 DictScope DD(P, "Unknown");
97 P.printHex("Kind", static_cast(Unknown.kind()));
98 ArrayRef Data;
99 BinaryStreamReader Reader(Unknown.getData());
100 consumeError(Reader.readBytes(Data, Reader.bytesRemaining()));
101 P.printBinaryBlock("Data", Data);
102 return Error::success();
103 }
104
105 Error visitLines(DebugLinesSubsectionRef &Lines,
106 const DebugSubsectionState &State) override {
107 if (!opts::checkModuleSubsection(opts::ModuleSubsection::Lines))
108 return Error::success();
109
110 DictScope DD(P, "Lines");
111
112 P.printNumber("RelocSegment", Lines.header()->RelocSegment);
113 P.printNumber("RelocOffset", Lines.header()->RelocOffset);
114 P.printNumber("CodeSize", Lines.header()->CodeSize);
115 P.printBoolean("HasColumns", Lines.hasColumnInfo());
116
117 for (const auto &L : Lines) {
118 DictScope DDDD(P, "FileEntry");
119
120 if (auto EC = printFileName("FileName", L.NameIndex, State))
121 return EC;
122
123 for (const auto &N : L.LineNumbers) {
124 DictScope DDD(P, "Line");
125 LineInfo LI(N.Flags);
126 P.printNumber("Offset", N.Offset);
127 if (LI.isAlwaysStepInto())
128 P.printString("StepInto", StringRef("Always"));
129 else if (LI.isNeverStepInto())
130 P.printString("StepInto", StringRef("Never"));
131 else
132 P.printNumber("LineNumberStart", LI.getStartLine());
133 P.printNumber("EndDelta", LI.getLineDelta());
134 P.printBoolean("IsStatement", LI.isStatement());
135 }
136 for (const auto &C : L.Columns) {
137 DictScope DDD(P, "Column");
138 P.printNumber("Start", C.StartColumn);
139 P.printNumber("End", C.EndColumn);
140 }
141 }
142
143 return Error::success();
144 }
145
146 Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
147 const DebugSubsectionState &State) override {
148 if (!opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums))
149 return Error::success();
150
151 DictScope DD(P, "FileChecksums");
152 for (const auto &CS : Checksums) {
153 DictScope DDD(P, "Checksum");
154 if (auto Result = getNameFromStringTable(CS.FileNameOffset, State))
155 P.printString("FileName", *Result);
156 else
157 return Result.takeError();
158 P.printEnum("Kind", uint8_t(CS.Kind), getFileChecksumNames());
159 P.printBinaryBlock("Checksum", CS.Checksum);
160 }
161 return Error::success();
162 }
163
164 Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
165 const DebugSubsectionState &State) override {
166 if (!opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines))
167 return Error::success();
168
169 DictScope D(P, "InlineeLines");
170 P.printBoolean("HasExtraFiles", Inlinees.hasExtraFiles());
171 ListScope LS(P, "Lines");
172 for (const auto &L : Inlinees) {
173 DictScope DDD(P, "Inlinee");
174 if (auto EC = printFileName("FileName", L.Header->FileID, State))
175 return EC;
176
177 if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee))
178 return EC;
179 P.printNumber("SourceLine", L.Header->SourceLineNum);
180 if (Inlinees.hasExtraFiles()) {
181 ListScope DDDD(P, "ExtraFiles");
182 for (const auto &EF : L.ExtraFiles) {
183 if (auto EC = printFileName("File", EF, State))
184 return EC;
185 }
186 }
187 }
188 return Error::success();
189 }
190
191 Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
192 const DebugSubsectionState &State) override {
193 if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports))
194 return Error::success();
195
196 ListScope D(P, "CrossModuleExports");
197 for (const auto &M : CSE) {
198 DictScope D(P, "Export");
199 P.printHex("Local", M.Local);
200 P.printHex("Global", M.Global);
201 }
202 return Error::success();
203 }
204
205 Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSI,
206 const DebugSubsectionState &State) override {
207 if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports))
208 return Error::success();
209
210 ListScope L(P, "CrossModuleImports");
211 for (const auto &M : CSI) {
212 DictScope D(P, "ModuleImport");
213 auto Name = getNameFromStringTable(M.Header->ModuleNameOffset, State);
214 if (!Name)
215 return Name.takeError();
216 P.printString("Module", *Name);
217 P.printHexList("Imports", M.Imports);
218 }
219 return Error::success();
220 }
221
222 Error visitFrameData(DebugFrameDataSubsectionRef &FD,
223 const DebugSubsectionState &State) override {
224 if (!opts::checkModuleSubsection(opts::ModuleSubsection::FrameData))
225 return Error::success();
226
227 ListScope L(P, "FrameData");
228 for (const auto &Frame : FD) {
229 DictScope D(P, "Frame");
230 auto Name = getNameFromStringTable(Frame.FrameFunc, State);
231 if (!Name)
232 return joinErrors(make_error(raw_error_code::invalid_format,
233 "Invalid Frame.FrameFunc index"),
234 Name.takeError());
235 P.printNumber("Rva", Frame.RvaStart);
236 P.printNumber("CodeSize", Frame.CodeSize);
237 P.printNumber("LocalSize", Frame.LocalSize);
238 P.printNumber("ParamsSize", Frame.ParamsSize);
239 P.printNumber("MaxStackSize", Frame.MaxStackSize);
240 P.printString("FrameFunc", *Name);
241 P.printNumber("PrologSize", Frame.PrologSize);
242 P.printNumber("SavedRegsSize", Frame.SavedRegsSize);
243 P.printNumber("Flags", Frame.Flags);
244 }
245 return Error::success();
246 }
247
248 Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
249 const DebugSubsectionState &State) override {
250 if (!opts::checkModuleSubsection(opts::ModuleSubsection::Symbols))
251 return Error::success();
252 ListScope L(P, "Symbols");
253
254 // This section should not actually appear in a PDB file, it really only
255 // appears in object files. But we support it here for testing. So we
256 // specify the Object File container type.
257 codeview::CVSymbolDumper SD(P, TPI, CodeViewContainer::ObjectFile, nullptr,
258 false);
259 for (auto S : Symbols) {
260 DictScope LL(P, "");
261 if (auto EC = SD.dump(S)) {
262 return make_error(
263 raw_error_code::corrupt_file,
264 "DEBUG_S_SYMBOLS subsection contained corrupt symbol record");
265 }
266 }
267 return Error::success();
268 }
269
270 Error visitStringTable(DebugStringTableSubsectionRef &Strings,
271 const DebugSubsectionState &State) override {
272 if (!opts::checkModuleSubsection(opts::ModuleSubsection::StringTable))
273 return Error::success();
274
275 ListScope D(P, "String Table");
276 BinaryStreamReader Reader(Strings.getBuffer());
277 StringRef S;
278 consumeError(Reader.readCString(S));
279 while (Reader.bytesRemaining() > 0) {
280 consumeError(Reader.readCString(S));
281 if (S.empty() && Reader.bytesRemaining() < 4)
282 break;
283 P.printString(S);
284 }
285 return Error::success();
286 }
287
288 private:
289 Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
290 CompactTypeDumpVisitor CTDV(IPI, Index, &P);
291 DictScope D(P, Label);
292 if (IPI.contains(Index)) {
293 CVType Type = IPI.getType(Index);
294 if (auto EC = codeview::visitTypeRecord(Type, CTDV))
295 return EC;
296 } else {
297 P.printString(
298 llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex())
299 .str());
300 }
301 return Error::success();
302 }
303 Error printFileName(StringRef Label, uint32_t Offset,
304 const DebugSubsectionState &State) {
305 if (auto Result = getNameFromChecksumsBuffer(Offset, State)) {
306 P.printString(Label, *Result);
307 return Error::success();
308 } else
309 return Result.takeError();
310 }
311
312 Expected
313 getNameFromStringTable(uint32_t Offset, const DebugSubsectionState &State) {
314 return State.strings().getString(Offset);
315 }
316
317 Expected
318 getNameFromChecksumsBuffer(uint32_t Offset,
319 const DebugSubsectionState &State) {
320 auto Array = State.checksums().getArray();
321 auto ChecksumIter = Array.at(Offset);
322 if (ChecksumIter == Array.end())
323 return make_error(raw_error_code::invalid_format);
324 const auto &Entry = *ChecksumIter;
325 return getNameFromStringTable(Entry.FileNameOffset, State);
326 }
327
328 ScopedPrinter &P;
329 LazyRandomTypeCollection &TPI;
330 LazyRandomTypeCollection &IPI;
331 };
332 }
333
334 static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) {
335 if (Stats.Upm.test(UsedIndex)) {
336 if (Stats.ActualUsedPages.test(UsedIndex))
337 Stats.MultiUsePages.set(UsedIndex);
338 Stats.ActualUsedPages.set(UsedIndex);
339 Stats.OrphanedPages.reset(UsedIndex);
340 } else {
341 // The MSF doesn't think this page is used, but it is.
342 Stats.UseAfterFreePages.set(UsedIndex);
343 }
344 }
345
346 static void printSectionOffset(llvm::raw_ostream &OS,
347 const SectionOffset &Off) {
348 OS << Off.Off << ", " << Off.Isect;
349 }
350
351 LLVMOutputStyle::LLVMOutputStyle(PDBFile &File) : File(File), P(outs()) {}
352
353 Error LLVMOutputStyle::dump() {
354 if (auto EC = dumpFileHeaders())
355 return EC;
356
357 if (auto EC = dumpStreamSummary())
358 return EC;
359
360 if (auto EC = dumpFreePageMap())
361 return EC;
362
363 if (auto EC = dumpStreamBlocks())
364 return EC;
365
366 if (auto EC = dumpBlockRanges())
367 return EC;
368
369 if (auto EC = dumpStreamBytes())
370 return EC;
371
372 if (auto EC = dumpStringTable())
373 return EC;
374
375 if (auto EC = dumpInfoStream())
376 return EC;
377
378 if (auto EC = dumpTpiStream(StreamTPI))
379 return EC;
380
381 if (auto EC = dumpTpiStream(StreamIPI))
382 return EC;
383
384 if (auto EC = dumpDbiStream())
385 return EC;
386
387 if (auto EC = dumpSectionContribs())
388 return EC;
389
390 if (auto EC = dumpSectionMap())
391 return EC;
392
393 if (auto EC = dumpGlobalsStream())
394 return EC;
395
396 if (auto EC = dumpPublicsStream())
397 return EC;
398
399 if (auto EC = dumpSectionHeaders())
400 return EC;
401
402 if (auto EC = dumpFpoStream())
403 return EC;
404
405 flush();
406
407 return Error::success();
408 }
409
410 Error LLVMOutputStyle::dumpFileHeaders() {
411 if (!opts::raw::DumpHeaders)
412 return Error::success();
413
414 DictScope D(P, "FileHeaders");
415 P.printNumber("BlockSize", File.getBlockSize());
416 P.printNumber("FreeBlockMap", File.getFreeBlockMapBlock());
417 P.printNumber("NumBlocks", File.getBlockCount());
418 P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
419 P.printNumber("Unknown1", File.getUnknown1());
420 P.printNumber("BlockMapAddr", File.getBlockMapIndex());
421 P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
422
423 // The directory is not contiguous. Instead, the block map contains a
424 // contiguous list of block numbers whose contents, when concatenated in
425 // order, make up the directory.
426 P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
427 P.printNumber("NumStreams", File.getNumStreams());
428 return Error::success();
429 }
430
431 Error LLVMOutputStyle::dumpStreamSummary() {
432 if (!opts::raw::DumpStreamSummary)
433 return Error::success();
434
435 if (StreamPurposes.empty())
436 discoverStreamPurposes(File, StreamPurposes);
437
438 uint32_t StreamCount = File.getNumStreams();
439
440 ListScope L(P, "Streams");
441 for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
442 std::string Label("Stream ");
443 Label += to_string(StreamIdx);
444
445 std::string Value = "[" + StreamPurposes[StreamIdx] + "] (";
446 Value += to_string(File.getStreamByteSize(StreamIdx));
447 Value += " bytes)";
448
449 P.printString(Label, Value);
450 }
451
452 P.flush();
453 return Error::success();
454 }
455
456 Error LLVMOutputStyle::dumpFreePageMap() {
457 if (!opts::raw::DumpPageStats)
458 return Error::success();
459
460 // Start with used pages instead of free pages because
461 // the number of free pages is far larger than used pages.
462 BitVector FPM = File.getMsfLayout().FreePageMap;
463
464 PageStats PS(FPM);
465
466 recordKnownUsedPage(PS, 0); // MSF Super Block
467
468 uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout());
469 uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout());
470 for (uint32_t I = 0; I < NumSections; ++I) {
471 uint32_t Fpm0 = 1 + BlocksPerSection * I;
472 // 2 Fpm blocks spaced at `getBlockSize()` block intervals
473 recordKnownUsedPage(PS, Fpm0);
474 recordKnownUsedPage(PS, Fpm0 + 1);
475 }
476
477 recordKnownUsedPage(PS, File.getBlockMapIndex()); // Stream Table
478
479 for (auto DB : File.getDirectoryBlockArray())
480 recordKnownUsedPage(PS, DB);
481
482 // Record pages used by streams. Note that pages for stream 0
483 // are considered being unused because that's what MSVC tools do.
484 // Stream 0 doesn't contain actual data, so it makes some sense,
485 // though it's a bit confusing to us.
486 for (auto &SE : File.getStreamMap().drop_front(1))
487 for (auto &S : SE)
488 recordKnownUsedPage(PS, S);
489
490 dumpBitVector("Msf Free Pages", FPM);
491 dumpBitVector("Orphaned Pages", PS.OrphanedPages);
492 dumpBitVector("Multiply Used Pages", PS.MultiUsePages);
493 dumpBitVector("Use After Free Pages", PS.UseAfterFreePages);
494 return Error::success();
495 }
496
497 void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) {
498 std::vector Vec;
499 for (uint32_t I = 0, E = V.size(); I != E; ++I)
500 if (V[I])
501 Vec.push_back(I);
502 P.printList(Name, Vec);
503 }
504
505 Error LLVMOutputStyle::dumpGlobalsStream() {
506 if (!opts::raw::DumpGlobals)
507 return Error::success();
508 if (!File.hasPDBGlobalsStream()) {
509 P.printString("Globals Stream not present");
510 return Error::success();
511 }
512
513 auto Globals = File.getPDBGlobalsStream();
514 if (!Globals)
515 return Globals.takeError();
516 DictScope D(P, "Globals Stream");
517
518 auto Dbi = File.getPDBDbiStream();
519 if (!Dbi)
520 return Dbi.takeError();
521
522 P.printNumber("Stream number", Dbi->getGlobalSymbolStreamIndex());
523 P.printNumber("Number of buckets", Globals->getNumBuckets());
524 P.printList("Hash Buckets", Globals->getHashBuckets());
525
526 return Error::success();
527 }
528
529 Error LLVMOutputStyle::dumpStreamBlocks() {
530 if (!opts::raw::DumpStreamBlocks)
531 return Error::success();
532
533 ListScope L(P, "StreamBlocks");
534 uint32_t StreamCount = File.getNumStreams();
535 for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
536 std::string Name("Stream ");
537 Name += to_string(StreamIdx);
538 auto StreamBlocks = File.getStreamBlockList(StreamIdx);
539 P.printList(Name, StreamBlocks);
540 }
541 return Error::success();
542 }
543
544 Error LLVMOutputStyle::dumpBlockRanges() {
545 if (!opts::raw::DumpBlockRange.hasValue())
546 return Error::success();
547 auto &R = *opts::raw::DumpBlockRange;
548 uint32_t Max = R.Max.getValueOr(R.Min);
549
550 if (Max < R.Min)
551 return make_error(
552 "Invalid block range specified. Max < Min",
553 std::make_error_code(std::errc::bad_address));
554 if (Max >= File.getBlockCount())
555 return make_error(
556 "Invalid block range specified. Requested block out of bounds",
557 std::make_error_code(std::errc::bad_address));
558
559 DictScope D(P, "Block Data");
560 for (uint32_t I = R.Min; I <= Max; ++I) {
561 auto ExpectedData = File.getBlockData(I, File.getBlockSize());
562 if (!ExpectedData)
563 return ExpectedData.takeError();
564 std::string Label;
565 llvm::raw_string_ostream S(Label);
566 S << "Block " << I;
567 S.flush();
568 P.printBinaryBlock(Label, *ExpectedData);
569 }
570
571 return Error::success();
572 }
573
574 static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset,
575 uint32_t &Size) {
576 if (Str.consumeInteger(0, SI))
577 return make_error(raw_error_code::invalid_format,
578 "Invalid Stream Specification");
579 if (Str.consume_front(":")) {
580 if (Str.consumeInteger(0, Offset))
581 return make_error(raw_error_code::invalid_format,
582 "Invalid Stream Specification");
583 }
584 if (Str.consume_front("@")) {
585 if (Str.consumeInteger(0, Size))
586 return make_error(raw_error_code::invalid_format,
587 "Invalid Stream Specification");
588 }
589 if (!Str.empty())
590 return make_error(raw_error_code::invalid_format,
591 "Invalid Stream Specification");
592 return Error::success();
593 }
594
595 Error LLVMOutputStyle::dumpStreamBytes() {
596 if (opts::raw::DumpStreamData.empty())
597 return Error::success();
598
599 if (StreamPurposes.empty())
600 discoverStreamPurposes(File, StreamPurposes);
601
602 DictScope D(P, "Stream Data");
603 for (auto &Str : opts::raw::DumpStreamData) {
604 uint32_t SI = 0;
605 uint32_t Begin = 0;
606 uint32_t Size = 0;
607 uint32_t End = 0;
608
609 if (auto EC = parseStreamSpec(Str, SI, Begin, Size))
610 return EC;
611
612 if (SI >= File.getNumStreams())
613 return make_error(raw_error_code::no_stream);
614
615 auto S = MappedBlockStream::createIndexedStream(
616 File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator());
617 if (!S)
618 continue;
619 DictScope DD(P, "Stream");
620 if (Size == 0)
621 End = S->getLength();
622 else {
623 End = Begin + Size;
624 if (End >= S->getLength())
625 return make_error(raw_error_code::index_out_of_bounds,
626 "Stream is not long enough!");
627 }
628
629 P.printNumber("Index", SI);
630 P.printString("Type", StreamPurposes[SI]);
631 P.printNumber("Size", S->getLength());
632 auto Blocks = File.getMsfLayout().StreamMap[SI];
633 P.printList("Blocks", Blocks);
634
635 BinaryStreamReader R(*S);
636 ArrayRef StreamData;
637 if (auto EC = R.readBytes(StreamData, S->getLength()))
638 return EC;
639 Size = End - Begin;
640 StreamData = StreamData.slice(Begin, Size);
641 P.printBinaryBlock("Data", StreamData, Begin);
642 }
643 return Error::success();
644 }
645
646 Error LLVMOutputStyle::dumpStringTable() {
647 if (!opts::raw::DumpStringTable)
648 return Error::success();
649
650 auto IS = File.getStringTable();
651 if (!IS)
652 return IS.takeError();
653
654 DictScope D(P, "String Table");
655 for (uint32_t I : IS->name_ids()) {
656 auto ES = IS->getStringForID(I);
657 if (!ES)
658 return ES.takeError();
659
660 if (ES->empty())
661 continue;
662 llvm::SmallString<32> Str;
663 Str.append("'");
664 Str.append(*ES);
665 Str.append("'");
666 P.printString(Str);
667 }
668 return Error::success();
669 }
670
671 Error LLVMOutputStyle::dumpInfoStream() {
672 if (!opts::raw::DumpHeaders)
673 return Error::success();
674 if (!File.hasPDBInfoStream()) {
675 P.printString("PDB Stream not present");
676 return Error::success();
677 }
678 auto IS = File.getPDBInfoStream();
679 if (!IS)
680 return IS.takeError();
681
682 DictScope D(P, "PDB Stream");
683 P.printNumber("Version", IS->getVersion());
684 P.printHex("Signature", IS->getSignature());
685 P.printNumber("Age", IS->getAge());
686 P.printObject("Guid", IS->getGuid());
687 P.printHex("Features", IS->getFeatures());
688 {
689 DictScope DD(P, "Named Streams");
690 for (const auto &S : IS->getNamedStreams().entries())
691 P.printObject(S.getKey(), S.getValue());
692 }
693 return Error::success();
694 }
695
696 namespace {
697 class RecordBytesVisitor : public TypeVisitorCallbacks {
698 public:
699 explicit RecordBytesVisitor(ScopedPrinter &P) : P(P) {}
700
701 Error visitTypeEnd(CVType &Record) override {
702 P.printBinaryBlock("Bytes", Record.content());
703 return Error::success();
704 }
705
706 private:
707 ScopedPrinter &P;
708 };
709 }
710
711 Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
712 assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
713
714 bool DumpRecordBytes = false;
715 bool DumpRecords = false;
716 bool DumpTpiHash = false;
717 StringRef Label;
718 StringRef VerLabel;
719 if (StreamIdx == StreamTPI) {
720 if (!File.hasPDBTpiStream()) {
721 P.printString("Type Info Stream (TPI) not present");
722 return Error::success();
723 }
724 DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
725 DumpRecords = opts::raw::DumpTpiRecords;
726 DumpTpiHash = opts::raw::DumpTpiHash;
727 Label = "Type Info Stream (TPI)";
728 VerLabel = "TPI Version";
729 } else if (StreamIdx == StreamIPI) {
730 if (!File.hasPDBIpiStream()) {
731 P.printString("Type Info Stream (IPI) not present");
732 return Error::success();
733 }
734 DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
735 DumpRecords = opts::raw::DumpIpiRecords;
736 Label = "Type Info Stream (IPI)";
737 VerLabel = "IPI Version";
738 }
739
740 auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
741 : File.getPDBIpiStream();
742 if (!Tpi)
743 return Tpi.takeError();
744
745 auto ExpectedTypes = initializeTypeDatabase(StreamIdx);
746 if (!ExpectedTypes)
747 return ExpectedTypes.takeError();
748 auto &Types = *ExpectedTypes;
749
750 if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
751 return Error::success();
752
753 std::unique_ptr StreamScope;
754 std::unique_ptr RecordScope;
755
756 StreamScope = llvm::make_unique(P, Label);
757 P.printNumber(VerLabel, Tpi->getTpiVersion());
758 P.printNumber("Record count", Tpi->getNumTypeRecords());
759
760 std::vector> Visitors;
761
762 // If we're in dump mode, add a dumper with the appropriate detail level.
763 if (DumpRecords) {
764 std::unique_ptr Dumper;
765 if (opts::raw::CompactRecords)
766 Dumper = make_unique(Types, &P);
767 else {
768 assert(TpiTypes);
769
770 auto X = make_unique(*TpiTypes, &P, false);
771 if (StreamIdx == StreamIPI)
772 X->setIpiTypes(*IpiTypes);
773 Dumper = std::move(X);
774 }
775 Visitors.push_back(std::move(Dumper));
776 }
777 if (DumpRecordBytes)
778 Visitors.push_back(make_unique(P));
779
780 // We always need to deserialize and add it to the type database. This is
781 // true if even if we're not dumping anything, because we could need the
782 // type database for the purposes of dumping symbols.
783 TypeVisitorCallbackPipeline Pipeline;
784 for (const auto &V : Visitors)
785 Pipeline.addCallbackToPipeline(*V);
786
787 if (DumpRecords || DumpRecordBytes)
788 RecordScope = llvm::make_unique(P, "Records");
789
790 Optional I = Types.getFirst();
791 while (I) {
792 std::unique_ptr OneRecordScope;
793
794 if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords)
795 OneRecordScope = llvm::make_unique(P, "");
796
797 auto T = Types.getType(*I);
798 if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline))
799 return EC;
800 I = Types.getNext(*I);
801 }
802
803 if (DumpTpiHash) {
804 DictScope DD(P, "Hash");
805 P.printNumber("Number of Hash Buckets", Tpi->getNumHashBuckets());
806 P.printNumber("Hash Key Size", Tpi->getHashKeySize());
807 P.printList("Values", Tpi->getHashValues());
808
809 ListScope LHA(P, "Adjusters");
810 auto ExpectedST = File.getStringTable();
811 if (!ExpectedST)
812 return ExpectedST.takeError();
813 const auto &ST = *ExpectedST;
814 for (const auto &E : Tpi->getHashAdjusters()) {
815 DictScope DHA(P);
816 auto Name = ST.getStringForID(E.first);
817 if (!Name)
818 return Name.takeError();
819
820 P.printString("Type", *Name);
821 P.printHex("TI", E.second);
822 }
823 }
824
825 ListScope L(P, "TypeIndexOffsets");
826 for (const auto &IO : Tpi->getTypeIndexOffsets()) {
827 P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(),
828 (uint32_t)IO.Offset)
829 .str());
830 }
831
832 P.flush();
833 return Error::success();
834 }
835
836 Expected
837 LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) {
838 auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
839 auto Tpi =
840 (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
841 if (!Tpi)
842 return Tpi.takeError();
843
844 if (!TypeCollection) {
845 // Initialize the type collection, even if we're not going to dump it. This
846 // way if some other part of the dumper decides it wants to use some or all
847 // of the records for whatever purposes, it can still access them lazily.
848 auto &Types = Tpi->typeArray();
849 uint32_t Count = Tpi->getNumTypeRecords();
850 auto Offsets = Tpi->getTypeIndexOffsets();
851 TypeCollection =
852 llvm::make_unique(Types, Count, Offsets);
853 }
854
855 return *TypeCollection;
856 }
857
858 Error LLVMOutputStyle::dumpDbiStream() {
859 bool DumpModules = opts::shared::DumpModules ||
860 opts::shared::DumpModuleSyms ||
861 opts::shared::DumpModuleFiles ||
862 !opts::shared::DumpModuleSubsections.empty();
863 if (!opts::raw::DumpHeaders && !DumpModules)
864 return Error::success();
865 if (!File.hasPDBDbiStream()) {
866 P.printString("DBI Stream not present");
867 return Error::success();
868 }
869
870 auto DS = File.getPDBDbiStream();
871 if (!DS)
872 return DS.takeError();
873
874 DictScope D(P, "DBI Stream");
875 P.printNumber("Dbi Version", DS->getDbiVersion());
876 P.printNumber("Age", DS->getAge());
877 P.printBoolean("Incremental Linking", DS->isIncrementallyLinked());
878 P.printBoolean("Has CTypes", DS->hasCTypes());
879 P.printBoolean("Is Stripped", DS->isStripped());
880 P.printObject("Machine Type", DS->getMachineType());
881 P.printNumber("Symbol Record Stream Index", DS->getSymRecordStreamIndex());
882 P.printNumber("Public Symbol Stream Index", DS->getPublicSymbolStreamIndex());
883 P.printNumber("Global Symbol Stream Index", DS->getGlobalSymbolStreamIndex());
884
885 uint16_t Major = DS->getBuildMajorVersion();
886 uint16_t Minor = DS->getBuildMinorVersion();
887 P.printVersion("Toolchain Version", Major, Minor);
888
889 std::string DllName;
890 raw_string_ostream DllStream(DllName);
891 DllStream << "mspdb" << Major << Minor << ".dll version";
892 DllStream.flush();
893 P.printVersion(DllName, Major, Minor, DS->getPdbDllVersion());
894
895 if (DumpModules) {
896 ListScope L(P, "Modules");
897 const DbiModuleList &Modules = DS->modules();
898 for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
899 const DbiModuleDescriptor &Modi = Modules.getModuleDescriptor(I);
900 DictScope DD(P);
901 P.printString("Name", Modi.getModuleName().str());
902 P.printNumber("Debug Stream Index", Modi.getModuleStreamIndex());
903 P.printString("Object File Name", Modi.getObjFileName().str());
904 P.printNumber("Num Files", Modi.getNumberOfFiles());
905 P.printNumber("Source File Name Idx", Modi.getSourceFileNameIndex());
906 P.printNumber("Pdb File Name Idx", Modi.getPdbFilePathNameIndex());
907 P.printNumber("Line Info Byte Size", Modi.getC11LineInfoByteSize());
908 P.printNumber("C13 Line Info Byte Size", Modi.getC13LineInfoByteSize());
909 P.printNumber("Symbol Byte Size", Modi.getSymbolDebugInfoByteSize());
910 P.printNumber("Type Server Index", Modi.getTypeServerIndex());
911 P.printBoolean("Has EC Info", Modi.hasECInfo());
912 if (opts::shared::DumpModuleFiles) {
913 std::string FileListName = to_string(Modules.getSourceFileCount(I)) +
914 " Contributing Source Files";
915 ListScope LL(P, FileListName);
916 for (auto File : Modules.source_files(I))
917 P.printString(File);
918 }
919 bool HasModuleDI = (Modi.getModuleStreamIndex() < File.getNumStreams());
920 bool ShouldDumpSymbols =
921 (opts::shared::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
922 if (HasModuleDI &&
923 (ShouldDumpSymbols || !opts::shared::DumpModuleSubsections.empty())) {
924 auto ModStreamData = MappedBlockStream::createIndexedStream(
925 File.getMsfLayout(), File.getMsfBuffer(),
926 Modi.getModuleStreamIndex(), File.getAllocator());
927
928 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
929 if (auto EC = ModS.reload())
930 return EC;
931
932 auto ExpectedTpi = initializeTypeDatabase(StreamTPI);
933 if (!ExpectedTpi)
934 return ExpectedTpi.takeError();
935 auto &Tpi = *ExpectedTpi;
936 if (ShouldDumpSymbols) {
937
938 ListScope SS(P, "Symbols");
939 codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr,
940 false);
941 bool HadError = false;
942 for (auto S : ModS.symbols(&HadError)) {
943 DictScope LL(P, "");
944 if (opts::shared::DumpModuleSyms) {
945 if (auto EC = SD.dump(S)) {
946 llvm::consumeError(std::move(EC));
947 HadError = true;
948 break;
949 }
950 }
951 if (opts::raw::DumpSymRecordBytes)
952 P.printBinaryBlock("Bytes", S.content());
953 }
954 if (HadError)
955 return make_error(
956 raw_error_code::corrupt_file,
957 "DBI stream contained corrupt symbol record");
958 }
959 if (!opts::shared::DumpModuleSubsections.empty()) {
960 ListScope SS(P, "Subsections");
961 auto ExpectedIpi = initializeTypeDatabase(StreamIPI);
962 if (!ExpectedIpi)
963 return ExpectedIpi.takeError();
964 auto &Ipi = *ExpectedIpi;
965 auto ExpectedStrings = File.getStringTable();
966 if (!ExpectedStrings)
967 return joinErrors(
968 make_error(raw_error_code::no_stream,
969 "Could not get string table!"),
970 ExpectedStrings.takeError());
971
972 C13RawVisitor V(P, Tpi, Ipi);
973 if (auto EC = codeview::visitDebugSubsections(
974 ModS.subsections(), V, ExpectedStrings->getStringTable()))
975 return EC;
976 }
977 }
978 }
979 }
980 return Error::success();
981 }
982
983 Error LLVMOutputStyle::dumpSectionContribs() {
984 if (!opts::raw::DumpSectionContribs)
985 return Error::success();
986 if (!File.hasPDBDbiStream()) {
987 P.printString("DBI Stream not present");
988 return Error::success();
989 }
990
991 auto Dbi = File.getPDBDbiStream();
992 if (!Dbi)
993 return Dbi.takeError();
994
995 ListScope L(P, "Section Contributions");
996 class Visitor : public ISectionContribVisitor {
997 public:
998 Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {}
999 void visit(const SectionContrib &SC) override {
1000 DictScope D(P, "Contribution");
1001 P.printNumber("ISect", SC.ISect);
1002 P.printNumber("Off", SC.Off);
1003 P.printNumber("Size", SC.Size);
1004 P.printFlags("Characteristics", SC.Characteristics,
1005 codeview::getImageSectionCharacteristicNames(),
1006 COFF::SectionCharacteristics(0x00F00000));
1007 {
1008 DictScope DD(P, "Module");
1009 P.printNumber("Index", SC.Imod);
1010 const DbiModuleList &Modules = DS.modules();
1011 if (Modules.getModuleCount() > SC.Imod) {
1012 P.printString("Name",
1013 Modules.getModuleDescriptor(SC.Imod).getModuleName());
1014 }
1015 }
1016 P.printNumber("Data CRC", SC.DataCrc);
1017 P.printNumber("Reloc CRC", SC.RelocCrc);
1018 P.flush();
1019 }
1020 void visit(const SectionContrib2 &SC) override {
1021 visit(SC.Base);
1022 P.printNumber("ISect Coff", SC.ISectCoff);
1023 P.flush();
1024 }
1025
1026 private:
1027 ScopedPrinter &P;
1028 DbiStream &DS;
1029 };
1030 Visitor V(P, *Dbi);
1031 Dbi->visitSectionContributions(V);
1032 return Error::success();
1033 }
1034
1035 Error LLVMOutputStyle::dumpSectionMap() {
1036 if (!opts::raw::DumpSectionMap)
1037 return Error::success();
1038 if (!File.hasPDBDbiStream()) {
1039 P.printString("DBI Stream not present");
1040 return Error::success();
1041 }
1042
1043 auto Dbi = File.getPDBDbiStream();
1044 if (!Dbi)
1045 return Dbi.takeError();
1046
1047 ListScope L(P, "Section Map");
1048 for (auto &M : Dbi->getSectionMap()) {
1049 DictScope D(P, "Entry");
1050 P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
1051 P.printNumber("Ovl", M.Ovl);
1052 P.printNumber("Group", M.Group);
1053 P.printNumber("Frame", M.Frame);
1054 P.printNumber("SecName", M.SecName);
1055 P.printNumber("ClassName", M.ClassName);
1056 P.printNumber("Offset", M.Offset);
1057 P.printNumber("SecByteLength", M.SecByteLength);
1058 P.flush();
1059 }
1060 return Error::success();
1061 }
1062
1063 Error LLVMOutputStyle::dumpPublicsStream() {
1064 if (!opts::raw::DumpPublics)
1065 return Error::success();
1066 if (!File.hasPDBPublicsStream()) {
1067 P.printString("Publics Stream not present");
1068 return Error::success();
1069 }
1070
1071 auto Publics = File.getPDBPublicsStream();
1072 if (!Publics)
1073 return Publics.takeError();
1074 DictScope D(P, "Publics Stream");
1075
1076 auto Dbi = File.getPDBDbiStream();
1077 if (!Dbi)
1078 return Dbi.takeError();
1079
1080 P.printNumber("Stream number", Dbi->getPublicSymbolStreamIndex());
1081 P.printNumber("SymHash", Publics->getSymHash());
1082 P.printNumber("AddrMap", Publics->getAddrMap());
1083 P.printNumber("Number of buckets", Publics->getNumBuckets());
1084 P.printList("Hash Buckets", Publics->getHashBuckets());
1085 P.printList("Address Map", Publics->getAddressMap());
1086 P.printList("Thunk Map", Publics->getThunkMap());
1087 P.printList("Section Offsets", Publics->getSectionOffsets(),
1088 printSectionOffset);
1089 ListScope L(P, "Symbols");
1090 auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
1091 if (!ExpectedTypes)
1092 return ExpectedTypes.takeError();
1093 auto &Tpi = *ExpectedTypes;
1094
1095 codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr, false);
1096 bool HadError = false;
1097 for (auto S : Publics->getSymbols(&HadError)) {
1098 DictScope DD(P, "");
1099
1100 if (auto EC = SD.dump(S)) {
1101 HadError = true;
1102 break;
1103 }
1104 if (opts::raw::DumpSymRecordBytes)
1105 P.printBinaryBlock("Bytes", S.content());
1106 }
1107 if (HadError)
1108 return make_error(
1109 raw_error_code::corrupt_file,
1110 "Public symbol stream contained corrupt record");
1111
1112 return Error::success();
1113 }
1114
1115 Error LLVMOutputStyle::dumpSectionHeaders() {
1116 if (!opts::raw::DumpSectionHeaders)
1117 return Error::success();
1118 if (!File.hasPDBDbiStream()) {
1119 P.printString("DBI Stream not present");
1120 return Error::success();
1121 }
1122
1123 auto Dbi = File.getPDBDbiStream();
1124 if (!Dbi)
1125 return Dbi.takeError();
1126
1127 ListScope D(P, "Section Headers");
1128 for (const object::coff_section &Section : Dbi->getSectionHeaders()) {
1129 DictScope DD(P, "");
1130
1131 // If a name is 8 characters long, there is no NUL character at end.
1132 StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name)));
1133 P.printString("Name", Name);
1134 P.printNumber("Virtual Size", Section.VirtualSize);
1135 P.printNumber("Virtual Address", Section.VirtualAddress);
1136 P.printNumber("Size of Raw Data", Section.SizeOfRawData);
1137 P.printNumber("File Pointer to Raw Data", Section.PointerToRawData);
1138 P.printNumber("File Pointer to Relocations", Section.PointerToRelocations);
1139 P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers);
1140 P.printNumber("Number of Relocations", Section.NumberOfRelocations);
1141 P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers);
1142 P.printFlags("Characteristics", Section.Characteristics,
1143 getImageSectionCharacteristicNames());
1144 }
1145 return Error::success();
1146 }
1147
1148 Error LLVMOutputStyle::dumpFpoStream() {
1149 if (!opts::raw::DumpFpo)
1150 return Error::success();
1151 if (!File.hasPDBDbiStream()) {
1152 P.printString("DBI Stream not present");
1153 return Error::success();
1154 }
1155
1156 auto Dbi = File.getPDBDbiStream();
1157 if (!Dbi)
1158 return Dbi.takeError();
1159
1160 ListScope D(P, "New FPO");
1161 for (const object::FpoData &Fpo : Dbi->getFpoRecords()) {
1162 DictScope DD(P, "");
1163 P.printNumber("Offset", Fpo.Offset);
1164 P.printNumber("Size", Fpo.Size);
1165 P.printNumber("Number of locals", Fpo.NumLocals);
1166 P.printNumber("Number of params", Fpo.NumParams);
1167 P.printNumber("Size of Prolog", Fpo.getPrologSize());
1168 P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs());
1169 P.printBoolean("Has SEH", Fpo.hasSEH());
1170 P.printBoolean("Use BP", Fpo.useBP());
1171 P.printNumber("Frame Pointer", Fpo.getFP());
1172 }
1173 return Error::success();
1174 }
1175
1176 void LLVMOutputStyle::flush() { P.flush(); }
+0
-70
tools/llvm-pdbdump/LLVMOutputStyle.h less more
None //===- LLVMOutputStyle.h -------------------------------------- *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H
11
12 #include "OutputStyle.h"
13
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"
17 #include "llvm/Support/ScopedPrinter.h"
18
19 #include
20
21 namespace llvm {
22 class BitVector;
23
24 namespace codeview {
25 class LazyRandomTypeCollection;
26 }
27
28 namespace pdb {
29 class LLVMOutputStyle : public OutputStyle {
30 public:
31 LLVMOutputStyle(PDBFile &File);
32
33 Error dump() override;
34
35 private:
36 Expected
37 initializeTypeDatabase(uint32_t SN);
38
39 Error dumpFileHeaders();
40 Error dumpStreamSummary();
41 Error dumpFreePageMap();
42 Error dumpBlockRanges();
43 Error dumpGlobalsStream();
44 Error dumpStreamBytes();
45 Error dumpStreamBlocks();
46 Error dumpStringTable();
47 Error dumpInfoStream();
48 Error dumpTpiStream(uint32_t StreamIdx);
49 Error dumpDbiStream();
50 Error dumpSectionContribs();
51 Error dumpSectionMap();
52 Error dumpPublicsStream();
53 Error dumpSectionHeaders();
54 Error dumpFpoStream();
55
56 void dumpBitVector(StringRef Name, const BitVector &V);
57
58 void flush();
59
60 PDBFile &File;
61 ScopedPrinter P;
62 std::unique_ptr TpiTypes;
63 std::unique_ptr IpiTypes;
64 SmallVector StreamPurposes;
65 };
66 }
67 }
68
69 #endif
+0
-145
tools/llvm-pdbdump/LinePrinter.cpp less more
None //===- LinePrinter.cpp ------------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "LinePrinter.h"
10
11 #include "llvm-pdbdump.h"
12
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/DebugInfo/PDB/UDTLayout.h"
15 #include "llvm/Support/Regex.h"
16
17 #include
18
19 using namespace llvm;
20 using namespace llvm::pdb;
21
22 namespace {
23 bool IsItemExcluded(llvm::StringRef Item,
24 std::list &IncludeFilters,
25 std::list &ExcludeFilters) {
26 if (Item.empty())
27 return false;
28
29 auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); };
30
31 // Include takes priority over exclude. If the user specified include
32 // filters, and none of them include this item, them item is gone.
33 if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred))
34 return true;
35
36 if (any_of(ExcludeFilters, match_pred))
37 return true;
38
39 return false;
40 }
41 }
42
43 using namespace llvm;
44
45 LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream)
46 : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor) {
47 SetFilters(ExcludeTypeFilters, opts::pretty::ExcludeTypes.begin(),
48 opts::pretty::ExcludeTypes.end());
49 SetFilters(ExcludeSymbolFilters, opts::pretty::ExcludeSymbols.begin(),
50 opts::pretty::ExcludeSymbols.end());
51 SetFilters(ExcludeCompilandFilters, opts::pretty::ExcludeCompilands.begin(),
52 opts::pretty::ExcludeCompilands.end());
53
54 SetFilters(IncludeTypeFilters, opts::pretty::IncludeTypes.begin(),
55 opts::pretty::IncludeTypes.end());
56 SetFilters(IncludeSymbolFilters, opts::pretty::IncludeSymbols.begin(),
57 opts::pretty::IncludeSymbols.end());
58 SetFilters(IncludeCompilandFilters, opts::pretty::IncludeCompilands.begin(),
59 opts::pretty::IncludeCompilands.end());
60 }
61
62 void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
63
64 void LinePrinter::Unindent() {
65 CurrentIndent = std::max(0, CurrentIndent - IndentSpaces);
66 }
67
68 void LinePrinter::NewLine() {
69 OS << "\n";
70 OS.indent(CurrentIndent);
71 }
72
73 bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {
74 if (IsTypeExcluded(Class.getName(), Class.getSize()))
75 return true;
76 if (Class.deepPaddingSize() < opts::pretty::PaddingThreshold)
77 return true;
78 return false;
79 }
80
81 bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) {
82 if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
83 return true;
84 if (Size < opts::pretty::SizeThreshold)
85 return true;
86 return false;
87 }
88
89 bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {
90 return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters);
91 }
92
93 bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) {
94 return IsItemExcluded(CompilandName, IncludeCompilandFilters,
95 ExcludeCompilandFilters);
96 }
97
98 WithColor::WithColor(LinePrinter &P, PDB_ColorItem C)
99 : OS(P.OS), UseColor(P.hasColor()) {
100 if (UseColor)
101 applyColor(C);
102 }
103
104 WithColor::~WithColor() {
105 if (UseColor)
106 OS.resetColor();
107 }
108
109 void WithColor::applyColor(PDB_ColorItem C) {
110 switch (C) {
111 case PDB_ColorItem::None:
112 OS.resetColor();
113 return;
114 case PDB_ColorItem::Comment:
115 OS.changeColor(raw_ostream::GREEN, false);
116 return;
117 case PDB_ColorItem::Address:
118 OS.changeColor(raw_ostream::YELLOW, /*bold=*/true);
119 return;
120 case PDB_ColorItem::Keyword:
121 OS.changeColor(raw_ostream::MAGENTA, true);
122 return;
123 case PDB_ColorItem::Register:
124 case PDB_ColorItem::Offset:
125 OS.changeColor(raw_ostream::YELLOW, false);
126 return;
127 case PDB_ColorItem::Type:
128 OS.changeColor(raw_ostream::CYAN, true);
129 return;
130 case PDB_ColorItem::Identifier:
131 OS.changeColor(raw_ostream::CYAN, false);
132 return;
133 case PDB_ColorItem::Path:
134 OS.changeColor(raw_ostream::CYAN, false);
135 return;
136 case PDB_ColorItem::Padding:
137 case PDB_ColorItem::SectionHeader:
138 OS.changeColor(raw_ostream::RED, true);
139 return;
140 case PDB_ColorItem::LiteralValue:
141 OS.changeColor(raw_ostream::GREEN, true);
142 return;
143 }
144 }
+0
-102
tools/llvm-pdbdump/LinePrinter.h less more
None //===- LinePrinter.h ------------------------------------------ *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
11
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/Support/Regex.h"
16
17 #include
18
19 namespace llvm {
20 namespace pdb {
21
22 class ClassLayout;
23
24 class LinePrinter {
25 friend class WithColor;
26
27 public:
28 LinePrinter(int Indent, bool UseColor, raw_ostream &Stream);
29
30 void Indent();
31 void Unindent();
32 void NewLine();
33
34 bool hasColor() const { return UseColor; }
35 raw_ostream &getStream() { return OS; }
36 int getIndentLevel() const { return CurrentIndent; }
37
38 bool IsClassExcluded(const ClassLayout &Class);
39 bool IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size);
40 bool IsSymbolExcluded(llvm::StringRef SymbolName);
41 bool IsCompilandExcluded(llvm::StringRef CompilandName);
42
43 private:
44 template
45 void SetFilters(std::list &List, Iter Begin, Iter End) {
46 List.clear();
47 for (; Begin != End; ++Begin)
48 List.emplace_back(StringRef(*Begin));
49 }
50
51 raw_ostream &OS;
52 int IndentSpaces;
53 int CurrentIndent;
54 bool UseColor;
55
56 std::list ExcludeCompilandFilters;
57 std::list ExcludeTypeFilters;
58 std::list ExcludeSymbolFilters;
59
60 std::list IncludeCompilandFilters;
61 std::list IncludeTypeFilters;
62 std::list IncludeSymbolFilters;
63 };
64
65 template
66 inline raw_ostream &operator<<(LinePrinter &Printer, const T &Item) {
67 Printer.getStream() << Item;
68 return Printer.getStream();
69 }
70
71 enum class PDB_ColorItem {
72 None,
73 Address,
74 Type,
75 Comment,
76 Padding,
77 Keyword,
78 Offset,
79 Identifier,
80 Path,
81 SectionHeader,
82 LiteralValue,
83 Register,
84 };
85
86 class WithColor {
87 public:
88 WithColor(LinePrinter &P, PDB_ColorItem C);
89 ~WithColor();
90
91 raw_ostream &get() { return OS; }
92
93 private:
94 void applyColor(PDB_ColorItem C);
95 raw_ostream &OS;
96 bool UseColor;
97 };
98 }
99 }
100
101 #endif
+0
-28
tools/llvm-pdbdump/OutputStyle.h less more
None //===- OutputStyle.h ------------------------------------------ *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_OUTPUTSTYLE_H
11
12 #include "llvm/Support/Error.h"
13
14 namespace llvm {
15 namespace pdb {
16 class PDBFile;
17
18 class OutputStyle {
19 public:
20 virtual ~OutputStyle() {}
21
22 virtual Error dump() = 0;
23 };
24 }
25 }
26
27 #endif
+0
-227
tools/llvm-pdbdump/PdbYaml.cpp less more
None //===- PdbYAML.cpp -------------------------------------------- *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "PdbYaml.h"
10
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
13 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
14 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
15 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
16 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
17 #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
18 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
19 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
20 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
21 #include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
22 #include "llvm/DebugInfo/PDB/PDBExtras.h"
23 #include "llvm/DebugInfo/PDB/PDBTypes.h"
24 #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
25 #include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
26
27 using namespace llvm;
28 using namespace llvm::pdb;
29 using namespace llvm::pdb::yaml;
30 using namespace llvm::yaml;
31
32 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
33 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef)
34 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping)
35 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo)
36 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
37 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::pdb::PdbRaw_FeatureSig)
38
39 namespace llvm {
40 namespace yaml {
41
42 template <> struct ScalarTraits {
43 static void output(const llvm::pdb::PDB_UniqueId &S, void *,
44 llvm::raw_ostream &OS) {
45 OS << S;
46 }
47
48 static StringRef input(StringRef Scalar, void *Ctx,
49 llvm::pdb::PDB_UniqueId &S) {
50 if (Scalar.size() != 38)
51 return "GUID strings are 38 characters long";
52 if (Scalar[0] != '{' || Scalar[37] != '}')
53 return "GUID is not enclosed in {}";
54 if (Scalar[9] != '-' || Scalar[14] != '-' || Scalar[19] != '-' ||
55 Scalar[24] != '-')
56 return "GUID sections are not properly delineated with dashes";
57
58 uint8_t *OutBuffer = S.Guid;
59 for (auto Iter = Scalar.begin(); Iter != Scalar.end();) {
60 if (*Iter == '-' || *Iter == '{' || *Iter == '}') {
61 ++Iter;
62 continue;
63 }
64 uint8_t Value = (llvm::hexDigitValue(*Iter) << 4);
65 ++Iter;
66 Value |= llvm::hexDigitValue(*Iter);
67 ++Iter;
68 *OutBuffer++ = Value;
69 }
70
71 return "";
72 }
73
74 static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
75 };
76
77 template <> struct ScalarEnumerationTraits {
78 static void enumeration(IO &io, llvm::pdb::PDB_Machine &Value) {
79 io.enumCase(Value, "Invalid", PDB_Machine::Invalid);
80 io.enumCase(Value, "Am33", PDB_Machine::Am33);
81 io.enumCase(Value, "Amd64", PDB_Machine::Amd64);
82 io.enumCase(Value, "Arm", PDB_Machine::Arm);
83 io.enumCase(Value, "ArmNT", PDB_Machine::ArmNT);
84 io.enumCase(Value, "Ebc", PDB_Machine::Ebc);
85 io.enumCase(Value, "x86", PDB_Machine::x86);
86 io.enumCase(Value, "Ia64", PDB_Machine::Ia64);
87 io.enumCase(Value, "M32R", PDB_Machine::M32R);
88 io.enumCase(Value, "Mips16", PDB_Machine::Mips16);
89 io.enumCase(Value, "MipsFpu", PDB_Machine::MipsFpu);
90 io.enumCase(Value, "MipsFpu16", PDB_Machine::MipsFpu16);
91 io.enumCase(Value, "PowerPCFP", PDB_Machine::PowerPCFP);
92 io.enumCase(Value, "R4000", PDB_Machine::R4000);
93 io.enumCase(Value, "SH3", PDB_Machine::SH3);
94 io.enumCase(Value, "SH3DSP", PDB_Machine::SH3DSP);
95 io.enumCase(Value, "Thumb", PDB_Machine::Thumb);
96 io.enumCase(Value, "WceMipsV2", PDB_Machine::WceMipsV2);
97 }
98 };
99
100 template <> struct ScalarEnumerationTraits {
101 static void enumeration(IO &io, llvm::pdb::PdbRaw_DbiVer &Value) {
102 io.enumCase(Value, "V41", llvm::pdb::PdbRaw_DbiVer::PdbDbiVC41);
103 io.enumCase(Value, "V50", llvm::pdb::PdbRaw_DbiVer::PdbDbiV50);
104 io.enumCase(Value, "V60", llvm::pdb::PdbRaw_DbiVer::PdbDbiV60);
105 io.enumCase(Value, "V70", llvm::pdb::PdbRaw_DbiVer::PdbDbiV70);
106 io.enumCase(Value, "V110", llvm::pdb::PdbRaw_DbiVer::PdbDbiV110);
107 }
108 };
109
110 template <> struct ScalarEnumerationTraits {
111 static void enumeration(IO &io, llvm::pdb::PdbRaw_ImplVer &Value) {
112 io.enumCase(Value, "VC2", llvm::pdb::PdbRaw_ImplVer::PdbImplVC2);
113 io.enumCase(Value, "VC4", llvm::pdb::PdbRaw_ImplVer::PdbImplVC4);
114 io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_ImplVer::PdbImplVC41);
115 io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_ImplVer::PdbImplVC50);
116 io.enumCase(Value, "VC98", llvm::pdb::PdbRaw_ImplVer::PdbImplVC98);
117 io.enumCase(Value, "VC70Dep", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70Dep);
118 io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_ImplVer::PdbImplVC70);
119 io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_ImplVer::PdbImplVC80);
120 io.enumCase(Value, "VC110", llvm::pdb::PdbRaw_ImplVer::PdbImplVC110);
121 io.enumCase(Value, "VC140", llvm::pdb::PdbRaw_ImplVer::PdbImplVC140);
122 }
123 };
124
125 template <> struct ScalarEnumerationTraits {
126 static void enumeration(IO &io, llvm::pdb::PdbRaw_TpiVer &Value) {
127 io.enumCase(Value, "VC40", llvm::pdb::PdbRaw_TpiVer::PdbTpiV40);
128 io.enumCase(Value, "VC41", llvm::pdb::PdbRaw_TpiVer::PdbTpiV41);
129 io.enumCase(Value, "VC50", llvm::pdb::PdbRaw_TpiVer::PdbTpiV50);
130 io.enumCase(Value, "VC70", llvm::pdb::PdbRaw_TpiVer::PdbTpiV70);
131 io.enumCase(Value, "VC80", llvm::pdb::PdbRaw_TpiVer::PdbTpiV80);
132 }
133 };
134
135 template <> struct ScalarEnumerationTraits {
136 static void enumeration(IO &io, PdbRaw_FeatureSig &Features) {
137 io.enumCase(Features, "MinimalDebugInfo",
138 PdbRaw_FeatureSig::MinimalDebugInfo);
139 io.enumCase(Features, "NoTypeMerge", PdbRaw_FeatureSig::NoTypeMerge);
140 io.enumCase(Features, "VC110", PdbRaw_FeatureSig::VC110);
141 io.enumCase(Features, "VC140", PdbRaw_FeatureSig::VC140);
142 }
143 };
144 }
145 }
146
147 void MappingTraits::mapping(IO &IO, PdbObject &Obj) {
148 IO.mapOptional("MSF", Obj.Headers);
149 IO.mapOptional("StreamSizes", Obj.StreamSizes);
150 IO.mapOptional("StreamMap", Obj.StreamMap);
151 IO.mapOptional("StringTable", Obj.StringTable);
152 IO.mapOptional("PdbStream", Obj.PdbStream);
153 IO.mapOptional("DbiStream", Obj.DbiStream);
154 IO.mapOptional("TpiStream", Obj.TpiStream);
155 IO.mapOptional("IpiStream", Obj.IpiStream);
156 }
157
158 void MappingTraits::mapping(IO &IO, MSFHeaders &Obj) {
159 IO.mapOptional("SuperBlock", Obj.SuperBlock);
160 IO.mapOptional("NumDirectoryBlocks", Obj.NumDirectoryBlocks);
161 IO.mapOptional("DirectoryBlocks", Obj.DirectoryBlocks);
162 IO.mapOptional("NumStreams", Obj.NumStreams);
163 IO.mapOptional("FileSize", Obj.FileSize);
164 }
165
166 void MappingTraits::mapping(IO &IO, msf::SuperBlock &SB) {
167 if (!IO.outputting()) {
168 ::memcpy(SB.MagicBytes, msf::Magic, sizeof(msf::Magic));
169 }
170
171 using u32 = support::ulittle32_t;
172 IO.mapOptional("BlockSize", SB.BlockSize, u32(4096U));
173 IO.mapOptional("FreeBlockMap", SB.FreeBlockMapBlock, u32(0U));
174 IO.mapOptional("NumBlocks", SB.NumBlocks, u32(0U));
175 IO.mapOptional("NumDirectoryBytes", SB.NumDirectoryBytes, u32(0U));
176 IO.mapOptional("Unknown1", SB.Unknown1, u32(0U));
177 IO.mapOptional("BlockMapAddr", SB.BlockMapAddr, u32(0U));
178 }
179
180 void MappingTraits::mapping(IO &IO, StreamBlockList &SB) {
181 IO.mapRequired("Stream", SB.Blocks);
182 }
183
184 void MappingTraits::mapping(IO &IO, PdbInfoStream &Obj) {
185 IO.mapOptional("Age", Obj.Age, 1U);
186 IO.mapOptional("Guid", Obj.Guid);
187 IO.mapOptional("Signature", Obj.Signature, 0U);
188 IO.mapOptional("Features", Obj.Features);
189 IO.mapOptional("Version", Obj.Version, PdbImplVC70);
190 }
191
192 void MappingTraits::mapping(IO &IO, PdbDbiStream &Obj) {
193 IO.mapOptional("VerHeader", Obj.VerHeader, PdbDbiV70);
194 IO.mapOptional("Age", Obj.Age, 1U);
195 IO.mapOptional("BuildNumber", Obj.BuildNumber, uint16_t(0U));
196 IO.mapOptional("PdbDllVersion", Obj.PdbDllVersion, 0U);
197 IO.mapOptional("PdbDllRbld", Obj.PdbDllRbld, uint16_t(0U));
198 IO.mapOptional("Flags", Obj.Flags, uint16_t(1U));
199 IO.mapOptional("MachineType", Obj.MachineType, PDB_Machine::x86);
200 IO.mapOptional("Modules", Obj.ModInfos);
201 }
202
203 void MappingTraits::mapping(IO &IO,
204 pdb::yaml::PdbTpiStream &Obj) {
205 IO.mapOptional("Version", Obj.Version, PdbTpiV80);
206 IO.mapRequired("Records", Obj.Records);
207 }
208
209 void MappingTraits::mapping(IO &IO,
210 NamedStreamMapping &Obj) {
211 IO.mapRequired("Name", Obj.StreamName);
212 IO.mapRequired("StreamNum", Obj.StreamNumber);
213 }
214
215 void MappingTraits::mapping(IO &IO, PdbModiStream &Obj) {
216 IO.mapOptional("Signature", Obj.Signature, 4U);
217 IO.mapRequired("Records", Obj.Symbols);
218 }
219
220 void MappingTraits::mapping(IO &IO, PdbDbiModuleInfo &Obj) {
221 IO.mapRequired("Module", Obj.Mod);
222 IO.mapOptional("ObjFile", Obj.Obj, Obj.Mod);
223 IO.mapOptional("SourceFiles", Obj.SourceFiles);
224 IO.mapOptional("Subsections", Obj.Subsections);
225 IO.mapOptional("Modi", Obj.Modi);
226 }
+0
-125
tools/llvm-pdbdump/PdbYaml.h less more
None //===- PdbYAML.h ---------------------------------------------- *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
11
12 #include "OutputStyle.h"
13
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 #include "llvm/DebugInfo/MSF/MSFCommon.h"
18 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
19 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
20 #include "llvm/DebugInfo/PDB/PDBTypes.h"
21 #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
22 #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
23 #include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
24 #include "llvm/Support/Endian.h"
25 #include "llvm/Support/YAMLTraits.h"
26
27 #include
28
29 namespace llvm {
30 namespace codeview {
31 class DebugStringTableSubsection;
32 }
33 namespace pdb {
34
35 namespace yaml {
36 struct SerializationContext;
37
38 struct MSFHeaders {
39 msf::SuperBlock SuperBlock;
40 uint32_t NumDirectoryBlocks = 0;
41 std::vector DirectoryBlocks;
42 uint32_t NumStreams = 0;
43 uint32_t FileSize = 0;
44 };
45
46 struct StreamBlockList {
47 std::vector Blocks;
48 };
49
50 struct NamedStreamMapping {
51 StringRef StreamName;
52 uint32_t StreamNumber;
53 };
54
55 struct PdbInfoStream {
56 PdbRaw_ImplVer Version = PdbImplVC70;
57 uint32_t Signature = 0;
58 uint32_t Age = 1;
59 PDB_UniqueId Guid;
60 std::vector Features;
61 std::vector NamedStreams;
62 };
63
64 struct PdbModiStream {
65 uint32_t Signature;
66 std::vector Symbols;
67 };
68
69 struct PdbDbiModuleInfo {
70 StringRef Obj;
71 StringRef Mod;
72 std::vector SourceFiles;
73 std::vector Subsections;
74 Optional Modi;
75 };
76
77 struct PdbDbiStream {
78 PdbRaw_DbiVer VerHeader = PdbDbiV70;
79 uint32_t Age = 1;
80 uint16_t BuildNumber = 0;
81 uint32_t PdbDllVersion = 0;
82 uint16_t PdbDllRbld = 0;
83 uint16_t Flags = 1;
84 PDB_Machine MachineType = PDB_Machine::x86;
85
86 std::vector ModInfos;
87 };
88
89 struct PdbTpiStream {
90 PdbRaw_TpiVer Version = PdbTpiV80;
91 std::vector Records;
92 };
93
94 struct PdbObject {
95 explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {}
96
97 Optional Headers;
98 Optional> StreamSizes;
99 Optional> StreamMap;
100 Optional PdbStream;
101 Optional DbiStream;
102 Optional TpiStream;
103 Optional IpiStream;
104
105 Optional> StringTable;
106
107 BumpPtrAllocator &Allocator;
108 };
109 }
110 }
111 }
112
113 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbObject)
114 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::MSFHeaders)
115 LLVM_YAML_DECLARE_MAPPING_TRAITS(msf::SuperBlock)
116 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::StreamBlockList)
117 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbInfoStream)
118 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiStream)
119 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbTpiStream)
120 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::NamedStreamMapping)
121 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbModiStream)
122 LLVM_YAML_DECLARE_MAPPING_TRAITS(pdb::yaml::PdbDbiModuleInfo)
123
124 #endif // LLVM_TOOLS_LLVMPDBDUMP_PDBYAML_H
+0
-94
tools/llvm-pdbdump/PrettyBuiltinDumper.cpp less more
None //===- PrettyBuiltinDumper.cpp ---------------------------------- *- C++ *-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "PrettyBuiltinDumper.h"
10 #include "LinePrinter.h"
11 #include "llvm-pdbdump.h"
12
13 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
14
15 using namespace llvm;
16 using namespace llvm::pdb;
17
18 BuiltinDumper::BuiltinDumper(LinePrinter &P)
19 : PDBSymDumper(false), Printer(P) {}
20
21 void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
22 if (Symbol.isConstType())
23 WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
24 if (Symbol.isVolatileType())
25 WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
26 WithColor(Printer, PDB_ColorItem::Type).get() << getTypeName(Symbol);
27 }
28
29 StringRef BuiltinDumper::getTypeName(const PDBSymbolTypeBuiltin &Symbol) {
30 PDB_BuiltinType Type = Symbol.getBuiltinType();
31 switch (Type) {
32 case PDB_BuiltinType::Float:
33 if (Symbol.getLength() == 4)
34 return "float";
35 return "double";
36 case PDB_BuiltinType::UInt:
37 switch (Symbol.getLength()) {
38 case 8:
39 return "unsigned __int64";
40 case 4:
41 return "unsigned int";
42 case 2:
43 return "unsigned short";
44 case 1:
45 return "unsigned char";
46 default:
47 return "unsigned";
48 }
49 case PDB_BuiltinType::Int:
50 switch (Symbol.getLength()) {
51 case 8:
52 return "__int64";
53 case 4:
54 return "int";
55 case 2:
56 return "short";
57 case 1:
58 return "char";
59 default:
60 return "int";
61 }
62 case PDB_BuiltinType::Char:
63 return "char";
64 case PDB_BuiltinType::WCharT:
65 return "wchar_t";
66 case PDB_BuiltinType::Void:
67 return "void";
68 case PDB_BuiltinType::Long:
69 return "long";
70 case PDB_BuiltinType::ULong:
71 return "unsigned long";
72 case PDB_BuiltinType::Bool:
73 return "bool";
74 case PDB_BuiltinType::Currency:
75 return "CURRENCY";
76 case PDB_BuiltinType::Date:
77 return "DATE";
78 case PDB_BuiltinType::Variant:
79 return "VARIANT";
80 case PDB_BuiltinType::Complex:
81 return "complex";
82 case PDB_BuiltinType::Bitfield:
83 return "bitfield";
84 case PDB_BuiltinType::BSTR:
85 return "BSTR";
86 case PDB_BuiltinType::HResult:
87 return "HRESULT";
88 case PDB_BuiltinType::BCD:
89 return "HRESULT";
90 default:
91 return "void";
92 }
93 }
+0
-35
tools/llvm-pdbdump/PrettyBuiltinDumper.h less more
None //===- PrettyBuiltinDumper.h ---------------------------------- *- C++ --*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_PRETTYBUILTINDUMPER_H
11
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
14
15 namespace llvm {
16 namespace pdb {
17
18 class LinePrinter;
19
20 class BuiltinDumper : public PDBSymDumper {
21 public:
22 BuiltinDumper(LinePrinter &P);
23
24 void start(const PDBSymbolTypeBuiltin &Symbol);
25
26 private:
27 StringRef getTypeName(const PDBSymbolTypeBuiltin &Symbol);
28
29 LinePrinter &Printer;
30 };
31 }
32 }
33
34 #endif
+0
-108
tools/llvm-pdbdump/PrettyClassDefinitionDumper.cpp less more
None //===- PrettyClassDefinitionDumper.cpp --------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "PrettyClassDefinitionDumper.h"
10
11 #include "LinePrinter.h"
12 #include "PrettyClassLayoutGraphicalDumper.h"
13 #include "llvm-pdbdump.h"
14
15 #include "llvm/ADT/APFloat.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
18 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
19 #include "llvm/DebugInfo/PDB/UDTLayout.h"
20
21 #include "llvm/Support/Format.h"
22
23 using namespace llvm;
24 using namespace llvm::pdb;
25
26 ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
27 : PDBSymDumper(true), Printer(P) {}
28
29 void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
30 assert(opts::pretty::ClassFormat !=
31 opts::pretty::ClassDefinitionFormat::None);
32
33 ClassLayout Layout(Class);
34 start(Layout);
35 }
36
37 void ClassDefinitionDumper::start(const ClassLayout &Layout) {
38 prettyPrintClassIntro(Layout);
39
40 PrettyClassLayoutGraphicalDumper Dumper(Printer, 1, 0);
41 DumpedAnything |= Dumper.start(Layout);
42
43 prettyPrintClassOutro(Layout);
44 }
45
46 void ClassDefinitionDumper::prettyPrintClassIntro(const ClassLayout &Layout) {
47 DumpedAnything = false;
48 Printer.NewLine();
49
50 uint32_t Size = Layout.getSize();
51 const PDBSymbolTypeUDT &Class = Layout.getClass();
52
53 WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
54 WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
55 WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size
56 << "]";
57 uint32_t BaseCount = Layout.bases().size();
58 if (BaseCount > 0) {
59 Printer.Indent();
60 char NextSeparator = ':';
61 for (auto BC : Layout.bases()) {
62 const auto &Base = BC->getBase();
63 if (Base.isIndirectVirtualBaseClass())
64 continue;
65
66 Printer.NewLine();
67 Printer << NextSeparator << " ";
68 WithColor(Printer, PDB_ColorItem::Keyword).get() << Base.getAccess();
69 if (BC->isVirtualBase())
70 WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
71
72 WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base.getName();
73 NextSeparator = ',';
74 }
75
76 Printer.Unindent();
77 }
78
79 Printer << " {";
80 Printer.Indent();
81 }
82
83 void ClassDefinitionDumper::prettyPrintClassOutro(const ClassLayout &Layout) {
84 Printer.Unindent();
85 if (DumpedAnything)
86 Printer.NewLine();
87 Printer << "}";
88 Printer.NewLine();
89 if (Layout.deepPaddingSize() > 0) {
90 APFloat Pct(100.0 * (double)Layout.deepPaddingSize() /
91 (double)Layout.getSize());
92 SmallString<8> PctStr;
93 Pct.toString(PctStr, 4);
94 WithColor(Printer, PDB_ColorItem::Padding).get()
95 << "Total padding " << Layout.deepPaddingSize() << " bytes (" << PctStr
96 << "% of class size)";
97 Printer.NewLine();
98 APFloat Pct2(100.0 * (double)Layout.immediatePadding() /
99 (double)Layout.getSize());
100 PctStr.clear();
101 Pct2.toString(PctStr, 4);
102 WithColor(Printer, PDB_ColorItem::Padding).get()
103 << "Immediate padding " << Layout.immediatePadding() << " bytes ("
104 << PctStr << "% of class size)";
105 Printer.NewLine();
106 }
107 }
+0
-47
tools/llvm-pdbdump/PrettyClassDefinitionDumper.h less more
None //===- PrettyClassDefinitionDumper.h ----------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H
10 #define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSDEFINITIONDUMPER_H
11
12 #include "llvm/ADT/BitVector.h"
13
14 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
17
18 #include
19 #include
20 #include
21
22 namespace llvm {
23 class BitVector;
24
25 namespace pdb {
26
27 class ClassLayout;
28 class LinePrinter;
29
30 class ClassDefinitionDumper : public PDBSymDumper {
31 public:
32 ClassDefinitionDumper(LinePrinter &P);
33
34 void start(const PDBSymbolTypeUDT &Class);
35 void start(const ClassLayout &Class);
36
37 private:
38 void prettyPrintClassIntro(const ClassLayout &Class);
39 void prettyPrintClassOutro(const ClassLayout &Class);
40
41 LinePrinter &Printer;
42 bool DumpedAnything = false;
43 };
44 }
45 }
46 #endif
+0
-216
tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp less more
None //===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "PrettyClassLayoutGraphicalDumper.h"
10
11 #include "LinePrinter.h"
12 #include "PrettyClassDefinitionDumper.h"
13 #include "PrettyEnumDumper.h"
14 #include "PrettyFunctionDumper.h"
15 #include "PrettyTypedefDumper.h"
16 #include "PrettyVariableDumper.h"
17 #include "PrettyVariableDumper.h"
18 #include "llvm-pdbdump.h"
19
20 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
22 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
23 #include "llvm/DebugInfo/PDB/UDTLayout.h"
24 #include "llvm/Support/Format.h"
25
26 using namespace llvm;
27 using namespace llvm::pdb;
28
29 PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
30 LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)
31 : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),
32 ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}
33
34 bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
35
36 if (RecursionLevel == 1 &&
37 opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {
38 for (auto &Other : Layout.other_items())
39 Other->dump(*this);
40 for (auto &Func : Layout.funcs())
41 Func->dump(*this);
42 }
43
44 const BitVector &UseMap = Layout.usedBytes();
45 int NextPaddingByte = UseMap.find_first_unset();
46
47 for (auto &Item : Layout.layout_items()) {
48 // Calculate the absolute offset of the first byte of the next field.