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