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