blob: b04bb8aef483939c05fe6ea0a2bc2949a633802d [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,
28 Breakpoint::MatchType type
29) :
30 BreakpointResolver (bkpt),
31 m_func_name (func_name),
32 m_class_name (NULL),
33 m_regex (),
34 m_match_type (type)
35{
36 if (m_match_type == Breakpoint::Regexp)
37 {
38 if (!m_regex.Compile (m_func_name.AsCString()))
39 {
40 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
41
42 if (log)
43 log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString());
44 }
45 }
46}
47
48BreakpointResolverName::BreakpointResolverName
49(
50 Breakpoint *bkpt,
51 RegularExpression &func_regex
52) :
53 BreakpointResolver (bkpt),
54 m_func_name (NULL),
55 m_class_name (NULL),
56 m_regex (func_regex),
57 m_match_type (Breakpoint::Regexp)
58{
59
60}
61
62BreakpointResolverName::BreakpointResolverName
63(
64 Breakpoint *bkpt,
65 const char *class_name,
66 const char *method,
67 Breakpoint::MatchType type
68) :
69 BreakpointResolver (bkpt),
70 m_func_name (method),
71 m_class_name (class_name),
72 m_regex (),
73 m_match_type (type)
74{
75
76}
77
78BreakpointResolverName::~BreakpointResolverName ()
79{
80}
81
82// FIXME: Right now we look at the module level, and call the module's "FindFunctions".
83// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function
84// lookup. At that point, we should switch the depth to CompileUnit, and look in these tables.
85
86Searcher::CallbackReturn
87BreakpointResolverName::SearchCallback
88(
89 SearchFilter &filter,
90 SymbolContext &context,
91 Address *addr,
92 bool containing
93)
94{
95 SymbolContextList func_list;
96 SymbolContextList sym_list;
97
98 bool skip_prologue = true;
99 uint32_t i;
100 bool new_location;
101 SymbolContext sc;
102 Address break_addr;
103 assert (m_breakpoint != NULL);
104
105 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
106
107 if (m_class_name)
108 {
109 if (log)
110 log->Warning ("Class/method function specification not supported yet.\n");
111 return Searcher::eCallbackReturnStop;
112 }
113
114 switch (m_match_type)
115 {
116 case Breakpoint::Exact:
117 if (context.module_sp)
118 {
119 context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
120 context.module_sp->FindFunctions (m_func_name, false, func_list);
121 }
122 break;
123 case Breakpoint::Regexp:
124 if (context.module_sp)
125 {
126 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
127 context.module_sp->FindFunctions (m_regex, true, func_list);
128 }
129 break;
130 case Breakpoint::Glob:
131 if (log)
132 log->Warning ("glob is not supported yet.");
133 break;
134 }
135
136 // Remove any duplicates between the funcion list and the symbol list
137 if (func_list.GetSize())
138 {
139 for (i = 0; i < func_list.GetSize(); i++)
140 {
141 if (func_list.GetContextAtIndex(i, sc) == false)
142 continue;
143
144 if (sc.function == NULL)
145 continue;
146 uint32_t j = 0;
147 while (j < sym_list.GetSize())
148 {
149 SymbolContext symbol_sc;
150 if (sym_list.GetContextAtIndex(j, symbol_sc))
151 {
152 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr())
153 {
154 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress())
155 {
156 sym_list.RemoveContextAtIndex(j);
157 continue; // Don't increment j
158 }
159 }
160 }
161
162 j++;
163 }
164 }
165
166 for (i = 0; i < func_list.GetSize(); i++)
167 {
168 if (func_list.GetContextAtIndex(i, sc))
169 {
170 if (sc.function)
171 {
172 break_addr = sc.function->GetAddressRange().GetBaseAddress();
173 if (skip_prologue)
174 {
175 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize();
176 if (prologue_byte_size)
177 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
178 }
179
180 if (filter.AddressPasses(break_addr))
181 {
182 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
183 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
184 {
185 if (log)
186 {
187 StreamString s;
188 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
189 log->Printf ("Added location: %s\n", s.GetData());
190 }
191 }
192 }
193 }
194 }
195 }
196 }
197
198 for (i = 0; i < sym_list.GetSize(); i++)
199 {
200 if (sym_list.GetContextAtIndex(i, sc))
201 {
202 if (sc.symbol && sc.symbol->GetAddressRangePtr())
203 {
204 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
205
206 if (skip_prologue)
207 {
208 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize();
209 if (prologue_byte_size)
210 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size);
211 }
212
213 if (filter.AddressPasses(break_addr))
214 {
215 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location));
216 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal())
217 {
218 StreamString s;
219 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);
220 if (log)
221 log->Printf ("Added location: %s\n", s.GetData());
222 }
223 }
224 }
225 }
226 }
227 return Searcher::eCallbackReturnContinue;
228}
229
230Searcher::Depth
231BreakpointResolverName::GetDepth()
232{
233 return Searcher::eDepthModule;
234}
235
236void
237BreakpointResolverName::GetDescription (Stream *s)
238{
239 s->PutCString("Breakpoint by name: ");
240
241 if (m_match_type == Breakpoint::Regexp)
242 s->Printf("'%s' (regular expression)", m_regex.GetText());
243 else
244 s->Printf("'%s'", m_func_name.AsCString());
245}
246
247void
248BreakpointResolverName::Dump (Stream *s) const
249{
250
251}
252