[llvm] Allow the dumping of .dwo files contents to show up when dumping an e… (PR #66726)

Greg Clayton via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 18 18:22:31 PDT 2023


https://github.com/clayborg created https://github.com/llvm/llvm-project/pull/66726

Allow the dumping of .dwo files contents to show up when dumping an executable with split DWARF.

Currently if you run llvm-dwarfdump on a binary that has skeleton compile units, you only see the skeleton compile units. Since the main binary has the linked addresses it would be nice to be able to dump DWARF from the .dwo files and how the resolved addresses instead of showing the address index and "<unresolved>" in the output. This patch adds an option that can be specified to dump the non skeleton DIEs named --dwo.

Added the ability to use the following options with split dwarf as well:
  --name <name>
  --lookup <addr>
  --debug-info <die-offset>

>From b987848ed3857a79cf677ed81bcbd2de414b4bfd Mon Sep 17 00:00:00 2001
From: Greg Clayton <gclayton at fb.com>
Date: Mon, 18 Sep 2023 18:18:41 -0700
Subject: [PATCH] Allow the dumping of .dwo files contents to show up when
 dumping an executable with split DWARF.

Currently if you run llvm-dwarfdump on a binary that has skeleton compile units, you only see the skeleton compile units. Since the main binary has the linked addresses it would be nice to be able to dump DWARF from the .dwo files and how the resolved addresses instead of showing the address index and "<unresolved>" in the output. This patch adds an option that can be specified to dump the non skeleton DIEs named --dwo.

Added the ability to use the following options with split dwarf as well:
  --name <name>
  --lookup <addr>
  --debug-info <die-offset>
---
 llvm/include/llvm/DebugInfo/DIContext.h       |  1 +
 llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp | 10 +++++--
 llvm/lib/DebugInfo/DWARF/DWARFContext.cpp     | 10 ++++++-
 llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp        |  2 +-
 .../llvm-dwarfdump/X86/statistics-dwo.test    | 22 ++++++++--------
 llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp  | 26 ++++++++++++++++++-
 6 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h
index 9ad27033ec110c2..78ac34e5f0d26c4 100644
--- a/llvm/include/llvm/DebugInfo/DIContext.h
+++ b/llvm/include/llvm/DebugInfo/DIContext.h
@@ -204,6 +204,7 @@ struct DIDumpOptions {
   bool Verbose = false;
   bool DisplayRawContents = false;
   bool IsEH = false;
+  bool DumpNonSkeleton = false;
   std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)>
       GetNameForDWARFReg;
 
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
index 6461f2ac031d2a0..30afa651ffc23a7 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
@@ -35,10 +35,16 @@ void DWARFCompileUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {
   OS << " (next unit at " << format("0x%08" PRIx64, getNextUnitOffset())
      << ")\n";
 
-  if (DWARFDie CUDie = getUnitDIE(false))
+  if (DWARFDie CUDie = getUnitDIE(false)) {
     CUDie.dump(OS, 0, DumpOpts);
-  else
+    if (DumpOpts.DumpNonSkeleton) {
+      DWARFDie NonSkeletonCUDie = getNonSkeletonUnitDIE(false);
+      if (NonSkeletonCUDie && CUDie != NonSkeletonCUDie)
+        NonSkeletonCUDie.dump(OS, 0, DumpOpts);
+    }
+  } else {
     OS << "<compile unit can't be parsed!>\n\n";
+  }
 }
 
 // VTable anchor.
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index a45ed0e56553d4e..c67728ec7bf3448 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -1007,9 +1007,17 @@ void DWARFContext::dump(
   auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) {
     OS << '\n' << Name << " contents:\n";
     if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo])
