| // 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. |
| |
| #pragma once |
| |
| #include <iosfwd> |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "llvm/DebugInfo/DWARF/DWARFDie.h" |
| |
| namespace llvm { |
| class DWARFContext; |
| } |
| |
| namespace zxdb { |
| |
| // One node in the ModuleSymbolIndex tree. One node represents the set of things |
| // with the same name inside a given namespace of a module. There could |
| // be multiple types of things with the same name in different compilation unit, |
| // and a single function can have multiple locations. So one one can represent |
| // many namespaces and functions. |
| class ModuleSymbolIndexNode { |
| public: |
| // A reference to a DIE that doesn't need the unit or the underlying |
| // llvm::DwarfDebugInfoEntry to be kept. This allows the discarding of the |
| // full parsed DIE structures after indexing. It can be converted back to a |
| // DIE, which will cause the DWARFUnit to be re-parsed. |
| // |
| // The offset stored in this structure is the offset from the beginning of |
| // the .debug_info section, which is the same as the offset stored in the |
| // llvm::DWARFDebugInfoEntry. |
| class DieRef { |
| public: |
| explicit DieRef() : offset_(0) {} |
| explicit DieRef(uint32_t offset) : offset_(offset) {} |
| explicit DieRef(const llvm::DWARFDie& die) : offset_(die.getOffset()) {} |
| |
| uint32_t offset() const { return offset_; } |
| |
| llvm::DWARFDie ToDie(llvm::DWARFContext* context) const; |
| |
| private: |
| uint32_t offset_; |
| }; |
| |
| ModuleSymbolIndexNode(); |
| |
| // Makes a node pointing to one function. |
| ModuleSymbolIndexNode(const DieRef& ref); |
| |
| ~ModuleSymbolIndexNode(); |
| |
| bool empty() const { return sub_.empty() && function_dies_.empty(); } |
| |
| const std::map<std::string, ModuleSymbolIndexNode>& sub() const { |
| return sub_; |
| } |
| const std::vector<DieRef>& function_dies() const { return function_dies_; } |
| |
| // Dump functions for debugging. A node does not contain its own name (this |
| // is stored in the parent's map. If printing some node other than the root, |
| // specify the name. |
| void Dump(std::ostream& out, int indent_level = 0) const; |
| void Dump(const std::string& name, std::ostream& out, |
| int indent_level = 0) const; |
| |
| // AsString is useful only in small unit tests since even a small module can |
| // have many megabytes of dump. |
| std::string AsString(int indent_level = 0) const; |
| |
| // Adds a DIE for a function with the name of this node. |
| void AddFunctionDie(const DieRef& ref); |
| |
| // Adds a child node with the given name and returns it. If one already exits |
| // with the name, returns the existing one. |
| ModuleSymbolIndexNode* AddChild(std::string&& name); |
| |
| // Adds a child to this node. If a node with this key already exists in this |
| // node, they will be merged. |
| void AddChild(std::pair<std::string, ModuleSymbolIndexNode>&& child); |
| |
| // Merges another node's children into this one. It's assumed there are no |
| // duplicate DIEs so the lists are just appended. |
| void Merge(ModuleSymbolIndexNode&& other); |
| |
| private: |
| // Performance note: The strings are all null-terminated C strings that come |
| // from the mapped DWARF data. We should use that in the map instead to avoid |
| // copying all the strings again. |
| std::map<std::string, ModuleSymbolIndexNode> sub_; |
| |
| // For any functions matching this name, lists the DIEs that implement it. |
| // If a function has the same name as a namespace, there could be sub_ |
| // entries as well as function_dies_. |
| std::vector<DieRef> function_dies_; |
| }; |
| |
| } // namespace zxdb |