blob: 2126966f8813f825a02814ed2de30af01dc8f57a [file] [log] [blame] [edit]
// 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_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EVAL_CONTEXT_H_
#include "lib/fit/function.h"
#include "src/developer/debug/zxdb/expr/eval_callback.h"
#include "src/developer/debug/zxdb/expr/expr_language.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/developer/debug/zxdb/expr/find_name.h"
#include "src/developer/debug/zxdb/expr/parsed_identifier.h"
#include "src/developer/debug/zxdb/expr/resolve_type.h"
#include "src/developer/debug/zxdb/expr/vector_register_format.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/symbol_data_provider.h"
#include "src/lib/fxl/memory/ref_counted.h"
namespace zxdb {
class Abi;
class Err;
class PrettyTypeManager;
class Symbol;
class SymbolDataProvider;
class Value;
class Variable;
// Interface used by expression evaluation to communicate with the outside world. This provides
// access to the variables currently in scope.
//
// PASSING CONVENTION
//
// Prefer to pass EvalContext function parameters as:
// const fxl::RefPtr<EvalContext>& context
// The advantage is that this will avoid an atomic refcount in most cases, but still is
// automatically ref-ed when bound in a lambda.
class EvalContext : public fxl::RefCountedThreadSafe<EvalContext> {
public:
// Callback type used to implement builtin functions.
using BuiltinFuncCallback =
fit::function<void(const fxl::RefPtr<EvalContext>& eval_context,
const std::vector<ExprValue>& params, EvalCallback cb)>;
// Returns the language associated with the expression.
virtual ExprLanguage GetLanguage() const = 0;
// The ABI defines the calling conventions on the current platform.
virtual const std::shared_ptr<Abi>& GetAbi() const = 0;
// Looks up the given name in the current context.
//
// These use the global FindName backend with our context from GetFindNameContext() below. The
// main difference is that this call additionally allows tests to inject names without setting up
// the very complex symbol system indexing.
//
// The version that returns a FoundName is the same as the one that takes an output vector but
// limits the result to 1 max.
FoundName FindName(const FindNameOptions& options, const ParsedIdentifier& identifier) const;
virtual void FindName(const FindNameOptions& options, const ParsedIdentifier& looking_for,
std::vector<FoundName>* results) const = 0;
// Returns a context for looking up names via FindName. Prefer not to use this and instead
// call EvalContext.FindName (which uses this context implicitly) because it additionally allows
// mocking.
virtual FindNameContext GetFindNameContext() const = 0;
// Issues the callback with the value of the given named value in the context of the current
// expression evaluation. This will handle things like implicit |this| members in addition to
// normal local variables.
//
// The callback also returns the Symbol associated with the variable it found. This can be used
// for diagnostics. It is possible for the symbol to be valid but the err to be set if the symbol
// was found but it could not be evaluated.
//
// The callback may be issued asynchronously in the future if communication with the remote
// debugged application is required. The callback may be issued reentrantly for synchronously
// available data.
//
// If the EvalContext is destroyed before the data is ready, the callback will not be issued.
virtual void GetNamedValue(const ParsedIdentifier& identifier, EvalCallback cb) const = 0;
// Like GetNamedValue() but takes an already-identified Variable.
//
// This will handle extern variables and will resolve them. In this case the EvalCallback's
// variable will be the resolved extern one. Otherwise it will be the input Value.
//
// The value is normally a Variable but it can also be an extern DataMember (which will transform
// into a Variable when the extern is resolved).
virtual void GetVariableValue(fxl::RefPtr<Value> variable, EvalCallback cb) const = 0;
// Checks for a builtin function with the given name. If one exists, returns a pointer to the
// callback. Returns null if it doesn't exist.
virtual const BuiltinFuncCallback* GetBuiltinFunction(const ParsedIdentifier& name) const = 0;
// Convenience wrappers around the toplevel GetConcreteType() that uses the FindNameContext()
// from this class.
fxl::RefPtr<Type> GetConcreteType(const Type* type) const {
return zxdb::GetConcreteType(GetFindNameContext(), type);
}
fxl::RefPtr<Type> GetConcreteType(const LazySymbol& symbol) const {
return zxdb::GetConcreteType(GetFindNameContext(), symbol);
}
template <typename DerivedType>
fxl::RefPtr<DerivedType> GetConcreteTypeAs(const Type* type) {
return zxdb::GetConcreteTypeAs<DerivedType>(GetFindNameContext(), type);
}
template <typename DerivedType>
fxl::RefPtr<DerivedType> GetConcreteTypeAs(const LazySymbol& symbol) {
return zxdb::GetConcreteTypeAs<DerivedType>(GetFindNameContext(), symbol);
}
// May return null (ProcessSymbols are destroyed with the process, and the EvalContext is
// refcounted and can outlive it).
virtual const ProcessSymbols* GetProcessSymbols() const = 0;
virtual fxl::RefPtr<SymbolDataProvider> GetDataProvider() = 0;
// Returns a symbolized (if possible) location for the given address.
virtual Location GetLocationForAddress(uint64_t address) const = 0;
virtual const PrettyTypeManager& GetPrettyTypeManager() const = 0;
// Returns the format to be used for converting vector registers to values.
virtual VectorRegisterFormat GetVectorRegisterFormat() const = 0;
// Returns true if base classes should automatically be promoted to derived classes (when the
// derived class is known) when pointer and references are dereferences.
virtual bool ShouldPromoteToDerived() const = 0;
protected:
// Only RefPtr should be destructing this class.
FRIEND_REF_COUNTED_THREAD_SAFE(EvalContext);
virtual ~EvalContext() = default;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EVAL_CONTEXT_H_