Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame^] | 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_ |