llvm-project

Форк
0
/
ModuleList.cpp 
1100 строк · 37.2 Кб
1
//===-- ModuleList.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/ModuleList.h"
10
#include "lldb/Core/Module.h"
11
#include "lldb/Core/ModuleSpec.h"
12
#include "lldb/Core/PluginManager.h"
13
#include "lldb/Host/FileSystem.h"
14
#include "lldb/Interpreter/OptionValueFileSpec.h"
15
#include "lldb/Interpreter/OptionValueFileSpecList.h"
16
#include "lldb/Interpreter/OptionValueProperties.h"
17
#include "lldb/Interpreter/Property.h"
18
#include "lldb/Symbol/ObjectFile.h"
19
#include "lldb/Symbol/SymbolContext.h"
20
#include "lldb/Symbol/TypeList.h"
21
#include "lldb/Symbol/VariableList.h"
22
#include "lldb/Utility/ArchSpec.h"
23
#include "lldb/Utility/ConstString.h"
24
#include "lldb/Utility/FileSpecList.h"
25
#include "lldb/Utility/LLDBLog.h"
26
#include "lldb/Utility/Log.h"
27
#include "lldb/Utility/UUID.h"
28
#include "lldb/lldb-defines.h"
29

30
#if defined(_WIN32)
31
#include "lldb/Host/windows/PosixApi.h"
32
#endif
33

34
#include "clang/Driver/Driver.h"
35
#include "llvm/ADT/StringRef.h"
36
#include "llvm/Support/FileSystem.h"
37
#include "llvm/Support/Threading.h"
38
#include "llvm/Support/raw_ostream.h"
39

40
#include <chrono>
41
#include <memory>
42
#include <mutex>
43
#include <string>
44
#include <utility>
45

46
namespace lldb_private {
47
class Function;
48
}
49
namespace lldb_private {
50
class RegularExpression;
51
}
52
namespace lldb_private {
53
class Stream;
54
}
55
namespace lldb_private {
56
class SymbolFile;
57
}
58
namespace lldb_private {
59
class Target;
60
}
61

62
using namespace lldb;
63
using namespace lldb_private;
64

65
namespace {
66

67
#define LLDB_PROPERTIES_modulelist
68
#include "CoreProperties.inc"
69

70
enum {
71
#define LLDB_PROPERTIES_modulelist
72
#include "CorePropertiesEnum.inc"
73
};
74

75
} // namespace
76

77
ModuleListProperties::ModuleListProperties() {
78
  m_collection_sp = std::make_shared<OptionValueProperties>("symbols");
79
  m_collection_sp->Initialize(g_modulelist_properties);
80
  m_collection_sp->SetValueChangedCallback(ePropertySymLinkPaths,
81
                                           [this] { UpdateSymlinkMappings(); });
82

83
  llvm::SmallString<128> path;
84
  if (clang::driver::Driver::getDefaultModuleCachePath(path)) {
85
    lldbassert(SetClangModulesCachePath(FileSpec(path)));
86
  }
87

88
  path.clear();
89
  if (llvm::sys::path::cache_directory(path)) {
90
    llvm::sys::path::append(path, "lldb");
91
    llvm::sys::path::append(path, "IndexCache");
92
    lldbassert(SetLLDBIndexCachePath(FileSpec(path)));
93
  }
94

95
}
96

97
bool ModuleListProperties::GetEnableExternalLookup() const {
98
  const uint32_t idx = ePropertyEnableExternalLookup;
99
  return GetPropertyAtIndexAs<bool>(
100
      idx, g_modulelist_properties[idx].default_uint_value != 0);
101
}
102

103
bool ModuleListProperties::SetEnableExternalLookup(bool new_value) {
104
  return SetPropertyAtIndex(ePropertyEnableExternalLookup, new_value);
105
}
106

107
SymbolDownload ModuleListProperties::GetSymbolAutoDownload() const {
108
  // Backward compatibility alias.
109
  if (GetPropertyAtIndexAs<bool>(ePropertyEnableBackgroundLookup, false))
110
    return eSymbolDownloadBackground;
111

112
  const uint32_t idx = ePropertyAutoDownload;
113
  return GetPropertyAtIndexAs<lldb::SymbolDownload>(
114
      idx, static_cast<lldb::SymbolDownload>(
115
               g_modulelist_properties[idx].default_uint_value));
116
}
117

118
FileSpec ModuleListProperties::GetClangModulesCachePath() const {
119
  const uint32_t idx = ePropertyClangModulesCachePath;
120
  return GetPropertyAtIndexAs<FileSpec>(idx, {});
121
}
122

123
bool ModuleListProperties::SetClangModulesCachePath(const FileSpec &path) {
124
  const uint32_t idx = ePropertyClangModulesCachePath;
125
  return SetPropertyAtIndex(idx, path);
126
}
127

128
FileSpec ModuleListProperties::GetLLDBIndexCachePath() const {
129
  const uint32_t idx = ePropertyLLDBIndexCachePath;
130
  return GetPropertyAtIndexAs<FileSpec>(idx, {});
131
}
132

133
bool ModuleListProperties::SetLLDBIndexCachePath(const FileSpec &path) {
134
  const uint32_t idx = ePropertyLLDBIndexCachePath;
135
  return SetPropertyAtIndex(idx, path);
136
}
137

