diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 1391 |
1 files changed, 691 insertions, 700 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index d45a8b56efe4..9f64e5255fd5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1,4 +1,4 @@ -//===-- SymbolFileDWARF.cpp ------------------------------------*- C++ -*-===// +//===-- SymbolFileDWARF.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -34,9 +34,9 @@ #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueProperties.h" +#include "Plugins/ExpressionParser/Clang/ClangUtil.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Symbol/Block.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" @@ -70,7 +70,6 @@ #include "ManualDWARFIndex.h" #include "SymbolFileDWARFDebugMap.h" #include "SymbolFileDWARFDwo.h" -#include "SymbolFileDWARFDwp.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Support/FileSystem.h" @@ -94,6 +93,8 @@ using namespace lldb; using namespace lldb_private; +LLDB_PLUGIN_DEFINE(SymbolFileDWARF) + char SymbolFileDWARF::ID; // static inline bool @@ -135,14 +136,6 @@ public: m_collection_sp->Initialize(g_symbolfiledwarf_properties); } - FileSpecList GetSymLinkPaths() { - const OptionValueFileSpecList *option_value = - m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList( - nullptr, true, ePropertySymLinkPaths); - assert(option_value); - return option_value->GetCurrentValue(); - } - bool IgnoreFileIndexes() const { return m_collection_sp->GetPropertyAtIndexAsBoolean( nullptr, ePropertyIgnoreIndexes, false); @@ -169,18 +162,46 @@ ParseLLVMLineTable(lldb_private::DWARFContext &context, llvm::Expected<const llvm::DWARFDebugLine::LineTable *> line_table = line.getOrParseLineTable( data, line_offset, ctx, nullptr, [&](llvm::Error e) { - LLDB_LOG_ERROR(log, std::move(e), - "SymbolFileDWARF::ParseLineTable failed to parse"); + LLDB_LOG_ERROR( + log, std::move(e), + "SymbolFileDWARF::ParseLineTable failed to parse: {0}"); }); if (!line_table) { LLDB_LOG_ERROR(log, line_table.takeError(), - "SymbolFileDWARF::ParseLineTable failed to parse"); + "SymbolFileDWARF::ParseLineTable failed to parse: {0}"); return nullptr; } return *line_table; } +static bool ParseLLVMLineTablePrologue(lldb_private::DWARFContext &context, + llvm::DWARFDebugLine::Prologue &prologue, + dw_offset_t line_offset, + dw_offset_t unit_offset) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + bool success = true; + llvm::DWARFDataExtractor data = context.getOrLoadLineData().GetAsLLVM(); + llvm::DWARFContext &ctx = context.GetAsLLVM(); + uint64_t offset = line_offset; + llvm::Error error = prologue.parse( + data, &offset, + [&](llvm::Error e) { + success = false; + LLDB_LOG_ERROR(log, std::move(e), + "SymbolFileDWARF::ParseSupportFiles failed to parse " + "line table prologue: {0}"); + }, + ctx, nullptr); + if (error) { + LLDB_LOG_ERROR(log, std::move(error), + "SymbolFileDWARF::ParseSupportFiles failed to parse line " + "table prologue: {0}"); + return false; + } + return success; +} + static llvm::Optional<std::string> GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx, llvm::StringRef compile_dir, FileSpec::Style style) { @@ -192,7 +213,7 @@ GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx, // Otherwise ask for a relative path. std::string rel_path; - auto relative = llvm::DILineInfoSpecifier::FileLineInfoKind::Default; + auto relative = llvm::DILineInfoSpecifier::FileLineInfoKind::RawValue; if (!prologue.getFileNameByIndex(idx, compile_dir, relative, rel_path, style)) return {}; return std::move(rel_path); @@ -227,15 +248,12 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, return support_files; } -FileSpecList SymbolFileDWARF::GetSymlinkPaths() { - return GetGlobalPluginProperties()->GetSymLinkPaths(); -} - void SymbolFileDWARF::Initialize() { LogChannelDWARF::Initialize(); PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, DebuggerInitialize); + SymbolFileDWARFDebugMap::Initialize(); } void SymbolFileDWARF::DebuggerInitialize(Debugger &debugger) { @@ -250,6 +268,7 @@ void SymbolFileDWARF::DebuggerInitialize(Debugger &debugger) { } void SymbolFileDWARF::Terminate() { + SymbolFileDWARFDebugMap::Terminate(); PluginManager::UnregisterPlugin(CreateInstance); LogChannelDWARF::Terminate(); } @@ -333,10 +352,8 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, if (add_type) { const bool assert_not_being_parsed = true; Type *type = ResolveTypeUID(die, assert_not_being_parsed); - if (type) { - if (type_set.find(type) == type_set.end()) - type_set.insert(type); - } + if (type) + type_set.insert(type); } } @@ -366,15 +383,12 @@ void SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, GetTypes(dwarf_cu->DIE(), dwarf_cu->GetOffset(), dwarf_cu->GetNextUnitOffset(), type_mask, type_set); } else { - DWARFDebugInfo *info = DebugInfo(); - if (info) { - const size_t num_cus = info->GetNumUnits(); - for (size_t cu_idx = 0; cu_idx < num_cus; ++cu_idx) { - dwarf_cu = info->GetUnitAtIndex(cu_idx); - if (dwarf_cu) { - GetTypes(dwarf_cu->DIE(), 0, UINT32_MAX, type_mask, type_set); - } - } + DWARFDebugInfo &info = DebugInfo(); + const size_t num_cus = info.GetNumUnits(); + for (size_t cu_idx = 0; cu_idx < num_cus; ++cu_idx) { + dwarf_cu = info.GetUnitAtIndex(cu_idx); + if (dwarf_cu) + GetTypes(dwarf_cu->DIE(), 0, UINT32_MAX, type_mask, type_set); } } @@ -418,9 +432,8 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFileSP objfile_sp, // contain the .o file index/ID m_debug_map_module_wp(), m_debug_map_symfile(nullptr), m_context(m_objfile_sp->GetModule()->GetSectionList(), dwo_section_list), - m_data_debug_loc(), m_abbr(), m_info(), m_fetched_external_modules(false), - m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), - m_unique_ast_type_map() {} + m_fetched_external_modules(false), + m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {} SymbolFileDWARF::~SymbolFileDWARF() {} @@ -471,9 +484,9 @@ void SymbolFileDWARF::InitializeObject() { LoadSectionData(eSectionTypeDWARFDebugNames, debug_names); if (debug_names.GetByteSize() > 0) { llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or = - DebugNamesDWARFIndex::Create( - *GetObjectFile()->GetModule(), debug_names, - m_context.getOrLoadStrData(), DebugInfo()); + DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(), + debug_names, + m_context.getOrLoadStrData(), *this); if (index_or) { m_index = std::move(*index_or); return; @@ -483,8 +496,8 @@ void SymbolFileDWARF::InitializeObject() { } } - m_index = std::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), - DebugInfo()); + m_index = + std::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(), *this); } bool SymbolFileDWARF::SupportedVersion(uint16_t version) { @@ -573,15 +586,6 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { return abilities; } -const DWARFDataExtractor & -SymbolFileDWARF::GetCachedSectionData(lldb::SectionType sect_type, - DWARFDataSegment &data_segment) { - llvm::call_once(data_segment.m_flag, [this, sect_type, &data_segment] { - this->LoadSectionData(sect_type, std::ref(data_segment.m_data)); - }); - return data_segment.m_data; -} - void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type, DWARFDataExtractor &data) { ModuleSP module_sp(m_objfile_sp->GetModule()); @@ -618,23 +622,14 @@ DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { return m_abbr.get(); } -const DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() const { - return m_abbr.get(); -} - -DWARFDebugInfo *SymbolFileDWARF::DebugInfo() { - if (m_info == nullptr) { +DWARFDebugInfo &SymbolFileDWARF::DebugInfo() { + llvm::call_once(m_info_once_flag, [&] { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast<void *>(this)); - if (m_context.getOrLoadDebugInfoData().GetByteSize() > 0) - m_info = std::make_unique<DWARFDebugInfo>(*this, m_context); - } - return m_info.get(); -} - -const DWARFDebugInfo *SymbolFileDWARF::DebugInfo() const { - return m_info.get(); + m_info = std::make_unique<DWARFDebugInfo>(*this, m_context); + }); + return *m_info; } DWARFUnit * @@ -642,15 +637,11 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { if (!comp_unit) return nullptr; - DWARFDebugInfo *info = DebugInfo(); - if (info) { - // The compile unit ID is the index of the DWARF unit. - DWARFUnit *dwarf_cu = info->GetUnitAtIndex(comp_unit->GetID()); - if (dwarf_cu && dwarf_cu->GetUserData() == nullptr) - dwarf_cu->SetUserData(comp_unit); - return dwarf_cu; - } - return nullptr; + // The compile unit ID is the index of the DWARF unit. + DWARFUnit *dwarf_cu = DebugInfo().GetUnitAtIndex(comp_unit->GetID()); + if (dwarf_cu && dwarf_cu->GetUserData() == nullptr) + dwarf_cu->SetUserData(comp_unit); + return dwarf_cu; } DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() { @@ -660,7 +651,7 @@ DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() { static_cast<void *>(this)); if (m_context.getOrLoadRangesData().GetByteSize() > 0) - m_ranges.reset(new DWARFDebugRanges()); + m_ranges = std::make_unique<DWARFDebugRanges>(); if (m_ranges) m_ranges->Extract(m_context); @@ -668,6 +659,22 @@ DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() { return m_ranges.get(); } +/// Make an absolute path out of \p file_spec and remap it using the +/// module's source remapping dictionary. +static void MakeAbsoluteAndRemap(FileSpec &file_spec, DWARFUnit &dwarf_cu, + const ModuleSP &module_sp) { + if (!file_spec) + return; + // If we have a full path to the compile unit, we don't need to + // resolve the file. This can be expensive e.g. when the source + // files are NFS mounted. + file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory()); + + std::string remapped_file; + if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file)) + file_spec.SetFile(remapped_file, FileSpec::Style::native); +} + lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { CompUnitSP cu_sp; CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData(); @@ -675,9 +682,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { // We already parsed this compile unit, had out a shared pointer to it cu_sp = comp_unit->shared_from_this(); } else { - if (&dwarf_cu.GetSymbolFileDWARF() != this) { - return dwarf_cu.GetSymbolFileDWARF().ParseCompileUnit(dwarf_cu); - } else if (dwarf_cu.GetOffset() == 0 && GetDebugMapSymfile()) { + if (dwarf_cu.GetOffset() == 0 && GetDebugMapSymfile()) { // Let the debug map create the compile unit cu_sp = m_debug_map_symfile->GetCompileUnit(this); dwarf_cu.SetUserData(cu_sp.get()); @@ -688,19 +693,9 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly(); if (cu_die) { FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle()); - if (cu_file_spec) { - // If we have a full path to the compile unit, we don't need to - // resolve the file. This can be expensive e.g. when the source - // files are NFS mounted. - cu_file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory()); - - std::string remapped_file; - if (module_sp->RemapSourceFile(cu_file_spec.GetPath(), - remapped_file)) - cu_file_spec.SetFile(remapped_file, FileSpec::Style::native); - } + MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp); - LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF( + LanguageType cu_language = SymbolFileDWARF::LanguageTypeFromDWARF( cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0)); bool is_optimized = dwarf_cu.GetNonSkeletonUnit().GetIsOptimized(); @@ -724,16 +719,13 @@ void SymbolFileDWARF::BuildCuTranslationTable() { if (!m_lldb_cu_to_dwarf_unit.empty()) return; - DWARFDebugInfo *info = DebugInfo(); - if (!info) - return; - - if (!info->ContainsTypeUnits()) { + DWARFDebugInfo &info = DebugInfo(); + if (!info.ContainsTypeUnits()) { // We can use a 1-to-1 mapping. No need to build a translation table. return; } - for (uint32_t i = 0, num = info->GetNumUnits(); i < num; ++i) { - if (auto *cu = llvm::dyn_cast<DWARFCompileUnit>(info->GetUnitAtIndex(i))) { + for (uint32_t i = 0, num = info.GetNumUnits(); i < num; ++i) { + if (auto *cu = llvm::dyn_cast<DWARFCompileUnit>(info.GetUnitAtIndex(i))) { cu->SetID(m_lldb_cu_to_dwarf_unit.size()); m_lldb_cu_to_dwarf_unit.push_back(i); } @@ -750,23 +742,16 @@ llvm::Optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) { } uint32_t SymbolFileDWARF::CalculateNumCompileUnits() { - DWARFDebugInfo *info = DebugInfo(); - if (!info) - return 0; BuildCuTranslationTable(); - return m_lldb_cu_to_dwarf_unit.empty() ? info->GetNumUnits() + return m_lldb_cu_to_dwarf_unit.empty() ? DebugInfo().GetNumUnits() : m_lldb_cu_to_dwarf_unit.size(); } CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { ASSERT_MODULE_LOCK(this); - DWARFDebugInfo *info = DebugInfo(); - if (!info) - return {}; - if (llvm::Optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) { if (auto *dwarf_cu = llvm::cast_or_null<DWARFCompileUnit>( - info->GetUnitAtIndex(*dwarf_idx))) + DebugInfo().GetUnitAtIndex(*dwarf_idx))) return ParseCompileUnit(*dwarf_cu); } return {}; @@ -778,8 +763,7 @@ Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, if (!die.IsValid()) return nullptr; - auto type_system_or_err = - GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); + auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU())); if (auto err = type_system_or_err.takeError()) { LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), std::move(err), "Unable to parse function"); @@ -792,6 +776,13 @@ Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die); } +lldb::addr_t SymbolFileDWARF::FixupAddress(lldb::addr_t file_addr) { + SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); + if (debug_map_symfile) + return debug_map_symfile->LinkOSOFileAddress(this, file_addr); + return file_addr; +} + bool SymbolFileDWARF::FixupAddress(Address &addr) { SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); if (debug_map_symfile) { @@ -804,11 +795,39 @@ 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 dwarf_cu->GetLanguageType(); + return GetLanguage(*dwarf_cu); else return eLanguageTypeUnknown; } +XcodeSDK SymbolFileDWARF::ParseXcodeSDK(CompileUnit &comp_unit) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); + if (!dwarf_cu) + return {}; + const DWARFBaseDIE cu_die = dwarf_cu->GetNonSkeletonUnit().GetUnitDIEOnly(); + if (!cu_die) + return {}; + const char *sdk = cu_die.GetAttributeValueAsString(DW_AT_APPLE_sdk, nullptr); + if (!sdk) + return {}; + const char *sysroot = + cu_die.GetAttributeValueAsString(DW_AT_LLVM_sysroot, ""); + // Register the sysroot path remapping with the module belonging to + // the CU as well as the one belonging to the symbol file. The two + // would be different if this is an OSO object and module is the + // corresponding debug map, in which case both should be updated. + ModuleSP module_sp = comp_unit.GetModule(); + if (module_sp) + module_sp->RegisterXcodeSDK(sdk, sysroot); + + ModuleSP local_module_sp = m_objfile_sp->GetModule(); + if (local_module_sp && local_module_sp != module_sp) + local_module_sp->RegisterXcodeSDK(sdk, sysroot); + + return {sdk}; +} + size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::ParseFunctions"); @@ -863,8 +882,24 @@ bool SymbolFileDWARF::ForEachExternalModule( bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { - if (!comp_unit.GetLineTable()) - ParseLineTable(comp_unit); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); + if (!dwarf_cu) + return false; + + 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())) + return false; + + comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue( + comp_unit.GetModule(), prologue, dwarf_cu->GetPathStyle(), + dwarf_cu->GetCompilationDirectory().GetCString())); + return true; } @@ -898,12 +933,15 @@ SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVM(); llvm::DWARFContext &ctx = m_context.GetAsLLVM(); llvm::DWARFDebugLine::Prologue prologue; - llvm::Error error = prologue.parse(data, &line_table_offset, ctx); - if (error) { + auto report = [](llvm::Error error) { Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); LLDB_LOG_ERROR(log, std::move(error), "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse " "the line table prologue"); + }; + llvm::Error error = prologue.parse(data, &line_table_offset, report, ctx); + if (error) { + report(std::move(error)); } else { list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), prologue, tu.GetPathStyle()); @@ -961,9 +999,12 @@ bool SymbolFileDWARF::ParseImportedModules( } std::reverse(module.path.begin(), module.path.end()); if (const char *include_path = module_die.GetAttributeValueAsString( - DW_AT_LLVM_include_path, nullptr)) - module.search_path = ConstString(include_path); - if (const char *sysroot = module_die.GetAttributeValueAsString( + DW_AT_LLVM_include_path, nullptr)) { + FileSpec include_spec(include_path, dwarf_cu->GetPathStyle()); + MakeAbsoluteAndRemap(include_spec, *dwarf_cu, m_objfile_sp->GetModule()); + module.search_path = ConstString(include_spec.GetPath()); + } + if (const char *sysroot = dwarf_cu->DIE().GetAttributeValueAsString( DW_AT_LLVM_sysroot, nullptr)) module.sysroot = ConstString(sysroot); imported_modules.push_back(module); @@ -981,18 +1022,13 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { if (!dwarf_cu) return false; - const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly(); - if (!dwarf_cu_die) - return false; - - const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned( - DW_AT_stmt_list, DW_INVALID_OFFSET); - if (cu_line_offset == DW_INVALID_OFFSET) + dw_offset_t offset = dwarf_cu->GetLineTableOffset(); + if (offset == DW_INVALID_OFFSET) return false; llvm::DWARFDebugLine line; - const llvm::DWARFDebugLine::LineTable *line_table = ParseLLVMLineTable( - m_context, line, cu_line_offset, dwarf_cu->GetOffset()); + const llvm::DWARFDebugLine::LineTable *line_table = + ParseLLVMLineTable(m_context, line, offset, dwarf_cu->GetOffset()); if (!line_table) return false; @@ -1000,20 +1036,23 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { // FIXME: Rather than parsing the whole line table and then copying it over // into LLDB, we should explore using a callback to populate the line table // while we parse to reduce memory usage. - std::unique_ptr<LineTable> line_table_up = - std::make_unique<LineTable>(&comp_unit); - LineSequence *sequence = line_table_up->CreateLineSequenceContainer(); + std::unique_ptr<LineSequence> sequence = + LineTable::CreateLineSequenceContainer(); + std::vector<std::unique_ptr<LineSequence>> sequences; for (auto &row : line_table->Rows) { - line_table_up->AppendLineEntryToSequence( - sequence, row.Address.Address, row.Line, row.Column, row.File, + LineTable::AppendLineEntryToSequence( + sequence.get(), row.Address.Address, row.Line, row.Column, row.File, row.IsStmt, row.BasicBlock, row.PrologueEnd, row.EpilogueBegin, row.EndSequence); if (row.EndSequence) { - line_table_up->InsertSequence(sequence); - sequence = line_table_up->CreateLineSequenceContainer(); + sequences.push_back(std::move(sequence)); + sequence = LineTable::CreateLineSequenceContainer(); } } + std::unique_ptr<LineTable> line_table_up = + std::make_unique<LineTable>(&comp_unit, std::move(sequences)); + if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) { // We have an object file that has a line table with addresses that are not // linked. We need to link the line table and convert the addresses that @@ -1024,10 +1063,6 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { comp_unit.SetLineTable(line_table_up.release()); } - comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue( - comp_unit.GetModule(), line_table->Prologue, dwarf_cu->GetPathStyle(), - dwarf_cu->GetCompilationDirectory().GetCString())); - return true; } @@ -1157,15 +1192,15 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( (name != nullptr || mangled_name != nullptr)) { std::unique_ptr<Declaration> decl_up; if (decl_file != 0 || decl_line != 0 || decl_column != 0) - decl_up.reset(new Declaration( + decl_up = std::make_unique<Declaration>( comp_unit.GetSupportFiles().GetFileSpecAtIndex(decl_file), - decl_line, decl_column)); + decl_line, decl_column); std::unique_ptr<Declaration> call_up; if (call_file != 0 || call_line != 0 || call_column != 0) - call_up.reset(new Declaration( + call_up = std::make_unique<Declaration>( comp_unit.GetSupportFiles().GetFileSpecAtIndex(call_file), - call_line, call_column)); + call_line, call_column); block->SetInlinedFunctionInfo(name, mangled_name, decl_up.get(), call_up.get()); @@ -1289,7 +1324,7 @@ CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) { // SymbolFileDWARF::GetDIE(). See comments inside the // SymbolFileDWARF::GetDIE() for details. if (DWARFDIE die = GetDIE(type_uid)) - return die.GetDecl(); + return GetDecl(die); return CompilerDecl(); } @@ -1302,7 +1337,7 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) { // SymbolFileDWARF::GetDIE(). See comments inside the // SymbolFileDWARF::GetDIE() for details. if (DWARFDIE die = GetDIE(type_uid)) - return die.GetDeclContext(); + return GetDeclContext(die); return CompilerDeclContext(); } @@ -1313,7 +1348,7 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { // SymbolFileDWARF::GetDIE(). See comments inside the // SymbolFileDWARF::GetDIE() for details. if (DWARFDIE die = GetDIE(type_uid)) - return die.GetContainingDeclContext(); + return GetContainingDeclContext(die); return CompilerDeclContext(); } @@ -1394,8 +1429,8 @@ bool SymbolFileDWARF::HasForwardDeclForClangType( } TypeSystem *type_system = compiler_type.GetTypeSystem(); - ClangASTContext *clang_type_system = - llvm::dyn_cast_or_null<ClangASTContext>(type_system); + TypeSystemClang *clang_type_system = + llvm::dyn_cast_or_null<TypeSystemClang>(type_system); if (!clang_type_system) return false; DWARFASTParserClang *ast_parser = @@ -1406,8 +1441,8 @@ bool SymbolFileDWARF::HasForwardDeclForClangType( bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - ClangASTContext *clang_type_system = - llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem()); + TypeSystemClang *clang_type_system = + llvm::dyn_cast_or_null<TypeSystemClang>(compiler_type.GetTypeSystem()); if (clang_type_system) { DWARFASTParserClang *ast_parser = static_cast<DWARFASTParserClang *>(clang_type_system->GetDWARFParser()); @@ -1444,8 +1479,7 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { dwarf_die.GetID(), dwarf_die.GetTagAsCString(), type->GetName().AsCString()); assert(compiler_type); - DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser(); - if (dwarf_ast) + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*dwarf_die.GetCU())) return dwarf_ast->CompleteTypeFromDWARF(dwarf_die, type, compiler_type); } return false; @@ -1473,20 +1507,25 @@ Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die, CompileUnit * SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit &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 (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(dwarf_cu).get(); } - return (CompileUnit *)dwarf_cu.GetUserData(); + return static_cast<CompileUnit *>(dwarf_cu.GetUserData()); } -size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name, - DIEArray &method_die_offsets) { - method_die_offsets.clear(); - m_index->GetObjCMethods(class_name, method_die_offsets); - return method_die_offsets.size(); +void SymbolFileDWARF::GetObjCMethods( + ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) { + m_index->GetObjCMethods(class_name, callback); } bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) { @@ -1522,17 +1561,15 @@ lldb::ModuleSP SymbolFileDWARF::GetExternalModule(ConstString name) { DWARFDIE SymbolFileDWARF::GetDIE(const DIERef &die_ref) { if (die_ref.dwo_num()) { - return DebugInfo() - ->GetUnitAtIndex(*die_ref.dwo_num()) - ->GetDwoSymbolFile() - ->GetDIE(die_ref); + SymbolFileDWARF *dwarf = *die_ref.dwo_num() == 0x3fffffff + ? m_dwp_symfile.get() + : this->DebugInfo() + .GetUnitAtIndex(*die_ref.dwo_num()) + ->GetDwoSymbolFile(); + return dwarf->DebugInfo().GetDIE(die_ref); } - DWARFDebugInfo *debug_info = DebugInfo(); - if (debug_info) - return debug_info->GetDIE(die_ref); - else - return DWARFDIE(); + return DebugInfo().GetDIE(die_ref); } /// Return the DW_AT_(GNU_)dwo_name. @@ -1569,7 +1606,7 @@ llvm::Optional<uint64_t> SymbolFileDWARF::GetDWOId() { return {}; } -std::unique_ptr<SymbolFileDWARFDwo> +std::shared_ptr<SymbolFileDWARFDwo> SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) { // If this is a Darwin-style debug map (non-.dSYM) symbol file, @@ -1589,14 +1626,8 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (!dwo_name) return nullptr; - SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile(); - if (dwp_symfile) { - uint64_t dwo_id = ::GetDWOId(*dwarf_cu, cu_die); - std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile = - dwp_symfile->GetSymbolFileForDwoId(*dwarf_cu, dwo_id); - if (dwo_symfile) - return dwo_symfile; - } + if (std::shared_ptr<SymbolFileDWARFDwo> dwp_sp = GetDwpSymbolFile()) + return dwp_sp; FileSpec dwo_file(dwo_name); FileSystem::Instance().Resolve(dwo_file); @@ -1624,20 +1655,21 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (dwo_obj_file == nullptr) return nullptr; - return std::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); + return std::make_shared<SymbolFileDWARFDwo>(*this, dwo_obj_file, + dwarf_cu->GetID()); } void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { if (m_fetched_external_modules) return; m_fetched_external_modules = true; - DWARFDebugInfo *debug_info = DebugInfo(); + DWARFDebugInfo &debug_info = DebugInfo(); // Follow DWO skeleton unit breadcrumbs. const uint32_t num_compile_units = GetNumCompileUnits(); for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { auto *dwarf_cu = - llvm::dyn_cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(cu_idx)); + llvm::dyn_cast<DWARFCompileUnit>(debug_info.GetUnitAtIndex(cu_idx)); if (!dwarf_cu) continue; @@ -1731,7 +1763,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { if (!m_global_aranges_up) { - m_global_aranges_up.reset(new GlobalVariableMap()); + m_global_aranges_up = std::make_unique<GlobalVariableMap>(); ModuleSP module_sp = GetObjectFile()->GetModule(); if (module_sp) { @@ -1773,6 +1805,32 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { return *m_global_aranges_up; } +void SymbolFileDWARF::ResolveFunctionAndBlock(lldb::addr_t file_vm_addr, + bool lookup_block, + SymbolContext &sc) { + assert(sc.comp_unit); + DWARFUnit &cu = GetDWARFCompileUnit(sc.comp_unit)->GetNonSkeletonUnit(); + DWARFDIE function_die = cu.LookupAddress(file_vm_addr); + DWARFDIE block_die; + if (function_die) { + sc.function = sc.comp_unit->FindFunctionByUID(function_die.GetID()).get(); + if (sc.function == nullptr) + sc.function = ParseFunction(*sc.comp_unit, function_die); + + if (sc.function && lookup_block) + block_die = function_die.LookupDeepestBlock(file_vm_addr); + } + + if (!sc.function || ! lookup_block) + return; + + Block &block = sc.function->GetBlock(true); + if (block_die) + sc.block = block.FindBlockByID(block_die.GetID()); + else + sc.block = block.FindBlockByID(function_die.GetID()); +} + uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { @@ -1791,123 +1849,99 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, eSymbolContextLineEntry | eSymbolContextVariable)) { lldb::addr_t file_vm_addr = so_addr.GetFileAddress(); - DWARFDebugInfo *debug_info = DebugInfo(); - if (debug_info) { - llvm::Expected<DWARFDebugAranges &> aranges = - debug_info->GetCompileUnitAranges(); - if (!aranges) { - Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); - LLDB_LOG_ERROR(log, aranges.takeError(), - "SymbolFileDWARF::ResolveSymbolContext failed to get cu " - "aranges. {0}"); - return 0; - } + DWARFDebugInfo &debug_info = DebugInfo(); + llvm::Expected<DWARFDebugAranges &> aranges = + debug_info.GetCompileUnitAranges(); + if (!aranges) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + LLDB_LOG_ERROR(log, aranges.takeError(), + "SymbolFileDWARF::ResolveSymbolContext failed to get cu " + "aranges. {0}"); + return 0; + } - const dw_offset_t cu_offset = aranges->FindAddress(file_vm_addr); - if (cu_offset == DW_INVALID_OFFSET) { - // Global variables are not in the compile unit address ranges. The - // only way to currently find global variables is to iterate over the - // .debug_pubnames or the __apple_names table and find all items in - // there that point to DW_TAG_variable DIEs and then find the address - // that matches. - if (resolve_scope & eSymbolContextVariable) { - GlobalVariableMap &map = GetGlobalAranges(); - const GlobalVariableMap::Entry *entry = - map.FindEntryThatContains(file_vm_addr); - if (entry && entry->data) { - Variable *variable = entry->data; - SymbolContextScope *scc = variable->GetSymbolContextScope(); - if (scc) { - scc->CalculateSymbolContext(&sc); - sc.variable = variable; - } - return sc.GetResolvedMask(); + const dw_offset_t cu_offset = aranges->FindAddress(file_vm_addr); + if (cu_offset == DW_INVALID_OFFSET) { + // Global variables are not in the compile unit address ranges. The only + // way to currently find global variables is to iterate over the + // .debug_pubnames or the __apple_names table and find all items in there + // that point to DW_TAG_variable DIEs and then find the address that + // matches. + if (resolve_scope & eSymbolContextVariable) { + GlobalVariableMap &map = GetGlobalAranges(); + const GlobalVariableMap::Entry *entry = + map.FindEntryThatContains(file_vm_addr); + if (entry && entry->data) { + Variable *variable = entry->data; + SymbolContextScope *scc = variable->GetSymbolContextScope(); + if (scc) { + scc->CalculateSymbolContext(&sc); + sc.variable = variable; } + return sc.GetResolvedMask(); } - } else { - uint32_t cu_idx = DW_INVALID_INDEX; - if (auto *dwarf_cu = llvm::dyn_cast_or_null<DWARFCompileUnit>( - debug_info->GetUnitAtOffset(DIERef::Section::DebugInfo, - cu_offset, &cu_idx))) { - sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); - if (sc.comp_unit) { - resolved |= eSymbolContextCompUnit; - - bool force_check_line_table = false; - if (resolve_scope & - (eSymbolContextFunction | eSymbolContextBlock)) { - DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr); - DWARFDIE block_die; - if (function_die) { - sc.function = - sc.comp_unit->FindFunctionByUID(function_die.GetID()).get(); - if (sc.function == nullptr) - sc.function = ParseFunction(*sc.comp_unit, function_die); - - if (sc.function && (resolve_scope & eSymbolContextBlock)) - block_die = function_die.LookupDeepestBlock(file_vm_addr); - } else { - // We might have had a compile unit that had discontiguous - // address ranges where the gaps are symbols that don't have - // any debug info. Discontiguous compile unit address ranges - // should only happen when there aren't other functions from - // other compile units in these gaps. This helps keep the size - // of the aranges down. - force_check_line_table = true; - } - - if (sc.function != nullptr) { - resolved |= eSymbolContextFunction; - - if (resolve_scope & eSymbolContextBlock) { - Block &block = sc.function->GetBlock(true); - - if (block_die) - sc.block = block.FindBlockByID(block_die.GetID()); - else - sc.block = block.FindBlockByID(function_die.GetID()); - if (sc.block) - resolved |= eSymbolContextBlock; - } - } + } + } else { + uint32_t cu_idx = DW_INVALID_INDEX; + if (auto *dwarf_cu = llvm::dyn_cast_or_null<DWARFCompileUnit>( + debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, cu_offset, + &cu_idx))) { + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); + if (sc.comp_unit) { + resolved |= eSymbolContextCompUnit; + + bool force_check_line_table = false; + if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) { + ResolveFunctionAndBlock(file_vm_addr, + resolve_scope & eSymbolContextBlock, sc); + if (sc.function) + resolved |= eSymbolContextFunction; + else { + // We might have had a compile unit that had discontiguous address + // ranges where the gaps are symbols that don't have any debug + // info. Discontiguous compile unit address ranges should only + // happen when there aren't other functions from other compile + // units in these gaps. This helps keep the size of the aranges + // down. + force_check_line_table = true; } + if (sc.block) + resolved |= eSymbolContextBlock; + } - if ((resolve_scope & eSymbolContextLineEntry) || - force_check_line_table) { - LineTable *line_table = sc.comp_unit->GetLineTable(); - if (line_table != nullptr) { - // And address that makes it into this function should be in - // terms of this debug file if there is no debug map, or it - // will be an address in the .o file which needs to be fixed up - // to be in terms of the debug map executable. Either way, - // calling FixupAddress() will work for us. - Address exe_so_addr(so_addr); - if (FixupAddress(exe_so_addr)) { - if (line_table->FindLineEntryByAddress(exe_so_addr, - sc.line_entry)) { - resolved |= eSymbolContextLineEntry; - } + if ((resolve_scope & eSymbolContextLineEntry) || + force_check_line_table) { + LineTable *line_table = sc.comp_unit->GetLineTable(); + if (line_table != nullptr) { + // And address that makes it into this function should be in terms + // of this debug file if there is no debug map, or it will be an + // address in the .o file which needs to be fixed up to be in + // terms of the debug map executable. Either way, calling + // FixupAddress() will work for us. + Address exe_so_addr(so_addr); + if (FixupAddress(exe_so_addr)) { + if (line_table->FindLineEntryByAddress(exe_so_addr, + sc.line_entry)) { + resolved |= eSymbolContextLineEntry; } } } + } - if (force_check_line_table && - !(resolved & eSymbolContextLineEntry)) { - // We might have had a compile unit that had discontiguous - // address ranges where the gaps are symbols that don't have any - // debug info. Discontiguous compile unit address ranges should - // only happen when there aren't other functions from other - // compile units in these gaps. This helps keep the size of the - // aranges down. - sc.comp_unit = nullptr; - resolved &= ~eSymbolContextCompUnit; - } - } else { - GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8x: compile unit %u failed to create a valid " - "lldb_private::CompileUnit class.", - cu_offset, cu_idx); + if (force_check_line_table && !(resolved & eSymbolContextLineEntry)) { + // We might have had a compile unit that had discontiguous address + // ranges where the gaps are symbols that don't have any debug info. + // Discontiguous compile unit address ranges should only happen when + // there aren't other functions from other compile units in these + // gaps. This helps keep the size of the aranges down. + sc.comp_unit = nullptr; + resolved &= ~eSymbolContextCompUnit; } + } else { + GetObjectFile()->GetModule()->ReportWarning( + "0x%8.8x: compile unit %u failed to create a valid " + "lldb_private::CompileUnit class.", + cu_offset, cu_idx); } } } @@ -1969,30 +2003,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress(); if (file_vm_addr != LLDB_INVALID_ADDRESS) { - DWARFDIE function_die = - GetDWARFCompileUnit(dc_cu)->LookupAddress(file_vm_addr); - DWARFDIE block_die; - if (function_die) { - sc.function = - sc.comp_unit->FindFunctionByUID(function_die.GetID()) - .get(); - if (sc.function == nullptr) - sc.function = - ParseFunction(*sc.comp_unit, function_die); - - if (sc.function && (resolve_scope & eSymbolContextBlock)) - block_die = - function_die.LookupDeepestBlock(file_vm_addr); - } - - if (sc.function != nullptr) { - Block &block = sc.function->GetBlock(true); - - if (block_die) - sc.block = block.FindBlockByID(block_die.GetID()); - else if (function_die) - sc.block = block.FindBlockByID(function_die.GetID()); - } + ResolveFunctionAndBlock( + file_vm_addr, resolve_scope & eSymbolContextBlock, sc); } } @@ -2035,15 +2047,15 @@ std::recursive_mutex &SymbolFileDWARF::GetModuleMutex() const { } bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( - const lldb_private::CompilerDeclContext *decl_ctx) { - if (decl_ctx == nullptr || !decl_ctx->IsValid()) { + const lldb_private::CompilerDeclContext &decl_ctx) { + if (!decl_ctx.IsValid()) { // Invalid namespace decl which means we aren't matching only things in // this symbol file, so return true to indicate it matches this symbol // file. return true; } - TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); + TypeSystem *decl_ctx_type_system = decl_ctx.GetTypeSystem(); auto type_system_or_err = GetTypeSystemForLanguage( decl_ctx_type_system->GetMinimumLanguage(nullptr)); if (auto err = type_system_or_err.takeError()) { @@ -2067,7 +2079,7 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( } void SymbolFileDWARF::FindGlobalVariables( - ConstString name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, VariableList &variables) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -2077,16 +2089,12 @@ void SymbolFileDWARF::FindGlobalVariables( log, "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", " "parent_decl_ctx=%p, max_matches=%u, variables)", - name.GetCString(), static_cast<const void *>(parent_decl_ctx), + name.GetCString(), static_cast<const void *>(&parent_decl_ctx), max_matches); if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return; - DWARFDebugInfo *info = DebugInfo(); - if (!info) - return; - // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); @@ -2098,69 +2106,46 @@ void SymbolFileDWARF::FindGlobalVariables( context, basename)) basename = name.GetStringRef(); - DIEArray die_offsets; - m_index->GetGlobalVariables(ConstString(basename), die_offsets); - const size_t num_die_matches = die_offsets.size(); - if (num_die_matches) { - SymbolContext sc; - sc.module_sp = m_objfile_sp->GetModule(); - assert(sc.module_sp); - - // Loop invariant: Variables up to this index have been checked for context - // matches. - uint32_t pruned_idx = original_size; + // Loop invariant: Variables up to this index have been checked for context + // matches. + uint32_t pruned_idx = original_size; - bool done = false; - for (size_t i = 0; i < num_die_matches && !done; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - - if (die) { - switch (die.Tag()) { - default: - case DW_TAG_subprogram: - case DW_TAG_inlined_subroutine: - case DW_TAG_try_block: - case DW_TAG_catch_block: - break; + SymbolContext sc; + m_index->GetGlobalVariables(ConstString(basename), [&](DWARFDIE die) { + if (!sc.module_sp) + sc.module_sp = m_objfile_sp->GetModule(); + assert(sc.module_sp); - case DW_TAG_variable: { - auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()); - if (!dwarf_cu) - continue; - sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); - - if (parent_decl_ctx) { - DWARFASTParser *dwarf_ast = die.GetDWARFParser(); - if (dwarf_ast) { - CompilerDeclContext actual_parent_decl_ctx = - dwarf_ast->GetDeclContextContainingUIDFromDWARF(die); - if (!actual_parent_decl_ctx || - actual_parent_decl_ctx != *parent_decl_ctx) - continue; - } - } + if (die.Tag() != DW_TAG_variable) + return true; - ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, - &variables); - while (pruned_idx < variables.GetSize()) { - VariableSP var_sp = variables.GetVariableAtIndex(pruned_idx); - if (name_is_mangled || - var_sp->GetName().GetStringRef().contains(name.GetStringRef())) - ++pruned_idx; - else - variables.RemoveVariableAtIndex(pruned_idx); - } + auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()); + if (!dwarf_cu) + return true; + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); - if (variables.GetSize() - original_size >= max_matches) - done = true; - } break; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); + if (parent_decl_ctx) { + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) { + CompilerDeclContext actual_parent_decl_ctx = + dwarf_ast->GetDeclContextContainingUIDFromDWARF(die); + if (!actual_parent_decl_ctx || + actual_parent_decl_ctx != parent_decl_ctx) + return true; } } - } + + ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables); + while (pruned_idx < variables.GetSize()) { + VariableSP var_sp = variables.GetVariableAtIndex(pruned_idx); + if (name_is_mangled || + var_sp->GetName().GetStringRef().contains(name.GetStringRef())) + ++pruned_idx; + else + variables.RemoveVariableAtIndex(pruned_idx); + } + + return variables.GetSize() - original_size < max_matches; + }); // Return the number of variable that were appended to the list const uint32_t num_matches = variables.GetSize() - original_size; @@ -2169,7 +2154,7 @@ void SymbolFileDWARF::FindGlobalVariables( log, "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", " "parent_decl_ctx=%p, max_matches=%u, variables) => %u", - name.GetCString(), static_cast<const void *>(parent_decl_ctx), + name.GetCString(), static_cast<const void *>(&parent_decl_ctx), max_matches, num_matches); } } @@ -2188,41 +2173,24 @@ void SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, regex.GetText().str().c_str(), max_matches); } - DWARFDebugInfo *info = DebugInfo(); - if (!info) - return; - // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); - DIEArray die_offsets; - m_index->GetGlobalVariables(regex, die_offsets); - SymbolContext sc; - sc.module_sp = m_objfile_sp->GetModule(); - assert(sc.module_sp); - - const size_t num_matches = die_offsets.size(); - if (num_matches) { - for (size_t i = 0; i < num_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); + m_index->GetGlobalVariables(regex, [&](DWARFDIE die) { + if (!sc.module_sp) + sc.module_sp = m_objfile_sp->GetModule(); + assert(sc.module_sp); - if (die) { - DWARFCompileUnit *dwarf_cu = - llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()); - if (!dwarf_cu) - continue; - sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); + DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()); + if (!dwarf_cu) + return true; + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); - ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables); + ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables); - if (variables.GetSize() - original_size >= max_matches) - break; - } else - m_index->ReportInvalidDIERef(die_ref, regex.GetText()); - } - } + return variables.GetSize() - original_size < max_matches; + }); } bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, @@ -2281,28 +2249,26 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, return false; } -bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx, +bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx, const DWARFDIE &die) { // If we have no parent decl context to match this DIE matches, and if the // parent decl context isn't valid, we aren't trying to look for any // particular decl context so any die matches. - if (decl_ctx == nullptr || !decl_ctx->IsValid()) + if (!decl_ctx.IsValid()) return true; if (die) { - DWARFASTParser *dwarf_ast = die.GetDWARFParser(); - if (dwarf_ast) { - CompilerDeclContext actual_decl_ctx = - dwarf_ast->GetDeclContextContainingUIDFromDWARF(die); - if (actual_decl_ctx) - return decl_ctx->IsContainedInLookup(actual_decl_ctx); + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) { + if (CompilerDeclContext actual_decl_ctx = + dwarf_ast->GetDeclContextContainingUIDFromDWARF(die)) + return decl_ctx.IsContainedInLookup(actual_decl_ctx); } } return false; } void SymbolFileDWARF::FindFunctions(ConstString name, - const CompilerDeclContext *parent_decl_ctx, + const CompilerDeclContext &parent_decl_ctx, FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list) { @@ -2337,17 +2303,13 @@ void SymbolFileDWARF::FindFunctions(ConstString name, const uint32_t original_size = sc_list.GetSize(); llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies; - DIEArray offsets; - CompilerDeclContext empty_decl_ctx; - if (!parent_decl_ctx) - parent_decl_ctx = &empty_decl_ctx; - - std::vector<DWARFDIE> dies; - m_index->GetFunctions(name, *this, *parent_decl_ctx, name_type_mask, dies); - for (const DWARFDIE &die : dies) { - if (resolved_dies.insert(die.GetDIE()).second) - ResolveFunction(die, include_inlines, sc_list); - } + + m_index->GetFunctions(name, *this, parent_decl_ctx, name_type_mask, + [&](DWARFDIE die) { + if (resolved_dies.insert(die.GetDIE()).second) + ResolveFunction(die, include_inlines, sc_list); + return true; + }); // Return the number of variable that were appended to the list const uint32_t num_matches = sc_list.GetSize() - original_size; @@ -2378,35 +2340,21 @@ void SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, regex.GetText().str().c_str()); } - DWARFDebugInfo *info = DebugInfo(); - if (!info) - return; - - DIEArray offsets; - m_index->GetFunctions(regex, offsets); - llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies; - for (DIERef ref : offsets) { - DWARFDIE die = info->GetDIE(ref); - if (!die) { - m_index->ReportInvalidDIERef(ref, regex.GetText()); - continue; - } + m_index->GetFunctions(regex, [&](DWARFDIE die) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); - } + return true; + }); } void SymbolFileDWARF::GetMangledNamesForFunction( const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names) { - DWARFDebugInfo *info = DebugInfo(); - uint32_t num_comp_units = 0; - if (info) - num_comp_units = info->GetNumUnits(); - + DWARFDebugInfo &info = DebugInfo(); + uint32_t num_comp_units = info.GetNumUnits(); for (uint32_t i = 0; i < num_comp_units; i++) { - DWARFUnit *cu = info->GetUnitAtIndex(i); + DWARFUnit *cu = info.GetUnitAtIndex(i); if (cu == nullptr) continue; @@ -2415,15 +2363,15 @@ void SymbolFileDWARF::GetMangledNamesForFunction( dwo->GetMangledNamesForFunction(scope_qualified_name, mangled_names); } - for (lldb::user_id_t uid : + for (DIERef die_ref : m_function_scope_qualified_name_map.lookup(scope_qualified_name)) { - DWARFDIE die = GetDIE(uid); + DWARFDIE die = GetDIE(die_ref); mangled_names.push_back(ConstString(die.GetMangledName())); } } void SymbolFileDWARF::FindTypes( - ConstString name, const CompilerDeclContext *parent_decl_ctx, + ConstString name, const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { @@ -2432,10 +2380,6 @@ void SymbolFileDWARF::FindTypes( if (!searched_symbol_files.insert(this).second) return; - DWARFDebugInfo *info = DebugInfo(); - if (!info) - return; - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { @@ -2444,8 +2388,8 @@ void SymbolFileDWARF::FindTypes( log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = " "%p (\"%s\"), max_matches=%u, type_list)", - name.GetCString(), static_cast<const void *>(parent_decl_ctx), - parent_decl_ctx->GetName().AsCString("<NULL>"), max_matches); + name.GetCString(), static_cast<const void *>(&parent_decl_ctx), + parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches); else GetObjectFile()->GetModule()->LogMessage( log, @@ -2457,38 +2401,28 @@ void SymbolFileDWARF::FindTypes( if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return; - DIEArray die_offsets; - m_index->GetTypes(name, die_offsets); - const size_t num_die_matches = die_offsets.size(); + m_index->GetTypes(name, [&](DWARFDIE die) { + if (!DIEInDeclContext(parent_decl_ctx, die)) + return true; // The containing decl contexts don't match - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - Type *matching_type = ResolveType(die, true, true); - if (matching_type) { - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - if (types.GetSize() >= max_matches) - break; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - } - } + Type *matching_type = ResolveType(die, true, true); + if (!matching_type) + return true; + + // We found a type pointer, now find the shared pointer form our type + // list + types.InsertUnique(matching_type->shared_from_this()); + return types.GetSize() < max_matches; + }); // Next search through the reachable Clang modules. This only applies for // DWARF objects compiled with -gmodules that haven't been processed by // dsymutil. - if (num_die_matches < max_matches) { + if (types.GetSize() < max_matches) { UpdateExternalModuleListIfNeeded(); for (const auto &pair : m_external_type_modules) - if (ModuleSP external_module_sp = pair.second) + if (ModuleSP external_module_sp = pair.second) if (SymbolFile *sym_file = external_module_sp->GetSymbolFile()) sym_file->FindTypes(name, parent_decl_ctx, max_matches, searched_symbol_files, types); @@ -2500,8 +2434,8 @@ void SymbolFileDWARF::FindTypes( log, "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx " "= %p (\"%s\"), max_matches=%u, type_list) => %u", - name.GetCString(), static_cast<const void *>(parent_decl_ctx), - parent_decl_ctx->GetName().AsCString("<NULL>"), max_matches, + name.GetCString(), static_cast<const void *>(&parent_decl_ctx), + parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches, types.GetSize()); } else { GetObjectFile()->GetModule()->LogMessage( @@ -2529,32 +2463,22 @@ void SymbolFileDWARF::FindTypes( if (!name) return; - DIEArray die_offsets; - m_index->GetTypes(name, die_offsets); - const size_t num_die_matches = die_offsets.size(); - - for (size_t i = 0; i < num_die_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - - if (!die) { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - continue; - } - if (!languages[die.GetCU()->GetLanguageType()]) - continue; + m_index->GetTypes(name, [&](DWARFDIE die) { + if (!languages[GetLanguage(*die.GetCU())]) + return true; llvm::SmallVector<CompilerContext, 4> die_context; die.GetDeclContext(die_context); if (!contextMatches(die_context, pattern)) - continue; + return true; if (Type *matching_type = ResolveType(die, true, true)) { // We found a type pointer, now find the shared pointer form our type // list. types.InsertUnique(matching_type->shared_from_this()); } - } + return true; + }); // Next search through the reachable Clang modules. This only applies for // DWARF objects compiled with -gmodules that haven't been processed by @@ -2569,7 +2493,7 @@ void SymbolFileDWARF::FindTypes( CompilerDeclContext SymbolFileDWARF::FindNamespace(ConstString name, - const CompilerDeclContext *parent_decl_ctx) { + const CompilerDeclContext &parent_decl_ctx) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -2584,32 +2508,18 @@ SymbolFileDWARF::FindNamespace(ConstString name, if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return namespace_decl_ctx; - DWARFDebugInfo *info = DebugInfo(); - if (info) { - DIEArray die_offsets; - m_index->GetNamespaces(name, die_offsets); - const size_t num_matches = die_offsets.size(); - if (num_matches) { - for (size_t i = 0; i < num_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - - if (die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - continue; // The containing decl contexts don't match - - DWARFASTParser *dwarf_ast = die.GetDWARFParser(); - if (dwarf_ast) { - namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF(die); - if (namespace_decl_ctx) - break; - } - } else { - m_index->ReportInvalidDIERef(die_ref, name.GetStringRef()); - } - } - } - } + m_index->GetNamespaces(name, [&](DWARFDIE die) { + if (!DIEInDeclContext(parent_decl_ctx, die)) + return true; // The containing decl contexts don't match + + DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU()); + if (!dwarf_ast) + return true; + + namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF(die); + return !namespace_decl_ctx.IsValid(); + }); + if (log && namespace_decl_ctx) { GetObjectFile()->GetModule()->LogMessage( log, @@ -2735,10 +2645,10 @@ bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu) { if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type()) m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; else { - DWARFDebugInfo *debug_info = DebugInfo(); + DWARFDebugInfo &debug_info = DebugInfo(); const uint32_t num_compile_units = GetNumCompileUnits(); for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { - DWARFUnit *dwarf_cu = debug_info->GetUnitAtIndex(cu_idx); + DWARFUnit *dwarf_cu = debug_info.GetUnitAtIndex(cu_idx); if (dwarf_cu != cu && dwarf_cu->Supports_DW_AT_APPLE_objc_complete_type()) { m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; @@ -2763,17 +2673,8 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( if (!type_name || (must_be_implementation && !GetObjCClassSymbol(type_name))) return type_sp; - DIEArray die_offsets; - m_index->GetCompleteObjCClass(type_name, must_be_implementation, die_offsets); - - const size_t num_matches = die_offsets.size(); - - if (num_matches) { - for (size_t i = 0; i < num_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE type_die = GetDIE(die_ref); - - if (type_die) { + m_index->GetCompleteObjCClass( + type_name, must_be_implementation, [&](DWARFDIE type_die) { bool try_resolving_type = false; // Don't try and resolve the DIE we are looking for with the DIE @@ -2788,35 +2689,32 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( break; } } + if (!try_resolving_type) + return true; - if (try_resolving_type) { - if (must_be_implementation && - type_die.Supports_DW_AT_APPLE_objc_complete_type()) - try_resolving_type = type_die.GetAttributeValueAsUnsigned( - DW_AT_APPLE_objc_complete_type, 0); - - if (try_resolving_type) { - Type *resolved_type = ResolveType(type_die, false, true); - if (resolved_type && resolved_type != DIE_IS_BEING_PARSED) { - DEBUG_PRINTF("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 - " (cu 0x%8.8" PRIx64 ")\n", - die.GetID(), - m_objfile_sp->GetFileSpec().GetFilename().AsCString( - "<Unknown>"), - type_die.GetID(), type_cu->GetID()); - - if (die) - GetDIEToType()[die.GetDIE()] = resolved_type; - type_sp = resolved_type->shared_from_this(); - break; - } - } - } - } else { - m_index->ReportInvalidDIERef(die_ref, type_name.GetStringRef()); - } - } - } + if (must_be_implementation && + type_die.Supports_DW_AT_APPLE_objc_complete_type()) + try_resolving_type = type_die.GetAttributeValueAsUnsigned( + DW_AT_APPLE_objc_complete_type, 0); + if (!try_resolving_type) + return true; + + Type *resolved_type = ResolveType(type_die, false, true); + if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED) + return true; + + DEBUG_PRINTF( + "resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 + " (cu 0x%8.8" PRIx64 ")\n", + die.GetID(), + m_objfile_sp->GetFileSpec().GetFilename().AsCString("<Unknown>"), + type_die.GetID(), type_cu->GetID()); + + if (die) + GetDIEToType()[die.GetDIE()] = resolved_type; + type_sp = resolved_type->shared_from_this(); + return false; + }); return type_sp; } @@ -2930,10 +2828,6 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( dwarf_decl_ctx.GetQualifiedName()); } - DIEArray die_offsets; - m_index->GetTypes(dwarf_decl_ctx, die_offsets); - const size_t num_matches = die_offsets.size(); - // Get the type system that we are looking to find a type for. We will // use this to ensure any matches we find are in a language that this // type system supports @@ -2950,91 +2844,85 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext( type_system = &type_system_or_err.get(); } } - if (num_matches) { - for (size_t i = 0; i < num_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE type_die = GetDIE(die_ref); - - if (type_die) { - // Make sure type_die's langauge matches the type system we are - // looking for. We don't want to find a "Foo" type from Java if we - // are looking for a "Foo" type for C, C++, ObjC, or ObjC++. - if (type_system && - !type_system->SupportsLanguage(type_die.GetLanguage())) - continue; - bool try_resolving_type = false; - - // Don't try and resolve the DIE we are looking for with the DIE - // itself! - const dw_tag_t type_tag = type_die.Tag(); - // Make sure the tags match - if (type_tag == tag) { - // The tags match, lets try resolving this type - try_resolving_type = true; - } else { - // The tags don't match, but we need to watch our for a forward - // declaration for a struct and ("struct foo") ends up being a - // class ("class foo { ... };") or vice versa. - switch (type_tag) { - case DW_TAG_class_type: - // We had a "class foo", see if we ended up with a "struct foo - // { ... };" - try_resolving_type = (tag == DW_TAG_structure_type); - break; - case DW_TAG_structure_type: - // We had a "struct foo", see if we ended up with a "class foo - // { ... };" - try_resolving_type = (tag == DW_TAG_class_type); - break; - default: - // Tags don't match, don't event try to resolve using this type - // whose name matches.... - break; - } - } - if (try_resolving_type) { - DWARFDeclContext type_dwarf_decl_ctx; - type_die.GetDWARFDeclContext(type_dwarf_decl_ctx); - - if (log) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') trying die=0x%8.8x (%s)", - DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), - dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), - type_dwarf_decl_ctx.GetQualifiedName()); - } + m_index->GetTypes(dwarf_decl_ctx, [&](DWARFDIE type_die) { + // Make sure type_die's langauge matches the type system we are + // looking for. We don't want to find a "Foo" type from Java if we + // are looking for a "Foo" type for C, C++, ObjC, or ObjC++. + if (type_system && + !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU()))) + return true; + bool try_resolving_type = false; - // Make sure the decl contexts match all the way up - if (dwarf_decl_ctx == type_dwarf_decl_ctx) { - Type *resolved_type = ResolveType(type_die, false); - if (resolved_type && resolved_type != DIE_IS_BEING_PARSED) { - type_sp = resolved_type->shared_from_this(); - break; - } - } - } else { - if (log) { - std::string qualified_name; - type_die.GetQualifiedName(qualified_name); - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::" - "FindDefinitionTypeForDWARFDeclContext(tag=%s, " - "qualified-name='%s') ignoring die=0x%8.8x (%s)", - DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), - dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), - qualified_name.c_str()); - } - } - } else { - m_index->ReportInvalidDIERef(die_ref, type_name.GetStringRef()); + // Don't try and resolve the DIE we are looking for with the DIE + // itself! + const dw_tag_t type_tag = type_die.Tag(); + // Make sure the tags match + if (type_tag == tag) { + // The tags match, lets try resolving this type + try_resolving_type = true; + } else { + // The tags don't match, but we need to watch our for a forward + // declaration for a struct and ("struct foo") ends up being a + // class ("class foo { ... };") or vice versa. + switch (type_tag) { + case DW_TAG_class_type: + // We had a "class foo", see if we ended up with a "struct foo + // { ... };" + try_resolving_type = (tag == DW_TAG_structure_type); + break; + case DW_TAG_structure_type: + // We had a "struct foo", see if we ended up with a "class foo + // { ... };" + try_resolving_type = (tag == DW_TAG_class_type); + break; + default: + // Tags don't match, don't event try to resolve using this type + // whose name matches.... + break; } } - } + + if (!try_resolving_type) { + if (log) { + std::string qualified_name; + type_die.GetQualifiedName(qualified_name); + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag=%s, " + "qualified-name='%s') ignoring die=0x%8.8x (%s)", + DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), + dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), + qualified_name.c_str()); + } + return true; + } + + DWARFDeclContext type_dwarf_decl_ctx = GetDWARFDeclContext(type_die); + + if (log) { + GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::" + "FindDefinitionTypeForDWARFDeclContext(tag=%s, " + "qualified-name='%s') trying die=0x%8.8x (%s)", + DW_TAG_value_to_name(dwarf_decl_ctx[0].tag), + dwarf_decl_ctx.GetQualifiedName(), type_die.GetOffset(), + type_dwarf_decl_ctx.GetQualifiedName()); + } + + // Make sure the decl contexts match all the way up + if (dwarf_decl_ctx != type_dwarf_decl_ctx) + return true; + + Type *resolved_type = ResolveType(type_die, false); + if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED) + return true; + + type_sp = resolved_type->shared_from_this(); + return false; + }); } } return type_sp; @@ -3045,8 +2933,7 @@ TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die, if (!die) return {}; - auto type_system_or_err = - GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); + auto type_system_or_err = GetTypeSystemForLanguage(GetLanguage(*die.GetCU())); if (auto err = type_system_or_err.takeError()) { LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), std::move(err), "Unable to parse type"); @@ -3067,7 +2954,7 @@ TypeSP SymbolFileDWARF::ParseType(const SymbolContext &sc, const DWARFDIE &die, .AsCString("")); if (scope_qualified_name.size()) { m_function_scope_qualified_name_map[scope_qualified_name].insert( - die.GetID()); + *die.GetDIERef()); } } } @@ -3124,7 +3011,8 @@ size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) { size_t functions_added = 0; const dw_offset_t function_die_offset = func.GetID(); - DWARFDIE function_die = dwarf_cu->GetDIE(function_die_offset); + DWARFDIE function_die = + dwarf_cu->GetNonSkeletonUnit().GetDIE(function_die_offset); if (function_die) { ParseBlocksRecursive(*comp_unit, &func.GetBlock(false), function_die, LLDB_INVALID_ADDRESS, 0); @@ -3152,10 +3040,6 @@ size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (sc.comp_unit != nullptr) { - DWARFDebugInfo *info = DebugInfo(); - if (info == nullptr) - return 0; - if (sc.function) { DWARFDIE function_die = GetDIE(sc.function->GetID()); @@ -3170,7 +3054,7 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { return num_variables; } } else if (sc.comp_unit) { - DWARFUnit *dwarf_cu = info->GetUnitAtIndex(sc.comp_unit->GetID()); + DWARFUnit *dwarf_cu = DebugInfo().GetUnitAtIndex(sc.comp_unit->GetID()); if (dwarf_cu == nullptr) return 0; @@ -3182,25 +3066,16 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { variables = std::make_shared<VariableList>(); sc.comp_unit->SetVariableList(variables); - DIEArray die_offsets; - m_index->GetGlobalVariables(dwarf_cu->GetNonSkeletonUnit(), - die_offsets); - const size_t num_matches = die_offsets.size(); - if (num_matches) { - for (size_t i = 0; i < num_matches; ++i) { - const DIERef &die_ref = die_offsets[i]; - DWARFDIE die = GetDIE(die_ref); - if (die) { + m_index->GetGlobalVariables( + dwarf_cu->GetNonSkeletonUnit(), [&](DWARFDIE die) { VariableSP var_sp( ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS)); if (var_sp) { variables->AddVariableIfUnique(var_sp); ++vars_added; } - } else - m_index->ReportInvalidDIERef(die_ref, ""); - } - } + return true; + }); } return vars_added; } @@ -3412,12 +3287,10 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, // declaration context. if ((parent_tag == DW_TAG_compile_unit || parent_tag == DW_TAG_partial_unit) && - Language::LanguageIsCPlusPlus(die.GetLanguage())) { - DWARFDeclContext decl_ctx; - - die.GetDWARFDeclContext(decl_ctx); - mangled = decl_ctx.GetQualifiedNameAsConstString().GetCString(); - } + Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU()))) + mangled = GetDWARFDeclContext(die) + .GetQualifiedNameAsConstString() + .GetCString(); } if (tag == DW_TAG_formal_parameter) @@ -3524,7 +3397,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, } } } else { - if (location_is_const_value_data) + if (location_is_const_value_data && + die.GetDIE()->IsGlobalOrStaticScopeVariable()) scope = eValueTypeVariableStatic; else { scope = eValueTypeVariableLocal; @@ -3603,7 +3477,7 @@ SymbolFileDWARF::FindBlockContainingSpecification( // Give the concrete function die specified by "func_die_offset", find the // concrete block whose DW_AT_specification or DW_AT_abstract_origin points // to "spec_block_die_offset" - return FindBlockContainingSpecification(DebugInfo()->GetDIE(func_die_ref), + return FindBlockContainingSpecification(DebugInfo().GetDIE(func_die_ref), spec_block_die_offset); } @@ -3762,7 +3636,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { CallSiteParameterArray parameters; for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid(); child = child.GetSibling()) { - if (child.Tag() != DW_TAG_call_site_parameter) + if (child.Tag() != DW_TAG_call_site_parameter && + child.Tag() != DW_TAG_GNU_call_site_parameter) continue; llvm::Optional<DWARFExpression> LocationInCallee; @@ -3792,7 +3667,7 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { dw_attr_t attr = attributes.AttributeAtIndex(i); if (attr == DW_AT_location) LocationInCallee = parse_simple_location(i); - if (attr == DW_AT_call_value) + if (attr == DW_AT_call_value || attr == DW_AT_GNU_call_site_value) LocationInCaller = parse_simple_location(i); } @@ -3805,12 +3680,13 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { } /// Collect call graph edges present in a function DIE. -static std::vector<std::unique_ptr<lldb_private::CallEdge>> -CollectCallEdges(ModuleSP module, DWARFDIE function_die) { +std::vector<std::unique_ptr<lldb_private::CallEdge>> +SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { // Check if the function has a supported call site-related attribute. // TODO: In the future it may be worthwhile to support call_all_source_calls. - uint64_t has_call_edges = - function_die.GetAttributeValueAsUnsigned(DW_AT_call_all_calls, 0); + bool has_call_edges = + function_die.GetAttributeValueAsUnsigned(DW_AT_call_all_calls, 0) || + function_die.GetAttributeValueAsUnsigned(DW_AT_GNU_all_call_sites, 0); if (!has_call_edges) return {}; @@ -3826,15 +3702,22 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) { std::vector<std::unique_ptr<CallEdge>> call_edges; for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid(); child = child.GetSibling()) { - if (child.Tag() != DW_TAG_call_site) + if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site) continue; llvm::Optional<DWARFDIE> call_origin; llvm::Optional<DWARFExpression> call_target; addr_t return_pc = LLDB_INVALID_ADDRESS; + addr_t call_inst_pc = LLDB_INVALID_ADDRESS; + addr_t low_pc = LLDB_INVALID_ADDRESS; + bool tail_call = false; + // Second DW_AT_low_pc may come from DW_TAG_subprogram referenced by + // DW_TAG_GNU_call_site's DW_AT_abstract_origin overwriting our 'low_pc'. + // So do not inherit attributes from DW_AT_abstract_origin. DWARFAttributes attributes; - const size_t num_attributes = child.GetAttributes(attributes); + const size_t num_attributes = + child.GetAttributes(attributes, DWARFDIE::Recurse::no); for (size_t i = 0; i < num_attributes; ++i) { DWARFFormValue form_value; if (!attributes.ExtractFormValueAtIndex(i, form_value)) { @@ -3844,8 +3727,11 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) { dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attr == DW_AT_call_tail_call || attr == DW_AT_GNU_tail_call) + tail_call = form_value.Boolean(); + // Extract DW_AT_call_origin (the call target's DIE). - if (attr == DW_AT_call_origin) { + if (attr == DW_AT_call_origin || attr == DW_AT_abstract_origin) { call_origin = form_value.Reference(); if (!call_origin->IsValid()) { LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}", @@ -3854,15 +3740,24 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) { } } + if (attr == DW_AT_low_pc) + low_pc = form_value.Address(); + // Extract DW_AT_call_return_pc (the PC the call returns to) if it's // available. It should only ever be unavailable for tail call edges, in // which case use LLDB_INVALID_ADDRESS. if (attr == DW_AT_call_return_pc) return_pc = form_value.Address(); + // Extract DW_AT_call_pc (the PC at the call/branch instruction). It + // should only ever be unavailable for non-tail calls, in which case use + // LLDB_INVALID_ADDRESS. + if (attr == DW_AT_call_pc) + call_inst_pc = form_value.Address(); + // Extract DW_AT_call_target (the location of the address of the indirect // call). - if (attr == DW_AT_call_target) { + if (attr == DW_AT_call_target || attr == DW_AT_GNU_call_site_target) { if (!DWARFFormValue::IsBlockForm(form_value.Form())) { LLDB_LOG(log, "CollectCallEdges: AT_call_target does not have block form"); @@ -3882,16 +3777,39 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) { continue; } + addr_t caller_address; + CallEdge::AddrType caller_address_type; + if (return_pc != LLDB_INVALID_ADDRESS) { + caller_address = return_pc; + caller_address_type = CallEdge::AddrType::AfterCall; + } else if (low_pc != LLDB_INVALID_ADDRESS) { + caller_address = low_pc; + caller_address_type = CallEdge::AddrType::AfterCall; + } else if (call_inst_pc != LLDB_INVALID_ADDRESS) { + caller_address = call_inst_pc; + caller_address_type = CallEdge::AddrType::Call; + } else { + LLDB_LOG(log, "CollectCallEdges: No caller address"); + continue; + } + // Adjust any PC forms. It needs to be fixed up if the main executable + // contains a debug map (i.e. pointers to object files), because we need a + // file address relative to the executable's text section. + caller_address = FixupAddress(caller_address); + // Extract call site parameters. CallSiteParameterArray parameters = CollectCallSiteParameters(module, child); std::unique_ptr<CallEdge> edge; if (call_origin) { - LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})", - call_origin->GetPubname(), return_pc); - edge = std::make_unique<DirectCallEdge>(call_origin->GetMangledName(), - return_pc, std::move(parameters)); + LLDB_LOG(log, + "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x}) " + "(call-PC: {2:x})", + call_origin->GetPubname(), return_pc, call_inst_pc); + edge = std::make_unique<DirectCallEdge>( + call_origin->GetMangledName(), caller_address_type, caller_address, + tail_call, std::move(parameters)); } else { if (log) { StreamString call_target_desc; @@ -3900,8 +3818,9 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) { LLDB_LOG(log, "CollectCallEdges: Found indirect call target: {0}", call_target_desc.GetString()); } - edge = std::make_unique<IndirectCallEdge>(*call_target, return_pc, - std::move(parameters)); + edge = std::make_unique<IndirectCallEdge>( + *call_target, caller_address_type, caller_address, tail_call, + std::move(parameters)); } if (log && parameters.size()) { @@ -3925,6 +3844,11 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) { std::vector<std::unique_ptr<lldb_private::CallEdge>> SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) { + // ParseCallEdgesInFunction must be called at the behest of an exclusively + // locked lldb::Function instance. Storage for parsed call edges is owned by + // the lldb::Function instance: locking at the SymbolFile level would be too + // late, because the act of storing results from ParseCallEdgesInFunction + // would be racy. DWARFDIE func_die = GetDIE(func_id.GetID()); if (func_die.IsValid()) return CollectCallEdges(GetObjectFile()->GetModule(), func_die); @@ -3945,8 +3869,8 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); if (!ts_or_err) return; - ClangASTContext *clang = - llvm::dyn_cast_or_null<ClangASTContext>(&ts_or_err.get()); + TypeSystemClang *clang = + llvm::dyn_cast_or_null<TypeSystemClang>(&ts_or_err.get()); if (!clang) return; clang->Dump(s); @@ -3957,26 +3881,93 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); if (module_sp) { m_debug_map_symfile = - (SymbolFileDWARFDebugMap *)module_sp->GetSymbolFile(); + static_cast<SymbolFileDWARFDebugMap *>(module_sp->GetSymbolFile()); } } return m_debug_map_symfile; } -SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { +const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() { llvm::call_once(m_dwp_symfile_once_flag, [this]() { ModuleSpec module_spec; module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec(); module_spec.GetSymbolFileSpec() = - FileSpec(m_objfile_sp->GetFileSpec().GetPath() + ".dwp"); + FileSpec(m_objfile_sp->GetModule()->GetFileSpec().GetPath() + ".dwp"); FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); FileSpec dwp_filespec = Symbols::LocateExecutableSymbolFile(module_spec, search_paths); if (FileSystem::Instance().Exists(dwp_filespec)) { - m_dwp_symfile = SymbolFileDWARFDwp::Create(GetObjectFile()->GetModule(), - dwp_filespec); + DataBufferSP dwp_file_data_sp; + lldb::offset_t dwp_file_data_offset = 0; + ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin( + GetObjectFile()->GetModule(), &dwp_filespec, 0, + FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp, + dwp_file_data_offset); + if (!dwp_obj_file) + return; + m_dwp_symfile = + std::make_shared<SymbolFileDWARFDwo>(*this, dwp_obj_file, 0x3fffffff); } }); - return m_dwp_symfile.get(); + return m_dwp_symfile; +} + +llvm::Expected<TypeSystem &> SymbolFileDWARF::GetTypeSystem(DWARFUnit &unit) { + return unit.GetSymbolFileDWARF().GetTypeSystemForLanguage(GetLanguage(unit)); +} + +DWARFASTParser *SymbolFileDWARF::GetDWARFParser(DWARFUnit &unit) { + auto type_system_or_err = GetTypeSystem(unit); + if (auto err = type_system_or_err.takeError()) { + LLDB_LOG_ERROR(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS), + std::move(err), "Unable to get DWARFASTParser"); + return nullptr; + } + return type_system_or_err->GetDWARFParser(); +} + +CompilerDecl SymbolFileDWARF::GetDecl(const DWARFDIE &die) { + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) + return dwarf_ast->GetDeclForUIDFromDWARF(die); + return CompilerDecl(); +} + +CompilerDeclContext SymbolFileDWARF::GetDeclContext(const DWARFDIE &die) { + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) + return dwarf_ast->GetDeclContextForUIDFromDWARF(die); + return CompilerDeclContext(); +} + +CompilerDeclContext +SymbolFileDWARF::GetContainingDeclContext(const DWARFDIE &die) { + if (DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU())) + return dwarf_ast->GetDeclContextContainingUIDFromDWARF(die); + return CompilerDeclContext(); +} + +DWARFDeclContext SymbolFileDWARF::GetDWARFDeclContext(const DWARFDIE &die) { + if (!die.IsValid()) + return {}; + DWARFDeclContext dwarf_decl_ctx = + die.GetDIE()->GetDWARFDeclContext(die.GetCU()); + dwarf_decl_ctx.SetLanguage(GetLanguage(*die.GetCU())); + return dwarf_decl_ctx; +} + +LanguageType SymbolFileDWARF::LanguageTypeFromDWARF(uint64_t val) { + // Note: user languages between lo_user and hi_user must be handled + // explicitly here. + switch (val) { + case DW_LANG_Mips_Assembler: + return eLanguageTypeMipsAssembler; + case DW_LANG_GOOGLE_RenderScript: + return eLanguageTypeExtRenderScript; + default: + return static_cast<LanguageType>(val); + } +} + +LanguageType SymbolFileDWARF::GetLanguage(DWARFUnit &unit) { + return LanguageTypeFromDWARF(unit.GetDWARFLanguageType()); } |