Skip to content

Commit 81c6606

Browse files
authored
Merge pull request #11745 from swiftlang/llvm/dwarfdump-tag-filter-to-21.x
🍒[llvm][dwarfdump] Add --child-tags option to filter by DWARF tags This patch adds a new option `--child-tags` (`-t` for short), which makes dwarfdump only dump children whose DWARF tag is in the list of tags specified by the user. Motivating examples are: * dumping all global variables in a CU * dumping all non-static data members of a structure * dumping all module import declarations of a CU * etc. For tags not known to dwarfdump, we pretend that the tag wasn't specified. Note, this flag only takes effect when `--show-children` is set (either explicitly or implicitly). We error out when trying to use the flag without dumping children. Example: ``` $ builds/release/bin/llvm-dwarfdump -t DW_TAG_structure_type a.out.dSYM ... 0x0000000c: DW_TAG_compile_unit DW_AT_producer ("clang version)") DW_AT_language (DW_LANG_C11) ... 0x0000002a: DW_TAG_structure_type DW_AT_APPLE_block (true) DW_AT_byte_size (0x20) 0x00000067: DW_TAG_structure_type DW_AT_APPLE_block (true) DW_AT_name ("__block_descriptor") DW_AT_byte_size (0x10) ... ``` ``` $ builds/release/bin/llvm-dwarfdump -t DW_TAG_structure_type -t DW_TAG_member a.out.dSYM ... 0x0000000c: DW_TAG_compile_unit DW_AT_producer ("clang version)") DW_AT_language (DW_LANG_C11) DW_AT_name ("macro.c") ... 0x0000002a: DW_TAG_structure_type DW_AT_APPLE_block (true) DW_AT_byte_size (0x20) 0x0000002c: DW_TAG_member DW_AT_name ("__isa") DW_AT_type (0x00000051 "void *") DW_AT_data_member_location (0x00) 0x00000033: DW_TAG_member DW_AT_name ("__flags") DW_AT_type (0x00000052 "int") DW_AT_data_member_location (0x08) 0x0000003a: DW_TAG_member DW_AT_name ("__reserved") DW_AT_type (0x00000052 "int") DW_AT_data_member_location (0x0c) 0x00000041: DW_TAG_member DW_AT_name ("__FuncPtr") DW_AT_type (0x00000056 "void (*)(int)") DW_AT_data_member_location (0x10) 0x00000048: DW_TAG_member DW_AT_name ("__descriptor") DW_AT_type (0x00000062 "__block_descriptor *") DW_AT_alignment (8) DW_AT_data_member_location (0x18) 0x00000067: DW_TAG_structure_type DW_AT_APPLE_block (true) DW_AT_name ("__block_descriptor") DW_AT_byte_size (0x10) 0x0000006a: DW_TAG_member DW_AT_name ("reserved") DW_AT_type (0x00000079 "unsigned long") DW_AT_data_member_location (0x00) 0x00000071: DW_TAG_member DW_AT_name ("Size") DW_AT_type (0x00000079 "unsigned long") DW_AT_data_member_location (0x08) ... ``` (cherry picked from commit f8656ed)
2 parents 22188a0 + f39a564 commit 81c6606

File tree

6 files changed

+169
-1
lines changed

6 files changed

+169
-1
lines changed

llvm/docs/CommandGuide/llvm-dwarfdump.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ OPTIONS
134134

135135
Abbreviate the description of type unit entries.
136136

137+
.. option:: -t, --filter-child-tag
138+
139+
Only dump children whose DWARF tag is one of the specified tags.
140+
Example usage:
141+
142+
.. code-block:: c
143+
144+
llvm-dwarfdump -t DW_TAG_structure_type -t DW_TAG_member -c
145+
137146
.. option:: -x, --regex
138147

139148
Treat any <name> strings as regular expressions when searching

llvm/include/llvm/DebugInfo/DIContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ struct DIDumpOptions {
210210
bool DumpNonSkeleton = false;
211211
bool ShowAggregateErrors = false;
212212
std::string JsonErrSummaryFile;
213+
/// List of DWARF tags to filter children by.
214+
llvm::SmallVector<unsigned, 0> FilterChildTag;
213215
std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)>
214216
GetNameForDWARFReg;
215217

