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 @@ -15,10 +15,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 @@ -27,46 +32,87 @@ public: enum Section : uint8_t { DebugInfo, DebugTypes }; - DIERef(llvm::Optional dwo_num, Section section, - dw_offset_t die_offset) - : m_dwo_num(dwo_num.getValueOr(0)), m_dwo_num_valid(bool(dwo_num)), + // 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_data(dwo_num.getValueOr(0) | main_cu.getValueOr(0)), + m_data_kind(dwo_num ? DwoKind + : (main_cu ? (dwz_common == MainDwz ? MainDwzKind + : DwzCommonKind) + : NoneKind)), m_section(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_dwo_num_valid) - return m_dwo_num; + if (m_data_kind == DwoKind) + return m_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_data_kind == MainDwzKind || m_data_kind == DwzCommonKind) + return m_data; return llvm::None; } + DwzCommon dwz_common() const { + assert(m_data_kind == MainDwzKind || m_data_kind == DwzCommonKind); + return m_data_kind == MainDwzKind ? MainDwz : CommonDwz; + } + + Kind kind_get() const { return Kind(m_data_kind); } + Section section() const { return static_cast
(m_section); } dw_offset_t die_offset() const { return m_die_offset; } bool operator<(DIERef other) const { - if (m_dwo_num_valid != other.m_dwo_num_valid) - return m_dwo_num_valid < other.m_dwo_num_valid; - if (m_dwo_num_valid && (m_dwo_num != other.m_dwo_num)) - return m_dwo_num < other.m_dwo_num; + if (m_data_kind != other.m_data_kind) + return m_data_kind < other.m_data_kind; + if (m_data_kind != NoneKind && (m_data != other.m_data)) + return m_data < other.m_data; if (m_section != other.m_section) return m_section < other.m_section; return m_die_offset < other.m_die_offset; } bool operator==(DIERef other) const { - if (m_dwo_num_valid != other.m_dwo_num_valid || - m_section != other.m_section || m_die_offset != other.m_die_offset) - return false; - if (m_dwo_num_valid && m_dwo_num != other.m_dwo_num) - return false; - return true; + if (m_data_kind != other.m_data_kind) + return m_data_kind == other.m_data_kind; + if (m_data_kind != NoneKind && (m_data != other.m_data)) + return m_data == other.m_data; + if (m_section != other.m_section) + return m_section == other.m_section; + return m_die_offset == other.m_die_offset; } private: - uint32_t m_dwo_num : 30; - uint32_t m_dwo_num_valid : 1; - uint32_t m_section : 1; + uint32_t m_data : 29; + uint32_t m_data_kind : 2; // Kind type + uint32_t m_section : 1; // Section type dw_offset_t m_die_offset; }; static_assert(sizeof(DIERef) == 8, ""); 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 @@ -27,8 +27,10 @@ if (m_cu == main_unit) main_unit = nullptr; - return DIERef(m_cu->GetSymbolFileDWARF().GetDwoNum(), m_cu->GetDebugSection(), - m_die->GetOffset()); + 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 @@ -52,8 +52,9 @@ cu = &cu->GetNonSkeletonUnit(); if (llvm::Optional die_offset = entry.getDIEUnitOffset()) - 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/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 @@ -1293,10 +1293,15 @@ // 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() <= 0x3fffffff); + 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().getValueOr(0)) << 32 | ref.die_offset() | - lldb::user_id_t(ref.dwo_num().hasValue()) << 62 | + 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 @@ -1323,8 +1328,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) @@ -1333,12 +1339,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 @@ -1612,7 +1620,7 @@ DWARFDIE SymbolFileDWARF::GetDIE(const DIERef &die_ref, DWARFUnit **main_unit_return) { 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()) @@ -1705,6 +1713,7 @@ if (dwo_obj_file == nullptr) return nullptr; + lldbassert(dwarf_cu->GetID() < 0x1fffffff); return std::make_shared(*this, dwo_obj_file, dwarf_cu->GetID()); } @@ -3950,7 +3959,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;