DWARF: Add support for type units+split dwarf combo
authorPavel Labath <pavel@labath.sk>
Tue, 25 Jun 2019 06:59:48 +0000 (06:59 +0000)
committerPavel Labath <pavel@labath.sk>
Tue, 25 Jun 2019 06:59:48 +0000 (06:59 +0000)
Summary:
With the last round of refactors, supporting type units in dwo files
becomes almost trivial. This patch contains a couple of small fixes,
which taken as a whole make type units work in the split dwarf scenario
(both DWARF4 and DWARF5):
- DWARFContext: make sure we actually read the debug_types.dwo section
- DWARFUnit: set string offsets base on all units in the dwo file, not
  just the main CU
- ManualDWARFIndex: index all units in the file
- SymbolFileDWARFDwo: Search for the single compile unit in the file, as
  we can no longer assume it will be the first one

The last part makes it obvious that there is still some work to be done
here, namely that we do not support dwo files with multiple compile
units. That is something that should be easier after the DIERef
refactors, but it still requires more work.

Tests are added for the type units+split dwarf + dwarf4/5 scenarios, as
well as a test that checks we behave reasonably in the presence of dwo
files with multiple CUs.

Reviewers: clayborg, JDevlieghere, aprantl

Subscribers: arphaman, lldb-commits

Differential Revision: https://reviews.llvm.org/D63643

llvm-svn: 364274

lldb/lit/SymbolFile/DWARF/debug-types-basic.test
lldb/lit/SymbolFile/DWARF/debug-types-expressions.test
lldb/lit/SymbolFile/DWARF/split-dwarf-multiple-cu.ll [new file with mode: 0644]
lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h

index bf2c9c69d1dbc48f96518b2558d686dee7bc10af..24a6a651d5f94ab4bcd60d963a7a111660587606 100644 (file)
@@ -2,15 +2,27 @@
 
 # Make sure DWARF v4 type units work.
 # RUN: %clangxx -target x86_64-pc-linux %S/Inputs/debug-types-basic.cpp \
-# RUN:   -g -gdwarf-4 -fdebug-types-section -c -o %t.o
-# RUN: ld.lld %t.o -o %t
-# RUN: %lldb %t -s %s -o exit | FileCheck %s
+# RUN:   -g -gdwarf-4 -fdebug-types-section -c -o %t4.o
+# RUN: ld.lld %t4.o -o %t4
+# RUN: %lldb %t4 -s %s -o exit | FileCheck %s
 
 # Now do the same for DWARF v5.
 # RUN: %clangxx -target x86_64-pc-linux %S/Inputs/debug-types-basic.cpp \
-# RUN:   -g -gdwarf-5 -fdebug-types-section -c -o %t.o
-# RUN: ld.lld %t.o -o %t
-# RUN: %lldb %t -s %s -o exit | FileCheck %s
+# RUN:   -g -gdwarf-5 -fdebug-types-section -c -o %t5.o
+# RUN: ld.lld %t5.o -o %t5
+# RUN: %lldb %t5 -s %s -o exit | FileCheck %s
+
+# Test type units in dwo files.
+# RUN: %clangxx -target x86_64-pc-linux %S/Inputs/debug-types-basic.cpp \
+# RUN:   -g -gdwarf-4 -fdebug-types-section -gsplit-dwarf -c -o %t4dwo.o
+# RUN: ld.lld %t4dwo.o -o %t4dwo
+# RUN: %lldb %t4dwo -s %s -o exit | FileCheck %s
+
+# And type units+dwo+dwarf5.
+# RUN: %clangxx -target x86_64-pc-linux %S/Inputs/debug-types-basic.cpp \
+# RUN:   -g -gdwarf-5 -fdebug-types-section -c -o %t5dwo.o
+# RUN: ld.lld %t5dwo.o -o %t5dwo
+# RUN: %lldb %t5dwo -s %s -o exit | FileCheck %s
 
 type lookup A
 # CHECK-LABEL: type lookup A
index da40269461afe7fbb0d45dd915cb7b8b31d4b998..6da06d7b74f375ddcb73d1729e3c2c2f87a77056 100644 (file)
@@ -2,13 +2,23 @@
 
 # Make sure DWARF v4 type units work.
 # RUN: %clangxx %S/Inputs/debug-types-expressions.cpp \