llvm/lib/DebugInfo/DWARF/DWARFDie.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,9 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
636636
DIDumpOptions ChildDumpOpts = DumpOpts;
637637
ChildDumpOpts.ShowParents = false;
638638
while (Child) {
639-
Child.dump(OS, Indent + 2, ChildDumpOpts);
639+
if (DumpOpts.FilterChildTag.empty() ||
640+
llvm::is_contained(DumpOpts.FilterChildTag, Child.getTag()))
641+
Child.dump(OS, Indent + 2, ChildDumpOpts);
640642
Child = Child.getSibling();
641643
}
642644
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
## Tests the --filter-child-tag (-t) option.
2+
3+
# RUN: yaml2obj %s -o %t.o
4+
5+
# RUN: llvm-dwarfdump %t.o --filter-child-tag=DW_TAG_structure_type | FileCheck %s --check-prefix=ONLY_STRUCT
6+
7+
# ONLY_STRUCT: DW_TAG_compile_unit
8+
# ONLY_STRUCT-NOT: DW_TAG_namespace
9+
# ONLY_STRUCT-NOT: DW_TAG_structure_type
10+
11+
# RUN: llvm-dwarfdump %t.o -t DW_TAG_structure_type -t DW_TAG_namespace | \
12+
# RUN: FileCheck %s --check-prefix=STRUCT_AND_NS --implicit-check-not=DW_TAG_subprogram --implicit-check-not=DW_TAG_member
13+
14+
# STRUCT_AND_NS: DW_TAG_compile_unit
15+
# STRUCT_AND_NS: DW_TAG_namespace
16+
# STRUCT_AND_NS: DW_TAG_structure_type
17+
# STRUCT_AND_NS: DW_TAG_structure_type
18+
19+
# RUN: llvm-dwarfdump %t.o -c --name=Foo -t DW_TAG_member | \
20+
# RUN: FileCheck %s --check-prefix=FOO_MEM --implicit-check-not=DW_TAG_compile_unit --implicit-check-not=DW_TAG_subprogram --implicit-check-not=DW_TAG_namespace
21+
22+
# FOO_MEM: DW_TAG_structure_type
23+
# FOO_MEM: DW_TAG_member
24+
# FOO_MEM: DW_TAG_member
25+
# FOO_MEM: DW_TAG_member
26+
# FOO_MEM-NOT: DW_TAG_structure_type
27+
# FOO_MEM-NOT: DW_TAG_member
28+
29+
# RUN: llvm-dwarfdump %t.o -c --name=Foo -t not_a_tag -t DW_TAG_member | \
30+
# RUN: FileCheck %s --check-prefix=SINGLE_INVALID_TAG --implicit-check-not=DW_TAG_compile_unit --implicit-check-not=DW_TAG_subprogram --implicit-check-not=DW_TAG_namespace
31+
32+
# SINGLE_INVALID_TAG: DW_TAG_structure_type
33+
# SINGLE_INVALID_TAG: DW_TAG_member
34+
# SINGLE_INVALID_TAG: DW_TAG_member
35+
# SINGLE_INVALID_TAG: DW_TAG_member
36+
# SINGLE_INVALID_TAG-NOT: DW_TAG_structure_type
37+
# SINGLE_INVALID_TAG-NOT: DW_TAG_member
38+
39+
# RUN: llvm-dwarfdump %t.o -c --name=Foo -t not_a_tag | \
40+
# RUN: FileCheck %s --check-prefix=ONLY_INVALID_TAGS --implicit-check-not=DW_TAG_compile_unit --implicit-check-not=DW_TAG_subprogram --implicit-check-not=DW_TAG_namespace --implicit-check-not=DW_TAG_member
41+
42+
# ONLY_INVALID_TAGS: DW_TAG_structure_type
43+
# ONLY_INVALID_TAGS-NOT: DW_TAG_structure_type
44+
45+
# RUN: llvm-dwarfdump %t.o -c -p --name=Foo -t DW_TAG_member | \
46+
# RUN: FileCheck %s --check-prefix=FOO_MEM_WITH_PARENT --implicit-check-not=DW_TAG_subprogram
47+
48+
# FOO_MEM_WITH_PARENT: DW_TAG_compile_unit
49+
# FOO_MEM_WITH_PARENT: DW_TAG_namespace
50+
# FOO_MEM_WITH_PARENT: DW_TAG_structure_type
51+
# FOO_MEM_WITH_PARENT: DW_TAG_member
52+
# FOO_MEM_WITH_PARENT: DW_TAG_member
53+
# FOO_MEM_WITH_PARENT: DW_TAG_member
54+
# FOO_MEM_WITH_PARENT-NOT: DW_TAG_structure_type
55+
# FOO_MEM_WITH_PARENT-NOT: DW_TAG_member
56+
57+
## Not specifying --show-children ignores the --filter-child-tag option.
58+
# RUN: llvm-dwarfdump %t.o --name=Foo -t DW_TAG_member 2>&1 | FileCheck %s --check-prefix=NO_SHOW_CHILDREN
59+
60+
# NO_SHOW_CHILDREN: DW_TAG_structure_type
61+
62+
--- !ELF
63+
FileHeader:
64+
Class: ELFCLASS64
65+
Data: ELFDATA2LSB
66+
Type: ET_EXEC
67+
Machine: EM_X86_64
68+
DWARF:
69+
debug_abbrev:
70+
- Table:
71+
- Tag: DW_TAG_compile_unit
72+
Children: DW_CHILDREN_yes
73+
Attributes:
74+
- Attribute: DW_AT_producer
75+
Form: DW_FORM_string
76+
- Tag: DW_TAG_namespace
77+
Children: DW_CHILDREN_yes
78+
Attributes:
79+
- Attribute: DW_AT_name
80+
Form: DW_FORM_string
81+
- Tag: DW_TAG_structure_type
82+
Children: DW_CHILDREN_yes
83+
Attributes:
84+
- Attribute: DW_AT_name
85+
Form: DW_FORM_string
86+
- Tag: DW_TAG_member
87+
Children: DW_CHILDREN_no
88+
Attributes:
89+
- Attribute: DW_AT_name
90+
Form: DW_FORM_string
91+
- Tag: DW_TAG_subprogram
92+
Children: DW_CHILDREN_no
93+
Attributes:
94+
- Attribute: DW_AT_name
95+
Form: DW_FORM_string
96+
debug_info:
97+
- Version: 5
98+
UnitType: DW_UT_compile
99+
Entries:
100+
- AbbrCode: 1
101+
Values:
102+
- CStr: handwritten
103+
- AbbrCode: 2
104+
Values:
105+
- CStr: ns
106+
- AbbrCode: 3
107+
Values:
108+
- CStr: Foo
109+
- AbbrCode: 4
110+
Values:
111+
- CStr: mem1
112+
- AbbrCode: 4
113+
Values:
114+
- CStr: mem2
115+
- AbbrCode: 4
116+
Values:
117+
- CStr: mem3
118+
- AbbrCode: 3
119+
Values:
120+
- CStr: NestedInFoo
121+
- AbbrCode: 4
122+
Values:
123+
- CStr: NestedMem1
124+
- AbbrCode: 4
125+
Values:
126+
- CStr: NestedMem2
127+
- AbbrCode: 5
128+
Values:
129+
- CStr: NestedFunc
130+
- AbbrCode: 0x0
131+
- AbbrCode: 5
132+
Values:
133+
- CStr: FooFunc
134+
- AbbrCode: 0x0
135+
- AbbrCode: 0x0
136+
- AbbrCode: 0x0

