diff --git a/thermosphere/src/gdb/hvisor_gdb_comms.cpp b/thermosphere/src/gdb/hvisor_gdb_comms.cpp
index f22fb1eb5..a4efd8865 100644
--- a/thermosphere/src/gdb/hvisor_gdb_comms.cpp
+++ b/thermosphere/src/gdb/hvisor_gdb_comms.cpp
@@ -87,11 +87,12 @@ namespace ams::hvisor::gdb {
}
size_t delimPos = transportInterfaceReadDataUntil(iface, m_buffer + 1, 4 + GDB_BUF_LEN - 1, '#');
- if (m_buffer[delimPos] != '#') {
- // The packet is malformed, send a nack
+ if (m_buffer[delimPos] != '#' || delimPos == 1) {
+ // The packet is malformed, send a nack. Refuse empty packets
return WriteNack(iface);
}
+ m_commandLetter = m_buffer[1];
m_commandData = std::string_view{m_buffer + 1, delimPos};
// Read the checksum
@@ -107,6 +108,9 @@ namespace ams::hvisor::gdb {
WriteAck(iface);
}
+ // Remove command letter
+ m_commandData.remove_prefix(1);
+
// State transitions...
if (m_state < State::Attached) {
DEBUG("Received connection from GDB, now attaching...\n");
diff --git a/thermosphere/src/gdb/hvisor_gdb_stop_points.cpp b/thermosphere/src/gdb/hvisor_gdb_stop_points.cpp
new file mode 100644
index 000000000..57ef54d7d
--- /dev/null
+++ b/thermosphere/src/gdb/hvisor_gdb_stop_points.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2019-2020 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/*
+* This file is part of Luma3DS.
+* Copyright (C) 2016-2019 Aurora Wright, TuxSH
+*
+* SPDX-License-Identifier: (MIT OR GPL-2.0-or-later)
+*/
+
+#include "hvisor_gdb_defines_internal.hpp"
+#include "hvisor_gdb_packet_data.hpp"
+
+#include "../breakpoints.h"
+#include "../software_breakpoints.h"
+#include "../watchpoints.h"
+
+namespace ams::hvisor::gdb {
+
+ GDB_DEFINE_HANDLER(ToggleStopPoint)
+ {
+ bool add = m_commandLetter == 'Z';
+
+ auto [nread, kind, addr, size] = ParseHexIntegerList<3>(m_commandData, ';');
+ if (nread == 0) {
+ return ReplyErrno(EILSEQ);
+ }
+ m_commandData.remove_prefix(nread);
+
+ // We don't support cond_list
+ bool persist = m_commandData == "cmds:1";
+
+ // In theory we should reject leading zeroes in "kind". Oh well...
+
+ int res;
+ static const WatchpointLoadStoreControl kinds[3] = {
+ WatchpointLoadStoreControl_Store,
+ WatchpointLoadStoreControl_Load,
+ WatchpointLoadStoreControl_LoadStore,
+ };
+
+ switch(kind) {
+ // Software breakpoint
+ case 0: {
+ if(size != 4) {
+ return ReplyErrno(EINVAL);
+ }
+ res = add ? addSoftwareBreakpoint(addr, persist) : removeSoftwareBreakpoint(addr, false);
+ return res == 0 ? ReplyOk() : ReplyErrno(-res);
+ }
+
+ // Hardware breakpoint
+ case 1: {
+ if(size != 4) {
+ return ReplyErrno(EINVAL);
+ }
+ res = add ? addBreakpoint(addr) : removeBreakpoint(addr);
+ return res == 0 ? ReplyOk() : ReplyErrno(-res);
+ }
+
+ // Watchpoints
+ case 2:
+ case 3:
+ case 4: {
+ res = add ? addWatchpoint(addr, size, kinds[kind - 2]) : removeWatchpoint(addr, size, kinds[kind - 2]);
+ return res == 0 ? ReplyOk() : ReplyErrno(-res);
+ }
+ default: {
+ return ReplyEmpty();
+ }
+ }
+ }
+
+}
diff --git a/thermosphere/src/gdb/stop_points.c b/thermosphere/src/gdb/stop_points.c
deleted file mode 100644
index 9adf42a18..000000000
--- a/thermosphere/src/gdb/stop_points.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-* This file is part of Luma3DS.
-* Copyright (C) 2016-2019 Aurora Wright, TuxSH
-*
-* SPDX-License-Identifier: (MIT OR GPL-2.0-or-later)
-*/
-
-#include
-
-#include "context.h"
-#include "net.h"
-
-#include "../breakpoints.h"
-#include "../software_breakpoints.h"
-#include "../watchpoints.h"
-
-GDB_DECLARE_HANDLER(ToggleStopPoint)
-{
- bool add = ctx->commandData[-1] == 'Z';
- unsigned long lst[3];
-
- const char *pos = GDB_ParseHexIntegerList(lst, ctx->commandData, 3, ';');
- if (pos == NULL) {
- return GDB_ReplyErrno(ctx, EILSEQ);
- }
- bool persist = *pos != 0 && strncmp(pos, ";cmds:1", 7) == 0;
-
- // In theory we should reject leading zeroes in "kind". Oh well...
- unsigned long kind = lst[0];
- uintptr_t addr = lst[1];
- size_t size = lst[2];
-
- int res;
- static const WatchpointLoadStoreControl kinds[3] = {
- WatchpointLoadStoreControl_Store,
- WatchpointLoadStoreControl_Load,
- WatchpointLoadStoreControl_LoadStore,
- };
-
- switch(kind) {
- // Software breakpoint
- case 0: {
- if(size != 4) {
- return GDB_ReplyErrno(ctx, EINVAL);
- }
- res = add ? addSoftwareBreakpoint(addr, persist) : removeSoftwareBreakpoint(addr, false);
- return res == 0 ? GDB_ReplyOk(ctx) : GDB_ReplyErrno(ctx, -res);
- }
-
- // Hardware breakpoint
- case 1: {
- if(size != 4) {
- return GDB_ReplyErrno(ctx, EINVAL);
- }
- res = add ? addBreakpoint(addr) : removeBreakpoint(addr);
- return res == 0 ? GDB_ReplyOk(ctx) : GDB_ReplyErrno(ctx, -res);
- }
-
- // Watchpoints
- case 2:
- case 3:
- case 4: {
- res = add ? addWatchpoint(addr, size, kinds[kind - 2]) : removeWatchpoint(addr, size, kinds[kind - 2]);
- return res == 0 ? GDB_ReplyOk(ctx) : GDB_ReplyErrno(ctx, -res);
- }
- default: {
- return GDB_ReplyEmpty(ctx);
- }
- }
-}
diff --git a/thermosphere/src/gdb/stop_points.h b/thermosphere/src/gdb/stop_points.h
deleted file mode 100644
index 37e8f86b5..000000000
--- a/thermosphere/src/gdb/stop_points.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
-* This file is part of Luma3DS.
-* Copyright (C) 2016-2019 Aurora Wright, TuxSH
-*
-* SPDX-License-Identifier: (MIT OR GPL-2.0-or-later)
-*/
-
-#pragma once
-
-#include "context.h"
-
-GDB_DECLARE_HANDLER(ToggleStopPoint);