diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp')
| -rw-r--r-- | source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 397 |
1 files changed, 255 insertions, 142 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ac320ac52b08..2a0a89f0b25a 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -9,7 +9,6 @@ #include "SymbolFileDWARF.h" -// Other libraries and framework includes #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" @@ -17,12 +16,12 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Core/Scalar.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/Scalar.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" @@ -111,17 +110,14 @@ using namespace lldb_private; namespace { -PropertyDefinition g_properties[] = { +static constexpr PropertyDefinition g_properties[] = { {"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr, - nullptr, + {}, "If the DW_AT_comp_dir matches any of these paths the symbolic " "links will be resolved at DWARF parse time."}, - {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr, - nullptr, + {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr, {}, "Ignore indexes present in the object files and always index DWARF " - "manually."}, - {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}, -}; + "manually."}}; enum { ePropertySymLinkPaths, @@ -200,7 +196,7 @@ static FileSpec resolveCompDir(const char *path_from_dwarf) { bool is_symlink = false; // Always normalize our compile unit directory to get rid of redundant // slashes and other path anomalies before we use it for path prepending - FileSpec local_spec(local_path, false); + FileSpec local_spec(local_path); const auto &file_specs = GetGlobalPluginProperties()->GetSymLinkPaths(); for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i) is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i), @@ -215,7 +211,7 @@ static FileSpec resolveCompDir(const char *path_from_dwarf) { return local_spec; FileSpec resolved_symlink; - const auto error = FileSystem::Readlink(local_spec, resolved_symlink); + const auto error = FileSystem::Instance().Readlink(local_spec, resolved_symlink); if (error.Success()) return resolved_symlink; @@ -263,6 +259,9 @@ SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFile *obj_file) { } TypeList *SymbolFileDWARF::GetTypeList() { + // This method can be called without going through the symbol vendor so we + // need to lock the module. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); if (debug_map_symfile) return debug_map_symfile->GetTypeList(); @@ -341,9 +340,10 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, } size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, - uint32_t type_mask, TypeList &type_list) + TypeClass type_mask, TypeList &type_list) { + ASSERT_MODULE_LOCK(this); TypeSet type_set; CompileUnit *comp_unit = NULL; @@ -413,9 +413,9 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile) m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(), m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(), m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(), - m_data_debug_ranges(), m_data_debug_str(), m_data_apple_names(), - m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(), - m_line(), m_fetched_external_modules(false), + m_data_debug_ranges(), m_data_debug_rnglists(), m_data_debug_str(), + m_data_apple_names(), m_data_apple_types(), m_data_apple_namespaces(), + m_abbr(), m_info(), m_line(), m_fetched_external_modules(false), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(), m_unique_ast_type_map() {} @@ -494,7 +494,7 @@ void SymbolFileDWARF::InitializeObject() { } bool SymbolFileDWARF::SupportedVersion(uint16_t version) { - return version == 2 || version == 3 || version == 4; + return version >= 2 && version <= 5; } uint32_t SymbolFileDWARF::CalculateAbilities() { @@ -645,19 +645,40 @@ const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_data() { return GetCachedSectionData(eSectionTypeDWARFDebugLine, m_data_debug_line); } +const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_str_data() { + return GetCachedSectionData(eSectionTypeDWARFDebugLineStr, m_data_debug_line_str); +} + const DWARFDataExtractor &SymbolFileDWARF::get_debug_macro_data() { return GetCachedSectionData(eSectionTypeDWARFDebugMacro, m_data_debug_macro); } +const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() { + const DWARFDataExtractor &debugLocData = get_debug_loc_data(); + if (debugLocData.GetByteSize() > 0) + return debugLocData; + return get_debug_loclists_data(); +} + const DWARFDataExtractor &SymbolFileDWARF::get_debug_loc_data() { return GetCachedSectionData(eSectionTypeDWARFDebugLoc, m_data_debug_loc); } +const DWARFDataExtractor &SymbolFileDWARF::get_debug_loclists_data() { + return GetCachedSectionData(eSectionTypeDWARFDebugLocLists, + m_data_debug_loclists); +} + const DWARFDataExtractor &SymbolFileDWARF::get_debug_ranges_data() { return GetCachedSectionData(eSectionTypeDWARFDebugRanges, m_data_debug_ranges); } +const DWARFDataExtractor &SymbolFileDWARF::get_debug_rnglists_data() { + return GetCachedSectionData(eSectionTypeDWARFDebugRngLists, + m_data_debug_rnglists); +} + const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_data() { return GetCachedSectionData(eSectionTypeDWARFDebugStr, m_data_debug_str); } @@ -747,21 +768,24 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { return NULL; } -DWARFDebugRanges *SymbolFileDWARF::DebugRanges() { +DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() { if (m_ranges.get() == NULL) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast<void *>(this)); - if (get_debug_ranges_data().GetByteSize() > 0) { + + if (get_debug_ranges_data().GetByteSize() > 0) m_ranges.reset(new DWARFDebugRanges()); - if (m_ranges.get()) - m_ranges->Extract(this); - } + else if (get_debug_rnglists_data().GetByteSize() > 0) + m_ranges.reset(new DWARFDebugRngLists()); + + if (m_ranges.get()) + m_ranges->Extract(this); } return m_ranges.get(); } -const DWARFDebugRanges *SymbolFileDWARF::DebugRanges() const { +const DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() const { return m_ranges.get(); } @@ -786,7 +810,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu, if (module_sp) { const DWARFDIE cu_die = dwarf_cu->DIE(); if (cu_die) { - FileSpec cu_file_spec{cu_die.GetName(), false}; + FileSpec cu_file_spec(cu_die.GetName()); 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 @@ -801,8 +825,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu, std::string remapped_file; if (module_sp->RemapSourceFile(cu_file_spec.GetPath(), remapped_file)) - cu_file_spec.SetFile(remapped_file, false, - FileSpec::Style::native); + cu_file_spec.SetFile(remapped_file, FileSpec::Style::native); } LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF( @@ -851,6 +874,7 @@ uint32_t SymbolFileDWARF::GetNumCompileUnits() { } CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { + ASSERT_MODULE_LOCK(this); CompUnitSP cu_sp; DWARFDebugInfo *info = DebugInfo(); if (info) { @@ -861,8 +885,9 @@ CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { return cu_sp; } -Function *SymbolFileDWARF::ParseCompileUnitFunction(const SymbolContext &sc, - const DWARFDIE &die) { +Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, + const DWARFDIE &die) { + ASSERT_MODULE_LOCK(this); if (die.IsValid()) { TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); @@ -870,7 +895,7 @@ Function *SymbolFileDWARF::ParseCompileUnitFunction(const SymbolContext &sc, if (type_system) { DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); if (dwarf_ast) - return dwarf_ast->ParseFunctionFromDWARF(sc, die); + return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die); } } return nullptr; @@ -884,20 +909,19 @@ bool SymbolFileDWARF::FixupAddress(Address &addr) { // This is a normal DWARF file, no address fixups need to happen return true; } -lldb::LanguageType -SymbolFileDWARF::ParseCompileUnitLanguage(const SymbolContext &sc) { - assert(sc.comp_unit); - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); +lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) { + ASSERT_MODULE_LOCK(this); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) return dwarf_cu->GetLanguageType(); else return eLanguageTypeUnknown; } -size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) { - assert(sc.comp_unit); +size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) { + ASSERT_MODULE_LOCK(this); size_t functions_added = 0; - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) { DWARFDIECollection function_dies; const size_t num_functions = @@ -905,8 +929,8 @@ size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) { size_t func_idx; for (func_idx = 0; func_idx < num_functions; ++func_idx) { DWARFDIE die = function_dies.GetDIEAtIndex(func_idx); - if (sc.comp_unit->FindFunctionByUID(die.GetID()).get() == NULL) { - if (ParseCompileUnitFunction(sc, die)) + if (comp_unit.FindFunctionByUID(die.GetID()).get() == NULL) { + if (ParseFunction(comp_unit, die)) ++functions_added; } } @@ -915,10 +939,10 @@ size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) { return functions_added; } -bool SymbolFileDWARF::ParseCompileUnitSupportFiles( - const SymbolContext &sc, FileSpecList &support_files) { - assert(sc.comp_unit); - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); +bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, + FileSpecList &support_files) { + ASSERT_MODULE_LOCK(this); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) { const DWARFBaseDIE cu_die = dwarf_cu->GetUnitDIEOnly(); @@ -930,19 +954,19 @@ bool SymbolFileDWARF::ParseCompileUnitSupportFiles( if (stmt_list != DW_INVALID_OFFSET) { // All file indexes in DWARF are one based and a file of index zero is // supposed to be the compile unit itself. - support_files.Append(*sc.comp_unit); + support_files.Append(comp_unit); return DWARFDebugLine::ParseSupportFiles( - sc.comp_unit->GetModule(), get_debug_line_data(), cu_comp_dir, - stmt_list, support_files); + comp_unit.GetModule(), get_debug_line_data(), cu_comp_dir, + stmt_list, support_files, dwarf_cu); } } } return false; } -bool SymbolFileDWARF::ParseCompileUnitIsOptimized( - const lldb_private::SymbolContext &sc) { - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); +bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { + ASSERT_MODULE_LOCK(this); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) return dwarf_cu->GetIsOptimized(); return false; @@ -951,6 +975,7 @@ bool SymbolFileDWARF::ParseCompileUnitIsOptimized( bool SymbolFileDWARF::ParseImportedModules( const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules) { + ASSERT_MODULE_LOCK(this); assert(sc.comp_unit); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); if (dwarf_cu) { @@ -1027,12 +1052,12 @@ static void ParseDWARFLineTableCallback(dw_offset_t offset, } } -bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) { - assert(sc.comp_unit); - if (sc.comp_unit->GetLineTable() != NULL) +bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { + ASSERT_MODULE_LOCK(this); + if (comp_unit.GetLineTable() != NULL) return true; - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) { const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly(); if (dwarf_cu_die) { @@ -1040,7 +1065,7 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) { dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET); if (cu_line_offset != DW_INVALID_OFFSET) { - std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit)); + std::unique_ptr<LineTable> line_table_ap(new LineTable(&comp_unit)); if (line_table_ap.get()) { ParseDWARFLineTableCallbackInfo info; info.line_table = line_table_ap.get(); @@ -1053,9 +1078,7 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) { * #0 * for MIPS. Use ArchSpec to clear the bit #0. */ - ArchSpec arch; - GetObjectFile()->GetArchitecture(arch); - switch (arch.GetMachine()) { + switch (GetObjectFile()->GetArchitecture().GetMachine()) { case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -1070,17 +1093,17 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) { lldb::offset_t offset = cu_line_offset; DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, - &info); + &info, dwarf_cu); SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); if (debug_map_symfile) { // 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 are relative to the .o file into addresses for // the main executable. - sc.comp_unit->SetLineTable( + comp_unit.SetLineTable( debug_map_symfile->LinkOSOLineTable(this, line_table_ap.get())); } else { - sc.comp_unit->SetLineTable(line_table_ap.release()); + comp_unit.SetLineTable(line_table_ap.release()); return true; } } @@ -1112,10 +1135,10 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) { return debug_macros_sp; } -bool SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext &sc) { - assert(sc.comp_unit); +bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) { + ASSERT_MODULE_LOCK(this); - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu == nullptr) return false; @@ -1131,16 +1154,14 @@ bool SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext &sc) { if (sect_offset == DW_INVALID_OFFSET) return false; - sc.comp_unit->SetDebugMacros(ParseDebugMacros(§_offset)); + comp_unit.SetDebugMacros(ParseDebugMacros(§_offset)); return true; } -size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc, - Block *parent_block, - const DWARFDIE &orig_die, - addr_t subprogram_low_pc, - uint32_t depth) { +size_t SymbolFileDWARF::ParseBlocksRecursive( + lldb_private::CompileUnit &comp_unit, Block *parent_block, + const DWARFDIE &orig_die, addr_t subprogram_low_pc, uint32_t depth) { size_t blocks_added = 0; DWARFDIE die = orig_die; while (die) { @@ -1219,13 +1240,13 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc, std::unique_ptr<Declaration> decl_ap; if (decl_file != 0 || decl_line != 0 || decl_column != 0) decl_ap.reset(new Declaration( - sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), + comp_unit.GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, decl_column)); std::unique_ptr<Declaration> call_ap; if (call_file != 0 || call_line != 0 || call_column != 0) call_ap.reset(new Declaration( - sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(call_file), + comp_unit.GetSupportFiles().GetFileSpecAtIndex(call_file), call_line, call_column)); block->SetInlinedFunctionInfo(name, mangled_name, decl_ap.get(), @@ -1235,8 +1256,9 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc, ++blocks_added; if (die.HasChildren()) { - blocks_added += ParseFunctionBlocks(sc, block, die.GetFirstChild(), - subprogram_low_pc, depth + 1); + blocks_added += + ParseBlocksRecursive(comp_unit, block, die.GetFirstChild(), + subprogram_low_pc, depth + 1); } } } break; @@ -1292,6 +1314,9 @@ void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) { } SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) { + // This method can be called without going through the symbol vendor so we + // need to lock the module. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we // must make sure we use the correct DWARF file when resolving things. On // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple @@ -1308,6 +1333,9 @@ SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) { DWARFDIE SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) { + // This method can be called without going through the symbol vendor so we + // need to lock the module. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we // must make sure we use the correct DWARF file when resolving things. On // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple @@ -1322,6 +1350,9 @@ SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) { } CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) { + // This method can be called without going through the symbol vendor so we + // need to lock the module. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIEFromUID(). See comments inside the // SymbolFileDWARF::GetDIEFromUID() for details. @@ -1333,6 +1364,9 @@ CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) { CompilerDeclContext SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) { + // This method can be called without going through the symbol vendor so we + // need to lock the module. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIEFromUID(). See comments inside the // SymbolFileDWARF::GetDIEFromUID() for details. @@ -1344,6 +1378,9 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) { CompilerDeclContext SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { + // This method can be called without going through the symbol vendor so we + // need to lock the module. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIEFromUID(). See comments inside the // SymbolFileDWARF::GetDIEFromUID() for details. @@ -1354,6 +1391,9 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) { } Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) { + // This method can be called without going through the symbol vendor so we + // need to lock the module. + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); // Anytime we have a lldb::user_id_t, we must get the DIE by calling // SymbolFileDWARF::GetDIEFromUID(). See comments inside the // SymbolFileDWARF::GetDIEFromUID() for details. @@ -1364,6 +1404,17 @@ Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) { return nullptr; } +llvm::Optional<SymbolFile::ArrayInfo> +SymbolFileDWARF::GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + DWARFDIE type_die = GetDIEFromUID(type_uid); + if (type_die) + return DWARFASTParser::ParseChildArrayInfo(type_die, exe_ctx); + else + return llvm::None; +} + Type *SymbolFileDWARF::ResolveTypeUID(const DIERef &die_ref) { return ResolveType(GetDIE(die_ref), true); } @@ -1429,8 +1480,7 @@ bool SymbolFileDWARF::HasForwardDeclForClangType( } bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) { - std::lock_guard<std::recursive_mutex> guard( - GetObjectFile()->GetModule()->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem()); @@ -1525,7 +1575,7 @@ bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) { sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get(); if (sc.function == NULL) - sc.function = ParseCompileUnitFunction(sc, die); + sc.function = ParseFunction(*sc.comp_unit, die); if (sc.function) { sc.module_sp = sc.function->CalculateSymbolContextModule(); @@ -1578,18 +1628,20 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( return dwo_symfile; } - FileSpec dwo_file(dwo_name, true); + FileSpec dwo_file(dwo_name); + FileSystem::Instance().Resolve(dwo_file); if (dwo_file.IsRelative()) { const char *comp_dir = cu_die.GetAttributeValueAsString( this, &dwarf_cu, DW_AT_comp_dir, nullptr); if (!comp_dir) return nullptr; - dwo_file.SetFile(comp_dir, true, FileSpec::Style::native); + dwo_file.SetFile(comp_dir, FileSpec::Style::native); + FileSystem::Instance().Resolve(dwo_file); dwo_file.AppendPathComponent(dwo_name); } - if (!dwo_file.Exists()) + if (!FileSystem::Instance().Exists(dwo_file)) return nullptr; const lldb::offset_t file_offset = 0; @@ -1597,7 +1649,8 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( lldb::offset_t dwo_file_data_offset = 0; ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin( GetObjectFile()->GetModule(), &dwo_file, file_offset, - dwo_file.GetByteSize(), dwo_file_data_sp, dwo_file_data_offset); + FileSystem::Instance().GetByteSize(dwo_file), dwo_file_data_sp, + dwo_file_data_offset); if (dwo_obj_file == nullptr) return nullptr; @@ -1616,7 +1669,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly(); - if (die && die.HasChildren() == false) { + if (die && !die.HasChildren()) { const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr); if (name) { @@ -1628,14 +1681,15 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); if (dwo_path) { ModuleSpec dwo_module_spec; - dwo_module_spec.GetFileSpec().SetFile(dwo_path, false, + dwo_module_spec.GetFileSpec().SetFile(dwo_path, FileSpec::Style::native); if (dwo_module_spec.GetFileSpec().IsRelative()) { const char *comp_dir = die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr); if (comp_dir) { - dwo_module_spec.GetFileSpec().SetFile(comp_dir, true, + dwo_module_spec.GetFileSpec().SetFile(comp_dir, FileSpec::Style::native); + FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec()); dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path); } } @@ -1726,7 +1780,7 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { } uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, - uint32_t resolve_scope, + SymbolContextItem resolve_scope, SymbolContext &sc) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, @@ -1784,7 +1838,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, sc.function = sc.comp_unit->FindFunctionByUID(function_die.GetID()).get(); if (sc.function == NULL) - sc.function = ParseCompileUnitFunction(sc, function_die); + sc.function = ParseFunction(*sc.comp_unit, function_die); if (sc.function && (resolve_scope & eSymbolContextBlock)) block_die = function_die.LookupDeepestBlock(file_vm_addr); @@ -1860,7 +1914,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, uint32_t line, bool check_inlines, - uint32_t resolve_scope, + SymbolContextItem resolve_scope, SymbolContextList &sc_list) { const uint32_t prev_size = sc_list.GetSize(); if (resolve_scope & eSymbolContextCompUnit) { @@ -1925,7 +1979,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, .get(); if (sc.function == NULL) sc.function = - ParseCompileUnitFunction(sc, function_die); + ParseFunction(*sc.comp_unit, function_die); if (sc.function && (resolve_scope & eSymbolContextBlock)) @@ -1975,11 +2029,17 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, } void SymbolFileDWARF::PreloadSymbols() { - std::lock_guard<std::recursive_mutex> guard( - GetObjectFile()->GetModule()->GetMutex()); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); m_index->Preload(); } +std::recursive_mutex &SymbolFileDWARF::GetModuleMutex() const { + lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); + if (module_sp) + return module_sp->GetMutex(); + return GetObjectFile()->GetModule()->GetMutex(); +} + bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile( const lldb_private::CompilerDeclContext *decl_ctx) { if (decl_ctx == nullptr || !decl_ctx->IsValid()) { @@ -2195,7 +2255,7 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, sc.block = function_block.FindBlockByID(inlined_die.GetID()); if (sc.block == NULL) sc.block = function_block.FindBlockByID(inlined_die.GetOffset()); - if (sc.block == NULL || sc.block->GetStartAddress(addr) == false) + if (sc.block == NULL || !sc.block->GetStartAddress(addr)) addr.Clear(); } else { sc.block = NULL; @@ -2231,11 +2291,10 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx, return false; } -uint32_t -SymbolFileDWARF::FindFunctions(const ConstString &name, - const CompilerDeclContext *parent_decl_ctx, - uint32_t name_type_mask, bool include_inlines, - bool append, SymbolContextList &sc_list) { +uint32_t SymbolFileDWARF::FindFunctions( + const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + FunctionNameType name_type_mask, bool include_inlines, bool append, + SymbolContextList &sc_list) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolFileDWARF::FindFunctions (name = '%s')", name.AsCString()); @@ -2378,9 +2437,8 @@ void SymbolFileDWARF::GetMangledNamesForFunction( } uint32_t SymbolFileDWARF::FindTypes( - const SymbolContext &sc, const ConstString &name, - const CompilerDeclContext *parent_decl_ctx, bool append, - uint32_t max_matches, + const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap &types) { // If we aren't appending the results to this list, then clear the list @@ -2469,8 +2527,8 @@ uint32_t SymbolFileDWARF::FindTypes( SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor(); if (sym_vendor) { const uint32_t num_external_matches = - sym_vendor->FindTypes(sc, name, parent_decl_ctx, append, - max_matches, searched_symbol_files, types); + sym_vendor->FindTypes(name, parent_decl_ctx, append, max_matches, + searched_symbol_files, types); if (num_external_matches) return num_external_matches; } @@ -2506,7 +2564,7 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context, if (die) { std::vector<CompilerContext> die_context; - die.GetDWOContext(die_context); + die.GetDeclContext(die_context); if (die_context != context) continue; @@ -2528,7 +2586,7 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context, } CompilerDeclContext -SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name, +SymbolFileDWARF::FindNamespace(const ConstString &name, const CompilerDeclContext *parent_decl_ctx) { Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -3065,39 +3123,36 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc, return types_added; } -size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc) { - assert(sc.comp_unit && sc.function); +size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) { + ASSERT_MODULE_LOCK(this); + CompileUnit *comp_unit = func.GetCompileUnit(); + lldbassert(comp_unit); + + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(comp_unit); + if (!dwarf_cu) + return 0; + size_t functions_added = 0; - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); - if (dwarf_cu) { - const dw_offset_t function_die_offset = sc.function->GetID(); - DWARFDIE function_die = dwarf_cu->GetDIE(function_die_offset); - if (function_die) { - ParseFunctionBlocks(sc, &sc.function->GetBlock(false), function_die, - LLDB_INVALID_ADDRESS, 0); - } + const dw_offset_t function_die_offset = func.GetID(); + DWARFDIE function_die = dwarf_cu->GetDIE(function_die_offset); + if (function_die) { + ParseBlocksRecursive(*comp_unit, &func.GetBlock(false), function_die, + LLDB_INVALID_ADDRESS, 0); } return functions_added; } -size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc) { - // At least a compile unit must be valid - assert(sc.comp_unit); +size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { + ASSERT_MODULE_LOCK(this); size_t types_added = 0; - DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); + DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (dwarf_cu) { - if (sc.function) { - dw_offset_t function_die_offset = sc.function->GetID(); - DWARFDIE func_die = dwarf_cu->GetDIE(function_die_offset); - if (func_die && func_die.HasChildren()) { - types_added = ParseTypes(sc, func_die.GetFirstChild(), true, true); - } - } else { - DWARFDIE dwarf_cu_die = dwarf_cu->DIE(); - if (dwarf_cu_die && dwarf_cu_die.HasChildren()) { - types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true); - } + DWARFDIE dwarf_cu_die = dwarf_cu->DIE(); + if (dwarf_cu_die && dwarf_cu_die.HasChildren()) { + SymbolContext sc; + sc.comp_unit = &comp_unit; + types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true); } } @@ -3105,6 +3160,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc) { } size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { + ASSERT_MODULE_LOCK(this); if (sc.comp_unit != NULL) { DWARFDebugInfo *info = DebugInfo(); if (info == NULL) @@ -3298,7 +3354,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, uint32_t block_length = form_value.Unsigned(); location.CopyOpcodeData(module, data, block_offset, block_length); } else { - const DWARFDataExtractor &debug_loc_data = get_debug_loc_data(); + const DWARFDataExtractor &debug_loc_data = DebugLocData(); const dw_offset_t debug_loc_offset = form_value.Unsigned(); size_t loc_list_length = DWARFExpression::LocationListSize( @@ -3319,22 +3375,10 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, case DW_AT_start_scope: { if (form_value.Form() == DW_FORM_sec_offset) { DWARFRangeList dwarf_scope_ranges; - const DWARFDebugRanges *debug_ranges = DebugRanges(); - debug_ranges->FindRanges(die.GetCU()->GetRangesBase(), + const DWARFDebugRangesBase *debug_ranges = DebugRanges(); + debug_ranges->FindRanges(die.GetCU(), form_value.Unsigned(), dwarf_scope_ranges); - - // All DW_AT_start_scope are relative to the base address of the - // compile unit. We add the compile unit base address to make - // sure all the addresses are properly fixed up. - for (size_t i = 0, count = dwarf_scope_ranges.GetSize(); - i < count; ++i) { - const DWARFRangeList::Entry &range = - dwarf_scope_ranges.GetEntryRef(i); - scope_ranges.Append(range.GetRangeBase() + - die.GetCU()->GetBaseAddress(), - range.GetByteSize()); - } } else { // TODO: Handle the case when DW_AT_start_scope have form // constant. The @@ -3436,6 +3480,11 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, is_static_lifetime = true; } SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); + if (debug_map_symfile) + // Set the module of the expression to the linked module + // instead of the oject file so the relocated address can be + // found there. + location.SetModule(debug_map_symfile->GetObjectFile()->GetModule()); if (is_static_lifetime) { if (is_external) @@ -3736,6 +3785,60 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, return vars_added; } +/// Collect call graph edges present in a function DIE. +static std::vector<lldb_private::CallEdge> +CollectCallEdges(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); + if (!has_call_edges) + return {}; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + LLDB_LOG(log, "CollectCallEdges: Found call site info in {0}", + function_die.GetPubname()); + + // Scan the DIE for TAG_call_site entries. + // TODO: A recursive scan of all blocks in the subprogram is needed in order + // to be DWARF5-compliant. This may need to be done lazily to be performant. + // For now, assume that all entries are nested directly under the subprogram + // (this is the kind of DWARF LLVM produces) and parse them eagerly. + std::vector<CallEdge> call_edges; + for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid(); + child = child.GetSibling()) { + if (child.Tag() != DW_TAG_call_site) + continue; + + // Extract DW_AT_call_origin (the call target's DIE). + DWARFDIE call_origin = child.GetReferencedDIE(DW_AT_call_origin); + if (!call_origin.IsValid()) { + LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}", + function_die.GetPubname()); + continue; + } + + // 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. + addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc, + LLDB_INVALID_ADDRESS); + + LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})", + call_origin.GetPubname(), return_pc); + call_edges.emplace_back(call_origin.GetMangledName(), return_pc); + } + return call_edges; +} + +std::vector<lldb_private::CallEdge> +SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) { + DWARFDIE func_die = GetDIEFromUID(func_id.GetID()); + if (func_die.IsValid()) + return CollectCallEdges(func_die); + return {}; +} + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -3745,6 +3848,14 @@ uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; } void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); } +void SymbolFileDWARF::DumpClangAST(Stream &s) { + TypeSystem *ts = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + ClangASTContext *clang = llvm::dyn_cast_or_null<ClangASTContext>(ts); + if (!clang) + return; + clang->Dump(s); +} + SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired()) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); @@ -3760,6 +3871,8 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { DWARFExpression::LocationListFormat SymbolFileDWARF::GetLocationListFormat() const { + if (m_data_debug_loclists.m_data.GetByteSize() > 0) + return DWARFExpression::LocLists; return DWARFExpression::RegularLocationList; } @@ -3768,9 +3881,9 @@ SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { ModuleSpec module_spec; module_spec.GetFileSpec() = m_obj_file->GetFileSpec(); module_spec.GetSymbolFileSpec() = - FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp", false); + FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp"); FileSpec dwp_filespec = Symbols::LocateExecutableSymbolFile(module_spec); - if (dwp_filespec.Exists()) { + if (FileSystem::Instance().Exists(dwp_filespec)) { m_dwp_symfile = SymbolFileDWARFDwp::Create(GetObjectFile()->GetModule(), dwp_filespec); } |
