Coverage Report

Created: 2023-09-21 18:56

/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
51
const char *SearchFilter::FilterTyToName(enum FilterTy type) {
52
51
  if (type > LastKnownFilterType)
53
0
    return g_ty_to_name[UnknownFilter];
54
55
51
  return g_ty_to_name[type];
56
51
}
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
22.5k
Searcher::Searcher() = default;
67
68
22.4k
Searcher::~Searcher() = default;
69
70
0
void Searcher::GetDescription(Stream *s) {}
71
72
SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType)
73
15.8k
    : m_target_sp(target_sp), SubclassID(filterType) {}
74
75
15.7k
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
7.45k
bool SearchFilter::AddressPasses(Address &address) { return true; }
142
143
0
bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; }
144
145
4.30k
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
31.6k
uint32_t SearchFilter::GetFilterRequiredItems() {
157
31.6k
  return (lldb::SymbolContextItem)0;
158
31.6k
}
159
160
299
void SearchFilter::GetDescription(Stream *s) {}
161
162
0
void SearchFilter::Dump(Stream *s) const {}
163
164
15
lldb::SearchFilterSP SearchFilter::CreateCopy(lldb::TargetSP& target_sp) {
165
15
  SearchFilterSP ret_sp = DoCreateCopy();
166
15
  ret_sp->SetTarget(target_sp);
167
15
  return ret_sp;
168
15
}
169
170
// Helper functions for serialization.
171
172
StructuredData::DictionarySP
173
51
SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) {
174
51
  if (!options_dict_sp || !options_dict_sp->IsValid())
175
0
    return StructuredData::DictionarySP();
176
177
51
  auto type_dict_sp = std::make_shared<StructuredData::Dictionary>();
178
51
  type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetFilterName());
179
51
  type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp);
180
181
51
  return type_dict_sp;
182
51
}
183
184
void SearchFilter::SerializeFileSpecList(
185
    StructuredData::DictionarySP &options_dict_sp, OptionNames name,
186
33
    FileSpecList &file_list) {
187
33
  size_t num_modules = file_list.GetSize();
188
189
  // Don't serialize empty lists.
190
33
  if (num_modules == 0)
191
7
    return;
192
193
26
  auto module_array_sp = std::make_shared<StructuredData::Array>();
194
71
  for (size_t i = 0; i < num_modules; 
i++45
) {
195
45
    module_array_sp->AddItem(std::make_shared<StructuredData::String>(
196
45
        file_list.GetFileSpecAtIndex(i).GetPath()));
197
45
  }
198
26
  options_dict_sp->AddItem(GetKey(name), module_array_sp);
199
26
}
200
201
// UTILITY Functions to help iterate down through the elements of the
202
// SymbolContext.
203
204
6.06k
void SearchFilter::Search(Searcher &searcher) {
205
6.06k
  SymbolContext empty_sc;
206
207
6.06k
  if (!m_target_sp)
208
1
    return;
209
6.06k
  empty_sc.target_sp = m_target_sp;
210
211
6.06k
  if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
212
4.37k
    searcher.SearchCallback(*this, empty_sc, nullptr);
213
4.37k
    return;
214
4.37k
  }
215
216
1.69k
  DoModuleIteration(empty_sc, searcher);
217
1.69k
}
218
219
9.19k
void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
220
9.19k
  SymbolContext empty_sc;
221
222
9.19k
  if (!m_target_sp)
223
0
    return;
224
9.19k
  empty_sc.target_sp = m_target_sp;
225
226
9.19k
  if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
227
138
    searcher.SearchCallback(*this, empty_sc, nullptr);
228
138
    return;
229
138
  }
230
231
115k
  
for (ModuleSP module_sp : modules.Modules())9.06k
{
232
115k
    if (!ModulePasses(module_sp))
233
0
      continue;
234
115k
    if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop)
235
0
      return;
236
115k
  }
