blob: f81f803665747dbfceae1e2272e041c132d803f1 [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_EXPR_EVAL_DWARF_EXPR_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EVAL_DWARF_EXPR_H_
#include <vector>
#include "src/developer/debug/zxdb/expr/eval_callback.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/developer/debug/zxdb/symbols/dwarf_expr_eval.h"
#include "src/lib/fxl/memory/ref_counted.h"
// This file bridges the C++/Rust expression system and the symbol system's DwarfExprEval which does
// the low-level DWARF operation evaluation of DwarfExpr objects. In the simplest case you'll want
// to evaluate a DWARF expression and get an ExprValue out. In that case, use:
//
// - DwarfExprToValue(...)
//
// There are some other uses that need more detailed control. Some code needs direct access to the
// DwarfExprEval. These cases should use one of the helper objects:
//
// - If you want an ExprValue out but need to set up some initial state on the DwarfExprEval
// before doing the evaluation, use AsyncDwarfExprEvalValue.
//
// - If you want raw access to the DwarfExprEval both before and after evaluation, use
// AsyncDwarfExprEval.
namespace zxdb {
class EvalContext;
class SymbolContext;
class Type;
// Evaluates the given DWARF expression and calls the callback with the result, using the given
// type. See file comment above.
void DwarfExprToValue(const fxl::RefPtr<EvalContext>& eval_context,
const SymbolContext& symbol_context, DwarfExpr expr, fxl::RefPtr<Type> type,
EvalCallback cb);
// Helper function which, given a completed DwarfExprEval, attempts to convert its result to the
// given type and executes the given callback.
void DwarfExprEvalToValue(const fxl::RefPtr<EvalContext>& context, DwarfExprEval& eval,
fxl::RefPtr<Type> type, EvalCallback cb);
// Manages evaluation of a DWARF expression (which might be asynchronous and need some tricky memory
// management). This keeps itself and the expression evaluator alive during the computation.
//
// See the file comment above, most callers will want one of the other variants.
//
// Example:
//
// auto eval = fxl::MakeRefCounted<AsyncDwarfExprEval>([](DwarfExprEval& eval) {
// eval->...();
// });
// eval->Eval(data_provider, expression);
//
class AsyncDwarfExprEval : public fxl::RefCountedThreadSafe<AsyncDwarfExprEval> {
public:
using DwarfEvalCallback = fit::callback<void(DwarfExprEval&, const Err& err)>;
// Allows the expression evaluator to be set up before Eval() is called for cases where it needs
// initial state.
DwarfExprEval& dwarf_eval() { return dwarf_eval_; }
// Starts evaluation. It will take a reference to itself during execution and the callback passed
// into the constructor will be issued on completion. This can only be called once.
//
// The symbol context should be the one for the module the expression came from so that addresses
// within the expression can be interpreted correctly.
void Eval(fxl::RefPtr<SymbolDataProvider> data_provider, const SymbolContext& expr_symbol_context,
DwarfExpr expr);
protected:
FRIEND_REF_COUNTED_THREAD_SAFE(AsyncDwarfExprEval);
FRIEND_MAKE_REF_COUNTED(AsyncDwarfExprEval);
explicit AsyncDwarfExprEval(DwarfEvalCallback cb) : dwarf_callback_(std::move(cb)) {}
virtual ~AsyncDwarfExprEval() = default;
private:
DwarfExprEval dwarf_eval_;
DwarfEvalCallback dwarf_callback_;
};
// Automatically converts the result of the DwarfExprEval to an EvalCallback (an error or a value).
// See the simpler DwarfExprToValue() function above for cases that don't need low-level access to
// the DwarfExprEval object.
//
// Example:
//
// auto eval = fxl::MakeRefCounted<AsyncDwarfExprEvalValue>(context, type, std::move(cb));
// ...any required setup of the dwarf_eval()...
// eval->Eval(context->GetDataProvider(), expression);
//
class AsyncDwarfExprEvalValue : public AsyncDwarfExprEval {
public:
// Call Eval() on the base class to start evaluation.
protected:
FRIEND_REF_COUNTED_THREAD_SAFE(AsyncDwarfExprEvalValue);
FRIEND_MAKE_REF_COUNTED(AsyncDwarfExprEvalValue);
// The passed-in callback will be executed if the DwarfExprEval returns success. It will have
// the given type.
AsyncDwarfExprEvalValue(const fxl::RefPtr<EvalContext>& context, fxl::RefPtr<Type> type,
EvalCallback cb);
private:
void OnEvalComplete(const Err& err);
fxl::RefPtr<EvalContext> context_;
// Not necessarily a concrete type, this is the type of the result the user will see.
fxl::RefPtr<Type> type_;
EvalCallback value_callback_;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EVAL_DWARF_EXPR_H_