138
bool ModuleListProperties::GetEnableLLDBIndexCache() const {
139
  const uint32_t idx = ePropertyEnableLLDBIndexCache;
140
  return GetPropertyAtIndexAs<bool>(
141
      idx, g_modulelist_properties[idx].default_uint_value != 0);
142
}
143

144
bool ModuleListProperties::SetEnableLLDBIndexCache(bool new_value) {
145
  return SetPropertyAtIndex(ePropertyEnableLLDBIndexCache, new_value);
146
}
147

148
uint64_t ModuleListProperties::GetLLDBIndexCacheMaxByteSize() {
149
  const uint32_t idx = ePropertyLLDBIndexCacheMaxByteSize;
150
  return GetPropertyAtIndexAs<uint64_t>(
151
      idx, g_modulelist_properties[idx].default_uint_value);
152
}
153

154
uint64_t ModuleListProperties::GetLLDBIndexCacheMaxPercent() {
155
  const uint32_t idx = ePropertyLLDBIndexCacheMaxPercent;
156
  return GetPropertyAtIndexAs<uint64_t>(
157
      idx, g_modulelist_properties[idx].default_uint_value);
158
}
159

160
uint64_t ModuleListProperties::GetLLDBIndexCacheExpirationDays() {
161
  const uint32_t idx = ePropertyLLDBIndexCacheExpirationDays;
162
  return GetPropertyAtIndexAs<uint64_t>(
163
      idx, g_modulelist_properties[idx].default_uint_value);
164
}
165

166
void ModuleListProperties::UpdateSymlinkMappings() {
167
  FileSpecList list =
168
      GetPropertyAtIndexAs<FileSpecList>(ePropertySymLinkPaths, {});
169
  llvm::sys::ScopedWriter lock(m_symlink_paths_mutex);
170
  const bool notify = false;
171
  m_symlink_paths.Clear(notify);
172
  for (auto symlink : list) {
173
    FileSpec resolved;
174
    Status status = FileSystem::Instance().Readlink(symlink, resolved);
175
    if (status.Success())
176
      m_symlink_paths.Append(symlink.GetPath(), resolved.GetPath(), notify);
177
  }
178
}
179

180
PathMappingList ModuleListProperties::GetSymlinkMappings() const {
181
  llvm::sys::ScopedReader lock(m_symlink_paths_mutex);
182
  return m_symlink_paths;
183
}
184

185
bool ModuleListProperties::GetLoadSymbolOnDemand() {
186
  const uint32_t idx = ePropertyLoadSymbolOnDemand;
187
  return GetPropertyAtIndexAs<bool>(
188
      idx, g_modulelist_properties[idx].default_uint_value != 0);
189
}
190

191
ModuleList::ModuleList() : m_modules(), m_modules_mutex() {}
192

193
ModuleList::ModuleList(const ModuleList &rhs) : m_modules(), m_modules_mutex() {
194
  std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex);
195
  std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex);
196
  m_modules = rhs.m_modules;
197
}
198

199
ModuleList::ModuleList(ModuleList::Notifier *notifier)
200
    : m_modules(), m_modules_mutex(), m_notifier(notifier) {}
201

202
const ModuleList &ModuleList::operator=(const ModuleList &rhs) {
203
  if (this != &rhs) {
204
    std::lock(m_modules_mutex, rhs.m_modules_mutex);
205
    std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex,
206
                                                    std::adopt_lock);
207
    std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex,
208
                                                    std::adopt_lock);
209
    m_modules = rhs.m_modules;
210
  }
211
  return *this;
212
}
213

214
ModuleList::~ModuleList() = default;
215

216
void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) {
217
  if (module_sp) {
218
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
219
    // We are required to keep the first element of the Module List as the
220
    // executable module.  So check here and if the first module is NOT an 
221
    // but the new one is, we insert this module at the beginning, rather than 
222
    // at the end.
223
    // We don't need to do any of this if the list is empty:
224
    if (m_modules.empty()) {
225
      m_modules.push_back(module_sp);
226
    } else {
227
      // Since producing the ObjectFile may take some work, first check the 0th
228
      // element, and only if that's NOT an executable look at the incoming
229
      // ObjectFile.  That way in the normal case we only look at the element
230
      // 0 ObjectFile. 
231
      const bool elem_zero_is_executable 
232
          = m_modules[0]->GetObjectFile()->GetType() 
233
              == ObjectFile::Type::eTypeExecutable;
234
      lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
235
      if (!elem_zero_is_executable && obj 
236
          && obj->GetType() == ObjectFile::Type::eTypeExecutable) {
237
        m_modules.insert(m_modules.begin(), module_sp);
238
      } else {
239
        m_modules.push_back(module_sp);
240
      }
241
    }
242
    if (use_notifier && m_notifier)
243
      m_notifier->NotifyModuleAdded(*this, module_sp);
244
  }
245
}
246

247
void ModuleList::Append(const ModuleSP &module_sp, bool notify) {
248
  AppendImpl(module_sp, notify);
249
}
250

