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