1 //===-- 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 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 BreakpointResolverName::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 
48 BreakpointResolverName::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 
62 BreakpointResolverName::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 
78 BreakpointResolverName::~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 
86 Searcher::CallbackReturn
87 BreakpointResolverName::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 
230 Searcher::Depth
231 BreakpointResolverName::GetDepth()
232 {
233     return Searcher::eDepthModule;
234 }
235 
236 void
237 BreakpointResolverName::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 
247 void
248 BreakpointResolverName::Dump (Stream *s) const
249 {
250 
251 }
252 
253