llvm/tools/llvm-dwarfdump/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(LLVM_LINK_COMPONENTS
2+
BinaryFormat
23
DebugInfoDWARF
34
DebugInfoDWARFLowLevel
45
AllTargetsDescs

llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/ADT/MapVector.h"
1515
#include "llvm/ADT/STLExtras.h"
1616
#include "llvm/ADT/SmallSet.h"
17+
#include "llvm/ADT/SmallVectorExtras.h"
1718
#include "llvm/ADT/StringSet.h"
1819
#include "llvm/DebugInfo/DIContext.h"
1920
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
@@ -241,6 +242,15 @@ static opt<bool>
241242
cat(DwarfDumpCategory));
242243
static alias ShowParentsAlias("p", desc("Alias for --show-parents."),
243244
aliasopt(ShowParents), cl::NotHidden);
245+
246+
static list<std::string> FilterChildTag(
247+
"filter-child-tag",
248+
desc("When --show-children is specified, show only DIEs with the "
249+
"specified DWARF tags."),
250+
value_desc("list of DWARF tags"), cat(DwarfDumpCategory));
251+
static alias FilterChildTagAlias("t", desc("Alias for --filter-child-tag."),
252+
aliasopt(FilterChildTag), cl::NotHidden);
253+
244254
static opt<bool>
245255
ShowForm("show-form",
246256
desc("Show DWARF form types after the DWARF attribute types."),
@@ -329,6 +339,13 @@ static cl::extrahelp
329339
/// @}
330340
//===----------------------------------------------------------------------===//
331341

342+
static llvm::SmallVector<unsigned>
343+
makeTagVector(const list<std::string> &TagStrings) {
344+
return llvm::map_to_vector(TagStrings, [](const std::string &Tag) {
345+
return llvm::dwarf::getTag(Tag);
346+
});
347+
}
348+
332349
static void error(Error Err) {
333350
if (!Err)
334351
return;
@@ -355,6 +372,7 @@ static DIDumpOptions getDumpOpts(DWARFContext &C) {
355372
DumpOpts.ShowAddresses = !Diff;
356373
DumpOpts.ShowChildren = ShowChildren;
357374
DumpOpts.ShowParents = ShowParents;
375+
DumpOpts.FilterChildTag = makeTagVector(FilterChildTag);
358376
DumpOpts.ShowForm = ShowForm;
359377
DumpOpts.SummarizeTypes = SummarizeTypes;
360378
DumpOpts.Verbose = Verbose;

0 commit comments

Comments
 (0)