251
void ModuleList::ReplaceEquivalent(
252
    const ModuleSP &module_sp,
253
    llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules) {
254
  if (module_sp) {
255
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
256

257
    // First remove any equivalent modules. Equivalent modules are modules
258
    // whose path, platform path and architecture match.
259
    ModuleSpec equivalent_module_spec(module_sp->GetFileSpec(),
260
                                      module_sp->GetArchitecture());
261
    equivalent_module_spec.GetPlatformFileSpec() =
262
        module_sp->GetPlatformFileSpec();
263

264
    size_t idx = 0;
265
    while (idx < m_modules.size()) {
266
      ModuleSP test_module_sp(m_modules[idx]);
267
      if (test_module_sp->MatchesModuleSpec(equivalent_module_spec)) {
268
        if (old_modules)
269
          old_modules->push_back(test_module_sp);
270
        RemoveImpl(m_modules.begin() + idx);
271
      } else {
272
        ++idx;
273
      }
274
    }
275
    // Now add the new module to the list
276
    Append(module_sp);
277
  }
278
}
279

280
bool ModuleList::AppendIfNeeded(const ModuleSP &new_module, bool notify) {
281
  if (new_module) {
282
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
283
    for (const ModuleSP &module_sp : m_modules) {
284
      if (module_sp.get() == new_module.get())
285
        return false; // Already in the list
286
    }
287
    // Only push module_sp on the list if it wasn't already in there.
288
    Append(new_module, notify);
289
    return true;
290
  }
291
  return false;
292
}
293

294
void ModuleList::Append(const ModuleList &module_list) {
295
  for (auto pos : module_list.m_modules)
296
    Append(pos);
297
}
298

299
bool ModuleList::AppendIfNeeded(const ModuleList &module_list) {
300
  bool any_in = false;
301
  for (auto pos : module_list.m_modules) {
302
    if (AppendIfNeeded(pos))
303
      any_in = true;
304
  }
305
  return any_in;
306
}
307

308
bool ModuleList::RemoveImpl(const ModuleSP &module_sp, bool use_notifier) {
309
  if (module_sp) {
310
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
311
    collection::iterator pos, end = m_modules.end();
312
    for (pos = m_modules.begin(); pos != end; ++pos) {
313
      if (pos->get() == module_sp.get()) {
314
        m_modules.erase(pos);
315
        if (use_notifier && m_notifier)
316
          m_notifier->NotifyModuleRemoved(*this, module_sp);
317
        return true;
318
      }
319
    }
320
  }
321
  return false;
322
}
323

324
ModuleList::collection::iterator
325
ModuleList::RemoveImpl(ModuleList::collection::iterator pos,
326
                       bool use_notifier) {
327
  ModuleSP module_sp(*pos);
328
  collection::iterator retval = m_modules.erase(pos);
329
  if (use_notifier && m_notifier)
330
    m_notifier->NotifyModuleRemoved(*this, module_sp);
331
  return retval;
332
}
333

334
bool ModuleList::Remove(const ModuleSP &module_sp, bool notify) {
335
  return RemoveImpl(module_sp, notify);
336
}
337

338
bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp,
339
                               const lldb::ModuleSP &new_module_sp) {
340
  if (!RemoveImpl(old_module_sp, false))
341
    return false;
342
  AppendImpl(new_module_sp, false);
343
  if (m_notifier)
344
    m_notifier->NotifyModuleUpdated(*this, old_module_sp, new_module_sp);
345
  return true;
346
}
347

348
bool ModuleList::RemoveIfOrphaned(const Module *module_ptr) {
349
  if (module_ptr) {
350
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
351
    collection::iterator pos, end = m_modules.end();
352
    for (pos = m_modules.begin(); pos != end; ++pos) {
353
      if (pos->get() == module_ptr) {
354
        if (pos->use_count() == 1) {
355
          pos = RemoveImpl(pos);
356
          return true;
357
        } else
358
          return false;
359
      }
360
    }
361
  }
362
  return false;
363
}
364

365
size_t ModuleList::RemoveOrphans(bool mandatory) {
366
  std::unique_lock<std::recursive_mutex> lock(m_modules_mutex, std::defer_lock);
367

368
  if (mandatory) {
369
    lock.lock();
370
  } else {
371
    // Not mandatory, remove orphans if we can get the mutex
372
    if (!lock.try_lock())
373
      return 0;
374
  }
375
  size_t remove_count = 0;
376
  // Modules might hold shared pointers to other modules, so removing one
377
  // module might make other modules orphans. Keep removing modules until
378
  // there are no further modules that can be removed.
379
  bool made_progress = true;
380
  while (made_progress) {
381
    // Keep track if we make progress this iteration.
382
    made_progress = false;
383
    collection::iterator pos = m_modules.begin();
384
    while (pos != m_modules.end()) {
385
      if (pos->use_count() == 1) {
386
        pos = RemoveImpl(pos);
387
        ++remove_count;
388
        // We did make progress.
389
        made_progress = true;
390
      } else {
391
        ++pos;
392
      }
393
    }
394
  }
395
  return remove_count;
396
}
397

