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/Module.h" 19 #include "lldb/Core/StreamString.h" 20 #include "lldb/Symbol/ClangNamespaceDecl.h" 21 #include "lldb/Symbol/Block.h" 22 #include "lldb/Symbol/Function.h" 23 #include "lldb/Symbol/Symbol.h" 24 #include "lldb/Symbol/SymbolContext.h" 25 #include "lldb/Target/ObjCLanguageRuntime.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, 31 const char *name_cstr, 32 uint32_t name_type_mask, 33 LanguageType language, 34 Breakpoint::MatchType type, 35 bool skip_prologue) : 36 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 37 m_class_name (), 38 m_regex (), 39 m_match_type (type), 40 m_language (language), 41 m_skip_prologue (skip_prologue) 42 { 43 44 if (m_match_type == Breakpoint::Regexp) 45 { 46 if (!m_regex.Compile (name_cstr)) 47 { 48 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 49 50 if (log) 51 log->Warning ("function name regexp: \"%s\" did not compile.", name_cstr); 52 } 53 } 54 else 55 { 56 AddNameLookup (ConstString(name_cstr), name_type_mask); 57 } 58 } 59 60 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, 61 const char *names[], 62 size_t num_names, 63 uint32_t name_type_mask, 64 LanguageType language, 65 bool skip_prologue) : 66 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 67 m_match_type (Breakpoint::Exact), 68 m_language (language), 69 m_skip_prologue (skip_prologue) 70 { 71 for (size_t i = 0; i < num_names; i++) 72 { 73 AddNameLookup (ConstString (names[i]), name_type_mask); 74 } 75 } 76 77 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, 78 std::vector<std::string> names, 79 uint32_t name_type_mask, 80 LanguageType language, 81 bool skip_prologue) : 82 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 83 m_match_type (Breakpoint::Exact), 84 m_language (language), 85 m_skip_prologue (skip_prologue) 86 { 87 for (const std::string& name : names) 88 { 89 AddNameLookup (ConstString (name.c_str(), name.size()), name_type_mask); 90 } 91 } 92 93 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, 94 RegularExpression &func_regex, 95 bool skip_prologue) : 96 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 97 m_class_name (NULL), 98 m_regex (func_regex), 99 m_match_type (Breakpoint::Regexp), 100 m_language (eLanguageTypeUnknown), 101 m_skip_prologue (skip_prologue) 102 { 103 } 104 105 BreakpointResolverName::BreakpointResolverName 106 ( 107 Breakpoint *bkpt, 108 const char *class_name, 109 const char *method, 110 Breakpoint::MatchType type, 111 bool skip_prologue 112 ) : 113 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 114 m_class_name (class_name), 115 m_regex (), 116 m_match_type (type), 117 m_language (eLanguageTypeUnknown), 118 m_skip_prologue (skip_prologue) 119 { 120 LookupInfo lookup; 121 lookup.name.SetCString(method); 122 lookup.lookup_name = lookup.name; 123 lookup.name_type_mask = eFunctionNameTypeMethod; 124 lookup.match_name_after_lookup = false; 125 m_lookups.push_back (lookup); 126 } 127 128 BreakpointResolverName::~BreakpointResolverName () 129 { 130 } 131 132 BreakpointResolverName::BreakpointResolverName(const BreakpointResolverName &rhs) : 133 BreakpointResolver(rhs.m_breakpoint, BreakpointResolver::NameResolver), 134 m_lookups(rhs.m_lookups), 135 m_class_name(rhs.m_class_name), 136 m_regex(rhs.m_regex), 137 m_match_type (rhs.m_match_type), 138 m_language (rhs.m_language), 139 m_skip_prologue (rhs.m_skip_prologue) 140 { 141 142 } 143 144 void 145 BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_type_mask) 146 { 147 ObjCLanguageRuntime::MethodName objc_method(name.GetCString(), false); 148 if (objc_method.IsValid(false)) 149 { 150 std::vector<ConstString> objc_names; 151 objc_method.GetFullNames(objc_names, true); 152 for (ConstString objc_name : objc_names) 153 { 154 LookupInfo lookup; 155 lookup.name = name; 156 lookup.lookup_name = objc_name; 157 lookup.name_type_mask = eFunctionNameTypeFull; 158 lookup.match_name_after_lookup = false; 159 m_lookups.push_back (lookup); 160 } 161 } 162 else 163 { 164 LookupInfo lookup; 165 lookup.name = name; 166 Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, m_language, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup); 167 m_lookups.push_back (lookup); 168 } 169 } 170 171 172 void 173 BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const 174 { 175 if (match_name_after_lookup && name) 176 { 177 SymbolContext sc; 178 size_t i = start_idx; 179 while (i < sc_list.GetSize()) 180 { 181 if (!sc_list.GetContextAtIndex(i, sc)) 182 break; 183 ConstString full_name (sc.GetFunctionName()); 184 if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == NULL) 185 { 186 sc_list.RemoveContextAtIndex(i); 187 } 188 else 189 { 190 ++i; 191 } 192 } 193 } 194 } 195 196 197 // FIXME: Right now we look at the module level, and call the module's "FindFunctions". 198 // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function 199 // lookup. At that point, we should switch the depth to CompileUnit, and look in these tables. 200 201 Searcher::CallbackReturn 202 BreakpointResolverName::SearchCallback 203 ( 204 SearchFilter &filter, 205 SymbolContext &context, 206 Address *addr, 207 bool containing 208 ) 209 { 210 SymbolContextList func_list; 211 //SymbolContextList sym_list; 212 213 uint32_t i; 214 bool new_location; 215 Address break_addr; 216 assert (m_breakpoint != NULL); 217 218 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 219 220 if (m_class_name) 221 { 222 if (log) 223 log->Warning ("Class/method function specification not supported yet.\n"); 224 return Searcher::eCallbackReturnStop; 225 } 226 bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; 227 const bool include_symbols = filter_by_cu == false; 228 const bool include_inlines = true; 229 const bool append = true; 230 231 switch (m_match_type) 232 { 233 case Breakpoint::Exact: 234 if (context.module_sp) 235 { 236 for (const LookupInfo &lookup : m_lookups) 237 { 238 const size_t start_func_idx = func_list.GetSize(); 239 context.module_sp->FindFunctions (lookup.lookup_name, 240 NULL, 241 lookup.name_type_mask, 242 include_symbols, 243 include_inlines, 244 append, 245 func_list); 246 const size_t end_func_idx = func_list.GetSize(); 247 248 if (start_func_idx < end_func_idx) 249 lookup.Prune (func_list, start_func_idx); 250 } 251 } 252 break; 253 case Breakpoint::Regexp: 254 if (context.module_sp) 255 { 256 context.module_sp->FindFunctions (m_regex, 257 !filter_by_cu, // include symbols only if we aren't filtering by CU 258 include_inlines, 259 append, 260 func_list); 261 } 262 break; 263 case Breakpoint::Glob: 264 if (log) 265 log->Warning ("glob is not supported yet."); 266 break; 267 } 268 269 // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point. 270 if (filter_by_cu) 271 { 272 uint32_t num_functions = func_list.GetSize(); 273 274 for (size_t idx = 0; idx < num_functions; idx++) 275 { 276 SymbolContext sc; 277 func_list.GetContextAtIndex(idx, sc); 278 if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) 279 { 280 func_list.RemoveContextAtIndex(idx); 281 num_functions--; 282 idx--; 283 } 284 } 285 } 286 287 // Remove any duplicates between the function list and the symbol list 288 SymbolContext sc; 289 if (func_list.GetSize()) 290 { 291 for (i = 0; i < func_list.GetSize(); i++) 292 { 293 if (func_list.GetContextAtIndex(i, sc)) 294 { 295 bool is_reexported = false; 296 297 if (sc.block && sc.block->GetInlinedFunctionInfo()) 298 { 299 if (!sc.block->GetStartAddress(break_addr)) 300 break_addr.Clear(); 301 } 302 else if (sc.function) 303 { 304 break_addr = sc.function->GetAddressRange().GetBaseAddress(); 305 if (m_skip_prologue && break_addr.IsValid()) 306 { 307 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); 308 if (prologue_byte_size) 309 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 310 } 311 } 312 else if (sc.symbol) 313 { 314 if (sc.symbol->GetType() == eSymbolTypeReExported) 315 { 316 const Symbol *actual_symbol = sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget()); 317 if (actual_symbol) 318 { 319 is_reexported = true; 320 break_addr = actual_symbol->GetAddress(); 321 } 322 } 323 else 324 { 325 break_addr = sc.symbol->GetAddress(); 326 } 327 328 if (m_skip_prologue && break_addr.IsValid()) 329 { 330 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); 331 if (prologue_byte_size) 332 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 333 } 334 } 335 336 if (break_addr.IsValid()) 337 { 338 if (filter.AddressPasses(break_addr)) 339 { 340 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 341 bp_loc_sp->SetIsReExported(is_reexported); 342 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 343 { 344 if (log) 345 { 346 StreamString s; 347 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 348 log->Printf ("Added location: %s\n", s.GetData()); 349 } 350 } 351 } 352 } 353 } 354 } 355 } 356 357 return Searcher::eCallbackReturnContinue; 358 } 359 360 Searcher::Depth 361 BreakpointResolverName::GetDepth() 362 { 363 return Searcher::eDepthModule; 364 } 365 366 void 367 BreakpointResolverName::GetDescription (Stream *s) 368 { 369 if (m_match_type == Breakpoint::Regexp) 370 s->Printf("regex = '%s'", m_regex.GetText()); 371 else 372 { 373 size_t num_names = m_lookups.size(); 374 if (num_names == 1) 375 s->Printf("name = '%s'", m_lookups[0].name.GetCString()); 376 else 377 { 378 s->Printf("names = {"); 379 for (size_t i = 0; i < num_names - 1; i++) 380 { 381 s->Printf ("'%s', ", m_lookups[i].name.GetCString()); 382 } 383 s->Printf ("'%s'}", m_lookups[num_names - 1].name.GetCString()); 384 } 385 } 386 } 387 388 void 389 BreakpointResolverName::Dump (Stream *s) const 390 { 391 392 } 393 394 lldb::BreakpointResolverSP 395 BreakpointResolverName::CopyForBreakpoint (Breakpoint &breakpoint) 396 { 397 lldb::BreakpointResolverSP ret_sp(new BreakpointResolverName(*this)); 398 ret_sp->SetBreakpoint(&breakpoint); 399 return ret_sp; 400 } 401