blob: d920a092d49f9c4f6a8e52d4435ad301d17c5dda [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_CLIENT_MOCK_FRAME_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_MOCK_FRAME_H_
#include "src/developer/debug/ipc/records.h"
#include "src/developer/debug/shared/register_id.h"
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/symbols/arch.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/symbol_test_parent_setter.h"
#include "src/lib/fxl/memory/ref_ptr.h"
namespace zxdb {
class EvalContextImpl;
class MockSymbolDataProvider;
// Provides a MockFrame implementation that just returns constant values for everything. Tests can
// override this to implement the subset of functionality they need.
class MockFrame : public Frame {
public:
// Session and Thread can be null as long as no code that uses this object needs it.
//
// The physical frame is the non-inlined call frame associated with this one. The pointer must
// outlive this class (normally both are owned by the Stack). A null physical frame indicates that
// this is not inline.
MockFrame(Session* session, Thread* thread, const Location& location, uint64_t sp,
uint64_t cfa = 0, std::vector<debug::RegisterValue> regs = {}, uint64_t frame_base = 0,
const Frame* physical_frame = nullptr, bool is_ambiguous_inline = false);
// This variant makes a location with a mock function object of the given name and the default
// value of everything else. It's usuaully enough for many types of tests. You may pass in a raw
// string containing namespaces as in C++ (e.g. "async::Loop::Run" will turn into a parsed
// identifier with function name "Run" within two nested namespaces "async" and "Loop".
MockFrame(Session* session, Thread* thread, TargetPointer ip, TargetPointer sp,
const std::string& func_name, FileLine file_line);
// This variant is similar to the above, but takes an absolute function name as a vector of
// strings, which will mimic the namespace hierarchy of a function. The last element of this
// vector is the function name.
//
// Note: Right now all of the strings passed in |absolute_function_name| will create Namespace
// symbol objects, except for the final string which is the function name. If we ever require the
// function to be nested in a collection/lexical block/etc, this will have to be changed.
MockFrame(Session* session, Thread* thread, TargetPointer ip, TargetPointer sp,
FileLine file_line, std::vector<std::string> absolute_function_name);
~MockFrame() override;
// Use GetLocation() to retrieve the location.
void set_location(Location l) { location_ = std::move(l); }
// Overrides all IPs with a new address, but doesn't change anything else about the location
// including the stack or symbols.
void SetAddress(uint64_t address);
void SetTrust(debug_ipc::StackFrame::Trust trust);
// Overrides the location's file_line with the new value, leaving everything else as-is.
void SetFileLine(const FileLine& file_line);
void set_is_ambiguous_inline(bool ambiguous) { is_ambiguous_inline_ = ambiguous; }
MockSymbolDataProvider* GetMockSymbolDataProvider();
// Frame implementation.
Thread* GetThread() const override;
bool IsInline() const override;
const Frame* GetPhysicalFrame() const override;
const Location& GetLocation() const override;
uint64_t GetAddress() const override;
debug_ipc::StackFrame::Trust GetTrust() const override;
const std::vector<debug::RegisterValue>* GetRegisterCategorySync(
debug::RegisterCategory category) const override;
void GetRegisterCategoryAsync(
debug::RegisterCategory category, bool always_request,
fit::function<void(const Err&, const std::vector<debug::RegisterValue>&)> cb) override;
void WriteRegister(debug::RegisterID id, std::vector<uint8_t> data,
fit::callback<void(const Err&)> cb) override;
std::optional<uint64_t> GetBasePointer() const override;
void GetBasePointerAsync(fit::callback<void(uint64_t bp)> cb) override;
uint64_t GetStackPointer() const override;
uint64_t GetCanonicalFrameAddress() const override;
fxl::RefPtr<SymbolDataProvider> GetSymbolDataProvider() const override;
fxl::RefPtr<EvalContext> GetEvalContext() const override;
bool IsAmbiguousInlineLocation() const override;
private:
void MakeLocation(TargetPointer ip, const std::string& function_name, FileLine file_line,
const std::vector<std::string>& namespace_strings);
Thread* thread_;
uint64_t sp_;
uint64_t cfa_;
debug_ipc::StackFrame::Trust trust_ = debug_ipc::StackFrame::Trust::kContext;
std::vector<debug::RegisterValue> general_registers_;
uint64_t frame_base_;
const Frame* physical_frame_; // Null if non-inlined.
Location location_;
// Holds all of the parent<-child links for the symbols if specified at construction time. Empty
// if there is no hierarchy.
std::vector<SymbolTestParentSetter> parent_setters_;
mutable fxl::RefPtr<MockSymbolDataProvider> symbol_data_provider_; // Lazy.
mutable fxl::RefPtr<EvalContextImpl> eval_context_; // Lazy.
bool is_ambiguous_inline_ = false;
FXL_DISALLOW_COPY_AND_ASSIGN(MockFrame);
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_MOCK_FRAME_H_