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 26 using namespace lldb; 27 using namespace lldb_private; 28 29 BreakpointResolverName::BreakpointResolverName 30 ( 31 Breakpoint *bkpt, 32 const char *func_name, 33 uint32_t func_name_type_mask, 34 Breakpoint::MatchType type, 35 bool skip_prologue 36 ) : 37 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 38 m_func_name_type_mask (func_name_type_mask), 39 m_class_name (), 40 m_regex (), 41 m_match_type (type), 42 m_skip_prologue (skip_prologue) 43 { 44 45 if (m_match_type == Breakpoint::Regexp) 46 { 47 if (!m_regex.Compile (func_name)) 48 { 49 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 50 51 if (log) 52 log->Warning ("function name regexp: \"%s\" did not compile.", func_name); 53 } 54 } 55 else 56 { 57 m_func_names.push_back(ConstString(func_name)); 58 } 59 } 60 61 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, 62 const char *names[], 63 size_t num_names, 64 uint32_t name_type_mask, 65 bool skip_prologue) : 66 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 67 m_func_name_type_mask (name_type_mask), 68 m_match_type (Breakpoint::Exact), 69 m_skip_prologue (skip_prologue) 70 { 71 for (size_t i = 0; i < num_names; i++) 72 { 73 m_func_names.push_back (ConstString (names[i])); 74 } 75 } 76 77 BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, 78 std::vector<std::string> names, 79 uint32_t name_type_mask, 80 bool skip_prologue) : 81 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 82 m_func_name_type_mask (name_type_mask), 83 m_match_type (Breakpoint::Exact), 84 m_skip_prologue (skip_prologue) 85 { 86 size_t num_names = names.size(); 87 88 for (size_t i = 0; i < num_names; i++) 89 { 90 m_func_names.push_back (ConstString (names[i].c_str())); 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_class_name (NULL), 102 m_regex (func_regex), 103 m_match_type (Breakpoint::Regexp), 104 m_skip_prologue (skip_prologue) 105 { 106 } 107 108 BreakpointResolverName::BreakpointResolverName 109 ( 110 Breakpoint *bkpt, 111 const char *class_name, 112 const char *method, 113 Breakpoint::MatchType type, 114 bool skip_prologue 115 ) : 116 BreakpointResolver (bkpt, BreakpointResolver::NameResolver), 117 m_class_name (class_name), 118 m_regex (), 119 m_match_type (type), 120 m_skip_prologue (skip_prologue) 121 { 122 m_func_names.push_back(ConstString(method)); 123 } 124 125 BreakpointResolverName::~BreakpointResolverName () 126 { 127 } 128 129 // FIXME: Right now we look at the module level, and call the module's "FindFunctions". 130 // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function 131 // lookup. At that point, we should switch the depth to CompileUnit, and look in these tables. 132 133 Searcher::CallbackReturn 134 BreakpointResolverName::SearchCallback 135 ( 136 SearchFilter &filter, 137 SymbolContext &context, 138 Address *addr, 139 bool containing 140 ) 141 { 142 SymbolContextList func_list; 143 SymbolContextList sym_list; 144 145 uint32_t i; 146 bool new_location; 147 SymbolContext sc; 148 Address break_addr; 149 assert (m_breakpoint != NULL); 150 151 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 152 153 if (m_class_name) 154 { 155 if (log) 156 log->Warning ("Class/method function specification not supported yet.\n"); 157 return Searcher::eCallbackReturnStop; 158 } 159 160 const bool include_symbols = false; 161 const bool include_inlines = true; 162 const bool append = true; 163 bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; 164 165 switch (m_match_type) 166 { 167 case Breakpoint::Exact: 168 if (context.module_sp) 169 { 170 size_t num_names = m_func_names.size(); 171 for (int j = 0; j < num_names; j++) 172 { 173 size_t num_functions = context.module_sp->FindFunctions (m_func_names[j], 174 NULL, 175 m_func_name_type_mask, 176 include_symbols, 177 include_inlines, 178 append, 179 func_list); 180 // If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain 181 // symbols, since all the ones from a set compilation unit will have been found above already. 182 183 if (num_functions == 0 && !filter_by_cu) 184 { 185 context.module_sp->FindFunctionSymbols (m_func_names[j], m_func_name_type_mask, sym_list); 186 } 187 } 188 } 189 break; 190 case Breakpoint::Regexp: 191 if (context.module_sp) 192 { 193 if (!filter_by_cu) 194 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); 195 context.module_sp->FindFunctions (m_regex, 196 include_symbols, 197 include_inlines, 198 append, 199 func_list); 200 } 201 break; 202 case Breakpoint::Glob: 203 if (log) 204 log->Warning ("glob is not supported yet."); 205 break; 206 } 207 208 // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point. 209 if (filter_by_cu) 210 { 211 uint32_t num_functions = func_list.GetSize(); 212 213 for (size_t idx = 0; idx < num_functions; idx++) 214 { 215 SymbolContext sc; 216 func_list.GetContextAtIndex(idx, sc); 217 if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) 218 { 219 func_list.RemoveContextAtIndex(idx); 220 num_functions--; 221 idx--; 222 } 223 } 224 } 225 226 // Remove any duplicates between the funcion list and the symbol list 227 if (func_list.GetSize()) 228 { 229 for (i = 0; i < func_list.GetSize(); i++) 230 { 231 if (func_list.GetContextAtIndex(i, sc) == false) 232 continue; 233 234 if (sc.function == NULL) 235 continue; 236 uint32_t j = 0; 237 while (j < sym_list.GetSize()) 238 { 239 SymbolContext symbol_sc; 240 if (sym_list.GetContextAtIndex(j, symbol_sc)) 241 { 242 if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) 243 { 244 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress()) 245 { 246 sym_list.RemoveContextAtIndex(j); 247 continue; // Don't increment j 248 } 249 } 250 } 251 252 j++; 253 } 254 } 255 256 for (i = 0; i < func_list.GetSize(); i++) 257 { 258 if (func_list.GetContextAtIndex(i, sc)) 259 { 260 if (sc.block && sc.block->GetInlinedFunctionInfo()) 261 { 262 if (!sc.block->GetStartAddress(break_addr)) 263 break_addr.Clear(); 264 } 265 else if (sc.function) 266 { 267 break_addr = sc.function->GetAddressRange().GetBaseAddress(); 268 if (m_skip_prologue) 269 { 270 if (break_addr.IsValid()) 271 { 272 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); 273 if (prologue_byte_size) 274 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 275 } 276 } 277 } 278 279 if (break_addr.IsValid()) 280 { 281 if (filter.AddressPasses(break_addr)) 282 { 283 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 284 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 285 { 286 if (log) 287 { 288 StreamString s; 289 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 290 log->Printf ("Added location: %s\n", s.GetData()); 291 } 292 } 293 } 294 } 295 } 296 } 297 } 298 299 for (i = 0; i < sym_list.GetSize(); i++) 300 { 301 if (sym_list.GetContextAtIndex(i, sc)) 302 { 303 if (sc.symbol && sc.symbol->ValueIsAddress()) 304 { 305 break_addr = sc.symbol->GetAddress(); 306 307 if (m_skip_prologue) 308 { 309 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); 310 if (prologue_byte_size) 311 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 312 } 313 314 if (filter.AddressPasses(break_addr)) 315 { 316 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 317 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 318 { 319 StreamString s; 320 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 321 if (log) 322 log->Printf ("Added location: %s\n", s.GetData()); 323 } 324 } 325 } 326 } 327 } 328 return Searcher::eCallbackReturnContinue; 329 } 330 331 Searcher::Depth 332 BreakpointResolverName::GetDepth() 333 { 334 return Searcher::eDepthModule; 335 } 336 337 void 338 BreakpointResolverName::GetDescription (Stream *s) 339 { 340 if (m_match_type == Breakpoint::Regexp) 341 s->Printf("regex = '%s'", m_regex.GetText()); 342 else 343 { 344 size_t num_names = m_func_names.size(); 345 if (num_names == 1) 346 s->Printf("name = '%s'", m_func_names[0].AsCString()); 347 else 348 { 349 s->Printf("names = {"); 350 for (size_t i = 0; i < num_names - 1; i++) 351 { 352 s->Printf ("'%s', ", m_func_names[i].AsCString()); 353 } 354 s->Printf ("'%s'}", m_func_names[num_names - 1].AsCString()); 355 } 356 } 357 } 358 359 void 360 BreakpointResolverName::Dump (Stream *s) const 361 { 362 363 } 364 365