1 | //===-- ModuleList.h --------------------------------------------*- 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 | #ifndef LLDB_CORE_MODULELIST_H |
10 | #define LLDB_CORE_MODULELIST_H |
11 | |
12 | #include "lldb/Core/Address.h" |
13 | #include "lldb/Core/ModuleSpec.h" |
14 | #include "lldb/Core/UserSettingsController.h" |
15 | #include "lldb/Utility/FileSpec.h" |
16 | #include "lldb/Utility/Iterable.h" |
17 | #include "lldb/Utility/Status.h" |
18 | #include "lldb/lldb-enumerations.h" |
19 | #include "lldb/lldb-forward.h" |
20 | #include "lldb/lldb-types.h" |
21 | |
22 | #include "llvm/ADT/DenseSet.h" |
23 | #include "llvm/Support/RWMutex.h" |
24 | |
25 | #include <functional> |
26 | #include <list> |
27 | #include <mutex> |
28 | #include <vector> |
29 | |
30 | #include <cstddef> |
31 | #include <cstdint> |
32 | |
33 | namespace lldb_private { |
34 | class ConstString; |
35 | class FileSpecList; |
36 | class Function; |
37 | class Log; |
38 | class Module; |
39 | class RegularExpression; |
40 | class Stream; |
41 | class SymbolContext; |
42 | class SymbolContextList; |
43 | class SymbolFile; |
44 | class Target; |
45 | class TypeList; |
46 | class UUID; |
47 | class VariableList; |
48 | struct ModuleFunctionSearchOptions; |
49 | |
50 | static constexpr OptionEnumValueElement g_auto_download_enum_values[] = { |
51 | { |
52 | .value: lldb::eSymbolDownloadOff, |
53 | .string_value: "off" , |
54 | .usage: "Disable automatically downloading symbols." , |
55 | }, |
56 | { |
57 | .value: lldb::eSymbolDownloadBackground, |
58 | .string_value: "background" , |
59 | .usage: "Download symbols in the background for images as they appear in the " |
60 | "backtrace." , |
61 | }, |
62 | { |
63 | .value: lldb::eSymbolDownloadForeground, |
64 | .string_value: "foreground" , |
65 | .usage: "Download symbols in the foreground for images as they appear in the " |
66 | "backtrace." , |
67 | }, |
68 | }; |
69 | |
70 | class ModuleListProperties : public Properties { |
71 | mutable llvm::sys::RWMutex m_symlink_paths_mutex; |
72 | PathMappingList m_symlink_paths; |
73 | |
74 | void UpdateSymlinkMappings(); |
75 | |
76 | public: |
77 | ModuleListProperties(); |
78 | |
79 | FileSpec GetClangModulesCachePath() const; |
80 | bool SetClangModulesCachePath(const FileSpec &path); |
81 | bool GetEnableExternalLookup() const; |
82 | bool SetEnableExternalLookup(bool new_value); |
83 | bool GetEnableLLDBIndexCache() const; |
84 | bool SetEnableLLDBIndexCache(bool new_value); |
85 | uint64_t GetLLDBIndexCacheMaxByteSize(); |
86 | uint64_t GetLLDBIndexCacheMaxPercent(); |
87 | uint64_t GetLLDBIndexCacheExpirationDays(); |
88 | FileSpec GetLLDBIndexCachePath() const; |
89 | bool SetLLDBIndexCachePath(const FileSpec &path); |
90 | |
91 | bool GetLoadSymbolOnDemand(); |
92 | |
93 | lldb::SymbolDownload GetSymbolAutoDownload() const; |
94 | |
95 | PathMappingList GetSymlinkMappings() const; |
96 | }; |
97 | |
98 | /// \class ModuleList ModuleList.h "lldb/Core/ModuleList.h" |
99 | /// A collection class for Module objects. |
100 | /// |
101 | /// Modules in the module collection class are stored as reference counted |
102 | /// shared pointers to Module objects. |
103 | class ModuleList { |
104 | public: |
105 | class Notifier { |
106 | public: |
107 | virtual ~Notifier() = default; |
108 | |
109 | virtual void NotifyModuleAdded(const ModuleList &module_list, |
110 | const lldb::ModuleSP &module_sp) = 0; |
111 | virtual void NotifyModuleRemoved(const ModuleList &module_list, |
112 | const lldb::ModuleSP &module_sp) = 0; |
113 | virtual void NotifyModuleUpdated(const ModuleList &module_list, |
114 | const lldb::ModuleSP &old_module_sp, |
115 | const lldb::ModuleSP &new_module_sp) = 0; |
116 | virtual void NotifyWillClearList(const ModuleList &module_list) = 0; |
117 | |
118 | virtual void NotifyModulesRemoved(lldb_private::ModuleList &module_list) = 0; |
119 | }; |
120 | |
121 | /// Default constructor. |
122 | /// |
123 | /// Creates an empty list of Module objects. |
124 | ModuleList(); |
125 | |
126 | /// Copy Constructor. |
127 | /// |
128 | /// Creates a new module list object with a copy of the modules from \a rhs. |
129 | /// |
130 | /// \param[in] rhs |
131 | /// Another module list object. |
132 | ModuleList(const ModuleList &rhs); |
133 | |
134 | ModuleList(ModuleList::Notifier *notifier); |
135 | |
136 | /// Destructor. |
137 | ~ModuleList(); |
138 | |
139 | /// Assignment operator. |
140 | /// |
141 | /// Copies the module list from \a rhs into this list. |
142 | /// |
143 | /// \param[in] rhs |
144 | /// Another module list object. |
145 | /// |
146 | /// \return |
147 | /// A const reference to this object. |
148 | const ModuleList &operator=(const ModuleList &rhs); |
149 | |
150 | /// Append a module to the module list. |
151 | /// |
152 | /// \param[in] module_sp |
153 | /// A shared pointer to a module to add to this collection. |
154 | /// |
155 | /// \param[in] notify |
156 | /// If true, and a notifier function is set, the notifier function |
157 | /// will be called. Defaults to true. |
158 | /// |
159 | /// When this ModuleList is the Target's ModuleList, the notifier |
160 | /// function is Target::ModulesDidLoad -- the call to |
161 | /// ModulesDidLoad may be deferred when adding multiple Modules |
162 | /// to the Target, but it must be called at the end, |
163 | /// before resuming execution. |
164 | void Append(const lldb::ModuleSP &module_sp, bool notify = true); |
165 | |
166 | /// Append a module to the module list and remove any equivalent modules. |
167 | /// Equivalent modules are ones whose file, platform file and architecture |
168 | /// matches. |
169 | /// |
170 | /// Replaces the module to the collection. |
171 | /// |
172 | /// \param[in] module_sp |
173 | /// A shared pointer to a module to replace in this collection. |
174 | /// |
175 | /// \param[in] old_modules |
176 | /// Optional pointer to a vector which, if provided, will have shared |
177 | /// pointers to the replaced module(s) appended to it. |
178 | void ReplaceEquivalent( |
179 | const lldb::ModuleSP &module_sp, |
180 | llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules = nullptr); |
181 | |
182 | /// Append a module to the module list, if it is not already there. |
183 | /// |
184 | /// \param[in] notify |
185 | /// If true, and a notifier function is set, the notifier function |
186 | /// will be called. Defaults to true. |
187 | /// |
188 | /// When this ModuleList is the Target's ModuleList, the notifier |
189 | /// function is Target::ModulesDidLoad -- the call to |
190 | /// ModulesDidLoad may be deferred when adding multiple Modules |
191 | /// to the Target, but it must be called at the end, |
192 | /// before resuming execution. |
193 | bool AppendIfNeeded(const lldb::ModuleSP &new_module, bool notify = true); |
194 | |
195 | void Append(const ModuleList &module_list); |
196 | |
197 | bool AppendIfNeeded(const ModuleList &module_list); |
198 | |
199 | bool ReplaceModule(const lldb::ModuleSP &old_module_sp, |
200 | const lldb::ModuleSP &new_module_sp); |
201 | |
202 | /// Clear the object's state. |
203 | /// |
204 | /// Clears the list of modules and releases a reference to each module |
205 | /// object and if the reference count goes to zero, the module will be |
206 | /// deleted. |
207 | void Clear(); |
208 | |
209 | /// Clear the object's state. |
210 | /// |
211 | /// Clears the list of modules and releases a reference to each module |
212 | /// object and if the reference count goes to zero, the module will be |
213 | /// deleted. Also release all memory that might be held by any collection |
214 | /// classes (like std::vector) |
215 | void Destroy(); |
216 | |
217 | /// Dump the description of each module contained in this list. |
218 | /// |
219 | /// Dump the description of each module contained in this list to the |
220 | /// supplied stream \a s. |
221 | /// |
222 | /// \param[in] s |
223 | /// The stream to which to dump the object description. |
224 | /// |
225 | /// \see Module::Dump(Stream *) const |
226 | void Dump(Stream *s) const; |
227 | |
228 | void LogUUIDAndPaths(Log *log, const char *prefix_cstr); |
229 | |
230 | std::recursive_mutex &GetMutex() const { return m_modules_mutex; } |
231 | |
232 | size_t GetIndexForModule(const Module *module) const; |
233 | |
234 | /// Get the module shared pointer for the module at index \a idx. |
235 | /// |
236 | /// \param[in] idx |
237 | /// An index into this module collection. |
238 | /// |
239 | /// \return |
240 | /// A shared pointer to a Module which can contain NULL if |
241 | /// \a idx is out of range. |
242 | /// |
243 | /// \see ModuleList::GetSize() |
244 | lldb::ModuleSP GetModuleAtIndex(size_t idx) const; |
245 | |
246 | /// Get the module shared pointer for the module at index \a idx without |
247 | /// acquiring the ModuleList mutex. This MUST already have been acquired |
248 | /// with ModuleList::GetMutex and locked for this call to be safe. |
249 | /// |
250 | /// \param[in] idx |
251 | /// An index into this module collection. |
252 | /// |
253 | /// \return |
254 | /// A shared pointer to a Module which can contain NULL if |
255 | /// \a idx is out of range. |
256 | /// |
257 | /// \see ModuleList::GetSize() |
258 | lldb::ModuleSP GetModuleAtIndexUnlocked(size_t idx) const; |
259 | |
260 | /// Get the module pointer for the module at index \a idx. |
261 | /// |
262 | /// \param[in] idx |
263 | /// An index into this module collection. |
264 | /// |
265 | /// \return |
266 | /// A pointer to a Module which can by nullptr if \a idx is out |
267 | /// of range. |
268 | /// |
269 | /// \see ModuleList::GetSize() |
270 | Module *GetModulePointerAtIndex(size_t idx) const; |
271 | |
272 | /// Find compile units by partial or full path. |
273 | /// |
274 | /// Finds all compile units that match \a path in all of the modules and |
275 | /// returns the results in \a sc_list. |
276 | /// |
277 | /// \param[in] path |
278 | /// The name of the compile unit we are looking for. |
279 | /// |
280 | /// \param[out] sc_list |
281 | /// A symbol context list that gets filled in with all of the |
282 | /// matches. |
283 | void FindCompileUnits(const FileSpec &path, SymbolContextList &sc_list) const; |
284 | |
285 | /// \see Module::FindFunctions () |
286 | void FindFunctions(ConstString name, lldb::FunctionNameType name_type_mask, |
287 | const ModuleFunctionSearchOptions &options, |
288 | SymbolContextList &sc_list) const; |
289 | |
290 | /// \see Module::FindFunctionSymbols () |
291 | void FindFunctionSymbols(ConstString name, |
292 | lldb::FunctionNameType name_type_mask, |
293 | SymbolContextList &sc_list); |
294 | |
295 | /// \see Module::FindFunctions () |
296 | void FindFunctions(const RegularExpression &name, |
297 | const ModuleFunctionSearchOptions &options, |
298 | SymbolContextList &sc_list); |
299 | |
300 | /// Find global and static variables by name. |
301 | /// |
302 | /// \param[in] name |
303 | /// The name of the global or static variable we are looking |
304 | /// for. |
305 | /// |
306 | /// \param[in] max_matches |
307 | /// Allow the number of matches to be limited to \a |
308 | /// max_matches. Specify UINT32_MAX to get all possible matches. |
309 | /// |
310 | /// \param[in] variable_list |
311 | /// A list of variables that gets the matches appended to. |
312 | void FindGlobalVariables(ConstString name, size_t max_matches, |
313 | VariableList &variable_list) const; |
314 | |
315 | /// Find global and static variables by regular expression. |
316 | /// |
317 | /// \param[in] regex |
318 | /// A regular expression to use when matching the name. |
319 | /// |
320 | /// \param[in] max_matches |
321 | /// Allow the number of matches to be limited to \a |
322 | /// max_matches. Specify UINT32_MAX to get all possible matches. |
323 | /// |
324 | /// \param[in] variable_list |
325 | /// A list of variables that gets the matches appended to. |
326 | void FindGlobalVariables(const RegularExpression ®ex, size_t max_matches, |
327 | VariableList &variable_list) const; |
328 | |
329 | /// Finds the first module whose file specification matches \a file_spec. |
330 | /// |
331 | /// \param[in] module_spec |
332 | /// A file specification object to match against the Module's |
333 | /// file specifications. If \a file_spec does not have |
334 | /// directory information, matches will occur by matching only |
335 | /// the basename of any modules in this list. If this value is |
336 | /// NULL, then file specifications won't be compared when |
337 | /// searching for matching modules. |
338 | /// |
339 | /// \param[out] matching_module_list |
340 | /// A module list that gets filled in with any modules that |
341 | /// match the search criteria. |
342 | void FindModules(const ModuleSpec &module_spec, |
343 | ModuleList &matching_module_list) const; |
344 | |
345 | lldb::ModuleSP FindModule(const Module *module_ptr) const; |
346 | |
347 | // Find a module by UUID |
348 | // |
349 | // The UUID value for a module is extracted from the ObjectFile and is the |
350 | // MD5 checksum, or a smarter object file equivalent, so finding modules by |
351 | // UUID values is very efficient and accurate. |
352 | lldb::ModuleSP FindModule(const UUID &uuid) const; |
353 | |
354 | lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const; |
355 | |
356 | void FindSymbolsWithNameAndType(ConstString name, |
357 | lldb::SymbolType symbol_type, |
358 | SymbolContextList &sc_list) const; |
359 | |
360 | void FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, |
361 | lldb::SymbolType symbol_type, |
362 | SymbolContextList &sc_list) const; |
363 | |
364 | /// Find types using a type-matching object that contains all search |
365 | /// parameters. |
366 | /// |
367 | /// \param[in] search_first |
368 | /// If non-null, this module will be searched before any other |
369 | /// modules. |
370 | /// |
371 | /// \param[in] query |
372 | /// A type matching object that contains all of the details of the type |
373 | /// search. |
374 | /// |
375 | /// \param[in] results |
376 | /// Any matching types will be populated into the \a results object using |
377 | /// TypeMap::InsertUnique(...). |
378 | void FindTypes(Module *search_first, const TypeQuery &query, |
379 | lldb_private::TypeResults &results) const; |
380 | |
381 | bool FindSourceFile(const FileSpec &orig_spec, FileSpec &new_spec) const; |
382 | |
383 | /// Find addresses by file/line |
384 | /// |
385 | /// \param[in] target_sp |
386 | /// The target the addresses are desired for. |
387 | /// |
388 | /// \param[in] file |
389 | /// Source file to locate. |
390 | /// |
391 | /// \param[in] line |
392 | /// Source line to locate. |
393 | /// |
394 | /// \param[in] function |
395 | /// Optional filter function. Addresses within this function will be |
396 | /// added to the 'local' list. All others will be added to the 'extern' |
397 | /// list. |
398 | /// |
399 | /// \param[out] output_local |
400 | /// All matching addresses within 'function' |
401 | /// |
402 | /// \param[out] output_extern |
403 | /// All matching addresses not within 'function' |
404 | void FindAddressesForLine(const lldb::TargetSP target_sp, |
405 | const FileSpec &file, uint32_t line, |
406 | Function *function, |
407 | std::vector<Address> &output_local, |
408 | std::vector<Address> &output_extern); |
409 | |
410 | /// Remove a module from the module list. |
411 | /// |
412 | /// \param[in] module_sp |
413 | /// A shared pointer to a module to remove from this collection. |
414 | /// |
415 | /// \param[in] notify |
416 | /// If true, and a notifier function is set, the notifier function |
417 | /// will be called. Defaults to true. |
418 | /// |
419 | /// When this ModuleList is the Target's ModuleList, the notifier |
420 | /// function is Target::ModulesDidUnload -- the call to |
421 | /// ModulesDidUnload may be deferred when removing multiple Modules |
422 | /// from the Target, but it must be called at the end, |
423 | /// before resuming execution. |
424 | bool Remove(const lldb::ModuleSP &module_sp, bool notify = true); |
425 | |
426 | size_t Remove(ModuleList &module_list); |
427 | |
428 | bool RemoveIfOrphaned(const Module *module_ptr); |
429 | |
430 | size_t RemoveOrphans(bool mandatory); |
431 | |
432 | bool ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) const; |
433 | |
434 | /// \copydoc Module::ResolveSymbolContextForAddress (const Address |
435 | /// &,uint32_t,SymbolContext&) |
436 | uint32_t ResolveSymbolContextForAddress(const Address &so_addr, |
437 | lldb::SymbolContextItem resolve_scope, |
438 | SymbolContext &sc) const; |
439 | |
440 | /// \copydoc Module::ResolveSymbolContextForFilePath (const char |
441 | /// *,uint32_t,bool,uint32_t,SymbolContextList&) |
442 | uint32_t ResolveSymbolContextForFilePath( |
443 | const char *file_path, uint32_t line, bool check_inlines, |
444 | lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const; |
445 | |
446 | /// \copydoc Module::ResolveSymbolContextsForFileSpec (const FileSpec |
447 | /// &,uint32_t,bool,uint32_t,SymbolContextList&) |
448 | uint32_t ResolveSymbolContextsForFileSpec( |
449 | const FileSpec &file_spec, uint32_t line, bool check_inlines, |
450 | lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const; |
451 | |
452 | /// Gets the size of the module list. |
453 | /// |
454 | /// \return |
455 | /// The number of modules in the module list. |
456 | size_t GetSize() const; |
457 | bool IsEmpty() const { return !GetSize(); } |
458 | |
459 | bool LoadScriptingResourcesInTarget(Target *target, std::list<Status> &errors, |
460 | Stream &feedback_stream, |
461 | bool continue_on_error = true); |
462 | |
463 | static ModuleListProperties &GetGlobalModuleListProperties(); |
464 | |
465 | static bool ModuleIsInCache(const Module *module_ptr); |
466 | |
467 | static Status |
468 | GetSharedModule(const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, |
469 | const FileSpecList *module_search_paths_ptr, |
470 | llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, |
471 | bool *did_create_ptr, bool always_create = false); |
472 | |
473 | static bool RemoveSharedModule(lldb::ModuleSP &module_sp); |
474 | |
475 | static void FindSharedModules(const ModuleSpec &module_spec, |
476 | ModuleList &matching_module_list); |
477 | |
478 | static lldb::ModuleSP FindSharedModule(const UUID &uuid); |
479 | |
480 | static size_t RemoveOrphanSharedModules(bool mandatory); |
481 | |
482 | static bool RemoveSharedModuleIfOrphaned(const Module *module_ptr); |
483 | |
484 | /// Applies 'callback' to each module in this ModuleList. |
485 | /// If 'callback' returns false, iteration terminates. |
486 | /// The 'module_sp' passed to 'callback' is guaranteed to |
487 | /// be non-null. |
488 | /// |
489 | /// This function is thread-safe. |
490 | void ForEach(std::function<bool(const lldb::ModuleSP &module_sp)> const |
491 | &callback) const; |
492 | |
493 | /// Returns true if 'callback' returns true for one of the modules |
494 | /// in this ModuleList. |
495 | /// |
496 | /// This function is thread-safe. |
497 | bool AnyOf( |
498 | std::function<bool(lldb_private::Module &module)> const &callback) const; |
499 | |
500 | /// Atomically swaps the contents of this module list with \a other. |
501 | void Swap(ModuleList &other); |
502 | |
503 | protected: |
504 | // Class typedefs. |
505 | typedef std::vector<lldb::ModuleSP> |
506 | collection; ///< The module collection type. |
507 | |
508 | void AppendImpl(const lldb::ModuleSP &module_sp, bool use_notifier = true); |
509 | |
510 | bool RemoveImpl(const lldb::ModuleSP &module_sp, bool use_notifier = true); |
511 | |
512 | collection::iterator RemoveImpl(collection::iterator pos, |
513 | bool use_notifier = true); |
514 | |
515 | void ClearImpl(bool use_notifier = true); |
516 | |
517 | // Member variables. |
518 | collection m_modules; ///< The collection of modules. |
519 | mutable std::recursive_mutex m_modules_mutex; |
520 | |
521 | Notifier *m_notifier = nullptr; |
522 | |
523 | public: |
524 | typedef LockingAdaptedIterable<collection, lldb::ModuleSP, vector_adapter, |
525 | std::recursive_mutex> |
526 | ModuleIterable; |
527 | ModuleIterable Modules() const { |
528 | return ModuleIterable(m_modules, GetMutex()); |
529 | } |
530 | |
531 | typedef AdaptedIterable<collection, lldb::ModuleSP, vector_adapter> |
532 | ModuleIterableNoLocking; |
533 | ModuleIterableNoLocking ModulesNoLocking() const { |
534 | return ModuleIterableNoLocking(m_modules); |
535 | } |
536 | }; |
537 | |
538 | } // namespace lldb_private |
539 | |
540 | #endif // LLDB_CORE_MODULELIST_H |
541 | |