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