blob: 186eb8a20ce2dff1b4dea011d7b53a5b9a9739ba [file] [log] [blame]
// Copyright 2016 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.
#include "breakpoint.h"
#include <cinttypes>
#include "lib/fxl/logging.h"
#include "lib/fxl/strings/string_printf.h"
namespace inferior_control {
Breakpoint::Breakpoint(uintptr_t address, size_t kind)
: address_(address), kind_(kind) {}
ProcessBreakpoint::ProcessBreakpoint(uintptr_t address, size_t kind,
ProcessBreakpointSet* owner)
: Breakpoint(address, kind), owner_(owner) {
FXL_DCHECK(owner_);
}
SoftwareBreakpoint::SoftwareBreakpoint(uintptr_t address, size_t kind,
ProcessBreakpointSet* owner)
: ProcessBreakpoint(address, kind, owner) {}
SoftwareBreakpoint::~SoftwareBreakpoint() {
if (IsInserted())
Remove();
}
ProcessBreakpointSet::ProcessBreakpointSet(Process* process)
: process_(process) {
FXL_DCHECK(process_);
}
bool ProcessBreakpointSet::InsertSoftwareBreakpoint(uintptr_t address,
size_t kind) {
if (breakpoints_.find(address) != breakpoints_.end()) {
FXL_LOG(ERROR) << fxl::StringPrintf(
"Breakpoint already inserted at address: 0x%" PRIxPTR, address);
return false;
}
std::unique_ptr<ProcessBreakpoint> breakpoint(
new SoftwareBreakpoint(address, kind, this));
if (!breakpoint->Insert()) {
FXL_LOG(ERROR) << "Failed to insert software breakpoint";
return false;
}
breakpoints_[address] = std::move(breakpoint);
return true;
}
bool ProcessBreakpointSet::RemoveSoftwareBreakpoint(uintptr_t address) {
auto iter = breakpoints_.find(address);
if (iter == breakpoints_.end()) {
FXL_LOG(ERROR) << fxl::StringPrintf(
"No breakpoint inserted at address: 0x%" PRIxPTR, address);
return false;
}
if (!iter->second->Remove()) {
FXL_LOG(ERROR) << "Failed to remove breakpoint";
return false;
}
breakpoints_.erase(iter);
return true;
}
ThreadBreakpoint::ThreadBreakpoint(uintptr_t address, size_t kind,
ThreadBreakpointSet* owner)
: Breakpoint(address, kind), owner_(owner) {
FXL_DCHECK(owner_);
}
SingleStepBreakpoint::SingleStepBreakpoint(uintptr_t address,
ThreadBreakpointSet* owner)
: ThreadBreakpoint(address, 0 /*TODO:type?*/, owner) {}
SingleStepBreakpoint::~SingleStepBreakpoint() {
if (IsInserted())
Remove();
}
ThreadBreakpointSet::ThreadBreakpointSet(Thread* thread) : thread_(thread) {
FXL_DCHECK(thread_);
}
bool ThreadBreakpointSet::InsertSingleStepBreakpoint(uintptr_t address) {
if (single_step_breakpoint_) {
FXL_LOG(ERROR) << fxl::StringPrintf(
"S/S bkpt already inserted at 0x%" PRIxPTR
", requested address: 0x%" PRIxPTR,
single_step_breakpoint_->address(), address);
return false;
}
std::unique_ptr<ThreadBreakpoint> breakpoint(
new SingleStepBreakpoint(address, this));
if (!breakpoint->Insert()) {
FXL_LOG(ERROR) << "Failed to insert s/s bkpt";
return false;
}
single_step_breakpoint_ = std::move(breakpoint);
return true;
}
bool ThreadBreakpointSet::RemoveSingleStepBreakpoint() {
if (!single_step_breakpoint_) {
FXL_LOG(ERROR) << fxl::StringPrintf("No s/s bkpt inserted");
return false;
}
single_step_breakpoint_.reset();
return true;
}
bool ThreadBreakpointSet::SingleStepBreakpointInserted() {
return !!single_step_breakpoint_;
}
} // namespace inferior_control