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 i = 0; i < num_names; i++) 172 { 173 uint32_t num_functions = context.module_sp->FindFunctions (m_func_names[i], 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 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeAuto)) 186 context.module_sp->FindSymbolsWithNameAndType (m_func_names[i], eSymbolTypeCode, sym_list); 187 } 188 } 189 } 190 break; 191 case Breakpoint::Regexp: 192 if (context.module_sp) 193 { 194 if (!filter_by_cu) 195 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); 196 context.module_sp->FindFunctions (m_regex, 197 include_symbols, 198 include_inlines, 199 append, 200 func_list); 201 } 202 break; 203 case Breakpoint::Glob: 204 if (log) 205 log->Warning ("glob is not supported yet."); 206 break; 207 } 208 209 // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point. 210 if (filter_by_cu) 211 { 212 uint32_t num_functions = func_list.GetSize(); 213 214 for (size_t idx = 0; idx < num_functions; idx++) 215 { 216 SymbolContext sc; 217 func_list.GetContextAtIndex(idx, sc); 218 if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) 219 { 220 func_list.RemoveContextAtIndex(idx); 221 num_functions--; 222 idx--; 223 } 224 } 225 } 226 227 // Remove any duplicates between the funcion list and the symbol list 228 if (func_list.GetSize()) 229 { 230 for (i = 0; i < func_list.GetSize(); i++) 231 { 232 if (func_list.GetContextAtIndex(i, sc) == false) 233 continue; 234 235 if (sc.function == NULL) 236 continue; 237 uint32_t j = 0; 238 while (j < sym_list.GetSize()) 239 { 240 SymbolContext symbol_sc; 241 if (sym_list.GetContextAtIndex(j, symbol_sc)) 242 { 243 if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) 244 { 245 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress()) 246 { 247 sym_list.RemoveContextAtIndex(j); 248 continue; // Don't increment j 249 } 250 } 251 } 252 253 j++; 254 } 255 } 256 257 for (i = 0; i < func_list.GetSize(); i++) 258 { 259 if (func_list.GetContextAtIndex(i, sc)) 260 { 261 if (sc.block && sc.block->GetInlinedFunctionInfo()) 262 { 263 if (!sc.block->GetStartAddress(break_addr)) 264 break_addr.Clear(); 265 } 266 else if (sc.function) 267 { 268 break_addr = sc.function->GetAddressRange().GetBaseAddress(); 269 if (m_skip_prologue) 270 { 271 if (break_addr.IsValid()) 272 { 273 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); 274 if (prologue_byte_size) 275 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 276 } 277 } 278 } 279 280 if (break_addr.IsValid()) 281 { 282 if (filter.AddressPasses(break_addr)) 283 { 284 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 285 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 286 { 287 if (log) 288 { 289 StreamString s; 290 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 291 log->Printf ("Added location: %s\n", s.GetData()); 292 } 293 } 294 } 295 } 296 } 297 } 298 } 299 300 for (i = 0; i < sym_list.GetSize(); i++) 301 { 302 if (sym_list.GetContextAtIndex(i, sc)) 303 { 304 if (sc.symbol && sc.symbol->ValueIsAddress()) 305 { 306 break_addr = sc.symbol->GetAddress(); 307 308 if (m_skip_prologue) 309 { 310 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); 311 if (prologue_byte_size) 312 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 313 } 314 315 if (filter.AddressPasses(break_addr)) 316 { 317 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 318 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 319 { 320 StreamString s; 321 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 322 if (log) 323 log->Printf ("Added location: %s\n", s.GetData()); 324 } 325 } 326 } 327 } 328 } 329 return Searcher::eCallbackReturnContinue; 330 } 331 332 Searcher::Depth 333 BreakpointResolverName::GetDepth() 334 { 335 return Searcher::eDepthModule; 336 } 337 338 void 339 BreakpointResolverName::GetDescription (Stream *s) 340 { 341 if (m_match_type == Breakpoint::Regexp) 342 s->Printf("regex = '%s'", m_regex.GetText()); 343 else 344 { 345 size_t num_names = m_func_names.size(); 346 if (num_names == 1) 347 s->Printf("name = '%s'", m_func_names[0].AsCString()); 348 else 349 { 350 s->Printf("names = {"); 351 for (size_t i = 0; i < num_names - 1; i++) 352 { 353 s->Printf ("'%s', ", m_func_names[i].AsCString()); 354 } 355 s->Printf ("'%s'}", m_func_names[num_names - 1].AsCString()); 356 } 357 } 358 } 359 360 void 361 BreakpointResolverName::Dump (Stream *s) const 362 { 363 364 } 365 366