398
size_t ModuleList::Remove(ModuleList &module_list) {
399
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
400
  size_t num_removed = 0;
401
  collection::iterator pos, end = module_list.m_modules.end();
402
  for (pos = module_list.m_modules.begin(); pos != end; ++pos) {
403
    if (Remove(*pos, false /* notify */))
404
      ++num_removed;
405
  }
406
  if (m_notifier)
407
    m_notifier->NotifyModulesRemoved(module_list);
408
  return num_removed;
409
}
410

411
void ModuleList::Clear() { ClearImpl(); }
412

413
void ModuleList::Destroy() { ClearImpl(); }
414

415
void ModuleList::ClearImpl(bool use_notifier) {
416
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
417
  if (use_notifier && m_notifier)
418
    m_notifier->NotifyWillClearList(*this);
419
  m_modules.clear();
420
}
421

422
Module *ModuleList::GetModulePointerAtIndex(size_t idx) const {
423
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
424
  if (idx < m_modules.size())
425
    return m_modules[idx].get();
426
  return nullptr;
427
}
428

429
ModuleSP ModuleList::GetModuleAtIndex(size_t idx) const {
430
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
431
  return GetModuleAtIndexUnlocked(idx);
432
}
433

434
ModuleSP ModuleList::GetModuleAtIndexUnlocked(size_t idx) const {
435
  ModuleSP module_sp;
436
  if (idx < m_modules.size())
437
    module_sp = m_modules[idx];
438
  return module_sp;
439
}
440

441
void ModuleList::FindFunctions(ConstString name,
442
                               FunctionNameType name_type_mask,
443
                               const ModuleFunctionSearchOptions &options,
444
                               SymbolContextList &sc_list) const {
445
  const size_t old_size = sc_list.GetSize();
446

447
  if (name_type_mask & eFunctionNameTypeAuto) {
448
    Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);
449

450
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
451
    for (const ModuleSP &module_sp : m_modules) {
452
      module_sp->FindFunctions(lookup_info, CompilerDeclContext(), options,
453
                               sc_list);
454
    }
455

456
    const size_t new_size = sc_list.GetSize();
457

458
    if (old_size < new_size)
459
      lookup_info.Prune(sc_list, old_size);
460
  } else {
461
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
462
    for (const ModuleSP &module_sp : m_modules) {
463
      module_sp->FindFunctions(name, CompilerDeclContext(), name_type_mask,
464
                               options, sc_list);
465
    }
466
  }
467
}
468

469
void ModuleList::FindFunctionSymbols(ConstString name,
470
                                     lldb::FunctionNameType name_type_mask,
471
                                     SymbolContextList &sc_list) {
472
  const size_t old_size = sc_list.GetSize();
473

474
  if (name_type_mask & eFunctionNameTypeAuto) {
475
    Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);
476

477
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
478
    for (const ModuleSP &module_sp : m_modules) {
479
      module_sp->FindFunctionSymbols(lookup_info.GetLookupName(),
480
                                     lookup_info.GetNameTypeMask(), sc_list);
481
    }
482

483
    const size_t new_size = sc_list.GetSize();
484

485
    if (old_size < new_size)
486
      lookup_info.Prune(sc_list, old_size);
487
  } else {
488
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
489
    for (const ModuleSP &module_sp : m_modules) {
490
      module_sp->FindFunctionSymbols(name, name_type_mask, sc_list);
491
    }
492
  }
493
}
494

495
void ModuleList::FindFunctions(const RegularExpression &name,
496
                               const ModuleFunctionSearchOptions &options,
497
                               SymbolContextList &sc_list) {
498
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
499
  for (const ModuleSP &module_sp : m_modules)
500
    module_sp->FindFunctions(name, options, sc_list);
501
}
502

503
void ModuleList::FindCompileUnits(const FileSpec &path,
504
                                  SymbolContextList &sc_list) const {
505
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
506
  for (const ModuleSP &module_sp : m_modules)
507
    module_sp->FindCompileUnits(path, sc_list);
508
}
509

510
void ModuleList::FindGlobalVariables(ConstString name, size_t max_matches,
511
                                     VariableList &variable_list) const {
512
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
513
  for (const ModuleSP &module_sp : m_modules) {
514
    module_sp->FindGlobalVariables(name, CompilerDeclContext(), max_matches,
515
                                   variable_list);
516
  }
517
}
518

519
void ModuleList::FindGlobalVariables(const RegularExpression &regex,
520
                                     size_t max_matches,
521
                                     VariableList &variable_list) const {
522
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
523
  for (const ModuleSP &module_sp : m_modules)
524
    module_sp->FindGlobalVariables(regex, max_matches, variable_list);
525
}
526

527
void ModuleList::FindSymbolsWithNameAndType(ConstString name,
528
                                            SymbolType symbol_type,
529
                                            SymbolContextList &sc_list) const {
530
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
531
  for (const ModuleSP &module_sp : m_modules)
532
    module_sp->FindSymbolsWithNameAndType(name, symbol_type, sc_list);
533
}
534

535
void ModuleList::FindSymbolsMatchingRegExAndType(
536
    const RegularExpression &regex, lldb::SymbolType symbol_type,
537
    SymbolContextList &sc_list) const {
538
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
539
  for (const ModuleSP &module_sp : m_modules)
540
    module_sp->FindSymbolsMatchingRegExAndType(regex, symbol_type, sc_list);
541
}
542