-      for (const auto &U : Units)
+      for (const auto &U : Units) {
         U->getDIEForOffset(*DumpOffset)
             .dump(OS, 0, DumpOpts.noImplicitRecursion());
+        DWARFDie CUDie = U->getUnitDIE(false);
+        DWARFDie CUNonSkeletonDie = U->getNonSkeletonUnitDIE(false);
+        if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) {
+          CUNonSkeletonDie.getDwarfUnit()->getDIEForOffset(*DumpOffset)
+              .dump(OS, 0, DumpOpts.noImplicitRecursion());
+
+        }
+      }
     else
       for (const auto &U : Units)
         U->dump(OS, DumpOpts);
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index 387345a4ac2d601..f5753b441f7b63f 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -751,7 +751,7 @@ void DWARFUnit::updateAddressDieMap(DWARFDie Die) {
 DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) {
   extractDIEsIfNeeded(false);
   if (AddrDieMap.empty())
-    updateAddressDieMap(getUnitDIE());
+    updateAddressDieMap(getNonSkeletonUnitDIE(/*ExtractUnitDIEOnly=*/false));
   auto R = AddrDieMap.upper_bound(Address);
   if (R == AddrDieMap.begin())
     return DWARFDie();
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test b/llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test
index 3e39591c46dce19..45fbc5b8945568f 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test
+++ b/llvm/test/tools/llvm-dwarfdump/X86/statistics-dwo.test
@@ -15,39 +15,39 @@ RUN: llvm-dwarfdump --statistics statistics-fib.split-dwarf.o | FileCheck %s
 # real_fib (int x, int answers[11])
 # {
 #   int result;
-# 
+#
 #   if ((answers)[x] != -1)
 #     return (answers)[x];
-# 
+#
 #   result = real_fib(x-1, answers) + real_fib(x-2, answers);
 #   (answers)[x] = result;
-# 
+#
 #   return result;
 # }
-# 
+#
 # int
 # fib (int x)
 # {
 #   int answers[11];
 #   int i;
-# 
+#
 #   if (x > 10)
 #     return -1;
-# 
+#
 #   for (i = 0; i < 11; i++)
 #     answers[i] = -1;
-# 
+#
 #   answers[0] = 0;
 #   answers[1] = 1;
 #   answers[2] = 1;
-# 
+#
 #   return real_fib(x, answers);
 # }
-# 
+#
 # int main (int argc, char **argv)
 # {
 #   int result;
-# 
+#
 #   result = fib(3);
 #   printf ("fibonacci(3) = %d\n", result);
 #   result = fib(4);
@@ -64,7 +64,7 @@ RUN: llvm-dwarfdump --statistics statistics-fib.split-dwarf.o | FileCheck %s
 #   printf ("fibonacci(9) = %d\n", result);
 #   result = fib(10);
 #   printf ("fibonacci(10) = %d\n", result);
-# 
+#
 #   return 0;
 # }
 #
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 156e10c84dddec9..46724dc571df3e3 100644
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -181,6 +181,14 @@ static opt<bool> FindAllApple(
 static opt<bool> IgnoreCase("ignore-case",
                             desc("Ignore case distinctions when using --name."),
                             value_desc("i"), cat(DwarfDumpCategory));
+static opt<bool> DumpNonSkeleton("dwo",
+                            desc("Dump the non skeleton DIE in the .dwo or "
+                                 ".dwp file after dumping the skeleton DIE "
+                                 "from the main executable. This allows "
+                                 "dumping the .dwo files with resolved "
+                                 "addresses."),
+                            value_desc("d"), cat(DwarfDumpCategory));
+
 static alias IgnoreCaseAlias("i", desc("Alias for --ignore-case."),
                              aliasopt(IgnoreCase), cl::NotHidden);
 static list<std::string> Name(
@@ -315,6 +323,7 @@ static DIDumpOptions getDumpOpts(DWARFContext &C) {
   DumpOpts.ShowForm = ShowForm;
   DumpOpts.SummarizeTypes = SummarizeTypes;
   DumpOpts.Verbose = Verbose;
+  DumpOpts.DumpNonSkeleton = DumpNonSkeleton;
   DumpOpts.RecoverableErrorHandler = C.getRecoverableErrorHandler();
   // In -verify mode, print DIEs without children in error messages.
   if (Verify) {
@@ -390,7 +399,7 @@ static void filterByName(
     const StringSet<> &Names, DWARFContext::unit_iterator_range CUs,
     raw_ostream &OS,
     std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
-  for (const auto &CU : CUs)
+  for (const auto &CU : CUs) {
     for (const auto &Entry : CU->dies()) {
       DWARFDie Die = {CU.get(), &Entry};
       if (const char *Name = Die.getName(DINameKind::ShortName))
@@ -399,6 +408,21 @@ static void filterByName(
       if (const char *Name = Die.getName(DINameKind::LinkageName))
         filterByName(Names, Die, Name, OS, GetNameForDWARFReg);
     }
+    // If we have split DWARF, then recurse down into the .dwo files as well.
+    DWARFDie CUDie = CU->getUnitDIE(false);
+    DWARFDie CUNonSkeletonDie = CU->getNonSkeletonUnitDIE(false);
+    if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie) {
+      // We have a DWO file, we need to search it as well
+      for (const auto &Entry : CUNonSkeletonDie.getDwarfUnit()->dies()) {
+        DWARFDie Die = {CUNonSkeletonDie.getDwarfUnit(), &Entry};
+        if (const char *Name = Die.getShortName())
+          if (filterByName(Names, Die, Name, OS, GetNameForDWARFReg))
+            continue;
+        if (const char *Name = Die.getLinkageName())
+          filterByName(Names, Die, Name, OS, GetNameForDWARFReg);
+      }
+    }
+  }
 }
 
 static void getDies(DWARFContext &DICtx, const AppleAcceleratorTable &Accel,



More information about the llvm-commits mailing list