aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
blob: c4efc06ab7873d8a39180ee3926585bbee452e8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
//===-- DWARFIndex.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDeclContext.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"

#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Target/Language.h"
#include "lldb/lldb-private-enumerations.h"

using namespace lldb_private;
using namespace lldb;
using namespace lldb_private::plugin::dwarf;

DWARFIndex::~DWARFIndex() = default;

IterationAction DWARFIndex::ProcessFunctionDIE(
    const Module::LookupInfo &lookup_info, DWARFDIE die,
    const CompilerDeclContext &parent_decl_ctx,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  llvm::StringRef name = lookup_info.GetLookupName().GetStringRef();
  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();

  if (!(name_type_mask & eFunctionNameTypeFull)) {
    ConstString name_to_match_against;
    if (const char *mangled_die_name = die.GetMangledName()) {
      name_to_match_against = ConstString(mangled_die_name);
    } else {
      SymbolFileDWARF *symbols = die.GetDWARF();
      if (ConstString demangled_die_name =
              symbols->ConstructFunctionDemangledName(die))
        name_to_match_against = demangled_die_name;
    }

    if (!lookup_info.NameMatchesLookupInfo(name_to_match_against,
                                           lookup_info.GetLanguageType()))
      return IterationAction::Continue;
  }

  // Exit early if we're searching exclusively for methods or selectors and
  // we have a context specified (no methods in namespaces).
  uint32_t looking_for_nonmethods =
      name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector);
  if (!looking_for_nonmethods && parent_decl_ctx.IsValid())
    return IterationAction::Continue;

  // Otherwise, we need to also check that the context matches. If it does not
  // match, we do nothing.
  if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die))
    return IterationAction::Continue;

  // In case of a full match, we just insert everything we find.
  if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name)
    return callback(die);

  // If looking for ObjC selectors, we need to also check if the name is a
  // possible selector.
  if (name_type_mask & eFunctionNameTypeSelector &&
      ObjCLanguage::IsPossibleObjCMethodName(die.GetName()))
    return callback(die);

  bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod;
  bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase;
  if (looking_for_methods || looking_for_functions) {
    // If we're looking for either methods or functions, we definitely want this
    // die. Otherwise, only keep it if the die type matches what we are
    // searching for.
    if ((looking_for_methods && looking_for_functions) ||
        looking_for_methods == die.IsMethod())
      return callback(die);
  }

  return IterationAction::Continue;
}

DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl(
    const DWARFIndex &index,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback,
    llvm::StringRef name)
    : m_index(index),
      m_dwarf(*llvm::cast<SymbolFileDWARF>(
          index.m_module.GetSymbolFile()->GetBackingSymbolFile())),
      m_callback(callback), m_name(name) {}

IterationAction DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const {
  if (DWARFDIE die = m_dwarf.GetDIE(ref))
    return m_callback(die);
  m_index.ReportInvalidDIERef(ref, m_name);
  return IterationAction::Continue;
}

IterationAction DWARFIndex::DIERefCallbackImpl::operator()(
    const llvm::AppleAcceleratorTable::Entry &entry) const {
  return this->operator()(DIERef(std::nullopt, DIERef::Section::DebugInfo,
                                 *entry.getDIESectionOffset()));
}

void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const {
  m_module.ReportErrorIfModifyDetected(
      "the DWARF debug information has been modified (accelerator table had "
      "bad die {0:x16} for '{1}')\n",
      ref.die_offset(), name.str().c_str());
}

void DWARFIndex::GetFullyQualifiedType(
    const DWARFDeclContext &context,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  GetTypes(context, [&](DWARFDIE die) {
    return GetFullyQualifiedTypeImpl(context, die, callback);
  });
}

IterationAction DWARFIndex::GetFullyQualifiedTypeImpl(
    const DWARFDeclContext &context, DWARFDIE die,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  DWARFDeclContext dwarf_decl_ctx = die.GetDWARFDeclContext();
  if (dwarf_decl_ctx == context)
    return callback(die);
  return IterationAction::Continue;
}

void DWARFIndex::GetTypesWithQuery(
    TypeQuery &query,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  GetTypes(query.GetTypeBasename(), [&](DWARFDIE die) {
    return ProcessTypeDIEMatchQuery(query, die, callback);
  });
}

IterationAction DWARFIndex::ProcessTypeDIEMatchQuery(
    TypeQuery &query, DWARFDIE die,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  // Check the language, but only if we have a language filter.
  if (query.HasLanguage() &&
      !query.LanguageMatches(SymbolFileDWARF::GetLanguageFamily(*die.GetCU())))
    return IterationAction::Continue;

  // Since mangled names are unique, we only need to check if the names are
  // the same.
  if (query.GetSearchByMangledName()) {
    if (die.GetMangledName(/*substitute_name_allowed=*/false) !=
        query.GetTypeBasename().GetStringRef())
      return IterationAction::Continue;
    return callback(die);
  }

  std::vector<lldb_private::CompilerContext> die_context;
  if (query.GetModuleSearch())
    die_context = die.GetDeclContext();
  else
    die_context = die.GetTypeLookupContext();

  if (!query.ContextMatches(die_context))
    return IterationAction::Continue;
  return callback(die);
}

void DWARFIndex::GetNamespacesWithParents(
    ConstString name, const CompilerDeclContext &parent_decl_ctx,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  GetNamespaces(name, [&](DWARFDIE die) {
    return ProcessNamespaceDieMatchParents(parent_decl_ctx, die, callback);
  });
}

void DWARFIndex::GetFunctions(
    const std::vector<Module::LookupInfo> &lookup_infos, SymbolFileDWARF &dwarf,
    const CompilerDeclContext &parent_decl_ctx,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  for (auto &lookup_info : lookup_infos)
    GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
}

IterationAction DWARFIndex::ProcessNamespaceDieMatchParents(
    const CompilerDeclContext &parent_decl_ctx, DWARFDIE die,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die))
    return IterationAction::Continue;
  return callback(die);
}