LLDB  mainline
ModuleList.cpp
Go to the documentation of this file.
1 //===-- ModuleList.cpp ------------------------------------------*- C++ -*-===//
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/FileSpecList.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/ModuleSpec.h"
13 #include "lldb/Host/FileSystem.h"
18 #include "lldb/Symbol/ObjectFile.h"
21 #include "lldb/Utility/ArchSpec.h"
23 #include "lldb/Utility/Log.h"
24 #include "lldb/Utility/Logging.h"
25 #include "lldb/Utility/UUID.h"
26 #include "lldb/lldb-defines.h"
27 
28 #if defined(_WIN32)
30 #endif
31 
32 #include "clang/Driver/Driver.h"
33 #include "llvm/ADT/StringRef.h"
34 #include "llvm/Support/FileSystem.h"
35 #include "llvm/Support/Threading.h"
36 #include "llvm/Support/raw_ostream.h"
37 
38 #include <chrono>
39 #include <memory>
40 #include <mutex>
41 #include <string>
42 #include <utility>
43 
44 namespace lldb_private {
45 class Function;
46 }
47 namespace lldb_private {
48 class RegularExpression;
49 }
50 namespace lldb_private {
51 class Stream;
52 }
53 namespace lldb_private {
54 class SymbolFile;
55 }
56 namespace lldb_private {
57 class Target;
58 }
59 namespace lldb_private {
60 class TypeList;
61 }
62 
63 using namespace lldb;
64 using namespace lldb_private;
65 
66 namespace {
67 
68 static constexpr PropertyDefinition g_properties[] = {
69  {"enable-external-lookup", OptionValue::eTypeBoolean, true, true, nullptr,
70  {},
71  "Control the use of external tools and repositories to locate symbol "
72  "files. Directories listed in target.debug-file-search-paths and "
73  "directory of the executable are always checked first for separate debug "
74  "info files. Then depending on this setting: "
75  "On macOS, Spotlight would be also used to locate a matching .dSYM "
76  "bundle based on the UUID of the executable. "
77  "On NetBSD, directory /usr/libdata/debug would be also searched. "
78  "On platforms other than NetBSD directory /usr/lib/debug would be "
79  "also searched."
80  },
81  {"clang-modules-cache-path", OptionValue::eTypeFileSpec, true, 0, nullptr,
82  {},
83  "The path to the clang modules cache directory (-fmodules-cache-path)."}};
84 
85 enum { ePropertyEnableExternalLookup, ePropertyClangModulesCachePath };
86 
87 } // namespace
88 
90  m_collection_sp =
91  std::make_shared<OptionValueProperties>(ConstString("symbols"));
92  m_collection_sp->Initialize(g_properties);
93 
94  llvm::SmallString<128> path;
95  clang::driver::Driver::getDefaultModuleCachePath(path);
96  SetClangModulesCachePath(path);
97 }
98 
100  const uint32_t idx = ePropertyEnableExternalLookup;
101  return m_collection_sp->GetPropertyAtIndexAsBoolean(
102  nullptr, idx, g_properties[idx].default_uint_value != 0);
103 }
104 
106  return m_collection_sp
107  ->GetPropertyAtIndexAsOptionValueFileSpec(nullptr, false,
108  ePropertyClangModulesCachePath)
109  ->GetCurrentValue();
110 }
111 
113  return m_collection_sp->SetPropertyAtIndexAsString(
114  nullptr, ePropertyClangModulesCachePath, path);
115 }
116 
117 
119  : m_modules(), m_modules_mutex(), m_notifier(nullptr) {}
120 
122  : m_modules(), m_modules_mutex(), m_notifier(nullptr) {
123  std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex);
124  std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex);
125  m_modules = rhs.m_modules;
126 }
127 
129  : m_modules(), m_modules_mutex(), m_notifier(notifier) {}
130 
132  if (this != &rhs) {
133  std::lock(m_modules_mutex, rhs.m_modules_mutex);
134  std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex,
135  std::adopt_lock);
136  std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex,
137  std::adopt_lock);
138  m_modules = rhs.m_modules;
139  }
140  return *this;
141 }
142 
143 ModuleList::~ModuleList() = default;
144 
145 void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) {
146  if (module_sp) {
147  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
148  m_modules.push_back(module_sp);
149  if (use_notifier && m_notifier)
150  m_notifier->NotifyModuleAdded(*this, module_sp);
151  }
152 }
153 
154 void ModuleList::Append(const ModuleSP &module_sp, bool notify) {
155  AppendImpl(module_sp, notify);
156 }
157 
158 void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) {
159  if (module_sp) {
160  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
161 
162  // First remove any equivalent modules. Equivalent modules are modules
163  // whose path, platform path and architecture match.
164  ModuleSpec equivalent_module_spec(module_sp->GetFileSpec(),
165  module_sp->GetArchitecture());
166  equivalent_module_spec.GetPlatformFileSpec() =
167  module_sp->GetPlatformFileSpec();
168 
169  size_t idx = 0;
170  while (idx < m_modules.size()) {
171  ModuleSP module_sp(m_modules[idx]);
172  if (module_sp->MatchesModuleSpec(equivalent_module_spec))
173  RemoveImpl(m_modules.begin() + idx);
174  else
175  ++idx;
176  }
177  // Now add the new module to the list
178  Append(module_sp);
179  }
180 }
181 
182 bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp, bool notify) {
183  if (module_sp) {
184  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
185  collection::iterator pos, end = m_modules.end();
186  for (pos = m_modules.begin(); pos != end; ++pos) {
187  if (pos->get() == module_sp.get())
188  return false; // Already in the list
189  }
190  // Only push module_sp on the list if it wasn't already in there.
191  Append(module_sp, notify);
192  return true;
193  }
194  return false;
195 }
196 
197 void ModuleList::Append(const ModuleList &module_list) {
198  for (auto pos : module_list.m_modules)
199  Append(pos);
200 }
201 
202 bool ModuleList::AppendIfNeeded(const ModuleList &module_list) {
203  bool any_in = false;
204  for (auto pos : module_list.m_modules) {
205  if (AppendIfNeeded(pos))
206  any_in = true;
207  }
208  return any_in;
209 }
210 
211 bool ModuleList::RemoveImpl(const ModuleSP &module_sp, bool use_notifier) {
212  if (module_sp) {
213  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
214  collection::iterator pos, end = m_modules.end();
215  for (pos = m_modules.begin(); pos != end; ++pos) {
216  if (pos->get() == module_sp.get()) {
217  m_modules.erase(pos);
218  if (use_notifier && m_notifier)
219  m_notifier->NotifyModuleRemoved(*this, module_sp);
220  return true;
221  }
222  }
223  }
224  return false;
225 }
226 
227 ModuleList::collection::iterator
228 ModuleList::RemoveImpl(ModuleList::collection::iterator pos,
229  bool use_notifier) {
230  ModuleSP module_sp(*pos);
231  collection::iterator retval = m_modules.erase(pos);
232  if (use_notifier && m_notifier)
233  m_notifier->NotifyModuleRemoved(*this, module_sp);
234  return retval;
235 }
236 
237 bool ModuleList::Remove(const ModuleSP &module_sp, bool notify) {
238  return RemoveImpl(module_sp, notify);
239 }
240 
241 bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp,
242  const lldb::ModuleSP &new_module_sp) {
243  if (!RemoveImpl(old_module_sp, false))
244  return false;
245  AppendImpl(new_module_sp, false);
246  if (m_notifier)
247  m_notifier->NotifyModuleUpdated(*this, old_module_sp, new_module_sp);
248  return true;
249 }
250 
251 bool ModuleList::RemoveIfOrphaned(const Module *module_ptr) {
252  if (module_ptr) {
253  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
254  collection::iterator pos, end = m_modules.end();
255  for (pos = m_modules.begin(); pos != end; ++pos) {
256  if (pos->get() == module_ptr) {
257  if (pos->unique()) {
258  pos = RemoveImpl(pos);
259  return true;
260  } else
261  return false;
262  }
263  }
264  }
265  return false;
266 }
267 
268 size_t ModuleList::RemoveOrphans(bool mandatory) {
269  std::unique_lock<std::recursive_mutex> lock(m_modules_mutex, std::defer_lock);
270 
271  if (mandatory) {
272  lock.lock();
273  } else {
274  // Not mandatory, remove orphans if we can get the mutex
275  if (!lock.try_lock())
276  return 0;
277  }
278  collection::iterator pos = m_modules.begin();
279  size_t remove_count = 0;
280  while (pos != m_modules.end()) {
281  if (pos->unique()) {
282  pos = RemoveImpl(pos);
283  ++remove_count;
284  } else {
285  ++pos;
286  }
287  }
288  return remove_count;
289 }
290 
291 size_t ModuleList::Remove(ModuleList &module_list) {
292  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
293  size_t num_removed = 0;
294  collection::iterator pos, end = module_list.m_modules.end();
295  for (pos = module_list.m_modules.begin(); pos != end; ++pos) {
296  if (Remove(*pos, false /* notify */))
297  ++num_removed;
298  }
299  if (m_notifier)
300  m_notifier->NotifyModulesRemoved(module_list);
301  return num_removed;
302 }
303 
305 
307 
308 void ModuleList::ClearImpl(bool use_notifier) {
309  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
310  if (use_notifier && m_notifier)
312  m_modules.clear();
313 }
314 
316  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
318 }
319 
321  if (idx < m_modules.size())
322  return m_modules[idx].get();
323  return nullptr;
324 }
325 
326 ModuleSP ModuleList::GetModuleAtIndex(size_t idx) const {
327  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
328  return GetModuleAtIndexUnlocked(idx);
329 }
330 
331 ModuleSP ModuleList::GetModuleAtIndexUnlocked(size_t idx) const {
332  ModuleSP module_sp;
333  if (idx < m_modules.size())
334  module_sp = m_modules[idx];
335  return module_sp;
336 }
337 
339  FunctionNameType name_type_mask,
340  bool include_symbols, bool include_inlines,
341  bool append,
342  SymbolContextList &sc_list) const {
343  if (!append)
344  sc_list.Clear();
345 
346  const size_t old_size = sc_list.GetSize();
347 
348  if (name_type_mask & eFunctionNameTypeAuto) {
349  Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);
350 
351  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
352  collection::const_iterator pos, end = m_modules.end();
353  for (pos = m_modules.begin(); pos != end; ++pos) {
354  (*pos)->FindFunctions(lookup_info.GetLookupName(), nullptr,
355  lookup_info.GetNameTypeMask(), include_symbols,
356  include_inlines, true, sc_list);
357  }
358 
359  const size_t new_size = sc_list.GetSize();
360 
361  if (old_size < new_size)
362  lookup_info.Prune(sc_list, old_size);
363  } else {
364  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
365  collection::const_iterator pos, end = m_modules.end();
366  for (pos = m_modules.begin(); pos != end; ++pos) {
367  (*pos)->FindFunctions(name, nullptr, name_type_mask, include_symbols,
368  include_inlines, true, sc_list);
369  }
370  }
371  return sc_list.GetSize() - old_size;
372 }
373 
375  lldb::FunctionNameType name_type_mask,
376  SymbolContextList &sc_list) {
377  const size_t old_size = sc_list.GetSize();
378 
379  if (name_type_mask & eFunctionNameTypeAuto) {
380  Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);
381 
382  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
383  collection::const_iterator pos, end = m_modules.end();
384  for (pos = m_modules.begin(); pos != end; ++pos) {
385  (*pos)->FindFunctionSymbols(lookup_info.GetLookupName(),
386  lookup_info.GetNameTypeMask(), sc_list);
387  }
388 
389  const size_t new_size = sc_list.GetSize();
390 
391  if (old_size < new_size)
392  lookup_info.Prune(sc_list, old_size);
393  } else {
394  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
395  collection::const_iterator pos, end = m_modules.end();
396  for (pos = m_modules.begin(); pos != end; ++pos) {
397  (*pos)->FindFunctionSymbols(name, name_type_mask, sc_list);
398  }
399  }
400 
401  return sc_list.GetSize() - old_size;
402 }
403 
405  bool include_symbols, bool include_inlines,
406  bool append, SymbolContextList &sc_list) {
407  const size_t old_size = sc_list.GetSize();
408 
409  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
410  collection::const_iterator pos, end = m_modules.end();
411  for (pos = m_modules.begin(); pos != end; ++pos) {
412  (*pos)->FindFunctions(name, include_symbols, include_inlines, append,
413  sc_list);
414  }
415 
416  return sc_list.GetSize() - old_size;
417 }
418 
419 size_t ModuleList::FindCompileUnits(const FileSpec &path, bool append,
420  SymbolContextList &sc_list) const {
421  if (!append)
422  sc_list.Clear();
423 
424  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
425  collection::const_iterator pos, end = m_modules.end();
426  for (pos = m_modules.begin(); pos != end; ++pos) {
427  (*pos)->FindCompileUnits(path, true, sc_list);
428  }
429 
430  return sc_list.GetSize();
431 }
432 
434  size_t max_matches,
435  VariableList &variable_list) const {
436  size_t initial_size = variable_list.GetSize();
437  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
438  collection::const_iterator pos, end = m_modules.end();
439  for (pos = m_modules.begin(); pos != end; ++pos) {
440  (*pos)->FindGlobalVariables(name, nullptr, max_matches, variable_list);
441  }
442  return variable_list.GetSize() - initial_size;
443 }
444 
446  size_t max_matches,
447  VariableList &variable_list) const {
448  size_t initial_size = variable_list.GetSize();
449  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
450  collection::const_iterator pos, end = m_modules.end();
451  for (pos = m_modules.begin(); pos != end; ++pos) {
452  (*pos)->FindGlobalVariables(regex, max_matches, variable_list);
453  }
454  return variable_list.GetSize() - initial_size;
455 }
456 
458  SymbolType symbol_type,
459  SymbolContextList &sc_list,
460  bool append) const {
461  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
462  if (!append)
463  sc_list.Clear();
464  size_t initial_size = sc_list.GetSize();
465 
466  collection::const_iterator pos, end = m_modules.end();
467  for (pos = m_modules.begin(); pos != end; ++pos)
468  (*pos)->FindSymbolsWithNameAndType(name, symbol_type, sc_list);
469  return sc_list.GetSize() - initial_size;
470 }
471 
473  const RegularExpression &regex, lldb::SymbolType symbol_type,
474  SymbolContextList &sc_list, bool append) const {
475  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
476  if (!append)
477  sc_list.Clear();
478  size_t initial_size = sc_list.GetSize();
479 
480  collection::const_iterator pos, end = m_modules.end();
481  for (pos = m_modules.begin(); pos != end; ++pos)
482  (*pos)->FindSymbolsMatchingRegExAndType(regex, symbol_type, sc_list);
483  return sc_list.GetSize() - initial_size;
484 }
485 
486 size_t ModuleList::FindModules(const ModuleSpec &module_spec,
487  ModuleList &matching_module_list) const {
488  size_t existing_matches = matching_module_list.GetSize();
489 
490  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
491  collection::const_iterator pos, end = m_modules.end();
492  for (pos = m_modules.begin(); pos != end; ++pos) {
493  ModuleSP module_sp(*pos);
494  if (module_sp->MatchesModuleSpec(module_spec))
495  matching_module_list.Append(module_sp);
496  }
497  return matching_module_list.GetSize() - existing_matches;
498 }
499 
500 ModuleSP ModuleList::FindModule(const Module *module_ptr) const {
501  ModuleSP module_sp;
502 
503  // Scope for "locker"
504  {
505  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
506  collection::const_iterator pos, end = m_modules.end();
507 
508  for (pos = m_modules.begin(); pos != end; ++pos) {
509  if ((*pos).get() == module_ptr) {
510  module_sp = (*pos);
511  break;
512  }
513  }
514  }
515  return module_sp;
516 }
517 
518 ModuleSP ModuleList::FindModule(const UUID &uuid) const {
519  ModuleSP module_sp;
520 
521  if (uuid.IsValid()) {
522  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
523  collection::const_iterator pos, end = m_modules.end();
524 
525  for (pos = m_modules.begin(); pos != end; ++pos) {
526  if ((*pos)->GetUUID() == uuid) {
527  module_sp = (*pos);
528  break;
529  }
530  }
531  }
532  return module_sp;
533 }
534 
535 size_t
537  bool name_is_fully_qualified, size_t max_matches,
538  llvm::DenseSet<SymbolFile *> &searched_symbol_files,
539  TypeList &types) const {
540  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
541 
542  size_t total_matches = 0;
543  collection::const_iterator pos, end = m_modules.end();
544  if (search_first) {
545  for (pos = m_modules.begin(); pos != end; ++pos) {
546  if (search_first == pos->get()) {
547  total_matches +=
548  search_first->FindTypes(name, name_is_fully_qualified, max_matches,
549  searched_symbol_files, types);
550 
551  if (total_matches >= max_matches)
552  break;
553  }
554  }
555  }
556 
557  if (total_matches < max_matches) {
558  for (pos = m_modules.begin(); pos != end; ++pos) {
559  // Search the module if the module is not equal to the one in the symbol
560  // context "sc". If "sc" contains a empty module shared pointer, then the
561  // comparison will always be true (valid_module_ptr != nullptr).
562  if (search_first != pos->get())
563  total_matches +=
564  (*pos)->FindTypes(name, name_is_fully_qualified, max_matches,
565  searched_symbol_files, types);
566 
567  if (total_matches >= max_matches)
568  break;
569  }
570  }
571 
572  return total_matches;
573 }
574 
575 bool ModuleList::FindSourceFile(const FileSpec &orig_spec,
576  FileSpec &new_spec) const {
577  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
578  collection::const_iterator pos, end = m_modules.end();
579  for (pos = m_modules.begin(); pos != end; ++pos) {
580  if ((*pos)->FindSourceFile(orig_spec, new_spec))
581  return true;
582  }
583  return false;
584 }
585 
586 void ModuleList::FindAddressesForLine(const lldb::TargetSP target_sp,
587  const FileSpec &file, uint32_t line,
588  Function *function,
589  std::vector<Address> &output_local,
590  std::vector<Address> &output_extern) {
591  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
592  collection::const_iterator pos, end = m_modules.end();
593  for (pos = m_modules.begin(); pos != end; ++pos) {
594  (*pos)->FindAddressesForLine(target_sp, file, line, function, output_local,
595  output_extern);
596  }
597 }
598 
599 ModuleSP ModuleList::FindFirstModule(const ModuleSpec &module_spec) const {
600  ModuleSP module_sp;
601  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
602  collection::const_iterator pos, end = m_modules.end();
603  for (pos = m_modules.begin(); pos != end; ++pos) {
604  ModuleSP module_sp(*pos);
605  if (module_sp->MatchesModuleSpec(module_spec))
606  return module_sp;
607  }
608  return module_sp;
609 }
610 
611 size_t ModuleList::GetSize() const {
612  size_t size = 0;
613  {
614  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
615  size = m_modules.size();
616  }
617  return size;
618 }
619 
620 void ModuleList::Dump(Stream *s) const {
621  // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this);
622  // s.Indent();
623  // s << "ModuleList\n";
624 
625  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
626  collection::const_iterator pos, end = m_modules.end();
627  for (pos = m_modules.begin(); pos != end; ++pos) {
628  (*pos)->Dump(s);
629  }
630 }
631 
632 void ModuleList::LogUUIDAndPaths(Log *log, const char *prefix_cstr) {
633  if (log != nullptr) {
634  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
635  collection::const_iterator pos, begin = m_modules.begin(),
636  end = m_modules.end();
637  for (pos = begin; pos != end; ++pos) {
638  Module *module = pos->get();
639  const FileSpec &module_file_spec = module->GetFileSpec();
640  log->Printf("%s[%u] %s (%s) \"%s\"", prefix_cstr ? prefix_cstr : "",
641  (uint32_t)std::distance(begin, pos),
642  module->GetUUID().GetAsString().c_str(),
644  module_file_spec.GetPath().c_str());
645  }
646  }
647 }
648 
650  Address &so_addr) const {
651  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
652  collection::const_iterator pos, end = m_modules.end();
653  for (pos = m_modules.begin(); pos != end; ++pos) {
654  if ((*pos)->ResolveFileAddress(vm_addr, so_addr))
655  return true;
656  }
657 
658  return false;
659 }
660 
661 uint32_t
663  SymbolContextItem resolve_scope,
664  SymbolContext &sc) const {
665  // The address is already section offset so it has a module
666  uint32_t resolved_flags = 0;
667  ModuleSP module_sp(so_addr.GetModule());
668  if (module_sp) {
669  resolved_flags =
670  module_sp->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc);
671  } else {
672  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
673  collection::const_iterator pos, end = m_modules.end();
674  for (pos = m_modules.begin(); pos != end; ++pos) {
675  resolved_flags =
676  (*pos)->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc);
677  if (resolved_flags != 0)
678  break;
679  }
680  }
681 
682  return resolved_flags;
683 }
684 
686  const char *file_path, uint32_t line, bool check_inlines,
687  SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {
688  FileSpec file_spec(file_path);
689  return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
690  resolve_scope, sc_list);
691 }
692 
694  const FileSpec &file_spec, uint32_t line, bool check_inlines,
695  SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {
696  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
697  collection::const_iterator pos, end = m_modules.end();
698  for (pos = m_modules.begin(); pos != end; ++pos) {
699  (*pos)->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
700  resolve_scope, sc_list);
701  }
702 
703  return sc_list.GetSize();
704 }
705 
706 size_t ModuleList::GetIndexForModule(const Module *module) const {
707  if (module) {
708  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
709  collection::const_iterator pos;
710  collection::const_iterator begin = m_modules.begin();
711  collection::const_iterator end = m_modules.end();
712  for (pos = begin; pos != end; ++pos) {
713  if ((*pos).get() == module)
714  return std::distance(begin, pos);
715  }
716  }
717  return LLDB_INVALID_INDEX32;
718 }
719 
720 namespace {
721 struct SharedModuleListInfo {
722  ModuleList module_list;
723  ModuleListProperties module_list_properties;
724 };
725 }
726 static SharedModuleListInfo &GetSharedModuleListInfo()
727 {
728  static SharedModuleListInfo *g_shared_module_list_info = nullptr;
729  static llvm::once_flag g_once_flag;
730  llvm::call_once(g_once_flag, []() {
731  // NOTE: Intentionally leak the module list so a program doesn't have to
732  // cleanup all modules and object files as it exits. This just wastes time
733  // doing a bunch of cleanup that isn't required.
734  if (g_shared_module_list_info == nullptr)
735  g_shared_module_list_info = new SharedModuleListInfo();
736  });
737  return *g_shared_module_list_info;
738 }
739 
741  return GetSharedModuleListInfo().module_list;
742 }
743 
745  return GetSharedModuleListInfo().module_list_properties;
746 }
747 
748 bool ModuleList::ModuleIsInCache(const Module *module_ptr) {
749  if (module_ptr) {
750  ModuleList &shared_module_list = GetSharedModuleList();
751  return shared_module_list.FindModule(module_ptr).get() != nullptr;
752  }
753  return false;
754 }
755 
756 size_t ModuleList::FindSharedModules(const ModuleSpec &module_spec,
757  ModuleList &matching_module_list) {
758  return GetSharedModuleList().FindModules(module_spec, matching_module_list);
759 }
760 
762  return GetSharedModuleList().RemoveOrphans(mandatory);
763 }
764 
766  ModuleSP &module_sp,
767  const FileSpecList *module_search_paths_ptr,
768  ModuleSP *old_module_sp_ptr,
769  bool *did_create_ptr, bool always_create) {
770  ModuleList &shared_module_list = GetSharedModuleList();
771  std::lock_guard<std::recursive_mutex> guard(
772  shared_module_list.m_modules_mutex);
773  char path[PATH_MAX];
774 
775  Status error;
776 
777  module_sp.reset();
778 
779  if (did_create_ptr)
780  *did_create_ptr = false;
781  if (old_module_sp_ptr)
782  old_module_sp_ptr->reset();
783 
784  const UUID *uuid_ptr = module_spec.GetUUIDPtr();
785  const FileSpec &module_file_spec = module_spec.GetFileSpec();
786  const ArchSpec &arch = module_spec.GetArchitecture();
787 
788  // Make sure no one else can try and get or create a module while this
789  // function is actively working on it by doing an extra lock on the global
790  // mutex list.
791  if (!always_create) {
792  ModuleList matching_module_list;
793  const size_t num_matching_modules =
794  shared_module_list.FindModules(module_spec, matching_module_list);
795  if (num_matching_modules > 0) {
796  for (size_t module_idx = 0; module_idx < num_matching_modules;
797  ++module_idx) {
798  module_sp = matching_module_list.GetModuleAtIndex(module_idx);
799 
800  // Make sure the file for the module hasn't been modified
801  if (module_sp->FileHasChanged()) {
802  if (old_module_sp_ptr && !*old_module_sp_ptr)
803  *old_module_sp_ptr = module_sp;
804 
806  if (log != nullptr)
807  log->Printf("module changed: %p, removing from global module list",
808  static_cast<void *>(module_sp.get()));
809 
810  shared_module_list.Remove(module_sp);
811  module_sp.reset();
812  } else {
813  // The module matches and the module was not modified from when it
814  // was last loaded.
815  return error;
816  }
817  }
818  }
819  }
820 
821  if (module_sp)
822  return error;
823 
824  module_sp = std::make_shared<Module>(module_spec);
825  // Make sure there are a module and an object file since we can specify a
826  // valid file path with an architecture that might not be in that file. By
827  // getting the object file we can guarantee that the architecture matches
828  if (module_sp->GetObjectFile()) {
829  // If we get in here we got the correct arch, now we just need to verify
830  // the UUID if one was given
831  if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {
832  module_sp.reset();
833  } else {
834  if (module_sp->GetObjectFile() &&
835  module_sp->GetObjectFile()->GetType() ==
837  module_sp.reset();
838  } else {
839  if (did_create_ptr) {
840  *did_create_ptr = true;
841  }
842 
843  shared_module_list.ReplaceEquivalent(module_sp);
844  return error;
845  }
846  }
847  } else {
848  module_sp.reset();
849  }
850 
851  if (module_search_paths_ptr) {
852  const auto num_directories = module_search_paths_ptr->GetSize();
853  for (size_t idx = 0; idx < num_directories; ++idx) {
854  auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx);
855  FileSystem::Instance().Resolve(search_path_spec);
856  namespace fs = llvm::sys::fs;
857  if (!FileSystem::Instance().IsDirectory(search_path_spec))
858  continue;
859  search_path_spec.AppendPathComponent(
860  module_spec.GetFileSpec().GetFilename().AsCString());
861  if (!FileSystem::Instance().Exists(search_path_spec))
862  continue;
863 
864  auto resolved_module_spec(module_spec);
865  resolved_module_spec.GetFileSpec() = search_path_spec;
866  module_sp = std::make_shared<Module>(resolved_module_spec);
867  if (module_sp->GetObjectFile()) {
868  // If we get in here we got the correct arch, now we just need to
869  // verify the UUID if one was given
870  if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) {
871  module_sp.reset();
872  } else {
873  if (module_sp->GetObjectFile()->GetType() ==
875  module_sp.reset();
876  } else {
877  if (did_create_ptr)
878  *did_create_ptr = true;
879 
880  shared_module_list.ReplaceEquivalent(module_sp);
881  return Status();
882  }
883  }
884  } else {
885  module_sp.reset();
886  }
887  }
888  }
889 
890  // Either the file didn't exist where at the path, or no path was given, so
891  // we now have to use more extreme measures to try and find the appropriate
892  // module.
893 
894  // Fixup the incoming path in case the path points to a valid file, yet the
895  // arch or UUID (if one was passed in) don't match.
896  ModuleSpec located_binary_modulespec =
898 
899  // Don't look for the file if it appears to be the same one we already
900  // checked for above...
901  if (located_binary_modulespec.GetFileSpec() != module_file_spec) {
903  located_binary_modulespec.GetFileSpec())) {
904  located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
905  if (path[0] == '\0')
906  module_file_spec.GetPath(path, sizeof(path));
907  // How can this check ever be true? This branch it is false, and we
908  // haven't modified file_spec.
909  if (FileSystem::Instance().Exists(
910  located_binary_modulespec.GetFileSpec())) {
911  std::string uuid_str;
912  if (uuid_ptr && uuid_ptr->IsValid())
913  uuid_str = uuid_ptr->GetAsString();
914 
915  if (arch.IsValid()) {
916  if (!uuid_str.empty())
918  "'%s' does not contain the %s architecture and UUID %s", path,
919  arch.GetArchitectureName(), uuid_str.c_str());
920  else
922  "'%s' does not contain the %s architecture.", path,
923  arch.GetArchitectureName());
924  }
925  } else {
926  error.SetErrorStringWithFormat("'%s' does not exist", path);
927  }
928  if (error.Fail())
929  module_sp.reset();
930  return error;
931  }
932 
933  // Make sure no one else can try and get or create a module while this
934  // function is actively working on it by doing an extra lock on the global
935  // mutex list.
936  ModuleSpec platform_module_spec(module_spec);
937  platform_module_spec.GetFileSpec() =
938  located_binary_modulespec.GetFileSpec();
939  platform_module_spec.GetPlatformFileSpec() =
940  located_binary_modulespec.GetFileSpec();
941  platform_module_spec.GetSymbolFileSpec() =
942  located_binary_modulespec.GetSymbolFileSpec();
943  ModuleList matching_module_list;
944  if (shared_module_list.FindModules(platform_module_spec,
945  matching_module_list) > 0) {
946  module_sp = matching_module_list.GetModuleAtIndex(0);
947 
948  // If we didn't have a UUID in mind when looking for the object file,
949  // then we should make sure the modification time hasn't changed!
950  if (platform_module_spec.GetUUIDPtr() == nullptr) {
951  auto file_spec_mod_time = FileSystem::Instance().GetModificationTime(
952  located_binary_modulespec.GetFileSpec());
953  if (file_spec_mod_time != llvm::sys::TimePoint<>()) {
954  if (file_spec_mod_time != module_sp->GetModificationTime()) {
955  if (old_module_sp_ptr)
956  *old_module_sp_ptr = module_sp;
957  shared_module_list.Remove(module_sp);
958  module_sp.reset();
959  }
960  }
961  }
962  }
963 
964  if (!module_sp) {
965  module_sp = std::make_shared<Module>(platform_module_spec);
966  // Make sure there are a module and an object file since we can specify a
967  // valid file path with an architecture that might not be in that file.
968  // By getting the object file we can guarantee that the architecture
969  // matches
970  if (module_sp && module_sp->GetObjectFile()) {
971  if (module_sp->GetObjectFile()->GetType() ==
973  module_sp.reset();
974  } else {
975  if (did_create_ptr)
976  *did_create_ptr = true;
977 
978  shared_module_list.ReplaceEquivalent(module_sp);
979  }
980  } else {
981  located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
982 
983  if (located_binary_modulespec.GetFileSpec()) {
984  if (arch.IsValid())
986  "unable to open %s architecture in '%s'",
987  arch.GetArchitectureName(), path);
988  else
989  error.SetErrorStringWithFormat("unable to open '%s'", path);
990  } else {
991  std::string uuid_str;
992  if (uuid_ptr && uuid_ptr->IsValid())
993  uuid_str = uuid_ptr->GetAsString();
994 
995  if (!uuid_str.empty())
997  "cannot locate a module for UUID '%s'", uuid_str.c_str());
998  else
999  error.SetErrorStringWithFormat("cannot locate a module");
1000  }
1001  }
1002  }
1003  }
1004 
1005  return error;
1006 }
1007 
1008 bool ModuleList::RemoveSharedModule(lldb::ModuleSP &module_sp) {
1009  return GetSharedModuleList().Remove(module_sp);
1010 }
1011 
1013  return GetSharedModuleList().RemoveIfOrphaned(module_ptr);
1014 }
1015 
1017  std::list<Status> &errors,
1018  Stream *feedback_stream,
1019  bool continue_on_error) {
1020  if (!target)
1021  return false;
1022  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1023  for (auto module : m_modules) {
1024  Status error;
1025  if (module) {
1026  if (!module->LoadScriptingResourceInTarget(target, error,
1027  feedback_stream)) {
1028  if (error.Fail() && error.AsCString()) {
1029  error.SetErrorStringWithFormat("unable to load scripting data for "
1030  "module %s - error reported was %s",
1031  module->GetFileSpec()
1032  .GetFileNameStrippingExtension()
1033  .GetCString(),
1034  error.AsCString());
1035  errors.push_back(error);
1036 
1037  if (!continue_on_error)
1038  return false;
1039  }
1040  }
1041  }
1042  }
1043  return errors.empty();
1044 }
1045 
1047  std::function<bool(const ModuleSP &module_sp)> const &callback) const {
1048  std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1049  for (const auto &module : m_modules) {
1050  // If the callback returns false, then stop iterating and break out
1051  if (!callback(module))
1052  break;
1053  }
1054 }
static ModuleList & GetSharedModuleList()
Definition: ModuleList.cpp:740
static Status GetSharedModule(const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr, bool always_create=false)
Definition: ModuleList.cpp:765
ConstString & GetFilename()
Filename string get accessor.
Definition: FileSpec.cpp:369
size_t RemoveOrphans(bool mandatory)
Definition: ModuleList.cpp:268
Defines a list of symbol context objects.
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:224
void Clear()
Clear the object&#39;s state.
Definition: ModuleList.cpp:304
bool IsValid() const
Definition: UUID.h:65
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition: Module.h:531
virtual void NotifyModuleUpdated(const ModuleList &module_list, const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp)=0
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
bool ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) const
Definition: ModuleList.cpp:649
A shared library that can be used during execution.
Definition: ObjectFile.h:73
A file utility class.
Definition: FileSpec.h:55
"lldb/Utility/RegularExpression.h" A C++ wrapper class for regex.
An architecture specification class.
Definition: ArchSpec.h:32
A class that describes a function.
Definition: Function.h:323
#define LIBLLDB_LOG_MODULES
Definition: Logging.h:35
static constexpr PropertyDefinition g_properties[]
Definition: Debugger.cpp:198
void ForEach(std::function< bool(const lldb::ModuleSP &module_sp)> const &callback) const
size_t GetIndexForModule(const Module *module) const
Definition: ModuleList.cpp:706
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:329
static FileSystem & Instance()
static bool ModuleIsInCache(const Module *module_ptr)
Definition: ModuleList.cpp:748
bool RemoveImpl(const lldb::ModuleSP &module_sp, bool use_notifier=true)
static SharedModuleListInfo & GetSharedModuleListInfo()
Definition: ModuleList.cpp:726
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
Definition: Module.cpp:1074
uint32_t GetSize() const
Get accessor for a symbol context list size.
bool FindSourceFile(const FileSpec &orig_spec, FileSpec &new_spec) const
Definition: ModuleList.cpp:575
void Destroy()
Clear the object&#39;s state.
Definition: ModuleList.cpp:306
bool Remove(const lldb::ModuleSP &module_sp, bool notify=true)
Remove a module from the module list.
lldb::ModuleSP GetModuleAtIndexUnlocked(size_t idx) const
Get the module shared pointer for the module at index idx without acquiring the ModuleList mutex...
Definition: ModuleList.cpp:331
collection m_modules
The collection of modules.
Definition: ModuleList.h:550
std::string GetAsString(llvm::StringRef separator="-") const
Definition: UUID.cpp:38
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:591
void Dump(Stream *s) const
Dump the description of each module contained in this list.
Definition: ModuleList.cpp:620
#define LLDB_INVALID_INDEX32
Definition: lldb-defines.h:86
lldb::ModuleSP GetModuleAtIndex(size_t idx) const
Get the module shared pointer for the module at index idx.
Definition: ModuleList.cpp:326
Module * GetModulePointerAtIndexUnlocked(size_t idx) const
Get the module pointer for the module at index idx without acquiring the ModuleList mutex...
Definition: ModuleList.cpp:320
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
static ModuleListProperties & GetGlobalModuleListProperties()
Definition: ModuleList.cpp:744
void ReplaceEquivalent(const lldb::ModuleSP &module_sp)
Append a module to the module list and remove any equivalent modules.
Definition: ModuleList.cpp:158
A collection class for Module objects.
Definition: ModuleList.h:91
virtual void NotifyWillClearList(const ModuleList &module_list)=0
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:109
A class that encapsulates name lookup information.
Definition: Module.h:955
lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const
Definition: ModuleList.cpp:599
size_t FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list, bool append=false) const
Definition: ModuleList.cpp:457
bool RemoveIfOrphaned(const Module *module_ptr)
Definition: ModuleList.cpp:251
ModuleList()
Default constructor.
Definition: ModuleList.cpp:118
size_t FindCompileUnits(const FileSpec &path, bool append, SymbolContextList &sc_list) const
Find compile units by partial or full path.
Definition: ModuleList.cpp:419
void Clear()
Clear the object&#39;s state.
uint32_t ResolveSymbolContextForFilePath(const char *file_path, uint32_t line, bool check_inlines, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const
Resolve items in the symbol context for a given file and line. (const char
Definition: ModuleList.cpp:685
size_t FindSymbolsMatchingRegExAndType(const RegularExpression &regex, lldb::SymbolType symbol_type, SymbolContextList &sc_list, bool append=false) const
Definition: ModuleList.cpp:472
bool SetClangModulesCachePath(llvm::StringRef path)
Definition: ModuleList.cpp:112
size_t FindFunctionSymbols(ConstString name, lldb::FunctionNameType name_type_mask, SymbolContextList &sc_list)
Definition: ModuleList.cpp:374
void Prune(SymbolContextList &sc_list, size_t start_idx) const
Definition: Module.cpp:741
A section + offset based address class.
Definition: Address.h:80
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
FileSpec & GetFileSpec()
Definition: ModuleSpec.h:75
std::recursive_mutex m_modules_mutex
Definition: ModuleList.h:551
uint32_t ResolveSymbolContextForAddress(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) const
Resolve the symbol context for the given address. (const Address
Definition: ModuleList.cpp:662
void FindAddressesForLine(const lldb::TargetSP target_sp, const FileSpec &file, uint32_t line, Function *function, std::vector< Address > &output_local, std::vector< Address > &output_extern)
Find addresses by file/line.
Definition: ModuleList.cpp:586
ConstString GetLookupName() const
Definition: Module.h:969
void ClearImpl(bool use_notifier=true)
Definition: ModuleList.cpp:308
ArchSpec & GetArchitecture()
Definition: ModuleSpec.h:111
virtual void NotifyModuleRemoved(const ModuleList &module_list, const lldb::ModuleSP &module_sp)=0
size_t FindTypes(ConstString type_name, bool exact_match, size_t max_matches, llvm::DenseSet< lldb_private::SymbolFile *> &searched_symbol_files, TypeList &types)
Find types by name.
Definition: Module.cpp:990
static size_t FindSharedModules(const ModuleSpec &module_spec, ModuleList &matching_module_list)
Definition: ModuleList.cpp:756
size_t FindGlobalVariables(ConstString name, size_t max_matches, VariableList &variable_list) const
Find global and static variables by name.
Definition: ModuleList.cpp:433
uint64_t addr_t
Definition: lldb-types.h:83
size_t GetSize() const
Gets the size of the module list.
Definition: ModuleList.cpp:611
void LogUUIDAndPaths(Log *log, const char *prefix_cstr)
Definition: ModuleList.cpp:632
A uniqued constant string class.
Definition: ConstString.h:38
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition: Address.cpp:264
Unknown or invalid language value.
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
static size_t RemoveOrphanSharedModules(bool mandatory)
Definition: ModuleList.cpp:761
FileSpec & GetSymbolFileSpec()
Definition: ModuleSpec.h:99
virtual void NotifyModulesRemoved(lldb_private::ModuleList &module_list)=0
Log * GetLogIfAnyCategoriesSet(uint32_t mask)
Definition: Logging.cpp:61
bool ReplaceModule(const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp)
Definition: ModuleList.cpp:241
Definition: SBAddress.h:15
bool Exists(const FileSpec &file_spec) const
Returns whether the given file exists.
bool LoadScriptingResourcesInTarget(Target *target, std::list< Status > &errors, Stream *feedback_stream=nullptr, bool continue_on_error=true)
lldb::ModuleSP FindModule(const Module *module_ptr) const
Definition: ModuleList.cpp:500
~ModuleList()
Destructor.
#define PATH_MAX
FileSpec GetClangModulesCachePath() const
Definition: ModuleList.cpp:105
Module * GetModulePointerAtIndex(size_t idx) const
Get the module pointer for the module at index idx.
Definition: ModuleList.cpp:315
virtual void NotifyModuleAdded(const ModuleList &module_list, const lldb::ModuleSP &module_sp)=0
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
size_t FindFunctions(ConstString name, lldb::FunctionNameType name_type_mask, bool include_symbols, bool include_inlines, bool append, SymbolContextList &sc_list) const
FileSpec & GetPlatformFileSpec()
Definition: ModuleSpec.h:87
size_t FindModules(const ModuleSpec &module_spec, ModuleList &matching_module_list) const
Finds the first module whose file specification matches file_spec.
Definition: ModuleList.cpp:486
static bool RemoveSharedModuleIfOrphaned(const Module *module_ptr)
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
bool AppendIfNeeded(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list, if it is not already there.
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
size_t FindTypes(Module *search_first, ConstString name, bool name_is_fully_qualified, size_t max_matches, llvm::DenseSet< SymbolFile *> &searched_symbol_files, TypeList &types) const
Find types by name.
Definition: ModuleList.cpp:536
uint32_t ResolveSymbolContextsForFileSpec(const FileSpec &file_spec, uint32_t line, bool check_inlines, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const
Resolve items in the symbol context for a given file and line. (const FileSpec
Definition: ModuleList.cpp:693
static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec)
const lldb_private::UUID & GetUUID()
Get a reference to the UUID value contained in this object.
Definition: Module.cpp:330
llvm::sys::TimePoint GetModificationTime(const FileSpec &file_spec) const
Returns the modification time of the given file.
An error handling class.
Definition: Status.h:44
static bool RemoveSharedModule(lldb::ModuleSP &module_sp)
lldb::FunctionNameType GetNameTypeMask() const
Definition: Module.h:973
void AppendImpl(const lldb::ModuleSP &module_sp, bool use_notifier=true)
Definition: ModuleList.cpp:145
const ModuleList & operator=(const ModuleList &rhs)
Assignment operator.
Definition: ModuleList.cpp:131