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