1 //===-- SearchFilter.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/Core/SearchFilter.h"
11
12 #include "lldb/Breakpoint/Breakpoint.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/ModuleList.h"
15 #include "lldb/Symbol/CompileUnit.h"
16 #include "lldb/Symbol/SymbolContext.h"
17 #include "lldb/Symbol/SymbolVendor.h"
18 #include "lldb/Target/Target.h"
19 #include "lldb/Utility/ConstString.h"
20 #include "lldb/Utility/Status.h"
21 #include "lldb/Utility/Stream.h"
22 #include "lldb/lldb-enumerations.h"
23
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/Support/ErrorHandling.h"
26
27 #include <memory>
28 #include <mutex>
29 #include <string>
30
31 #include <inttypes.h>
32 #include <string.h>
33
34 namespace lldb_private {
35 class Address;
36 }
37 namespace lldb_private {
38 class Function;
39 }
40
41 using namespace lldb;
42 using namespace lldb_private;
43
44 const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception",
45 "Module", "Modules",
46 "ModulesAndCU", "Unknown"};
47
48 const char
49 *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = {
50 "ModuleList", "CUList"};
51
FilterTyToName(enum FilterTy type)52 const char *SearchFilter::FilterTyToName(enum FilterTy type) {
53 if (type > LastKnownFilterType)
54 return g_ty_to_name[UnknownFilter];
55
56 return g_ty_to_name[type];
57 }
58
NameToFilterTy(llvm::StringRef name)59 SearchFilter::FilterTy SearchFilter::NameToFilterTy(llvm::StringRef name) {
60 for (size_t i = 0; i <= LastKnownFilterType; i++) {
61 if (name == g_ty_to_name[i])
62 return (FilterTy)i;
63 }
64 return UnknownFilter;
65 }
66
67 Searcher::Searcher() = default;
68
69 Searcher::~Searcher() = default;
70
GetDescription(Stream * s)71 void Searcher::GetDescription(Stream *s) {}
72
SearchFilter(const TargetSP & target_sp,unsigned char filterType)73 SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType)
74 : m_target_sp(target_sp), SubclassID(filterType) {}
75
76 SearchFilter::SearchFilter(const SearchFilter &rhs) = default;
77
78 SearchFilter &SearchFilter::operator=(const SearchFilter &rhs) = default;
79
80 SearchFilter::~SearchFilter() = default;
81
CreateFromStructuredData(Target & target,const StructuredData::Dictionary & filter_dict,Status & error)82 SearchFilterSP SearchFilter::CreateFromStructuredData(
83 Target &target, const StructuredData::Dictionary &filter_dict,
84 Status &error) {
85 SearchFilterSP result_sp;
86 if (!filter_dict.IsValid()) {
87 error.SetErrorString("Can't deserialize from an invalid data object.");
88 return result_sp;
89 }
90
91 llvm::StringRef subclass_name;
92
93 bool success = filter_dict.GetValueForKeyAsString(
94 GetSerializationSubclassKey(), subclass_name);
95 if (!success) {
96 error.SetErrorStringWithFormat("Filter data missing subclass key");
97 return result_sp;
98 }
99
100 FilterTy filter_type = NameToFilterTy(subclass_name);
101 if (filter_type == UnknownFilter) {
102 error.SetErrorStringWithFormatv("Unknown filter type: {0}.", subclass_name);
103 return result_sp;
104 }
105
106 StructuredData::Dictionary *subclass_options = nullptr;
107 success = filter_dict.GetValueForKeyAsDictionary(
108 GetSerializationSubclassOptionsKey(), subclass_options);
109 if (!success || !subclass_options || !subclass_options->IsValid()) {
110 error.SetErrorString("Filter data missing subclass options key.");
111 return result_sp;
112 }
113
114 switch (filter_type) {
115 case Unconstrained:
116 result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
117 target, *subclass_options, error);
118 break;
119 case ByModule:
120 result_sp = SearchFilterByModule::CreateFromStructuredData(
121 target, *subclass_options, error);
122 break;
123 case ByModules:
124 result_sp = SearchFilterByModuleList::CreateFromStructuredData(
125 target, *subclass_options, error);
126 break;
127 case ByModulesAndCU:
128 result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData(
129 target, *subclass_options, error);
130 break;
131 case Exception:
132 error.SetErrorString("Can't serialize exception breakpoints yet.");
133 break;
134 default:
135 llvm_unreachable("Should never get an uresolvable filter type.");
136 }
137
138 return result_sp;
139 }
140
ModulePasses(const FileSpec & spec)141 bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; }
142
ModulePasses(const ModuleSP & module_sp)143 bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; }
144
AddressPasses(Address & address)145 bool SearchFilter::AddressPasses(Address &address) { return true; }
146
CompUnitPasses(FileSpec & fileSpec)147 bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; }
148
CompUnitPasses(CompileUnit & compUnit)149 bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; }
150
FunctionPasses(Function & function)151 bool SearchFilter::FunctionPasses(Function &function) {
152 // This is a slightly cheesy job, but since we don't have finer grained
153 // filters yet, just checking that the start address passes is probably
154 // good enough for the base class behavior.
155 Address addr = function.GetAddressRange().GetBaseAddress();
156 return AddressPasses(addr);
157 }
158
159
GetFilterRequiredItems()160 uint32_t SearchFilter::GetFilterRequiredItems() {
161 return (lldb::SymbolContextItem)0;
162 }
163
GetDescription(Stream * s)164 void SearchFilter::GetDescription(Stream *s) {}
165
Dump(Stream * s) const166 void SearchFilter::Dump(Stream *s) const {}
167
CopyForBreakpoint(Breakpoint & breakpoint)168 lldb::SearchFilterSP SearchFilter::CopyForBreakpoint(Breakpoint &breakpoint) {
169 SearchFilterSP ret_sp = DoCopyForBreakpoint(breakpoint);
170 TargetSP target_sp = breakpoint.GetTargetSP();
171 ret_sp->SetTarget(target_sp);
172 return ret_sp;
173 }
174
175 //----------------------------------------------------------------------
176 // Helper functions for serialization.
177 //----------------------------------------------------------------------
178
179 StructuredData::DictionarySP
WrapOptionsDict(StructuredData::DictionarySP options_dict_sp)180 SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) {
181 if (!options_dict_sp || !options_dict_sp->IsValid())
182 return StructuredData::DictionarySP();
183
184 auto type_dict_sp = std::make_shared<StructuredData::Dictionary>();
185 type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetFilterName());
186 type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp);
187
188 return type_dict_sp;
189 }
190
SerializeFileSpecList(StructuredData::DictionarySP & options_dict_sp,OptionNames name,FileSpecList & file_list)191 void SearchFilter::SerializeFileSpecList(
192 StructuredData::DictionarySP &options_dict_sp, OptionNames name,
193 FileSpecList &file_list) {
194 size_t num_modules = file_list.GetSize();
195
196 // Don't serialize empty lists.
197 if (num_modules == 0)
198 return;
199
200 auto module_array_sp = std::make_shared<StructuredData::Array>();
201 for (size_t i = 0; i < num_modules; i++) {
202 module_array_sp->AddItem(std::make_shared<StructuredData::String>(
203 file_list.GetFileSpecAtIndex(i).GetPath()));
204 }
205 options_dict_sp->AddItem(GetKey(name), module_array_sp);
206 }
207
208 //----------------------------------------------------------------------
209 // UTILITY Functions to help iterate down through the elements of the
210 // SymbolContext.
211 //----------------------------------------------------------------------
212
Search(Searcher & searcher)213 void SearchFilter::Search(Searcher &searcher) {
214 SymbolContext empty_sc;
215
216 if (!m_target_sp)
217 return;
218 empty_sc.target_sp = m_target_sp;
219
220 if (searcher.GetDepth() == lldb::eSearchDepthTarget)
221 searcher.SearchCallback(*this, empty_sc, nullptr, false);
222 else
223 DoModuleIteration(empty_sc, searcher);
224 }
225
SearchInModuleList(Searcher & searcher,ModuleList & modules)226 void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
227 SymbolContext empty_sc;
228
229 if (!m_target_sp)
230 return;
231 empty_sc.target_sp = m_target_sp;
232
233 if (searcher.GetDepth() == lldb::eSearchDepthTarget)
234 searcher.SearchCallback(*this, empty_sc, nullptr, false);
235 else {
236 std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
237 const size_t numModules = modules.GetSize();
238
239 for (size_t i = 0; i < numModules; i++) {
240 ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i));
241 if (ModulePasses(module_sp)) {
242 if (DoModuleIteration(module_sp, searcher) ==
243 Searcher::eCallbackReturnStop)
244 return;
245 }
246 }
247 }
248 }
249
250 Searcher::CallbackReturn
DoModuleIteration(const lldb::ModuleSP & module_sp,Searcher & searcher)251 SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp,
252 Searcher &searcher) {
253 SymbolContext matchingContext(m_target_sp, module_sp);
254 return DoModuleIteration(matchingContext, searcher);
255 }
256
257 Searcher::CallbackReturn
DoModuleIteration(const SymbolContext & context,Searcher & searcher)258 SearchFilter::DoModuleIteration(const SymbolContext &context,
259 Searcher &searcher) {
260 if (searcher.GetDepth() >= lldb::eSearchDepthModule) {
261 if (context.module_sp) {
262 if (searcher.GetDepth() == lldb::eSearchDepthModule) {
263 SymbolContext matchingContext(context.module_sp.get());
264 searcher.SearchCallback(*this, matchingContext, nullptr, false);
265 } else {
266 return DoCUIteration(context.module_sp, context, searcher);
267 }
268 } else {
269 const ModuleList &target_images = m_target_sp->GetImages();
270 std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
271
272 size_t n_modules = target_images.GetSize();
273 for (size_t i = 0; i < n_modules; i++) {
274 // If this is the last level supplied, then call the callback directly,
275 // otherwise descend.
276 ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i));
277 if (!ModulePasses(module_sp))
278 continue;
279
280 if (searcher.GetDepth() == lldb::eSearchDepthModule) {
281 SymbolContext matchingContext(m_target_sp, module_sp);
282
283 Searcher::CallbackReturn shouldContinue =
284 searcher.SearchCallback(*this, matchingContext, nullptr, false);
285 if (shouldContinue == Searcher::eCallbackReturnStop ||
286 shouldContinue == Searcher::eCallbackReturnPop)
287 return shouldContinue;
288 } else {
289 Searcher::CallbackReturn shouldContinue =
290 DoCUIteration(module_sp, context, searcher);
291 if (shouldContinue == Searcher::eCallbackReturnStop)
292 return shouldContinue;
293 else if (shouldContinue == Searcher::eCallbackReturnPop)
294 continue;
295 }
296 }
297 }
298 }
299 return Searcher::eCallbackReturnContinue;
300 }
301
302 Searcher::CallbackReturn
DoCUIteration(const ModuleSP & module_sp,const SymbolContext & context,Searcher & searcher)303 SearchFilter::DoCUIteration(const ModuleSP &module_sp,
304 const SymbolContext &context, Searcher &searcher) {
305 Searcher::CallbackReturn shouldContinue;
306 if (context.comp_unit == nullptr) {
307 const size_t num_comp_units = module_sp->GetNumCompileUnits();
308 for (size_t i = 0; i < num_comp_units; i++) {
309 CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i));
310 if (cu_sp) {
311 if (!CompUnitPasses(*(cu_sp.get())))
312 continue;
313
314 if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) {
315 SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
316
317 shouldContinue =
318 searcher.SearchCallback(*this, matchingContext, nullptr, false);
319
320 if (shouldContinue == Searcher::eCallbackReturnPop)
321 return Searcher::eCallbackReturnContinue;
322 else if (shouldContinue == Searcher::eCallbackReturnStop)
323 return shouldContinue;
324 } else {
325 // First make sure this compile unit's functions are parsed
326 // since CompUnit::ForeachFunction only iterates over already
327 // parsed functions.
328 SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
329 if (!sym_vendor)
330 continue;
331 if (!sym_vendor->ParseFunctions(*cu_sp))
332 continue;
333 // If we got any functions, use ForeachFunction to do the iteration.
334 cu_sp->ForeachFunction([&](const FunctionSP &func_sp) {
335 if (!FunctionPasses(*func_sp.get()))
336 return false; // Didn't pass the filter, just keep going.
337 if (searcher.GetDepth() == lldb::eSearchDepthFunction) {
338 SymbolContext matchingContext(m_target_sp, module_sp,
339 cu_sp.get(), func_sp.get());
340 shouldContinue = searcher.SearchCallback(*this,
341 matchingContext,
342 nullptr, false);
343 } else {
344 shouldContinue = DoFunctionIteration(func_sp.get(), context,
345 searcher);
346 }
347 return shouldContinue != Searcher::eCallbackReturnContinue;
348 });
349 }
350 }
351 }
352 } else {
353 if (CompUnitPasses(*context.comp_unit)) {
354 SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit);
355 return searcher.SearchCallback(*this, matchingContext, nullptr, false);
356 }
357 }
358 return Searcher::eCallbackReturnContinue;
359 }
360
DoFunctionIteration(Function * function,const SymbolContext & context,Searcher & searcher)361 Searcher::CallbackReturn SearchFilter::DoFunctionIteration(
362 Function *function, const SymbolContext &context, Searcher &searcher) {
363 // FIXME: Implement...
364 return Searcher::eCallbackReturnContinue;
365 }
366
367 //----------------------------------------------------------------------
368 // SearchFilterForUnconstrainedSearches:
369 // Selects a shared library matching a given file spec, consulting the targets
370 // "black list".
371 //----------------------------------------------------------------------
CreateFromStructuredData(Target & target,const StructuredData::Dictionary & data_dict,Status & error)372 SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData(
373 Target &target, const StructuredData::Dictionary &data_dict,
374 Status &error) {
375 // No options for an unconstrained search.
376 return std::make_shared<SearchFilterForUnconstrainedSearches>(
377 target.shared_from_this());
378 }
379
380 StructuredData::ObjectSP
SerializeToStructuredData()381 SearchFilterForUnconstrainedSearches::SerializeToStructuredData() {
382 // The options dictionary is an empty dictionary:
383 auto result_sp = std::make_shared<StructuredData::Dictionary>();
384 return WrapOptionsDict(result_sp);
385 }
386
ModulePasses(const FileSpec & module_spec)387 bool SearchFilterForUnconstrainedSearches::ModulePasses(
388 const FileSpec &module_spec) {
389 return !m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec);
390 }
391
ModulePasses(const lldb::ModuleSP & module_sp)392 bool SearchFilterForUnconstrainedSearches::ModulePasses(
393 const lldb::ModuleSP &module_sp) {
394 if (!module_sp)
395 return true;
396 else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp))
397 return false;
398 else
399 return true;
400 }
401
DoCopyForBreakpoint(Breakpoint & breakpoint)402 lldb::SearchFilterSP SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint(
403 Breakpoint &breakpoint) {
404 return std::make_shared<SearchFilterForUnconstrainedSearches>(*this);
405 }
406
407 //----------------------------------------------------------------------
408 // SearchFilterByModule:
409 // Selects a shared library matching a given file spec
410 //----------------------------------------------------------------------
411
SearchFilterByModule(const lldb::TargetSP & target_sp,const FileSpec & module)412 SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp,
413 const FileSpec &module)
414 : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {}
415
416 SearchFilterByModule::SearchFilterByModule(const SearchFilterByModule &rhs) =
417 default;
418
419 SearchFilterByModule &SearchFilterByModule::
operator =(const SearchFilterByModule & rhs)420 operator=(const SearchFilterByModule &rhs) {
421 m_target_sp = rhs.m_target_sp;
422 m_module_spec = rhs.m_module_spec;
423 return *this;
424 }
425
426 SearchFilterByModule::~SearchFilterByModule() = default;
427
ModulePasses(const ModuleSP & module_sp)428 bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) {
429 return (module_sp &&
430 FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false));
431 }
432
ModulePasses(const FileSpec & spec)433 bool SearchFilterByModule::ModulePasses(const FileSpec &spec) {
434 // Do a full match only if "spec" has a directory
435 const bool full_match = (bool)spec.GetDirectory();
436 return FileSpec::Equal(spec, m_module_spec, full_match);
437 }
438
AddressPasses(Address & address)439 bool SearchFilterByModule::AddressPasses(Address &address) {
440 // FIXME: Not yet implemented
441 return true;
442 }
443
CompUnitPasses(FileSpec & fileSpec)444 bool SearchFilterByModule::CompUnitPasses(FileSpec &fileSpec) { return true; }
445
CompUnitPasses(CompileUnit & compUnit)446 bool SearchFilterByModule::CompUnitPasses(CompileUnit &compUnit) {
447 return true;
448 }
449
Search(Searcher & searcher)450 void SearchFilterByModule::Search(Searcher &searcher) {
451 if (!m_target_sp)
452 return;
453
454 if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
455 SymbolContext empty_sc;
456 empty_sc.target_sp = m_target_sp;
457 searcher.SearchCallback(*this, empty_sc, nullptr, false);
458 }
459
460 // If the module file spec is a full path, then we can just find the one
461 // filespec that passes. Otherwise, we need to go through all modules and
462 // find the ones that match the file name.
463
464 const ModuleList &target_modules = m_target_sp->GetImages();
465 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
466
467 const size_t num_modules = target_modules.GetSize();
468 for (size_t i = 0; i < num_modules; i++) {
469 Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
470 const bool full_match = (bool)m_module_spec.GetDirectory();
471 if (FileSpec::Equal(m_module_spec, module->GetFileSpec(), full_match)) {
472 SymbolContext matchingContext(m_target_sp, module->shared_from_this());
473 Searcher::CallbackReturn shouldContinue;
474
475 shouldContinue = DoModuleIteration(matchingContext, searcher);
476 if (shouldContinue == Searcher::eCallbackReturnStop)
477 return;
478 }
479 }
480 }
481
GetDescription(Stream * s)482 void SearchFilterByModule::GetDescription(Stream *s) {
483 s->PutCString(", module = ");
484 s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>"));
485 }
486
GetFilterRequiredItems()487 uint32_t SearchFilterByModule::GetFilterRequiredItems() {
488 return eSymbolContextModule;
489 }
490
Dump(Stream * s) const491 void SearchFilterByModule::Dump(Stream *s) const {}
492
493 lldb::SearchFilterSP
DoCopyForBreakpoint(Breakpoint & breakpoint)494 SearchFilterByModule::DoCopyForBreakpoint(Breakpoint &breakpoint) {
495 return std::make_shared<SearchFilterByModule>(*this);
496 }
497
CreateFromStructuredData(Target & target,const StructuredData::Dictionary & data_dict,Status & error)498 SearchFilterSP SearchFilterByModule::CreateFromStructuredData(
499 Target &target, const StructuredData::Dictionary &data_dict,
500 Status &error) {
501 StructuredData::Array *modules_array;
502 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
503 modules_array);
504 if (!success) {
505 error.SetErrorString("SFBM::CFSD: Could not find the module list key.");
506 return nullptr;
507 }
508
509 size_t num_modules = modules_array->GetSize();
510 if (num_modules > 1) {
511 error.SetErrorString(
512 "SFBM::CFSD: Only one modules allowed for SearchFilterByModule.");
513 return nullptr;
514 }
515
516 llvm::StringRef module;
517 success = modules_array->GetItemAtIndexAsString(0, module);
518 if (!success) {
519 error.SetErrorString("SFBM::CFSD: filter module item not a string.");
520 return nullptr;
521 }
522 FileSpec module_spec(module);
523
524 return std::make_shared<SearchFilterByModule>(target.shared_from_this(),
525 module_spec);
526 }
527
SerializeToStructuredData()528 StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() {
529 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
530 auto module_array_sp = std::make_shared<StructuredData::Array>();
531 module_array_sp->AddItem(
532 std::make_shared<StructuredData::String>(m_module_spec.GetPath()));
533 options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp);
534 return WrapOptionsDict(options_dict_sp);
535 }
536
537 //----------------------------------------------------------------------
538 // SearchFilterByModuleList:
539 // Selects a shared library matching a given file spec
540 //----------------------------------------------------------------------
541
SearchFilterByModuleList(const lldb::TargetSP & target_sp,const FileSpecList & module_list)542 SearchFilterByModuleList::SearchFilterByModuleList(
543 const lldb::TargetSP &target_sp, const FileSpecList &module_list)
544 : SearchFilter(target_sp, FilterTy::ByModules),
545 m_module_spec_list(module_list) {}
546
SearchFilterByModuleList(const lldb::TargetSP & target_sp,const FileSpecList & module_list,enum FilterTy filter_ty)547 SearchFilterByModuleList::SearchFilterByModuleList(
548 const lldb::TargetSP &target_sp, const FileSpecList &module_list,
549 enum FilterTy filter_ty)
550 : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {}
551
552 SearchFilterByModuleList::SearchFilterByModuleList(
553 const SearchFilterByModuleList &rhs) = default;
554
555 SearchFilterByModuleList &SearchFilterByModuleList::
operator =(const SearchFilterByModuleList & rhs)556 operator=(const SearchFilterByModuleList &rhs) {
557 m_target_sp = rhs.m_target_sp;
558 m_module_spec_list = rhs.m_module_spec_list;
559 return *this;
560 }
561
562 SearchFilterByModuleList::~SearchFilterByModuleList() = default;
563
ModulePasses(const ModuleSP & module_sp)564 bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) {
565 if (m_module_spec_list.GetSize() == 0)
566 return true;
567
568 return module_sp && m_module_spec_list.FindFileIndex(
569 0, module_sp->GetFileSpec(), false) != UINT32_MAX;
570 }
571
ModulePasses(const FileSpec & spec)572 bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) {
573 if (m_module_spec_list.GetSize() == 0)
574 return true;
575
576 return m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX;
577 }
578
AddressPasses(Address & address)579 bool SearchFilterByModuleList::AddressPasses(Address &address) {
580 // FIXME: Not yet implemented
581 return true;
582 }
583
CompUnitPasses(FileSpec & fileSpec)584 bool SearchFilterByModuleList::CompUnitPasses(FileSpec &fileSpec) {
585 return true;
586 }
587
CompUnitPasses(CompileUnit & compUnit)588 bool SearchFilterByModuleList::CompUnitPasses(CompileUnit &compUnit) {
589 return true;
590 }
591
Search(Searcher & searcher)592 void SearchFilterByModuleList::Search(Searcher &searcher) {
593 if (!m_target_sp)
594 return;
595
596 if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
597 SymbolContext empty_sc;
598 empty_sc.target_sp = m_target_sp;
599 searcher.SearchCallback(*this, empty_sc, nullptr, false);
600 }
601
602 // If the module file spec is a full path, then we can just find the one
603 // filespec that passes. Otherwise, we need to go through all modules and
604 // find the ones that match the file name.
605
606 const ModuleList &target_modules = m_target_sp->GetImages();
607 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
608
609 const size_t num_modules = target_modules.GetSize();
610 for (size_t i = 0; i < num_modules; i++) {
611 Module *module = target_modules.GetModulePointerAtIndexUnlocked(i);
612 if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) !=
613 UINT32_MAX) {
614 SymbolContext matchingContext(m_target_sp, module->shared_from_this());
615 Searcher::CallbackReturn shouldContinue;
616
617 shouldContinue = DoModuleIteration(matchingContext, searcher);
618 if (shouldContinue == Searcher::eCallbackReturnStop)
619 return;
620 }
621 }
622 }
623
GetDescription(Stream * s)624 void SearchFilterByModuleList::GetDescription(Stream *s) {
625 size_t num_modules = m_module_spec_list.GetSize();
626 if (num_modules == 1) {
627 s->Printf(", module = ");
628 s->PutCString(
629 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
630 "<Unknown>"));
631 } else {
632 s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules);
633 for (size_t i = 0; i < num_modules; i++) {
634 s->PutCString(
635 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
636 "<Unknown>"));
637 if (i != num_modules - 1)
638 s->PutCString(", ");
639 }
640 }
641 }
642
GetFilterRequiredItems()643 uint32_t SearchFilterByModuleList::GetFilterRequiredItems() {
644 return eSymbolContextModule;
645 }
646
Dump(Stream * s) const647 void SearchFilterByModuleList::Dump(Stream *s) const {}
648
649 lldb::SearchFilterSP
DoCopyForBreakpoint(Breakpoint & breakpoint)650 SearchFilterByModuleList::DoCopyForBreakpoint(Breakpoint &breakpoint) {
651 return std::make_shared<SearchFilterByModuleList>(*this);
652 }
653
CreateFromStructuredData(Target & target,const StructuredData::Dictionary & data_dict,Status & error)654 SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
655 Target &target, const StructuredData::Dictionary &data_dict,
656 Status &error) {
657 StructuredData::Array *modules_array;
658 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
659 modules_array);
660 FileSpecList modules;
661 if (success) {
662 size_t num_modules = modules_array->GetSize();
663 for (size_t i = 0; i < num_modules; i++) {
664 llvm::StringRef module;
665 success = modules_array->GetItemAtIndexAsString(i, module);
666 if (!success) {
667 error.SetErrorStringWithFormat(
668 "SFBM::CFSD: filter module item %zu not a string.", i);
669 return nullptr;
670 }
671 modules.Append(FileSpec(module));
672 }
673 }
674
675 return std::make_shared<SearchFilterByModuleList>(target.shared_from_this(),
676 modules);
677 }
678
SerializeUnwrapped(StructuredData::DictionarySP & options_dict_sp)679 void SearchFilterByModuleList::SerializeUnwrapped(
680 StructuredData::DictionarySP &options_dict_sp) {
681 SerializeFileSpecList(options_dict_sp, OptionNames::ModList,
682 m_module_spec_list);
683 }
684
SerializeToStructuredData()685 StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() {
686 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
687 SerializeUnwrapped(options_dict_sp);
688 return WrapOptionsDict(options_dict_sp);
689 }
690
691 //----------------------------------------------------------------------
692 // SearchFilterByModuleListAndCU:
693 // Selects a shared library matching a given file spec
694 //----------------------------------------------------------------------
695
SearchFilterByModuleListAndCU(const lldb::TargetSP & target_sp,const FileSpecList & module_list,const FileSpecList & cu_list)696 SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
697 const lldb::TargetSP &target_sp, const FileSpecList &module_list,
698 const FileSpecList &cu_list)
699 : SearchFilterByModuleList(target_sp, module_list,
700 FilterTy::ByModulesAndCU),
701 m_cu_spec_list(cu_list) {}
702
703 SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(
704 const SearchFilterByModuleListAndCU &rhs) = default;
705
706 SearchFilterByModuleListAndCU &SearchFilterByModuleListAndCU::
operator =(const SearchFilterByModuleListAndCU & rhs)707 operator=(const SearchFilterByModuleListAndCU &rhs) {
708 if (&rhs != this) {
709 m_target_sp = rhs.m_target_sp;
710 m_module_spec_list = rhs.m_module_spec_list;
711 m_cu_spec_list = rhs.m_cu_spec_list;
712 }
713 return *this;
714 }
715
716 SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default;
717
CreateFromStructuredData(Target & target,const StructuredData::Dictionary & data_dict,Status & error)718 lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
719 Target &target, const StructuredData::Dictionary &data_dict,
720 Status &error) {
721 StructuredData::Array *modules_array = nullptr;
722 SearchFilterSP result_sp;
723 bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList),
724 modules_array);
725 FileSpecList modules;
726 if (success) {
727 size_t num_modules = modules_array->GetSize();
728 for (size_t i = 0; i < num_modules; i++) {
729 llvm::StringRef module;
730 success = modules_array->GetItemAtIndexAsString(i, module);
731 if (!success) {
732 error.SetErrorStringWithFormat(
733 "SFBM::CFSD: filter module item %zu not a string.", i);
734 return result_sp;
735 }
736 modules.Append(FileSpec(module));
737 }
738 }
739
740 StructuredData::Array *cus_array = nullptr;
741 success =
742 data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array);
743 if (!success) {
744 error.SetErrorString("SFBM::CFSD: Could not find the CU list key.");
745 return result_sp;
746 }
747
748 size_t num_cus = cus_array->GetSize();
749 FileSpecList cus;
750 for (size_t i = 0; i < num_cus; i++) {
751 llvm::StringRef cu;
752 success = cus_array->GetItemAtIndexAsString(i, cu);
753 if (!success) {
754 error.SetErrorStringWithFormat(
755 "SFBM::CFSD: filter cu item %zu not a string.", i);
756 return nullptr;
757 }
758 cus.Append(FileSpec(cu));
759 }
760
761 return std::make_shared<SearchFilterByModuleListAndCU>(
762 target.shared_from_this(), modules, cus);
763 }
764
765 StructuredData::ObjectSP
SerializeToStructuredData()766 SearchFilterByModuleListAndCU::SerializeToStructuredData() {
767 auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
768 SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp);
769 SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list);
770 return WrapOptionsDict(options_dict_sp);
771 }
772
AddressPasses(Address & address)773 bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
774 SymbolContext sym_ctx;
775 address.CalculateSymbolContext(&sym_ctx, eSymbolContextEverything);
776 if (!sym_ctx.comp_unit) {
777 if (m_cu_spec_list.GetSize() != 0)
778 return false; // Has no comp_unit so can't pass the file check.
779 }
780 if (m_cu_spec_list.FindFileIndex(0, sym_ctx.comp_unit, false) == UINT32_MAX)
781 return false; // Fails the file check
782 return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp);
783 }
784
CompUnitPasses(FileSpec & fileSpec)785 bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
786 return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX;
787 }
788
CompUnitPasses(CompileUnit & compUnit)789 bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) {
790 bool in_cu_list =
791 m_cu_spec_list.FindFileIndex(0, compUnit, false) != UINT32_MAX;
792 if (in_cu_list) {
793 ModuleSP module_sp(compUnit.GetModule());
794 if (module_sp) {
795 bool module_passes = SearchFilterByModuleList::ModulePasses(module_sp);
796 return module_passes;
797 } else
798 return true;
799 } else
800 return false;
801 }
802
Search(Searcher & searcher)803 void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
804 if (!m_target_sp)
805 return;
806
807 if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
808 SymbolContext empty_sc;
809 empty_sc.target_sp = m_target_sp;
810 searcher.SearchCallback(*this, empty_sc, nullptr, false);
811 }
812
813 // If the module file spec is a full path, then we can just find the one
814 // filespec that passes. Otherwise, we need to go through all modules and
815 // find the ones that match the file name.
816
817 ModuleList matching_modules;
818 const ModuleList &target_images = m_target_sp->GetImages();
819 std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
820
821 const size_t num_modules = target_images.GetSize();
822 bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
823 for (size_t i = 0; i < num_modules; i++) {
824 lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i);
825 if (no_modules_in_filter ||
826 m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) !=
827 UINT32_MAX) {
828 SymbolContext matchingContext(m_target_sp, module_sp);
829 Searcher::CallbackReturn shouldContinue;
830
831 if (searcher.GetDepth() == lldb::eSearchDepthModule) {
832 shouldContinue = DoModuleIteration(matchingContext, searcher);
833 if (shouldContinue == Searcher::eCallbackReturnStop)
834 return;
835 } else {
836 const size_t num_cu = module_sp->GetNumCompileUnits();
837 for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) {
838 CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
839 matchingContext.comp_unit = cu_sp.get();
840 if (matchingContext.comp_unit) {
841 if (m_cu_spec_list.FindFileIndex(0, *matchingContext.comp_unit,
842 false) != UINT32_MAX) {
843 shouldContinue =
844 DoCUIteration(module_sp, matchingContext, searcher);
845 if (shouldContinue == Searcher::eCallbackReturnStop)
846 return;
847 }
848 }
849 }
850 }
851 }
852 }
853 }
854
GetDescription(Stream * s)855 void SearchFilterByModuleListAndCU::GetDescription(Stream *s) {
856 size_t num_modules = m_module_spec_list.GetSize();
857 if (num_modules == 1) {
858 s->Printf(", module = ");
859 s->PutCString(
860 m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
861 "<Unknown>"));
862 } else if (num_modules > 0) {
863 s->Printf(", modules(%" PRIu64 ") = ", static_cast<uint64_t>(num_modules));
864 for (size_t i = 0; i < num_modules; i++) {
865 s->PutCString(
866 m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString(
867 "<Unknown>"));
868 if (i != num_modules - 1)
869 s->PutCString(", ");
870 }
871 }
872 }
873
GetFilterRequiredItems()874 uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() {
875 return eSymbolContextModule | eSymbolContextCompUnit;
876 }
877
Dump(Stream * s) const878 void SearchFilterByModuleListAndCU::Dump(Stream *s) const {}
879
880 lldb::SearchFilterSP
DoCopyForBreakpoint(Breakpoint & breakpoint)881 SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) {
882 return std::make_shared<SearchFilterByModuleListAndCU>(*this);
883 }
884