blob: 2452b89fa4131631659987f4e9772b1b690bd677 [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.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EVAL_CONTEXT_IMPL_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EVAL_CONTEXT_IMPL_H_
#include <optional>
#include <vector>
#include "src/developer/debug/zxdb/expr/eval_context.h"
#include "src/developer/debug/zxdb/expr/found_name.h"
#include "src/developer/debug/zxdb/expr/pretty_type_manager.h"
#include "src/developer/debug/zxdb/symbols/symbol.h"
#include "src/developer/debug/zxdb/symbols/symbol_context.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace zxdb {
class CodeBlock;
class DwarfExprEval;
class LazySymbol;
class Location;
class ProcessSymbols;
class SymbolDataProvider;
class Variable;
// An implementation of EvalContext that integrates with the DWARF symbol system. It will provide
// the values of variables currently in scope.
//
// This object is reference counted since it requires asynchronous operations in some cases. This
// means it can outlive the scope in which it was invoked (say if the thread was resumed or the
// process was killed).
//
// Generally the creator of this context will be something representing that context in the running
// program like a stack frame. This frame should call DisownContext() when it is destroyed to ensure
// that evaluation does not use any invalid context.
class EvalContextImpl : public EvalContext {
public:
// Construct with fxl::MakeRefCounted.
// EvalContext implementation.
//
// NOTE: Some of these implementations return constant values because the expression library
// doesn't have enough context to know what they should be. The ClientEvalContextImpl hooks
// some things up to the debugger settings system.
ExprLanguage GetLanguage() const override;
const std::shared_ptr<Abi>& GetAbi() const override { return abi_; }
FindNameContext GetFindNameContext() const override;
void GetNamedValue(const ParsedIdentifier& name, EvalCallback cb) const override;
void GetVariableValue(fxl::RefPtr<Value> variable, EvalCallback cb) const override;
const ProcessSymbols* GetProcessSymbols() const override;
fxl::RefPtr<SymbolDataProvider> GetDataProvider() override;
NameLookupCallback GetSymbolNameLookupCallback() override;
Location GetLocationForAddress(uint64_t address) const override;
const PrettyTypeManager& GetPrettyTypeManager() const override { return pretty_type_manager_; }
VectorRegisterFormat GetVectorRegisterFormat() const override {
return VectorRegisterFormat::kDouble;
}
bool ShouldPromoteToDerived() const override { return false; }
protected:
FRIEND_REF_COUNTED_THREAD_SAFE(EvalContextImpl);
FRIEND_MAKE_REF_COUNTED(EvalContextImpl);
// All of the input pointers can be null:
//
// - The ProcessSymbols can be a null weak pointer in which case globals will not be resolved.
// This can make testing easier and supports evaluating math without a loaded program.
//
// - The SymbolDataProvider can be null in which case anything that requires memory from the
// target will fail. Some operations like pure math don't require this.
//
// - The code block can be null in which case nothing using the current scope will work. This
// includes local variables, variables on "this", and things relative to the current namespace.
//
// The variant that takes a location will extract the code block from the location if possible.
EvalContextImpl(std::shared_ptr<Abi> abi, fxl::WeakPtr<const ProcessSymbols> process_symbols,
fxl::RefPtr<SymbolDataProvider> data_provider, ExprLanguage language,
fxl::RefPtr<CodeBlock> code_block = fxl::RefPtr<CodeBlock>());
EvalContextImpl(std::shared_ptr<Abi> abi, fxl::WeakPtr<const ProcessSymbols> process_symbols,
fxl::RefPtr<SymbolDataProvider> data_provider, const Location& location,
std::optional<ExprLanguage> force_language = std::nullopt);
~EvalContextImpl() override;
private:
// Converts an extern value to a real Variable by looking the name up in the index.
Err ResolveExternValue(const fxl::RefPtr<Value>& input_value,
fxl::RefPtr<Variable>* resolved) const;
// Computes the value of the given variable and issues the callback (possibly asynchronously,
// possibly not).
void DoResolve(FoundName found, EvalCallback cb) const;
// Implements type name lookup on the target's symbol index.
FoundName DoTargetSymbolsNameLookup(const ParsedIdentifier& ident);
std::shared_ptr<Abi> abi_;
fxl::WeakPtr<const ProcessSymbols> process_symbols_; // Possibly null.
fxl::RefPtr<SymbolDataProvider> data_provider_; // Possibly null.
// Innermost block of the current context. May be null if there is none (this means you won't get
// any local variable lookups).
fxl::RefPtr<const CodeBlock> block_;
// Language extracted from the code block.
ExprLanguage language_ = ExprLanguage::kC;
PrettyTypeManager pretty_type_manager_;
mutable fxl::WeakPtrFactory<EvalContextImpl> weak_factory_;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EVAL_CONTEXT_IMPL_H_