-# RUN:   -g -fdebug-types-section -o %t
-# RUN: %lldb %t -s %s -o exit | FileCheck %s
+# RUN:   -g -gdwarf-4 -fdebug-types-section -o %t4
+# RUN: %lldb %t4 -s %s -o exit | FileCheck %s
 
 # Now do the same for DWARF v5.
 # RUN: %clangxx %S/Inputs/debug-types-expressions.cpp \
-# RUN:   -g -gdwarf-5 -fdebug-types-section -o %t
-# RUN: %lldb %t -s %s -o exit | FileCheck %s
+# RUN:   -g -gdwarf-5 -fdebug-types-section -o %t5
+# RUN: %lldb %t5 -s %s -o exit | FileCheck %s
+
+# Test type units in dwo files.
+# RUN: %clangxx %S/Inputs/debug-types-expressions.cpp \
+# RUN:   -g -gdwarf-4 -fdebug-types-section -o %t4dwo
+# RUN: %lldb %t4dwo -s %s -o exit | FileCheck %s
+
+# And type units+dwo+dwarf5.
+# RUN: %clangxx %S/Inputs/debug-types-expressions.cpp \
+# RUN:   -g -gdwarf-5 -fdebug-types-section -o %t5dwo
+# RUN: %lldb %t5dwo -s %s -o exit | FileCheck %s
 
 breakpoint set -n foo
 process launch
diff --git a/lldb/lit/SymbolFile/DWARF/split-dwarf-multiple-cu.ll b/lldb/lit/SymbolFile/DWARF/split-dwarf-multiple-cu.ll
new file mode 100644 (file)
index 0000000..9c23487
--- /dev/null
@@ -0,0 +1,40 @@
+; Check handling of dwo files with multiple compile units. Right now this is not
+; supported, but it should not cause us to crash or misbehave either...
+
+; RUN: llc %s -filetype=obj -o %t.o --split-dwarf-file=%t.o
+; RUN: %lldb %t.o -o "image lookup -s x1 -v" -o "image lookup -s x2 -v" -b | FileCheck %s
+
+; CHECK: image lookup -s x1
+; CHECK: 1 symbols match 'x1'
+; CHECK-NOT: CompileUnit:
+; CHECK-NOT: Variable:
+
+; CHECK: image lookup -s x2
+; CHECK: 1 symbols match 'x2'
+; CHECK-NOT: CompileUnit:
+; CHECK-NOT: Variable:
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@x1 = dso_local global i32 42, align 4, !dbg !10
+@x2 = dso_local global i32 47, align 4, !dbg !20
+
+!llvm.dbg.cu = !{!12, !22}
+!llvm.module.flags = !{!8, !9, !1}
+
+!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
+!11 = distinct !DIGlobalVariable(name: "x1", scope: !12, type: !7)
+!12 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, emissionKind: FullDebug, globals: !15)
+!15 = !{!10}
+
+!20 = !DIGlobalVariableExpression(var: !21, expr: !DIExpression())
+!21 = distinct !DIGlobalVariable(name: "x2", scope: !22, type: !7)
+!22 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, emissionKind: FullDebug, globals: !25)
+!25 = !{!20}
+
+!3 = !DIFile(filename: "-", directory: "/tmp")
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = !{i32 1, !"wchar_size", i32 4}
index 96d193cbf82aed6489795b5f4cce7b81eb0ffd16..9fd4ec616e274009f82267628f014bf35aa0fc94 100644 (file)
@@ -97,6 +97,6 @@ const DWARFDataExtractor &DWARFContext::getOrLoadStrOffsetsData() {
 }
 
 const DWARFDataExtractor &DWARFContext::getOrLoadDebugTypesData() {
-  return LoadOrGetSection(eSectionTypeDWARFDebugTypes, llvm::None,
-                          m_data_debug_types);
+  return LoadOrGetSection(eSectionTypeDWARFDebugTypes,
+                          eSectionTypeDWARFDebugTypesDwo, m_data_debug_types);
 }
index 06e9bed31903e1a0e26bc95c3f9aaf1f0b8c12f1..917fbf916c551ca78a71e79650cdf67447730924 100644 (file)
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Utility/Stream.h"
 
-#include "DWARFUnit.h"
+#include "DWARFCompileUnit.h"
 #include "DWARFDebugAbbrev.h"
 #include "DWARFDebugAranges.h"
 #include "DWARFDebugInfo.h"
 #include "DWARFDebugRanges.h"
 #include "DWARFDeclContext.h"
 #include "DWARFFormValue.h"
+#include "DWARFUnit.h"
 #include "SymbolFileDWARF.h"
 #include "SymbolFileDWARFDwo.h"
 
