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, BreakpointResolver::NameResolver), 32 m_func_name (), 33 m_basename_filter (), 34 m_func_name_type_mask (func_name_type_mask), 35 m_class_name (), 36 m_regex (), 37 m_match_type (type) 38 { 39 if (func_name_type_mask == eFunctionNameTypeAuto) 40 { 41 if ((::strchr (func_name, '(' ) != NULL) || 42 (::strstr (func_name, "-[") == func_name) || 43 (::strstr (func_name, "+[") == func_name)) 44 { 45 // We have a name that contains an open parens, or starts with 46 // "+[" or "-[", so this looks like a complete function prototype 47 m_func_name_type_mask = eFunctionNameTypeFull; 48 } 49 else 50 { 51 // We don't have a full function name, but we might have a partial 52 // function basename with namespaces or classes 53 if (::strstr (func_name, "::") != NULL) 54 { 55 // Keep the full name in "m_basename_filter" 56 m_basename_filter = func_name; 57 // Now set "m_func_name" to just the function basename 58 m_func_name.SetCString(m_basename_filter.c_str() + m_basename_filter.rfind("::") + 2); 59 // We have a name with a double colon which means we have a 60 // function name that is a C++ method or a function in a C++ 61 // namespace 62 m_func_name_type_mask = eFunctionNameTypeBase | eFunctionNameTypeMethod; 63 } 64 else if (::strstr (func_name, ":") != NULL) 65 { 66 // Single colon => selector 67 m_func_name_type_mask = eFunctionNameTypeSelector; 68 } 69 else 70 { 71 // just a basename by default 72 m_func_name_type_mask = eFunctionNameTypeBase; 73 } 74 } 75 } 76 77 if (!m_func_name) 78 m_func_name.SetCString(func_name); 79 80 if (m_match_type == Breakpoint::Regexp) 81 { 82 if (!m_regex.Compile (m_func_name.AsCString())) 83 { 84 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 85 86 if (log) 87 log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString()); 88 } 89 } 90 } 91 92 BreakpointResolverName::BreakpointResolverName 93 ( 94 Breakpoint *bkpt, 95 RegularExpression &func_regex 96 ) : 97 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 98 m_func_name (NULL), 99 m_class_name (NULL), 100 m_regex (func_regex), 101 m_match_type (Breakpoint::Regexp) 102 { 103 104 } 105 106 BreakpointResolverName::BreakpointResolverName 107 ( 108 Breakpoint *bkpt, 109 const char *class_name, 110 const char *method, 111 Breakpoint::MatchType type 112 ) : 113 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 114 m_func_name (method), 115 m_class_name (class_name), 116 m_regex (), 117 m_match_type (type) 118 { 119 120 } 121 122 BreakpointResolverName::~BreakpointResolverName () 123 { 124 } 125 126 // FIXME: Right now we look at the module level, and call the module's "FindFunctions". 127 // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function 128 // lookup. At that point, we should switch the depth to CompileUnit, and look in these tables. 129 130 Searcher::CallbackReturn 131 BreakpointResolverName::SearchCallback 132 ( 133 SearchFilter &filter, 134 SymbolContext &context, 135 Address *addr, 136 bool containing 137 ) 138 { 139 SymbolContextList func_list; 140 SymbolContextList sym_list; 141 142 bool skip_prologue = true; 143 uint32_t i; 144 bool new_location; 145 SymbolContext sc; 146 Address break_addr; 147 assert (m_breakpoint != NULL); 148 149 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 150 151 if (m_class_name) 152 { 153 if (log) 154 log->Warning ("Class/method function specification not supported yet.\n"); 155 return Searcher::eCallbackReturnStop; 156 } 157 158 const bool include_symbols = false; 159 const bool append = false; 160 switch (m_match_type) 161 { 162 case Breakpoint::Exact: 163 if (context.module_sp) 164 { 165 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) 166 context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list); 167 context.module_sp->FindFunctions (m_func_name, 168 m_func_name_type_mask, 169 include_symbols, 170 append, 171 func_list); 172 } 173 break; 174 case Breakpoint::Regexp: 175 if (context.module_sp) 176 { 177 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); 178 context.module_sp->FindFunctions (m_regex, 179 include_symbols, 180 append, 181 func_list); 182 } 183 break; 184 case Breakpoint::Glob: 185 if (log) 186 log->Warning ("glob is not supported yet."); 187 break; 188 } 189 190 if (!m_basename_filter.empty()) 191 { 192 // Filter out any matches whose names don't contain the basename filter 193 const char *basename_filter = m_basename_filter.c_str(); 194 if (func_list.GetSize()) 195 { 196 bool remove = false; 197 for (i = 0; i < func_list.GetSize(); remove = false) 198 { 199 if (func_list.GetContextAtIndex(i, sc) == false) 200 remove = true; 201 else if (sc.function == NULL) 202 remove = true; 203 else 204 { 205 const InlineFunctionInfo* inlined_info = NULL; 206 207 if (sc.block) 208 inlined_info = sc.block->GetInlinedFunctionInfo(); 209 210 if (inlined_info) 211 { 212 if (::strstr (inlined_info->GetName().AsCString(), basename_filter) == NULL) 213 remove = true; 214 } 215 else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL) 216 remove = true; 217 } 218 219 if (remove) 220 { 221 func_list.RemoveContextAtIndex(i); 222 continue; 223 } 224 i++; 225 } 226 } 227 228 if (sym_list.GetSize()) 229 { 230 bool remove = false; 231 for (i = 0; i < sym_list.GetSize(); remove = false) 232 { 233 if (sym_list.GetContextAtIndex(i, sc) == false) 234 remove = true; 235 else if (sc.symbol == NULL) 236 remove = true; 237 else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL) 238 remove = true; 239 240 if (remove) 241 { 242 sym_list.RemoveContextAtIndex(i); 243 continue; 244 } 245 i++; 246 } 247 } 248 } 249 250 // Remove any duplicates between the funcion list and the symbol list 251 if (func_list.GetSize()) 252 { 253 for (i = 0; i < func_list.GetSize(); i++) 254 { 255 if (func_list.GetContextAtIndex(i, sc) == false) 256 continue; 257 258 if (sc.function == NULL) 259 continue; 260 uint32_t j = 0; 261 while (j < sym_list.GetSize()) 262 { 263 SymbolContext symbol_sc; 264 if (sym_list.GetContextAtIndex(j, symbol_sc)) 265 { 266 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr()) 267 { 268 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress()) 269 { 270 sym_list.RemoveContextAtIndex(j); 271 continue; // Don't increment j 272 } 273 } 274 } 275 276 j++; 277 } 278 } 279 280 for (i = 0; i < func_list.GetSize(); i++) 281 { 282 if (func_list.GetContextAtIndex(i, sc)) 283 { 284 if (sc.block && sc.block->GetInlinedFunctionInfo()) 285 { 286 if (!sc.block->GetStartAddress(break_addr)) 287 break_addr.Clear(); 288 } 289 else if (sc.function) 290 { 291 break_addr = sc.function->GetAddressRange().GetBaseAddress(); 292 if (skip_prologue) 293 { 294 if (break_addr.IsValid()) 295 { 296 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); 297 if (prologue_byte_size) 298 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 299 } 300 } 301 } 302 303 if (break_addr.IsValid()) 304 { 305 if (filter.AddressPasses(break_addr)) 306 { 307 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 308 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 309 { 310 if (log) 311 { 312 StreamString s; 313 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 314 log->Printf ("Added location: %s\n", s.GetData()); 315 } 316 } 317 } 318 } 319 } 320 } 321 } 322 323 for (i = 0; i < sym_list.GetSize(); i++) 324 { 325 if (sym_list.GetContextAtIndex(i, sc)) 326 { 327 if (sc.symbol && sc.symbol->GetAddressRangePtr()) 328 { 329 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress(); 330 331 if (skip_prologue) 332 { 333 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); 334 if (prologue_byte_size) 335 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 336 } 337 338 if (filter.AddressPasses(break_addr)) 339 { 340 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 341 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 342 { 343 StreamString s; 344 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 345 if (log) 346 log->Printf ("Added location: %s\n", s.GetData()); 347 } 348 } 349 } 350 } 351 } 352 return Searcher::eCallbackReturnContinue; 353 } 354 355 Searcher::Depth 356 BreakpointResolverName::GetDepth() 357 { 358 return Searcher::eDepthModule; 359 } 360 361 void 362 BreakpointResolverName::GetDescription (Stream *s) 363 { 364 if (m_match_type == Breakpoint::Regexp) 365 s->Printf("regex = '%s'", m_regex.GetText()); 366 else if (m_basename_filter.empty()) 367 s->Printf("name = '%s'", m_func_name.AsCString()); 368 else 369 s->Printf("name = '%s'", m_basename_filter.c_str()); 370 } 371 372 void 373 BreakpointResolverName::Dump (Stream *s) const 374 { 375 376 } 377 378