Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions llvm/docs/CommandGuide/llvm-dwarfdump.rst
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ OPTIONS

Abbreviate the description of type unit entries.

.. option:: -t, --filter-child-tag

Only dump children whose DWARF tag is one of the specified tags.
Example usage:
`llvm-dwarfdump -t DW_TAG_structure_type -t DW_TAG_member -c`

.. option:: -x, --regex

Treat any <name> strings as regular expressions when searching
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/DebugInfo/DIContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ struct DIDumpOptions {
bool ShowAddresses = true;
bool ShowChildren = false;
bool ShowParents = false;
/// List of DWARF tags to filter children by.
llvm::SmallVector<unsigned, 0> FilterChildTag;
bool ShowForm = false;
bool SummarizeTypes = false;
bool Verbose = false;
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,9 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
DIDumpOptions ChildDumpOpts = DumpOpts;
ChildDumpOpts.ShowParents = false;
while (Child) {
Child.dump(OS, Indent + 2, ChildDumpOpts);
if (DumpOpts.FilterChildTag.empty() ||
llvm::is_contained(DumpOpts.FilterChildTag, Child.getTag()))
Child.dump(OS, Indent + 2, ChildDumpOpts);
Child = Child.getSibling();
}
}
Expand Down
127 changes: 127 additions & 0 deletions llvm/test/tools/llvm-dwarfdump/X86/filter-child-tag.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Tests the --filter-child-tag (-t) option.
# RUN: yaml2obj %s -o %t.o
# RUN: llvm-dwarfdump %t.o --filter-child-tag=DW_TAG_structure_type | FileCheck %s --check-prefix=ONLY_STRUCT
# RUN: llvm-dwarfdump %t.o -t DW_TAG_structure_type -t DW_TAG_namespace | FileCheck %s --check-prefix=STRUCT_AND_NS --implicit-check-not=DW_TAG_subprogram --implicit-check-not=DW_TAG_member
# RUN: llvm-dwarfdump %t.o -c --name=Foo -t DW_TAG_member | 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
# RUN: llvm-dwarfdump %t.o -c --name=Foo -t not_a_tag -t DW_TAG_member | 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
# RUN: llvm-dwarfdump %t.o -c --name=Foo -t not_a_tag | 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
# RUN: llvm-dwarfdump %t.o -c -p --name=Foo -t DW_TAG_member | FileCheck %s --check-prefix=FOO_MEM_WITH_PARENT --implicit-check-not=DW_TAG_subprogram
# RUN: not llvm-dwarfdump %t.o --name=Foo -t DW_TAG_member 2>&1 | FileCheck %s --check-prefix=ERROR_NO_SHOW_CHILDREN

# ONLY_STRUCT: DW_TAG_compile_unit
# ONLY_STRUCT-NOT: DW_TAG_namespace
# ONLY_STRUCT-NOT: DW_TAG_structure_type

# STRUCT_AND_NS: DW_TAG_compile_unit
# STRUCT_AND_NS: DW_TAG_namespace
# STRUCT_AND_NS: DW_TAG_structure_type
# STRUCT_AND_NS: DW_TAG_structure_type

# FOO_MEM: DW_TAG_structure_type
# FOO_MEM: DW_TAG_member
# FOO_MEM: DW_TAG_member
# FOO_MEM: DW_TAG_member
# FOO_MEM-NOT: DW_TAG_structure_type
# FOO_MEM-NOT: DW_TAG_member

# SINGLE_INVALID_TAG: DW_TAG_structure_type
# SINGLE_INVALID_TAG: DW_TAG_member
# SINGLE_INVALID_TAG: DW_TAG_member
# SINGLE_INVALID_TAG: DW_TAG_member
# SINGLE_INVALID_TAG-NOT: DW_TAG_structure_type
# SINGLE_INVALID_TAG-NOT: DW_TAG_member

# ONLY_INVALID_TAGS: DW_TAG_structure_type
# ONLY_INVALID_TAGS-NOT: DW_TAG_structure_type