543
void ModuleList::FindModules(const ModuleSpec &module_spec,
544
                             ModuleList &matching_module_list) const {
545
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
546
  for (const ModuleSP &module_sp : m_modules) {
547
    if (module_sp->MatchesModuleSpec(module_spec))
548
      matching_module_list.Append(module_sp);
549
  }
550
}
551

552
ModuleSP ModuleList::FindModule(const Module *module_ptr) const {
553
  ModuleSP module_sp;
554

555
  // Scope for "locker"
556
  {
557
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
558
    collection::const_iterator pos, end = m_modules.end();
559

560
    for (pos = m_modules.begin(); pos != end; ++pos) {
561
      if ((*pos).get() == module_ptr) {
562
        module_sp = (*pos);
563
        break;
564
      }
565
    }
566
  }
567
  return module_sp;
568
}
569

570
ModuleSP ModuleList::FindModule(const UUID &uuid) const {
571
  ModuleSP module_sp;
572

573
  if (uuid.IsValid()) {
574
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
575
    collection::const_iterator pos, end = m_modules.end();
576

577
    for (pos = m_modules.begin(); pos != end; ++pos) {
578
      if ((*pos)->GetUUID() == uuid) {
579
        module_sp = (*pos);
580
        break;
581
      }
582
    }
583
  }
584
  return module_sp;
585
}
586

587
void ModuleList::FindTypes(Module *search_first, const TypeQuery &query,
588
                           TypeResults &results) const {
589
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
590
  if (search_first) {
591
    search_first->FindTypes(query, results);
592
    if (results.Done(query))
593
      return;
594
  }
595
  for (const auto &module_sp : m_modules) {
596
    if (search_first != module_sp.get()) {
597
      module_sp->FindTypes(query, results);
598
      if (results.Done(query))
599
        return;
600
    }
601
  }
602
}
603

604
bool ModuleList::FindSourceFile(const FileSpec &orig_spec,
605
                                FileSpec &new_spec) const {
606
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
607
  for (const ModuleSP &module_sp : m_modules) {
608
    if (module_sp->FindSourceFile(orig_spec, new_spec))
609
      return true;
610
  }
611
  return false;
612
}
613

614
void ModuleList::FindAddressesForLine(const lldb::TargetSP target_sp,
615
                                      const FileSpec &file, uint32_t line,
616
                                      Function *function,
617
                                      std::vector<Address> &output_local,
618
                                      std::vector<Address> &output_extern) {
619
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
620
  for (const ModuleSP &module_sp : m_modules) {
621
    module_sp->FindAddressesForLine(target_sp, file, line, function,
622
                                    output_local, output_extern);
623
  }
624
}
625

626
ModuleSP ModuleList::FindFirstModule(const ModuleSpec &module_spec) const {
627
  ModuleSP module_sp;
628
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
629
  collection::const_iterator pos, end = m_modules.end();
630
  for (pos = m_modules.begin(); pos != end; ++pos) {
631
    ModuleSP module_sp(*pos);
632
    if (module_sp->MatchesModuleSpec(module_spec))
633
      return module_sp;
634
  }
635
  return module_sp;
636
}
637

638
size_t ModuleList::GetSize() const {
639
  size_t size = 0;
640
  {
641
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
642
    size = m_modules.size();
643
  }
644
  return size;
645
}
646

647
void ModuleList::Dump(Stream *s) const {
648
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
649
  for (const ModuleSP &module_sp : m_modules)
650
    module_sp->Dump(s);
651
}
652

653
void ModuleList::LogUUIDAndPaths(Log *log, const char *prefix_cstr) {
654
  if (log != nullptr) {
655
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
656
    collection::const_iterator pos, begin = m_modules.begin(),
657
                                    end = m_modules.end();
658
    for (pos = begin; pos != end; ++pos) {
659
      Module *module = pos->get();
660
      const FileSpec &module_file_spec = module->GetFileSpec();
661
      LLDB_LOGF(log, "%s[%u] %s (%s) \"%s\"", prefix_cstr ? prefix_cstr : "",
662
                (uint32_t)std::distance(begin, pos),
663
                module->GetUUID().GetAsString().c_str(),
664
                module->GetArchitecture().GetArchitectureName(),
665
                module_file_spec.GetPath().c_str());
666
    }
667
  }
668
}
669

670
bool ModuleList::ResolveFileAddress(lldb::addr_t vm_addr,
671
                                    Address &so_addr) const {
672
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
673
  for (const ModuleSP &module_sp : m_modules) {
674
    if (module_sp->ResolveFileAddress(vm_addr, so_addr))
675
      return true;
676
  }
677

678
  return false;
679
}
680

681
uint32_t
682
ModuleList::ResolveSymbolContextForAddress(const Address &so_addr,
683
                                           SymbolContextItem resolve_scope,
684
                                           SymbolContext &sc) const {
685
  // The address is already section offset so it has a module
686
  uint32_t resolved_flags = 0;
687
  ModuleSP module_sp(so_addr.GetModule());
688
  if (module_sp) {
689
    resolved_flags =
690
        module_sp->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc);
691
  } else {
692
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
693
    collection::const_iterator pos, end = m_modules.end();
694
    for (pos = m_modules.begin(); pos != end; ++pos) {
695
      resolved_flags =
696
          (*pos)->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc);
697
      if (resolved_flags != 0)
698
        break;
699
    }
