diff --git a/lldb/include/lldb/Core/dwarf.h b/lldb/include/lldb/Core/dwarf.h --- a/lldb/include/lldb/Core/dwarf.h +++ b/lldb/include/lldb/Core/dwarf.h @@ -30,11 +30,12 @@ // any addresses in the compile units that get // parsed -typedef uint32_t dw_offset_t; // Dwarf Debug Information Entry offset for any +typedef uint64_t dw_offset_t; // Dwarf Debug Information Entry offset for any // offset into the file /* Constants */ -#define DW_INVALID_OFFSET (~(dw_offset_t)0) +#define DW_DIE_OFFSET_MAX_BITSIZE 40 +#define DW_INVALID_OFFSET (((uint64_t)1u << DW_DIE_OFFSET_MAX_BITSIZE) - 1) #define DW_INVALID_INDEX 0xFFFFFFFFul // #define DW_ADDR_none 0x0 diff --git a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h --- a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h +++ b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -128,7 +128,7 @@ void GetFDEIndex(); - bool FDEToUnwindPlan(uint32_t offset, Address startaddr, + bool FDEToUnwindPlan(dw_offset_t offset, Address startaddr, UnwindPlan &unwind_plan); const CIE *GetCIE(dw_offset_t cie_offset); @@ -159,7 +159,7 @@ Type m_type; CIESP - ParseCIE(const uint32_t cie_offset); + ParseCIE(const dw_offset_t cie_offset); lldb::RegisterKind GetRegisterKind() const { return m_type == EH ? lldb::eRegisterKindEHFrame : lldb::eRegisterKindDWARF; 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 @@ -12,6 +12,7 @@ #include "lldb/Core/dwarf.h" #include "llvm/Support/FormatProviders.h" #include +#include #include #include @@ -29,8 +30,8 @@ DIERef(std::optional dwo_num, Section section, dw_offset_t die_offset) - : m_dwo_num(dwo_num.value_or(0)), m_dwo_num_valid(bool(dwo_num)), - m_section(section), m_die_offset(die_offset) { + : m_die_offset(die_offset), m_dwo_num(dwo_num.value_or(0)), + m_dwo_num_valid(bool(dwo_num)), m_section(section) { assert(this->dwo_num() == dwo_num && "Dwo number out of range?"); } @@ -85,11 +86,32 @@ /// void Encode(lldb_private::DataEncoder &encoder) const; + static constexpr uint64_t k_die_offset_bit_size = DW_DIE_OFFSET_MAX_BITSIZE; + static constexpr uint64_t k_dwo_num_bit_size = + 64 - DW_DIE_OFFSET_MAX_BITSIZE - /* size of control bits */ 2; + + static constexpr uint64_t k_dwo_num_valid_bit_shift_by = + k_dwo_num_bit_size + k_die_offset_bit_size; + static constexpr uint64_t k_dwo_num_valid_bit = + (1ull << k_dwo_num_valid_bit_shift_by); + static constexpr uint64_t k_section_bit_shift_by = + k_dwo_num_valid_bit_shift_by + 1; + static constexpr uint64_t k_section_bit = (1ull << k_section_bit_shift_by); + + static constexpr uint64_t + k_dwo_num_mask = (~0ull) >> (64 - k_dwo_num_bit_size); // 0x1fffff; + static constexpr uint64_t k_die_offset_mask = (~0ull) >> + (64 - k_die_offset_bit_size); + private: - uint32_t m_dwo_num : 30; - uint32_t m_dwo_num_valid : 1; - uint32_t m_section : 1; - dw_offset_t m_die_offset; + // Allow 2TB of .debug_info/.debug_types offset + dw_offset_t m_die_offset : k_die_offset_bit_size; + // Used for DWO index or for .o file index on mac + dw_offset_t m_dwo_num : k_dwo_num_bit_size; + // Set to 1 if m_file_index is a DWO number + dw_offset_t m_dwo_num_valid : 1; + // Set to 0 for .debug_info 1 for .debug_types, + dw_offset_t m_section : 1; }; 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 @@ -10,6 +10,7 @@ #include "lldb/Utility/DataEncoder.h" #include "lldb/Utility/DataExtractor.h" #include "llvm/Support/Format.h" +#include #include using namespace lldb; @@ -23,34 +24,29 @@ OS << "/" << format_hex_no_prefix(ref.die_offset(), 8); } -constexpr uint32_t k_dwo_num_mask = 0x3FFFFFFF; -constexpr uint32_t k_dwo_num_valid_bitmask = (1u << 30); -constexpr uint32_t k_section_bitmask = (1u << 31); - std::optional DIERef::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr) { - const uint32_t bitfield_storage = data.GetU32(offset_ptr); - uint32_t dwo_num = bitfield_storage & k_dwo_num_mask; - bool dwo_num_valid = (bitfield_storage & (k_dwo_num_valid_bitmask)) != 0; - Section section = (Section)((bitfield_storage & (k_section_bitmask)) != 0); + const uint64_t bitfield_storage = data.GetU64(offset_ptr); + uint32_t dwo_num = + (bitfield_storage >> k_die_offset_bit_size) & k_dwo_num_mask; + bool dwo_num_valid = (bitfield_storage & (k_dwo_num_valid_bit)) != 0; + Section section = (Section)((bitfield_storage & (k_section_bit)) != 0); // DIE offsets can't be zero and if we fail to decode something from data, // it will return 0 - dw_offset_t die_offset = data.GetU32(offset_ptr); + dw_offset_t die_offset = bitfield_storage & DIERef::k_die_offset_mask; if (die_offset == 0) return std::nullopt; if (dwo_num_valid) return DIERef(dwo_num, section, die_offset); - else - return DIERef(std::nullopt, section, die_offset); + + return DIERef(std::nullopt, section, die_offset); } void DIERef::Encode(DataEncoder &encoder) const { - uint32_t bitfield_storage = m_dwo_num; - if (m_dwo_num_valid) - bitfield_storage |= k_dwo_num_valid_bitmask; - if (m_section) - bitfield_storage |= k_section_bitmask; - encoder.AppendU32(bitfield_storage); - static_assert(sizeof(m_die_offset) == 4, "m_die_offset must be 4 bytes"); - encoder.AppendU32(m_die_offset); + uint64_t bitfield_storage = + uint64_t(m_dwo_num) << k_die_offset_bit_size | m_die_offset | + uint64_t(m_dwo_num_valid) << DIERef::k_dwo_num_valid_bit_shift_by | + uint64_t(section() == DIERef::Section::DebugTypes) + << DIERef::k_dwo_num_valid_bit_shift_by; + encoder.AppendU64(bitfield_storage); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -136,7 +136,7 @@ }); uint32_t idx = std::distance(m_units.begin(), pos); if (idx == 0) - return DW_INVALID_OFFSET; + return DW_INVALID_INDEX; return idx - 1; } 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 @@ -12,6 +12,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Threading.h" +#include "DIERef.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -1398,12 +1399,15 @@ user_id_t SymbolFileDWARF::GetUID(DIERef ref) { if (GetDebugMapSymfile()) - return GetID() | ref.die_offset(); + return GetDebugMapSymfile()->GetUID({*this, ref}); - lldbassert(GetDwoNum().value_or(0) <= 0x3fffffff); - return user_id_t(GetDwoNum().value_or(0)) << 32 | ref.die_offset() | - lldb::user_id_t(GetDwoNum().has_value()) << 62 | - lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) << 63; + lldbassert(ref.dwo_num().value_or(0) <= DIERef::k_dwo_num_mask); + return user_id_t(ref.dwo_num().value_or(0)) << DIERef::k_die_offset_bit_size | + ref.die_offset() | + lldb::user_id_t(ref.dwo_num().has_value()) + << DIERef::k_dwo_num_valid_bit_shift_by | + lldb::user_id_t(ref.section() == DIERef::Section::DebugTypes) + << DIERef::k_section_bit_shift_by; } std::optional @@ -1419,10 +1423,7 @@ // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF // instance. if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile()) { - SymbolFileDWARF *dwarf = debug_map->GetSymbolFileByOSOIndex( - debug_map->GetOSOIndexFromUserID(uid)); - return DecodedUID{ - *dwarf, {std::nullopt, DIERef::Section::DebugInfo, dw_offset_t(uid)}}; + return debug_map->DecodeUID(uid); } dw_offset_t die_offset = uid; if (die_offset == DW_INVALID_OFFSET) @@ -1432,9 +1433,9 @@ uid >> 63 ? DIERef::Section::DebugTypes : DIERef::Section::DebugInfo; std::optional dwo_num; - bool dwo_valid = uid >> 62 & 1; + bool dwo_valid = uid & DIERef::k_dwo_num_valid_bit; if (dwo_valid) - dwo_num = uid >> 32 & 0x3fffffff; + dwo_num = uid >> DW_DIE_OFFSET_MAX_BITSIZE & DIERef::k_dwo_num_mask; return DecodedUID{*this, {dwo_num, section, die_offset}}; } @@ -1694,7 +1695,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() == DIERef::k_dwo_num_mask ? m_dwp_symfile.get() : this->DebugInfo() .GetUnitAtIndex(*die_ref.dwo_num()) @@ -3184,7 +3185,8 @@ return 0; size_t functions_added = 0; - const dw_offset_t function_die_offset = func.GetID(); + const dw_offset_t function_die_offset = + func.GetID() & DIERef::k_die_offset_mask; DWARFDIE function_die = dwarf_cu->GetNonSkeletonUnit().GetDIE(function_die_offset); if (function_die) { @@ -4160,8 +4162,8 @@ dwp_file_data_offset); if (!dwp_obj_file) return; - m_dwp_symfile = - std::make_shared(*this, dwp_obj_file, 0x3fffffff); + m_dwp_symfile = std::make_shared( + *this, dwp_obj_file, DIERef::k_dwo_num_mask); } }); return m_dwp_symfile; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -17,9 +17,9 @@ #include #include +#include "SymbolFileDWARF.h" #include "UniqueDWARFASTType.h" -class SymbolFileDWARF; class DWARFCompileUnit; class DWARFDebugAranges; class DWARFDeclContext; @@ -208,9 +208,9 @@ /// the given index contains. lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; - static uint32_t GetOSOIndexFromUserID(lldb::user_id_t uid) { - return (uint32_t)((uid >> 32ull) - 1ull); - } + lldb::user_id_t GetUID(SymbolFileDWARF::DecodedUID decoded_uid); + + std::optional DecodeUID(lldb::user_id_t uid); static SymbolFileDWARF *GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -211,7 +211,7 @@ // Set the ID of the symbol file DWARF to the index of the OSO // shifted left by 32 bits to provide a unique prefix for any // UserID's that get created in the symbol file. - oso_symfile->SetID(((uint64_t)m_cu_idx + 1ull) << 32ull); + oso_symfile->SetID(m_cu_idx + 1); } return symfile; } @@ -773,6 +773,29 @@ return 0; } +namespace { +uint32_t GetOSOIndexFromUserID(lldb::user_id_t uid) { + return static_cast((uid >> DW_DIE_OFFSET_MAX_BITSIZE) - 1); +} +} // namespace + +user_id_t +SymbolFileDWARFDebugMap::GetUID(SymbolFileDWARF::DecodedUID decoded_uid) { + return ((static_cast(decoded_uid.dwarf.GetID()) + 1) + << DW_DIE_OFFSET_MAX_BITSIZE) | + decoded_uid.ref.die_offset(); +} + +std::optional +SymbolFileDWARFDebugMap::DecodeUID(user_id_t uid) { + if (SymbolFileDWARF *dwarf = + GetSymbolFileByOSOIndex(GetOSOIndexFromUserID(uid))) { + return SymbolFileDWARF::DecodedUID{ + *dwarf, {std::nullopt, DIERef::Section::DebugInfo, dw_offset_t(uid)}}; + } + return std::nullopt; +} + Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) { std::lock_guard guard(GetModuleMutex()); const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -41,7 +41,7 @@ DWARFDIE GetDIE(const DIERef &die_ref) override; - std::optional GetDwoNum() override { return GetID() >> 32; } + std::optional GetDwoNum() override { return GetID(); } lldb::offset_t GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -29,7 +29,7 @@ : SymbolFileDWARF(objfile, objfile->GetSectionList( /*update_module_section_list*/ false)), m_base_symbol_file(base_symbol_file) { - SetID(user_id_t(id) << 32); + SetID(id); // Parsing of the dwarf unit index is not thread-safe, so we need to prime it // to enable subsequent concurrent lookups. @@ -42,7 +42,7 @@ if (auto *unit_contrib = entry->getContribution()) return llvm::dyn_cast_or_null( DebugInfo().GetUnitAtOffset(DIERef::Section::DebugInfo, - unit_contrib->getOffset32())); + unit_contrib->getOffset())); } return nullptr; } diff --git a/lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s b/lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s --- a/lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s +++ b/lldb/test/Shell/SymbolFile/DWARF/DW_AT_range-DW_FORM_sec_offset.s @@ -8,7 +8,7 @@ # RUN: -o exit | FileCheck %s # Failure was the block range 1..2 was not printed plus: -# error: DW_AT_range-DW_FORM_sec_offset.s.tmp {0x0000003f}: DIE has DW_AT_ranges(0xc) attribute, but range extraction failed (missing or invalid range list table), please file a bug and attach the file at the start of this error message +# error: DW_AT_range-DW_FORM_sec_offset.s.tmp {0x000000000000003f}: DIE has DW_AT_ranges(0xc) attribute, but range extraction failed (missing or invalid range list table), please file a bug and attach the file at the start of this error message # CHECK-LABEL: image lookup -v -s lookup_rnglists # CHECK: Function: id = {0x00000029}, name = "rnglists", range = [0x0000000000000000-0x0000000000000003) diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -683,7 +683,7 @@ - AbbrCode: 0x1 Values: - CStr: "dwo_unit" - - Value: 0x01020304 + - Value: 0x0120304 - AbbrCode: 0x0 )";