blob: e87ec0cf192b36558b6d05904372ecf325ccc8d3 [file] [log] [blame]
// Copyright 2020 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_DEBUG_AGENT_MOCK_THREAD_HANDLE_H_
#define SRC_DEVELOPER_DEBUG_DEBUG_AGENT_MOCK_THREAD_HANDLE_H_
#include <zircon/syscalls/object.h>
#include <map>
#include "src/developer/debug/debug_agent/thread_handle.h"
namespace debug_agent {
class MockThreadHandle final : public ThreadHandle {
public:
struct WatchpointInstallation {
debug_ipc::BreakpointType type;
debug::AddressRange address_range;
};
explicit MockThreadHandle(zx_koid_t thread_koid, std::string name = std::string());
// Note that this state is always returned. The thread could have been Suspend()-ed which will
// indiate is_suspended(), but the GetState will still report the value set here.
void set_state(State s) { state_ = s; }
// Sets the values to be returned for the given register category query.
void SetRegisterCategory(debug::RegisterCategory cat, std::vector<debug::RegisterValue> values);
// Sets the information to return for the next watchpoint set.
void set_watchpoint_range_to_return(debug::AddressRange r) { watchpoint_range_to_return_ = r; }
void set_watchpoint_slot_to_return(int slot) { watchpoint_slot_to_return_ = slot; }
// Returns the number of breakpoint installs/uninstalls for the given address / total.
size_t BreakpointInstallCount(uint64_t address) const;
size_t TotalBreakpointInstallCalls() const;
size_t BreakpointUninstallCount(uint64_t address) const;
size_t TotalBreakpointUninstallCalls() const;
// Log of all watchpoint additions.
const std::vector<WatchpointInstallation>& watchpoint_installs() const {
return watchpoint_installs_;
}
// Returns the number of watchpoint installs/uninstalls for the given address / total.
size_t WatchpointInstallCount(const debug::AddressRange&) const;
size_t TotalWatchpointInstallCalls() const;
size_t WatchpointUninstallCount(const debug::AddressRange&) const;
size_t TotalWatchpointUninstallCalls() const;
// Returns the suspend count for implementing reference-counted suspension via MockSuspendHandle.
int suspend_count() const { return *suspend_count_; }
bool is_suspended() const { return suspend_count() > 0; }
bool single_step() const { return single_step_; }
// ThreadHandle implementation.
const zx::thread& GetNativeHandle() const override { return null_handle_; }
zx::thread& GetNativeHandle() override { return null_handle_; }
zx_koid_t GetKoid() const override { return thread_koid_; }
std::string GetName() const override { return name_; }
State GetState() const override { return state_; }
debug_ipc::ThreadRecord GetThreadRecord(zx_koid_t process_koid) const override;
debug_ipc::ExceptionRecord GetExceptionRecord() const override;
std::unique_ptr<SuspendHandle> Suspend() override;
bool WaitForSuspension(TickTimePoint deadline) const override;
std::optional<GeneralRegisters> GetGeneralRegisters() const override;
void SetGeneralRegisters(const GeneralRegisters& regs) override;
std::optional<DebugRegisters> GetDebugRegisters() const override;
bool SetDebugRegisters(const DebugRegisters& regs) override;
void SetSingleStep(bool single_step) override;
std::vector<debug::RegisterValue> ReadRegisters(
const std::vector<debug::RegisterCategory>& cats_to_get) const override;
std::vector<debug::RegisterValue> WriteRegisters(
const std::vector<debug::RegisterValue>& regs) override;
bool InstallHWBreakpoint(uint64_t address) override;
bool UninstallHWBreakpoint(uint64_t address) override;
std::optional<WatchpointInfo> InstallWatchpoint(debug_ipc::BreakpointType type,
const debug::AddressRange& range) override;
bool UninstallWatchpoint(const debug::AddressRange& range) override;
private:
// Always null, for returning only from the getters above.
// TODO(brettw) Remove this when the ThreadHandle no longer exposes a zx::thread getter.
static zx::thread null_handle_;
zx_koid_t thread_koid_;
std::string name_;
std::vector<debug::RegisterValue> registers_[static_cast<size_t>(debug::RegisterCategory::kLast)];
State state_;
bool single_step_ = false;
GeneralRegisters general_registers_;
DebugRegisters debug_registers_;
debug::AddressRange watchpoint_range_to_return_;
int watchpoint_slot_to_return_ = 0;
std::map<uint64_t, size_t> bp_installs_;
std::map<uint64_t, size_t> bp_uninstalls_;
std::vector<WatchpointInstallation> watchpoint_installs_;
std::map<debug::AddressRange, size_t, debug::AddressRangeBeginCmp> wp_installs_;
std::map<debug::AddressRange, size_t, debug::AddressRangeBeginCmp> wp_uninstalls_;
// Shared count modifies by the MockSuspendHandles. Positive indicates this thread is suspended.
std::shared_ptr<int> suspend_count_;
};
} // namespace debug_agent
#endif // SRC_DEVELOPER_DEBUG_DEBUG_AGENT_MOCK_THREAD_HANDLE_H_