1 | //===-- CompileUnit.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_SYMBOL_COMPILEUNIT_H |
10 | #define LLDB_SYMBOL_COMPILEUNIT_H |
11 | |
12 | #include "lldb/Core/ModuleChild.h" |
13 | #include "lldb/Core/SourceLocationSpec.h" |
14 | #include "lldb/Symbol/DebugMacros.h" |
15 | #include "lldb/Symbol/Function.h" |
16 | #include "lldb/Symbol/LineTable.h" |
17 | #include "lldb/Symbol/SourceModule.h" |
18 | #include "lldb/Utility/FileSpecList.h" |
19 | #include "lldb/Utility/Stream.h" |
20 | #include "lldb/Utility/UserID.h" |
21 | #include "lldb/lldb-enumerations.h" |
22 | |
23 | #include "llvm/ADT/DenseMap.h" |
24 | #include "llvm/ADT/DenseSet.h" |
25 | |
26 | namespace lldb_private { |
27 | /// \class CompileUnit CompileUnit.h "lldb/Symbol/CompileUnit.h" |
28 | /// A class that describes a compilation unit. |
29 | /// |
30 | /// A representation of a compilation unit, or compiled source file. |
31 | /// The UserID of the compile unit is specified by the SymbolFile plug-in and |
32 | /// can have any value as long as the value is unique within the Module that |
33 | /// owns this compile units. |
34 | /// |
35 | /// Each compile unit has a list of functions, global and static variables, |
36 | /// support file list (include files and inlined source files), and a line |
37 | /// table. |
38 | class CompileUnit : public std::enable_shared_from_this<CompileUnit>, |
39 | public ModuleChild, |
40 | public UserID, |
41 | public SymbolContextScope { |
42 | public: |
43 | /// Construct with a module, path, UID and language. |
44 | /// |
45 | /// Initialize the compile unit given the owning \a module, a path to |
46 | /// convert into a FileSpec, the SymbolFile plug-in supplied \a uid, and the |
47 | /// source language type. |
48 | /// |
49 | /// \param[in] module_sp |
50 | /// The parent module that owns this compile unit. This value |
51 | /// must be a valid pointer value. |
52 | /// |
53 | /// \param[in] user_data |
54 | /// User data where the SymbolFile parser can store data. |
55 | /// |
56 | /// \param[in] pathname |
57 | /// The path to the source file for this compile unit. |
58 | /// |
59 | /// \param[in] uid |
60 | /// The user ID of the compile unit. This value is supplied by |
61 | /// the SymbolFile plug-in and should be a value that allows |
62 | /// the SymbolFile plug-in to easily locate and parse additional |
63 | /// information for the compile unit. |
64 | /// |
65 | /// \param[in] language |
66 | /// A language enumeration type that describes the main language |
67 | /// of this compile unit. |
68 | /// |
69 | /// \param[in] is_optimized |
70 | /// A value that can initialized with eLazyBoolYes, eLazyBoolNo |
71 | /// or eLazyBoolCalculate. If set to eLazyBoolCalculate, then |
72 | /// an extra call into SymbolVendor will be made to calculate if |
73 | /// the compile unit is optimized will be made when |
74 | /// CompileUnit::GetIsOptimized() is called. |
75 | /// |
76 | /// \see lldb::LanguageType |
77 | CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, |
78 | const char *pathname, lldb::user_id_t uid, |
79 | lldb::LanguageType language, lldb_private::LazyBool is_optimized); |
80 | |
81 | /// Construct with a module, file spec, UID and language. |
82 | /// |
83 | /// Initialize the compile unit given the owning \a module, a path to |
84 | /// convert into a FileSpec, the SymbolFile plug-in supplied \a uid, and the |
85 | /// source language type. |
86 | /// |
87 | /// \param[in] module_sp |
88 | /// The parent module that owns this compile unit. This value |
89 | /// must be a valid pointer value. |
90 | /// |
91 | /// \param[in] user_data |
92 | /// User data where the SymbolFile parser can store data. |
93 | /// |
94 | /// \param[in] support_file_sp |
95 | /// The file specification for the source file of this compile |
96 | /// unit. |
97 | /// |
98 | /// \param[in] uid |
99 | /// The user ID of the compile unit. This value is supplied by |
100 | /// the SymbolFile plug-in and should be a value that allows |
101 | /// the plug-in to easily locate and parse |
102 | /// additional information for the compile unit. |
103 | /// |
104 | /// \param[in] language |
105 | /// A language enumeration type that describes the main language |
106 | /// of this compile unit. |
107 | /// |
108 | /// \param[in] is_optimized |
109 | /// A value that can initialized with eLazyBoolYes, eLazyBoolNo |
110 | /// or eLazyBoolCalculate. If set to eLazyBoolCalculate, then |
111 | /// an extra call into SymbolVendor will be made to calculate if |
112 | /// the compile unit is optimized will be made when |
113 | /// CompileUnit::GetIsOptimized() is called. |
114 | /// |
115 | /// \param[in] support_files |
116 | /// An rvalue list of already parsed support files. |
117 | /// \see lldb::LanguageType |
118 | CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, |
119 | lldb::SupportFileSP support_file_sp, lldb::user_id_t uid, |
120 | lldb::LanguageType language, lldb_private::LazyBool is_optimized, |
121 | SupportFileList &&support_files = {}); |
122 | |
123 | /// Add a function to this compile unit. |
124 | /// |
125 | /// Typically called by the SymbolFile plug-ins as they partially parse the |
126 | /// debug information. |
127 | /// |
128 | /// \param[in] function_sp |
129 | /// A shared pointer to the Function object. |
130 | void AddFunction(lldb::FunctionSP &function_sp); |
131 | |
132 | /// \copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) |
133 | /// |
134 | /// \see SymbolContextScope |
135 | void CalculateSymbolContext(SymbolContext *sc) override; |
136 | |
137 | lldb::ModuleSP CalculateSymbolContextModule() override; |
138 | |
139 | CompileUnit *CalculateSymbolContextCompileUnit() override; |
140 | |
141 | /// \copydoc SymbolContextScope::DumpSymbolContext(Stream*) |
142 | /// |
143 | /// \see SymbolContextScope |
144 | void DumpSymbolContext(Stream *s) override; |
145 | |
146 | lldb::LanguageType GetLanguage(); |
147 | |
148 | void SetLanguage(lldb::LanguageType language) { |
149 | m_flags.Set(flagsParsedLanguage); |
150 | m_language = language; |
151 | } |
152 | |
153 | void GetDescription(Stream *s, lldb::DescriptionLevel level) const; |
154 | |
155 | /// Apply a lambda to each function in this compile unit. |
156 | /// |
157 | /// This provides raw access to the function shared pointer list and will not |
158 | /// cause the SymbolFile plug-in to parse any unparsed functions. |
159 | /// |
160 | /// \note Prefer using FindFunctionByUID over this if possible. |
161 | /// |
162 | /// \param[in] lambda |
163 | /// The lambda that should be applied to every function. The lambda can |
164 | /// return true if the iteration should be aborted earlier. |
165 | void ForeachFunction( |
166 | llvm::function_ref<bool(const lldb::FunctionSP &)> lambda) const; |
167 | |
168 | /// Find a function in the compile unit based on the predicate matching_lambda |
169 | /// |
170 | /// \param[in] matching_lambda |
171 | /// A predicate that will be used within FindFunction to evaluate each |
172 | /// FunctionSP in m_functions_by_uid. When the predicate returns true |
173 | /// FindFunction will return the corresponding FunctionSP. |
174 | /// |
175 | /// \return |
176 | /// The first FunctionSP that the matching_lambda prediate returns true for. |
177 | lldb::FunctionSP FindFunction( |
178 | llvm::function_ref<bool(const lldb::FunctionSP &)> matching_lambda); |
179 | |
180 | /// Dump the compile unit contents to the stream \a s. |
181 | /// |
182 | /// \param[in] s |
183 | /// The stream to which to dump the object description. |
184 | /// |
185 | /// \param[in] show_context |
186 | /// If \b true, variables will dump their symbol context |
187 | /// information. |
188 | void Dump(Stream *s, bool show_context) const; |
189 | |
190 | /// Find the line entry by line and optional inlined file spec. |
191 | /// |
192 | /// Finds the first line entry that has an index greater than \a start_idx |
193 | /// that matches \a line. If \a file_spec_ptr is NULL, then the search |
194 | /// matches line entries whose file matches the file for the compile unit. |
195 | /// If \a file_spec_ptr is not NULL, line entries must match the specified |
196 | /// file spec (for inlined line table entries). |
197 | /// |
198 | /// Multiple calls to this function can find all entries that match a given |
199 | /// file and line by starting with \a start_idx equal to zero, and calling |
200 | /// this function back with the return value + 1. |
201 | /// |
202 | /// \param[in] start_idx |
203 | /// The zero based index at which to start looking for matches. |
204 | /// |
205 | /// \param[in] line |
206 | /// The line number to search for. |
207 | /// |
208 | /// \param[in] file_spec_ptr |
209 | /// If non-NULL search for entries that match this file spec, |
210 | /// else if NULL, search for line entries that match the compile |
211 | /// unit file. |
212 | /// |
213 | /// \param[in] exact |
214 | /// If \b true match only if there is a line table entry for this line |
215 | /// number. |
216 | /// If \b false, find the line table entry equal to or after this line |
217 | /// number. |
218 | /// |
219 | /// \param[out] line_entry |
220 | /// If non-NULL, a copy of the line entry that was found. |
221 | /// |
222 | /// \return |
223 | /// The zero based index of a matching line entry, or UINT32_MAX |
224 | /// if no matching line entry is found. |
225 | uint32_t FindLineEntry(uint32_t start_idx, uint32_t line, |
226 | const FileSpec *file_spec_ptr, bool exact, |
227 | LineEntry *line_entry); |
228 | |
229 | /// Return the primary source spec associated with this compile unit. |
230 | const FileSpec &GetPrimaryFile() const { |
231 | return m_primary_support_file_sp->GetSpecOnly(); |
232 | } |
233 | |
234 | /// Return the primary source file associated with this compile unit. |
235 | lldb::SupportFileSP GetPrimarySupportFile() const { |
236 | return m_primary_support_file_sp; |
237 | } |
238 | |
239 | /// Get the line table for the compile unit. |
240 | /// |
241 | /// Called by clients and the SymbolFile plug-in. The SymbolFile plug-ins |
242 | /// use this function to determine if the line table has be parsed yet. |
243 | /// Clients use this function to get the line table from a compile unit. |
244 | /// |
245 | /// \return |
246 | /// The line table object pointer, or NULL if this line table |
247 | /// hasn't been parsed yet. |
248 | LineTable *GetLineTable(); |
249 | |
250 | DebugMacros *GetDebugMacros(); |
251 | |
252 | /// Apply a lambda to each external lldb::Module referenced by this |
253 | /// compilation unit. Recursively also descends into the referenced external |
254 | /// modules of any encountered compilation unit. |
255 | /// |
256 | /// \param visited_symbol_files |
257 | /// A set of SymbolFiles that were already visited to avoid |
258 | /// visiting one file more than once. |
259 | /// |
260 | /// \param[in] lambda |
261 | /// The lambda that should be applied to every function. The lambda can |
262 | /// return true if the iteration should be aborted earlier. |
263 | /// |
264 | /// \return |
265 | /// If the lambda early-exited, this function returns true to |
266 | /// propagate the early exit. |
267 | virtual bool ForEachExternalModule( |
268 | llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files, |
269 | llvm::function_ref<bool(Module &)> lambda); |
270 | |
271 | /// Get the compile unit's support file list. |
272 | /// |
273 | /// The support file list is used by the line table, and any objects that |
274 | /// have valid Declaration objects. |
275 | /// |
276 | /// \return |
277 | /// A support file list object. |
278 | const SupportFileList &GetSupportFiles(); |
279 | |
280 | /// Used by plugins that parse the support file list. |
281 | SupportFileList &GetSupportFileList() { |
282 | m_flags.Set(flagsParsedSupportFiles); |
283 | return m_support_files; |
284 | } |
285 | |
286 | /// Get the compile unit's imported module list. |
287 | /// |
288 | /// This reports all the imports that the compile unit made, including the |
289 | /// current module. |
290 | /// |
291 | /// \return |
292 | /// A list of imported modules. |
293 | const std::vector<SourceModule> &GetImportedModules(); |
294 | |
295 | /// Get the SymbolFile plug-in user data. |
296 | /// |
297 | /// SymbolFile plug-ins can store user data to internal state or objects to |
298 | /// quickly allow them to parse more information for a given object. |
299 | /// |
300 | /// \return |
301 | /// The user data stored with the CompileUnit when it was |
302 | /// constructed. |
303 | void *GetUserData() const; |
304 | |
305 | /// Get the variable list for a compile unit. |
306 | /// |
307 | /// Called by clients to get the variable list for a compile unit. The |
308 | /// variable list will contain all global and static variables that were |
309 | /// defined at the compile unit level. |
310 | /// |
311 | /// \param[in] can_create |
312 | /// If \b true, the variable list will be parsed on demand. If |
313 | /// \b false, the current variable list will be returned even |
314 | /// if it contains a NULL VariableList object (typically |
315 | /// called by dumping routines that want to display only what |
316 | /// has currently been parsed). |
317 | /// |
318 | /// \return |
319 | /// A shared pointer to a variable list, that can contain NULL |
320 | /// VariableList pointer if there are no global or static |
321 | /// variables. |
322 | lldb::VariableListSP GetVariableList(bool can_create); |
323 | |
324 | /// Finds a function by user ID. |
325 | /// |
326 | /// Typically used by SymbolFile plug-ins when partially parsing the debug |
327 | /// information to see if the function has been parsed yet. |
328 | /// |
329 | /// \param[in] uid |
330 | /// The user ID of the function to find. This value is supplied |
331 | /// by the SymbolFile plug-in and should be a value that |
332 | /// allows the plug-in to easily locate and parse additional |
333 | /// information in the function. |
334 | /// |
335 | /// \return |
336 | /// A shared pointer to the function object that might contain |
337 | /// a NULL Function pointer. |
338 | lldb::FunctionSP FindFunctionByUID(lldb::user_id_t uid); |
339 | |
340 | /// Set the line table for the compile unit. |
341 | /// |
342 | /// Called by the SymbolFile plug-in when if first parses the line table and |
343 | /// hands ownership of the line table to this object. The compile unit owns |
344 | /// the line table object and will delete the object when it is deleted. |
345 | /// |
346 | /// \param[in] line_table |
347 | /// A line table object pointer that this object now owns. |
348 | void SetLineTable(LineTable *line_table); |
349 | |
350 | void SetDebugMacros(const DebugMacrosSP &debug_macros); |
351 | |
352 | /// Set accessor for the variable list. |
353 | /// |
354 | /// Called by the SymbolFile plug-ins after they have parsed the variable |
355 | /// lists and are ready to hand ownership of the list over to this object. |
356 | /// |
357 | /// \param[in] variable_list_sp |
358 | /// A shared pointer to a VariableList. |
359 | void SetVariableList(lldb::VariableListSP &variable_list_sp); |
360 | |
361 | /// Resolve symbol contexts by file and line. |
362 | /// |
363 | /// Given a file in \a src_location_spec, find all instances and |
364 | /// append them to the supplied symbol context list \a sc_list. |
365 | /// |
366 | /// \param[in] src_location_spec |
367 | /// The \a src_location_spec containing the \a file_spec, the line and the |
368 | /// column of the symbol to look for. Also hold the inlines and |
369 | /// exact_match flags. |
370 | /// |
371 | /// If check_inlines is \b true, this function will also match any inline |
372 | /// file and line matches. If \b false, the compile unit's |
373 | /// file specification must match \a file_spec for any matches |
374 | /// to be returned. |
375 | /// |
376 | /// If exact_match is \b true, only resolve the context if \a line and \a |
377 | /// column exists in the line table. If \b false, resolve the context to |
378 | /// the closest line greater than \a line in the line table. |
379 | /// |
380 | /// \param[in] resolve_scope |
381 | /// For each matching line entry, this bitfield indicates what |
382 | /// values within each SymbolContext that gets added to \a |
383 | /// sc_list will be resolved. See the SymbolContext::Scope |
384 | /// enumeration for a list of all available bits that can be |
385 | /// resolved. Only SymbolContext entries that can be resolved |
386 | /// using a LineEntry base address will be able to be resolved. |
387 | /// |
388 | /// \param[out] sc_list |
389 | /// A SymbolContext list class that will get any matching |
390 | /// entries appended to. |
391 | /// |
392 | /// \see enum SymbolContext::Scope |
393 | void ResolveSymbolContext(const SourceLocationSpec &src_location_spec, |
394 | lldb::SymbolContextItem resolve_scope, |
395 | SymbolContextList &sc_list); |
396 | |
397 | /// Get whether compiler optimizations were enabled for this compile unit |
398 | /// |
399 | /// "optimized" means that the debug experience may be difficult for the |
400 | /// user to understand. Variables may not be available when the developer |
401 | /// would expect them, stepping through the source lines in the function may |
402 | /// appear strange, etc. |
403 | /// |
404 | /// \return |
405 | /// Returns 'true' if this compile unit was compiled with |
406 | /// optimization. 'false' indicates that either the optimization |
407 | /// is unknown, or this compile unit was built without optimization. |
408 | bool GetIsOptimized(); |
409 | |
410 | /// Returns the number of functions in this compile unit |
411 | size_t GetNumFunctions() const { return m_functions_by_uid.size(); } |
412 | |
413 | protected: |
414 | /// User data for the SymbolFile parser to store information into. |
415 | void *m_user_data; |
416 | /// The programming language enumeration value. |
417 | lldb::LanguageType m_language; |
418 | /// Compile unit flags that help with partial parsing. |
419 | Flags m_flags; |
420 | /// Maps UIDs to functions. |
421 | llvm::DenseMap<lldb::user_id_t, lldb::FunctionSP> m_functions_by_uid; |
422 | /// All modules, including the current module, imported by this |
423 | /// compile unit. |
424 | std::vector<SourceModule> m_imported_modules; |
425 | /// The primary file associated with this compile unit. |
426 | lldb::SupportFileSP m_primary_support_file_sp; |
427 | /// Files associated with this compile unit's line table and declarations. |
428 | SupportFileList m_support_files; |
429 | /// Line table that will get parsed on demand. |
430 | std::unique_ptr<LineTable> m_line_table_up; |
431 | /// Debug macros that will get parsed on demand. |
432 | DebugMacrosSP m_debug_macros_sp; |
433 | /// Global and static variable list that will get parsed on demand. |
434 | lldb::VariableListSP m_variables; |
435 | /// eLazyBoolYes if this compile unit was compiled with |
436 | /// optimization. |
437 | lldb_private::LazyBool m_is_optimized; |
438 | |
439 | private: |
440 | enum { |
441 | flagsParsedAllFunctions = |
442 | (1u << 0), ///< Have we already parsed all our functions |
443 | flagsParsedVariables = |
444 | (1u << 1), ///< Have we already parsed globals and statics? |
445 | flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support |
446 | ///files for this compile unit? |
447 | flagsParsedLineTable = |
448 | (1u << 3), ///< Have we parsed the line table already? |
449 | flagsParsedLanguage = (1u << 4), ///< Have we parsed the language already? |
450 | flagsParsedImportedModules = |
451 | (1u << 5), ///< Have we parsed the imported modules already? |
452 | flagsParsedDebugMacros = |
453 | (1u << 6) ///< Have we parsed the debug macros already? |
454 | }; |
455 | |
456 | CompileUnit(const CompileUnit &) = delete; |
457 | const CompileUnit &operator=(const CompileUnit &) = delete; |
458 | const char *GetCachedLanguage() const; |
459 | }; |
460 | |
461 | } // namespace lldb_private |
462 | |
463 | #endif // LLDB_SYMBOL_COMPILEUNIT_H |
464 | |