# FOO_MEM_WITH_PARENT: DW_TAG_compile_unit
# FOO_MEM_WITH_PARENT: DW_TAG_namespace
# FOO_MEM_WITH_PARENT: DW_TAG_structure_type
# FOO_MEM_WITH_PARENT: DW_TAG_member
# FOO_MEM_WITH_PARENT: DW_TAG_member
# FOO_MEM_WITH_PARENT: DW_TAG_member
# FOO_MEM_WITH_PARENT-NOT: DW_TAG_structure_type
# FOO_MEM_WITH_PARENT-NOT: DW_TAG_member

# ERROR_NO_SHOW_CHILDREN: incompatible arguments: --filter-child-tag requires --show-children

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
DWARF:
debug_abbrev:
- Table:
# 1
- Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_string
# 2
- Tag: DW_TAG_namespace
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_string
# 3
- Tag: DW_TAG_structure_type
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_string
# 4
- Tag: DW_TAG_member
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_string
# 5
- Tag: DW_TAG_subprogram
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_string
debug_info:
- Version: 5
UnitType: DW_UT_compile
Entries:
- AbbrCode: 1
Values:
- CStr: handwritten
- AbbrCode: 2
Values:
- CStr: ns
- AbbrCode: 3
Values:
- CStr: Foo
- AbbrCode: 4
Values:
- CStr: mem1
- AbbrCode: 4
Values:
- CStr: mem2
- AbbrCode: 4
Values:
- CStr: mem3
- AbbrCode: 3
Values:
- CStr: NestedInFoo
- AbbrCode: 4
Values:
- CStr: NestedMem1
- AbbrCode: 4
Values:
- CStr: NestedMem2
- AbbrCode: 5
Values:
- CStr: NestedFunc
- AbbrCode: 0x0
- AbbrCode: 5
Values:
- CStr: FooFunc
- AbbrCode: 0x0
- AbbrCode: 0x0
- AbbrCode: 0x0
24 changes: 24 additions & 0 deletions llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVectorExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
Expand Down Expand Up @@ -242,6 +243,15 @@ static opt<bool>
cat(DwarfDumpCategory));
static alias ShowParentsAlias("p", desc("Alias for --show-parents."),
aliasopt(ShowParents), cl::NotHidden);

static list<std::string> FilterChildTag(
"filter-child-tag",
desc("When --show-children is specified, show only DIEs with the "
"specified DWARF tags."),
value_desc("list of DWARF tags"), cat(DwarfDumpCategory));
static alias FilterChildTagAlias("t", desc("Alias for --filter-child-tag."),
aliasopt(FilterChildTag), cl::NotHidden);

static opt<bool>
ShowForm("show-form",
desc("Show DWARF form types after the DWARF attribute types."),
Expand Down Expand Up @@ -330,6 +340,13 @@ static cl::extrahelp
/// @}
//===----------------------------------------------------------------------===//

static llvm::SmallVector<unsigned>
makeTagVector(const list<std::string> &TagStrings) {
return llvm::map_to_vector(TagStrings, [](const std::string &Tag) {
return llvm::dwarf::getTag(Tag);
});
}

static void error(Error Err) {
if (!Err)
return;
Expand All @@ -356,6 +373,7 @@ static DIDumpOptions getDumpOpts(DWARFContext &C) {
DumpOpts.ShowAddresses = !Diff;
DumpOpts.ShowChildren = ShowChildren;
DumpOpts.ShowParents = ShowParents;
DumpOpts.FilterChildTag = makeTagVector(FilterChildTag);
DumpOpts.ShowForm = ShowForm;
DumpOpts.SummarizeTypes = SummarizeTypes;
DumpOpts.Verbose = Verbose;
Expand Down Expand Up @@ -899,6 +917,12 @@ int main(int argc, char **argv) {
Find.empty() && !FindAllApple)
ShowChildren = true;

if (!ShowChildren && !FilterChildTag.empty()) {
WithColor::error() << "incompatible arguments: --filter-child-tag requires "
"--show-children";
return 1;
}

// Defaults to a.out if no filenames specified.
if (InputFilenames.empty())
InputFilenames.push_back("a.out");
Expand Down