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