700
  }
701

702
  return resolved_flags;
703
}
704

705
uint32_t ModuleList::ResolveSymbolContextForFilePath(
706
    const char *file_path, uint32_t line, bool check_inlines,
707
    SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {
708
  FileSpec file_spec(file_path);
709
  return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
710
                                          resolve_scope, sc_list);
711
}
712

713
uint32_t ModuleList::ResolveSymbolContextsForFileSpec(
714
    const FileSpec &file_spec, uint32_t line, bool check_inlines,
715
    SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {
716
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
717
  for (const ModuleSP &module_sp : m_modules) {
718
    module_sp->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
719
                                                resolve_scope, sc_list);
720
  }
721

722
  return sc_list.GetSize();
723
}
724

725
size_t ModuleList::GetIndexForModule(const Module *module) const {
726
  if (module) {
727
    std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
728
    collection::const_iterator pos;
729
    collection::const_iterator begin = m_modules.begin();
730
    collection::const_iterator end = m_modules.end();
731
    for (pos = begin; pos != end; ++pos) {
732
      if ((*pos).get() == module)
733
        return std::distance(begin, pos);
734
    }
735
  }
736
  return LLDB_INVALID_INDEX32;
737
}
738

739
namespace {
740
struct SharedModuleListInfo {
741
  ModuleList module_list;
742
  ModuleListProperties module_list_properties;
743
};
744
}
745
static SharedModuleListInfo &GetSharedModuleListInfo()
746
{
747
  static SharedModuleListInfo *g_shared_module_list_info = nullptr;
748
  static llvm::once_flag g_once_flag;
749
  llvm::call_once(g_once_flag, []() {
750
    // NOTE: Intentionally leak the module list so a program doesn't have to
751
    // cleanup all modules and object files as it exits. This just wastes time
752
    // doing a bunch of cleanup that isn't required.
753
    if (g_shared_module_list_info == nullptr)
754
      g_shared_module_list_info = new SharedModuleListInfo();
755
  });
756
  return *g_shared_module_list_info;
757
}
758

759
static ModuleList &GetSharedModuleList() {
760
  return GetSharedModuleListInfo().module_list;
761
}
762

763
ModuleListProperties &ModuleList::GetGlobalModuleListProperties() {
764
  return GetSharedModuleListInfo().module_list_properties;
765
}
766

767
bool ModuleList::ModuleIsInCache(const Module *module_ptr) {
768
  if (module_ptr) {
769
    ModuleList &shared_module_list = GetSharedModuleList();
770
    return shared_module_list.FindModule(module_ptr).get() != nullptr;
771
  }
772
  return false;
773
}
774

775
void ModuleList::FindSharedModules(const ModuleSpec &module_spec,
776
                                   ModuleList &matching_module_list) {
777
  GetSharedModuleList().FindModules(module_spec, matching_module_list);
778
}
779

780
lldb::ModuleSP ModuleList::FindSharedModule(const UUID &uuid) {
781
  return GetSharedModuleList().FindModule(uuid);
782
}
783

784
size_t ModuleList::RemoveOrphanSharedModules(bool mandatory) {
785
  return GetSharedModuleList().RemoveOrphans(mandatory);
786
}
787

788
Status
789
ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
790
                            const FileSpecList *module_search_paths_ptr,
791
                            llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,
