| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_CODE_BLOCK_H_ |
| #define SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_CODE_BLOCK_H_ |
| |
| #include <vector> |
| |
| #include "src/developer/debug/zxdb/common/address_ranges.h" |
| #include "src/developer/debug/zxdb/symbols/arch.h" |
| #include "src/developer/debug/zxdb/symbols/symbol.h" |
| |
| namespace zxdb { |
| |
| class SymbolContext; |
| |
| // Base class for anything that has code: lexical blocks, inlined subroutines, and functions. A |
| // DWARF lexical block is represented as a CodeBlock rather than a derived type since it has no |
| // additional attributes. |
| class CodeBlock : public Symbol { |
| public: |
| // Construct with fxl::MakeRefCounted(). |
| |
| // Symbol overrides. |
| const CodeBlock* AsCodeBlock() const override; |
| |
| // The valid ranges of code for this block. In many cases there will be only one range (most |
| // functions specify DW_AT_low_pc and DW_AT_high_pc), but some blocks, especially inlined |
| // subroutines, may be at multiple discontiguous ranges in the code (DW_AT_ranges are specified). |
| // In this case, the ranges will be in sorted order. |
| // |
| // Some lexical blocks won't have location information in them. These are often strictly to hold |
| // groups of variables, each of which has their own range of validity. |
| // |
| // Function declarations will have no ranges associated with them. These aren't strictly "code |
| // blocks" but many functions won't have a declaration/implementation split and there's so much |
| // overlap it's more convenient to just have one type representing both. |
| // |
| // These ranges will be RELATIVE to the module. See GetAbsoluteCodeRanges() to get absolute |
| // addresses. |
| const AddressRanges& code_ranges() const { return code_ranges_; } |
| void set_code_ranges(AddressRanges r) { code_ranges_ = std::move(r); } |
| |
| // Retrieves the code ranges for this block in absolute addresses for the process. |
| AddressRanges GetAbsoluteCodeRanges(const SymbolContext& symbol_context) const; |
| |
| // Computes the full code range covering all sub-ranges. There can be multiple code ranges that |
| // can be discontiguous so not everything in this range is guaranteed to be inside the code block. |
| // Returns empty AddressRange if there are no code ranges. |
| AddressRange GetFullRange(const SymbolContext& symbol_context) const; |
| |
| // The code blocks (lexical blocks and inlines) that are children of this one. |
| const std::vector<LazySymbol>& inner_blocks() const { return inner_blocks_; } |
| void set_inner_blocks(std::vector<LazySymbol> ib) { inner_blocks_ = std::move(ib); } |
| |
| // Variables contained within this block. |
| const std::vector<LazySymbol>& variables() const { return variables_; } |
| void set_variables(std::vector<LazySymbol> v) { variables_ = std::move(v); } |
| |
| // Returns true if the block's code ranges contain the given address. A block with no specified |
| // range will always return true. |
| bool ContainsAddress(const SymbolContext& symbol_context, uint64_t absolute_address) const; |
| |
| // Recursively searches all children of this block for the innermost block covering the given |
| // address. Returns |this| if the current block is already the most specific, or nullptr if the |
| // current block doesn't contain the address. |
| // |
| // Whether this function will go into inlined subroutines is controlled by recurse_into_inlines. |
| // In many cases the Stack will handle expanding inlined subroutines and one would use this |
| // function to find the most specific code block in the current virtual frame. |
| const CodeBlock* GetMostSpecificChild(const SymbolContext& symbol_context, |
| uint64_t absolute_address, |
| bool recurse_into_inlines = false) const; |
| |
| // Recursively searches the containing blocks until it finds a function (physical or inline). If |
| // this code block is a function, returns |this| as a Function. Returns null on error, but this |
| // should not happen for well-formed symbols (all code should be inside functions). |
| fxl::RefPtr<Function> GetContainingFunction() const; |
| |
| // Returns the chain of inline functions to the current code block. |
| // |
| // The returned vector will go back in time. The [0] item will be the most specific function |
| // containing this code block (always GetContainingFunction(), will be = |this| if this is a |
| // function). |
| // |
| // The back "should" be the containing non-inlined function (this depends on the symbols declaring |
| // a function for the code block which they should do, but calling code shouldn't crash on |
| // malformed symbols). |
| // |
| // If the current block is not in an inline function, the returned vector will have one element. |
| std::vector<fxl::RefPtr<Function>> GetInlineChain() const; |
| |
| // Like GetInlineChain() but returns only those functions with ambiguous inline locations at the |
| // given address. If the address is at the first address of an inline routine, it's ambiguous |
| // whether the virtual location is at the first instruction of the inlined function, or at the |
| // optimized-out "call" to the inlined function. |
| // |
| // The returned vector will go back in time. The [0] item will be the most specific function |
| // containing this code block (always GetContainingFunction(), will be = |this| if this is a |
| // function). |
| // |
| // When the [0] item is ambiguous (the address is at the beginning of it), the [1] item will |
| // be the containing function (inlined or not). If that's also ambiguous, there will be a [2] |
| // item, etc. The back() item will be either a non-inlined function or a non-ambiguous inlined |
| // function. |
| std::vector<fxl::RefPtr<Function>> GetAmbiguousInlineChain(const SymbolContext& symbol_context, |
| TargetPointer absolute_address) const; |
| |
| protected: |
| FRIEND_REF_COUNTED_THREAD_SAFE(CodeBlock); |
| FRIEND_MAKE_REF_COUNTED(CodeBlock); |
| |
| explicit CodeBlock(DwarfTag tag); |
| ~CodeBlock() override; |
| |
| private: |
| AddressRanges code_ranges_; |
| std::vector<LazySymbol> inner_blocks_; |
| std::vector<LazySymbol> variables_; |
| }; |
| |
| } // namespace zxdb |
| |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_CODE_BLOCK_H_ |