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