1 //===-- BreakpointResolverName.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/Breakpoint/BreakpointResolverName.h"
11
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/StreamString.h"
20 #include "lldb/Symbol/ClangNamespaceDecl.h"
21 #include "lldb/Symbol/Block.h"
22 #include "lldb/Symbol/Function.h"
23 #include "lldb/Symbol/Symbol.h"
24 #include "lldb/Symbol/SymbolContext.h"
25 #include "lldb/Target/ObjCLanguageRuntime.h"
26
27 using namespace lldb;
28 using namespace lldb_private;
29
BreakpointResolverName(Breakpoint * bkpt,const char * name_cstr,uint32_t name_type_mask,Breakpoint::MatchType type,bool skip_prologue)30 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
31 const char *name_cstr,
32 uint32_t name_type_mask,
33 Breakpoint::MatchType type,
34 bool skip_prologue) :
35 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
36 m_class_name (),
37 m_regex (),
38 m_match_type (type),
39 m_skip_prologue (skip_prologue)
40 {
41
42 if (m_match_type == Breakpoint::Regexp)
43 {
44 if (!m_regex.Compile (name_cstr))
45 {
46 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
47
48 if (log)
49 log->Warning ("function name regexp: \"%s\" did not compile.", name_cstr);
50 }
51 }
52 else
53 {
54 AddNameLookup (ConstString(name_cstr), name_type_mask);
55 }
56 }
57
BreakpointResolverName(Breakpoint * bkpt,const char * names[],size_t num_names,uint32_t name_type_mask,bool skip_prologue)58 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
59 const char *names[],
60 size_t num_names,
61 uint32_t name_type_mask,
62 bool skip_prologue) :
63 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
64 m_match_type (Breakpoint::Exact),
65 m_skip_prologue (skip_prologue)
66 {
67 for (size_t i = 0; i < num_names; i++)
68 {
69 AddNameLookup (ConstString (names[i]), name_type_mask);
70 }
71 }
72
BreakpointResolverName(Breakpoint * bkpt,std::vector<std::string> names,uint32_t name_type_mask,bool skip_prologue)73 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
74 std::vector<std::string> names,
75 uint32_t name_type_mask,
76 bool skip_prologue) :
77 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
78 m_match_type (Breakpoint::Exact),
79 m_skip_prologue (skip_prologue)
80 {
81 for (const std::string& name : names)
82 {
83 AddNameLookup (ConstString (name.c_str(), name.size()), name_type_mask);
84 }
85 }
86
BreakpointResolverName(Breakpoint * bkpt,RegularExpression & func_regex,bool skip_prologue)87 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
88 RegularExpression &func_regex,
89 bool skip_prologue) :
90 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
91 m_class_name (NULL),
92 m_regex (func_regex),
93 m_match_type (Breakpoint::Regexp),
94 m_skip_prologue (skip_prologue)
95 {
96 }
97
BreakpointResolverName(Breakpoint * bkpt,const char * class_name,const char * method,Breakpoint::MatchType type,bool skip_prologue)98 BreakpointResolverName::BreakpointResolverName
99 (
100 Breakpoint *bkpt,
101 const char *class_name,
102 const char *method,
103 Breakpoint::MatchType type,
104 bool skip_prologue
105 ) :
106 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
107 m_class_name (class_name),
108 m_regex (),
109 m_match_type (type),
110 m_skip_prologue (skip_prologue)
111 {
112 LookupInfo lookup;
113 lookup.name.SetCString(method);
114 lookup.lookup_name = lookup.name;
115 lookup.name_type_mask = eFunctionNameTypeMethod;
116 lookup.match_name_after_lookup = false;
117 m_lookups.push_back (lookup);
118 }
119
~BreakpointResolverName()120 BreakpointResolverName::~BreakpointResolverName ()
121 {
122 }
123
124 void
AddNameLookup(const ConstString & name,uint32_t name_type_mask)125 BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_type_mask)
126 {
127 ObjCLanguageRuntime::MethodName objc_method(name.GetCString(), false);
128 if (objc_method.IsValid(false))
129 {
130 std::vector<ConstString> objc_names;
131 objc_method.GetFullNames(objc_names, true);
132 for (ConstString objc_name : objc_names)
133 {
134 LookupInfo lookup;
135 lookup.name = name;
136 lookup.lookup_name = objc_name;
137 lookup.name_type_mask = eFunctionNameTypeFull;
138 lookup.match_name_after_lookup = false;
139 m_lookups.push_back (lookup);
140 }
141 }
142 else
143 {
144 LookupInfo lookup;
145 lookup.name = name;
146 Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup);
147 m_lookups.push_back (lookup);
148 }
149 }
150
151
152 void
Prune(SymbolContextList & sc_list,size_t start_idx) const153 BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const
154 {
155 if (match_name_after_lookup && name)
156 {
157 SymbolContext sc;
158 size_t i = start_idx;
159 while (i < sc_list.GetSize())
160 {
161 if (!sc_list.GetContextAtIndex(i, sc))
162 break;
163 ConstString full_name (sc.GetFunctionName());
164 if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == NULL)
165 {
166 sc_list.RemoveContextAtIndex(i);
167 }
168 else
169 {
170 ++i;
171 }
172 }
173 }
174 }
175
176
177 // FIXME: Right now we look at the module level, and call the module's "FindFunctions".
178 // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
179 // lookup. At that point, we should switch the depth to CompileUnit, and look in these tables.
180
181 Searcher::CallbackReturn
SearchCallback(SearchFilter & filter,SymbolContext & context,Address * addr,bool containing)182 BreakpointResolverName::SearchCallback
183 (
184 SearchFilter &filter,
185 SymbolContext &context,
186 Address *addr,
187 bool containing
188 )
189 {
190 SymbolContextList func_list;
191 //SymbolContextList sym_list;
192
193 uint32_t i;
194 bool new_location;
195 Address break_addr;
196 assert (m_breakpoint != NULL);
197
198 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
199
200 if (m_class_name)
201 {
202 if (log)
203 log->Warning ("Class/method function specification not supported yet.\n");
204 return Searcher::eCallbackReturnStop;
205 }
206 bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
207 const bool include_symbols = filter_by_cu == false;
208 const bool include_inlines = true;
209 const bool append = true;
210
211 switch (m_match_type)
212 {
213 case Breakpoint::Exact:
214 if (context.module_sp)
215 {
216 for (const LookupInfo &lookup : m_lookups)
217 {
218 const size_t start_func_idx = func_list.GetSize();
219 context.module_sp->FindFunctions (lookup.lookup_name,
220 NULL,
221 lookup.name_type_mask,
222 include_symbols,
223 include_inlines,
224 append,
225 func_list);
226 const size_t end_func_idx = func_list.GetSize();
227
228 if (start_func_idx < end_func_idx)
229 lookup.Prune (func_list, start_func_idx);
230 }
231 }
232 break;
233 case Breakpoint::Regexp:
234 if (context.module_sp)
235 {
236 context.module_sp->FindFunctions (m_regex,
237 !filter_by_cu, // include symbols only if we aren't filterning by CU
238 include_inlines,
239 append,
240 func_list);
241 }
242 break;
243 case Breakpoint::Glob:
244 if (log)
245 log->Warning ("glob is not supported yet.");
246 break;
247 }
248
249 // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point.
250 if (filter_by_cu)
251 {
252 uint32_t num_functions = func_list.GetSize();
253
254 for (size_t idx = 0; idx < num_functions; idx++)
255 {
256 SymbolContext sc;
257 func_list.GetContextAtIndex(idx, sc);
258 if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit))
259 {
260 func_list.RemoveContextAtIndex(idx);
261 num_functions--;
262 idx--;
263 }
264 }
265 }
266
267 // Remove any duplicates between the funcion list and the symbol list
268 SymbolContext sc;
269 if (func_list.GetSize())
270 {
271 for (i = 0; i < func_list.GetSize(); i++)
272 {
273 if (func_list.GetContextAtIndex(i, sc))
274 {
275 bool is_reexported = false;
276
277 if (sc.block && sc.block->GetInlinedFunctionInfo())
278 {
279 if (!sc.block->GetStartAddress(break_addr))
280 break_addr.Clear();
281 }
282 else if (sc.function)
283 {
284 break_addr = sc.function->GetAddressRange().GetBaseAddress();
285 if (m_skip_prologue && break_addr.IsValid())
286 {
287 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
288 if (prologue_byte_size)
289 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
290 }
291 }
292 else if (sc.symbol)
293 {
294 if (sc.symbol->GetType() == eSymbolTypeReExported)
295 {
296 const Symbol *actual_symbol = sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget());
297 if (actual_symbol)
298 {
299 is_reexported = true;
300 break_addr = actual_symbol->GetAddress();
301 }
302 }
303 else
304 {
305 break_addr = sc.symbol->GetAddress();
306 }
307
308 if (m_skip_prologue && break_addr.IsValid())
309 {
310 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
311 if (prologue_byte_size)
312 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
313 }
314 }
315
316 if (break_addr.IsValid())
317 {
318 if (filter.AddressPasses(break_addr))
319 {
320 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
321 bp_loc_sp->SetIsReExported(is_reexported);
322 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
323 {
324 if (log)
325 {
326 StreamString s;
327 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
328 log->Printf ("Added location: %s\n", s.GetData());
329 }
330 }
331 }
332 }
333 }
334 }
335 }
336
337 return Searcher::eCallbackReturnContinue;
338 }
339
340 Searcher::Depth
GetDepth()341 BreakpointResolverName::GetDepth()
342 {
343 return Searcher::eDepthModule;
344 }
345
346 void
GetDescription(Stream * s)347 BreakpointResolverName::GetDescription (Stream *s)
348 {
349 if (m_match_type == Breakpoint::Regexp)
350 s->Printf("regex = '%s'", m_regex.GetText());
351 else
352 {
353 size_t num_names = m_lookups.size();
354 if (num_names == 1)
355 s->Printf("name = '%s'", m_lookups[0].name.GetCString());
356 else
357 {
358 s->Printf("names = {");
359 for (size_t i = 0; i < num_names - 1; i++)
360 {
361 s->Printf ("'%s', ", m_lookups[i].name.GetCString());
362 }
363 s->Printf ("'%s'}", m_lookups[num_names - 1].name.GetCString());
364 }
365 }
366 }
367
368 void
Dump(Stream * s) const369 BreakpointResolverName::Dump (Stream *s) const
370 {
371
372 }
373
374