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