| // Copyright 2019 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_DWARF_DIE_SCANNER_H_ |
| #define SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_DWARF_DIE_SCANNER_H_ |
| |
| #include <lib/syslog/cpp/macros.h> |
| #include <stdint.h> |
| |
| #include <utility> |
| #include <vector> |
| |
| namespace llvm { |
| |
| class DWARFDebugInfoEntry; |
| class DWARFUnit; |
| |
| } // namespace llvm |
| |
| namespace zxdb { |
| |
| // This is a helper class for generating a zxdb::Index. |
| // |
| // It works in two phases. In the first, it linearly iterates through the DIEs of a unit. The |
| // calling code does: |
| // |
| // while (!scanner.done()) { |
| // current_die = scanner.Prepare(); |
| // ... work on current_die ... |
| // scanner.Advance(); |
| // } |
| // |
| // In the second phase, the scanner can provide extra information for a DIE in the unit in constant |
| // time. |
| // |
| // This class exists because in LLVM, getting the parent of a DIE used to require an inefficient |
| // linear search. Since LLVM provides a direct way to get parent index, the necessity of this class |
| // is largely elimiated. |
| class DwarfDieScanner2 { |
| public: |
| static constexpr uint32_t kNoParent = static_cast<uint32_t>(-1); |
| |
| // The unit pointer must outlive this class. |
| explicit DwarfDieScanner2(llvm::DWARFUnit* unit); |
| |
| ~DwarfDieScanner2(); |
| |
| // Call at the beginning of each iteration (when !done()) to get the current DIE. This is required |
| // to be called before Advance() as it sets some internal state. |
| const llvm::DWARFDebugInfoEntry* Prepare(); |
| |
| // Advances to the next DIE. |
| void Advance(); |
| |
| uint32_t die_index() const { return die_index_; } |
| uint32_t die_count() const { return die_count_; } |
| |
| bool done() const { return die_index_ == die_count_; } |
| |
| // Returns true if the current stack position is considered to be directly inside a function. |
| // Lexical blocks count as being inside a function, but if a new type is defined inside a function |
| // the children of that type are no longer considered to be inside a function. |
| // |
| // This is used to avoid indexing function-local variables. |
| bool is_inside_function() const { return tree_stack_.back().inside_function; } |
| |
| // Return the parent's index of a DIE in constant time. Will return kNoParent for the root. |
| uint32_t GetParentIndex(uint32_t index) const; |
| |
| private: |
| // Stores the list of parent indices according to the current depth in the tree. At any given |
| // point, the parent index of the current node will be tree_stack.back(). inside_function should |
| // be set if this node or any parent node is a function. |
| struct StackEntry { |
| StackEntry(unsigned i, bool f) : index(i), inside_function(f) {} |
| |
| unsigned index; |
| |
| // Tracks whether this node is a child of a function with no intermediate types. This is to |
| // avoid indexing local variables inside functions or inside blocks inside functions. |
| bool inside_function; |
| }; |
| |
| llvm::DWARFUnit* unit_; |
| |
| uint32_t die_count_ = 0; |
| uint32_t die_index_ = 0; |
| |
| const llvm::DWARFDebugInfoEntry* cur_die_ = nullptr; |
| |
| std::vector<StackEntry> tree_stack_; |
| }; |
| |
| } // namespace zxdb |
| |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_DWARF_DIE_SCANNER_H_ |