diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF')
24 files changed, 577 insertions, 260 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt index fb468440f9e03..05d9e66428680 100644 --- a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -30,6 +30,8 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN NameToDIE.cpp SymbolFileDWARF.cpp SymbolFileDWARFDwo.cpp + SymbolFileDWARFDwoDwp.cpp + SymbolFileDWARFDwp.cpp SymbolFileDWARFDebugMap.cpp UniqueDWARFASTType.cpp @@ -47,5 +49,6 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN lldbPluginCPlusPlusLanguage lldbPluginExpressionParserClang LINK_COMPONENTS + DebugInfoDWARF Support ) diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/source/Plugins/SymbolFile/DWARF/DIERef.cpp index 5ed9c6ab72825..c05444c031e67 100644 --- a/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ b/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -65,7 +65,7 @@ lldb::user_id_t DIERef::GetUID(SymbolFileDWARF *dwarf) const { // // SymbolFileDWARFDwo sets the ID to the compile unit offset. //---------------------------------------------------------------------- - if (dwarf) + if (dwarf && die_offset != DW_INVALID_OFFSET) return dwarf->GetID() | die_offset; else return LLDB_INVALID_UID; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index f5418763d67be..6ae2b225d8696 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -786,7 +786,17 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, m_ast.ParseClassTemplateDecl(decl_ctx, accessibility, type_name_cstr, tag_decl_kind, template_param_infos); - + if (!class_template_decl) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " + "clang::ClassTemplateDecl failed to return a decl.", + static_cast<void *>(this), die.GetOffset(), + DW_TAG_value_to_name(tag), type_name_cstr); + } + return TypeSP(); + } + clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl( @@ -927,6 +937,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, // Set a bit that lets us know that we are currently parsing this dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + bool is_scoped = false; DWARFFormValue encoding_form; const size_t num_attributes = die.GetAttributes(attributes); @@ -963,6 +974,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_AT_declaration: is_forward_declaration = form_value.Boolean(); break; + case DW_AT_enum_class: + is_scoped = form_value.Boolean(); + break; case DW_AT_allocated: case DW_AT_associated: case DW_AT_bit_stride: @@ -1052,7 +1066,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, clang_type = m_ast.CreateEnumerationType( type_name_cstr, GetClangDeclContextContainingDIE(die, nullptr), - decl, enumerator_clang_type); + decl, enumerator_clang_type, is_scoped); } else { enumerator_clang_type = m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()); @@ -2741,8 +2755,6 @@ bool DWARFASTParserClang::ParseChildMembers( form_value.BlockData() - debug_info_data.GetDataStart(); if (DWARFExpression::Evaluate( nullptr, // ExecutionContext * - nullptr, // ClangExpressionVariableList * - nullptr, // ClangExpressionDeclMap * nullptr, // RegisterContext * module_sp, debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, &initialValue, @@ -3214,11 +3226,11 @@ bool DWARFASTParserClang::ParseChildMembers( uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate( - nullptr, nullptr, nullptr, nullptr, module_sp, - debug_info_data, die.GetCU(), block_offset, - block_length, eRegisterKindDWARF, &initialValue, - nullptr, memberOffset, nullptr)) { + if (DWARFExpression::Evaluate(nullptr, nullptr, module_sp, + debug_info_data, die.GetCU(), + block_offset, block_length, + eRegisterKindDWARF, &initialValue, + nullptr, memberOffset, nullptr)) { member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); } } else { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp index 2507465750c7f..e04dc76d1dbe0 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp @@ -662,8 +662,6 @@ size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, form_value.BlockData() - debug_info_data.GetDataStart(); if (DWARFExpression::Evaluate( NULL, // ExecutionContext * - NULL, // ClangExpressionVariableList * - NULL, // ClangExpressionDeclMap * NULL, // RegisterContext * module_sp, debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, &initialValue, NULL, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 79b2acc4b4f38..5d7b12067263e 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -39,68 +39,48 @@ using namespace std; extern int g_verbose; DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data) - : m_dwarf2Data(dwarf2Data), m_abbrevs(NULL), m_user_data(NULL), - m_die_array(), m_func_aranges_ap(), m_base_addr(0), - m_offset(DW_INVALID_OFFSET), m_length(0), m_version(0), - m_addr_size(DWARFCompileUnit::GetDefaultAddressSize()), - m_producer(eProducerInvalid), m_producer_version_major(0), - m_producer_version_minor(0), m_producer_version_update(0), - m_language_type(eLanguageTypeUnknown), m_is_dwarf64(false), - m_is_optimized(eLazyBoolCalculate), m_addr_base(0), - m_ranges_base(0), m_base_obj_offset(DW_INVALID_OFFSET) {} + : m_dwarf2Data(dwarf2Data) {} DWARFCompileUnit::~DWARFCompileUnit() {} -void DWARFCompileUnit::Clear() { - m_offset = DW_INVALID_OFFSET; - m_length = 0; - m_version = 0; - m_abbrevs = NULL; - m_addr_size = DWARFCompileUnit::GetDefaultAddressSize(); - m_base_addr = 0; - m_die_array.clear(); - m_func_aranges_ap.reset(); - m_user_data = NULL; - m_producer = eProducerInvalid; - m_language_type = eLanguageTypeUnknown; - m_is_dwarf64 = false; - m_is_optimized = eLazyBoolCalculate; - m_addr_base = 0; - m_base_obj_offset = DW_INVALID_OFFSET; -} +DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data, + lldb::offset_t *offset_ptr) { + DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(dwarf2Data)); + // Out of memory? + if (cu_sp.get() == NULL) + return nullptr; -bool DWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr) { - Clear(); + const DWARFDataExtractor &debug_info = dwarf2Data->get_debug_info_data(); - m_offset = *offset_ptr; + cu_sp->m_offset = *offset_ptr; if (debug_info.ValidOffset(*offset_ptr)) { dw_offset_t abbr_offset; - const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev(); - m_length = debug_info.GetDWARFInitialLength(offset_ptr); - m_is_dwarf64 = debug_info.IsDWARF64(); - m_version = debug_info.GetU16(offset_ptr); + const DWARFDebugAbbrev *abbr = dwarf2Data->DebugAbbrev(); + cu_sp->m_length = debug_info.GetDWARFInitialLength(offset_ptr); + cu_sp->m_is_dwarf64 = debug_info.IsDWARF64(); + cu_sp->m_version = debug_info.GetU16(offset_ptr); abbr_offset = debug_info.GetDWARFOffset(offset_ptr); - m_addr_size = debug_info.GetU8(offset_ptr); + cu_sp->m_addr_size = debug_info.GetU8(offset_ptr); - bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset() - 1); - bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); + bool length_OK = + debug_info.ValidOffset(cu_sp->GetNextCompileUnitOffset() - 1); + bool version_OK = SymbolFileDWARF::SupportedVersion(cu_sp->m_version); bool abbr_offset_OK = - m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); - bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); + dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); + bool addr_size_OK = (cu_sp->m_addr_size == 4) || (cu_sp->m_addr_size == 8); if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL) { - m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); - return true; + cu_sp->m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); + return cu_sp; } // reset the offset to where we tried to parse from if anything went wrong - *offset_ptr = m_offset; + *offset_ptr = cu_sp->m_offset; } - return false; + return nullptr; } void DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) { @@ -620,6 +600,10 @@ void DWARFCompileUnit::Index(NameToDIE &func_basenames, NameToDIE &objc_class_selectors, NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) { + assert(!m_dwarf2Data->GetBaseCompileUnit() && + "DWARFCompileUnit associated with .dwo or .dwp " + "should not be indexed directly"); + Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 430251337575a..8ea0d6465adf4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -18,6 +18,8 @@ class NameToDIE; class SymbolFileDWARF; class SymbolFileDWARFDwo; +typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP; + class DWARFCompileUnit { public: enum Producer { @@ -28,39 +30,35 @@ public: eProcucerOther }; - DWARFCompileUnit(SymbolFileDWARF *dwarf2Data); + static DWARFCompileUnitSP Extract(SymbolFileDWARF *dwarf2Data, + lldb::offset_t *offset_ptr); ~DWARFCompileUnit(); - bool Extract(const lldb_private::DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr); size_t ExtractDIEsIfNeeded(bool cu_die_only); DWARFDIE LookupAddress(const dw_addr_t address); size_t AppendDIEsWithTag(const dw_tag_t tag, DWARFDIECollection &matching_dies, uint32_t depth = UINT32_MAX) const; - void Clear(); bool Verify(lldb_private::Stream *s) const; void Dump(lldb_private::Stream *s) const; + // Offset of the initial length field. dw_offset_t GetOffset() const { return m_offset; } lldb::user_id_t GetID() const; - uint32_t Size() const { - return m_is_dwarf64 ? 23 - : 11; /* Size in bytes of the compile unit header */ - } + // Size in bytes of the initial length + compile unit header. + uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; } bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); } dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); } dw_offset_t GetNextCompileUnitOffset() const { - return m_offset + m_length + (m_is_dwarf64 ? 12 : 4); + return m_offset + (m_is_dwarf64 ? 12 : 4) + m_length; } + // Size of the CU data (without initial length and without header). size_t GetDebugInfoSize() const { - return m_length + (m_is_dwarf64 ? 12 : 4) - Size(); /* Size in bytes of the - .debug_info data - associated with this - compile unit. */ + return (m_is_dwarf64 ? 12 : 4) + m_length - Size(); } + // Size of the CU data incl. header but without initial length. uint32_t GetLength() const { return m_length; } uint16_t GetVersion() const { return m_version; } const DWARFAbbreviationDeclarationSet *GetAbbreviations() const { @@ -165,7 +163,7 @@ protected: SymbolFileDWARF *m_dwarf2Data; std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file; const DWARFAbbreviationDeclarationSet *m_abbrevs; - void *m_user_data; + void *m_user_data = nullptr; DWARFDebugInfoEntry::collection m_die_array; // The compile unit debug information entry item std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap; // A table similar to @@ -174,23 +172,24 @@ protected: // points to the exact // DW_TAG_subprogram // DIEs - dw_addr_t m_base_addr; + dw_addr_t m_base_addr = 0; + // Offset of the initial length field. dw_offset_t m_offset; dw_offset_t m_length; uint16_t m_version; uint8_t m_addr_size; - Producer m_producer; - uint32_t m_producer_version_major; - uint32_t m_producer_version_minor; - uint32_t m_producer_version_update; - lldb::LanguageType m_language_type; + Producer m_producer = eProducerInvalid; + uint32_t m_producer_version_major = 0; + uint32_t m_producer_version_minor = 0; + uint32_t m_producer_version_update = 0; + lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown; bool m_is_dwarf64; - lldb_private::LazyBool m_is_optimized; - dw_addr_t m_addr_base; // Value of DW_AT_addr_base - dw_addr_t m_ranges_base; // Value of DW_AT_ranges_base - dw_offset_t m_base_obj_offset; // If this is a dwo compile unit this is the - // offset of the base compile unit in the main - // object file + lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate; + dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base + dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base + // If this is a dwo compile unit this is the offset of the base compile unit + // in the main object file + dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET; void ParseProducerInfo(); @@ -203,6 +202,8 @@ protected: NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces); private: + DWARFCompileUnit(SymbolFileDWARF *dwarf2Data); + const DWARFDebugInfoEntry *GetCompileUnitDIEPtrOnly() { ExtractDIEsIfNeeded(true); if (m_die_array.empty()) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 5222419d3233e..4ef2e772ea5d3 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -392,17 +392,11 @@ lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const { } bool DWARFDIE::HasChildren() const { - if (m_die) - return m_die->HasChildren(); - else - return false; + return m_die && m_die->HasChildren(); } bool DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type() const { - if (IsValid()) - return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu); - else - return false; + return IsValid() && GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu); } size_t DWARFDIE::GetAttributes(DWARFAttributes &attributes, @@ -464,5 +458,5 @@ bool operator==(const DWARFDIE &lhs, const DWARFDIE &rhs) { } bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs) { - return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU(); + return !(lhs == rhs); } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp index d681925daeacc..1cf0e7eeeb600 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp @@ -98,6 +98,21 @@ dw_uleb128_t DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential( } //---------------------------------------------------------------------- +// DWARFAbbreviationDeclarationSet::GetUnsupportedForms() +//---------------------------------------------------------------------- +void DWARFAbbreviationDeclarationSet::GetUnsupportedForms( + std::set<dw_form_t> &invalid_forms) const { + for (const auto &abbr_decl : m_decls) { + const size_t num_attrs = abbr_decl.NumAttributes(); + for (size_t i=0; i<num_attrs; ++i) { + dw_form_t form = abbr_decl.GetFormByIndex(i); + if (!DWARFFormValue::FormIsSupported(form)) + invalid_forms.insert(form); + } + } +} + +//---------------------------------------------------------------------- // Encode // // Encode the abbreviation table onto the end of the buffer provided @@ -175,3 +190,12 @@ DWARFDebugAbbrev::GetAbbreviationDeclarationSet( return &(pos->second); return NULL; } + +//---------------------------------------------------------------------- +// DWARFDebugAbbrev::GetUnsupportedForms() +//---------------------------------------------------------------------- +void DWARFDebugAbbrev::GetUnsupportedForms( + std::set<dw_form_t> &invalid_forms) const { + for (const auto &pair : m_abbrevCollMap) + pair.second.GetUnsupportedForms(invalid_forms); +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h index 137c81780513c..2bacb6349b6fc 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h @@ -41,6 +41,7 @@ public: // void Encode(BinaryStreamBuf& debug_abbrev_buf) const; dw_uleb128_t AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration &abbrevDecl); + void GetUnsupportedForms(std::set<dw_form_t> &invalid_forms) const; const DWARFAbbreviationDeclaration * GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const; @@ -65,6 +66,7 @@ public: GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const; void Dump(lldb_private::Stream *s) const; void Parse(const lldb_private::DWARFDataExtractor &data); + void GetUnsupportedForms(std::set<dw_form_t> &invalid_forms) const; protected: DWARFAbbreviationDeclarationCollMap m_abbrevCollMap; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index eff9850d435dd..9c0f1d3c89056 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -97,17 +97,8 @@ void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() { if (m_compile_units.empty()) { if (m_dwarf2Data != NULL) { lldb::offset_t offset = 0; - const DWARFDataExtractor &debug_info_data = - m_dwarf2Data->get_debug_info_data(); - while (debug_info_data.ValidOffset(offset)) { - DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data)); - // Out of memory? - if (cu_sp.get() == NULL) - break; - - if (cu_sp->Extract(debug_info_data, &offset) == false) - break; - + DWARFCompileUnitSP cu_sp; + while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, &offset))) { m_compile_units.push_back(cu_sp); offset = cu_sp->GetNextCompileUnitOffset(); @@ -248,12 +239,10 @@ void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback, if (dwarf2Data) { lldb::offset_t offset = 0; uint32_t depth = 0; - DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data)); - if (cu.get() == NULL) - return; DWARFDebugInfoEntry die; - while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset)) { + DWARFCompileUnitSP cu; + while ((cu = DWARFCompileUnit::Extract(dwarf2Data, &offset))) { const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset(); depth = 0; @@ -288,12 +277,6 @@ void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback, if (!dwarf2Data->get_debug_info_data().ValidOffset(offset)) break; - // See if during the callback anyone retained a copy of the compile - // unit other than ourselves and if so, let whomever did own the object - // and create a new one for our own use! - if (!cu.unique()) - cu.reset(new DWARFCompileUnit(dwarf2Data)); - // Make sure we start on a proper offset = next_cu_offset; } @@ -507,80 +490,3 @@ void DWARFDebugInfo::Dump(Stream *s, const uint32_t die_offset, die.Dump(s, recurse_depth); } } - -//---------------------------------------------------------------------- -// FindCallbackString -// -// A callback function for the static DWARFDebugInfo::Parse() function -// that gets called each time a compile unit header or debug information -// entry is successfully parsed. -// -// This function will find the die_offset of any items whose DW_AT_name -// matches the given string -//---------------------------------------------------------------------- -typedef struct FindCallbackStringInfoTag { - const char *name; - bool ignore_case; - RegularExpression *regex; - vector<dw_offset_t> &die_offsets; -} FindCallbackStringInfo; - -static dw_offset_t -FindCallbackString(SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu, - DWARFDebugInfoEntry *die, const dw_offset_t next_offset, - const uint32_t curr_depth, void *userData) { - FindCallbackStringInfo *info = (FindCallbackStringInfo *)userData; - - if (!die) - return next_offset; - - const char *die_name = die->GetName(dwarf2Data, cu); - if (!die_name) - return next_offset; - - if (info->regex) { - if (info->regex->Execute(llvm::StringRef(die_name))) - info->die_offsets.push_back(die->GetOffset()); - } else { - if ((info->ignore_case ? strcasecmp(die_name, info->name) - : strcmp(die_name, info->name)) == 0) - info->die_offsets.push_back(die->GetOffset()); - } - - // Just return the current offset to parse the next CU or DIE entry - return next_offset; -} - -//---------------------------------------------------------------------- -// Find -// -// Finds all DIE that have a specific DW_AT_name attribute by manually -// searching through the debug information (not using the -// .debug_pubnames section). The string must match the entire name -// and case sensitive searches are an option. -//---------------------------------------------------------------------- -bool DWARFDebugInfo::Find(const char *name, bool ignore_case, - vector<dw_offset_t> &die_offsets) const { - die_offsets.clear(); - if (name && name[0]) { - FindCallbackStringInfo info = {name, ignore_case, NULL, die_offsets}; - DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); - } - return !die_offsets.empty(); -} - -//---------------------------------------------------------------------- -// Find -// -// Finds all DIE that have a specific DW_AT_name attribute by manually -// searching through the debug information (not using the -// .debug_pubnames section). The string must match the supplied regular -// expression. -//---------------------------------------------------------------------- -bool DWARFDebugInfo::Find(RegularExpression &re, - vector<dw_offset_t> &die_offsets) const { - die_offsets.clear(); - FindCallbackStringInfo info = {NULL, false, &re, die_offsets}; - DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); - return !die_offsets.empty(); -} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index be4e18b12be0b..14c7d767d05b4 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -50,10 +50,6 @@ public: static void Verify(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data); static void Dump(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data, const uint32_t die_offset, const uint32_t recurse_depth); - bool Find(const char *name, bool ignore_case, - std::vector<dw_offset_t> &die_offsets) const; - bool Find(lldb_private::RegularExpression &re, - std::vector<dw_offset_t> &die_offsets) const; enum { eDumpFlag_Verbose = (1 << 0), // Verbose dumping @@ -65,8 +61,6 @@ public: DWARFDebugAranges &GetCompileUnitAranges(); protected: - typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP; - static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset, const DWARFCompileUnitSP &cu_sp); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 8d87c201eceb2..f595bd83d8469 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -161,9 +161,9 @@ bool DWARFDebugInfoEntry::FastExtract( case DW_FORM_strp: case DW_FORM_sec_offset: if (cu->IsDWARF64()) - debug_info_data.GetU64(offset_ptr); + debug_info_data.GetU64(&offset); else - debug_info_data.GetU32(offset_ptr); + debug_info_data.GetU32(&offset); break; default: @@ -325,9 +325,9 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data, case DW_FORM_strp: case DW_FORM_sec_offset: if (cu->IsDWARF64()) - debug_info_data.GetU64(offset_ptr); + debug_info_data.GetU64(&offset); else - debug_info_data.GetU32(offset_ptr); + debug_info_data.GetU32(&offset); break; default: @@ -1314,19 +1314,6 @@ bool DWARFDebugInfoEntry::AppendTypeName(SymbolFileDWARF *dwarf2Data, return false; } -bool DWARFDebugInfoEntry::Contains(const DWARFDebugInfoEntry *die) const { - if (die) { - const dw_offset_t die_offset = die->GetOffset(); - if (die_offset > GetOffset()) { - const DWARFDebugInfoEntry *sibling = GetSibling(); - assert(sibling); // TODO: take this out - if (sibling) - return die_offset < sibling->GetOffset(); - } - } - return false; -} - //---------------------------------------------------------------------- // BuildAddressRangeTable //---------------------------------------------------------------------- diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 15abac77a475d..89450d327adfd 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -60,18 +60,6 @@ public: m_empty_children(false), m_abbr_idx(0), m_has_children(false), m_tag(0) {} - void Clear() { - m_offset = DW_INVALID_OFFSET; - m_parent_idx = 0; - m_sibling_idx = 0; - m_empty_children = false; - m_abbr_idx = 0; - m_has_children = false; - m_tag = 0; - } - - bool Contains(const DWARFDebugInfoEntry *die) const; - void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, DWARFDebugAranges *debug_aranges) const; @@ -211,8 +199,6 @@ public: dw_offset_t GetOffset() const { return m_offset; } - void SetOffset(dw_offset_t offset) { m_offset = offset; } - bool HasChildren() const { return m_has_children; } void SetHasChildren(bool b) { m_has_children = b; } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 515c083fedb08..a8c48b7f2f849 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -15,6 +15,18 @@ using namespace lldb_private; using namespace std; +static dw_addr_t GetBaseAddressMarker(uint32_t addr_size) { + switch(addr_size) { + case 2: + return 0xffff; + case 4: + return 0xffffffff; + case 8: + return 0xffffffffffffffff; + } + llvm_unreachable("GetBaseAddressMarker unsupported address size."); +} + DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {} DWARFDebugRanges::~DWARFDebugRanges() {} @@ -39,38 +51,27 @@ bool DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data, const DWARFDataExtractor &debug_ranges_data = dwarf2Data->get_debug_ranges_data(); uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); + dw_addr_t base_addr = 0; + dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size); while ( debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) { dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); + if (!begin && !end) { // End of range list break; } - // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits - // of ones - switch (addr_size) { - case 2: - if (begin == 0xFFFFull) - begin = LLDB_INVALID_ADDRESS; - break; - - case 4: - if (begin == 0xFFFFFFFFull) - begin = LLDB_INVALID_ADDRESS; - break; - case 8: - break; - - default: - llvm_unreachable("DWARFRangeList::Extract() unsupported address size."); + if (begin == base_addr_marker) { + base_addr = end; + continue; } // Filter out empty ranges if (begin < end) - range_list.Append(DWARFRangeList::Entry(begin, end - begin)); + range_list.Append(DWARFRangeList::Entry(begin + base_addr, end - begin)); } // Make sure we consumed at least something diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 0853671ee8749..a21e313c2f811 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -725,3 +725,39 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, } return -1; } + +bool DWARFFormValue::FormIsSupported(dw_form_t form) { + switch (form) { + case DW_FORM_addr: + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_string: + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_sdata: + case DW_FORM_strp: + case DW_FORM_udata: + case DW_FORM_ref_addr: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + case DW_FORM_indirect: + case DW_FORM_sec_offset: + case DW_FORM_exprloc: + case DW_FORM_flag_present: + case DW_FORM_ref_sig8: + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_addr_index: + return true; + default: + break; + } + return false; +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 8d6af3d65b331..2aa7460c49109 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -86,6 +86,7 @@ public: bool is_dwarf64); static int Compare(const DWARFFormValue &a, const DWARFFormValue &b); void Clear(); + static bool FormIsSupported(dw_form_t form); protected: const DWARFCompileUnit *m_cu; // Compile unit for this form diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ef18c2b5d3bab..f149ec354f08c 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -13,7 +13,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -22,6 +21,7 @@ #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/StreamString.h" #include "lldb/Utility/Timer.h" @@ -30,6 +30,7 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" +#include "lldb/Host/Symbols.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueProperties.h" @@ -53,7 +54,7 @@ #include "lldb/Target/Language.h" -#include "lldb/Utility/TaskPool.h" +#include "lldb/Host/TaskPool.h" #include "DWARFASTParser.h" #include "DWARFASTParserClang.h" @@ -71,6 +72,7 @@ #include "LogChannelDWARF.h" #include "SymbolFileDWARFDebugMap.h" #include "SymbolFileDWARFDwo.h" +#include "SymbolFileDWARFDwp.h" #include "llvm/Support/FileSystem.h" @@ -207,6 +209,10 @@ static const char *resolveCompDir(const char *path_from_dwarf) { return nullptr; } +DWARFCompileUnit *SymbolFileDWARF::GetBaseCompileUnit() { + return nullptr; +} + void SymbolFileDWARF::Initialize() { LogChannelDWARF::Initialize(); PluginManager::RegisterPlugin(GetPluginNameStatic(), @@ -435,13 +441,11 @@ void SymbolFileDWARF::InitializeObject() { ModuleSP module_sp(m_obj_file->GetModule()); if (module_sp) { const SectionList *section_list = module_sp->GetSectionList(); - const Section *section = + Section *section = section_list->FindSectionByName(GetDWARFMachOSegmentName()).get(); - // Memory map the DWARF mach-o segment so we have everything mmap'ed - // to keep our heap memory usage down. if (section) - m_obj_file->MemoryMapSectionData(section, m_dwarf_data); + m_obj_file->ReadSectionData(section, m_dwarf_data); } get_apple_names_data(); @@ -497,6 +501,21 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { if (section_list == NULL) return 0; + // On non Apple platforms we might have .debug_types debug info that + // is created by using "-fdebug-types-section". LLDB currently will try + // to load this debug info, but it causes crashes during debugging when + // types are missing since it doesn't know how to parse the info in + // the .debug_types type units. This causes all complex debug info + // types to be unresolved. Because this causes LLDB to crash and since + // it really doesn't provide a solid debuggiung experience, we should + // disable trying to debug this kind of DWARF until support gets + // added or deprecated. + if (section_list->FindSectionByName(ConstString(".debug_types"))) { + m_obj_file->GetModule()->ReportWarning( + "lldb doesn’t support .debug_types debug info"); + return 0; + } + uint64_t debug_abbrev_file_size = 0; uint64_t debug_info_file_size = 0; uint64_t debug_line_file_size = 0; @@ -517,6 +536,20 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { if (section) debug_abbrev_file_size = section->GetFileSize(); + DWARFDebugAbbrev *abbrev = DebugAbbrev(); + if (abbrev) { + std::set<dw_form_t> invalid_forms; + abbrev->GetUnsupportedForms(invalid_forms); + if (!invalid_forms.empty()) { + StreamString error; + error.Printf("unsupported DW_FORM value%s:", invalid_forms.size() > 1 ? "s" : ""); + for (auto form : invalid_forms) + error.Printf(" %#x", form); + m_obj_file->GetModule()->ReportWarning("%s", error.GetString().str().c_str()); + return 0; + } + } + section = section_list->FindSectionByType(eSectionTypeDWARFDebugLine, true) .get(); @@ -1539,6 +1572,16 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( if (!dwo_name) return nullptr; + SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile(); + if (dwp_symfile) { + uint64_t dwo_id = cu_die.GetAttributeValueAsUnsigned(this, &dwarf_cu, + DW_AT_GNU_dwo_id, 0); + std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile = + dwp_symfile->GetSymbolFileForDwoId(&dwarf_cu, dwo_id); + if (dwo_symfile) + return dwo_symfile; + } + FileSpec dwo_file(dwo_name, true); if (dwo_file.IsRelative()) { const char *comp_dir = cu_die.GetAttributeValueAsString( @@ -1600,7 +1643,29 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { } dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); - // printf ("Loading dwo = '%s'\n", dwo_path); + + // When LLDB loads "external" modules it looks at the + // presence of DW_AT_GNU_dwo_name. + // However, when the already created module + // (corresponding to .dwo itself) is being processed, + // it will see the presence of DW_AT_GNU_dwo_name + // (which contains the name of dwo file) and + // will try to call ModuleList::GetSharedModule again. + // In some cases (i.e. for empty files) Clang 4.0 + // generates a *.dwo file which has DW_AT_GNU_dwo_name, + // but no DW_AT_comp_dir. In this case the method + // ModuleList::GetSharedModule will fail and + // the warning will be printed. However, as one can notice + // in this case we don't actually need to try to load the already + // loaded module (corresponding to .dwo) so we simply skip it. + if (m_obj_file->GetFileSpec() + .GetFileNameExtension() + .GetStringRef() == "dwo" && + llvm::StringRef(m_obj_file->GetFileSpec().GetPath()) + .endswith(dwo_module_spec.GetFileSpec().GetPath())) { + continue; + } + Status error = ModuleList::GetSharedModule( dwo_module_spec, module_sp, NULL, NULL, NULL); if (!module_sp) { @@ -1640,9 +1705,8 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { const DWARFExpression &location = var_sp->LocationExpression(); Value location_result; Status error; - if (location.Evaluate(nullptr, nullptr, nullptr, - LLDB_INVALID_ADDRESS, nullptr, nullptr, - location_result, &error)) { + if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr, + nullptr, location_result, &error)) { if (location_result.GetValueType() == Value::eValueTypeFileAddress) { lldb::addr_t file_addr = @@ -4288,3 +4352,18 @@ DWARFExpression::LocationListFormat SymbolFileDWARF::GetLocationListFormat() const { return DWARFExpression::RegularLocationList; } + +SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() { + llvm::call_once(m_dwp_symfile_once_flag, [this]() { + ModuleSpec module_spec; + module_spec.GetFileSpec() = m_obj_file->GetFileSpec(); + module_spec.GetSymbolFileSpec() = + FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp", false); + FileSpec dwp_filespec = Symbols::LocateExecutableSymbolFile(module_spec); + if (dwp_filespec.Exists()) { + m_dwp_symfile = SymbolFileDWARFDwp::Create(GetObjectFile()->GetModule(), + dwp_filespec); + } + }); + return m_dwp_symfile.get(); +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 9b1eb1d76fea9..6902dc0333d2f 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -61,6 +61,7 @@ class DWARFDIECollection; class DWARFFormValue; class SymbolFileDWARFDebugMap; class SymbolFileDWARFDwo; +class SymbolFileDWARFDwp; #define DIE_IS_BEING_PARSED ((lldb_private::Type *)1) @@ -275,8 +276,8 @@ public: GetCompUnitForDWARFCompUnit(DWARFCompileUnit *dwarf_cu, uint32_t cu_idx = UINT32_MAX); - size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, - DIEArray &method_die_offsets); + virtual size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, + DIEArray &method_die_offsets); bool Supports_DW_AT_APPLE_objc_complete_type(DWARFCompileUnit *cu); @@ -298,6 +299,11 @@ public: GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die); + // For regular SymbolFileDWARF instances the method returns nullptr, + // for the instances of the subclass SymbolFileDWARFDwo + // the method returns a pointer to the base compile unit. + virtual DWARFCompileUnit *GetBaseCompileUnit(); + protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; @@ -391,14 +397,10 @@ protected: virtual lldb::TypeSP FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx); - lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( + virtual lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( const DWARFDIE &die, const lldb_private::ConstString &type_name, bool must_be_implementation); - lldb::TypeSP - FindCompleteObjCDefinitionType(const lldb_private::ConstString &type_name, - bool header_definition_ok); - lldb_private::Symbol * GetObjCClassSymbol(const lldb_private::ConstString &objc_class_name); @@ -464,8 +466,14 @@ protected: return m_forward_decl_clang_type_to_die; } + SymbolFileDWARFDwp *GetDwpSymbolFile(); + lldb::ModuleWP m_debug_map_module_wp; SymbolFileDWARFDebugMap *m_debug_map_symfile; + + llvm::once_flag m_dwp_symfile_once_flag; + std::unique_ptr<SymbolFileDWARFDwp> m_dwp_symfile; + lldb_private::DWARFDataExtractor m_dwarf_data; DWARFDataSegment m_data_debug_abbrev; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index c14ebd1628be6..17c188a41a773 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -61,6 +61,14 @@ SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit *dwarf_cu, } DWARFCompileUnit *SymbolFileDWARFDwo::GetCompileUnit() { + // A clang module is found via a skeleton CU, but is not a proper DWO. + // Clang modules have a .debug_info section instead of the *_dwo variant. + if (auto *section_list = m_obj_file->GetSectionList(false)) + if (auto section_sp = + section_list->FindSectionByType(eSectionTypeDWARFDebugInfo, true)) + if (!section_sp->GetName().GetStringRef().endswith("dwo")) + return nullptr; + // Only dwo files with 1 compile unit is supported if (GetNumCompileUnits() == 1) return DebugInfo()->GetCompileUnitAtIndex(0); @@ -91,6 +99,12 @@ SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie() { return GetBaseSymbolFile()->GetForwardDeclClangTypeToDie(); } +size_t SymbolFileDWARFDwo::GetObjCMethodDIEOffsets( + lldb_private::ConstString class_name, DIEArray &method_die_offsets) { + return GetBaseSymbolFile()->GetObjCMethodDIEOffsets( + class_name, method_die_offsets); +} + UniqueDWARFASTTypeMap &SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() { return GetBaseSymbolFile()->GetUniqueDWARFASTTypeMap(); } @@ -101,6 +115,17 @@ lldb::TypeSP SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext( die_decl_ctx); } +lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE( + const DWARFDIE &die, const lldb_private::ConstString &type_name, + bool must_be_implementation) { + return GetBaseSymbolFile()->FindCompleteObjCDefinitionTypeForDIE( + die, type_name, must_be_implementation); +} + +DWARFCompileUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() { + return m_base_dwarf_cu; +} + SymbolFileDWARF *SymbolFileDWARFDwo::GetBaseSymbolFile() { return m_base_dwarf_cu->GetSymbolFileDWARF(); } diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 8cd67a2b24247..b67967aafab26 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -33,6 +33,9 @@ public: lldb_private::DWARFExpression::LocationListFormat GetLocationListFormat() const override; + size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, + DIEArray &method_die_offsets) override; + lldb_private::TypeSystem * GetTypeSystemForLanguage(lldb::LanguageType language) override; @@ -45,6 +48,8 @@ public: return nullptr; } + DWARFCompileUnit *GetBaseCompileUnit() override; + protected: void LoadSectionData(lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data) override; @@ -62,6 +67,10 @@ protected: lldb::TypeSP FindDefinitionTypeForDWARFDeclContext( const DWARFDeclContext &die_decl_ctx) override; + lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE( + const DWARFDIE &die, const lldb_private::ConstString &type_name, + bool must_be_implementation) override; + SymbolFileDWARF *GetBaseSymbolFile(); lldb::ObjectFileSP m_obj_file_sp; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp new file mode 100644 index 0000000000000..f6de1818eae08 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp @@ -0,0 +1,36 @@ +//===-- SymbolFileDWARFDwoDwp.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolFileDWARFDwoDwp.h" + +#include "lldb/Core/Section.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/LLDBAssert.h" + +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" + +using namespace lldb; +using namespace lldb_private; + +SymbolFileDWARFDwoDwp::SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile, + ObjectFileSP objfile, + DWARFCompileUnit *dwarf_cu, + uint64_t dwo_id) + : SymbolFileDWARFDwo(objfile, dwarf_cu), m_dwp_symfile(dwp_symfile), + m_dwo_id(dwo_id) {} + +void SymbolFileDWARFDwoDwp::LoadSectionData(lldb::SectionType sect_type, + DWARFDataExtractor &data) { + if (m_dwp_symfile->LoadSectionData(m_dwo_id, sect_type, data)) + return; + + SymbolFileDWARF::LoadSectionData(sect_type, data); +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h new file mode 100644 index 0000000000000..00ad7aafd96b0 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h @@ -0,0 +1,34 @@ +//===-- SymbolFileDWARFDwoDwp.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARFDwoDwp_SymbolFileDWARFDwoDwp_h_ +#define SymbolFileDWARFDwoDwp_SymbolFileDWARFDwoDwp_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "SymbolFileDWARFDwo.h" +#include "SymbolFileDWARFDwp.h" + +class SymbolFileDWARFDwoDwp : public SymbolFileDWARFDwo { +public: + SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile, + lldb::ObjectFileSP objfile, DWARFCompileUnit *dwarf_cu, + uint64_t dwo_id); + +protected: + void LoadSectionData(lldb::SectionType sect_type, + lldb_private::DWARFDataExtractor &data) override; + + SymbolFileDWARFDwp *m_dwp_symfile; + uint64_t m_dwo_id; +}; + +#endif // SymbolFileDWARFDwoDwp_SymbolFileDWARFDwoDwp_h_ diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp new file mode 100644 index 0000000000000..1dc1dab34a5c4 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp @@ -0,0 +1,142 @@ +//===-- SymbolFileDWARFDwp.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolFileDWARFDwp.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" + +#include "SymbolFileDWARFDwoDwp.h" + +static llvm::DWARFSectionKind +lldbSectTypeToLlvmSectionKind(lldb::SectionType type) { + switch (type) { + case lldb::eSectionTypeDWARFDebugInfo: + return llvm::DW_SECT_INFO; + // case lldb::eSectionTypeDWARFDebugTypes: + // return llvm::DW_SECT_TYPES; + case lldb::eSectionTypeDWARFDebugAbbrev: + return llvm::DW_SECT_ABBREV; + case lldb::eSectionTypeDWARFDebugLine: + return llvm::DW_SECT_LINE; + case lldb::eSectionTypeDWARFDebugLoc: + return llvm::DW_SECT_LOC; + case lldb::eSectionTypeDWARFDebugStrOffsets: + return llvm::DW_SECT_STR_OFFSETS; + // case lldb::eSectionTypeDWARFDebugMacinfo: + // return llvm::DW_SECT_MACINFO; + case lldb::eSectionTypeDWARFDebugMacro: + return llvm::DW_SECT_MACRO; + default: + // Note: 0 is an invalid dwarf section kind. + return llvm::DWARFSectionKind(0); + } +} + +std::unique_ptr<SymbolFileDWARFDwp> +SymbolFileDWARFDwp::Create(lldb::ModuleSP module_sp, + const lldb_private::FileSpec &file_spec) { + const lldb::offset_t file_offset = 0; + lldb::DataBufferSP file_data_sp; + lldb::offset_t file_data_offset = 0; + lldb::ObjectFileSP obj_file = lldb_private::ObjectFile::FindPlugin( + module_sp, &file_spec, file_offset, file_spec.GetByteSize(), file_data_sp, + file_data_offset); + if (obj_file == nullptr) + return nullptr; + + std::unique_ptr<SymbolFileDWARFDwp> dwp_symfile( + new SymbolFileDWARFDwp(module_sp, obj_file)); + + lldb_private::DWARFDataExtractor debug_cu_index; + if (!dwp_symfile->LoadRawSectionData(lldb::eSectionTypeDWARFDebugCuIndex, + debug_cu_index)) + return nullptr; + + llvm::DataExtractor llvm_debug_cu_index( + llvm::StringRef(debug_cu_index.PeekCStr(0), debug_cu_index.GetByteSize()), + debug_cu_index.GetByteOrder() == lldb::eByteOrderLittle, + debug_cu_index.GetAddressByteSize()); + if (!dwp_symfile->m_debug_cu_index.parse(llvm_debug_cu_index)) + return nullptr; + dwp_symfile->InitDebugCUIndexMap(); + return dwp_symfile; +} + +void SymbolFileDWARFDwp::InitDebugCUIndexMap() { + m_debug_cu_index_map.clear(); + for (const auto &entry : m_debug_cu_index.getRows()) + m_debug_cu_index_map.emplace(entry.getSignature(), &entry); +} + +SymbolFileDWARFDwp::SymbolFileDWARFDwp(lldb::ModuleSP module_sp, + lldb::ObjectFileSP obj_file) + : m_obj_file(std::move(obj_file)), m_debug_cu_index(llvm::DW_SECT_INFO) +{} + +std::unique_ptr<SymbolFileDWARFDwo> +SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu, + uint64_t dwo_id) { + return std::unique_ptr<SymbolFileDWARFDwo>( + new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id)); +} + +bool SymbolFileDWARFDwp::LoadSectionData( + uint64_t dwo_id, lldb::SectionType sect_type, + lldb_private::DWARFDataExtractor &data) { + lldb_private::DWARFDataExtractor section_data; + if (!LoadRawSectionData(sect_type, section_data)) + return false; + + auto it = m_debug_cu_index_map.find(dwo_id); + if (it == m_debug_cu_index_map.end()) + return false; + + auto *offsets = + it->second->getOffset(lldbSectTypeToLlvmSectionKind(sect_type)); + if (offsets) { + data.SetData(section_data, offsets->Offset, offsets->Length); + } else { + data.SetData(section_data, 0, section_data.GetByteSize()); + } + return true; +} + +bool SymbolFileDWARFDwp::LoadRawSectionData( + lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data) { + std::lock_guard<std::mutex> lock(m_sections_mutex); + + auto it = m_sections.find(sect_type); + if (it != m_sections.end()) { + if (it->second.GetByteSize() == 0) + return false; + + data = it->second; + return true; + } + + const lldb_private::SectionList *section_list = + m_obj_file->GetSectionList(false /* update_module_section_list */); + if (section_list) { + lldb::SectionSP section_sp( + section_list->FindSectionByType(sect_type, true)); + if (section_sp) { + if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) { + m_sections[sect_type] = data; + return true; + } + } + } + m_sections[sect_type].Clear(); + return false; +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h new file mode 100644 index 0000000000000..a7372b9358b16 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h @@ -0,0 +1,55 @@ +//===-- SymbolFileDWARFDwp.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARFDwp_SymbolFileDWARFDwp_h_ +#define SymbolFileDWARFDwp_SymbolFileDWARFDwp_h_ + +// C Includes +// C++ Includes +#include <memory> + +// Other libraries and framework includes +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" + +// Project includes +#include "lldb/Core/Module.h" + +#include "DWARFDataExtractor.h" +#include "SymbolFileDWARFDwo.h" + +class SymbolFileDWARFDwp { +public: + static std::unique_ptr<SymbolFileDWARFDwp> + Create(lldb::ModuleSP module_sp, const lldb_private::FileSpec &file_spec); + + std::unique_ptr<SymbolFileDWARFDwo> + GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu, uint64_t dwo_id); + + bool LoadSectionData(uint64_t dwo_id, lldb::SectionType sect_type, + lldb_private::DWARFDataExtractor &data); + +private: + explicit SymbolFileDWARFDwp(lldb::ModuleSP module_sp, + lldb::ObjectFileSP obj_file); + + bool LoadRawSectionData(lldb::SectionType sect_type, + lldb_private::DWARFDataExtractor &data); + + void InitDebugCUIndexMap(); + + lldb::ObjectFileSP m_obj_file; + + std::mutex m_sections_mutex; + std::map<lldb::SectionType, lldb_private::DWARFDataExtractor> m_sections; + + llvm::DWARFUnitIndex m_debug_cu_index; + std::map<uint64_t, const llvm::DWARFUnitIndex::Entry *> m_debug_cu_index_map; +}; + +#endif // SymbolFileDWARFDwp_SymbolFileDWARFDwp_h_ |