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/Target/Target.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 bool skip_prologue 31 ) : 32 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 33 m_func_name (), 34 m_basename_filter (), 35 m_func_name_type_mask (func_name_type_mask), 36 m_class_name (), 37 m_regex (), 38 m_match_type (type), 39 m_skip_prologue (skip_prologue) 40 { 41 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 82 if (m_match_type == Breakpoint::Regexp) 83 { 84 if (!m_regex.Compile (m_func_name.AsCString())) 85 { 86 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 87 88 if (log) 89 log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString()); 90 } 91 } 92 } 93 94 BreakpointResolverName::BreakpointResolverName 95 ( 96 Breakpoint *bkpt, 97 RegularExpression &func_regex, 98 bool skip_prologue 99 ) : 100 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 101 m_func_name (NULL), 102 m_class_name (NULL), 103 m_regex (func_regex), 104 m_match_type (Breakpoint::Regexp), 105 m_skip_prologue (skip_prologue) 106 { 107 } 108 109 BreakpointResolverName::BreakpointResolverName 110 ( 111 Breakpoint *bkpt, 112 const char *class_name, 113 const char *method, 114 Breakpoint::MatchType type, 115 bool skip_prologue 116 ) : 117 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 118 m_func_name (method), 119 m_class_name (class_name), 120 m_regex (), 121 m_match_type (type), 122 m_skip_prologue (skip_prologue) 123 { 124 125 } 126 127 BreakpointResolverName::~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 135 Searcher::CallbackReturn 136 BreakpointResolverName::SearchCallback 137 ( 138 SearchFilter &filter, 139 SymbolContext &context, 140 Address *addr, 141 bool containing 142 ) 143 { 144 SymbolContextList func_list; 145 SymbolContextList sym_list; 146 147 uint32_t i; 148 bool new_location; 149 SymbolContext sc; 150 Address break_addr; 151 assert (m_breakpoint != NULL); 152 153 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 154 155 if (m_class_name) 156 { 157 if (log) 158 log->Warning ("Class/method function specification not supported yet.\n"); 159 return Searcher::eCallbackReturnStop; 160 } 161 162 const bool include_symbols = false; 163 const bool append = false; 164 bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; 165 166 switch (m_match_type) 167 { 168 case Breakpoint::Exact: 169 if (context.module_sp) 170 { 171 uint32_t num_functions = context.module_sp->FindFunctions (m_func_name, 172 m_func_name_type_mask, 173 include_symbols, 174 append, 175 func_list); 176 // If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain 177 // symbols, since all the ones from a set compilation unit will have been found above already. 178 179 if (num_functions == 0 && !filter_by_cu) 180 { 181 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) 182 context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list); 183 } 184 } 185 break; 186 case Breakpoint::Regexp: 187 if (context.module_sp) 188 { 189 if (!filter_by_cu) 190 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); 191 context.module_sp->FindFunctions (m_regex, 192 include_symbols, 193 append, 194 func_list); 195 } 196 break; 197 case Breakpoint::Glob: 198 if (log) 199 log->Warning ("glob is not supported yet."); 200 break; 201 } 202 203 // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point. 204 if (filter_by_cu) 205 { 206 uint32_t num_functions = func_list.GetSize(); 207 208 for (size_t idx = 0; idx < num_functions; idx++) 209 { 210 SymbolContext sc; 211 func_list.GetContextAtIndex(idx, sc); 212 if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) 213 { 214 func_list.RemoveContextAtIndex(idx); 215 num_functions--; 216 idx--; 217 } 218 } 219 } 220 221 222 if (!m_basename_filter.empty()) 223 { 224 // Filter out any matches whose names don't contain the basename filter 225 const char *basename_filter = m_basename_filter.c_str(); 226 if (func_list.GetSize()) 227 { 228 bool remove = false; 229 for (i = 0; i < func_list.GetSize(); remove = false) 230 { 231 if (func_list.GetContextAtIndex(i, sc) == false) 232 remove = true; 233 else if (sc.function == NULL) 234 remove = true; 235 else 236 { 237 const InlineFunctionInfo* inlined_info = NULL; 238 239 if (sc.block) 240 inlined_info = sc.block->GetInlinedFunctionInfo(); 241 242 if (inlined_info) 243 { 244 if (::strstr (inlined_info->GetName().AsCString(), basename_filter) == NULL) 245 remove = true; 246 } 247 else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL) 248 remove = true; 249 } 250 251 if (remove) 252 { 253 func_list.RemoveContextAtIndex(i); 254 continue; 255 } 256 i++; 257 } 258 } 259 260 if (sym_list.GetSize()) 261 { 262 bool remove = false; 263 for (i = 0; i < sym_list.GetSize(); remove = false) 264 { 265 if (sym_list.GetContextAtIndex(i, sc) == false) 266 remove = true; 267 else if (sc.symbol == NULL) 268 remove = true; 269 else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL) 270 remove = true; 271 272 if (remove) 273 { 274 sym_list.RemoveContextAtIndex(i); 275 continue; 276 } 277 i++; 278 } 279 } 280 } 281 282 // Remove any duplicates between the funcion list and the symbol list 283 if (func_list.GetSize()) 284 { 285 for (i = 0; i < func_list.GetSize(); i++) 286 { 287 if (func_list.GetContextAtIndex(i, sc) == false) 288 continue; 289 290 if (sc.function == NULL) 291 continue; 292 uint32_t j = 0; 293 while (j < sym_list.GetSize()) 294 { 295 SymbolContext symbol_sc; 296 if (sym_list.GetContextAtIndex(j, symbol_sc)) 297 { 298 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr()) 299 { 300 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress()) 301 { 302 sym_list.RemoveContextAtIndex(j); 303 continue; // Don't increment j 304 } 305 } 306 } 307 308 j++; 309 } 310 } 311 312 for (i = 0; i < func_list.GetSize(); i++) 313 { 314 if (func_list.GetContextAtIndex(i, sc)) 315 { 316 if (sc.block && sc.block->GetInlinedFunctionInfo()) 317 { 318 if (!sc.block->GetStartAddress(break_addr)) 319 break_addr.Clear(); 320 } 321 else if (sc.function) 322 { 323 break_addr = sc.function->GetAddressRange().GetBaseAddress(); 324 if (m_skip_prologue) 325 { 326 if (break_addr.IsValid()) 327 { 328 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); 329 if (prologue_byte_size) 330 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 331 } 332 } 333 } 334 335 if (break_addr.IsValid()) 336 { 337 if (filter.AddressPasses(break_addr)) 338 { 339 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 340 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 341 { 342 if (log) 343 { 344 StreamString s; 345 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 346 log->Printf ("Added location: %s\n", s.GetData()); 347 } 348 } 349 } 350 } 351 } 352 } 353 } 354 355 for (i = 0; i < sym_list.GetSize(); i++) 356 { 357 if (sym_list.GetContextAtIndex(i, sc)) 358 { 359 if (sc.symbol && sc.symbol->GetAddressRangePtr()) 360 { 361 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress(); 362 363 if (m_skip_prologue) 364 { 365 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); 366 if (prologue_byte_size) 367 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 368 } 369 370 if (filter.AddressPasses(break_addr)) 371 { 372 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 373 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 374 { 375 StreamString s; 376 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 377 if (log) 378 log->Printf ("Added location: %s\n", s.GetData()); 379 } 380 } 381 } 382 } 383 } 384 return Searcher::eCallbackReturnContinue; 385 } 386 387 Searcher::Depth 388 BreakpointResolverName::GetDepth() 389 { 390 return Searcher::eDepthModule; 391 } 392 393 void 394 BreakpointResolverName::GetDescription (Stream *s) 395 { 396 if (m_match_type == Breakpoint::Regexp) 397 s->Printf("regex = '%s'", m_regex.GetText()); 398 else if (m_basename_filter.empty()) 399 s->Printf("name = '%s'", m_func_name.AsCString()); 400 else 401 s->Printf("name = '%s'", m_basename_filter.c_str()); 402 } 403 404 void 405 BreakpointResolverName::Dump (Stream *s) const 406 { 407 408 } 409 410