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