[Lldb-commits] [lldb] 8dfd6ca - [lldb] [DWARF-5] Be lazier about loading .dwo files

Jan Kratochvil via lldb-commits lldb-commits at lists.llvm.org
Fri Jul 30 14:17:17 PDT 2021


Author: Eric Leese
Date: 2021-07-30T23:17:06+02:00
New Revision: 8dfd6cae9bd62ae5ef056b994ece2e98f1558830

URL: https://github.com/llvm/llvm-project/commit/8dfd6cae9bd62ae5ef056b994ece2e98f1558830
DIFF: https://github.com/llvm/llvm-project/commit/8dfd6cae9bd62ae5ef056b994ece2e98f1558830.diff

LOG: [lldb] [DWARF-5] Be lazier about loading .dwo files

This change makes sure that DwarfUnit does not load a .dwo file until
necessary. I also take advantage of DWARF 5's guarantee that the first
support file is also the primary file to make it possible to create
a compile unit without loading the .dwo file.

Review By: jankratochvil, dblaikie

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

Added: 
    lldb/test/Shell/SymbolFile/DWARF/dwarf5-lazy-dwo.c
    lldb/test/Shell/SymbolFile/DWARF/split-optimized.c

Modified: 
    lldb/include/lldb/Symbol/CompileUnit.h
    lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
    lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
    lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
    lldb/source/Symbol/CompileUnit.cpp
    lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg
    lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index 2e52bca7097c..c9a8a19f0962 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -442,6 +442,7 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
 
   CompileUnit(const CompileUnit &) = delete;
   const CompileUnit &operator=(const CompileUnit &) = delete;
+  const char *GetCachedLanguage() const;
 };
 
 } // namespace lldb_private

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 824e43872269..067561be0cf0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -35,12 +35,12 @@ DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
                      DIERef::Section section, bool is_dwo)
     : UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs),
       m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo),
-      m_dwo_id(header.GetDWOId()) {}
+      m_has_parsed_non_skeleton_unit(false), m_dwo_id(header.GetDWOId()) {}
 
 DWARFUnit::~DWARFUnit() = default;
 
-// Parses first DIE of a compile unit.
-void DWARFUnit::ExtractUnitDIEIfNeeded() {
+// Parses first DIE of a compile unit, excluding DWO.
+void DWARFUnit::ExtractUnitDIENoDwoIfNeeded() {
   {
     llvm::sys::ScopedReader lock(m_first_die_mutex);
     if (m_first_die)
@@ -50,7 +50,8 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() {
   if (m_first_die)
     return; // Already parsed
 
-  LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", GetOffset());
+  LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIENoDwoIfNeeded()",
+                     GetOffset());
 
   // Set the offset to that of the first DIE and calculate the start of the
   // next compilation unit header.
@@ -66,6 +67,58 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() {
   }
 }
 
+// Parses first DIE of a compile unit including DWO.
+void DWARFUnit::ExtractUnitDIEIfNeeded() {
+  ExtractUnitDIENoDwoIfNeeded();
+
+  if (m_has_parsed_non_skeleton_unit)
+    return;
+
+  m_has_parsed_non_skeleton_unit = true;
+
+  std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
+      m_dwarf.GetDwoSymbolFileForCompileUnit(*this, m_first_die);
+  if (!dwo_symbol_file)
+    return;
+
+  DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(m_dwo_id);
+
+  if (!dwo_cu)
+    return; // Can't fetch the compile unit from the dwo file.
+  dwo_cu->SetUserData(this);
+
+  DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
+  if (!dwo_cu_die.IsValid())
+    return; // Can't fetch the compile unit DIE from the dwo file.
+
+  // Here for DWO CU we want to use the address base set in the skeleton unit
+  // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
+  // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_*
+  // attributes which were applicable to the DWO units. The corresponding
+  // DW_AT_* attributes standardized in DWARF v5 are also applicable to the
+  // main unit in contrast.
+  if (m_addr_base)
+    dwo_cu->SetAddrBase(*m_addr_base);
+  else if (m_gnu_addr_base)
+    dwo_cu->SetAddrBase(*m_gnu_addr_base);
+
+  if (GetVersion() <= 4 && m_gnu_ranges_base)
+    dwo_cu->SetRangesBase(*m_gnu_ranges_base);
+  else if (dwo_symbol_file->GetDWARFContext()
+               .getOrLoadRngListsData()
+               .GetByteSize() > 0)
+    dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
+
+  if (GetVersion() >= 5 &&
+      dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() >
+          0)
+    dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
+
+  dwo_cu->SetBaseAddress(GetBaseAddress());
+
+  m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu);
+}
+
 // Parses a compile unit and indexes its DIEs if it hasn't already been done.
 // It will leave this compile unit extracted forever.
 void DWARFUnit::ExtractDIEsIfNeeded() {
@@ -291,14 +344,12 @@ void DWARFUnit::SetDwoStrOffsetsBase() {
 }
 
 uint64_t DWARFUnit::GetDWOId() {
-  ExtractUnitDIEIfNeeded();
+  ExtractUnitDIENoDwoIfNeeded();
   return m_dwo_id;
 }
 
 // m_die_array_mutex must be already held as read/write.
 void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
-  llvm::Optional<uint64_t> addr_base, gnu_addr_base, gnu_ranges_base;
-
   DWARFAttributes attributes;
   size_t num_attributes = cu_die.GetAttributes(this, attributes);
 
@@ -308,8 +359,7 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
       continue;
     DWARFFormValue form_value;
     if (attributes.ExtractFormValueAtIndex(i, form_value)) {
-      addr_base = form_value.Unsigned();
-      SetAddrBase(*addr_base);
+      SetAddrBase(form_value.Unsigned());
       break;
     }
   }
@@ -341,10 +391,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
       m_line_table_offset = form_value.Unsigned();
       break;
     case DW_AT_GNU_addr_base:
-      gnu_addr_base = form_value.Unsigned();
+      m_gnu_addr_base = form_value.Unsigned();
       break;
     case DW_AT_GNU_ranges_base:
-      gnu_ranges_base = form_value.Unsigned();
+      m_gnu_ranges_base = form_value.Unsigned();
       break;
     case DW_AT_GNU_dwo_id:
       m_dwo_id = form_value.Unsigned();
@@ -353,50 +403,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
   }
 
   if (m_is_dwo) {
+    m_has_parsed_non_skeleton_unit = true;
     SetDwoStrOffsetsBase();
     return;
   }
