[Lldb-commits] [lldb] 2cf6968 - [lldb/DWARF] Fix a split-dwarf crash while parsing compile units

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Apr 29 07:21:20 PDT 2020


Author: Pavel Labath
Date: 2020-04-29T16:21:11+02:00
New Revision: 2cf69684fb3089a2cde46fc9eac22dd6b8475b5f

URL: https://github.com/llvm/llvm-project/commit/2cf69684fb3089a2cde46fc9eac22dd6b8475b5f
DIFF: https://github.com/llvm/llvm-project/commit/2cf69684fb3089a2cde46fc9eac22dd6b8475b5f.diff

LOG: [lldb/DWARF] Fix a split-dwarf crash while parsing compile units

The cause of this crash is relatively simple -- we are using a
SymbolFileDWARFDwo to parse a (skeleton) dwarf unit. This cause the
CompileUnit to be created with the wrong ID, which later triggers an
assertion in SymbolFile::SetCompileUnitAtIndex. The fix is also simple
-- ensure we use the right symbol file for parsing.

However, a fairly elaborate setup is needed trigger this bug, because
ParseCompileUnit is normally called very early on (and with the right
symbol file object) during the process of accessing a compile unit.
The only way this can be triggered is if the DWARF unit is
"accidentally" pulled into scope during expression evaluation
This can happen if the "this" object used for the context of an
expression is in a namespace, and that namespace is also present in
other compile units

The included test recreates this setup.

Added: 
    lldb/test/Shell/SymbolFile/DWARF/split-dwarf-expression-eval-bug.cpp

Modified: 
    lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 5eebc9657905..ca7710d8ab14 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1450,17 +1450,20 @@ Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
 
 CompileUnit *
 SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu) {
-  DWARFCompileUnit *non_dwo_cu =
-      dwarf_cu.IsDWOUnit()
-          ? static_cast<DWARFCompileUnit *>(dwarf_cu.GetUserData())
-          : &dwarf_cu;
+  if (dwarf_cu.IsDWOUnit()) {
+    DWARFCompileUnit *non_dwo_cu =
+        static_cast<DWARFCompileUnit *>(dwarf_cu.GetUserData());
+    assert(non_dwo_cu);
+    return non_dwo_cu->GetSymbolFileDWARF().GetCompUnitForDWARFCompUnit(
+        *non_dwo_cu);
+  }
   // Check if the symbol vendor already knows about this compile unit?
-  if (non_dwo_cu->GetUserData() == nullptr) {
+  if (dwarf_cu.GetUserData() == nullptr) {
     // The symbol vendor doesn't know about this compile unit, we need to parse
     // and add it to the symbol vendor object.
-    return ParseCompileUnit(*non_dwo_cu).get();
+    return ParseCompileUnit(dwarf_cu).get();
   }
-  return static_cast<CompileUnit *>(non_dwo_cu->GetUserData());
+  return static_cast<CompileUnit *>(dwarf_cu.GetUserData());
 }
 
 void SymbolFileDWARF::GetObjCMethods(

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/split-dwarf-expression-eval-bug.cpp b/lldb/test/Shell/SymbolFile/DWARF/split-dwarf-expression-eval-bug.cpp
new file mode 100644
index 000000000000..dcdc81b3e7eb
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/split-dwarf-expression-eval-bug.cpp
@@ -0,0 +1,37 @@
+// This tests a crash which occured under very specific circumstances. The
+// interesting aspects of this test are:
+// - we print a global variable from one compile unit
+// - we are stopped in a member function of a class in a namespace
+// - that namespace is also present in a third file, which also has a global
+//   variable
+
+// UNSUPPORTED: system-darwin, system-windows
+
+// RUN: %clang_host -c -gsplit-dwarf %s -o %t1.o -DONE
+// RUN: %clang_host -c -gsplit-dwarf %s -o %t2.o -DTWO
+// RUN: %clang_host -c -gsplit-dwarf %s -o %t3.o -DTHREE
+// RUN: %clang_host %t1.o %t2.o %t3.o -o %t
+// RUN: %lldb %t -o "br set -n foo" -o run -o "p bool_in_first_cu" -o exit \
+// RUN:   | FileCheck %s
+
+// CHECK: (lldb) p bool_in_first_cu
+// CHECK: (bool) $0 = true
+
+
+#if defined(ONE)
+bool bool_in_first_cu = true;
+#elif defined(TWO)
+bool bool_in_second_cu = true;
+
+namespace NS {
+void f() {}
+}
+#elif defined(THREE)
+namespace NS {
+struct S {
+  void foo() {}
+};
+}
+
+int main() { NS::S().foo(); }
+#endif


        


More information about the lldb-commits mailing list