Coverage Report

Created: 2022-01-18 06:27

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