[lib/inferior_control] Remove size parameter from s/w breakpoints
The size is fixed, so simplify by removing it.
Also rename "kind" parameter of Breakpoint to "size", since
that's what it is.
Tested: Run example from garnet/bin/debugserver/README.md.
fx shell debugserver 7000 /system/test/sys/debugger-test segfault
Then on host: gdb
(gdb) target extended-remote 192.168.42.72:7000
(gdb) file out/build-zircon/build-x64/system/utest/debugger/debugger.elf
(gdb) run
Change-Id: I4b8923893e6897c09c3939ef0ed1b3c3f32f1d79
diff --git a/garnet/bin/debugserver/cmd_handler.cc b/garnet/bin/debugserver/cmd_handler.cc
index cd4f72e..4f4503a 100644
--- a/garnet/bin/debugserver/cmd_handler.cc
+++ b/garnet/bin/debugserver/cmd_handler.cc
@@ -780,9 +780,14 @@
switch (type) {
case 0:
- if (insert)
- return InsertSoftwareBreakpoint(addr, kind, optional_params, std::move(callback));
- return RemoveSoftwareBreakpoint(addr, kind, std::move(callback));
+ if (kind != inferior_control::SoftwareBreakpoint::Size()) {
+ FXL_LOG(ERROR) << "zZ0: unsupported kind field: " << kind;
+ return ReplyWithError(ErrorCode::INVAL, std::move(callback));
+ }
+ if (insert) {
+ return InsertSoftwareBreakpoint(addr, optional_params, std::move(callback));
+ }
+ return RemoveSoftwareBreakpoint(addr, std::move(callback));
default:
break;
}
@@ -1306,10 +1311,10 @@
}
bool CommandHandler::InsertSoftwareBreakpoint(
- uintptr_t addr, size_t kind, const fxl::StringView& optional_params,
+ uintptr_t addr, const fxl::StringView& optional_params,
ResponseCallback callback) {
FXL_VLOG(1) << fxl::StringPrintf(
- "Insert software breakpoint at %" PRIxPTR ", kind: %lu", addr, kind);
+ "Insert software breakpoint at 0x%lx", addr);
inferior_control::Process* current_process = server_->current_process();
if (!current_process) {
@@ -1319,7 +1324,7 @@
// TODO(armansito): Handle |optional_params|.
- if (!current_process->breakpoints()->InsertSoftwareBreakpoint(addr, kind)) {
+ if (!current_process->breakpoints()->InsertSoftwareBreakpoint(addr)) {
FXL_LOG(ERROR) << "Failed to insert software breakpoint";
return ReplyWithError(ErrorCode::PERM, std::move(callback));
}
@@ -1327,10 +1332,10 @@
return ReplyOK(std::move(callback));
}
-bool CommandHandler::RemoveSoftwareBreakpoint(uintptr_t addr, size_t kind,
+bool CommandHandler::RemoveSoftwareBreakpoint(uintptr_t addr,
ResponseCallback callback) {
- FXL_VLOG(1) << fxl::StringPrintf("Remove software breakpoint at %" PRIxPTR,
- addr);
+ FXL_VLOG(1) << fxl::StringPrintf(
+ "Remove software breakpoint at 0x%lx", addr);
inferior_control::Process* current_process = server_->current_process();
if (!current_process) {
diff --git a/garnet/bin/debugserver/cmd_handler.h b/garnet/bin/debugserver/cmd_handler.h
index 617b567..5b07795 100644
--- a/garnet/bin/debugserver/cmd_handler.h
+++ b/garnet/bin/debugserver/cmd_handler.h
@@ -81,11 +81,10 @@
bool Handle_vRun(const fxl::StringView& packet, ResponseCallback callback);
// Breakpoints
- bool InsertSoftwareBreakpoint(uintptr_t addr, size_t kind,
+ bool InsertSoftwareBreakpoint(uintptr_t addr,
const fxl::StringView& optional_params,
ResponseCallback callback);
- bool RemoveSoftwareBreakpoint(uintptr_t addr, size_t kind,
- ResponseCallback callback);
+ bool RemoveSoftwareBreakpoint(uintptr_t addr, ResponseCallback callback);
// The root Server instance that owns us.
RspServer* server_; // weak
diff --git a/garnet/lib/inferior_control/breakpoint.cc b/garnet/lib/inferior_control/breakpoint.cc
index 186eb8a..e5c9774 100644
--- a/garnet/lib/inferior_control/breakpoint.cc
+++ b/garnet/lib/inferior_control/breakpoint.cc
@@ -6,36 +6,94 @@
#include <cinttypes>
+#include "garnet/lib/debugger_utils/breakpoints.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/strings/string_printf.h"
+#include "process.h"
+
namespace inferior_control {
-Breakpoint::Breakpoint(uintptr_t address, size_t kind)
- : address_(address), kind_(kind) {}
+Breakpoint::Breakpoint(uintptr_t address, size_t size)
+ : address_(address), size_(size) {}
-ProcessBreakpoint::ProcessBreakpoint(uintptr_t address, size_t kind,
+ProcessBreakpoint::ProcessBreakpoint(uintptr_t address, size_t size,
ProcessBreakpointSet* owner)
- : Breakpoint(address, kind), owner_(owner) {
+ : Breakpoint(address, size), owner_(owner) {
FXL_DCHECK(owner_);
}
-SoftwareBreakpoint::SoftwareBreakpoint(uintptr_t address, size_t kind,
+SoftwareBreakpoint::SoftwareBreakpoint(uintptr_t address,
ProcessBreakpointSet* owner)
- : ProcessBreakpoint(address, kind, owner) {}
+ : ProcessBreakpoint(address, Size(), owner) {}
SoftwareBreakpoint::~SoftwareBreakpoint() {
if (IsInserted())
Remove();
}
+size_t SoftwareBreakpoint::Size() {
+ return debugger_utils::GetBreakpointInstructionSize();
+}
+
+bool SoftwareBreakpoint::Insert() {
+ // TODO(PT-103): Handle breakpoints in unloaded solibs.
+
+ if (IsInserted()) {
+ FXL_LOG(WARNING) << "Breakpoint already inserted";
+ return false;
+ }
+
+ // Read the current contents at the address that we're about to overwrite, so
+ // that it can be restored later.
+ size_t num_bytes = Size();
+ std::vector<uint8_t> orig;
+ orig.resize(num_bytes);
+ if (!owner()->process()->ReadMemory(address(), orig.data(), num_bytes)) {
+ FXL_LOG(ERROR) << "Failed to obtain current contents of memory";
+ return false;
+ }
+
+ // Insert the breakpoint instruction.
+ const uint8_t* insn = debugger_utils::GetBreakpointInstruction();
+ if (!owner()->process()->WriteMemory(address(), insn, num_bytes)) {
+ FXL_LOG(ERROR) << "Failed to insert software breakpoint";
+ return false;
+ }
+
+ original_bytes_ = std::move(orig);
+ return true;
+}
+
+bool SoftwareBreakpoint::Remove() {
+ if (!IsInserted()) {
+ FXL_LOG(WARNING) << "Breakpoint not inserted";
+ return false;
+ }
+
+ FXL_DCHECK(original_bytes_.size() == Size());
+
+ // Restore the original contents.
+ if (!owner()->process()->WriteMemory(
+ address(), original_bytes_.data(), Size())) {
+ FXL_LOG(ERROR) << "Failed to restore original instructions";
+ return false;
+ }
+
+ original_bytes_.clear();
+ return true;
+}
+
+bool SoftwareBreakpoint::IsInserted() const {
+ return !original_bytes_.empty();
+}
+
ProcessBreakpointSet::ProcessBreakpointSet(Process* process)
: process_(process) {
FXL_DCHECK(process_);
}
-bool ProcessBreakpointSet::InsertSoftwareBreakpoint(uintptr_t address,
- size_t kind) {
+bool ProcessBreakpointSet::InsertSoftwareBreakpoint(uintptr_t address) {
if (breakpoints_.find(address) != breakpoints_.end()) {
FXL_LOG(ERROR) << fxl::StringPrintf(
"Breakpoint already inserted at address: 0x%" PRIxPTR, address);
@@ -43,7 +101,7 @@
}
std::unique_ptr<ProcessBreakpoint> breakpoint(
- new SoftwareBreakpoint(address, kind, this));
+ new SoftwareBreakpoint(address, this));
if (!breakpoint->Insert()) {
FXL_LOG(ERROR) << "Failed to insert software breakpoint";
return false;
@@ -70,9 +128,9 @@
return true;
}
-ThreadBreakpoint::ThreadBreakpoint(uintptr_t address, size_t kind,
+ThreadBreakpoint::ThreadBreakpoint(uintptr_t address, size_t size,
ThreadBreakpointSet* owner)
- : Breakpoint(address, kind), owner_(owner) {
+ : Breakpoint(address, size), owner_(owner) {
FXL_DCHECK(owner_);
}
diff --git a/garnet/lib/inferior_control/breakpoint.h b/garnet/lib/inferior_control/breakpoint.h
index 5b466f2..8bd2468 100644
--- a/garnet/lib/inferior_control/breakpoint.h
+++ b/garnet/lib/inferior_control/breakpoint.h
@@ -23,7 +23,7 @@
// Represents a breakpoint.
class Breakpoint {
public:
- Breakpoint(uintptr_t address, size_t kind);
+ Breakpoint(uintptr_t address, size_t size);
virtual ~Breakpoint() = default;
// Inserts the breakpoint at the memory address it was initialized with.
@@ -38,20 +38,20 @@
virtual bool IsInserted() const = 0;
uintptr_t address() const { return address_; }
- size_t kind() const { return kind_; }
+ size_t size() const { return size_; }
private:
Breakpoint() = default;
uintptr_t address_;
- size_t kind_;
+ size_t size_;
FXL_DISALLOW_COPY_AND_ASSIGN(Breakpoint);
};
class ProcessBreakpoint : public Breakpoint {
protected:
- ProcessBreakpoint(uintptr_t address, size_t kind,
+ ProcessBreakpoint(uintptr_t address, size_t size,
ProcessBreakpointSet* owner);
ProcessBreakpointSet* owner() const { return owner_; }
@@ -64,8 +64,10 @@
// Represents a software breakpoint.
class SoftwareBreakpoint final : public ProcessBreakpoint {
public:
- SoftwareBreakpoint(uintptr_t address, size_t kind,
- ProcessBreakpointSet* owner);
+ // Return the size in bytes of a s/w breakpoint.
+ static size_t Size();
+
+ SoftwareBreakpoint(uintptr_t address, ProcessBreakpointSet* owner);
~SoftwareBreakpoint() override;
// Breakpoint overrides
@@ -92,11 +94,9 @@
// Returns a pointer to the process that this object belongs to.
Process* process() const { return process_; }
- // Inserts a software breakpoint at the specified memory address with the
- // given kind. |kind| is an architecture dependent parameter that specifies
- // how many bytes the software breakpoint spans. Returns true on success or
- // false on failure.
- bool InsertSoftwareBreakpoint(uintptr_t address, size_t kind);
+ // Inserts a software breakpoint at the specified memory address.
+ // Returns true on success or false on failure.
+ bool InsertSoftwareBreakpoint(uintptr_t address);
// Removes the software breakpoint that was previously inserted at the given
// address. Returns false if there is an error of a breakpoint was not
@@ -114,7 +114,7 @@
class ThreadBreakpoint : public Breakpoint {
protected:
- ThreadBreakpoint(uintptr_t address, size_t kind, ThreadBreakpointSet* owner);
+ ThreadBreakpoint(uintptr_t address, size_t size, ThreadBreakpointSet* owner);
ThreadBreakpointSet* owner() const { return owner_; }
private:
@@ -151,8 +151,8 @@
// Returns a pointer to the thread that this object belongs to.
Thread* thread() const { return thread_; }
- // Inserts a single-step breakpoint at the specified memory address with the
- // given kind. |address| is recorded as the current pc value, at the moment
+ // Inserts a single-step breakpoint at the specified memory address.
+ // |address| is recorded as the current pc value, at the moment
// for bookkeeping purposes.
// Returns true on success or false on failure.
bool InsertSingleStepBreakpoint(uintptr_t address);
diff --git a/garnet/lib/inferior_control/breakpoint_arm64.cc b/garnet/lib/inferior_control/breakpoint_arm64.cc
index 730a885..5a81ce0 100644
--- a/garnet/lib/inferior_control/breakpoint_arm64.cc
+++ b/garnet/lib/inferior_control/breakpoint_arm64.cc
@@ -4,34 +4,11 @@
#include "breakpoint.h"
+#include "garnet/lib/debugger_utils/breakpoints.h"
#include "lib/fxl/logging.h"
namespace inferior_control {
-namespace {
-
-// TODO(dje): This isn't needed until we support debugserver-injected
-// breakpoints.
-// The arm64 s/w breakpoint instruction.
-// const uint32_t kBreakpoint = 0xd4200000;
-
-} // namespace
-
-bool SoftwareBreakpoint::Insert() {
- FXL_NOTIMPLEMENTED();
- return false;
-}
-
-bool SoftwareBreakpoint::Remove() {
- FXL_NOTIMPLEMENTED();
- return false;
-}
-
-bool SoftwareBreakpoint::IsInserted() const {
- FXL_NOTIMPLEMENTED();
- return false;
-}
-
bool SingleStepBreakpoint::Insert() {
FXL_NOTIMPLEMENTED();
return false;
diff --git a/garnet/lib/inferior_control/breakpoint_x64.cc b/garnet/lib/inferior_control/breakpoint_x64.cc
index 0e86503..775e3f7 100644
--- a/garnet/lib/inferior_control/breakpoint_x64.cc
+++ b/garnet/lib/inferior_control/breakpoint_x64.cc
@@ -4,6 +4,7 @@
#include "breakpoint.h"
+#include "garnet/lib/debugger_utils/breakpoints.h"
#include "lib/fxl/logging.h"
#include "process.h"
@@ -14,65 +15,6 @@
namespace {
-// The i386 Int3 instruction.
-const uint8_t kInt3 = 0xCC;
-
-} // namespace
-
-bool SoftwareBreakpoint::Insert() {
- // TODO: Handle breakpoints in unloaded solibs.
-
- if (IsInserted()) {
- FXL_LOG(WARNING) << "Breakpoint already inserted";
- return false;
- }
-
- // We only support inserting the single byte Int3 instruction.
- if (kind() != 1) {
- FXL_LOG(ERROR) << "Software breakpoint kind must be 1 on X64";
- return false;
- }
-
- // Read the current contents at the address that we're about to overwrite, so
- // that it can be restored later.
- uint8_t orig;
- if (!owner()->process()->ReadMemory(address(), &orig, 1)) {
- FXL_LOG(ERROR) << "Failed to obtain current contents of memory";
- return false;
- }
-
- // Insert the Int3 instruction.
- if (!owner()->process()->WriteMemory(address(), &kInt3, 1)) {
- FXL_LOG(ERROR) << "Failed to insert software breakpoint";
- return false;
- }
-
- original_bytes_.push_back(orig);
- return true;
-}
-
-bool SoftwareBreakpoint::Remove() {
- if (!IsInserted()) {
- FXL_LOG(WARNING) << "Breakpoint not inserted";
- return false;
- }
-
- FXL_DCHECK(original_bytes_.size() == 1);
-
- // Restore the original contents.
- if (!owner()->process()->WriteMemory(address(), original_bytes_.data(), 1)) {
- FXL_LOG(ERROR) << "Failed to restore original instructions";
- return false;
- }
-
- original_bytes_.clear();
- return true;
-}
-
-bool SoftwareBreakpoint::IsInserted() const { return !original_bytes_.empty(); }
-
-namespace {
-
// Set the TF bit in the RFLAGS register of |thread|.
bool SetRflagsTF(Thread* thread, bool enable) {