blob: 37054d4afa7f07c96843aea203ac5ef8f328a676 [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{
107
108}
109
110BreakpointResolverName::BreakpointResolverName
111(
112 Breakpoint *bkpt,
113 const char *class_name,
114 const char *method,
Greg Clayton7dd98df2011-07-12 17:06:17 +0000115 Breakpoint::MatchType type,
116 bool skip_prologue
Chris Lattner24943d22010-06-08 16:52:24 +0000117) :
Johnny Chena62ad7c2010-10-28 17:27:46 +0000118 BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
Chris Lattner24943d22010-06-08 16:52:24 +0000119 m_func_name (method),
120 m_class_name (class_name),
121 m_regex (),
Greg Clayton7dd98df2011-07-12 17:06:17 +0000122 m_match_type (type),
123 m_skip_prologue (skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000124{
125
126}
127
128BreakpointResolverName::~BreakpointResolverName ()
129{
130}
131
132// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
133// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
134// lookup. At that point, we should switch the depth to CompileUnit, and look in these tables.
135
136Searcher::CallbackReturn
137BreakpointResolverName::SearchCallback
138(
139 SearchFilter &filter,
140 SymbolContext &context,
141 Address *addr,
142 bool containing
143)
144{
145 SymbolContextList func_list;
146 SymbolContextList sym_list;
Greg Clayton12bec712010-06-28 21:30:43 +0000147
Chris Lattner24943d22010-06-08 16:52:24 +0000148 uint32_t i;
149 bool new_location;
150 SymbolContext sc;
151 Address break_addr;
152 assert (m_breakpoint != NULL);
Greg Clayton12bec712010-06-28 21:30:43 +0000153
Greg Claytone005f2c2010-11-06 01:53:30 +0000154 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Greg Clayton12bec712010-06-28 21:30:43 +0000155
Chris Lattner24943d22010-06-08 16:52:24 +0000156 if (m_class_name)
157 {
158 if (log)
159 log->Warning ("Class/method function specification not supported yet.\n");
160 return Searcher::eCallbackReturnStop;
161 }
Greg Clayton12bec712010-06-28 21:30:43 +0000162
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000163 const bool include_symbols = false;
164 const bool append = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000165 switch (m_match_type)
166 {
Greg Clayton12bec712010-06-28 21:30:43 +0000167 case Breakpoint::Exact:
168 if (context.module_sp)
169 {
170 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
171 context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000172 context.module_sp->FindFunctions (m_func_name,
173 m_func_name_type_mask,
174 include_symbols,
175 append,
176 func_list);
Greg Clayton12bec712010-06-28 21:30:43 +0000177 }
178 break;
179 case Breakpoint::Regexp:
180 if (context.module_sp)
181 {
Caroline Ticed8ac2a12010-10-26 18:33:57 +0000182 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000183 context.module_sp->FindFunctions (m_regex,
184 include_symbols,
185 append,
186 func_list);
Greg Clayton12bec712010-06-28 21:30:43 +0000187 }
188 break;
189 case Breakpoint::Glob:
190 if (log)
191 log->Warning ("glob is not supported yet.");
192 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000193 }
Greg Clayton12bec712010-06-28 21:30:43 +0000194
Greg Clayton48fbdf72010-10-12 04:29:14 +0000195 if (!m_basename_filter.empty())
196 {
197 // Filter out any matches whose names don't contain the basename filter
198 const char *basename_filter = m_basename_filter.c_str();
199 if (func_list.GetSize())
200 {
201 bool remove = false;
202 for (i = 0; i < func_list.GetSize(); remove = false)
203 {
204 if (func_list.GetContextAtIndex(i, sc) == false)
205 remove = true;
206 else if (sc.function == NULL)
207 remove = true;
Greg Claytonfeb6e562010-11-14 00:22:48 +0000208 else
209 {
210 const InlineFunctionInfo* inlined_info = NULL;
211
212 if (sc.block)
213 inlined_info = sc.block->GetInlinedFunctionInfo();
214
215 if (inlined_info)
216 {
217 if (::strstr (inlined_info->GetName().AsCString(), basename_filter) == NULL)
218 remove = true;
219 }
220 else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL)
221 remove = true;
222 }
Greg Clayton48fbdf72010-10-12 04:29:14 +0000223
224 if (remove)
225 {
226 func_list.RemoveContextAtIndex(i);
227 continue;
228 }
229 i++;
230 }
231 }
232
233 if (sym_list.GetSize())
234 {
235 bool remove = false;
236 for (i = 0; i < sym_list.GetSize(); remove = false)
237 {
238 if (sym_list.GetContextAtIndex(i, sc) == false)
239 remove = true;
240 else if (sc.symbol == NULL)
241 remove = true;
242 else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL)
243 remove = true;
244
245 if (remove)
246 {
247 sym_list.RemoveContextAtIndex(i);
248 continue;
249 }
250 i++;
251 }
252 }
253 }
254
Chris Lattner24943d22010-06-08 16:52:24 +0000255 // Remove any duplicates between the funcion list and the symbol list
256 if (func_list.GetSize())
257 {
258 for (i = 0; i < func_list.GetSize(); i++)
259 {
260 if (func_list.GetContextAtIndex(i, sc) == false)
261 continue;
Greg Clayton12bec712010-06-28 21:30:43 +0000262
Chris Lattner24943d22010-06-08 16:52:24 +0000263 if (sc.function == NULL)
264 continue;
265 uint32_t j = 0;
266 while (j < sym_list.GetSize())
267 {
268 SymbolContext symbol_sc;
269 if (sym_list.GetContextAtIndex(j, symbol_sc))
270 {
271 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
272 {
273 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
274 {
275 sym_list.RemoveContextAtIndex(j);
276 continue; // Don't increment j
277 }
278 }
279 }
Greg Clayton12bec712010-06-28 21:30:43 +0000280
Chris Lattner24943d22010-06-08 16:52:24 +0000281 j++;
282 }
283 }
Greg Clayton12bec712010-06-28 21:30:43 +0000284
Chris Lattner24943d22010-06-08 16:52:24 +0000285 for (i = 0; i < func_list.GetSize(); i++)
286 {
287 if (func_list.GetContextAtIndex(i, sc))
288 {
Greg Claytonfeb6e562010-11-14 00:22:48 +0000289 if (sc.block && sc.block->GetInlinedFunctionInfo())
290 {
291 if (!sc.block->GetStartAddress(break_addr))
292 break_addr.Clear();
293 }
294 else if (sc.function)
Chris Lattner24943d22010-06-08 16:52:24 +0000295 {
296 break_addr = sc.function->GetAddressRange().GetBaseAddress();
Greg Clayton7dd98df2011-07-12 17:06:17 +0000297 if (m_skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000298 {
Greg Claytonfeb6e562010-11-14 00:22:48 +0000299 if (break_addr.IsValid())
300 {
301 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
302 if (prologue_byte_size)
303 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
304 }
Chris Lattner24943d22010-06-08 16:52:24 +0000305 }
Greg Claytonfeb6e562010-11-14 00:22:48 +0000306 }
307
308 if (break_addr.IsValid())
309 {
Chris Lattner24943d22010-06-08 16:52:24 +0000310 if (filter.AddressPasses(break_addr))
311 {
312 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
313 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
314 {
315 if (log)
316 {
317 StreamString s;
318 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
319 log->Printf ("Added location: %s\n", s.GetData());
320 }
321 }
322 }
323 }
324 }
325 }
326 }
Greg Clayton12bec712010-06-28 21:30:43 +0000327
Chris Lattner24943d22010-06-08 16:52:24 +0000328 for (i = 0; i < sym_list.GetSize(); i++)
329 {
330 if (sym_list.GetContextAtIndex(i, sc))
331 {
332 if (sc.symbol && sc.symbol->GetAddressRangePtr())
333 {
334 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
Greg Clayton12bec712010-06-28 21:30:43 +0000335
Greg Clayton7dd98df2011-07-12 17:06:17 +0000336 if (m_skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000337 {
338 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
339 if (prologue_byte_size)
340 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
341 }
Greg Clayton12bec712010-06-28 21:30:43 +0000342
Chris Lattner24943d22010-06-08 16:52:24 +0000343 if (filter.AddressPasses(break_addr))
344 {
345 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
346 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
347 {
348 StreamString s;
349 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
350 if (log)
351 log->Printf ("Added location: %s\n", s.GetData());
352 }
353 }
354 }
355 }
356 }
357 return Searcher::eCallbackReturnContinue;
358}
359
360Searcher::Depth
361BreakpointResolverName::GetDepth()
362{
363 return Searcher::eDepthModule;
364}
365
366void
367BreakpointResolverName::GetDescription (Stream *s)
368{
Chris Lattner24943d22010-06-08 16:52:24 +0000369 if (m_match_type == Breakpoint::Regexp)
Greg Clayton12bec712010-06-28 21:30:43 +0000370 s->Printf("regex = '%s'", m_regex.GetText());
Greg Clayton48fbdf72010-10-12 04:29:14 +0000371 else if (m_basename_filter.empty())
Greg Clayton12bec712010-06-28 21:30:43 +0000372 s->Printf("name = '%s'", m_func_name.AsCString());
Greg Clayton48fbdf72010-10-12 04:29:14 +0000373 else
374 s->Printf("name = '%s'", m_basename_filter.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000375}
376
377void
378BreakpointResolverName::Dump (Stream *s) const
379{
380
381}
382