| 1 | //===-- SymbolFileDWARFDwo.cpp --------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "SymbolFileDWARFDwo.h" |
| 10 | |
| 11 | #include "lldb/Core/Section.h" |
| 12 | #include "lldb/Expression/DWARFExpression.h" |
| 13 | #include "lldb/Symbol/ObjectFile.h" |
| 14 | #include "lldb/Utility/LLDBAssert.h" |
| 15 | #include "llvm/Support/Casting.h" |
| 16 | |
| 17 | #include "DWARFCompileUnit.h" |
| 18 | #include "DWARFDebugInfo.h" |
| 19 | #include "DWARFUnit.h" |
| 20 | #include <optional> |
| 21 | |
| 22 | using namespace lldb; |
| 23 | using namespace lldb_private; |
| 24 | using namespace lldb_private::plugin::dwarf; |
| 25 | |
| 26 | char SymbolFileDWARFDwo::ID; |
| 27 | |
| 28 | SymbolFileDWARFDwo::SymbolFileDWARFDwo(SymbolFileDWARF &base_symbol_file, |
| 29 | ObjectFileSP objfile, uint32_t id) |
| 30 | : SymbolFileDWARF(objfile, objfile->GetSectionList( |
| 31 | /*update_module_section_list*/ false)), |
| 32 | m_base_symbol_file(base_symbol_file) { |
| 33 | SetFileIndex(id); |
| 34 | |
| 35 | // Parsing of the dwarf unit index is not thread-safe, so we need to prime it |
| 36 | // to enable subsequent concurrent lookups. |
| 37 | m_context.GetAsLLVM().getCUIndex(); |
| 38 | } |
| 39 | |
| 40 | DWARFCompileUnit *SymbolFileDWARFDwo::GetDWOCompileUnitForHash(uint64_t hash) { |
| 41 | if (const llvm::DWARFUnitIndex &index = m_context.GetAsLLVM().getCUIndex()) { |
| 42 | if (const llvm::DWARFUnitIndex::Entry *entry = index.getFromHash(Offset: hash)) { |
| 43 | if (auto *unit_contrib = entry->getContribution()) |
| 44 | return llvm::dyn_cast_or_null<DWARFCompileUnit>( |
| 45 | Val: DebugInfo().GetUnitAtOffset(section: DIERef::Section::DebugInfo, |
| 46 | cu_offset: unit_contrib->getOffset())); |
| 47 | } |
| 48 | return nullptr; |
| 49 | } |
| 50 | |
| 51 | DWARFCompileUnit *cu = FindSingleCompileUnit(); |
| 52 | if (!cu) |
| 53 | return nullptr; |
| 54 | std::optional<uint64_t> dwo_id = cu->GetDWOId(); |
| 55 | if (!dwo_id || hash != *dwo_id) |
| 56 | return nullptr; |
| 57 | return cu; |
| 58 | } |
| 59 | |
| 60 | DWARFCompileUnit *SymbolFileDWARFDwo::FindSingleCompileUnit() { |
| 61 | DWARFDebugInfo &debug_info = DebugInfo(); |
| 62 | |
| 63 | // Right now we only support dwo files with one compile unit. If we don't have |
| 64 | // type units, we can just check for the unit count. |
| 65 | if (!debug_info.ContainsTypeUnits() && debug_info.GetNumUnits() == 1) |
| 66 | return llvm::cast<DWARFCompileUnit>(Val: debug_info.GetUnitAtIndex(idx: 0)); |
| 67 | |
| 68 | // Otherwise, we have to run through all units, and find the compile unit that |
| 69 | // way. |
| 70 | DWARFCompileUnit *cu = nullptr; |
| 71 | for (size_t i = 0; i < debug_info.GetNumUnits(); ++i) { |
| 72 | if (auto *candidate = |
| 73 | llvm::dyn_cast<DWARFCompileUnit>(Val: debug_info.GetUnitAtIndex(idx: i))) { |
| 74 | if (cu) |
| 75 | return nullptr; // More that one CU found. |
| 76 | cu = candidate; |
| 77 | } |
| 78 | } |
| 79 | return cu; |
| 80 | } |
| 81 | |
| 82 | lldb::offset_t SymbolFileDWARFDwo::( |
| 83 | const lldb_private::DataExtractor &data, const lldb::offset_t data_offset, |
| 84 | const uint8_t op) const { |
| 85 | return GetBaseSymbolFile().GetVendorDWARFOpcodeSize(data, data_offset, op); |
| 86 | } |
| 87 | |
| 88 | uint64_t SymbolFileDWARFDwo::GetDebugInfoSize(bool load_all_debug_info) { |
| 89 | // Directly get debug info from current dwo object file's section list |
| 90 | // instead of asking SymbolFileCommon::GetDebugInfo() which parses from |
| 91 | // owning module which is wrong. |
| 92 | SectionList *section_list = |
| 93 | m_objfile_sp->GetSectionList(/*update_module_section_list=*/false); |
| 94 | if (section_list) |
| 95 | return section_list->GetDebugInfoSize(); |
| 96 | return 0; |
| 97 | } |
| 98 | |
| 99 | bool SymbolFileDWARFDwo::( |
| 100 | uint8_t op, const lldb_private::DataExtractor &opcodes, |
| 101 | lldb::offset_t &offset, std::vector<lldb_private::Value> &stack) const { |
| 102 | return GetBaseSymbolFile().ParseVendorDWARFOpcode(op, opcodes, offset, stack); |
| 103 | } |
| 104 | |
| 105 | llvm::DenseMap<const DWARFDebugInfoEntry *, Type *> & |
| 106 | SymbolFileDWARFDwo::GetDIEToType() { |
| 107 | return GetBaseSymbolFile().GetDIEToType(); |
| 108 | } |
| 109 | |
| 110 | SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() { |
| 111 | return GetBaseSymbolFile().GetDIEToVariable(); |
| 112 | } |
| 113 | |
| 114 | llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> & |
| 115 | SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() { |
| 116 | return GetBaseSymbolFile().GetForwardDeclCompilerTypeToDIE(); |
| 117 | } |
| 118 | |
| 119 | void SymbolFileDWARFDwo::GetObjCMethods( |
| 120 | lldb_private::ConstString class_name, |
| 121 | llvm::function_ref<bool(DWARFDIE die)> callback) { |
| 122 | GetBaseSymbolFile().GetObjCMethods(class_name, callback); |
| 123 | } |
| 124 | |
| 125 | UniqueDWARFASTTypeMap &SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() { |
| 126 | return GetBaseSymbolFile().GetUniqueDWARFASTTypeMap(); |
| 127 | } |
| 128 | |
| 129 | DWARFDIE SymbolFileDWARFDwo::FindDefinitionDIE(const DWARFDIE &die) { |
| 130 | return GetBaseSymbolFile().FindDefinitionDIE(die); |
| 131 | } |
| 132 | |
| 133 | lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE( |
| 134 | const DWARFDIE &die, lldb_private::ConstString type_name, |
| 135 | bool must_be_implementation) { |
| 136 | return GetBaseSymbolFile().FindCompleteObjCDefinitionTypeForDIE( |
| 137 | die, type_name, must_be_implementation); |
| 138 | } |
| 139 | |
| 140 | llvm::Expected<lldb::TypeSystemSP> |
| 141 | SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) { |
| 142 | return GetBaseSymbolFile().GetTypeSystemForLanguage(language); |
| 143 | } |
| 144 | |
| 145 | DWARFDIE |
| 146 | SymbolFileDWARFDwo::GetDIE(const DIERef &die_ref) { |
| 147 | if (die_ref.file_index() == GetFileIndex()) |
| 148 | return DebugInfo().GetDIE(section: die_ref.section(), die_offset: die_ref.die_offset()); |
| 149 | return GetBaseSymbolFile().GetDIE(die_ref); |
| 150 | } |
| 151 | |
| 152 | void SymbolFileDWARFDwo::FindGlobalVariables( |
| 153 | ConstString name, const CompilerDeclContext &parent_decl_ctx, |
| 154 | uint32_t max_matches, VariableList &variables) { |
| 155 | GetBaseSymbolFile().FindGlobalVariables(name, parent_decl_ctx, max_matches, |
| 156 | variables); |
| 157 | } |
| 158 | |
| 159 | bool SymbolFileDWARFDwo::GetDebugInfoIndexWasLoadedFromCache() const { |
| 160 | return GetBaseSymbolFile().GetDebugInfoIndexWasLoadedFromCache(); |
| 161 | } |
| 162 | void SymbolFileDWARFDwo::SetDebugInfoIndexWasLoadedFromCache() { |
| 163 | GetBaseSymbolFile().SetDebugInfoIndexWasLoadedFromCache(); |
| 164 | } |
| 165 | bool SymbolFileDWARFDwo::GetDebugInfoIndexWasSavedToCache() const { |
| 166 | return GetBaseSymbolFile().GetDebugInfoIndexWasSavedToCache(); |
| 167 | } |
| 168 | void SymbolFileDWARFDwo::SetDebugInfoIndexWasSavedToCache() { |
| 169 | GetBaseSymbolFile().SetDebugInfoIndexWasSavedToCache(); |
| 170 | } |
| 171 | bool SymbolFileDWARFDwo::GetDebugInfoHadFrameVariableErrors() const { |
| 172 | return GetBaseSymbolFile().GetDebugInfoHadFrameVariableErrors(); |
| 173 | } |
| 174 | void SymbolFileDWARFDwo::SetDebugInfoHadFrameVariableErrors() { |
| 175 | return GetBaseSymbolFile().SetDebugInfoHadFrameVariableErrors(); |
| 176 | } |
| 177 | |
| 178 | SymbolFileDWARF * |
| 179 | SymbolFileDWARFDwo::GetDIERefSymbolFile(const DIERef &die_ref) { |
| 180 | return GetBaseSymbolFile().GetDIERefSymbolFile(die_ref); |
| 181 | } |
| 182 | |