blob: 141a15bef7df9de0b9b79620c194734c5c7531dd [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;
Chris Lattner24943d22010-06-08 16:52:24 +0000164 switch (m_match_type)
165 {
Greg Clayton12bec712010-06-28 21:30:43 +0000166 case Breakpoint::Exact:
167 if (context.module_sp)
168 {
Greg Claytond74270e2011-09-02 04:03:59 +0000169 if (context.module_sp->FindFunctions (m_func_name,
170 m_func_name_type_mask,
171 include_symbols,
172 append,
173 func_list) == 0)
174 {
175 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
176 context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
177 }
Greg Clayton12bec712010-06-28 21:30:43 +0000178 }
179 break;
180 case Breakpoint::Regexp:
181 if (context.module_sp)
182 {
Caroline Ticed8ac2a12010-10-26 18:33:57 +0000183 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
Greg Clayton28d5fcc2011-01-27 06:44:37 +0000184 context.module_sp->FindFunctions (m_regex,
185 include_symbols,
186 append,
187 func_list);
Greg Clayton12bec712010-06-28 21:30:43 +0000188 }
189 break;
190 case Breakpoint::Glob:
191 if (log)
192 log->Warning ("glob is not supported yet.");
193 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000194 }
Greg Clayton12bec712010-06-28 21:30:43 +0000195
Greg Clayton48fbdf72010-10-12 04:29:14 +0000196 if (!m_basename_filter.empty())
197 {
198 // Filter out any matches whose names don't contain the basename filter
199 const char *basename_filter = m_basename_filter.c_str();
200 if (func_list.GetSize())
201 {
202 bool remove = false;
203 for (i = 0; i < func_list.GetSize(); remove = false)
204 {
205 if (func_list.GetContextAtIndex(i, sc) == false)
206 remove = true;
207 else if (sc.function == NULL)
208 remove = true;
Greg Claytonfeb6e562010-11-14 00:22:48 +0000209 else
210 {
211 const InlineFunctionInfo* inlined_info = NULL;
212
213 if (sc.block)
214 inlined_info = sc.block->GetInlinedFunctionInfo();
215
216 if (inlined_info)
217 {
218 if (::strstr (inlined_info->GetName().AsCString(), basename_filter) == NULL)
219 remove = true;
220 }
221 else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL)
222 remove = true;
223 }
Greg Clayton48fbdf72010-10-12 04:29:14 +0000224
225 if (remove)
226 {
227 func_list.RemoveContextAtIndex(i);
228 continue;
229 }
230 i++;
231 }
232 }
233
234 if (sym_list.GetSize())
235 {
236 bool remove = false;
237 for (i = 0; i < sym_list.GetSize(); remove = false)
238 {
239 if (sym_list.GetContextAtIndex(i, sc) == false)
240 remove = true;
241 else if (sc.symbol == NULL)
242 remove = true;
243 else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL)
244 remove = true;
245
246 if (remove)
247 {
248 sym_list.RemoveContextAtIndex(i);
249 continue;
250 }
251 i++;
252 }
253 }
254 }
255
Chris Lattner24943d22010-06-08 16:52:24 +0000256 // Remove any duplicates between the funcion list and the symbol list
257 if (func_list.GetSize())
258 {
259 for (i = 0; i < func_list.GetSize(); i++)
260 {
261 if (func_list.GetContextAtIndex(i, sc) == false)
262 continue;
Greg Clayton12bec712010-06-28 21:30:43 +0000263
Chris Lattner24943d22010-06-08 16:52:24 +0000264 if (sc.function == NULL)
265 continue;
266 uint32_t j = 0;
267 while (j < sym_list.GetSize())
268 {
269 SymbolContext symbol_sc;
270 if (sym_list.GetContextAtIndex(j, symbol_sc))
271 {
272 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
273 {
274 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
275 {
276 sym_list.RemoveContextAtIndex(j);
277 continue; // Don't increment j
278 }
279 }
280 }
Greg Clayton12bec712010-06-28 21:30:43 +0000281
Chris Lattner24943d22010-06-08 16:52:24 +0000282 j++;
283 }
284 }
Greg Clayton12bec712010-06-28 21:30:43 +0000285
Chris Lattner24943d22010-06-08 16:52:24 +0000286 for (i = 0; i < func_list.GetSize(); i++)
287 {
288 if (func_list.GetContextAtIndex(i, sc))
289 {
Greg Claytonfeb6e562010-11-14 00:22:48 +0000290 if (sc.block && sc.block->GetInlinedFunctionInfo())
291 {
292 if (!sc.block->GetStartAddress(break_addr))
293 break_addr.Clear();
294 }
295 else if (sc.function)
Chris Lattner24943d22010-06-08 16:52:24 +0000296 {
297 break_addr = sc.function->GetAddressRange().GetBaseAddress();
Greg Clayton7dd98df2011-07-12 17:06:17 +0000298 if (m_skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000299 {
Greg Claytonfeb6e562010-11-14 00:22:48 +0000300 if (break_addr.IsValid())
301 {
302 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
303 if (prologue_byte_size)
304 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
305 }
Chris Lattner24943d22010-06-08 16:52:24 +0000306 }
Greg Claytonfeb6e562010-11-14 00:22:48 +0000307 }
308
309 if (break_addr.IsValid())
310 {
Chris Lattner24943d22010-06-08 16:52:24 +0000311 if (filter.AddressPasses(break_addr))
312 {
313 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
314 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
315 {
316 if (log)
317 {
318 StreamString s;
319 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
320 log->Printf ("Added location: %s\n", s.GetData());
321 }
322 }
323 }
324 }
325 }
326 }
327 }
Greg Clayton12bec712010-06-28 21:30:43 +0000328
Chris Lattner24943d22010-06-08 16:52:24 +0000329 for (i = 0; i < sym_list.GetSize(); i++)
330 {
331 if (sym_list.GetContextAtIndex(i, sc))
332 {
333 if (sc.symbol && sc.symbol->GetAddressRangePtr())
334 {
335 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
Greg Clayton12bec712010-06-28 21:30:43 +0000336
Greg Clayton7dd98df2011-07-12 17:06:17 +0000337 if (m_skip_prologue)
Chris Lattner24943d22010-06-08 16:52:24 +0000338 {
339 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
340 if (prologue_byte_size)
341 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
342 }
Greg Clayton12bec712010-06-28 21:30:43 +0000343
Chris Lattner24943d22010-06-08 16:52:24 +0000344 if (filter.AddressPasses(break_addr))
345 {
346 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
347 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
348 {
349 StreamString s;
350 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
351 if (log)
352 log->Printf ("Added location: %s\n", s.GetData());
353 }
354 }
355 }
356 }
357 }
358 return Searcher::eCallbackReturnContinue;
359}
360
361Searcher::Depth
362BreakpointResolverName::GetDepth()
363{
364 return Searcher::eDepthModule;
365}
366
367void
368BreakpointResolverName::GetDescription (Stream *s)
369{
Chris Lattner24943d22010-06-08 16:52:24 +0000370 if (m_match_type == Breakpoint::Regexp)
Greg Clayton12bec712010-06-28 21:30:43 +0000371 s->Printf("regex = '%s'", m_regex.GetText());
Greg Clayton48fbdf72010-10-12 04:29:14 +0000372 else if (m_basename_filter.empty())
Greg Clayton12bec712010-06-28 21:30:43 +0000373 s->Printf("name = '%s'", m_func_name.AsCString());
Greg Clayton48fbdf72010-10-12 04:29:14 +0000374 else
375 s->Printf("name = '%s'", m_basename_filter.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000376}
377
378void
379BreakpointResolverName::Dump (Stream *s) const
380{
381
382}
383