792
                            bool *did_create_ptr, bool always_create) {
793
  ModuleList &shared_module_list = GetSharedModuleList();
794
  std::lock_guard<std::recursive_mutex> guard(
795
      shared_module_list.m_modules_mutex);
796
  char path[PATH_MAX];
797

798
  Status error;
799

800
  module_sp.reset();
801

802
  if (did_create_ptr)
803
    *did_create_ptr = false;
804

805
  const UUID *uuid_ptr = module_spec.GetUUIDPtr();
806
  const FileSpec &module_file_spec = module_spec.GetFileSpec();
807
  const ArchSpec &arch = module_spec.GetArchitecture();
808

809
  // Make sure no one else can try and get or create a module while this
810
  // function is actively working on it by doing an extra lock on the global
811
  // mutex list.
812
  if (!always_create) {
813
    ModuleList matching_module_list;
814
    shared_module_list.FindModules(module_spec, matching_module_list);
815
    const size_t num_matching_modules = matching_module_list.GetSize();
816

817
    if (num_matching_modules > 0) {
818
      for (size_t module_idx = 0; module_idx < num_matching_modules;
819
           ++module_idx) {
820
        module_sp = matching_module_list.GetModuleAtIndex(module_idx);
821

822
        // Make sure the file for the module hasn't been modified
823
        if (module_sp->FileHasChanged()) {
824
          if (old_modules)
825
            old_modules->push_back(module_sp);
826

827
          Log *log = GetLog(LLDBLog::Modules);
828
          if (log != nullptr)
829
            LLDB_LOGF(
830
                log, "%p '%s' module changed: removing from global module list",
831
                static_cast<void *>(module_sp.get()),
832
                module_sp->GetFileSpec().GetFilename().GetCString());
833

834
          shared_module_list.Remove(module_sp);
835
          module_sp.reset();
836
        } else {
837
          // The module matches and the module was not modified from when it
838
          // was last loaded.
839
          return error;
840
        }
841
      }
842
    }
843
  }
844

845
  if (module_sp)
846
    return error;
847

848
  module_sp = std::make_shared<Module>(module_spec);
849
  // Make sure there are a module and an object file since we can specify a
850
  // valid file path with an architecture that might not be in that file. By
851
  // getting the object file we can guarantee that the architecture matches
852
  if (module_sp->GetObjectFile()) {
853
    // If we get in here we got the correct arch, now we just need to verify
854
    // the UUID if one was given
855
    if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {
856
      module_sp.reset();
857
    } else {
858
      if (module_sp->GetObjectFile() &&
859
          module_sp->GetObjectFile()->GetType() ==
860
              ObjectFile::eTypeStubLibrary) {
861
        module_sp.reset();
862
      } else {
863
        if (did_create_ptr) {
864
          *did_create_ptr = true;
865
        }
866

867
        shared_module_list.ReplaceEquivalent(module_sp, old_modules);
868
        return error;
869
      }
870
    }
871
  } else {
872
    module_sp.reset();
873
  }
874

875
  if (module_search_paths_ptr) {
876
    const auto num_directories = module_search_paths_ptr->GetSize();
877
    for (size_t idx = 0; idx < num_directories; ++idx) {
878
      auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx);
879
      FileSystem::Instance().Resolve(search_path_spec);
880
      namespace fs = llvm::sys::fs;
881
      if (!FileSystem::Instance().IsDirectory(search_path_spec))
882
        continue;
883
      search_path_spec.AppendPathComponent(
884
          module_spec.GetFileSpec().GetFilename().GetStringRef());
885
      if (!FileSystem::Instance().Exists(search_path_spec))
886
        continue;
887

888
      auto resolved_module_spec(module_spec);
889
      resolved_module_spec.GetFileSpec() = search_path_spec;
890
      module_sp = std::make_shared<Module>(resolved_module_spec);
891
      if (module_sp->GetObjectFile()) {
892
        // If we get in here we got the correct arch, now we just need to
893
        // verify the UUID if one was given
894
        if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {
895
          module_sp.reset();
896
        } else {
897
          if (module_sp->GetObjectFile()->GetType() ==
898
              ObjectFile::eTypeStubLibrary) {
899
            module_sp.reset();
900
          } else {
901
            if (did_create_ptr)
902
              *did_create_ptr = true;
903

904
            shared_module_list.ReplaceEquivalent(module_sp, old_modules);
905
            return Status();
906
          }
907
        }
908
      } else {
909
        module_sp.reset();
910
      }
911
    }
912
  }
913

914
  // Either the file didn't exist where at the path, or no path was given, so
915
  // we now have to use more extreme measures to try and find the appropriate
916
  // module.
917

918
  // Fixup the incoming path in case the path points to a valid file, yet the
919
  // arch or UUID (if one was passed in) don't match.
920
  ModuleSpec located_binary_modulespec =
921
      PluginManager::LocateExecutableObjectFile(module_spec);
922

923
  // Don't look for the file if it appears to be the same one we already
924
  // checked for above...
