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