diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -223,6 +223,8 @@ uint8_t GetUnitType() const { return m_header.GetUnitType(); } bool IsTypeUnit() const { return m_header.IsTypeUnit(); } + /// Note that this check only works for DWARF5+. + bool IsSkeletonUnit() const { return GetUnitType() == llvm::dwarf::DW_UT_skeleton; } std::optional GetStringOffsetSectionItem(uint32_t index) const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -162,12 +162,13 @@ // though as some functions have template parameter types and other things // that cause extra copies of types to be included, but we should find these // types in the .dwo file only as methods could have return types removed and - // we don't have to index incomplete types from the skeletone compile unit. + // we don't have to index incomplete types from the skeleton compile unit. if (unit.GetDWOId()) { + // Index the .dwo or dwp instead of the skeleton unit. if (SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile()) { // Type units in a dwp file are indexed separately, so we just need to - // process the split unit here. However, if the split unit is in a dwo file, - // then we need to process type units here. + // process the split unit here. However, if the split unit is in a dwo + // file, then we need to process type units here. if (dwo_symbol_file == dwp) { IndexUnitImpl(unit.GetNonSkeletonUnit(), cu_language, set); } else { @@ -175,11 +176,22 @@ for (size_t i = 0; i < dwo_info.GetNumUnits(); ++i) IndexUnitImpl(*dwo_info.GetUnitAtIndex(i), cu_language, set); } + return; } - } else { - // We either have a normal compile unit which we want to index. - IndexUnitImpl(unit, cu_language, set); + // This was a DWARF5 skeleton CU and the .dwo file couldn't be located. + if (unit.GetVersion() >= 5 && unit.IsSkeletonUnit()) + return; + + // Either this is a DWARF 4 + fission CU with the .dwo file + // missing, or it's a -gmodules pch or pcm. Try to detect the + // latter by checking whether the first DIE is a DW_TAG_module. + // If it's a pch/pcm, continue indexing it. + if (unit.GetDIE(unit.GetFirstDIEOffset()).GetFirstChild().Tag() != + llvm::dwarf::DW_TAG_module) + return; } + // We have a normal compile unit which we want to index. + IndexUnitImpl(unit, cu_language, set); } void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit, diff --git a/lldb/test/Shell/SymbolFile/DWARF/Inputs/pch.h b/lldb/test/Shell/SymbolFile/DWARF/Inputs/pch.h new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/Inputs/pch.h @@ -0,0 +1,5 @@ +typedef int anchor_t; + +struct TypeFromPCH { + int field; +}; diff --git a/lldb/test/Shell/SymbolFile/DWARF/clang-gmodules-type-lookup.c b/lldb/test/Shell/SymbolFile/DWARF/clang-gmodules-type-lookup.c new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/clang-gmodules-type-lookup.c @@ -0,0 +1,18 @@ +// UNSUPPORTED: system-windows + +// Test that LLDB can follow DWO links produced by -gmodules debug +// info to find a type in a precompiled header. +// +// RUN: %clangxx_host -g -gmodules -fmodules -std=c99 -x c-header %S/Inputs/pch.h -g -c -o %t.pch +// RUN: %clangxx_host -g -gmodules -fmodules -std=c99 -x c -include-pch %t.pch %s -c -o %t.o +// RUN: %clangxx_host %t.o -o %t.exe +// RUN: lldb-test symbols -dump-clang-ast -find type --language=C99 \ +// RUN: -compiler-context 'AnyModule:*,Struct:TypeFromPCH' %t.exe | FileCheck %s + +anchor_t anchor; + +int main(int argc, char **argv) { return 0; } + +// CHECK: Found 1 type +// CHECK: "TypeFromPCH" +// CHECK: FieldDecl {{.*}} field