1 //===-- AddressResolverName.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 "lldb/Core/AddressResolverName.h"
10
11 #include "lldb/Core/Address.h"
12 #include "lldb/Core/AddressRange.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Symbol/Function.h"
15 #include "lldb/Symbol/Symbol.h"
16 #include "lldb/Symbol/SymbolContext.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/Logging.h"
19 #include "lldb/Utility/Stream.h"
20 #include "lldb/lldb-enumerations.h"
21 #include "lldb/lldb-forward.h"
22 #include "lldb/lldb-types.h"
23 #include "llvm/ADT/StringRef.h"
24
25 #include <memory>
26 #include <string>
27 #include <vector>
28
29 #include <stdint.h>
30
31 using namespace lldb;
32 using namespace lldb_private;
33
AddressResolverName(const char * func_name,AddressResolver::MatchType type)34 AddressResolverName::AddressResolverName(const char *func_name,
35 AddressResolver::MatchType type)
36 : AddressResolver(), m_func_name(func_name), m_class_name(nullptr),
37 m_regex(), m_match_type(type) {
38 if (m_match_type == AddressResolver::Regexp) {
39 m_regex = RegularExpression(m_func_name.GetStringRef());
40 if (!m_regex.IsValid()) {
41 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
42
43 if (log)
44 log->Warning("function name regexp: \"%s\" did not compile.",
45 m_func_name.AsCString());
46 }
47 }
48 }
49
AddressResolverName(RegularExpression func_regex)50 AddressResolverName::AddressResolverName(RegularExpression func_regex)
51 : AddressResolver(), m_func_name(nullptr), m_class_name(nullptr),
52 m_regex(std::move(func_regex)), m_match_type(AddressResolver::Regexp) {}
53
AddressResolverName(const char * class_name,const char * method,AddressResolver::MatchType type)54 AddressResolverName::AddressResolverName(const char *class_name,
55 const char *method,
56 AddressResolver::MatchType type)
57 : AddressResolver(), m_func_name(method), m_class_name(class_name),
58 m_regex(), m_match_type(type) {}
59
60 AddressResolverName::~AddressResolverName() = default;
61
62 // FIXME: Right now we look at the module level, and call the module's
63 // "FindFunctions".
64 // Greg says he will add function tables, maybe at the CompileUnit level to
65 // accelerate function lookup. At that point, we should switch the depth to
66 // CompileUnit, and look in these tables.
67
68 Searcher::CallbackReturn
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr)69 AddressResolverName::SearchCallback(SearchFilter &filter,
70 SymbolContext &context, Address *addr) {
71 SymbolContextList func_list;
72 SymbolContextList sym_list;
73
74 bool skip_prologue = true;
75 uint32_t i;
76 SymbolContext sc;
77 Address func_addr;
78
79 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
80
81 if (m_class_name) {
82 if (log)
83 log->Warning("Class/method function specification not supported yet.\n");
84 return Searcher::eCallbackReturnStop;
85 }
86
87 const bool include_symbols = false;
88 const bool include_inlines = true;
89 switch (m_match_type) {
90 case AddressResolver::Exact:
91 if (context.module_sp) {
92 context.module_sp->FindSymbolsWithNameAndType(m_func_name,
93 eSymbolTypeCode, sym_list);
94 context.module_sp->FindFunctions(m_func_name, CompilerDeclContext(),
95 eFunctionNameTypeAuto, include_symbols,
96 include_inlines, func_list);
97 }
98 break;
99
100 case AddressResolver::Regexp:
101 if (context.module_sp) {
102 context.module_sp->FindSymbolsMatchingRegExAndType(
103 m_regex, eSymbolTypeCode, sym_list);
104 context.module_sp->FindFunctions(m_regex, include_symbols,
105 include_inlines, func_list);
106 }
107 break;
108
109 case AddressResolver::Glob:
110 if (log)
111 log->Warning("glob is not supported yet.");
112 break;
113 }
114
115 // Remove any duplicates between the function list and the symbol list
116 if (func_list.GetSize()) {
117 for (i = 0; i < func_list.GetSize(); i++) {
118 if (!func_list.GetContextAtIndex(i, sc))
119 continue;
120
121 if (sc.function == nullptr)
122 continue;
123 uint32_t j = 0;
124 while (j < sym_list.GetSize()) {
125 SymbolContext symbol_sc;
126 if (sym_list.GetContextAtIndex(j, symbol_sc)) {
127 if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) {
128 if (sc.function->GetAddressRange().GetBaseAddress() ==
129 symbol_sc.symbol->GetAddressRef()) {
130 sym_list.RemoveContextAtIndex(j);
131 continue; // Don't increment j
132 }
133 }
134 }
135
136 j++;
137 }
138 }
139
140 for (i = 0; i < func_list.GetSize(); i++) {
141 if (func_list.GetContextAtIndex(i, sc)) {
142 if (sc.function) {
143 func_addr = sc.function->GetAddressRange().GetBaseAddress();
144 addr_t byte_size = sc.function->GetAddressRange().GetByteSize();
145 if (skip_prologue) {
146 const uint32_t prologue_byte_size =
147 sc.function->GetPrologueByteSize();
148 if (prologue_byte_size) {
149 func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size);
150 byte_size -= prologue_byte_size;
151 }
152 }
153
154 if (filter.AddressPasses(func_addr)) {
155 AddressRange new_range(func_addr, byte_size);
156 m_address_ranges.push_back(new_range);
157 }
158 }
159 }
160 }
161 }
162
163 for (i = 0; i < sym_list.GetSize(); i++) {
164 if (sym_list.GetContextAtIndex(i, sc)) {
165 if (sc.symbol && sc.symbol->ValueIsAddress()) {
166 func_addr = sc.symbol->GetAddressRef();
167 addr_t byte_size = sc.symbol->GetByteSize();
168
169 if (skip_prologue) {
170 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
171 if (prologue_byte_size) {
172 func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size);
173 byte_size -= prologue_byte_size;
174 }
175 }
176
177 if (filter.AddressPasses(func_addr)) {
178 AddressRange new_range(func_addr, byte_size);
179 m_address_ranges.push_back(new_range);
180 }
181 }
182 }
183 }
184 return Searcher::eCallbackReturnContinue;
185 }
186
GetDepth()187 lldb::SearchDepth AddressResolverName::GetDepth() {
188 return lldb::eSearchDepthModule;
189 }
190
GetDescription(Stream * s)191 void AddressResolverName::GetDescription(Stream *s) {
192 s->PutCString("Address by function name: ");
193
194 if (m_match_type == AddressResolver::Regexp)
195 s->Printf("'%s' (regular expression)", m_regex.GetText().str().c_str());
196 else
197 s->Printf("'%s'", m_func_name.AsCString());
198 }
199