237
9.06k
}
238
239
Searcher::CallbackReturn
240
SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp,
241
115k
                                Searcher &searcher) {
242
115k
  SymbolContext matchingContext(m_target_sp, module_sp);
243
115k
  return DoModuleIteration(matchingContext, searcher);
244
115k
}
245
246
Searcher::CallbackReturn
247
SearchFilter::DoModuleIteration(const SymbolContext &context,
248
128k
                                Searcher &searcher) {
249
128k
  if (searcher.GetDepth() < lldb::eSearchDepthModule)
250
0
    return Searcher::eCallbackReturnContinue;
251
252
128k
  if (context.module_sp) {
253
127k
    if (searcher.GetDepth() != lldb::eSearchDepthModule)
254
52.6k
      return DoCUIteration(context.module_sp, context, searcher);
255
256
74.5k
    SymbolContext matchingContext(context.module_sp.get());
257
74.5k
    searcher.SearchCallback(*this, matchingContext, nullptr);
258
74.5k
    return Searcher::eCallbackReturnContinue;
259
127k
  }
260
261
80.5k
  
for (ModuleSP module_sp : m_target_sp->GetImages().Modules())1.69k
{
262
    // If this is the last level supplied, then call the callback directly,
263
    // otherwise descend.
264
80.5k
    if (!ModulePasses(module_sp))
265
1.58k
      continue;
266
267
78.9k
    if (searcher.GetDepth() == lldb::eSearchDepthModule) {
268
78.8k
      SymbolContext matchingContext(m_target_sp, module_sp);
269
270
78.8k
      Searcher::CallbackReturn shouldContinue =
271
78.8k
          searcher.SearchCallback(*this, matchingContext, nullptr);
272
78.8k
      if (shouldContinue == Searcher::eCallbackReturnStop ||
273
78.8k
          shouldContinue == Searcher::eCallbackReturnPop)
274
0
        return shouldContinue;
275
78.8k
    } else {
276
123
      Searcher::CallbackReturn shouldContinue =
277
123
          DoCUIteration(module_sp, context, searcher);
278
123
      if (shouldContinue == Searcher::eCallbackReturnStop)
279
0
        return shouldContinue;
280
123
      else if (shouldContinue == Searcher::eCallbackReturnPop)
281
0
        continue;
282
123
    }
283
78.9k
  }
284
285
1.69k
  return Searcher::eCallbackReturnContinue;
286
1.69k
}
287
288
Searcher::CallbackReturn
289
SearchFilter::DoCUIteration(const ModuleSP &module_sp,
290
53.7k
                            const SymbolContext &context, Searcher &searcher) {
291
53.7k
  Searcher::CallbackReturn shouldContinue;
292
53.7k
  if (context.comp_unit != nullptr) {
293
1.03k
    if (CompUnitPasses(*context.comp_unit)) {
294
1.03k
      SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit);
295
1.03k
      return searcher.SearchCallback(*this, matchingContext, nullptr);
296
1.03k
    }
297
0
    return Searcher::eCallbackReturnContinue;
298
1.03k
  }
299
300
52.7k
  const size_t num_comp_units = module_sp->GetNumCompileUnits();
301
55.9k
  for (size_t i = 0; i < num_comp_units; 
i++3.14k
) {
302
3.14k
    CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i));
303
3.14k
    if (!cu_sp)
304
0
      continue;
305
3.14k
    if (!CompUnitPasses(*(cu_sp.get())))
306
2.99k
      continue;
307
308
152
    if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) {
309
151
      SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
310
311
151
      shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr);
312
313
151
      if (shouldContinue == Searcher::eCallbackReturnPop)
314
0
        return Searcher::eCallbackReturnContinue;
315
151
      else if (shouldContinue == Searcher::eCallbackReturnStop)
316
0
        return shouldContinue;
317
151
      continue;
318
151
    }
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
52.7k
  return Searcher::eCallbackReturnContinue;
344
52.7k
}
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
27
SearchFilterForUnconstrainedSearches::SerializeToStructuredData() {
365
  // The options dictionary is an empty dictionary:
366
27
  auto result_sp = std::make_shared<StructuredData::Dictionary>();
367
27
  return WrapOptionsDict(result_sp);
368
27
}
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
273k
    const lldb::ModuleSP &module_sp) {
377
273k
  if (!module_sp)
378
0
    return true;
379
273k
  else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp))
380
4.01k
    return false;
381
268k
  return true;
382
273k
}
383
384
6
SearchFilterSP SearchFilterForUnconstrainedSearches::DoCreateCopy() {
385
6
  return std::make_shared<SearchFilterForUnconstrainedSearches>(*this);
386
6
}
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
904
    : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {}
394
395
904
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
904
void SearchFilterByModule::Search(Searcher &searcher) {
412
904
  if (!m_target_sp)
413
0
    return;
414
415
904
  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
904
  const ModuleList &target_modules = m_target_sp->GetImages();
426
904
  std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
427
428
40.9k
  for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
429
40.9k
    if (FileSpec::Match(m_module_spec, module_sp->GetFileSpec())) {
430
936
      SymbolContext matchingContext(m_target_sp, module_sp);
431
936
      Searcher::CallbackReturn shouldContinue;
432
433
936
      shouldContinue = DoModuleIteration(matchingContext, searcher);
434
936
      if (shouldContinue == Searcher::eCallbackReturnStop)
435
0
        return;
436
936
    }
437
40.9k
  }
438
904
}
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
7.42k
    : SearchFilter(target_sp, FilterTy::ByModules),
500
7.42k
      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.07k
    : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {}
506
507
8.44k
SearchFilterByModuleList::~SearchFilterByModuleList() = default;
508
509
291k
bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) {
510
291k
  if (m_module_spec_list.GetSize() == 0)
511
157k
    return true;
512
513
134k
  return module_sp && m_module_spec_list.FindFileIndex(
514
134k
                          0, module_sp->GetFileSpec(), false) != UINT32_MAX;
515
291k
}
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
9.12k
bool SearchFilterByModuleList::AddressPasses(Address &address) {
525
  // FIXME: Not yet implemented
526
9.12k
  return true;
527
9.12k
}
528
529
7.40k
void SearchFilterByModuleList::Search(Searcher &searcher) {
530
7.40k
  if (!m_target_sp)
531
0
    return;
532
533
7.40k
  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
206k
  for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
543
206k
    if (m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) ==
544
206k
        UINT32_MAX)
