1 //===-- Block.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 liblldb_Block_h_
10 #define liblldb_Block_h_
11 
12 #include "lldb/Core/AddressRange.h"
13 #include "lldb/Symbol/CompilerType.h"
14 #include "lldb/Symbol/LineEntry.h"
15 #include "lldb/Symbol/SymbolContext.h"
16 #include "lldb/Symbol/SymbolContextScope.h"
17 #include "lldb/Utility/RangeMap.h"
18 #include "lldb/Utility/Stream.h"
19 #include "lldb/Utility/UserID.h"
20 #include "lldb/lldb-private.h"
21 #include <vector>
22 
23 namespace lldb_private {
24 
25 /// \class Block Block.h "lldb/Symbol/Block.h"
26 /// A class that describes a single lexical block.
27 ///
28 /// A Function object owns a BlockList object which owns one or more
29 /// Block objects. The BlockList object contains a section offset address
30 /// range, and Block objects contain one or more ranges which are offsets into
31 /// that range. Blocks are can have discontiguous ranges within the BlockList
32 /// address range, and each block can contain child blocks each with their own
33 /// sets of ranges.
34 ///
35 /// Each block has a variable list that represents local, argument, and static
36 /// variables that are scoped to the block.
37 ///
38 /// Inlined functions are represented by attaching a InlineFunctionInfo shared
39 /// pointer object to a block. Inlined functions are represented as named
40 /// blocks.
41 class Block : public UserID, public SymbolContextScope {
42 public:
43   typedef RangeArray<uint32_t, uint32_t, 1> RangeList;
44   typedef RangeList::Entry Range;
45 
46   /// Construct with a User ID \a uid, \a depth.
47   ///
48   /// Initialize this block with the specified UID \a uid. The \a depth in the
49   /// \a block_list is used to represent the parent, sibling, and child block
50   /// information and also allows for partial parsing at the block level.
51   ///
52   /// \param[in] uid
53   ///     The UID for a given block. This value is given by the
54   ///     SymbolFile plug-in and can be any value that helps the
55   ///     SymbolFile plug-in to match this block back to the debug
56   ///     information data that it parses for further or more in
57   ///     depth parsing. Common values would be the index into a
58   ///     table, or an offset into the debug information.
59   ///
60   /// \param[in] depth
61   ///     The integer depth of this block in the block list hierarchy.
62   ///
63   /// \param[in] block_list
64   ///     The block list that this object belongs to.
65   ///
66   /// \see BlockList
67   Block(lldb::user_id_t uid);
68 
69   /// Destructor.
70   ~Block() override;
71 
72   /// Add a child to this object.
73   ///
74   /// \param[in] child_block_sp
75   ///     A shared pointer to a child block that will get added to
76   ///     this block.
77   void AddChild(const lldb::BlockSP &child_block_sp);
78 
79   /// Add a new offset range to this block.
80   ///
81   /// \param[in] start_offset
82   ///     An offset into this Function's address range that
83   ///     describes the start address of a range for this block.
84   ///
85   /// \param[in] end_offset
86   ///     An offset into this Function's address range that
87   ///     describes the end address of a range for this block.
88   void AddRange(const Range &range);
89 
90   void FinalizeRanges();
91 
92   /// \copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*)
93   ///
94   /// \see SymbolContextScope
95   void CalculateSymbolContext(SymbolContext *sc) override;
96 
97   lldb::ModuleSP CalculateSymbolContextModule() override;
98 
99   CompileUnit *CalculateSymbolContextCompileUnit() override;
100 
101   Function *CalculateSymbolContextFunction() override;
102 
103   Block *CalculateSymbolContextBlock() override;
104 
105   /// Check if an offset is in one of the block offset ranges.
106   ///
107   /// \param[in] range_offset
108   ///     An offset into the Function's address range.
109   ///
110   /// \return
111   ///     Returns \b true if \a range_offset falls in one of this
112   ///     block's ranges, \b false otherwise.
113   bool Contains(lldb::addr_t range_offset) const;
114 
115   /// Check if a offset range is in one of the block offset ranges.
116   ///
117   /// \param[in] range
118   ///     An offset range into the Function's address range.
119   ///
120   /// \return
121   ///     Returns \b true if \a range falls in one of this
122   ///     block's ranges, \b false otherwise.
123   bool Contains(const Range &range) const;
124 
125   /// Check if this object contains "block" as a child block at any depth.
126   ///
127   /// \param[in] block
128   ///     A potential child block.
129   ///
130   /// \return
131   ///     Returns \b true if \a block is a child of this block, \b
132   ///     false otherwise.
133   bool Contains(const Block *block) const;
134 
135   /// Dump the block contents.
136   ///
137   /// \param[in] s
138   ///     The stream to which to dump the object description.
139   ///
140   /// \param[in] base_addr
141   ///     The resolved start address of the Function's address
142   ///     range. This should be resolved as the file or load address
143   ///     prior to passing the value into this function for dumping.
144   ///
145   /// \param[in] depth
146   ///     Limit the number of levels deep that this function should
147   ///     print as this block can contain child blocks. Specify
148   ///     INT_MAX to dump all child blocks.
149   ///
150   /// \param[in] show_context
151   ///     If \b true, variables will dump their context information.
152   void Dump(Stream *s, lldb::addr_t base_addr, int32_t depth,
153             bool show_context) const;
154 
155   /// \copydoc SymbolContextScope::DumpSymbolContext(Stream*)
156   ///
157   /// \see SymbolContextScope
158   void DumpSymbolContext(Stream *s) override;
159 
160   void DumpAddressRanges(Stream *s, lldb::addr_t base_addr);
161 
162   void GetDescription(Stream *s, Function *function,
163                       lldb::DescriptionLevel level, Target *target) const;
164 
165   /// Get the parent block.
166   ///
167   /// \return
168   ///     The parent block pointer, or nullptr if this block has no
169   ///     parent.
170   Block *GetParent() const;
171 
172   /// Get the inlined block that contains this block.
173   ///
174   /// \return
175   ///     If this block contains inlined function info, it will return
176   ///     this block, else parent blocks will be searched to see if
177   ///     any contain this block. nullptr will be returned if this block
178   ///     nor any parent blocks are inlined function blocks.
179   Block *GetContainingInlinedBlock();
180 
181   /// Get the inlined parent block for this block.
182   ///
183   /// \return
184   ///     The parent block pointer, or nullptr if this block has no
185   ///     parent.
186   Block *GetInlinedParent();
187 
188   //------------------------------------------------------------------
189   /// Get the inlined block at the given call site that contains this block.
190   ///
191   /// @param[in] find_call_site
192   ///     a declaration with the file and line of the call site to find.
193   ///
194   /// @return
195   ///     If this block contains inlined function info and is at the call
196   ///     site given by the file and line at the given \b declaration, then
197   ///     it will return this block, otherwise the parent blocks will be
198   ///     searched to see if any is at the call site. nullptr will be returned
199   ///     if no block is found at the call site.
200   //------------------------------------------------------------------
201   Block *
202   GetContainingInlinedBlockWithCallSite(const Declaration &find_call_site);
203 
204   /// Get the sibling block for this block.
205   ///
206   /// \return
207   ///     The sibling block pointer, or nullptr if this block has no
208   ///     sibling.
209   Block *GetSibling() const;
210 
211   /// Get the first child block.
212   ///
213   /// \return
214   ///     The first child block pointer, or nullptr if this block has no
215   ///     children.
216   Block *GetFirstChild() const {
217     return (m_children.empty() ? nullptr : m_children.front().get());
218   }
219 
220   /// Get the variable list for this block only.
221   ///
222   /// \param[in] can_create
223   ///     If \b true, the variables can be parsed if they already
224   ///     haven't been, else the current state of the block will be
225   ///     returned.
226   ///
227   /// \return
228   ///     A variable list shared pointer that contains all variables
229   ///     for this block.
230   lldb::VariableListSP GetBlockVariableList(bool can_create);
231 
232   /// Get the variable list for this block and optionally all child blocks if
233   /// \a get_child_variables is \b true.
234   ///
235   /// \param[in] get_child_variables
236   ///     If \b true, all variables from all child blocks will be
237   ///     added to the variable list.
238   ///
239   /// \param[in] can_create
240   ///     If \b true, the variables can be parsed if they already
241   ///     haven't been, else the current state of the block will be
242   ///     returned. Passing \b true for this parameter can be used
243   ///     to see the current state of what has been parsed up to this
244   ///     point.
245   ///
246   /// \param[in] add_inline_child_block_variables
247   ///     If this is \b false, no child variables of child blocks
248   ///     that are inlined functions will be gotten. If \b true then
249   ///     all child variables will be added regardless of whether they
250   ///     come from inlined functions or not.
251   ///
252   /// \return
253   ///     A variable list shared pointer that contains all variables
254   ///     for this block.
255   uint32_t AppendBlockVariables(bool can_create, bool get_child_block_variables,
256                                 bool stop_if_child_block_is_inlined_function,
257                                 const std::function<bool(Variable *)> &filter,
258                                 VariableList *variable_list);
259 
260   /// Appends the variables from this block, and optionally from all parent
261   /// blocks, to \a variable_list.
262   ///
263   /// \param[in] can_create
264   ///     If \b true, the variables can be parsed if they already
265   ///     haven't been, else the current state of the block will be
266   ///     returned. Passing \b true for this parameter can be used
267   ///     to see the current state of what has been parsed up to this
268   ///     point.
269   ///
270   /// \param[in] get_parent_variables
271   ///     If \b true, all variables from all parent blocks will be
272   ///     added to the variable list.
273   ///
274   /// \param[in] stop_if_block_is_inlined_function
275   ///     If \b true, all variables from all parent blocks will be
276   ///     added to the variable list until there are no parent blocks
277   ///     or the parent block has inlined function info.
278   ///
279   /// \param[in,out] variable_list
280   ///     All variables in this block, and optionally all parent
281   ///     blocks will be added to this list.
282   ///
283   /// \return
284   ///     The number of variable that were appended to \a
285   ///     variable_list.
286   uint32_t AppendVariables(bool can_create, bool get_parent_variables,
287                            bool stop_if_block_is_inlined_function,
288                            const std::function<bool(Variable *)> &filter,
289                            VariableList *variable_list);
290 
291   /// Get const accessor for any inlined function information.
292   ///
293   /// \return
294   ///     A const pointer to any inlined function information, or nullptr
295   ///     if this is a regular block.
296   const InlineFunctionInfo *GetInlinedFunctionInfo() const {
297     return m_inlineInfoSP.get();
298   }
299 
300   /// Get the symbol file which contains debug info for this block's
301   /// symbol context module.
302   ///
303   /// \return A pointer to the symbol file or nullptr.
304   SymbolFile *GetSymbolFile();
305 
306   CompilerDeclContext GetDeclContext();
307 
308   /// Get the memory cost of this object.
309   ///
310   /// Returns the cost of this object plus any owned objects from the ranges,
311   /// variables, and inline function information.
312   ///
313   /// \return
314   ///     The number of bytes that this object occupies in memory.
315   size_t MemorySize() const;
316 
317   /// Set accessor for any inlined function information.
318   ///
319   /// \param[in] name
320   ///     The method name for the inlined function. This value should
321   ///     not be nullptr.
322   ///
323   /// \param[in] mangled
324   ///     The mangled method name for the inlined function. This can
325   ///     be nullptr if there is no mangled name for an inlined function
326   ///     or if the name is the same as \a name.
327   ///
328   /// \param[in] decl_ptr
329   ///     A optional pointer to declaration information for the
330   ///     inlined function information. This value can be nullptr to
331   ///     indicate that no declaration information is available.
332   ///
333   /// \param[in] call_decl_ptr
334   ///     Optional calling location declaration information that
335   ///     describes from where this inlined function was called.
336   void SetInlinedFunctionInfo(const char *name, const char *mangled,
337                               const Declaration *decl_ptr,
338                               const Declaration *call_decl_ptr);
339 
340   void SetParentScope(SymbolContextScope *parent_scope) {
341     m_parent_scope = parent_scope;
342   }
343 
344   /// Set accessor for the variable list.
345   ///
346   /// Called by the SymbolFile plug-ins after they have parsed the variable
347   /// lists and are ready to hand ownership of the list over to this object.
348   ///
349   /// \param[in] variable_list_sp
350   ///     A shared pointer to a VariableList.
351   void SetVariableList(lldb::VariableListSP &variable_list_sp) {
352     m_variable_list_sp = variable_list_sp;
353   }
354 
355   bool BlockInfoHasBeenParsed() const { return m_parsed_block_info; }
356 
357   void SetBlockInfoHasBeenParsed(bool b, bool set_children);
358 
359   Block *FindBlockByID(lldb::user_id_t block_id);
360 
361   size_t GetNumRanges() const { return m_ranges.GetSize(); }
362 
363   bool GetRangeContainingOffset(const lldb::addr_t offset, Range &range);
364 
365   bool GetRangeContainingAddress(const Address &addr, AddressRange &range);
366 
367   bool GetRangeContainingLoadAddress(lldb::addr_t load_addr, Target &target,
368                                      AddressRange &range);
369 
370   uint32_t GetRangeIndexContainingAddress(const Address &addr);
371 
372   // Since blocks might have multiple discontiguous address ranges, we need to
373   // be able to get at any of the address ranges in a block.
374   bool GetRangeAtIndex(uint32_t range_idx, AddressRange &range);
375 
376   bool GetStartAddress(Address &addr);
377 
378   void SetDidParseVariables(bool b, bool set_children);
379 
380 protected:
381   typedef std::vector<lldb::BlockSP> collection;
382   // Member variables.
383   SymbolContextScope *m_parent_scope;
384   collection m_children;
385   RangeList m_ranges;
386   lldb::InlineFunctionInfoSP m_inlineInfoSP; ///< Inlined function information.
387   lldb::VariableListSP m_variable_list_sp; ///< The variable list for all local,
388                                            ///static and parameter variables
389                                            ///scoped to this block.
390   bool m_parsed_block_info : 1, ///< Set to true if this block and it's children
391                                 ///have all been parsed
392       m_parsed_block_variables : 1, m_parsed_child_blocks : 1;
393 
394   // A parent of child blocks can be asked to find a sibling block given
395   // one of its child blocks
396   Block *GetSiblingForChild(const Block *child_block) const;
397 
398 private:
399   DISALLOW_COPY_AND_ASSIGN(Block);
400 };
401 
402 } // namespace lldb_private
403 
404 #endif // liblldb_Block_h_
405