From 2ccddfe3c68f6fff97e1627cfc25faf4fd7d10d1 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sun, 18 Mar 2018 20:09:02 +0000 Subject: [PATCH] DWARFUnit split out of DWARFCompileUnit DW_TAG_partial_unit for DWZ can be then presented by DWARFPartialUnit also inherited from DWARFUnit. Differential revision: https://reviews.llvm.org/D40466 llvm-svn: 327809 --- .../source/Plugins/SymbolFile/DWARF/CMakeLists.txt | 1 + .../Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp | 465 --------------- .../Plugins/SymbolFile/DWARF/DWARFCompileUnit.h | 102 +--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 630 +++++++++++++++++++++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h | 159 ++++++ 5 files changed, 796 insertions(+), 561 deletions(-) create mode 100644 lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp create mode 100644 lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt index 6544280..9ec7e28 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -23,6 +23,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN DWARFDIE.cpp DWARFDIECollection.cpp DWARFFormValue.cpp + DWARFUnit.cpp HashedNameToDIE.cpp LogChannelDWARF.cpp NameToDIE.cpp diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index c3890f0..e685be6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -9,7 +9,6 @@ #include "DWARFCompileUnit.h" -#include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" @@ -41,8 +40,6 @@ extern int g_verbose; DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data) : m_dwarf2Data(dwarf2Data) {} -DWARFCompileUnit::~DWARFCompileUnit() {} - DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data, lldb::offset_t *offset_ptr) { DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(dwarf2Data)); @@ -344,28 +341,6 @@ void DWARFCompileUnit::Dump(Stream *s) const { GetNextCompileUnitOffset()); } -static uint8_t g_default_addr_size = 4; - -uint8_t DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit *cu) { - if (cu) - return cu->GetAddressByteSize(); - return DWARFCompileUnit::GetDefaultAddressSize(); -} - -bool DWARFCompileUnit::IsDWARF64(const DWARFCompileUnit *cu) { - if (cu) - return cu->IsDWARF64(); - return false; -} - -uint8_t DWARFCompileUnit::GetDefaultAddressSize() { - return g_default_addr_size; -} - -void DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size) { - g_default_addr_size = addr_size; -} - lldb::user_id_t DWARFCompileUnit::GetID() const { dw_offset_t local_id = m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; @@ -516,47 +491,6 @@ DWARFCompileUnit::LookupAddress(const dw_addr_t address) { return DWARFDIE(); } -//---------------------------------------------------------------------- -// Compare function DWARFDebugAranges::Range structures -//---------------------------------------------------------------------- -static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, - const dw_offset_t die_offset) { - return die.GetOffset() < die_offset; -} - -//---------------------------------------------------------------------- -// GetDIE() -// -// Get the DIE (Debug Information Entry) with the specified offset by -// first checking if the DIE is contained within this compile unit and -// grabbing the DIE from this compile unit. Otherwise we grab the DIE -// from the DWARF file. -//---------------------------------------------------------------------- -DWARFDIE -DWARFCompileUnit::GetDIE(dw_offset_t die_offset) { - if (die_offset != DW_INVALID_OFFSET) { - if (m_dwo_symbol_file) - return m_dwo_symbol_file->GetCompileUnit()->GetDIE(die_offset); - - if (ContainsDIEOffset(die_offset)) { - ExtractDIEsIfNeeded(false); - DWARFDebugInfoEntry::iterator end = m_die_array.end(); - DWARFDebugInfoEntry::iterator pos = - lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset); - if (pos != end) { - if (die_offset == (*pos).GetOffset()) - return DWARFDIE(this, &(*pos)); - } - } else { - // Don't specify the compile unit offset as we don't know it because the - // DIE belongs to - // a different compile unit in the same symbol file. - return m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset); - } - } - return DWARFDIE(); // Not found -} - size_t DWARFCompileUnit::AppendDIEsWithTag(const dw_tag_t tag, DWARFDIECollection &dies, uint32_t depth) const { @@ -594,381 +528,6 @@ size_t DWARFCompileUnit::AppendDIEsWithTag(const dw_tag_t tag, // m_global_die_indexes.push_back (die - first_die); //} -void DWARFCompileUnit::Index(NameToDIE &func_basenames, - NameToDIE &func_fullnames, NameToDIE &func_methods, - NameToDIE &func_selectors, - 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) { - m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage( - log, - "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]", - GetOffset()); - } - - const LanguageType cu_language = GetLanguageType(); - DWARFFormValue::FixedFormSizes fixed_form_sizes = - DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), - m_is_dwarf64); - - IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames, - func_fullnames, func_methods, func_selectors, - objc_class_selectors, globals, types, namespaces); - - SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile(); - if (dwo_symbol_file) { - IndexPrivate(dwo_symbol_file->GetCompileUnit(), cu_language, - fixed_form_sizes, GetOffset(), func_basenames, func_fullnames, - func_methods, func_selectors, objc_class_selectors, globals, - types, namespaces); - } -} - -void DWARFCompileUnit::IndexPrivate( - DWARFCompileUnit *dwarf_cu, const LanguageType cu_language, - const DWARFFormValue::FixedFormSizes &fixed_form_sizes, - const dw_offset_t cu_offset, NameToDIE &func_basenames, - NameToDIE &func_fullnames, NameToDIE &func_methods, - NameToDIE &func_selectors, NameToDIE &objc_class_selectors, - NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) { - DWARFDebugInfoEntry::const_iterator pos; - DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin(); - DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end(); - for (pos = begin; pos != end; ++pos) { - const DWARFDebugInfoEntry &die = *pos; - - const dw_tag_t tag = die.Tag(); - - switch (tag) { - case DW_TAG_array_type: - case DW_TAG_base_type: - case DW_TAG_class_type: - case DW_TAG_constant: - case DW_TAG_enumeration_type: - case DW_TAG_inlined_subroutine: - case DW_TAG_namespace: - case DW_TAG_string_type: - case DW_TAG_structure_type: - case DW_TAG_subprogram: - case DW_TAG_subroutine_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - case DW_TAG_unspecified_type: - case DW_TAG_variable: - break; - - default: - continue; - } - - DWARFAttributes attributes; - const char *name = NULL; - const char *mangled_cstr = NULL; - bool is_declaration = false; - // bool is_artificial = false; - bool has_address = false; - bool has_location_or_const_value = false; - bool is_global_or_static_variable = false; - - DWARFFormValue specification_die_form; - const size_t num_attributes = - die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes); - if (num_attributes > 0) { - for (uint32_t i = 0; i < num_attributes; ++i) { - dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - switch (attr) { - case DW_AT_name: - if (attributes.ExtractFormValueAtIndex(i, form_value)) - name = form_value.AsCString(); - break; - - case DW_AT_declaration: - if (attributes.ExtractFormValueAtIndex(i, form_value)) - is_declaration = form_value.Unsigned() != 0; - break; - - // case DW_AT_artificial: - // if (attributes.ExtractFormValueAtIndex(i, - // form_value)) - // is_artificial = form_value.Unsigned() != 0; - // break; - - case DW_AT_MIPS_linkage_name: - case DW_AT_linkage_name: - if (attributes.ExtractFormValueAtIndex(i, form_value)) - mangled_cstr = form_value.AsCString(); - break; - - case DW_AT_low_pc: - case DW_AT_high_pc: - case DW_AT_ranges: - has_address = true; - break; - - case DW_AT_entry_pc: - has_address = true; - break; - - case DW_AT_location: - case DW_AT_const_value: - has_location_or_const_value = true; - if (tag == DW_TAG_variable) { - const DWARFDebugInfoEntry *parent_die = die.GetParent(); - while (parent_die != NULL) { - switch (parent_die->Tag()) { - case DW_TAG_subprogram: - case DW_TAG_lexical_block: - case DW_TAG_inlined_subroutine: - // Even if this is a function level static, we don't add it. We - // could theoretically - // add these if we wanted to by introspecting into the - // DW_AT_location and seeing - // if the location describes a hard coded address, but we dont - // want the performance - // penalty of that right now. - is_global_or_static_variable = false; - // if - // (attributes.ExtractFormValueAtIndex(dwarf2Data, - // i, form_value)) - // { - // // If we have valid block - // data, then we have location - // expression bytes - // // that are fixed (not a - // location list). - // const uint8_t *block_data = - // form_value.BlockData(); - // if (block_data) - // { - // uint32_t block_length = - // form_value.Unsigned(); - // if (block_length == 1 + - // attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) - // { - // if (block_data[0] == - // DW_OP_addr) - // add_die = true; - // } - // } - // } - parent_die = NULL; // Terminate the while loop. - break; - - case DW_TAG_compile_unit: - is_global_or_static_variable = true; - parent_die = NULL; // Terminate the while loop. - break; - - default: - parent_die = - parent_die->GetParent(); // Keep going in the while loop. - break; - } - } - } - break; - - case DW_AT_specification: - if (attributes.ExtractFormValueAtIndex(i, form_value)) - specification_die_form = form_value; - break; - } - } - } - - switch (tag) { - case DW_TAG_subprogram: - if (has_address) { - if (name) { - ObjCLanguage::MethodName objc_method(name, true); - if (objc_method.IsValid(true)) { - ConstString objc_class_name_with_category( - objc_method.GetClassNameWithCategory()); - ConstString objc_selector_name(objc_method.GetSelector()); - ConstString objc_fullname_no_category_name( - objc_method.GetFullNameWithoutCategory(true)); - ConstString objc_class_name_no_category(objc_method.GetClassName()); - func_fullnames.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); - if (objc_class_name_with_category) - objc_class_selectors.Insert(objc_class_name_with_category, - DIERef(cu_offset, die.GetOffset())); - if (objc_class_name_no_category && - objc_class_name_no_category != objc_class_name_with_category) - objc_class_selectors.Insert(objc_class_name_no_category, - DIERef(cu_offset, die.GetOffset())); - if (objc_selector_name) - func_selectors.Insert(objc_selector_name, - DIERef(cu_offset, die.GetOffset())); - if (objc_fullname_no_category_name) - func_fullnames.Insert(objc_fullname_no_category_name, - DIERef(cu_offset, die.GetOffset())); - } - // If we have a mangled name, then the DW_AT_name attribute - // is usually the method name without the class or any parameters - const DWARFDebugInfoEntry *parent = die.GetParent(); - bool is_method = false; - if (parent) { - dw_tag_t parent_tag = parent->Tag(); - if (parent_tag == DW_TAG_class_type || - parent_tag == DW_TAG_structure_type) { - is_method = true; - } else { - if (specification_die_form.IsValid()) { - DWARFDIE specification_die = - dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE( - DIERef(specification_die_form)); - if (specification_die.GetParent().IsStructOrClass()) - is_method = true; - } - } - } - - if (is_method) - func_methods.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); - else - func_basenames.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); - - if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) - func_fullnames.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); - } - if (mangled_cstr) { - // Make sure our mangled name isn't the same string table entry - // as our name. If it starts with '_', then it is ok, else compare - // the string to make sure it isn't the same and we don't end up - // with duplicate entries - if (name && name != mangled_cstr && - ((mangled_cstr[0] == '_') || - (::strcmp(name, mangled_cstr) != 0))) { - Mangled mangled(ConstString(mangled_cstr), true); - func_fullnames.Insert(mangled.GetMangledName(), - DIERef(cu_offset, die.GetOffset())); - ConstString demangled = mangled.GetDemangledName(cu_language); - if (demangled) - func_fullnames.Insert(demangled, - DIERef(cu_offset, die.GetOffset())); - } - } - } - break; - - case DW_TAG_inlined_subroutine: - if (has_address) { - if (name) - func_basenames.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); - if (mangled_cstr) { - // Make sure our mangled name isn't the same string table entry - // as our name. If it starts with '_', then it is ok, else compare - // the string to make sure it isn't the same and we don't end up - // with duplicate entries - if (name && name != mangled_cstr && - ((mangled_cstr[0] == '_') || - (::strcmp(name, mangled_cstr) != 0))) { - Mangled mangled(ConstString(mangled_cstr), true); - func_fullnames.Insert(mangled.GetMangledName(), - DIERef(cu_offset, die.GetOffset())); - ConstString demangled = mangled.GetDemangledName(cu_language); - if (demangled) - func_fullnames.Insert(demangled, - DIERef(cu_offset, die.GetOffset())); - } - } else - func_fullnames.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); - } - break; - - case DW_TAG_array_type: - case DW_TAG_base_type: - case DW_TAG_class_type: - case DW_TAG_constant: - case DW_TAG_enumeration_type: - case DW_TAG_string_type: - case DW_TAG_structure_type: - case DW_TAG_subroutine_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - case DW_TAG_unspecified_type: - if (name && !is_declaration) - types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); - if (mangled_cstr && !is_declaration) - types.Insert(ConstString(mangled_cstr), - DIERef(cu_offset, die.GetOffset())); - break; - - case DW_TAG_namespace: - if (name) - namespaces.Insert(ConstString(name), - DIERef(cu_offset, die.GetOffset())); - break; - - case DW_TAG_variable: - if (name && has_location_or_const_value && is_global_or_static_variable) { - globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); - // Be sure to include variables by their mangled and demangled - // names if they have any since a variable can have a basename - // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled - // mangled name "(anonymous namespace)::i"... - - // Make sure our mangled name isn't the same string table entry - // as our name. If it starts with '_', then it is ok, else compare - // the string to make sure it isn't the same and we don't end up - // with duplicate entries - if (mangled_cstr && name != mangled_cstr && - ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { - Mangled mangled(ConstString(mangled_cstr), true); - globals.Insert(mangled.GetMangledName(), - DIERef(cu_offset, die.GetOffset())); - ConstString demangled = mangled.GetDemangledName(cu_language); - if (demangled) - globals.Insert(demangled, DIERef(cu_offset, die.GetOffset())); - } - } - break; - - default: - continue; - } - } -} - -bool DWARFCompileUnit::Supports_unnamed_objc_bitfields() { - if (GetProducer() == eProducerClang) { - const uint32_t major_version = GetProducerVersionMajor(); - if (major_version > 425 || - (major_version == 425 && GetProducerVersionUpdate() >= 13)) - return true; - else - return false; - } - return true; // Assume all other compilers didn't have incorrect ObjC bitfield - // info -} - -bool DWARFCompileUnit::Supports_DW_AT_APPLE_objc_complete_type() { - if (GetProducer() == eProducerLLVMGCC) - return false; - return true; -} - -bool DWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid() { - // llvm-gcc makes completely invalid decl file attributes and won't ever - // be fixed, so we need to know to ignore these. - return GetProducer() == eProducerLLVMGCC; -} - void DWARFCompileUnit::ParseProducerInfo() { m_producer_version_major = UINT32_MAX; m_producer_version_minor = UINT32_MAX; @@ -1036,19 +595,6 @@ uint32_t DWARFCompileUnit::GetProducerVersionUpdate() { return m_producer_version_update; } -LanguageType DWARFCompileUnit::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(val); - } -} - LanguageType DWARFCompileUnit::GetLanguageType() { if (m_language_type != eLanguageTypeUnknown) return m_language_type; @@ -1060,8 +606,6 @@ LanguageType DWARFCompileUnit::GetLanguageType() { return m_language_type; } -bool DWARFCompileUnit::IsDWARF64() const { return m_is_dwarf64; } - bool DWARFCompileUnit::GetIsOptimized() { if (m_is_optimized == eLazyBoolCalculate) { const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); @@ -1080,11 +624,6 @@ bool DWARFCompileUnit::GetIsOptimized() { } } -DWARFFormValue::FixedFormSizes DWARFCompileUnit::GetFixedFormSizes() { - return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), - IsDWARF64()); -} - TypeSystem *DWARFCompileUnit::GetTypeSystem() { if (m_dwarf2Data) return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType()); @@ -1105,7 +644,3 @@ void DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base, m_ranges_base = ranges_base; m_base_obj_offset = base_obj_offset; } - -lldb::ByteOrder DWARFCompileUnit::GetByteOrder() const { - return m_dwarf2Data->GetObjectFile()->GetByteOrder(); -} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 748d717..1e56a6c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -10,29 +10,16 @@ #ifndef SymbolFileDWARF_DWARFCompileUnit_h_ #define SymbolFileDWARF_DWARFCompileUnit_h_ -#include "DWARFDIE.h" -#include "DWARFDebugInfoEntry.h" -#include "lldb/lldb-enumerations.h" - -class NameToDIE; -class SymbolFileDWARF; -class SymbolFileDWARFDwo; +#include "DWARFUnit.h" typedef std::shared_ptr DWARFCompileUnitSP; -enum DWARFProducer { - eProducerInvalid = 0, - eProducerClang, - eProducerGCC, - eProducerLLVMGCC, - eProcucerOther -}; +class DWARFCompileUnit : public DWARFUnit { + friend class DWARFUnit; -class DWARFCompileUnit { public: static DWARFCompileUnitSP Extract(SymbolFileDWARF *dwarf2Data, lldb::offset_t *offset_ptr); - ~DWARFCompileUnit(); size_t ExtractDIEsIfNeeded(bool cu_die_only); DWARFDIE LookupAddress(const dw_addr_t address); @@ -41,47 +28,15 @@ public: uint32_t depth = UINT32_MAX) const; 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; - // 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_is_dwarf64 ? 12 : 4) + m_length; - } - // Size of the CU data (without initial length and without header). - size_t GetDebugInfoSize() const { - 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 { - return m_abbrevs; - } dw_offset_t GetAbbrevOffset() const; - uint8_t GetAddressByteSize() const { return m_addr_size; } - dw_addr_t GetBaseAddress() const { return m_base_addr; } - dw_addr_t GetAddrBase() const { return m_addr_base; } - dw_addr_t GetRangesBase() const { return m_ranges_base; } void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base, dw_offset_t base_obj_offset); void ClearDIEs(bool keep_compile_unit_die); void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data, DWARFDebugAranges *debug_aranges); - lldb::ByteOrder GetByteOrder() const; - lldb_private::TypeSystem *GetTypeSystem(); - DWARFFormValue::FixedFormSizes GetFixedFormSizes(); - - void SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } - DWARFDIE GetCompileUnitDIEOnly() { return DWARFDIE(this, GetCompileUnitDIEPtrOnly()); } @@ -105,38 +60,10 @@ public: void AddCompileUnitDIE(DWARFDebugInfoEntry &die); - bool HasDIEsParsed() const { return m_die_array.size() > 1; } - - DWARFDIE - GetDIE(dw_offset_t die_offset); - - static uint8_t GetAddressByteSize(const DWARFCompileUnit *cu); - - static bool IsDWARF64(const DWARFCompileUnit *cu); - - static uint8_t GetDefaultAddressSize(); - - static void SetDefaultAddressSize(uint8_t addr_size); - - void *GetUserData() const { return m_user_data; } - void SetUserData(void *d); - bool Supports_DW_AT_APPLE_objc_complete_type(); - - bool DW_AT_decl_file_attributes_are_invalid(); - - bool Supports_unnamed_objc_bitfields(); - - void Index(NameToDIE &func_basenames, NameToDIE &func_fullnames, - NameToDIE &func_methods, NameToDIE &func_selectors, - NameToDIE &objc_class_selectors, NameToDIE &globals, - NameToDIE &types, NameToDIE &namespaces); - const DWARFDebugAranges &GetFunctionAranges(); - SymbolFileDWARF *GetSymbolFileDWARF() const { return m_dwarf2Data; } - DWARFProducer GetProducer(); uint32_t GetProducerVersionMajor(); @@ -145,21 +72,14 @@ public: uint32_t GetProducerVersionUpdate(); - static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val); - lldb::LanguageType GetLanguageType(); - bool IsDWARF64() const; - bool GetIsOptimized(); - SymbolFileDWARFDwo *GetDwoSymbolFile() const { - return m_dwo_symbol_file.get(); - } - - dw_offset_t GetBaseObjOffset() const { return m_base_obj_offset; } - protected: + virtual DWARFCompileUnit &Data() override { return *this; } + virtual const DWARFCompileUnit &Data() const override { return *this; } + SymbolFileDWARF *m_dwarf2Data; std::unique_ptr m_dwo_symbol_file; const DWARFAbbreviationDeclarationSet *m_abbrevs; @@ -173,8 +93,6 @@ protected: // DW_TAG_subprogram // DIEs 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; @@ -193,14 +111,6 @@ protected: void ParseProducerInfo(); - static void - IndexPrivate(DWARFCompileUnit *dwarf_cu, const lldb::LanguageType cu_language, - const DWARFFormValue::FixedFormSizes &fixed_form_sizes, - const dw_offset_t cu_offset, NameToDIE &func_basenames, - NameToDIE &func_fullnames, NameToDIE &func_methods, - NameToDIE &func_selectors, NameToDIE &objc_class_selectors, - NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces); - private: DWARFCompileUnit(SymbolFileDWARF *dwarf2Data); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp new file mode 100644 index 0000000..5af6fe6 --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -0,0 +1,630 @@ +//===-- DWARFUnit.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFUnit.h" + +#include "Plugins/Language/ObjC/ObjCLanguage.h" +#include "lldb/Core/Module.h" +#include "lldb/Symbol/ObjectFile.h" + +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" +#include "LogChannelDWARF.h" +#include "SymbolFileDWARFDwo.h" + +using namespace lldb; +using namespace lldb_private; +using namespace std; + +extern int g_verbose; + +DWARFUnit::DWARFUnit() {} + +DWARFUnit::~DWARFUnit() {} + +size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { + return Data().ExtractDIEsIfNeeded(cu_die_only); +} + +DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { + return Data().LookupAddress(address); +} + +size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, + DWARFDIECollection &dies, + uint32_t depth) const { + return Data().AppendDIEsWithTag(tag, dies, depth); +} + +bool DWARFUnit::Verify(Stream *s) const { + return Data().Verify(s); +} + +void DWARFUnit::Dump(Stream *s) const { + Data().Dump(s); +} + +lldb::user_id_t DWARFUnit::GetID() const { + return Data().GetID(); +} + +uint32_t DWARFUnit::Size() const { return IsDWARF64() ? 23 : 11; } + +dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { + return m_offset + (IsDWARF64() ? 12 : 4) + GetLength(); +} + +size_t DWARFUnit::GetDebugInfoSize() const { + return (IsDWARF64() ? 12 : 4) + GetLength() - Size(); +} + +uint32_t DWARFUnit::GetLength() const { return Data().m_length; } +uint16_t DWARFUnit::GetVersion() const { return Data().m_version; } + +const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { + return Data().m_abbrevs; +} + +dw_offset_t DWARFUnit::GetAbbrevOffset() const { + return Data().GetAbbrevOffset(); +} + +uint8_t DWARFUnit::GetAddressByteSize() const { return Data().m_addr_size; } + +dw_addr_t DWARFUnit::GetBaseAddress() const { return Data().m_base_addr; } + +dw_addr_t DWARFUnit::GetAddrBase() const { return Data().m_addr_base; } + +dw_addr_t DWARFUnit::GetRangesBase() const { return Data().m_ranges_base; } + +void DWARFUnit::SetAddrBase(dw_addr_t addr_base, + dw_addr_t ranges_base, + dw_offset_t base_obj_offset) { + Data().SetAddrBase(addr_base, ranges_base, base_obj_offset); +} + +void DWARFUnit::ClearDIEs(bool keep_compile_unit_die) { + Data().ClearDIEs(keep_compile_unit_die); +} + +void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data, + DWARFDebugAranges *debug_aranges) { + Data().BuildAddressRangeTable(dwarf2Data, debug_aranges); +} + +lldb::ByteOrder DWARFUnit::GetByteOrder() const { + return Data().m_dwarf2Data->GetObjectFile()->GetByteOrder(); +} + +TypeSystem *DWARFUnit::GetTypeSystem() { + return Data().GetTypeSystem(); +} + +DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { + return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), + IsDWARF64()); +} + +void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { + Data().m_base_addr = base_addr; +} + +DWARFDIE DWARFUnit::GetCompileUnitDIEOnly() { + return Data().GetCompileUnitDIEOnly(); +} + +DWARFDIE DWARFUnit::DIE() { + return Data().DIE(); +} + +bool DWARFUnit::HasDIEsParsed() const { return Data().m_die_array.size() > 1; } + +//---------------------------------------------------------------------- +// Compare function DWARFDebugAranges::Range structures +//---------------------------------------------------------------------- +static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, + const dw_offset_t die_offset) { + return die.GetOffset() < die_offset; +} + +//---------------------------------------------------------------------- +// GetDIE() +// +// Get the DIE (Debug Information Entry) with the specified offset by +// first checking if the DIE is contained within this compile unit and +// grabbing the DIE from this compile unit. Otherwise we grab the DIE +// from the DWARF file. +//---------------------------------------------------------------------- +DWARFDIE +DWARFUnit::GetDIE(dw_offset_t die_offset) { + if (die_offset != DW_INVALID_OFFSET) { + if (GetDwoSymbolFile()) + return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); + + if (ContainsDIEOffset(die_offset)) { + ExtractDIEsIfNeeded(false); + DWARFDebugInfoEntry::iterator end = Data().m_die_array.end(); + DWARFDebugInfoEntry::iterator pos = lower_bound( + Data().m_die_array.begin(), end, die_offset, CompareDIEOffset); + if (pos != end) { + if (die_offset == (*pos).GetOffset()) + return DWARFDIE(&Data(), &(*pos)); + } + } else { + // Don't specify the compile unit offset as we don't know it because the + // DIE belongs to + // a different compile unit in the same symbol file. + return Data().m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset); + } + } + return DWARFDIE(); // Not found +} + +static uint8_t g_default_addr_size = 4; + +uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { + if (cu) + return cu->GetAddressByteSize(); + return DWARFCompileUnit::GetDefaultAddressSize(); +} + +bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { + if (cu) + return cu->IsDWARF64(); + return false; +} + +uint8_t DWARFUnit::GetDefaultAddressSize() { + return g_default_addr_size; +} + +void DWARFUnit::SetDefaultAddressSize(uint8_t addr_size) { + g_default_addr_size = addr_size; +} + +void *DWARFUnit::GetUserData() const { return Data().m_user_data; } + +void DWARFUnit::SetUserData(void *d) { + Data().SetUserData(d); +} + +bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { + if (GetProducer() == eProducerLLVMGCC) + return false; + return true; +} + +bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { + // llvm-gcc makes completely invalid decl file attributes and won't ever + // be fixed, so we need to know to ignore these. + return GetProducer() == eProducerLLVMGCC; +} + +bool DWARFUnit::Supports_unnamed_objc_bitfields() { + if (GetProducer() == eProducerClang) { + const uint32_t major_version = GetProducerVersionMajor(); + if (major_version > 425 || + (major_version == 425 && GetProducerVersionUpdate() >= 13)) + return true; + else + return false; + } + return true; // Assume all other compilers didn't have incorrect ObjC bitfield + // info +} + +SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { + return Data().m_dwarf2Data; +} + +DWARFProducer DWARFUnit::GetProducer() { + return Data().GetProducer(); +} + +uint32_t DWARFUnit::GetProducerVersionMajor() { + return Data().GetProducerVersionMajor(); +} + +uint32_t DWARFUnit::GetProducerVersionMinor() { + return Data().GetProducerVersionMinor(); +} + +uint32_t DWARFUnit::GetProducerVersionUpdate() { + return Data().GetProducerVersionUpdate(); +} + +LanguageType DWARFUnit::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(val); + } +} + +LanguageType DWARFUnit::GetLanguageType() { + return Data().GetLanguageType(); +} + +bool DWARFUnit::IsDWARF64() const { return Data().m_is_dwarf64; } + +bool DWARFUnit::GetIsOptimized() { + return Data().GetIsOptimized(); +} + +SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { + return Data().m_dwo_symbol_file.get(); +} + +dw_offset_t DWARFUnit::GetBaseObjOffset() const { + return Data().m_base_obj_offset; +} + +const DWARFDebugInfoEntry *DWARFUnit::GetCompileUnitDIEPtrOnly() { + return Data().GetCompileUnitDIEPtrOnly(); +} + +const DWARFDebugInfoEntry *DWARFUnit::DIEPtr() { + return Data().DIEPtr(); +} + +void DWARFUnit::Index(NameToDIE &func_basenames, + NameToDIE &func_fullnames, NameToDIE &func_methods, + NameToDIE &func_selectors, + NameToDIE &objc_class_selectors, + NameToDIE &globals, NameToDIE &types, + NameToDIE &namespaces) { + assert(!Data().m_dwarf2Data->GetBaseCompileUnit() && + "DWARFUnit associated with .dwo or .dwp " + "should not be indexed directly"); + + Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); + + if (log) { + Data().m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage( + log, + "DWARFUnit::Index() for compile unit at .debug_info[0x%8.8x]", + GetOffset()); + } + + const LanguageType cu_language = GetLanguageType(); + DWARFFormValue::FixedFormSizes fixed_form_sizes = + DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), + IsDWARF64()); + + IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames, + func_fullnames, func_methods, func_selectors, + objc_class_selectors, globals, types, namespaces); + + SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile(); + if (dwo_symbol_file) { + IndexPrivate( + dwo_symbol_file->GetCompileUnit(), cu_language, fixed_form_sizes, + GetOffset(), func_basenames, func_fullnames, func_methods, + func_selectors, objc_class_selectors, globals, types, namespaces); + } +} + +void DWARFUnit::IndexPrivate( + DWARFUnit *dwarf_cu, const LanguageType cu_language, + const DWARFFormValue::FixedFormSizes &fixed_form_sizes, + const dw_offset_t cu_offset, NameToDIE &func_basenames, + NameToDIE &func_fullnames, NameToDIE &func_methods, + NameToDIE &func_selectors, NameToDIE &objc_class_selectors, + NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) { + DWARFDebugInfoEntry::const_iterator pos; + DWARFDebugInfoEntry::const_iterator begin = + dwarf_cu->Data().m_die_array.begin(); + DWARFDebugInfoEntry::const_iterator end = dwarf_cu->Data().m_die_array.end(); + for (pos = begin; pos != end; ++pos) { + const DWARFDebugInfoEntry &die = *pos; + + const dw_tag_t tag = die.Tag(); + + switch (tag) { + case DW_TAG_array_type: + case DW_TAG_base_type: + case DW_TAG_class_type: + case DW_TAG_constant: + case DW_TAG_enumeration_type: + case DW_TAG_inlined_subroutine: + case DW_TAG_namespace: + case DW_TAG_string_type: + case DW_TAG_structure_type: + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + case DW_TAG_unspecified_type: + case DW_TAG_variable: + break; + + default: + continue; + } + + DWARFAttributes attributes; + const char *name = NULL; + const char *mangled_cstr = NULL; + bool is_declaration = false; + // bool is_artificial = false; + bool has_address = false; + bool has_location_or_const_value = false; + bool is_global_or_static_variable = false; + + DWARFFormValue specification_die_form; + const size_t num_attributes = + die.GetAttributes(&dwarf_cu->Data(), fixed_form_sizes, attributes); + if (num_attributes > 0) { + for (uint32_t i = 0; i < num_attributes; ++i) { + dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + switch (attr) { + case DW_AT_name: + if (attributes.ExtractFormValueAtIndex(i, form_value)) + name = form_value.AsCString(); + break; + + case DW_AT_declaration: + if (attributes.ExtractFormValueAtIndex(i, form_value)) + is_declaration = form_value.Unsigned() != 0; + break; + + // case DW_AT_artificial: + // if (attributes.ExtractFormValueAtIndex(i, + // form_value)) + // is_artificial = form_value.Unsigned() != 0; + // break; + + case DW_AT_MIPS_linkage_name: + case DW_AT_linkage_name: + if (attributes.ExtractFormValueAtIndex(i, form_value)) + mangled_cstr = form_value.AsCString(); + break; + + case DW_AT_low_pc: + case DW_AT_high_pc: + case DW_AT_ranges: + has_address = true; + break; + + case DW_AT_entry_pc: + has_address = true; + break; + + case DW_AT_location: + case DW_AT_const_value: + has_location_or_const_value = true; + if (tag == DW_TAG_variable) { + const DWARFDebugInfoEntry *parent_die = die.GetParent(); + while (parent_die != NULL) { + switch (parent_die->Tag()) { + case DW_TAG_subprogram: + case DW_TAG_lexical_block: + case DW_TAG_inlined_subroutine: + // Even if this is a function level static, we don't add it. We + // could theoretically + // add these if we wanted to by introspecting into the + // DW_AT_location and seeing + // if the location describes a hard coded address, but we dont + // want the performance + // penalty of that right now. + is_global_or_static_variable = false; + // if + // (attributes.ExtractFormValueAtIndex(dwarf2Data, + // i, form_value)) + // { + // // If we have valid block + // data, then we have location + // expression bytes + // // that are fixed (not a + // location list). + // const uint8_t *block_data = + // form_value.BlockData(); + // if (block_data) + // { + // uint32_t block_length = + // form_value.Unsigned(); + // if (block_length == 1 + + // attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) + // { + // if (block_data[0] == + // DW_OP_addr) + // add_die = true; + // } + // } + // } + parent_die = NULL; // Terminate the while loop. + break; + + case DW_TAG_compile_unit: + is_global_or_static_variable = true; + parent_die = NULL; // Terminate the while loop. + break; + + default: + parent_die = + parent_die->GetParent(); // Keep going in the while loop. + break; + } + } + } + break; + + case DW_AT_specification: + if (attributes.ExtractFormValueAtIndex(i, form_value)) + specification_die_form = form_value; + break; + } + } + } + + switch (tag) { + case DW_TAG_subprogram: + if (has_address) { + if (name) { + ObjCLanguage::MethodName objc_method(name, true); + if (objc_method.IsValid(true)) { + ConstString objc_class_name_with_category( + objc_method.GetClassNameWithCategory()); + ConstString objc_selector_name(objc_method.GetSelector()); + ConstString objc_fullname_no_category_name( + objc_method.GetFullNameWithoutCategory(true)); + ConstString objc_class_name_no_category(objc_method.GetClassName()); + func_fullnames.Insert(ConstString(name), + DIERef(cu_offset, die.GetOffset())); + if (objc_class_name_with_category) + objc_class_selectors.Insert(objc_class_name_with_category, + DIERef(cu_offset, die.GetOffset())); + if (objc_class_name_no_category && + objc_class_name_no_category != objc_class_name_with_category) + objc_class_selectors.Insert(objc_class_name_no_category, + DIERef(cu_offset, die.GetOffset())); + if (objc_selector_name) + func_selectors.Insert(objc_selector_name, + DIERef(cu_offset, die.GetOffset())); + if (objc_fullname_no_category_name) + func_fullnames.Insert(objc_fullname_no_category_name, + DIERef(cu_offset, die.GetOffset())); + } + // If we have a mangled name, then the DW_AT_name attribute + // is usually the method name without the class or any parameters + const DWARFDebugInfoEntry *parent = die.GetParent(); + bool is_method = false; + if (parent) { + dw_tag_t parent_tag = parent->Tag(); + if (parent_tag == DW_TAG_class_type || + parent_tag == DW_TAG_structure_type) { + is_method = true; + } else { + if (specification_die_form.IsValid()) { + DWARFDIE specification_die = + dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE( + DIERef(specification_die_form)); + if (specification_die.GetParent().IsStructOrClass()) + is_method = true; + } + } + } + + if (is_method) + func_methods.Insert(ConstString(name), + DIERef(cu_offset, die.GetOffset())); + else + func_basenames.Insert(ConstString(name), + DIERef(cu_offset, die.GetOffset())); + + if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) + func_fullnames.Insert(ConstString(name), + DIERef(cu_offset, die.GetOffset())); + } + if (mangled_cstr) { + // Make sure our mangled name isn't the same string table entry + // as our name. If it starts with '_', then it is ok, else compare + // the string to make sure it isn't the same and we don't end up + // with duplicate entries + if (name && name != mangled_cstr && + ((mangled_cstr[0] == '_') || + (::strcmp(name, mangled_cstr) != 0))) { + Mangled mangled(ConstString(mangled_cstr), true); + func_fullnames.Insert(mangled.GetMangledName(), + DIERef(cu_offset, die.GetOffset())); + ConstString demangled = mangled.GetDemangledName(cu_language); + if (demangled) + func_fullnames.Insert(demangled, + DIERef(cu_offset, die.GetOffset())); + } + } + } + break; + + case DW_TAG_inlined_subroutine: + if (has_address) { + if (name) + func_basenames.Insert(ConstString(name), + DIERef(cu_offset, die.GetOffset())); + if (mangled_cstr) { + // Make sure our mangled name isn't the same string table entry + // as our name. If it starts with '_', then it is ok, else compare + // the string to make sure it isn't the same and we don't end up + // with duplicate entries + if (name && name != mangled_cstr && + ((mangled_cstr[0] == '_') || + (::strcmp(name, mangled_cstr) != 0))) { + Mangled mangled(ConstString(mangled_cstr), true); + func_fullnames.Insert(mangled.GetMangledName(), + DIERef(cu_offset, die.GetOffset())); + ConstString demangled = mangled.GetDemangledName(cu_language); + if (demangled) + func_fullnames.Insert(demangled, + DIERef(cu_offset, die.GetOffset())); + } + } else + func_fullnames.Insert(ConstString(name), + DIERef(cu_offset, die.GetOffset())); + } + break; + + case DW_TAG_array_type: + case DW_TAG_base_type: + case DW_TAG_class_type: + case DW_TAG_constant: + case DW_TAG_enumeration_type: + case DW_TAG_string_type: + case DW_TAG_structure_type: + case DW_TAG_subroutine_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + case DW_TAG_unspecified_type: + if (name && !is_declaration) + types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); + if (mangled_cstr && !is_declaration) + types.Insert(ConstString(mangled_cstr), + DIERef(cu_offset, die.GetOffset())); + break; + + case DW_TAG_namespace: + if (name) + namespaces.Insert(ConstString(name), + DIERef(cu_offset, die.GetOffset())); + break; + + case DW_TAG_variable: + if (name && has_location_or_const_value && is_global_or_static_variable) { + globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); + // Be sure to include variables by their mangled and demangled + // names if they have any since a variable can have a basename + // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled + // mangled name "(anonymous namespace)::i"... + + // Make sure our mangled name isn't the same string table entry + // as our name. If it starts with '_', then it is ok, else compare + // the string to make sure it isn't the same and we don't end up + // with duplicate entries + if (mangled_cstr && name != mangled_cstr && + ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { + Mangled mangled(ConstString(mangled_cstr), true); + globals.Insert(mangled.GetMangledName(), + DIERef(cu_offset, die.GetOffset())); + ConstString demangled = mangled.GetDemangledName(cu_language); + if (demangled) + globals.Insert(demangled, DIERef(cu_offset, die.GetOffset())); + } + } + break; + + default: + continue; + } + } +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h new file mode 100644 index 0000000..0fb271f --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -0,0 +1,159 @@ +//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFUnit_h_ +#define SymbolFileDWARF_DWARFUnit_h_ + +#include "DWARFDIE.h" +#include "DWARFDebugInfoEntry.h" +#include "lldb/lldb-enumerations.h" + +class DWARFUnit; +class DWARFCompileUnit; +class NameToDIE; +class SymbolFileDWARF; +class SymbolFileDWARFDwo; + +typedef std::shared_ptr DWARFUnitSP; + +enum DWARFProducer { + eProducerInvalid = 0, + eProducerClang, + eProducerGCC, + eProducerLLVMGCC, + eProcucerOther +}; + +class DWARFUnit { +public: + virtual ~DWARFUnit(); + + 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; + 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; + // Size in bytes of the initial length + compile unit header. + uint32_t Size() const; + 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; + // Size of the CU data (without initial length and without header). + size_t GetDebugInfoSize() const; + // Size of the CU data incl. header but without initial length. + uint32_t GetLength() const; + uint16_t GetVersion() const; + const DWARFAbbreviationDeclarationSet *GetAbbreviations() const; + dw_offset_t GetAbbrevOffset() const; + uint8_t GetAddressByteSize() const; + dw_addr_t GetBaseAddress() const; + dw_addr_t GetAddrBase() const; + dw_addr_t GetRangesBase() const; + void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base, dw_offset_t base_obj_offset); + void ClearDIEs(bool keep_compile_unit_die); + void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data, + DWARFDebugAranges *debug_aranges); + + lldb::ByteOrder GetByteOrder() const; + + lldb_private::TypeSystem *GetTypeSystem(); + + DWARFFormValue::FixedFormSizes GetFixedFormSizes(); + + void SetBaseAddress(dw_addr_t base_addr); + + DWARFDIE + GetCompileUnitDIEOnly(); + + DWARFDIE + DIE(); + + bool HasDIEsParsed() const; + + DWARFDIE GetDIE(dw_offset_t die_offset); + + static uint8_t GetAddressByteSize(const DWARFUnit *cu); + + static bool IsDWARF64(const DWARFUnit *cu); + + static uint8_t GetDefaultAddressSize(); + + static void SetDefaultAddressSize(uint8_t addr_size); + + void *GetUserData() const; + + void SetUserData(void *d); + + bool Supports_DW_AT_APPLE_objc_complete_type(); + + bool DW_AT_decl_file_attributes_are_invalid(); + + bool Supports_unnamed_objc_bitfields(); + + void Index(NameToDIE &func_basenames, NameToDIE &func_fullnames, + NameToDIE &func_methods, NameToDIE &func_selectors, + NameToDIE &objc_class_selectors, NameToDIE &globals, + NameToDIE &types, NameToDIE &namespaces); + + SymbolFileDWARF *GetSymbolFileDWARF() const; + + DWARFProducer GetProducer(); + + uint32_t GetProducerVersionMajor(); + + uint32_t GetProducerVersionMinor(); + + uint32_t GetProducerVersionUpdate(); + + static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val); + + lldb::LanguageType GetLanguageType(); + + bool IsDWARF64() const; + + bool GetIsOptimized(); + + SymbolFileDWARFDwo *GetDwoSymbolFile() const; + + dw_offset_t GetBaseObjOffset() const; + +protected: + virtual DWARFCompileUnit &Data() = 0; + virtual const DWARFCompileUnit &Data() const = 0; + + DWARFUnit(); + + static void + IndexPrivate(DWARFUnit *dwarf_cu, const lldb::LanguageType cu_language, + const DWARFFormValue::FixedFormSizes &fixed_form_sizes, + const dw_offset_t cu_offset, NameToDIE &func_basenames, + NameToDIE &func_fullnames, NameToDIE &func_methods, + NameToDIE &func_selectors, NameToDIE &objc_class_selectors, + NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces); + + // Offset of the initial length field. + dw_offset_t m_offset; + +private: + const DWARFDebugInfoEntry *GetCompileUnitDIEPtrOnly(); + + const DWARFDebugInfoEntry *DIEPtr(); + + DISALLOW_COPY_AND_ASSIGN(DWARFUnit); +}; + +#endif // SymbolFileDWARF_DWARFUnit_h_ -- 2.7.4