|  | // 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; | 
|  | 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(fxl::WeakPtr<const ProcessSymbols> process_symbols, | 
|  | fxl::RefPtr<SymbolDataProvider> data_provider, ExprLanguage language, | 
|  | fxl::RefPtr<CodeBlock> code_block = fxl::RefPtr<CodeBlock>()); | 
|  | EvalContextImpl(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); | 
|  |  | 
|  | 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_ |