545
196k
      continue;
546
10.4k
    SymbolContext matchingContext(m_target_sp, module_sp);
547
10.4k
    Searcher::CallbackReturn shouldContinue;
548
549
10.4k
    shouldContinue = DoModuleIteration(matchingContext, searcher);
550
10.4k
    if (shouldContinue == Searcher::eCallbackReturnStop)
551
0
      return;
552
10.4k
  }
553
7.40k
}
554
555
54
void SearchFilterByModuleList::GetDescription(Stream *s) {
556
54
  size_t num_modules = m_module_spec_list.GetSize();
557
54
  if (num_modules == 1) {
558
52
    s->Printf(", module = ");
559
52
    s->PutCString(
560
52
        m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString(
561
52
            "<Unknown>"));
562
52
    return;
563
52
  }
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
10.4k
uint32_t SearchFilterByModuleList::GetFilterRequiredItems() {
576
10.4k
  return eSymbolContextModule;
577
10.4k
}
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
24
    StructuredData::DictionarySP &options_dict_sp) {
613
24
  SerializeFileSpecList(options_dict_sp, OptionNames::ModList,
614
24
                        m_module_spec_list);
615
24
}
616
617
15
StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() {
618
15
  auto options_dict_sp = std::make_shared<StructuredData::Dictionary>();
619
15
  SerializeUnwrapped(options_dict_sp);
620
15
  return WrapOptionsDict(options_dict_sp);
621
15
}
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
1.07k
    : SearchFilterByModuleList(target_sp, module_list,
630
1.07k
                               FilterTy::ByModulesAndCU),
631
1.07k
      m_cu_spec_list(cu_list) {}
632
633
1.07k
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.29k
bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
692
1.29k
  SymbolContext sym_ctx;
693
1.29k
  address.CalculateSymbolContext(&sym_ctx, eSymbolContextEverything);
694
1.29k
  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.29k
  FileSpec cu_spec;
699
1.29k
  if (sym_ctx.comp_unit)
700
1.29k
    cu_spec = sym_ctx.comp_unit->GetPrimaryFile();
701
1.29k
  if (m_cu_spec_list.FindFileIndex(0, cu_spec, false) == UINT32_MAX)
702
2
    return false; // Fails the file check
703
1.28k
  return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp); 
704
1.29k
}
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.07k
bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) {
711
4.07k
  bool in_cu_list = m_cu_spec_list.FindFileIndex(0, compUnit.GetPrimaryFile(),
712
4.07k
                                                 false) != UINT32_MAX;
713
4.07k
  if (!in_cu_list)
714
2.99k
    return false;
715
716
1.08k
  ModuleSP module_sp(compUnit.GetModule());
717
1.08k
  if (!module_sp)
718
0
    return true;
719
720
1.08k
  return SearchFilterByModuleList::ModulePasses(module_sp);
721
1.08k
}
722
723
1.08k
void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
724
1.08k
  if (!m_target_sp)
725
0
    return;
726
727
1.08k
  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.08k
  ModuleList matching_modules;
738
739
1.08k
  bool no_modules_in_filter = m_module_spec_list.GetSize() == 0;
740
56.0k
  for (ModuleSP module_sp : m_target_sp->GetImages().Modules()) {
741
56.0k
    if (!no_modules_in_filter &&
742
56.0k
        m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) ==
743
1.05k
            UINT32_MAX)
744
1.03k
      continue;
745
746
55.0k
    SymbolContext matchingContext(m_target_sp, module_sp);
747
55.0k
    Searcher::CallbackReturn shouldContinue;
748
749
55.0k
    if (searcher.GetDepth() == lldb::eSearchDepthModule) {
750
269
      shouldContinue = DoModuleIteration(matchingContext, searcher);
751
269
      if (shouldContinue == Searcher::eCallbackReturnStop)
752
0
        return;
753
269
      continue;
754
269
    }
755
756
54.7k
    const size_t num_cu = module_sp->GetNumCompileUnits();
757
56.0k
    for (size_t cu_idx = 0; cu_idx < num_cu; 
cu_idx++1.32k
) {
758
1.32k
      CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx);
759
1.32k
      matchingContext.comp_unit = cu_sp.get();
760
1.32k
      if (!matchingContext.comp_unit)
761
0
        continue;
762
1.32k
      if (m_cu_spec_list.FindFileIndex(
763
1.32k
              0, matchingContext.comp_unit->GetPrimaryFile(), false) ==
764
1.32k
          UINT32_MAX)
765
285
        continue;
766
1.03k
      shouldContinue = DoCUIteration(module_sp, matchingContext, searcher);
767
1.03k
      if (shouldContinue == Searcher::eCallbackReturnStop)
768
0
        return;
769
1.03k
    }
770
54.7k
  }
771
1.08k
}
772
773
23
void SearchFilterByModuleListAndCU::GetDescription(Stream *s) {
774
23
  size_t num_modules = m_module_spec_list.GetSize();
775
23
  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
23
  } 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
23
}
791
792
264
uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() {
793
264
  return eSymbolContextModule | eSymbolContextCompUnit;
794
264
}
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
}