Author: labath Date: Thu Jun 13 04:22:47 2019 New Revision: 363250 URL: http://llvm.org/viewvc/llvm-project?rev=363250&view=rev Log: DWARF: Don't create lldb CompileUnits for DWARF type units
Summary: Type units don't represent actual compilations and a lot of the operations that we do with lldb compile units (getting their line tables, variables, etc.) don't make sense for them. There is also a lot more of them (sometimes over 100x), so making them more lightweight pays off. The main change in this patch is that we stop creating lldb CompileUnits for DWARF type units. The trickiest part here is that the SymbolFile interface requires that we assign consecutive sequence IDs to the compile units we create. As DWARF type and compile units can come in any order (in v5), this means we can no longer use 1-1 mapping between DWARF and lldb compile units. Instead I build a translation table between the two indices. To avoid pessimizing the case where there are no type units, I build the translation table only in case we have at least one type unit. Additionaly, I also tried to strenghted type safete by replacing DWARFUnit with DWARFCompileUnit where applicable. Though that was not stricly necessary, I found it a good way to ensure that the transformations I am doing here make sense. In the places where I was changing the function signatures, and where it was obvious that the objects being handled were not null, I also replaced pointers with references. There shouldn't be any major functional change with this patch. The only change I observed is that now the types in the type units will not be parsed when one calls Module::ParseAllDebugSymbols, unless they are referenced from other compile units. This makes sense, given how ParseAllDebugSymbols is implemented (it iterates over all compile units), and it only matters for one hand-writted test where I did not bother to reference the types from the compile units (which I now do). Reviewers: clayborg, JDevlieghere, aprantl Subscribers: jdoerfert, lldb-commits Differential Revision: https://reviews.llvm.org/D63005 Added: lldb/trunk/lit/SymbolFile/DWARF/debug-types-dwarf5.s Modified: lldb/trunk/lit/SymbolFile/DWARF/debug-types-line-tables.s lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h Added: lldb/trunk/lit/SymbolFile/DWARF/debug-types-dwarf5.s URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/DWARF/debug-types-dwarf5.s?rev=363250&view=auto ============================================================================== --- lldb/trunk/lit/SymbolFile/DWARF/debug-types-dwarf5.s (added) +++ lldb/trunk/lit/SymbolFile/DWARF/debug-types-dwarf5.s Thu Jun 13 04:22:47 2019 @@ -0,0 +1,94 @@ +# RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t +# RUN: %lldb %t -o "image lookup -v -s f1" -o exit | FileCheck %s + +# CHECK: Function: id = {0x7fffffff0000003c}, name = "f1", range = [0x0000000000000000-0x0000000000000001) +# CHECK: Blocks: id = {0x7fffffff0000003c}, range = [0x00000000-0x00000001) + + + .text + .globl f1 + .type f1,@function +f1: + nop +.Lfunc_end0: + .size f1, .Lfunc_end0-f1 + # -- End function + .section .debug_str,"MS",@progbits,1 +.Lproducer: + .asciz "Hand-written DWARF" +.Lf1: + .asciz "f1" +.Le1: + .asciz "e1" + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 4 # DW_TAG_enumeration_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits +.Ltu_begin0: + .long .Ltu_end0-.Ltu_start0 # Length of Unit +.Ltu_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 47 # Type Signature + .long .Ltype-.Ltu_begin0 # Type DIE Offset + .byte 3 # Abbrev [1] 0x18:0x1d DW_TAG_type_unit +.Ltype: + .byte 5 # Abbrev [5] 0x2e:0x9 DW_TAG_enumeration_type + .long .Le1 # DW_AT_name + .byte 0 # End Of Children Mark +.Ltu_end0: + +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x5f DW_TAG_compile_unit + .long .Lproducer # DW_AT_producer + .quad f1 # DW_AT_low_pc + .long .Lfunc_end0-f1 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2b:0x37 DW_TAG_subprogram + .quad f1 # DW_AT_low_pc + .long .Lfunc_end0-f1 # DW_AT_high_pc + .long .Lf1 # DW_AT_name + .byte 0 # End Of Children Mark +.Ldebug_info_end0: Modified: lldb/trunk/lit/SymbolFile/DWARF/debug-types-line-tables.s URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/DWARF/debug-types-line-tables.s?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/lit/SymbolFile/DWARF/debug-types-line-tables.s (original) +++ lldb/trunk/lit/SymbolFile/DWARF/debug-types-line-tables.s Thu Jun 13 04:22:47 2019 @@ -169,6 +169,13 @@ .byte 1 # DW_CHILDREN_yes .byte 0 # EOM(1) .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) .byte 0 # EOM(3) .section .debug_info,"",@progbits .Lcu_begin0: @@ -178,6 +185,16 @@ .long .debug_abbrev # Offset Into Abbrev. Section .byte 8 # Address Size (in bytes) .byte 4 # Abbrev [4] 0xb:0x32 DW_TAG_compile_unit + .byte 5 # Abbrev [5] DW_TAG_structure_type + .quad 5390450678491038984 # DW_AT_signature + .byte 5 # Abbrev [5] DW_TAG_structure_type + .quad 5390450678491038985 # DW_AT_signature + .byte 5 # Abbrev [5] DW_TAG_structure_type + .quad 5390450678491038986 # DW_AT_signature + .byte 5 # Abbrev [5] DW_TAG_structure_type + .quad 5390450678491038987 # DW_AT_signature + .byte 5 # Abbrev [5] DW_TAG_structure_type + .quad 5390450678491038988 # DW_AT_signature .byte 0 # End Of Children Mark .Ldebug_info_end1: Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp Thu Jun 13 04:22:47 2019 @@ -70,7 +70,7 @@ void DWARFCompileUnit::BuildAddressRange // We got nothing from the functions, maybe we have a line tables only // situation. Check the line tables and build the arange table from this. SymbolContext sc; - sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this); + sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(*this); if (sc.comp_unit) { SymbolFileDWARFDebugMap *debug_map_sym_file = m_dwarf->GetDebugMapSymfile(); @@ -96,7 +96,7 @@ void DWARFCompileUnit::BuildAddressRange // We got nothing from the functions, maybe we have a line tables only // situation. Check the line tables and build the arange table from this. SymbolContext sc; - sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this); + sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(*this); if (sc.comp_unit) { if (LineTable *line_table = sc.comp_unit->GetLineTable()) { LineTable::FileAddressRanges file_ranges; Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp Thu Jun 13 04:22:47 2019 @@ -182,6 +182,11 @@ DWARFTypeUnit *DWARFDebugInfo::GetTypeUn return llvm::cast<DWARFTypeUnit>(GetUnitAtIndex(pos->second)); } +bool DWARFDebugInfo::ContainsTypeUnits() { + ParseUnitHeadersIfNeeded(); + return !m_type_hash_to_unit_index.empty(); +} + DWARFDIE DWARFDebugInfo::GetDIEForDIEOffset(DIERef::Section section, dw_offset_t die_offset) { Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h Thu Jun 13 04:22:47 2019 @@ -48,6 +48,7 @@ public: dw_offset_t die_offset); DWARFUnit *GetUnit(const DIERef &die_ref); DWARFTypeUnit *GetTypeUnitForHash(uint64_t hash); + bool ContainsTypeUnits(); DWARFDIE GetDIEForDIEOffset(DIERef::Section section, dw_offset_t die_offset); DWARFDIE GetDIE(const DIERef &die_ref); Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Thu Jun 13 04:22:47 2019 @@ -165,10 +165,6 @@ FileSpecList SymbolFileDWARF::GetSymlink return GetGlobalPluginProperties()->GetSymLinkPaths(); } -DWARFUnit *SymbolFileDWARF::GetBaseCompileUnit() { - return nullptr; -} - void SymbolFileDWARF::Initialize() { LogChannelDWARF::Initialize(); PluginManager::RegisterPlugin(GetPluginNameStatic(), @@ -651,51 +647,51 @@ DWARFDebugRangesBase *SymbolFileDWARF::G return m_rnglists.get(); } -lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu) { +lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { CompUnitSP cu_sp; - if (dwarf_cu) { - CompileUnit *comp_unit = (CompileUnit *)dwarf_cu->GetUserData(); - if (comp_unit) { - // We already parsed this compile unit, had out a shared pointer to it - cu_sp = comp_unit->shared_from_this(); + CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData(); + if (comp_unit) { + // We already parsed this compile unit, had out a shared pointer to it + cu_sp = comp_unit->shared_from_this(); + } else { + if (dwarf_cu.GetSymbolFileDWARF() != this) { + return dwarf_cu.GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu); + } else if (dwarf_cu.GetOffset() == 0 && GetDebugMapSymfile()) { + // Let the debug map create the compile unit + cu_sp = m_debug_map_symfile->GetCompileUnit(this); + dwarf_cu.SetUserData(cu_sp.get()); } else { - if (dwarf_cu->GetSymbolFileDWARF() != this) { - return dwarf_cu->GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu); - } else if (dwarf_cu->GetOffset() == 0 && GetDebugMapSymfile()) { - // Let the debug map create the compile unit - cu_sp = m_debug_map_symfile->GetCompileUnit(this); - dwarf_cu->SetUserData(cu_sp.get()); - } else { - ModuleSP module_sp(m_obj_file->GetModule()); - if (module_sp) { - const DWARFDIE cu_die = dwarf_cu->DIE(); - if (cu_die) { - FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu->GetPathStyle()); - if (cu_file_spec) { - // If we have a full path to the compile unit, we don't need to - // resolve the file. This can be expensive e.g. when the source - // files are NFS mounted. - cu_file_spec.MakeAbsolute(dwarf_cu->GetCompilationDirectory()); - - std::string remapped_file; - if (module_sp->RemapSourceFile(cu_file_spec.GetPath(), - remapped_file)) - cu_file_spec.SetFile(remapped_file, FileSpec::Style::native); - } + ModuleSP module_sp(m_obj_file->GetModule()); + if (module_sp) { + const DWARFDIE cu_die = dwarf_cu.DIE(); + if (cu_die) { + FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle()); + if (cu_file_spec) { + // If we have a full path to the compile unit, we don't need to + // resolve the file. This can be expensive e.g. when the source + // files are NFS mounted. + cu_file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory()); + + std::string remapped_file; + if (module_sp->RemapSourceFile(cu_file_spec.GetPath(), + remapped_file)) + cu_file_spec.SetFile(remapped_file, FileSpec::Style::native); + } - LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF( - cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0)); + LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF( + cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0)); - bool is_optimized = dwarf_cu->GetIsOptimized(); - cu_sp = std::make_shared<CompileUnit>( - module_sp, dwarf_cu, cu_file_spec, dwarf_cu->GetID(), - cu_language, is_optimized ? eLazyBoolYes : eLazyBoolNo); + bool is_optimized = dwarf_cu.GetIsOptimized(); + BuildCuTranslationTable(); + cu_sp = std::make_shared<CompileUnit>( + module_sp, &dwarf_cu, cu_file_spec, + *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language, + is_optimized ? eLazyBoolYes : eLazyBoolNo); - dwarf_cu->SetUserData(cu_sp.get()); + dwarf_cu.SetUserData(cu_sp.get()); - m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( - dwarf_cu->GetID(), cu_sp); - } + m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( + dwarf_cu.GetID(), cu_sp); } } } @@ -703,23 +699,56 @@ lldb::CompUnitSP SymbolFileDWARF::ParseC return cu_sp; } +void SymbolFileDWARF::BuildCuTranslationTable() { + if (!m_lldb_cu_to_dwarf_unit.empty()) + return; + + DWARFDebugInfo *info = DebugInfo(); + if (!info) + return; + + if (!info->ContainsTypeUnits()) { + // We can use a 1-to-1 mapping. No need to build a translation table. + return; + } + for (uint32_t i = 0, num = info->GetNumUnits(); i < num; ++i) { + if (auto *cu = llvm::dyn_cast<DWARFCompileUnit>(info->GetUnitAtIndex(i))) { + cu->SetID(m_lldb_cu_to_dwarf_unit.size()); + m_lldb_cu_to_dwarf_unit.push_back(i); + } + } +} + +llvm::Optional<uint32_t> SymbolFileDWARF::GetDWARFUnitIndex(uint32_t cu_idx) { + BuildCuTranslationTable(); + if (m_lldb_cu_to_dwarf_unit.empty()) + return cu_idx; + if (cu_idx >= m_lldb_cu_to_dwarf_unit.size()) + return llvm::None; + return m_lldb_cu_to_dwarf_unit[cu_idx]; +} + uint32_t SymbolFileDWARF::GetNumCompileUnits() { DWARFDebugInfo *info = DebugInfo(); - if (info) - return info->GetNumUnits(); - return 0; + if (!info) + return 0; + BuildCuTranslationTable(); + return m_lldb_cu_to_dwarf_unit.empty() ? info->GetNumUnits() + : m_lldb_cu_to_dwarf_unit.size(); } CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) { ASSERT_MODULE_LOCK(this); - CompUnitSP cu_sp; DWARFDebugInfo *info = DebugInfo(); - if (info) { - DWARFUnit *dwarf_cu = info->GetUnitAtIndex(cu_idx); - if (dwarf_cu) - cu_sp = ParseCompileUnit(dwarf_cu); + if (!info) + return {}; + + if (llvm::Optional<uint32_t> dwarf_idx = GetDWARFUnitIndex(cu_idx)) { + if (auto *dwarf_cu = llvm::cast_or_null<DWARFCompileUnit>( + info->GetUnitAtIndex(*dwarf_idx))) + return ParseCompileUnit(*dwarf_cu); } - return cu_sp; + return {}; } Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit, @@ -777,13 +806,7 @@ size_t SymbolFileDWARF::ParseFunctions(C bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { ASSERT_MODULE_LOCK(this); - DWARFUnit *unit = GetDWARFCompileUnit(&comp_unit); - if (auto *tu = llvm::dyn_cast_or_null<DWARFTypeUnit>(unit)) { - support_files = GetTypeUnitSupportFiles(*tu); - return true; - } - - if (unit) { + if (DWARFUnit *unit = GetDWARFCompileUnit(&comp_unit)) { const dw_offset_t stmt_list = unit->GetLineTableOffset(); if (stmt_list != DW_INVALID_OFFSET) { // All file indexes in DWARF are one based and a file of index zero is @@ -798,9 +821,14 @@ bool SymbolFileDWARF::ParseSupportFiles( } FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) { - if (CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(&unit)) - return lldb_cu->GetSupportFiles().GetFileSpecAtIndex(file_idx); - return FileSpec(); + if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit)) { + if (CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(*dwarf_cu)) + return lldb_cu->GetSupportFiles().GetFileSpecAtIndex(file_idx); + return FileSpec(); + } + + auto &tu = llvm::cast<DWARFTypeUnit>(unit); + return GetTypeUnitSupportFiles(tu).GetFileSpecAtIndex(file_idx); } const FileSpecList & @@ -1425,14 +1453,15 @@ Type *SymbolFileDWARF::ResolveType(const return nullptr; } -CompileUnit *SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu) { +CompileUnit * +SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu) { // Check if the symbol vendor already knows about this compile unit? - if (dwarf_cu->GetUserData() == nullptr) { + if (dwarf_cu.GetUserData() == nullptr) { // The symbol vendor doesn't know about this compile unit, we need to parse // and add it to the symbol vendor object. return ParseCompileUnit(dwarf_cu).get(); } - return (CompileUnit *)dwarf_cu->GetUserData(); + return (CompileUnit *)dwarf_cu.GetUserData(); } size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name, @@ -1445,9 +1474,10 @@ size_t SymbolFileDWARF::GetObjCMethodDIE bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) { sc.Clear(false); - if (die) { + if (die && llvm::isa<DWARFCompileUnit>(die.GetCU())) { // Check if the symbol vendor already knows about this compile unit? - sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU()); + sc.comp_unit = + GetCompUnitForDWARFCompUnit(llvm::cast<DWARFCompileUnit>(*die.GetCU())); sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get(); if (sc.function == nullptr) @@ -1482,24 +1512,29 @@ SymbolFileDWARF::GetDIE(const DIERef &di std::unique_ptr<SymbolFileDWARFDwo> SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( - DWARFUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die) { + DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) { // If we are using a dSYM file, we never want the standard DWO files since // the -gmodules support uses the same DWO machanism to specify full debug // info files for modules. if (GetDebugMapSymfile()) return nullptr; + DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit); + // Only compile units can be split into two parts. + if (!dwarf_cu) + return nullptr; + const char *dwo_name = - cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr); + cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_GNU_dwo_name, nullptr); if (!dwo_name) return nullptr; SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile(); if (dwp_symfile) { uint64_t dwo_id = - cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id, 0); + cu_die.GetAttributeValueAsUnsigned(dwarf_cu, DW_AT_GNU_dwo_id, 0); std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile = - dwp_symfile->GetSymbolFileForDwoId(&dwarf_cu, dwo_id); + dwp_symfile->GetSymbolFileForDwoId(*dwarf_cu, dwo_id); if (dwo_symfile) return dwo_symfile; } @@ -1508,7 +1543,7 @@ SymbolFileDWARF::GetDwoSymbolFileForComp FileSystem::Instance().Resolve(dwo_file); if (dwo_file.IsRelative()) { const char *comp_dir = - cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_comp_dir, nullptr); + cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr); if (!comp_dir) return nullptr; @@ -1530,7 +1565,7 @@ SymbolFileDWARF::GetDwoSymbolFileForComp if (dwo_obj_file == nullptr) return nullptr; - return llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, &dwarf_cu); + return llvm::make_unique<SymbolFileDWARFDwo>(dwo_obj_file, *dwarf_cu); } void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { @@ -1706,10 +1741,10 @@ uint32_t SymbolFileDWARF::ResolveSymbolC } } else { uint32_t cu_idx = DW_INVALID_INDEX; - DWARFUnit *dwarf_cu = debug_info->GetUnitAtOffset(DIERef::Section::DebugInfo, - cu_offset, &cu_idx); - if (dwarf_cu) { - sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu); + if (auto *dwarf_cu = llvm::dyn_cast_or_null<DWARFCompileUnit>( + debug_info->GetUnitAtOffset(DIERef::Section::DebugInfo, + cu_offset, &cu_idx))) { + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); if (sc.comp_unit) { resolved |= eSymbolContextCompUnit; @@ -1802,110 +1837,100 @@ uint32_t SymbolFileDWARF::ResolveSymbolC SymbolContextList &sc_list) { const uint32_t prev_size = sc_list.GetSize(); if (resolve_scope & eSymbolContextCompUnit) { - DWARFDebugInfo *debug_info = DebugInfo(); - if (debug_info) { - uint32_t cu_idx; - DWARFUnit *dwarf_cu = nullptr; - - for (cu_idx = 0; - (dwarf_cu = debug_info->GetUnitAtIndex(cu_idx)) != nullptr; - ++cu_idx) { - CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(dwarf_cu); - const bool full_match = (bool)file_spec.GetDirectory(); - bool file_spec_matches_cu_file_spec = - dc_cu != nullptr && FileSpec::Equal(file_spec, *dc_cu, full_match); - if (check_inlines || file_spec_matches_cu_file_spec) { - SymbolContext sc(m_obj_file->GetModule()); - sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu); - if (sc.comp_unit) { - uint32_t file_idx = UINT32_MAX; - - // If we are looking for inline functions only and we don't find it - // in the support files, we are done. - if (check_inlines) { + for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; + ++cu_idx) { + CompileUnit *dc_cu = ParseCompileUnitAtIndex(cu_idx).get(); + if (!dc_cu) + continue; + + const bool full_match = (bool)file_spec.GetDirectory(); + bool file_spec_matches_cu_file_spec = + FileSpec::Equal(file_spec, *dc_cu, full_match); + if (check_inlines || file_spec_matches_cu_file_spec) { + SymbolContext sc(m_obj_file->GetModule()); + sc.comp_unit = dc_cu; + uint32_t file_idx = UINT32_MAX; + + // If we are looking for inline functions only and we don't find it + // in the support files, we are done. + if (check_inlines) { + file_idx = + sc.comp_unit->GetSupportFiles().FindFileIndex(1, file_spec, true); + if (file_idx == UINT32_MAX) + continue; + } + + if (line != 0) { + LineTable *line_table = sc.comp_unit->GetLineTable(); + + if (line_table != nullptr && line != 0) { + // We will have already looked up the file index if we are + // searching for inline entries. + if (!check_inlines) file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex( 1, file_spec, true); - if (file_idx == UINT32_MAX) - continue; - } - if (line != 0) { - LineTable *line_table = sc.comp_unit->GetLineTable(); - - if (line_table != nullptr && line != 0) { - // We will have already looked up the file index if we are - // searching for inline entries. - if (!check_inlines) - file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex( - 1, file_spec, true); - - if (file_idx != UINT32_MAX) { - uint32_t found_line; - uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex( - 0, file_idx, line, false, &sc.line_entry); - found_line = sc.line_entry.line; - - while (line_idx != UINT32_MAX) { - sc.function = nullptr; - sc.block = nullptr; - if (resolve_scope & - (eSymbolContextFunction | eSymbolContextBlock)) { - const lldb::addr_t file_vm_addr = - sc.line_entry.range.GetBaseAddress().GetFileAddress(); - if (file_vm_addr != LLDB_INVALID_ADDRESS) { - DWARFDIE function_die = - dwarf_cu->LookupAddress(file_vm_addr); - DWARFDIE block_die; - if (function_die) { - sc.function = - sc.comp_unit - ->FindFunctionByUID(function_die.GetID()) - .get(); - if (sc.function == nullptr) - sc.function = - ParseFunction(*sc.comp_unit, function_die); - - if (sc.function && - (resolve_scope & eSymbolContextBlock)) - block_die = - function_die.LookupDeepestBlock(file_vm_addr); - } - - if (sc.function != nullptr) { - Block &block = sc.function->GetBlock(true); - - if (block_die) - sc.block = block.FindBlockByID(block_die.GetID()); - else if (function_die) - sc.block = - block.FindBlockByID(function_die.GetID()); - } - } + if (file_idx != UINT32_MAX) { + uint32_t found_line; + uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex( + 0, file_idx, line, false, &sc.line_entry); + found_line = sc.line_entry.line; + + while (line_idx != UINT32_MAX) { + sc.function = nullptr; + sc.block = nullptr; + if (resolve_scope & + (eSymbolContextFunction | eSymbolContextBlock)) { + const lldb::addr_t file_vm_addr = + sc.line_entry.range.GetBaseAddress().GetFileAddress(); + if (file_vm_addr != LLDB_INVALID_ADDRESS) { + DWARFDIE function_die = + GetDWARFCompileUnit(dc_cu)->LookupAddress(file_vm_addr); + DWARFDIE block_die; + if (function_die) { + sc.function = + sc.comp_unit->FindFunctionByUID(function_die.GetID()) + .get(); + if (sc.function == nullptr) + sc.function = + ParseFunction(*sc.comp_unit, function_die); + + if (sc.function && (resolve_scope & eSymbolContextBlock)) + block_die = + function_die.LookupDeepestBlock(file_vm_addr); } - sc_list.Append(sc); - line_idx = line_table->FindLineEntryIndexByFileIndex( - line_idx + 1, file_idx, found_line, true, - &sc.line_entry); + if (sc.function != nullptr) { + Block &block = sc.function->GetBlock(true); + + if (block_die) + sc.block = block.FindBlockByID(block_die.GetID()); + else if (function_die) + sc.block = block.FindBlockByID(function_die.GetID()); + } } } - } else if (file_spec_matches_cu_file_spec && !check_inlines) { - // only append the context if we aren't looking for inline call - // sites by file and line and if the file spec matches that of - // the compile unit + sc_list.Append(sc); + line_idx = line_table->FindLineEntryIndexByFileIndex( + line_idx + 1, file_idx, found_line, true, &sc.line_entry); } - } else if (file_spec_matches_cu_file_spec && !check_inlines) { - // only append the context if we aren't looking for inline call - // sites by file and line and if the file spec matches that of - // the compile unit - sc_list.Append(sc); } - - if (!check_inlines) - break; + } else if (file_spec_matches_cu_file_spec && !check_inlines) { + // only append the context if we aren't looking for inline call + // sites by file and line and if the file spec matches that of + // the compile unit + sc_list.Append(sc); } + } else if (file_spec_matches_cu_file_spec && !check_inlines) { + // only append the context if we aren't looking for inline call + // sites by file and line and if the file spec matches that of + // the compile unit + sc_list.Append(sc); } + + if (!check_inlines) + break; } } } @@ -2007,7 +2032,10 @@ uint32_t SymbolFileDWARF::FindGlobalVari break; case DW_TAG_variable: { - sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU()); + auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()); + if (!dwarf_cu) + continue; + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); if (parent_decl_ctx) { DWARFASTParser *dwarf_ast = die.GetDWARFParser(); @@ -2089,7 +2117,11 @@ uint32_t SymbolFileDWARF::FindGlobalVari DWARFDIE die = GetDIE(die_ref); if (die) { - sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU()); + DWARFCompileUnit *dwarf_cu = + llvm::dyn_cast<DWARFCompileUnit>(die.GetCU()); + if (!dwarf_cu) + continue; + sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables); @@ -2533,9 +2565,13 @@ TypeSP SymbolFileDWARF::GetTypeForDIE(co if (die) { Type *type_ptr = GetDIEToType().lookup(die.GetDIE()); if (type_ptr == nullptr) { - CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU()); - assert(lldb_cu); - SymbolContext sc(lldb_cu); + SymbolContextScope *scope; + if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU())) + scope = GetCompUnitForDWARFCompUnit(*dwarf_cu); + else + scope = GetObjectFile()->GetModule().get(); + assert(scope); + SymbolContext sc(scope); const DWARFDebugInfoEntry *parent_die = die.GetParent().GetDIE(); while (parent_die != nullptr) { if (parent_die->Tag() == DW_TAG_subprogram) Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h Thu Jun 13 04:22:47 2019 @@ -40,7 +40,7 @@ class DebugMapModule; class DWARFAbbreviationDeclaration; class DWARFAbbreviationDeclarationSet; -class DWARFileUnit; +class DWARFCompileUnit; class DWARFDebugAbbrev; class DWARFDebugAranges; class DWARFDebugInfo; @@ -239,7 +239,8 @@ public: bool HasForwardDeclForClangType(const lldb_private::CompilerType &compiler_type); - lldb_private::CompileUnit *GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu); + lldb_private::CompileUnit * + GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu); virtual size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name, DIEArray &method_die_offsets); @@ -250,7 +251,7 @@ public: static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die); - virtual lldb::CompUnitSP ParseCompileUnit(DWARFUnit *dwarf_cu); + virtual lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu); virtual lldb_private::DWARFExpression::LocationListFormat GetLocationListFormat() const; @@ -285,7 +286,7 @@ public: // 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 DWARFUnit *GetBaseCompileUnit(); + virtual DWARFCompileUnit *GetBaseCompileUnit() { return nullptr; } static bool DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx, @@ -433,6 +434,9 @@ protected: return m_forward_decl_clang_type_to_die; } + void BuildCuTranslationTable(); + llvm::Optional<uint32_t> GetDWARFUnitIndex(uint32_t cu_idx); + struct DecodedUID { SymbolFileDWARF *dwarf; DIERef ref; @@ -483,6 +487,7 @@ protected: ClangTypeToDIE m_forward_decl_clang_type_to_die; llvm::DenseMap<dw_offset_t, lldb_private::FileSpecList> m_type_unit_support_files; + std::vector<uint32_t> m_lldb_cu_to_dwarf_unit; }; #endif // SymbolFileDWARF_SymbolFileDWARF_h_ Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp Thu Jun 13 04:22:47 2019 @@ -13,18 +13,19 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/LLDBAssert.h" -#include "DWARFUnit.h" +#include "DWARFCompileUnit.h" #include "DWARFDebugInfo.h" +#include "DWARFUnit.h" using namespace lldb; using namespace lldb_private; SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, - DWARFUnit *dwarf_cu) + DWARFCompileUnit &dwarf_cu) : SymbolFileDWARF(objfile.get(), objfile->GetSectionList( /*update_module_section_list*/ false)), m_obj_file_sp(objfile), m_base_dwarf_cu(dwarf_cu) { - SetID(((lldb::user_id_t)dwarf_cu->GetID()) << 32); + SetID(((lldb::user_id_t)dwarf_cu.GetID()) << 32); } void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type, @@ -45,10 +46,11 @@ void SymbolFileDWARFDwo::LoadSectionData SymbolFileDWARF::LoadSectionData(sect_type, data); } -lldb::CompUnitSP SymbolFileDWARFDwo::ParseCompileUnit(DWARFUnit *dwarf_cu) { - assert(GetCompileUnit() == dwarf_cu && "SymbolFileDWARFDwo::ParseCompileUnit " - "called with incompatible compile " - "unit"); +lldb::CompUnitSP +SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { + assert(GetCompileUnit() == &dwarf_cu && + "SymbolFileDWARFDwo::ParseCompileUnit called with incompatible " + "compile unit"); return GetBaseSymbolFile()->ParseCompileUnit(m_base_dwarf_cu); } @@ -106,12 +108,8 @@ lldb::TypeSP SymbolFileDWARFDwo::FindCom die, type_name, must_be_implementation); } -DWARFUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() { - return m_base_dwarf_cu; -} - SymbolFileDWARF *SymbolFileDWARFDwo::GetBaseSymbolFile() { - return m_base_dwarf_cu->GetSymbolFileDWARF(); + return m_base_dwarf_cu.GetSymbolFileDWARF(); } DWARFExpression::LocationListFormat @@ -126,7 +124,7 @@ SymbolFileDWARFDwo::GetTypeSystemForLang DWARFDIE SymbolFileDWARFDwo::GetDIE(const DIERef &die_ref) { - lldbassert(die_ref.cu_offset == m_base_dwarf_cu->GetOffset() || + lldbassert(die_ref.cu_offset == m_base_dwarf_cu.GetOffset() || die_ref.cu_offset == DW_INVALID_OFFSET); return DebugInfo()->GetDIEForDIEOffset(die_ref.section, die_ref.die_offset); } Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h Thu Jun 13 04:22:47 2019 @@ -13,11 +13,11 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF { public: - SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFUnit *dwarf_cu); + SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu); ~SymbolFileDWARFDwo() override = default; - lldb::CompUnitSP ParseCompileUnit(DWARFUnit *dwarf_cu) override; + lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu) override; DWARFUnit *GetCompileUnit(); @@ -42,7 +42,7 @@ public: return nullptr; } - DWARFUnit *GetBaseCompileUnit() override; + DWARFCompileUnit *GetBaseCompileUnit() override { return &m_base_dwarf_cu; } protected: void LoadSectionData(lldb::SectionType sect_type, @@ -68,7 +68,7 @@ protected: SymbolFileDWARF *GetBaseSymbolFile(); lldb::ObjectFileSP m_obj_file_sp; - DWARFUnit *m_base_dwarf_cu; + DWARFCompileUnit &m_base_dwarf_cu; }; #endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_ Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp Thu Jun 13 04:22:47 2019 @@ -21,7 +21,7 @@ using namespace lldb_private; SymbolFileDWARFDwoDwp::SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile, ObjectFileSP objfile, - DWARFUnit *dwarf_cu, + DWARFCompileUnit &dwarf_cu, uint64_t dwo_id) : SymbolFileDWARFDwo(objfile, dwarf_cu), m_dwp_symfile(dwp_symfile), m_dwo_id(dwo_id) {} Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h Thu Jun 13 04:22:47 2019 @@ -15,7 +15,7 @@ class SymbolFileDWARFDwoDwp : public SymbolFileDWARFDwo { public: SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile, - lldb::ObjectFileSP objfile, DWARFUnit *dwarf_cu, + lldb::ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu, uint64_t dwo_id); protected: Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp Thu Jun 13 04:22:47 2019 @@ -81,7 +81,7 @@ SymbolFileDWARFDwp::SymbolFileDWARFDwp(l {} std::unique_ptr<SymbolFileDWARFDwo> -SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFUnit *dwarf_cu, +SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFCompileUnit &dwarf_cu, uint64_t dwo_id) { return std::unique_ptr<SymbolFileDWARFDwo>( new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id)); Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h?rev=363250&r1=363249&r2=363250&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h Thu Jun 13 04:22:47 2019 @@ -24,7 +24,7 @@ public: Create(lldb::ModuleSP module_sp, const lldb_private::FileSpec &file_spec); std::unique_ptr<SymbolFileDWARFDwo> - GetSymbolFileForDwoId(DWARFUnit *dwarf_cu, uint64_t dwo_id); + GetSymbolFileForDwoId(DWARFCompileUnit &dwarf_cu, uint64_t dwo_id); bool LoadSectionData(uint64_t dwo_id, lldb::SectionType sect_type, lldb_private::DWARFDataExtractor &data); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits