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 110 BreakpointResolverName::BreakpointResolverName 111 ( 112 Breakpoint *bkpt, 113 const char *class_name, 114 const char *method, 115 Breakpoint::MatchType type, 116 bool skip_prologue 117 ) : 118 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 119 m_func_name (method), 120 m_class_name (class_name), 121 m_regex (), 122 m_match_type (type), 123 m_skip_prologue (skip_prologue) 124 { 125 126 } 127 128 BreakpointResolverName::~BreakpointResolverName () 129 { 130 } 131 132 // FIXME: Right now we look at the module level, and call the module's "FindFunctions". 133 // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function 134 // lookup. At that point, we should switch the depth to CompileUnit, and look in these tables. 135 136 Searcher::CallbackReturn 137 BreakpointResolverName::SearchCallback 138 ( 139 SearchFilter &filter, 140 SymbolContext &context, 141 Address *addr, 142 bool containing 143 ) 144 { 145 SymbolContextList func_list; 146 SymbolContextList sym_list; 147 148 uint32_t i; 149 bool new_location; 150 SymbolContext sc; 151 Address break_addr; 152 assert (m_breakpoint != NULL); 153 154 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 155 156 if (m_class_name) 157 { 158 if (log) 159 log->Warning ("Class/method function specification not supported yet.\n"); 160 return Searcher::eCallbackReturnStop; 161 } 162 163 const bool include_symbols = false; 164 const bool append = false; 165 switch (m_match_type) 166 { 167 case Breakpoint::Exact: 168 if (context.module_sp) 169 { 170 if (context.module_sp->FindFunctions (m_func_name, 171 m_func_name_type_mask, 172 include_symbols, 173 append, 174 func_list) == 0) 175 { 176 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) 177 context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list); 178 } 179 } 180 break; 181 case Breakpoint::Regexp: 182 if (context.module_sp) 183 { 184 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); 185 context.module_sp->FindFunctions (m_regex, 186 include_symbols, 187 append, 188 func_list); 189 } 190 break; 191 case Breakpoint::Glob: 192 if (log) 193 log->Warning ("glob is not supported yet."); 194 break; 195 } 196 197 if (!m_basename_filter.empty()) 198 { 199 // Filter out any matches whose names don't contain the basename filter 200 const char *basename_filter = m_basename_filter.c_str(); 201 if (func_list.GetSize()) 202 { 203 bool remove = false; 204 for (i = 0; i < func_list.GetSize(); remove = false) 205 { 206 if (func_list.GetContextAtIndex(i, sc) == false) 207 remove = true; 208 else if (sc.function == NULL) 209 remove = true; 210 else 211 { 212 const InlineFunctionInfo* inlined_info = NULL; 213 214 if (sc.block) 215 inlined_info = sc.block->GetInlinedFunctionInfo(); 216 217 if (inlined_info) 218 { 219 if (::strstr (inlined_info->GetName().AsCString(), basename_filter) == NULL) 220 remove = true; 221 } 222 else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL) 223 remove = true; 224 } 225 226 if (remove) 227 { 228 func_list.RemoveContextAtIndex(i); 229 continue; 230 } 231 i++; 232 } 233 } 234 235 if (sym_list.GetSize()) 236 { 237 bool remove = false; 238 for (i = 0; i < sym_list.GetSize(); remove = false) 239 { 240 if (sym_list.GetContextAtIndex(i, sc) == false) 241 remove = true; 242 else if (sc.symbol == NULL) 243 remove = true; 244 else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL) 245 remove = true; 246 247 if (remove) 248 { 249 sym_list.RemoveContextAtIndex(i); 250 continue; 251 } 252 i++; 253 } 254 } 255 } 256 257 // Remove any duplicates between the funcion list and the symbol list 258 if (func_list.GetSize()) 259 { 260 for (i = 0; i < func_list.GetSize(); i++) 261 { 262 if (func_list.GetContextAtIndex(i, sc) == false) 263 continue; 264 265 if (sc.function == NULL) 266 continue; 267 uint32_t j = 0; 268 while (j < sym_list.GetSize()) 269 { 270 SymbolContext symbol_sc; 271 if (sym_list.GetContextAtIndex(j, symbol_sc)) 272 { 273 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr()) 274 { 275 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress()) 276 { 277 sym_list.RemoveContextAtIndex(j); 278 continue; // Don't increment j 279 } 280 } 281 } 282 283 j++; 284 } 285 } 286 287 for (i = 0; i < func_list.GetSize(); i++) 288 { 289 if (func_list.GetContextAtIndex(i, sc)) 290 { 291 if (sc.block && sc.block->GetInlinedFunctionInfo()) 292 { 293 if (!sc.block->GetStartAddress(break_addr)) 294 break_addr.Clear(); 295 } 296 else if (sc.function) 297 { 298 break_addr = sc.function->GetAddressRange().GetBaseAddress(); 299 if (m_skip_prologue) 300 { 301 if (break_addr.IsValid()) 302 { 303 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); 304 if (prologue_byte_size) 305 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 306 } 307 } 308 } 309 310 if (break_addr.IsValid()) 311 { 312 if (filter.AddressPasses(break_addr)) 313 { 314 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 315 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 316 { 317 if (log) 318 { 319 StreamString s; 320 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 321 log->Printf ("Added location: %s\n", s.GetData()); 322 } 323 } 324 } 325 } 326 } 327 } 328 } 329 330 for (i = 0; i < sym_list.GetSize(); i++) 331 { 332 if (sym_list.GetContextAtIndex(i, sc)) 333 { 334 if (sc.symbol && sc.symbol->GetAddressRangePtr()) 335 { 336 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress(); 337 338 if (m_skip_prologue) 339 { 340 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); 341 if (prologue_byte_size) 342 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 343 } 344 345 if (filter.AddressPasses(break_addr)) 346 { 347 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 348 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 349 { 350 StreamString s; 351 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 352 if (log) 353 log->Printf ("Added location: %s\n", s.GetData()); 354 } 355 } 356 } 357 } 358 } 359 return Searcher::eCallbackReturnContinue; 360 } 361 362 Searcher::Depth 363 BreakpointResolverName::GetDepth() 364 { 365 return Searcher::eDepthModule; 366 } 367 368 void 369 BreakpointResolverName::GetDescription (Stream *s) 370 { 371 if (m_match_type == Breakpoint::Regexp) 372 s->Printf("regex = '%s'", m_regex.GetText()); 373 else if (m_basename_filter.empty()) 374 s->Printf("name = '%s'", m_func_name.AsCString()); 375 else 376 s->Printf("name = '%s'", m_basename_filter.c_str()); 377 } 378 379 void 380 BreakpointResolverName::Dump (Stream *s) const 381 { 382 383 } 384 385