diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h b/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h --- a/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -16,10 +16,15 @@ #include #include -/// Identifies a DWARF debug info entry within a given Module. It contains three -/// "coordinates": -/// - dwo_num: identifies the dwo file in the Module. If this field is not set, -/// the DIERef references the main file. +/// Identifies a DWARF debug info entry within a given Module. It contains +/// multiple "coordinates": +/// - dwo_num: -gsplit-dwarf only: identifies the dwo file in the Module. +/// If this field is not set, the DIERef references the main file. +/// - main_cu: DWZ only: index of main compilation unit which used +/// DW_TAG_imported_unit for this DIERef or some its parent. +/// For transitive imports this is the very first CU. +/// It is always a CU in the main file (and not DWZ common symbol file). +/// - DWZ common flag: DWZ only: the DIE is in a shared DWZ common symbol file. /// - section: identifies the section of the debug info entry in the given file: /// debug_info or debug_types. /// - die_offset: The offset of the debug info entry as an absolute offset from @@ -28,39 +33,75 @@ public: enum Section : uint8_t { DebugInfo, DebugTypes }; - DIERef(llvm::Optional dwo_num, Section section, - dw_offset_t die_offset) - : m_u(dwo_num, section), m_die_offset(die_offset) { + // DWZ only: Is the DIE located in DWZ common symbol file? + enum DwzCommon : uint8_t { MainDwz, CommonDwz }; + + enum Kind : uint8_t { + NoneKind, + + // DWZ only: The DIE is in DW_TAG_partial_unit in main symbol file and it + // needs main_cu. + MainDwzKind, + + // -gsplit-dwarf only: The DIE is in a separate dwo file specified by + // dwo_num. + DwoKind, + + // DWZ only: The DIE is in DW_TAG_partial_unit in DWZ common symbol file and + // it needs main_cu. + DwzCommonKind + }; + + DIERef(llvm::Optional dwo_num, llvm::Optional main_cu, + DwzCommon dwz_common, Section section, dw_offset_t die_offset) + : m_u(dwo_num, main_cu, dwz_common, section), m_die_offset(die_offset) { assert(this->dwo_num() == dwo_num && "Dwo number out of range?"); + assert(this->main_cu() == main_cu && "Main Cu number out of range?"); + assert(dwz_common == MainDwz || main_cu); } llvm::Optional dwo_num() const { - if (m_u.s.dwo_num_valid) - return m_u.s.dwo_num; + if (m_u.s.data_kind == DwoKind) + return m_u.s.data; return llvm::None; } + // It indexes DWARFCompileUnit's excl. DWARFTypeUnit's. + // It is the index used as parameter of SymbolFileDWARF::GetDWARFUnitIndex. + llvm::Optional main_cu() const { + if (m_u.s.data_kind == MainDwzKind || m_u.s.data_kind == DwzCommonKind) + return m_u.s.data; + return llvm::None; + } + + DwzCommon dwz_common() const { + assert(m_u.s.data_kind == MainDwzKind || m_u.s.data_kind == DwzCommonKind); + return m_u.s.data_kind == MainDwzKind ? MainDwz : CommonDwz; + } + + Kind kind_get() const { return Kind(m_u.s.data_kind); } + Section section() const { return static_cast
(m_u.s.section); } dw_offset_t die_offset() const { return m_die_offset; } bool operator<(DIERef other) const { - if (m_u.s.dwo_num_valid != other.m_u.s.dwo_num_valid) - return m_u.s.dwo_num_valid < other.m_u.s.dwo_num_valid; - // Assuming if not m_u.s.dwo_num_valid then m_u.s.dwo_num is zero. - if (m_u.s.dwo_num != other.m_u.s.dwo_num) - return m_u.s.dwo_num < other.m_u.s.dwo_num; + if (m_u.s.data_kind != other.m_u.s.data_kind) + return m_u.s.data_kind < other.m_u.s.data_kind; + // Assuming if m_u.s.data_kind == NoneKind then m_u.s.data is zero. + if (m_u.s.data != other.m_u.s.data) + return m_u.s.data < other.m_u.s.data; if (m_u.s.section != other.m_u.s.section) return m_u.s.section < other.m_u.s.section; return m_die_offset < other.m_die_offset; } bool operator==(DIERef other) const { - if (m_u.s.dwo_num_valid != other.m_u.s.dwo_num_valid) - return m_u.s.dwo_num_valid == other.m_u.s.dwo_num_valid; - // Assuming if not m_u.s.dwo_num_valid then m_u.s.dwo_num is zero. - if (m_u.s.dwo_num != other.m_u.s.dwo_num) - return m_u.s.dwo_num == other.m_u.s.dwo_num; + if (m_u.s.data_kind != other.m_u.s.data_kind) + return m_u.s.data_kind == other.m_u.s.data_kind; + // Assuming if m_u.s.data_kind == NoneKind then m_u.s.data is zero. + if (m_u.s.data != other.m_u.s.data) + return m_u.s.data == other.m_u.s.data; if (m_u.s.section != other.m_u.s.section) return m_u.s.section == other.m_u.s.section; return m_die_offset == other.m_die_offset; @@ -68,8 +109,9 @@ private: friend struct llvm::DenseMapInfo; - DIERef(unsigned unique) : m_u(llvm::None, DebugInfo), m_die_offset(0) { - m_u.s.dwo_num = unique; + DIERef(unsigned unique) + : m_u(llvm::None, llvm::None, MainDwz, DebugInfo), m_die_offset(0) { + m_u.s.data = unique; } uint32_t get_hash_value() const { return llvm::detail::combineHashValue(m_u.hash_bits, m_die_offset); @@ -77,16 +119,23 @@ union U { struct S { - uint32_t dwo_num : 30; - uint32_t dwo_num_valid : 1; - uint32_t section : 1; - S(llvm::Optional dwo_num_, Section section_) - : dwo_num(dwo_num_.getValueOr(0)), dwo_num_valid(bool(dwo_num_)), + uint32_t data : 29; + uint32_t data_kind : 2; // Kind type + uint32_t section : 1; // Section type + S(llvm::Optional dwo_num, llvm::Optional main_cu, + DwzCommon dwz_common, Section section_) + : data(dwo_num.getValueOr(0) | main_cu.getValueOr(0)), + data_kind(dwo_num + ? DwoKind + : (main_cu ? (dwz_common == MainDwz ? MainDwzKind + : DwzCommonKind) + : NoneKind)), section(section_) {} } s; uint32_t hash_bits; - U(llvm::Optional dwo_num, Section section) - : s(dwo_num, section) {} + U(llvm::Optional dwo_num, llvm::Optional main_cu, + DwzCommon dwz_common, Section section) + : s(dwo_num, main_cu, dwz_common, section) {} } m_u; dw_offset_t m_die_offset; }; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -13,6 +13,19 @@ StringRef Style) { if (ref.dwo_num()) OS << format_hex_no_prefix(*ref.dwo_num(), 8) << "/"; - OS << (ref.section() == DIERef::DebugInfo ? "INFO" : "TYPE"); + if (ref.main_cu()) + OS << format_hex_no_prefix(*ref.main_cu(), 8) << "/"; + OS << (ref.section() == DIERef::Section::DebugInfo ? "INFO" : "TYPE"); + switch (ref.kind_get()) { + case DIERef::Kind::NoneKind: + case DIERef::Kind::DwoKind: + break; + case DIERef::Kind::MainDwzKind: + OS << "/DWZ"; + break; + case DIERef::Kind::DwzCommonKind: + OS << "/DWZCOMMON"; + break; + } OS << "/" << format_hex_no_prefix(ref.die_offset(), 8); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp @@ -24,8 +24,17 @@ if (!IsValid()) return llvm::None; - return DIERef(m_cu->GetSymbolFileDWARF().GetDwoNum(), m_cu->GetDebugSection(), - m_die->GetOffset()); + DWARFUnit *main_unit = GetMainCU(); + + if (GetCU()->GetSymbolFileDWARF().GetDwoNum().hasValue()) + main_unit = nullptr; + if (GetCU().GetCU() == main_unit) + main_unit = nullptr; + + return DIERef( + m_cu->GetSymbolFileDWARF().GetDwoNum(), + (!main_unit ? llvm::None : llvm::Optional(main_unit->GetID())), + DIERef::MainDwz, m_cu->GetDebugSection(), m_die->GetOffset()); } dw_tag_t DWARFBaseDIE::Tag() const { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -53,8 +53,9 @@ cu = &cu->GetNonSkeletonUnit(); if (llvm::Optional die_offset = entry.getDIEUnitOffset()) // FIXME: .debug_names have no DWZ support yet. - return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(), - DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset); + return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(), llvm::None, + DIERef::MainDwz, DIERef::Section::DebugInfo, + cu->GetOffset() + *die_offset); return llvm::None; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h --- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -65,7 +65,8 @@ DIEInfo(dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h); explicit operator DIERef() const { - return DIERef(llvm::None, DIERef::Section::DebugInfo, die_offset); + return DIERef(llvm::None, llvm::None, DIERef::MainDwz, + DIERef::Section::DebugInfo, die_offset); } }; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -7,7 +7,9 @@ //===----------------------------------------------------------------------===// #include "NameToDIE.h" +#include "DWARFDebugInfo.h" #include "DWARFUnit.h" +#include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/RegularExpression.h" @@ -48,16 +50,24 @@ DWARFUnit &s_unit, llvm::function_ref callback) const { lldbassert(!s_unit.GetSymbolFileDWARF().GetDwoNum()); const DWARFUnit &ns_unit = s_unit.GetNonSkeletonUnit(); + SymbolFileDWARF *ns_symfile = &ns_unit.GetSymbolFileDWARF(); const uint32_t size = m_map.GetSize(); for (uint32_t i = 0; i < size; ++i) { const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(i); - if (ns_unit.GetSymbolFileDWARF().GetDwoNum() == die_ref.dwo_num() && - ns_unit.GetDebugSection() == die_ref.section() && - ns_unit.GetOffset() <= die_ref.die_offset() && - die_ref.die_offset() < ns_unit.GetNextUnitOffset()) { - if (!callback(die_ref)) - return; - } + if (ns_unit.GetDebugSection() != die_ref.section()) + continue; + if (die_ref.main_cu()) { + DWARFDebugInfo &ns_info = ns_symfile->DebugInfo(); + DWARFUnit *die_main_unit = ns_info.GetUnitAtIndex( + *ns_symfile->GetDWARFUnitIndex(*die_ref.main_cu())); + if (&ns_unit != die_main_unit) + continue; + } else if (!(ns_symfile->GetDwoNum() == die_ref.dwo_num() && + ns_unit.GetOffset() <= die_ref.die_offset() && + die_ref.die_offset() < ns_unit.GetNextUnitOffset())) + continue; + if (!callback(die_ref)) + return; } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -318,6 +318,8 @@ /// Same as GetLanguage() but reports all C++ versions as C++ (no version). static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit); + llvm::Optional GetDWARFUnitIndex(uint32_t cu_idx); + protected: typedef llvm::DenseMap DIERefToTypePtr; typedef llvm::DenseMap DIERefToVariableSP; @@ -471,7 +473,6 @@ } void BuildCuTranslationTable(); - llvm::Optional GetDWARFUnitIndex(uint32_t cu_idx); struct DecodedUID { SymbolFileDWARF &dwarf; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1341,10 +1341,31 @@ if (GetDebugMapSymfile()) return GetID() | ref.die_offset(); - lldbassert(GetDwoNum().getValueOr(0) <= 0x3fffffff); - return user_id_t(GetDwoNum().getValueOr(0)) << 32 | ref.die_offset() | - lldb::user_id_t(GetDwoNum().hasValue()) << 62 | - lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) << 63; +#ifndef NDEBUG + DWARFDIE dwarfdie_check = GetDIE(ref); + lldbassert(dwarfdie_check.IsValid()); + lldbassert(*dwarfdie_check.GetDIERef() == ref); +#endif + + // WARNING: Use ref.dwo_num() as GetDwoNum() may not be valid in 'this'. + static_assert(sizeof(ref.die_offset()) * 8 == 32, ""); + lldbassert(!ref.dwo_num().hasValue() || *ref.dwo_num() <= 0x1fffffff); + lldbassert(!ref.main_cu().hasValue() || *ref.main_cu() <= 0x1fffffff); + lldbassert(0 <= ref.kind_get()); + lldbassert(ref.kind_get() <= 3); + user_id_t retval = + user_id_t(ref.dwo_num() ? *ref.dwo_num() + : (ref.main_cu() ? *ref.main_cu() : 0)) + << 32 | + ref.die_offset() | user_id_t(ref.kind_get()) << 61 | + lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) << 63; + +#ifndef NDEBUG + DWARFDIE dwarfdie_check2 = GetDIE(retval); + lldbassert(dwarfdie_check2 == dwarfdie_check); +#endif + + return retval; } llvm::Optional @@ -1362,8 +1383,9 @@ if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) { SymbolFileDWARF *dwarf = debug_map->GetSymbolFileByOSOIndex( debug_map->GetOSOIndexFromUserID(uid)); - return DecodedUID{ - *dwarf, {llvm::None, DIERef::Section::DebugInfo, dw_offset_t(uid)}}; + return DecodedUID{*dwarf, + {llvm::None, llvm::None, DIERef::MainDwz, + DIERef::Section::DebugInfo, dw_offset_t(uid)}}; } dw_offset_t die_offset = uid; if (die_offset == DW_INVALID_OFFSET) @@ -1372,12 +1394,14 @@ DIERef::Section section = uid >> 63 ? DIERef::Section::DebugTypes : DIERef::Section::DebugInfo; + DIERef::Kind kind = DIERef::Kind(uid >> 61 & 3); + llvm::Optional dwo_num; - bool dwo_valid = uid >> 62 & 1; - if (dwo_valid) - dwo_num = uid >> 32 & 0x3fffffff; + if (kind == DIERef::Kind::DwoKind) + dwo_num = uid >> 32 & 0x1fffffff; - return DecodedUID{*this, {dwo_num, section, die_offset}}; + return DecodedUID{ + *this, {dwo_num, llvm::None, DIERef::MainDwz, section, die_offset}}; } DWARFDIE @@ -1639,7 +1663,7 @@ DWARFDIE SymbolFileDWARF::GetDIE(const DIERef &die_ref) { if (die_ref.dwo_num()) { - SymbolFileDWARF *dwarf = *die_ref.dwo_num() == 0x3fffffff + SymbolFileDWARF *dwarf = *die_ref.dwo_num() == 0x1fffffff ? m_dwp_symfile.get() : this->DebugInfo() .GetUnitAtIndex(*die_ref.dwo_num()) @@ -1728,6 +1752,7 @@ if (dwo_obj_file == nullptr) return nullptr; + lldbassert(dwarf_cu->GetID() < 0x1fffffff); return std::make_shared(*this, dwo_obj_file, dwarf_cu->GetID()); } @@ -3870,7 +3895,7 @@ if (!dwp_obj_file) return; m_dwp_symfile = - std::make_shared(*this, dwp_obj_file, 0x3fffffff); + std::make_shared(*this, dwp_obj_file, 0x1fffffff); } }); return m_dwp_symfile;