blob: 2b44fd9f065933784f49115feb840aad74b70619 [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 <src/lib/fxl/logging.h>
#include "garnet/lib/debugger_utils/breakpoints.h"
#include "breakpoint.h"
#include "process.h"
#include "registers.h"
#include "thread.h"
namespace inferior_control {
namespace {
// Set the TF bit in the RFLAGS register of |thread|.
bool SetRflagsTF(Thread* thread, bool enable) {
Registers* registers = thread->registers();
if (!registers->RefreshGeneralRegisters()) {
FXL_LOG(ERROR) << "Failed to refresh general regs";
return false;
}
if (!registers->SetSingleStep(enable)) {
FXL_LOG(ERROR) << "Failed to set rflags.TF";
return false;
}
if (!registers->WriteGeneralRegisters()) {
FXL_LOG(ERROR) << "Failed to write general regs";
return false;
}
return true;
}
} // anonymous namespace
bool SingleStepBreakpoint::Insert() {
if (IsInserted()) {
FXL_LOG(WARNING) << "Breakpoint already inserted";
return false;
}
// TODO: Manage things like the user having already set TF.
if (!SetRflagsTF(owner()->thread(), true))
return false;
inserted_ = true;
return true;
}
bool SingleStepBreakpoint::Remove() {
if (!IsInserted()) {
FXL_LOG(WARNING) << "Breakpoint not inserted";
return false;
}
if (!SetRflagsTF(owner()->thread(), false))
return false;
inserted_ = false;
return true;
}
bool SingleStepBreakpoint::IsInserted() const { return inserted_; }
} // namespace inferior_control