blob: 0529c5f70175abfd5a6144cc2dfb7e6d68811620 [file] [log] [blame]
// 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>
namespace llvm {
class DWARFContext;
class DWARFDie;
}
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. The index contains
// things that might need to be named globally: functions, globals, and class
// statics. It does not contain function-level statics. Variables in functions
// are searched when in the context of that function, and can't be referenced
// outside of it.
//
// 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 {
private:
using Map = std::map<std::string, ModuleSymbolIndexNode>;
public:
using Iterator = Map::iterator;
using ConstIterator = Map::const_iterator;
// 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.
//
// Random code reading the index can convert a DieRef to a Symbol object
// using ModuleSymbols::IndexDieRefToSymbol().
class DieRef {
public:
explicit DieRef() : offset_(0) {}
explicit DieRef(uint32_t offset) : offset_(offset) {}
explicit DieRef(const llvm::DWARFDie& die);
uint32_t offset() const { return offset_; }
// For use by ModuleSymbols. Other callers read the DieRef comments above.
llvm::DWARFDie ToDie(llvm::DWARFContext* context) const;
private:
uint32_t offset_;
};
ModuleSymbolIndexNode();
// Makes a node pointing to one DIE.
ModuleSymbolIndexNode(const DieRef& ref);
~ModuleSymbolIndexNode();
bool empty() const { return sub_.empty() && dies_.empty(); }
const Map& sub() const { return sub_; }
const std::vector<DieRef>& dies() const { return dies_; }
// Dump DIEs 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 with the name of this node.
void AddDie(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 DIES matching this name, lists the DIEs that implement it.
// If a function or static variable has the same name as a namespace, there
// could be sub_ entries as well as dies_.
std::vector<DieRef> dies_;
};
} // namespace zxdb