blob: 9b73890ed9ffd936854110f4d7c40f25dfd07e0a [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 <optional>
#include <vector>
#include "garnet/bin/zxdb/expr/expr_eval_context.h"
#include "garnet/bin/zxdb/expr/found_variable.h"
#include "garnet/bin/zxdb/expr/symbol_variable_resolver.h"
#include "garnet/bin/zxdb/symbols/symbol.h"
#include "garnet/bin/zxdb/symbols/symbol_context.h"
#include "lib/fxl/memory/weak_ptr.h"
namespace zxdb {
class CodeBlock;
class LazySymbol;
class Location;
class ProcessSymbols;
class SymbolDataProvider;
class Variable;
// An implementation of ExprEvalContext 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 SymbolEvalContext : public ExprEvalContext {
public:
// The ProcessSymbols can be a null weak pointer in which case, globals will
// not be resolved (this can make testing easier).
SymbolEvalContext(fxl::WeakPtr<const ProcessSymbols> process_symbols,
const SymbolContext& symbol_context,
fxl::RefPtr<SymbolDataProvider> data_provider,
fxl::RefPtr<CodeBlock> code_block);
SymbolEvalContext(fxl::WeakPtr<const ProcessSymbols> process_symbols,
fxl::RefPtr<SymbolDataProvider> data_provider,
const Location& location);
~SymbolEvalContext() override;
// ExprEvalContext implementation.
void GetNamedValue(const Identifier& name, ValueCallback cb) override;
SymbolVariableResolver& GetVariableResolver() override;
fxl::RefPtr<SymbolDataProvider> GetDataProvider() override;
private:
struct SearchResult {
enum Status {
// The variable was found, the value is set and there is no Err.
kFound,
// The variable was not found. The Err object will not be set (not finding
// a variable for a given phase of lookup isn't necessarily an error).
kNotFound,
// There was a problem and evaluation should not continue. For example,
// the name may be ambiguous. The Err object will be set.
kError
};
SearchResult() = default;
SearchResult(Status s, Err e = Err(),
fxl::RefPtr<Symbol> sym = fxl::RefPtr<Symbol>())
: status(s), err(std::move(e)), symbol(std::move(sym)) {}
Status status = kNotFound;
Err err;
fxl::RefPtr<Symbol> symbol;
};
// Computes the value of the given variable and issues the callback (possibly
// asynchronously, possibly not).
void DoResolve(FoundVariable found, ValueCallback cb) const;
fxl::WeakPtr<const ProcessSymbols> process_symbols_; // Possibly null.
SymbolContext symbol_context_;
fxl::RefPtr<SymbolDataProvider> data_provider_; // Possibly null.
SymbolVariableResolver resolver_;
// 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_;
fxl::WeakPtrFactory<SymbolEvalContext> weak_factory_;
};
} // namespace zxdb