[llvm] [llvm][dwarfdump] Add --child-tags option to filter by DWARF tags (PR #165720)

Michael Buch via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 30 06:45:54 PDT 2025


https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/165720

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 22.0.0git (git at github.com:Michael137/llvm-project.git 737da3347c2fb01dd403420cf83e9b8fbea32618)")
              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 22.0.0git (git at github.com:Michael137/llvm-project.git 737da3347c2fb01dd403420cf83e9b8fbea32618)")
              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)             
...                                       
```

>From 80328f1cc998a4779f14f92ed9f57684950c0d0e Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 21 Oct 2025 16:51:43 +0100
Subject: [PATCH] [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.
---
 llvm/include/llvm/DebugInfo/DIContext.h      |  2 ++
 llvm/lib/DebugInfo/DWARF/DWARFDie.cpp        |  4 +++-
 llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 24 ++++++++++++++++++++
 3 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h
index e7e87bbfebf38..32ce4520dbca7 100644
--- a/llvm/include/llvm/DebugInfo/DIContext.h
+++ b/llvm/include/llvm/DebugInfo/DIContext.h
@@ -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> ChildTagsFilter;
   bool ShowForm = false;
   bool SummarizeTypes = false;
   bool Verbose = false;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index db5cc37c93f90..7558fbda18459 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -676,7 +676,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.ChildTagsFilter.empty() ||
+                llvm::is_contained(DumpOpts.ChildTagsFilter, Child.getTag()))
+              Child.dump(OS, Indent + 2, ChildDumpOpts);
             Child = Child.getSibling();
           }
         }
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 79f05278c329d..eb5f8b4af95a6 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -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"
@@ -241,6 +242,15 @@ static opt<bool>
                 cat(DwarfDumpCategory));
 static alias ShowParentsAlias("p", desc("Alias for --show-parents."),
                               aliasopt(ShowParents), cl::NotHidden);
+
+static list<std::string>
+    ChildTags("child-tags",
+              desc("When --show-children is specified, show only DIEs with the "
+                   "specified DWARF tags."),
+              value_desc("list of DWARF tags"), cat(DwarfDumpCategory));
+static alias TagsAlias("t", desc("Alias for --child-tags."),
+                       aliasopt(ChildTags), cl::NotHidden);
+
 static opt<bool>
     ShowForm("show-form",
              desc("Show DWARF form types after the DWARF attribute types."),
@@ -329,6 +339,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;
@@ -355,6 +372,7 @@ static DIDumpOptions getDumpOpts(DWARFContext &C) {
   DumpOpts.ShowAddresses = !Diff;
   DumpOpts.ShowChildren = ShowChildren;
   DumpOpts.ShowParents = ShowParents;
+  DumpOpts.ChildTagsFilter = makeTagVector(ChildTags);
   DumpOpts.ShowForm = ShowForm;
   DumpOpts.SummarizeTypes = SummarizeTypes;
   DumpOpts.Verbose = Verbose;
@@ -898,6 +916,12 @@ int main(int argc, char **argv) {
       Find.empty() && !FindAllApple)
     ShowChildren = true;
 
+  if (!ShowChildren && !ChildTags.empty()) {
+    WithColor::error()
+        << "incompatible arguments: --child-tags requires --show-children";
+    return 1;
+  }
+
   // Defaults to a.out if no filenames specified.
   if (InputFilenames.empty())
     InputFilenames.push_back("a.out");



More information about the llvm-commits mailing list