blob: 401305c4d52f3fc69fc51d62164cba2ffbcfe46f [file] [log] [blame]
// 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_INDEX_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_INDEX_H_
#include <iosfwd>
#include <map>
#include <string>
#include <string_view>
#include "src/developer/debug/zxdb/symbols/identifier.h"
#include "src/developer/debug/zxdb/symbols/index_node.h"
#include "src/lib/fxl/macros.h"
namespace llvm {
class DWARFCompileUnit;
class DWARFContext;
class DWARFDie;
class DWARFUnit;
namespace object {
class ObjectFile;
} // namespace object
} // namespace llvm
namespace zxdb {
class Index {
public:
Index() = default;
~Index() = default;
// This function takes an object file rather than a context so it can create its own context, and
// then discard the context when it's done. Since most debugging information is not needed after
// indexing, this saves a lot of memory.
//
// Normal callers will want to use the fast path (which internally falls back to the slow path
// for cross unit references). Tests can set the force_slow_path flag to cause everything to be
// indexed with the slow path for validation purposes.
void CreateIndex(llvm::object::ObjectFile* object_file, bool force_slow_path = false);
// Dumps the file index to the stream for debugging.
void DumpFileIndex(std::ostream& out) const;
// Takes a fully-qualified name with namespaces and classes and template parameters and returns
// the list of symbols which match exactly.
//
// TODO(bug 36754) it would be nice if this could be deleted and all code go through
// expr/find_name.h to query the index. As-is this duplicates some of FindName's logic in a less
// flexible way.
std::vector<IndexNode::SymbolRef> FindExact(const Identifier& input) const;
// Looks up the name in the file index and returns the set of matches. The name is matched from
// the right side with a left boundary of either a slash or the beginning of the full path. This
// may match more than one file name, and the caller is left to decide which one(s) it wants.
std::vector<std::string> FindFileMatches(std::string_view name) const;
// Same as FindFileMatches but does a prefix search. This only matches the file name component
// (not directory paths).
//
// In the future it would be nice to match directories if there was a "/".
std::vector<std::string> FindFilePrefixes(const std::string& prefix) const;
// Looks up the given exact file path and returns all compile units it appears in. The file must
// be an exact match (normally it's one of the results from FindFileMatches).
//
// The contents of the vector are indices into the compilation unit array. (see
// llvm::DWARFContext::getCompileUnitAtIndex).
const std::vector<unsigned>* FindFileUnitIndices(const std::string& name) const;
// See main_functions_ below.
const std::vector<IndexNode::SymbolRef>& main_functions() const { return main_functions_; }
std::vector<IndexNode::SymbolRef>& main_functions() { return main_functions_; }
const IndexNode& root() const { return root_; }
IndexNode& root() { return root_; }
size_t files_indexed() const { return file_name_index_.size(); }
// Returns how many symbols are indexed. This iterates through everything so can be slow.
size_t CountSymbolsIndexed() const;
private:
void IndexCompileUnit(llvm::DWARFContext* context, llvm::DWARFUnit* unit, unsigned unit_index,
bool force_slow_path);
void IndexCompileUnitSourceFiles(llvm::DWARFContext* context, llvm::DWARFUnit* unit,
unsigned unit_index);
// Populates the file_name_index_ given a now-unchanging files_ map.
void IndexFileNames();
// Symbol index.
IndexNode root_ = IndexNode(IndexNode::Kind::kRoot);
// Maps full path names to compile units that reference them. This must not be mutated once the
// file_name_index_ is built.
//
// The contents of the vector are indices into the compilation unit array. (see
// llvm::DWARFContext::getCompileUnitAtIndex). These are "unsigned" type because that's what LLVM
// uses for these indices.
//
// This is a map, not a multimap, because some files will appear in many compilation units. I
// suspect it's better to avoid duplicating the names (like a multimap would) and eating the cost
// of indirect heap allocations for vectors in the single-item case.
using FileIndex = std::map<std::string, std::vector<unsigned>>;
FileIndex files_;
// Maps the last file name component (the part following the last slash) to the set of entries in
// the files_ index that have that name.
//
// This is a multimap because the name parts will generally be unique so we should get few
// duplicates. The cost of using a vector for most items containing one element becomes higher in
// that case.
using FileNameIndex = std::multimap<std::string_view, FileIndex::const_iterator>;
FileNameIndex file_name_index_;
// All references to functions in this module found annotated with the DW_AT_main_subprogram
// attribute. Normally there will be 0 (not all compiler annotate this) or 1.
std::vector<IndexNode::SymbolRef> main_functions_;
FXL_DISALLOW_COPY_AND_ASSIGN(Index);
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_INDEX_H_