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 append = false; 124 bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; 125 126 switch (m_match_type) 127 { 128 case Breakpoint::Exact: 129 if (context.module_sp) 130 { 131 uint32_t num_functions = context.module_sp->FindFunctions (m_func_name, 132 NULL, 133 m_func_name_type_mask, 134 include_symbols, 135 append, 136 func_list); 137 // If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain 138 // symbols, since all the ones from a set compilation unit will have been found above already. 139 140 if (num_functions == 0 && !filter_by_cu) 141 { 142 if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeAuto)) 143 context.module_sp->FindSymbolsWithNameAndType (m_func_name, NULL, eSymbolTypeCode, sym_list); 144 } 145 } 146 break; 147 case Breakpoint::Regexp: 148 if (context.module_sp) 149 { 150 if (!filter_by_cu) 151 context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); 152 context.module_sp->FindFunctions (m_regex, 153 include_symbols, 154 append, 155 func_list); 156 } 157 break; 158 case Breakpoint::Glob: 159 if (log) 160 log->Warning ("glob is not supported yet."); 161 break; 162 } 163 164 // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point. 165 if (filter_by_cu) 166 { 167 uint32_t num_functions = func_list.GetSize(); 168 169 for (size_t idx = 0; idx < num_functions; idx++) 170 { 171 SymbolContext sc; 172 func_list.GetContextAtIndex(idx, sc); 173 if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) 174 { 175 func_list.RemoveContextAtIndex(idx); 176 num_functions--; 177 idx--; 178 } 179 } 180 } 181 182 // Remove any duplicates between the funcion list and the symbol list 183 if (func_list.GetSize()) 184 { 185 for (i = 0; i < func_list.GetSize(); i++) 186 { 187 if (func_list.GetContextAtIndex(i, sc) == false) 188 continue; 189 190 if (sc.function == NULL) 191 continue; 192 uint32_t j = 0; 193 while (j < sym_list.GetSize()) 194 { 195 SymbolContext symbol_sc; 196 if (sym_list.GetContextAtIndex(j, symbol_sc)) 197 { 198 if (symbol_sc.symbol && symbol_sc.symbol->GetAddressRangePtr()) 199 { 200 if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRangePtr()->GetBaseAddress()) 201 { 202 sym_list.RemoveContextAtIndex(j); 203 continue; // Don't increment j 204 } 205 } 206 } 207 208 j++; 209 } 210 } 211 212 for (i = 0; i < func_list.GetSize(); i++) 213 { 214 if (func_list.GetContextAtIndex(i, sc)) 215 { 216 if (sc.block && sc.block->GetInlinedFunctionInfo()) 217 { 218 if (!sc.block->GetStartAddress(break_addr)) 219 break_addr.Clear(); 220 } 221 else if (sc.function) 222 { 223 break_addr = sc.function->GetAddressRange().GetBaseAddress(); 224 if (m_skip_prologue) 225 { 226 if (break_addr.IsValid()) 227 { 228 const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); 229 if (prologue_byte_size) 230 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 231 } 232 } 233 } 234 235 if (break_addr.IsValid()) 236 { 237 if (filter.AddressPasses(break_addr)) 238 { 239 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 240 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 241 { 242 if (log) 243 { 244 StreamString s; 245 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 246 log->Printf ("Added location: %s\n", s.GetData()); 247 } 248 } 249 } 250 } 251 } 252 } 253 } 254 255 for (i = 0; i < sym_list.GetSize(); i++) 256 { 257 if (sym_list.GetContextAtIndex(i, sc)) 258 { 259 if (sc.symbol && sc.symbol->GetAddressRangePtr()) 260 { 261 break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress(); 262 263 if (m_skip_prologue) 264 { 265 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); 266 if (prologue_byte_size) 267 break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); 268 } 269 270 if (filter.AddressPasses(break_addr)) 271 { 272 BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(break_addr, &new_location)); 273 if (bp_loc_sp && new_location && !m_breakpoint->IsInternal()) 274 { 275 StreamString s; 276 bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); 277 if (log) 278 log->Printf ("Added location: %s\n", s.GetData()); 279 } 280 } 281 } 282 } 283 } 284 return Searcher::eCallbackReturnContinue; 285 } 286 287 Searcher::Depth 288 BreakpointResolverName::GetDepth() 289 { 290 return Searcher::eDepthModule; 291 } 292 293 void 294 BreakpointResolverName::GetDescription (Stream *s) 295 { 296 if (m_match_type == Breakpoint::Regexp) 297 s->Printf("regex = '%s'", m_regex.GetText()); 298 else 299 s->Printf("name = '%s'", m_func_name.AsCString()); 300 } 301 302 void 303 BreakpointResolverName::Dump (Stream *s) const 304 { 305 306 } 307 308