925
  if (located_binary_modulespec.GetFileSpec() != module_file_spec) {
926
    if (!FileSystem::Instance().Exists(
927
            located_binary_modulespec.GetFileSpec())) {
928
      located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
929
      if (path[0] == '\0')
930
        module_file_spec.GetPath(path, sizeof(path));
931
      // How can this check ever be true? This branch it is false, and we
932
      // haven't modified file_spec.
933
      if (FileSystem::Instance().Exists(
934
              located_binary_modulespec.GetFileSpec())) {
935
        std::string uuid_str;
936
        if (uuid_ptr && uuid_ptr->IsValid())
937
          uuid_str = uuid_ptr->GetAsString();
938

939
        if (arch.IsValid()) {
940
          if (!uuid_str.empty())
941
            error.SetErrorStringWithFormat(
942
                "'%s' does not contain the %s architecture and UUID %s", path,
943
                arch.GetArchitectureName(), uuid_str.c_str());
944
          else
945
            error.SetErrorStringWithFormat(
946
                "'%s' does not contain the %s architecture.", path,
947
                arch.GetArchitectureName());
948
        }
949
      } else {
950
        error.SetErrorStringWithFormat("'%s' does not exist", path);
951
      }
952
      if (error.Fail())
953
        module_sp.reset();
954
      return error;
955
    }
956

957
    // Make sure no one else can try and get or create a module while this
958
    // function is actively working on it by doing an extra lock on the global
959
    // mutex list.
960
    ModuleSpec platform_module_spec(module_spec);
961
    platform_module_spec.GetFileSpec() =
962
        located_binary_modulespec.GetFileSpec();
963
    platform_module_spec.GetPlatformFileSpec() =
964
        located_binary_modulespec.GetFileSpec();
965
    platform_module_spec.GetSymbolFileSpec() =
966
        located_binary_modulespec.GetSymbolFileSpec();
967
    ModuleList matching_module_list;
968
    shared_module_list.FindModules(platform_module_spec, matching_module_list);
969
    if (!matching_module_list.IsEmpty()) {
970
      module_sp = matching_module_list.GetModuleAtIndex(0);
971

972
      // If we didn't have a UUID in mind when looking for the object file,
973
      // then we should make sure the modification time hasn't changed!
974
      if (platform_module_spec.GetUUIDPtr() == nullptr) {
975
        auto file_spec_mod_time = FileSystem::Instance().GetModificationTime(
976
            located_binary_modulespec.GetFileSpec());
977
        if (file_spec_mod_time != llvm::sys::TimePoint<>()) {
978
          if (file_spec_mod_time != module_sp->GetModificationTime()) {
979
            if (old_modules)
980
              old_modules->push_back(module_sp);
981
            shared_module_list.Remove(module_sp);
982
            module_sp.reset();
983
          }
984
        }
985
      }
986
    }
987

988
    if (!module_sp) {
989
      module_sp = std::make_shared<Module>(platform_module_spec);
990
      // Make sure there are a module and an object file since we can specify a
991
      // valid file path with an architecture that might not be in that file.
992
      // By getting the object file we can guarantee that the architecture
993
      // matches
994
      if (module_sp && module_sp->GetObjectFile()) {
995
        if (module_sp->GetObjectFile()->GetType() ==
996
            ObjectFile::eTypeStubLibrary) {
997
          module_sp.reset();
998
        } else {
999
          if (did_create_ptr)
1000
            *did_create_ptr = true;
1001

1002
          shared_module_list.ReplaceEquivalent(module_sp, old_modules);
1003
        }
1004
      } else {
1005
        located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
1006

1007
        if (located_binary_modulespec.GetFileSpec()) {
1008
          if (arch.IsValid())
1009
            error.SetErrorStringWithFormat(
1010
                "unable to open %s architecture in '%s'",
1011
                arch.GetArchitectureName(), path);
1012
          else
1013
            error.SetErrorStringWithFormat("unable to open '%s'", path);
1014
        } else {
1015
          std::string uuid_str;
1016
          if (uuid_ptr && uuid_ptr->IsValid())
1017
            uuid_str = uuid_ptr->GetAsString();
1018

1019
          if (!uuid_str.empty())
1020
            error.SetErrorStringWithFormat(
1021
                "cannot locate a module for UUID '%s'", uuid_str.c_str());
1022
          else
1023
            error.SetErrorString("cannot locate a module");
1024
        }
1025
      }
1026
    }
1027
  }
1028

1029
  return error;
1030
}
1031

1032
bool ModuleList::RemoveSharedModule(lldb::ModuleSP &module_sp) {
1033
  return GetSharedModuleList().Remove(module_sp);
1034
}
1035

1036
bool ModuleList::RemoveSharedModuleIfOrphaned(const Module *module_ptr) {
1037
  return GetSharedModuleList().RemoveIfOrphaned(module_ptr);
1038
}
1039

1040
bool ModuleList::LoadScriptingResourcesInTarget(Target *target,
1041
                                                std::list<Status> &errors,
1042
                                                Stream &feedback_stream,
1043
                                                bool continue_on_error) {
1044
  if (!target)
1045
    return false;
1046
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1047
  for (auto module : m_modules) {
1048
    Status error;
1049
    if (module) {
1050
      if (!module->LoadScriptingResourceInTarget(target, error,
1051
                                                 feedback_stream)) {
1052
        if (error.Fail() && error.AsCString()) {
1053
          error.SetErrorStringWithFormat("unable to load scripting data for "
1054
                                         "module %s - error reported was %s",
1055
                                         module->GetFileSpec()
1056
                                             .GetFileNameStrippingExtension()
1057
                                             .GetCString(),
1058
                                         error.AsCString());
1059
          errors.push_back(error);
1060

1061
          if (!continue_on_error)
1062
            return false;
1063
        }
1064
      }
1065
    }
1066
  }
1067
  return errors.empty();
1068
}
1069

1070
void ModuleList::ForEach(
1071
    std::function<bool(const ModuleSP &module_sp)> const &callback) const {
1072
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1073
  for (const auto &module_sp : m_modules) {
1074
    assert(module_sp != nullptr);
1075
    // If the callback returns false, then stop iterating and break out
1076
    if (!callback(module_sp))
1077
      break;
1078
  }
1079
}
1080

1081
bool ModuleList::AnyOf(
1082
    std::function<bool(lldb_private::Module &module_sp)> const &callback)
1083
    const {
1084
  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1085
  for (const auto &module_sp : m_modules) {
1086
    assert(module_sp != nullptr);
1087
    if (callback(*module_sp))
1088
      return true;
1089
  }
1090

1091
  return false;
1092
}
1093

1094

1095
void ModuleList::Swap(ModuleList &other) {
1096
  // scoped_lock locks both mutexes at once.
1097
  std::scoped_lock<std::recursive_mutex, std::recursive_mutex> lock(
1098
      m_modules_mutex, other.m_modules_mutex);
1099
  m_modules.swap(other.m_modules);
1100
}
1101

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.