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
21using namespace lldb;
22using namespace lldb_private;
23
24char SymbolFileDWARFDwo::ID;
25
26SymbolFileDWARFDwo::SymbolFileDWARFDwo(SymbolFileDWARF &base_symbol_file,
27                                       ObjectFileSP objfile, uint32_t id)
28    : SymbolFileDWARF(objfile, objfile->GetSectionList(
29                                   /*update_module_section_list*/ false)),
30      m_base_symbol_file(base_symbol_file) {
31  SetID(user_id_t(id) << 32);
32
33  // Parsing of the dwarf unit index is not thread-safe, so we need to prime it
34  // to enable subsequent concurrent lookups.
35  m_context.GetAsLLVM().getCUIndex();
36}
37
38DWARFCompileUnit *SymbolFileDWARFDwo::GetDWOCompileUnitForHash(uint64_t hash) {
39  if (const llvm::DWARFUnitIndex &index = m_context.GetAsLLVM().getCUIndex()) {
40    if (const llvm::DWARFUnitIndex::Entry *entry = index.getFromHash(hash)) {
41      if (auto *unit_contrib = entry->getContribution())
42        return llvm::dyn_cast_or_null<DWARFCompileUnit>(
43            DebugInfo().GetUnitAtOffset(DIERef::Section::DebugInfo,
44                                        unit_contrib->Offset));
45    }
46    return nullptr;
47  }
48
49  DWARFCompileUnit *cu = FindSingleCompileUnit();
50  if (!cu)
51    return nullptr;
52  if (hash !=
53      cu->GetUnitDIEOnly().GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0))
54    return nullptr;
55  return cu;
56}
57
58DWARFCompileUnit *SymbolFileDWARFDwo::FindSingleCompileUnit() {
59  DWARFDebugInfo &debug_info = DebugInfo();
60
61  // Right now we only support dwo files with one compile unit. If we don't have
62  // type units, we can just check for the unit count.
63  if (!debug_info.ContainsTypeUnits() && debug_info.GetNumUnits() == 1)
64    return llvm::cast<DWARFCompileUnit>(debug_info.GetUnitAtIndex(0));
65
66  // Otherwise, we have to run through all units, and find the compile unit that
67  // way.
68  DWARFCompileUnit *cu = nullptr;
69  for (size_t i = 0; i < debug_info.GetNumUnits(); ++i) {
70    if (auto *candidate =
71            llvm::dyn_cast<DWARFCompileUnit>(debug_info.GetUnitAtIndex(i))) {
72      if (cu)
73        return nullptr; // More that one CU found.
74      cu = candidate;
75    }
76  }
77  return cu;
78}
79
80SymbolFileDWARF::DIEToTypePtr &SymbolFileDWARFDwo::GetDIEToType() {
81  return GetBaseSymbolFile().GetDIEToType();
82}
83
84SymbolFileDWARF::DIEToVariableSP &SymbolFileDWARFDwo::GetDIEToVariable() {
85  return GetBaseSymbolFile().GetDIEToVariable();
86}
87
88SymbolFileDWARF::DIEToClangType &
89SymbolFileDWARFDwo::GetForwardDeclDieToClangType() {
90  return GetBaseSymbolFile().GetForwardDeclDieToClangType();
91}
92
93SymbolFileDWARF::ClangTypeToDIE &
94SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie() {
95  return GetBaseSymbolFile().GetForwardDeclClangTypeToDie();
96}
97
98void SymbolFileDWARFDwo::GetObjCMethods(
99    lldb_private::ConstString class_name,
100    llvm::function_ref<bool(DWARFDIE die)> callback) {
101  GetBaseSymbolFile().GetObjCMethods(class_name, callback);
102}
103
104UniqueDWARFASTTypeMap &SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() {
105  return GetBaseSymbolFile().GetUniqueDWARFASTTypeMap();
106}
107
108lldb::TypeSP SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext(
109    const DWARFDeclContext &die_decl_ctx) {
110  return GetBaseSymbolFile().FindDefinitionTypeForDWARFDeclContext(
111      die_decl_ctx);
112}
113
114lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE(
115    const DWARFDIE &die, lldb_private::ConstString type_name,
116    bool must_be_implementation) {
117  return GetBaseSymbolFile().FindCompleteObjCDefinitionTypeForDIE(
118      die, type_name, must_be_implementation);
119}
120
121llvm::Expected<TypeSystem &>
122SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) {
123  return GetBaseSymbolFile().GetTypeSystemForLanguage(language);
124}
125
126DWARFDIE
127SymbolFileDWARFDwo::GetDIE(const DIERef &die_ref) {
128  if (die_ref.dwo_num() == GetDwoNum())
129    return DebugInfo().GetDIE(die_ref);
130  return GetBaseSymbolFile().GetDIE(die_ref);
131}
132