blob: 42889091a979949cc1d1cebd6d3d25c80cd4dd22 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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/StreamString.h"
Greg Clayton17cd9952011-04-22 03:55:06 +000019#include "lldb/Target/Target.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020
21using namespace lldb;
22using namespace lldb_private;
23
24BreakpointResolverName::BreakpointResolverName
25(
26 Breakpoint *bkpt,
27 const char *func_name,
Greg Clayton12bec712010-06-28 21:30:43 +000028 uint32_t func_name_type_mask,
Greg Clayton7dd98df2011-07-12 17:06:17 +000029 Breakpoint::MatchType type,
30 bool skip_prologue
Chris Lattner24943d22010-06-08 16:52:24 +000031) :
Johnny Chena62ad7c2010-10-28 17:27:46 +000032 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
Greg Clayton48fbdf72010-10-12 04:29:14 +000033 m_func_name (),
34 m_basename_filter (),
Greg Clayton12bec712010-06-28 21:30:43 +000035 m_func_name_type_mask (func_name_type_mask),
36 m_class_name (),
Chris Lattner24943d22010-06-08 16:52:24 +000037 m_regex (),
Greg Clayton7dd98df2011-07-12 17:06:17 +000038 m_match_type (type),
39 m_skip_prologue (skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +000040{
Greg Clayton48fbdf72010-10-12 04:29:14 +000041 if (func_name_type_mask == eFunctionNameTypeAuto)
42 {
43 if ((::strchr (func_name, '(' ) != NULL) ||
44 (::strstr (func_name, "-[") == func_name) ||
45 (::strstr (func_name, "+[") == func_name))
46 {
47 // We have a name that contains an open parens, or starts with
48 // "+[" or "-[", so this looks like a complete function prototype
49 m_func_name_type_mask = eFunctionNameTypeFull;
50 }
51 else
52 {
53 // We don't have a full function name, but we might have a partial
54 // function basename with namespaces or classes
55 if (::strstr (func_name, "::") != NULL)
56 {
57 // Keep the full name in "m_basename_filter"
58 m_basename_filter = func_name;
59 // Now set "m_func_name" to just the function basename
60 m_func_name.SetCString(m_basename_filter.c_str() + m_basename_filter.rfind("::") + 2);
61 // We have a name with a double colon which means we have a
62 // function name that is a C++ method or a function in a C++
63 // namespace
64 m_func_name_type_mask = eFunctionNameTypeBase | eFunctionNameTypeMethod;
65 }
66 else if (::strstr (func_name, ":") != NULL)
67 {
68 // Single colon => selector
69 m_func_name_type_mask = eFunctionNameTypeSelector;
70 }
71 else
72 {
73 // just a basename by default
74 m_func_name_type_mask = eFunctionNameTypeBase;
75 }
76 }
77 }
78
79 if (!m_func_name)
80 m_func_name.SetCString(func_name);
81
Chris Lattner24943d22010-06-08 16:52:24 +000082 if (m_match_type == Breakpoint::Regexp)
83 {
84 if (!m_regex.Compile (m_func_name.AsCString()))
85 {
Greg Claytone005f2c2010-11-06 01:53:30 +000086 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +000087
88 if (log)
89 log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
90 }
91 }
92}
93
94BreakpointResolverName::BreakpointResolverName
95(
96 Breakpoint *bkpt,
Greg Clayton7dd98df2011-07-12 17:06:17 +000097 RegularExpression &func_regex,
98 bool skip_prologue
Chris Lattner24943d22010-06-08 16:52:24 +000099) :
Johnny Chena62ad7c2010-10-28 17:27:46 +0000100 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
Chris Lattner24943d22010-06-08 16:52:24 +0000101 m_func_name (NULL),
102 m_class_name (NULL),
103 m_regex (func_regex),
Greg Clayton7dd98df2011-07-12 17:06:17 +0000104 m_match_type (Breakpoint::Regexp),
105 m_skip_prologue (skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000106{
Chris Lattner24943d22010-06-08 16:52:24 +0000107}
108
109BreakpointResolverName::BreakpointResolverName
110(
111 Breakpoint *bkpt,
112 const char *class_name,
113 const char *method,
Greg Clayton7dd98df2011-07-12 17:06:17 +0000114 Breakpoint::MatchType type,
115 bool skip_prologue
Chris Lattner24943d22010-06-08 16:52:24 +0000116) :
Johnny Chena62ad7c2010-10-28 17:27:46 +0000117 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
Chris Lattner24943d22010-06-08 16:52:24 +0000118 m_func_name (method),
119 m_class_name (class_name),
120 m_regex (),
Greg Clayton7dd98df2011-07-12 17:06:17 +0000121 m_match_type (type),
122 m_skip_prologue (skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000123{
124
125}
126
127BreakpointResolverName::~BreakpointResolverName ()
128{
129}
130
131// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
132// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
133// lookup. At that point, we should switch the depth to CompileUnit, and look in these tables.
134
135Searcher::CallbackReturn
136BreakpointResolverName::SearchCallback
137(
138 SearchFilter &filter,
139 SymbolContext &context,
140 Address *addr,
141 bool containing
142)
143{
144 SymbolContextList func_list;
145 SymbolContextList sym_list;
Greg Clayton12bec712010-06-28 21:30:43 +0000146
Chris Lattner24943d22010-06-08 16:52:24 +0000147 uint32_t i;
148 bool new_location;
149 SymbolContext sc;
150 Address break_addr;
151 assert (m_breakpoint != NULL);
Greg Clayton12bec712010-06-28 21:30:43 +0000152
Greg Claytone005f2c2010-11-06 01:53:30 +0000153 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Greg Clayton12bec712010-06-28 21:30:43 +0000154
Chris Lattner24943d22010-06-08 16:52:24 +0000155 if (m_class_name)
156 {
157 if (log)
158 log->Warning ("Class/method function specification not supported yet.\n");
159 return Searcher::eCallbackReturnStop;
160 }
Greg Clayton12bec712010-06-28 21:30:43 +0000161
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000162 const bool include_symbols = false;
163 const bool append = false;
Jim Inghamd6d47972011-09-23 00:54:11 +0000164 bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
165
Chris Lattner24943d22010-06-08 16:52:24 +0000166 switch (m_match_type)
167 {
Greg Clayton12bec712010-06-28 21:30:43 +0000168 case Breakpoint::Exact:
169 if (context.module_sp)
170 {
Jim Inghamd6d47972011-09-23 00:54:11 +0000171 uint32_t num_functions = context.module_sp->FindFunctions (m_func_name,
Greg Claytond74270e2011-09-02 04:03:59 +0000172 m_func_name_type_mask,
173 include_symbols,
174 append,
Jim Inghamd6d47972011-09-23 00:54:11 +0000175 func_list);
176 // If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain
177 // symbols, since all the ones from a set compilation unit will have been found above already.
178
179 if (num_functions == 0 && !filter_by_cu)
Greg Claytond74270e2011-09-02 04:03:59 +0000180 {
181 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
182 context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
183 }
Greg Clayton12bec712010-06-28 21:30:43 +0000184 }
185 break;
186 case Breakpoint::Regexp:
187 if (context.module_sp)
188 {
Jim Inghamd6d47972011-09-23 00:54:11 +0000189 if (!filter_by_cu)
190 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000191 context.module_sp->FindFunctions (m_regex,
192 include_symbols,
193 append,
194 func_list);
Greg Clayton12bec712010-06-28 21:30:43 +0000195 }
196 break;
197 case Breakpoint::Glob:
198 if (log)
199 log->Warning ("glob is not supported yet.");
200 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000201 }
Jim Inghamd6d47972011-09-23 00:54:11 +0000202
203 // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point.
204 if (filter_by_cu)
205 {
206 uint32_t num_functions = func_list.GetSize();
207
208 for (size_t idx = 0; idx < num_functions; idx++)
209 {
210 SymbolContext sc;
211 func_list.GetContextAtIndex(idx, sc);
212 if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit))
213 {
214 func_list.RemoveContextAtIndex(idx);
215 num_functions--;
216 idx--;
217 }
218 }
219 }
220
221
Greg Clayton48fbdf72010-10-12 04:29:14 +0000222 if (!m_basename_filter.empty())
223 {
224 // Filter out any matches whose names don't contain the basename filter
225 const char *basename_filter = m_basename_filter.c_str();
226 if (func_list.GetSize())
227 {
228 bool remove = false;
229 for (i = 0; i < func_list.GetSize(); remove = false)
230 {
231 if (func_list.GetContextAtIndex(i, sc) == false)
232 remove = true;
233 else if (sc.function == NULL)
234 remove = true;
Greg Claytonfeb6e562010-11-14 00:22:48 +0000235 else
236 {
237 const InlineFunctionInfo* inlined_info = NULL;
238
239 if (sc.block)
240 inlined_info = sc.block->GetInlinedFunctionInfo();
241
242 if (inlined_info)
243 {
244 if (::strstr (inlined_info->GetName().AsCString(), basename_filter) == NULL)
245 remove = true;
246 }
247 else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL)
248 remove = true;
249 }
Greg Clayton48fbdf72010-10-12 04:29:14 +0000250
251 if (remove)
252 {
253 func_list.RemoveContextAtIndex(i);
254 continue;
255 }
256 i++;
257 }
258 }
259
260 if (sym_list.GetSize())
261 {
262 bool remove = false;
263 for (i = 0; i < sym_list.GetSize(); remove = false)
264 {
265 if (sym_list.GetContextAtIndex(i, sc) == false)
266 remove = true;
267 else if (sc.symbol == NULL)
268 remove = true;
269 else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL)
270 remove = true;
271
272 if (remove)
273 {
274 sym_list.RemoveContextAtIndex(i);
275 continue;
276 }
277 i++;
278 }
279 }
280 }
281
Chris Lattner24943d22010-06-08 16:52:24 +0000282 // Remove any duplicates between the funcion list and the symbol list
283 if (func_list.GetSize())
284 {
285 for (i = 0; i < func_list.GetSize(); i++)
286 {
287 if (func_list.GetContextAtIndex(i, sc) == false)
288 continue;
Greg Clayton12bec712010-06-28 21:30:43 +0000289
Chris Lattner24943d22010-06-08 16:52:24 +0000290 if (sc.function == NULL)
291 continue;
292 uint32_t j = 0;
293 while (j < sym_list.GetSize())
294 {
295 SymbolContext symbol_sc;
296 if (sym_list.GetContextAtIndex(j, symbol_sc))
297 {
298 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
299 {
300 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
301 {
302 sym_list.RemoveContextAtIndex(j);
303 continue; // Don't increment j
304 }
305 }
306 }
Greg Clayton12bec712010-06-28 21:30:43 +0000307
Chris Lattner24943d22010-06-08 16:52:24 +0000308 j++;
309 }
310 }
Greg Clayton12bec712010-06-28 21:30:43 +0000311
Chris Lattner24943d22010-06-08 16:52:24 +0000312 for (i = 0; i < func_list.GetSize(); i++)
313 {
314 if (func_list.GetContextAtIndex(i, sc))
315 {
Greg Claytonfeb6e562010-11-14 00:22:48 +0000316 if (sc.block && sc.block->GetInlinedFunctionInfo())
317 {
318 if (!sc.block->GetStartAddress(break_addr))
319 break_addr.Clear();
320 }
321 else if (sc.function)
Chris Lattner24943d22010-06-08 16:52:24 +0000322 {
323 break_addr = sc.function->GetAddressRange().GetBaseAddress();
Greg Clayton7dd98df2011-07-12 17:06:17 +0000324 if (m_skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000325 {
Greg Claytonfeb6e562010-11-14 00:22:48 +0000326 if (break_addr.IsValid())
327 {
328 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
329 if (prologue_byte_size)
330 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
331 }
Chris Lattner24943d22010-06-08 16:52:24 +0000332 }
Greg Claytonfeb6e562010-11-14 00:22:48 +0000333 }
334
335 if (break_addr.IsValid())
336 {
Chris Lattner24943d22010-06-08 16:52:24 +0000337 if (filter.AddressPasses(break_addr))
338 {
339 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
340 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
341 {
342 if (log)
343 {
344 StreamString s;
345 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
346 log->Printf ("Added location: %s\n", s.GetData());
347 }
348 }
349 }
350 }
351 }
352 }
353 }
Greg Clayton12bec712010-06-28 21:30:43 +0000354
Chris Lattner24943d22010-06-08 16:52:24 +0000355 for (i = 0; i < sym_list.GetSize(); i++)
356 {
357 if (sym_list.GetContextAtIndex(i, sc))
358 {
359 if (sc.symbol && sc.symbol->GetAddressRangePtr())
360 {
361 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
Greg Clayton12bec712010-06-28 21:30:43 +0000362
Greg Clayton7dd98df2011-07-12 17:06:17 +0000363 if (m_skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000364 {
365 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
366 if (prologue_byte_size)
367 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
368 }
Greg Clayton12bec712010-06-28 21:30:43 +0000369
Chris Lattner24943d22010-06-08 16:52:24 +0000370 if (filter.AddressPasses(break_addr))
371 {
372 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
373 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
374 {
375 StreamString s;
376 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
377 if (log)
378 log->Printf ("Added location: %s\n", s.GetData());
379 }
380 }
381 }
382 }
383 }
384 return Searcher::eCallbackReturnContinue;
385}
386
387Searcher::Depth
388BreakpointResolverName::GetDepth()
389{
390 return Searcher::eDepthModule;
391}
392
393void
394BreakpointResolverName::GetDescription (Stream *s)
395{
Chris Lattner24943d22010-06-08 16:52:24 +0000396 if (m_match_type == Breakpoint::Regexp)
Greg Clayton12bec712010-06-28 21:30:43 +0000397 s->Printf("regex = '%s'", m_regex.GetText());
Greg Clayton48fbdf72010-10-12 04:29:14 +0000398 else if (m_basename_filter.empty())
Greg Clayton12bec712010-06-28 21:30:43 +0000399 s->Printf("name = '%s'", m_func_name.AsCString());
Greg Clayton48fbdf72010-10-12 04:29:14 +0000400 else
401 s->Printf("name = '%s'", m_basename_filter.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000402}
403
404void
405BreakpointResolverName::Dump (Stream *s) const
406{
407
408}
409