blob: f244e3b56deec3a66742cfd6a16c98d9b2c6f895 [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"
19#include "lldb/lldb-private-log.h"
20
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,
Chris Lattner24943d22010-06-08 16:52:24 +000029 Breakpoint::MatchType type
30) :
Johnny Chena62ad7c2010-10-28 17:27:46 +000031 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
Greg Clayton48fbdf72010-10-12 04:29:14 +000032 m_func_name (),
33 m_basename_filter (),
Greg Clayton12bec712010-06-28 21:30:43 +000034 m_func_name_type_mask (func_name_type_mask),
35 m_class_name (),
Chris Lattner24943d22010-06-08 16:52:24 +000036 m_regex (),
37 m_match_type (type)
38{
Greg Clayton48fbdf72010-10-12 04:29:14 +000039 if (func_name_type_mask == eFunctionNameTypeAuto)
40 {
41 if ((::strchr (func_name, '(' ) != NULL) ||
42 (::strstr (func_name, "-[") == func_name) ||
43 (::strstr (func_name, "+[") == func_name))
44 {
45 // We have a name that contains an open parens, or starts with
46 // "+[" or "-[", so this looks like a complete function prototype
47 m_func_name_type_mask = eFunctionNameTypeFull;
48 }
49 else
50 {
51 // We don't have a full function name, but we might have a partial
52 // function basename with namespaces or classes
53 if (::strstr (func_name, "::") != NULL)
54 {
55 // Keep the full name in "m_basename_filter"
56 m_basename_filter = func_name;
57 // Now set "m_func_name" to just the function basename
58 m_func_name.SetCString(m_basename_filter.c_str() + m_basename_filter.rfind("::") + 2);
59 // We have a name with a double colon which means we have a
60 // function name that is a C++ method or a function in a C++
61 // namespace
62 m_func_name_type_mask = eFunctionNameTypeBase | eFunctionNameTypeMethod;
63 }
64 else if (::strstr (func_name, ":") != NULL)
65 {
66 // Single colon => selector
67 m_func_name_type_mask = eFunctionNameTypeSelector;
68 }
69 else
70 {
71 // just a basename by default
72 m_func_name_type_mask = eFunctionNameTypeBase;
73 }
74 }
75 }
76
77 if (!m_func_name)
78 m_func_name.SetCString(func_name);
79
Chris Lattner24943d22010-06-08 16:52:24 +000080 if (m_match_type == Breakpoint::Regexp)
81 {
82 if (!m_regex.Compile (m_func_name.AsCString()))
83 {
Greg Claytone005f2c2010-11-06 01:53:30 +000084 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +000085
86 if (log)
87 log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
88 }
89 }
90}
91
92BreakpointResolverName::BreakpointResolverName
93(
94 Breakpoint *bkpt,
95 RegularExpression &func_regex
96) :
Johnny Chena62ad7c2010-10-28 17:27:46 +000097 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
Chris Lattner24943d22010-06-08 16:52:24 +000098 m_func_name (NULL),
99 m_class_name (NULL),
100 m_regex (func_regex),
101 m_match_type (Breakpoint::Regexp)
102{
103
104}
105
106BreakpointResolverName::BreakpointResolverName
107(
108 Breakpoint *bkpt,
109 const char *class_name,
110 const char *method,
111 Breakpoint::MatchType type
112) :
Johnny Chena62ad7c2010-10-28 17:27:46 +0000113 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
Chris Lattner24943d22010-06-08 16:52:24 +0000114 m_func_name (method),
115 m_class_name (class_name),
116 m_regex (),
117 m_match_type (type)
118{
119
120}
121
122BreakpointResolverName::~BreakpointResolverName ()
123{
124}
125
126// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
127// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
128// lookup. At that point, we should switch the depth to CompileUnit, and look in these tables.
129
130Searcher::CallbackReturn
131BreakpointResolverName::SearchCallback
132(
133 SearchFilter &filter,
134 SymbolContext &context,
135 Address *addr,
136 bool containing
137)
138{
139 SymbolContextList func_list;
140 SymbolContextList sym_list;
Greg Clayton12bec712010-06-28 21:30:43 +0000141
Chris Lattner24943d22010-06-08 16:52:24 +0000142 bool skip_prologue = true;
143 uint32_t i;
144 bool new_location;
145 SymbolContext sc;
146 Address break_addr;
147 assert (m_breakpoint != NULL);
Greg Clayton12bec712010-06-28 21:30:43 +0000148
Greg Claytone005f2c2010-11-06 01:53:30 +0000149 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Greg Clayton12bec712010-06-28 21:30:43 +0000150
Chris Lattner24943d22010-06-08 16:52:24 +0000151 if (m_class_name)
152 {
153 if (log)
154 log->Warning ("Class/method function specification not supported yet.\n");
155 return Searcher::eCallbackReturnStop;
156 }
Greg Clayton12bec712010-06-28 21:30:43 +0000157
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000158 const bool include_symbols = false;
159 const bool append = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000160 switch (m_match_type)
161 {
Greg Clayton12bec712010-06-28 21:30:43 +0000162 case Breakpoint::Exact:
163 if (context.module_sp)
164 {
165 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
166 context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000167 context.module_sp->FindFunctions (m_func_name,
168 m_func_name_type_mask,
169 include_symbols,
170 append,
171 func_list);
Greg Clayton12bec712010-06-28 21:30:43 +0000172 }
173 break;
174 case Breakpoint::Regexp:
175 if (context.module_sp)
176 {
Caroline Ticed8ac2a12010-10-26 18:33:57 +0000177 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000178 context.module_sp->FindFunctions (m_regex,
179 include_symbols,
180 append,
181 func_list);
Greg Clayton12bec712010-06-28 21:30:43 +0000182 }
183 break;
184 case Breakpoint::Glob:
185 if (log)
186 log->Warning ("glob is not supported yet.");
187 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000188 }
Greg Clayton12bec712010-06-28 21:30:43 +0000189
Greg Clayton48fbdf72010-10-12 04:29:14 +0000190 if (!m_basename_filter.empty())
191 {
192 // Filter out any matches whose names don't contain the basename filter
193 const char *basename_filter = m_basename_filter.c_str();
194 if (func_list.GetSize())
195 {
196 bool remove = false;
197 for (i = 0; i < func_list.GetSize(); remove = false)
198 {
199 if (func_list.GetContextAtIndex(i, sc) == false)
200 remove = true;
201 else if (sc.function == NULL)
202 remove = true;
Greg Claytonfeb6e562010-11-14 00:22:48 +0000203 else
204 {
205 const InlineFunctionInfo* inlined_info = NULL;
206
207 if (sc.block)
208 inlined_info = sc.block->GetInlinedFunctionInfo();
209
210 if (inlined_info)
211 {
212 if (::strstr (inlined_info->GetName().AsCString(), basename_filter) == NULL)
213 remove = true;
214 }
215 else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL)
216 remove = true;
217 }
Greg Clayton48fbdf72010-10-12 04:29:14 +0000218
219 if (remove)
220 {
221 func_list.RemoveContextAtIndex(i);
222 continue;
223 }
224 i++;
225 }
226 }
227
228 if (sym_list.GetSize())
229 {
230 bool remove = false;
231 for (i = 0; i < sym_list.GetSize(); remove = false)
232 {
233 if (sym_list.GetContextAtIndex(i, sc) == false)
234 remove = true;
235 else if (sc.symbol == NULL)
236 remove = true;
237 else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL)
238 remove = true;
239
240 if (remove)
241 {
242 sym_list.RemoveContextAtIndex(i);
243 continue;
244 }
245 i++;
246 }
247 }
248 }
249
Chris Lattner24943d22010-06-08 16:52:24 +0000250 // Remove any duplicates between the funcion list and the symbol list
251 if (func_list.GetSize())
252 {
253 for (i = 0; i < func_list.GetSize(); i++)
254 {
255 if (func_list.GetContextAtIndex(i, sc) == false)
256 continue;
Greg Clayton12bec712010-06-28 21:30:43 +0000257
Chris Lattner24943d22010-06-08 16:52:24 +0000258 if (sc.function == NULL)
259 continue;
260 uint32_t j = 0;
261 while (j < sym_list.GetSize())
262 {
263 SymbolContext symbol_sc;
264 if (sym_list.GetContextAtIndex(j, symbol_sc))
265 {
266 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
267 {
268 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
269 {
270 sym_list.RemoveContextAtIndex(j);
271 continue; // Don't increment j
272 }
273 }
274 }
Greg Clayton12bec712010-06-28 21:30:43 +0000275
Chris Lattner24943d22010-06-08 16:52:24 +0000276 j++;
277 }
278 }
Greg Clayton12bec712010-06-28 21:30:43 +0000279
Chris Lattner24943d22010-06-08 16:52:24 +0000280 for (i = 0; i < func_list.GetSize(); i++)
281 {
282 if (func_list.GetContextAtIndex(i, sc))
283 {
Greg Claytonfeb6e562010-11-14 00:22:48 +0000284 if (sc.block && sc.block->GetInlinedFunctionInfo())
285 {
286 if (!sc.block->GetStartAddress(break_addr))
287 break_addr.Clear();
288 }
289 else if (sc.function)
Chris Lattner24943d22010-06-08 16:52:24 +0000290 {
291 break_addr = sc.function->GetAddressRange().GetBaseAddress();
292 if (skip_prologue)
293 {
Greg Claytonfeb6e562010-11-14 00:22:48 +0000294 if (break_addr.IsValid())
295 {
296 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
297 if (prologue_byte_size)
298 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
299 }
Chris Lattner24943d22010-06-08 16:52:24 +0000300 }
Greg Claytonfeb6e562010-11-14 00:22:48 +0000301 }
302
303 if (break_addr.IsValid())
304 {
Chris Lattner24943d22010-06-08 16:52:24 +0000305 if (filter.AddressPasses(break_addr))
306 {
307 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
308 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
309 {
310 if (log)
311 {
312 StreamString s;
313 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
314 log->Printf ("Added location: %s\n", s.GetData());
315 }
316 }
317 }
318 }
319 }
320 }
321 }
Greg Clayton12bec712010-06-28 21:30:43 +0000322
Chris Lattner24943d22010-06-08 16:52:24 +0000323 for (i = 0; i < sym_list.GetSize(); i++)
324 {
325 if (sym_list.GetContextAtIndex(i, sc))
326 {
327 if (sc.symbol && sc.symbol->GetAddressRangePtr())
328 {
329 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
Greg Clayton12bec712010-06-28 21:30:43 +0000330
Chris Lattner24943d22010-06-08 16:52:24 +0000331 if (skip_prologue)
332 {
333 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
334 if (prologue_byte_size)
335 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
336 }
Greg Clayton12bec712010-06-28 21:30:43 +0000337
Chris Lattner24943d22010-06-08 16:52:24 +0000338 if (filter.AddressPasses(break_addr))
339 {
340 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
341 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
342 {
343 StreamString s;
344 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
345 if (log)
346 log->Printf ("Added location: %s\n", s.GetData());
347 }
348 }
349 }
350 }
351 }
352 return Searcher::eCallbackReturnContinue;
353}
354
355Searcher::Depth
356BreakpointResolverName::GetDepth()
357{
358 return Searcher::eDepthModule;
359}
360
361void
362BreakpointResolverName::GetDescription (Stream *s)
363{
Chris Lattner24943d22010-06-08 16:52:24 +0000364 if (m_match_type == Breakpoint::Regexp)
Greg Clayton12bec712010-06-28 21:30:43 +0000365 s->Printf("regex = '%s'", m_regex.GetText());
Greg Clayton48fbdf72010-10-12 04:29:14 +0000366 else if (m_basename_filter.empty())
Greg Clayton12bec712010-06-28 21:30:43 +0000367 s->Printf("name = '%s'", m_func_name.AsCString());
Greg Clayton48fbdf72010-10-12 04:29:14 +0000368 else
369 s->Printf("name = '%s'", m_basename_filter.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000370}
371
372void
373BreakpointResolverName::Dump (Stream *s) const
374{
375
376}
377