]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/AddressResolverName.cpp
MFV r340865:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / AddressResolverName.cpp
1 //===-- AddressResolverName.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Core/AddressResolverName.h"
11
12 #include "lldb/Core/Address.h"      // for Address, operator==
13 #include "lldb/Core/AddressRange.h" // for AddressRange
14 #include "lldb/Core/Module.h"
15 #include "lldb/Symbol/Function.h"
16 #include "lldb/Symbol/Symbol.h"
17 #include "lldb/Symbol/SymbolContext.h"
18 #include "lldb/Utility/Log.h"
19 #include "lldb/Utility/Logging.h"   // for GetLogIfAllCategoriesSet, LIB...
20 #include "lldb/Utility/Stream.h"    // for Stream
21 #include "lldb/lldb-enumerations.h" // for SymbolType::eSymbolTypeCode
22 #include "lldb/lldb-forward.h"      // for ModuleSP
23 #include "lldb/lldb-types.h"        // for addr_t
24 #include "llvm/ADT/StringRef.h"     // for StringRef
25
26 #include <memory> // for shared_ptr
27 #include <string> // for string
28 #include <vector> // for vector
29
30 #include <stdint.h> // for uint32_t
31
32 using namespace lldb;
33 using namespace lldb_private;
34
35 AddressResolverName::AddressResolverName(const char *func_name,
36                                          AddressResolver::MatchType type)
37     : AddressResolver(), m_func_name(func_name), m_class_name(nullptr),
38       m_regex(), m_match_type(type) {
39   if (m_match_type == AddressResolver::Regexp) {
40     if (!m_regex.Compile(m_func_name.GetStringRef())) {
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
50 AddressResolverName::AddressResolverName(RegularExpression &func_regex)
51     : AddressResolver(), m_func_name(nullptr), m_class_name(nullptr),
52       m_regex(func_regex), m_match_type(AddressResolver::Regexp) {}
53
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
66 // lookup.  At that point, we should switch the depth to CompileUnit, and look
67 // in these tables.
68
69 Searcher::CallbackReturn
70 AddressResolverName::SearchCallback(SearchFilter &filter,
71                                     SymbolContext &context, Address *addr,
72                                     bool containing) {
73   SymbolContextList func_list;
74   SymbolContextList sym_list;
75
76   bool skip_prologue = true;
77   uint32_t i;
78   SymbolContext sc;
79   Address func_addr;
80
81   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
82
83   if (m_class_name) {
84     if (log)
85       log->Warning("Class/method function specification not supported yet.\n");
86     return Searcher::eCallbackReturnStop;
87   }
88
89   const bool include_symbols = false;
90   const bool include_inlines = true;
91   const bool append = false;
92   switch (m_match_type) {
93   case AddressResolver::Exact:
94     if (context.module_sp) {
95       context.module_sp->FindSymbolsWithNameAndType(m_func_name,
96                                                     eSymbolTypeCode, sym_list);
97       context.module_sp->FindFunctions(m_func_name, nullptr,
98                                        eFunctionNameTypeAuto, include_symbols,
99                                        include_inlines, append, func_list);
100     }
101     break;
102
103   case AddressResolver::Regexp:
104     if (context.module_sp) {
105       context.module_sp->FindSymbolsMatchingRegExAndType(
106           m_regex, eSymbolTypeCode, sym_list);
107       context.module_sp->FindFunctions(m_regex, include_symbols,
108                                        include_inlines, append, func_list);
109     }
110     break;
111
112   case AddressResolver::Glob:
113     if (log)
114       log->Warning("glob is not supported yet.");
115     break;
116   }
117
118   // Remove any duplicates between the function list and the symbol list
119   if (func_list.GetSize()) {
120     for (i = 0; i < func_list.GetSize(); i++) {
121       if (!func_list.GetContextAtIndex(i, sc))
122         continue;
123
124       if (sc.function == nullptr)
125         continue;
126       uint32_t j = 0;
127       while (j < sym_list.GetSize()) {
128         SymbolContext symbol_sc;
129         if (sym_list.GetContextAtIndex(j, symbol_sc)) {
130           if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) {
131             if (sc.function->GetAddressRange().GetBaseAddress() ==
132                 symbol_sc.symbol->GetAddressRef()) {
133               sym_list.RemoveContextAtIndex(j);
134               continue; // Don't increment j
135             }
136           }
137         }
138
139         j++;
140       }
141     }
142
143     for (i = 0; i < func_list.GetSize(); i++) {
144       if (func_list.GetContextAtIndex(i, sc)) {
145         if (sc.function) {
146           func_addr = sc.function->GetAddressRange().GetBaseAddress();
147           addr_t byte_size = sc.function->GetAddressRange().GetByteSize();
148           if (skip_prologue) {
149             const uint32_t prologue_byte_size =
150                 sc.function->GetPrologueByteSize();
151             if (prologue_byte_size) {
152               func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size);
153               byte_size -= prologue_byte_size;
154             }
155           }
156
157           if (filter.AddressPasses(func_addr)) {
158             AddressRange new_range(func_addr, byte_size);
159             m_address_ranges.push_back(new_range);
160           }
161         }
162       }
163     }
164   }
165
166   for (i = 0; i < sym_list.GetSize(); i++) {
167     if (sym_list.GetContextAtIndex(i, sc)) {
168       if (sc.symbol && sc.symbol->ValueIsAddress()) {
169         func_addr = sc.symbol->GetAddressRef();
170         addr_t byte_size = sc.symbol->GetByteSize();
171
172         if (skip_prologue) {
173           const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
174           if (prologue_byte_size) {
175             func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size);
176             byte_size -= prologue_byte_size;
177           }
178         }
179
180         if (filter.AddressPasses(func_addr)) {
181           AddressRange new_range(func_addr, byte_size);
182           m_address_ranges.push_back(new_range);
183         }
184       }
185     }
186   }
187   return Searcher::eCallbackReturnContinue;
188 }
189
190 Searcher::Depth AddressResolverName::GetDepth() {
191   return Searcher::eDepthModule;
192 }
193
194 void AddressResolverName::GetDescription(Stream *s) {
195   s->PutCString("Address by function name: ");
196
197   if (m_match_type == AddressResolver::Regexp)
198     s->Printf("'%s' (regular expression)", m_regex.GetText().str().c_str());
199   else
200     s->Printf("'%s'", m_func_name.AsCString());
201 }