@@ -657,7 +658,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
   if (!dwo_symbol_file)
     return 0;
 
-  DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
+  DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
   if (!dwo_cu)
     return 0;
 
index 7eea51fbfd3c500529cf41db5c5e3dda5c09d8e2..33e83d1fe57f60ac6ba12fd8b4e90575bf088da2 100644 (file)
@@ -363,7 +363,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
   else if (gnu_ranges_base)
     dwo_cu->SetRangesBase(*gnu_ranges_base);
 
-  SetDwoStrOffsetsBase(dwo_cu);
+  for (size_t i = 0; i < m_dwo_symbol_file->DebugInfo()->GetNumUnits(); ++i) {
+    DWARFUnit *unit = m_dwo_symbol_file->DebugInfo()->GetUnitAtIndex(i);
+    SetDwoStrOffsetsBase(unit);
+  }
 }
 
 DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
index 00f2dbfa03775be73528078abc100b4836595235..aff8b5d8c15fd19e5a4097a1876eaa1c5226acb7 100644 (file)
@@ -104,9 +104,10 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, IndexSet &set) {
 
   IndexUnitImpl(unit, cu_language, set);
 
-  SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile();
-  if (dwo_symbol_file && dwo_symbol_file->GetCompileUnit()) {
-    IndexUnitImpl(*dwo_symbol_file->GetCompileUnit(), cu_language, set);
+  if (SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile()) {
+    DWARFDebugInfo &dwo_info = *dwo_symbol_file->DebugInfo();
+    for (size_t i = 0; i < dwo_info.GetNumUnits(); ++i)
+      IndexUnitImpl(*dwo_info.GetUnitAtIndex(i), cu_language, set);
   }
 }
 
index c6911449c7392b3c7eed86b15e57be1b99791806..c5b54b65ea29c5539fc4dbee514a3cca88edf749 100644 (file)
@@ -12,6 +12,7 @@
 #include "lldb/Expression/DWARFExpression.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Utility/LLDBAssert.h"
+#include "llvm/Support/Casting.h"
 
 #include "DWARFCompileUnit.h"
 #include "DWARFDebugInfo.h"
@@ -54,12 +55,34 @@ SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
   return GetBaseSymbolFile().ParseCompileUnit(m_base_dwarf_cu);
 }
 
-DWARFUnit *SymbolFileDWARFDwo::GetCompileUnit() {
-  // Only dwo files with 1 compile unit is supported
-  if (GetNumCompileUnits() == 1)
-    return DebugInfo()->GetUnitAtIndex(0);
-  else
+DWARFCompileUnit *SymbolFileDWARFDwo::GetCompileUnit() {
+  if (!m_cu)
+    m_cu = ComputeCompileUnit();
+  return m_cu;
+}
+
+DWARFCompileUnit *SymbolFileDWARFDwo::ComputeCompileUnit() {
+  DWARFDebugInfo *debug_info = DebugInfo();
+  if (!debug_info)
     return nullptr;
+
+  // Right now we only support dwo files with one compile unit. If we don't have
+  // type units, we can just check for the unit count.
+  if (!debug_info->ContainsTypeUnits() && debug_info->GetNumUnits() == 1)
+    return llvm::cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(0));
+
+  // Otherwise, we have to run through all units, and find the compile unit that
+  // way.
+  DWARFCompileUnit *cu = nullptr;
+  for (size_t i = 0; i < debug_info->GetNumUnits(); ++i) {
+    if (auto *candidate =
+            llvm::dyn_cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(i))) {
+      if (cu)
+        return nullptr; // More that one CU found.
+      cu = candidate;
+    }
+  }
+  return cu;
 }
 
 DWARFUnit *
index 663f2d400540d9b6edcc4684a866ed1cae91d0d0..9b2f3bb84c4f341943e39da6d2ed04c61a557cb0 100644 (file)
@@ -19,7 +19,7 @@ public:
 
   lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu) override;
 
-  DWARFUnit *GetCompileUnit();
+  DWARFCompileUnit *GetCompileUnit();
 
   DWARFUnit *
   GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override;
@@ -69,8 +69,11 @@ protected:
 
   SymbolFileDWARF &GetBaseSymbolFile();
 
+  DWARFCompileUnit *ComputeCompileUnit();
+
   lldb::ObjectFileSP m_obj_file_sp;
   DWARFCompileUnit &m_base_dwarf_cu;
+  DWARFCompileUnit *m_cu = nullptr;
 };
 
 #endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_