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