]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Core/SearchFilter.cpp
Vendor import of lldb trunk r351319 (just before the release_80 branch
[FreeBSD/FreeBSD.git] / 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"
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
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
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
71 void Searcher::GetDescription(Stream *s) {}
72
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
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
141 bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; }
142
143 bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; }
144
145 bool SearchFilter::AddressPasses(Address &address) { return true; }
146
147 bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; }
148
149 bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; }
150
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
160 uint32_t SearchFilter::GetFilterRequiredItems() {
161   return (lldb::SymbolContextItem)0;
162 }
163
164 void SearchFilter::GetDescription(Stream *s) {}
165
166 void SearchFilter::Dump(Stream *s) const {}
167
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
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
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
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
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
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
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
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
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 //----------------------------------------------------------------------
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
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
387 bool SearchFilterForUnconstrainedSearches::ModulePasses(
388     const FileSpec &module_spec) {
389   return !m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec);
390 }
391
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
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
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::
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
428 bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) {
429   return (module_sp &&
430           FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false));
431 }
432
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
439 bool SearchFilterByModule::AddressPasses(Address &address) {
440   // FIXME: Not yet implemented
441   return true;
442 }
443
444 bool SearchFilterByModule::CompUnitPasses(FileSpec &fileSpec) { return true; }
445
446 bool SearchFilterByModule::CompUnitPasses(CompileUnit &compUnit) {
447   return true;
448 }
449
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
482 void SearchFilterByModule::GetDescription(Stream *s) {
483   s->PutCString(", module = ");
484   s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>"));
485 }
486
487 uint32_t SearchFilterByModule::GetFilterRequiredItems() {
488   return eSymbolContextModule;
489 }
490
491 void SearchFilterByModule::Dump(Stream *s) const {}
492
493 lldb::SearchFilterSP
494 SearchFilterByModule::DoCopyForBreakpoint(Breakpoint &breakpoint) {
495   return std::make_shared<SearchFilterByModule>(*this);
496 }
497
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
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
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
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::
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
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
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
579 bool SearchFilterByModuleList::AddressPasses(Address &address) {
580   // FIXME: Not yet implemented
581   return true;
582 }
583
584 bool SearchFilterByModuleList::CompUnitPasses(FileSpec &fileSpec) {
585   return true;
586 }
587
588 bool SearchFilterByModuleList::CompUnitPasses(CompileUnit &compUnit) {
589   return true;
590 }
591
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
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
643 uint32_t SearchFilterByModuleList::GetFilterRequiredItems() {
644   return eSymbolContextModule;
645 }
646
647 void SearchFilterByModuleList::Dump(Stream *s) const {}
648
649 lldb::SearchFilterSP
650 SearchFilterByModuleList::DoCopyForBreakpoint(Breakpoint &breakpoint) {
651   return std::make_shared<SearchFilterByModuleList>(*this);
652 }
653
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
679 void SearchFilterByModuleList::SerializeUnwrapped(
680     StructuredData::DictionarySP &options_dict_sp) {
681   SerializeFileSpecList(options_dict_sp, OptionNames::ModList,
682                         m_module_spec_list);
683 }
684
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
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::
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
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
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
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
785 bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
786   return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX;
787 }
788
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
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
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
874 uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() {
875   return eSymbolContextModule | eSymbolContextCompUnit;
876 }
877
878 void SearchFilterByModuleListAndCU::Dump(Stream *s) const {}
879
880 lldb::SearchFilterSP
881 SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) {
882   return std::make_shared<SearchFilterByModuleListAndCU>(*this);
883 }