-
-  std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
-      m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die);
-  if (!dwo_symbol_file)
-    return;
-
-  DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(m_dwo_id);
-
-  if (!dwo_cu)
-    return; // Can't fetch the compile unit from the dwo file.
-  dwo_cu->SetUserData(this);
-
-  DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
-  if (!dwo_cu_die.IsValid())
-    return; // Can't fetch the compile unit DIE from the dwo file.
-
-  // Here for DWO CU we want to use the address base set in the skeleton unit
-  // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
-  // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_*
-  // attributes which were applicable to the DWO units. The corresponding
-  // DW_AT_* attributes standardized in DWARF v5 are also applicable to the main
-  // unit in contrast.
-  if (addr_base)
-    dwo_cu->SetAddrBase(*addr_base);
-  else if (gnu_addr_base)
-    dwo_cu->SetAddrBase(*gnu_addr_base);
-
-  if (GetVersion() <= 4 && gnu_ranges_base)
-    dwo_cu->SetRangesBase(*gnu_ranges_base);
-  else if (dwo_symbol_file->GetDWARFContext()
-               .getOrLoadRngListsData()
-               .GetByteSize() > 0)
-    dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
-
-  if (GetVersion() >= 5 &&
-      dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() >
-          0)
-    dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
-  dwo_cu->SetBaseAddress(GetBaseAddress());
-
-  m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu);
 }
 
 size_t DWARFUnit::GetDebugInfoSize() const {
@@ -412,7 +422,7 @@ dw_offset_t DWARFUnit::GetAbbrevOffset() const {
 }
 
 dw_offset_t DWARFUnit::GetLineTableOffset() {
-  ExtractUnitDIEIfNeeded();
+  ExtractUnitDIENoDwoIfNeeded();
   return m_line_table_offset;
 }
 

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index da79a6aaf64e..79059b67ba88 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -92,6 +92,7 @@ class DWARFUnit : public lldb_private::UserID {
   uint64_t GetDWOId();
 
   void ExtractUnitDIEIfNeeded();
+  void ExtractUnitDIENoDwoIfNeeded();
   void ExtractDIEsIfNeeded();
 
   class ScopedExtractDIEs {
@@ -151,7 +152,7 @@ class DWARFUnit : public lldb_private::UserID {
   const DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
   dw_offset_t GetAbbrevOffset() const;
   uint8_t GetAddressByteSize() const { return m_header.GetAddressByteSize(); }
-  dw_addr_t GetAddrBase() const { return m_addr_base; }
+  dw_addr_t GetAddrBase() const { return m_addr_base ? *m_addr_base : 0; }
   dw_addr_t GetBaseAddress() const { return m_base_addr; }
   dw_offset_t GetLineTableOffset();
   dw_addr_t GetRangesBase() const { return m_ranges_base; }
@@ -268,7 +269,7 @@ class DWARFUnit : public lldb_private::UserID {
   // Get the DWARF unit DWARF debug information entry. Parse the single DIE
   // if needed.
   const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
-    ExtractUnitDIEIfNeeded();
+    ExtractUnitDIENoDwoIfNeeded();
     // m_first_die_mutex is not required as m_first_die is never cleared.
     if (!m_first_die)
       return NULL;
@@ -315,9 +316,11 @@ class DWARFUnit : public lldb_private::UserID {
   lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
   llvm::Optional<lldb_private::FileSpec> m_comp_dir;
   llvm::Optional<lldb_private::FileSpec> m_file_spec;
-  dw_addr_t m_addr_base = 0;     ///< Value of DW_AT_addr_base.
-  dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base.
-  dw_addr_t m_ranges_base = 0;   ///< Value of DW_AT_rnglists_base.
+  llvm::Optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base.
+  dw_addr_t m_loclists_base = 0;         ///< Value of DW_AT_loclists_base.
+  dw_addr_t m_ranges_base = 0;           ///< Value of DW_AT_rnglists_base.
+  llvm::Optional<uint64_t> m_gnu_addr_base;
+  llvm::Optional<uint64_t> m_gnu_ranges_base;
 
   /// Value of DW_AT_stmt_list.
   dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
@@ -330,6 +333,7 @@ class DWARFUnit : public lldb_private::UserID {
 
   const DIERef::Section m_section;
   bool m_is_dwo;
+  bool m_has_parsed_non_skeleton_unit;
   /// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5).
   uint64_t m_dwo_id;
 

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index ccaf31317d75..5927ba922593 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -687,6 +687,17 @@ static void MakeAbsoluteAndRemap(FileSpec &file_spec, DWARFUnit &dwarf_cu,
     file_spec.SetFile(*remapped_file, FileSpec::Style::native);
 }
 
+/// Return the DW_AT_(GNU_)dwo_name.
+static const char *GetDWOName(DWARFCompileUnit &dwarf_cu,
+                              const DWARFDebugInfoEntry &cu_die) {
+  const char *dwo_name =
+      cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+  if (!dwo_name)
+    dwo_name =
+        cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_dwo_name, nullptr);
+  return dwo_name;
+}
+
 lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
   CompUnitSP cu_sp;
   CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData();
@@ -701,25 +712,66 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
     } else {
       ModuleSP module_sp(m_objfile_sp->GetModule());
       if (module_sp) {
-        const DWARFBaseDIE cu_die =
-            dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
-        if (cu_die) {
-          FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
-          MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);
-
-          LanguageType cu_language = SymbolFileDWARF::LanguageTypeFromDWARF(
-              cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
-
-          bool is_optimized = dwarf_cu.GetNonSkeletonUnit().GetIsOptimized();
+        auto initialize_cu = [&](const FileSpec &file_spec,
+                                 LanguageType cu_language) {
           BuildCuTranslationTable();
           cu_sp = std::make_shared<CompileUnit>(
-              module_sp, &dwarf_cu, cu_file_spec,
+              module_sp, &dwarf_cu, file_spec,
               *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language,
-              is_optimized ? eLazyBoolYes : eLazyBoolNo);
+              eLazyBoolCalculate);
 
           dwarf_cu.SetUserData(cu_sp.get());
 
           SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp);
+        };
+
+        auto lazy_initialize_cu = [&]() {
+          // If the version is < 5, we can't do lazy initialization.
+          if (dwarf_cu.GetVersion() < 5)
+            return false;
+
+          // If there is no DWO, there is no reason to initialize
+          // lazily; we will do eager initialization in that case.
+          if (GetDebugMapSymfile())
+            return false;
+          const DWARFBaseDIE cu_die = dwarf_cu.GetUnitDIEOnly();
+          if (!cu_die)
+            return false;
+          if (!GetDWOName(dwarf_cu, *cu_die.GetDIE()))
+            return false;
+
+          // With DWARFv5 we can assume that the first support
+          // file is also the name of the compile unit. This
+          // allows us to avoid loading the non-skeleton unit,
+          // which may be in a separate DWO file.
+          FileSpecList support_files;
+          if (!ParseSupportFiles(dwarf_cu, module_sp, support_files))
+            return false;
+          if (support_files.GetSize() == 0)
+            return false;
+
+          initialize_cu(support_files.GetFileSpecAtIndex(0),
+                        eLanguageTypeUnknown);
+          cu_sp->SetSupportFiles(std::move(support_files));
+          return true;
+        };
+
+        if (!lazy_initialize_cu()) {
+          // Eagerly initialize compile unit
+          const DWARFBaseDIE cu_die =
+              dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
+          if (cu_die) {
+            LanguageType cu_language = SymbolFileDWARF::LanguageTypeFromDWARF(
+                dwarf_cu.GetDWARFLanguageType());
+
+            FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
+
+            // Path needs to be remapped in this case. In the support files
+            // case ParseSupportFiles takes care of the remapping.
+            MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);
+
+            initialize_cu(cu_file_spec, cu_language);
+          }
         }
       }
     }
@@ -807,7 +859,7 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
   if (dwarf_cu)
-    return GetLanguage(*dwarf_cu);
+    return GetLanguage(dwarf_cu->GetNonSkeletonUnit());
   else
     return eLanguageTypeUnknown;
 }
@@ -898,18 +950,29 @@ bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
   if (!dwarf_cu)
     return false;
 
-  dw_offset_t offset = dwarf_cu->GetLineTableOffset();
+  if (!ParseSupportFiles(*dwarf_cu, comp_unit.GetModule(), support_files))
+    return false;
+
+  comp_unit.SetSupportFiles(support_files);
+  return true;
+}
+
+bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu,
+                                        const ModuleSP &module,
+                                        FileSpecList &support_files) {
+
+  dw_offset_t offset = dwarf_cu.GetLineTableOffset();
   if (offset == DW_INVALID_OFFSET)
     return false;
 
   llvm::DWARFDebugLine::Prologue prologue;
   if (!ParseLLVMLineTablePrologue(m_context, prologue, offset,
-                                  dwarf_cu->GetOffset()))
+                                  dwarf_cu.GetOffset()))
     return false;
 
-  comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue(
-      comp_unit.GetModule(), prologue, dwarf_cu->GetPathStyle(),
-      dwarf_cu->GetCompilationDirectory().GetCString()));
+  support_files = ParseSupportFilesFromPrologue(
+      module, prologue, dwarf_cu.GetPathStyle(),
+      dwarf_cu.GetCompilationDirectory().GetCString());
 
   return true;
 }
@@ -965,7 +1028,7 @@ bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) {
   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
   DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
   if (dwarf_cu)
-    return dwarf_cu->GetIsOptimized();
+    return dwarf_cu->GetNonSkeletonUnit().GetIsOptimized();
   return false;
 }
 
@@ -1585,17 +1648,6 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
   return DebugInfo().GetDIE(die_ref);
 }
 
-/// Return the DW_AT_(GNU_)dwo_name.
-static const char *GetDWOName(DWARFCompileUnit &dwarf_cu,
-                              const DWARFDebugInfoEntry &cu_die) {
-  const char *dwo_name =
-      cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
-  if (!dwo_name)
-    dwo_name =
-        cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_dwo_name, nullptr);
-  return dwo_name;
-}
-
 /// Return the DW_AT_(GNU_)dwo_id.
 /// FIXME: Technically 0 is a valid hash.
 static uint64_t GetDWOId(DWARFCompileUnit &dwarf_cu,

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index d9feeef549ed..e7cc33c9d809 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -368,6 +368,9 @@ class SymbolFileDWARF : public lldb_private::SymbolFile,
   lldb::TypeSP ParseType(const lldb_private::SymbolContext &sc,
                          const DWARFDIE &die, bool *type_is_new);
 
+  bool ParseSupportFiles(DWARFUnit &dwarf_cu, const lldb::ModuleSP &module,
+                         lldb_private::FileSpecList &support_files);
+
   lldb_private::Type *ResolveTypeUID(const DWARFDIE &die,
                                      bool assert_not_being_parsed);
 

diff  --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index 588ed4976d65..1b258516fac8 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -52,7 +52,7 @@ void CompileUnit::DumpSymbolContext(Stream *s) {
 
 void CompileUnit::GetDescription(Stream *s,
                                  lldb::DescriptionLevel level) const {
-  const char *language = Language::GetNameForLanguageType(m_language);
+  const char *language = GetCachedLanguage();
   *s << "id = " << (const UserID &)*this << ", file = \""
      << this->GetPrimaryFile() << "\", language = \"" << language << '"';
 }
@@ -97,12 +97,18 @@ lldb::FunctionSP CompileUnit::FindFunction(
   return {};
 }
 
+const char *CompileUnit::GetCachedLanguage() const {
+  if (m_flags.IsClear(flagsParsedLanguage))
+    return "<not loaded>";
+  return Language::GetNameForLanguageType(m_language);
+}
+
 // Dump the current contents of this object. No functions that cause on demand
 // parsing of functions, globals, statics are called, so this is a good
 // function to call to get an idea of the current contents of the CompileUnit
 // object.
 void CompileUnit::Dump(Stream *s, bool show_context) const {
-  const char *language = Language::GetNameForLanguageType(m_language);
+  const char *language = GetCachedLanguage();
 
   s->Printf("%p: ", static_cast<const void *>(this));
   s->Indent();

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/dwarf5-lazy-dwo.c b/lldb/test/Shell/SymbolFile/DWARF/dwarf5-lazy-dwo.c
new file mode 100644
index 000000000000..5aafbeb60b41
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/dwarf5-lazy-dwo.c
@@ -0,0 +1,30 @@
+// Test we load dwo information lazily.
+
+// RUN: %clang_host %s -fno-standalone-debug -g \
+// RUN:   -gdwarf-5 -gpubnames -gsplit-dwarf -c -o %t1.o -DONE
+// RUN: %clang_host %s -fno-standalone-debug -g \
+// RUN:   -gdwarf-5 -gpubnames -gsplit-dwarf -c -o %t2.o -DTWO
+// RUN: %clang_host %t1.o %t2.o -o %t
+// RUN: %lldb %t -o "log enable ll""db object" -o "settings set stop-line-count-before 0" \
+// RUN:   -o "b main" -o "run" -o "image lookup -n main -v" -b | FileCheck %s
+
+// CHECK-NOT: 2.dwo,
+// CHECK: (lldb) b main
+// CHECK-NOT: 2.dwo,
+// CHECK: 1.dwo,
+// CHECK-NOT: 2.dwo,
+// CHECK: (lldb) run
+// CHECK-NOT: 2.dwo,
+// CHECK: stop reason = breakpoint
+// CHECK-NOT: 2.dwo,
+// CHECK: (lldb) image lookup
+// CHECK-NOT: 2.dwo,
+// CHECK: CompileUnit: id = {0x00000000}, file =
+// CHECK-SAME: language = "c99"
+// CHECK-NOT: 2.dwo,
+
+#ifdef ONE
+int main() { return 0; }
+#else
+int x;
+#endif

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg b/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg
index 84376e61665b..cd335969a66e 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg
+++ b/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg
@@ -1 +1 @@
-config.suffixes = ['.cpp', '.m', '.mm', '.s', '.test', '.ll']
+config.suffixes = ['.cpp', '.m', '.mm', '.s', '.test', '.ll', '.c']

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/split-optimized.c b/lldb/test/Shell/SymbolFile/DWARF/split-optimized.c
new file mode 100644
index 000000000000..a85b1eebeb3a
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/split-optimized.c
@@ -0,0 +1,22 @@
+// Test that optimized flag is properly included in DWARF.
+
+// ObjectFileELF::ApplyRelocations does not implement arm32.
+// XFAIL: target-arm && linux-gnu
+
+// RUN: %clang_host %s -fno-standalone-debug -glldb \
+// RUN:   -gdwarf-5 -gpubnames -gsplit-dwarf -O3 -c -o %t1.o
+
+// RUN: llvm-dwarfdump %t1.o | FileCheck %s --check-prefix DWARFDUMP_O
+// RUN: llvm-dwarfdump %t1.dwo | FileCheck %s --check-prefix DWARFDUMP_DWO
+// RUN: %lldb -b -o 'script lldb.SBDebugger.Create().CreateTarget("%t1.o").FindFunctions("main",lldb.eFunctionNameTypeAuto).GetContextAtIndex(0).GetFunction().GetIsOptimized()' | FileCheck %s
+
+// DWARFDUMP_O-NOT: DW_AT_APPLE_optimized
+//
+// DWARFDUMP_DWO: DW_TAG_compile_unit
+// DWARFDUMP_DWO-NOT: DW_TAG_
+// DWARFDUMP_DWO: DW_AT_APPLE_optimized	(true)
+
+// CHECK: (lldb) script lldb.SBDebugger.Create()
+// CHECK-NEXT: True
+
+int main(void) { return 0; }

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s b/lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
index 3ae9673684d5..cf23a2a3c585 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
@@ -10,40 +10,40 @@
 # CHECK: (INT3) A = 3
 
 # CHECK-LABEL: image lookup -v -n F1
-# CHECK: CompileUnit: id = {0x00000001}, file = "1.c", language = "unknown"
+# CHECK: CompileUnit: id = {0x00000001}, file = "1.c", language = "<not loaded>"
 # CHECK: Function: {{.*}}, name = "F1", range = [0x0000000000000001-0x0000000000000002)
 # CHECK: Variable: {{.*}}, name = "x", type = "int", location = DW_OP_reg1 RDX
 
 # SYMBOLS:      Compile units:
-# SYMBOLS-NEXT: CompileUnit{0x00000000}, language = "unknown", file = '0.c'
+# SYMBOLS-NEXT: CompileUnit{0x00000000}, language = "<not loaded>", file = '0.c'
 # SYMBOLS-NEXT:   Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x0
 # SYMBOLS-NEXT:   Function{{.*}}, demangled = F0
 # SYMBOLS-NEXT:   Block{{.*}}, ranges = [0x00000000-0x00000001)
 # SYMBOLS-NEXT:     Variable{{.*}}, name = "x", {{.*}}, location = 
 # SYMBOLS-NEXT:       DW_LLE_startx_length   (0x0000000000000001, 0x0000000000000001): DW_OP_reg0 RAX
 # SYMBOLS-EMPTY:
-# SYMBOLS-NEXT: CompileUnit{0x00000001}, language = "unknown", file = '1.c'
+# SYMBOLS-NEXT: CompileUnit{0x00000001}, language = "<not loaded>", file = '1.c'
 # SYMBOLS-NEXT:   Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x2
 # SYMBOLS-NEXT:   Function{{.*}}, demangled = F1
 # SYMBOLS-NEXT:   Block{{.*}}, ranges = [0x00000001-0x00000002)
 # SYMBOLS-NEXT:     Variable{{.*}}, name = "x", {{.*}}, location = 
 # SYMBOLS-NEXT:       DW_LLE_startx_length   (0x0000000000000003, 0x0000000000000001): DW_OP_reg1 RDX
 # SYMBOLS-EMPTY:
-# SYMBOLS-NEXT: CompileUnit{0x00000002}, language = "unknown", file = '2.c'
+# SYMBOLS-NEXT: CompileUnit{0x00000002}, language = "<not loaded>", file = '2.c'
 # SYMBOLS-NEXT:   Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x4
 # SYMBOLS-NEXT:   Function{{.*}}, demangled = F2
 # SYMBOLS-NEXT:   Block{{.*}}, ranges = [0x00000002-0x00000003)
 # SYMBOLS-NEXT:     Variable{{.*}}, name = "x", {{.*}}, location = 
 # SYMBOLS-NEXT:       DW_LLE_startx_length   (0x0000000000000005, 0x0000000000000001): DW_OP_reg2 RCX
 # SYMBOLS-EMPTY:
-# SYMBOLS-NEXT: CompileUnit{0x00000003}, language = "unknown", file = '3.c'
+# SYMBOLS-NEXT: CompileUnit{0x00000003}, language = "<not loaded>", file = '3.c'
 # SYMBOLS-NEXT:   Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x6
 # SYMBOLS-NEXT:   Function{{.*}}, demangled = F3
 # SYMBOLS-NEXT:   Block{{.*}}, ranges = [0x00000003-0x00000004)
 # SYMBOLS-NEXT:     Variable{{.*}}, name = "x", {{.*}}, location = 
 # SYMBOLS-NEXT:       DW_LLE_startx_length   (0x0000000000000007, 0x0000000000000001): DW_OP_reg3 RBX
 # SYMBOLS-EMPTY:
-# SYMBOLS-NEXT: CompileUnit{0x00000004}, language = "unknown", file = ''
+# SYMBOLS-NEXT: CompileUnit{0x00000004}, language = "<not loaded>", file = ''
 # SYMBOLS-EMPTY:
 
         .section        .debug_abbrev,"", at progbits


        


More information about the lldb-commits mailing list