From 0b8d0035b9b1c12c42bd480bba0186eacf58aa33 Mon Sep 17 00:00:00 2001
From: TuxSH <1922548+TuxSH@users.noreply.github.com>
Date: Thu, 6 Feb 2020 21:38:01 +0000
Subject: [PATCH] =?UTF-8?q?thermosph=C3=A8re:=20C++=20gdb/regs?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
thermosphere/src/gdb/hvisor_gdb_regs.cpp | 226 +++++++++++++++++++++++
thermosphere/src/gdb/regs.c | 212 ---------------------
thermosphere/src/gdb/regs.h | 10 -
3 files changed, 226 insertions(+), 222 deletions(-)
create mode 100644 thermosphere/src/gdb/hvisor_gdb_regs.cpp
delete mode 100644 thermosphere/src/gdb/regs.c
delete mode 100644 thermosphere/src/gdb/regs.h
diff --git a/thermosphere/src/gdb/hvisor_gdb_regs.cpp b/thermosphere/src/gdb/hvisor_gdb_regs.cpp
new file mode 100644
index 000000000..f6b70c613
--- /dev/null
+++ b/thermosphere/src/gdb/hvisor_gdb_regs.cpp
@@ -0,0 +1,226 @@
+/*
+ * 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 "../exceptions.h"
+#include "../fpu.h"
+
+namespace {
+
+ auto GetRegisterPointerAndSize(unsigned long id, ExceptionStackFrame *frame, FpuRegisterCache *fpuRegCache)
+ {
+ void *outPtr = nullptr;
+ size_t outSz = 0;
+
+ switch (id) {
+ case 0 ... 30:
+ outPtr = &frame->x[id];
+ outSz = 8;
+ break;
+ case 31:
+ outPtr = exceptionGetSpPtr(frame);
+ outSz = 8;
+ break;
+ case 32:
+ outPtr = &frame->spsr_el2;
+ outSz = 4;
+ break;
+ case 33 ... 64:
+ outPtr = &fpuRegCache->q[id - 33];
+ outSz = 16;
+ break;
+ case 65:
+ outPtr = &fpuRegCache->fpsr;
+ outSz = 4;
+ break;
+ case 66:
+ outPtr = &fpuRegCache->fpcr;
+ outSz = 4;
+ break;
+ default:
+ __builtin_unreachable();
+ break;
+ }
+
+ return std::tuple{outPtr, outSz};
+ }
+
+}
+
+namespace ams::hvisor::gdb {
+
+ // Note: GDB treats cpsr, fpsr, fpcr as 32-bit integers...
+ GDB_DEFINE_HANDLER(ReadRegisters)
+ {
+ ENSURE(m_selectedCoreId == currentCoreCtx->coreId);
+
+ ExceptionStackFrame *frame = currentCoreCtx->guestFrame;
+ FpuRegisterCache *fpuRegCache = fpuReadRegisters();
+
+ char *buf = GetInPlaceOutputBuffer();
+
+ size_t n = 0;
+
+ struct {
+ u64 sp;
+ u64 pc;
+ u32 cpsr;
+ } cpuSprs = {
+ .sp = *exceptionGetSpPtr(frame),
+ .pc = frame->elr_el2,
+ .cpsr = static_cast(frame->spsr_el2),
+ };
+
+ u32 fpuSprs[2] = {
+ static_cast(fpuRegCache->fpsr),
+ static_cast(fpuRegCache->fpcr),
+ };
+
+ n += EncodeHex(buf + n, frame->x, sizeof(frame->x));
+ n += EncodeHex(buf + n, &cpuSprs, 8+8+4);
+ n += EncodeHex(buf + n, fpuRegCache->q, sizeof(fpuRegCache->q));
+ n += EncodeHex(buf + n, fpuSprs, sizeof(fpuSprs));
+
+ return SendPacket(std::string_view{buf, n});
+ }
+
+ GDB_DEFINE_HANDLER(WriteRegisters)
+ {
+ ENSURE(m_selectedCoreId == currentCoreCtx->coreId);
+
+ ExceptionStackFrame *frame = currentCoreCtx->guestFrame;
+ FpuRegisterCache *fpuRegCache = fpuGetRegisterCache();
+
+ char *tmp = GetWorkBuffer();
+
+ size_t n = 0;
+
+ struct {
+ u64 sp;
+ u64 pc;
+ u32 cpsr;
+ } cpuSprs;
+
+ u32 fpuSprs[2];
+
+ struct {
+ void *dst;
+ size_t sz;
+ } infos[4] = {
+ { frame->x, sizeof(frame->x) },
+ { &cpuSprs, 8+8+4 },
+ { fpuRegCache->q, sizeof(fpuRegCache->q) },
+ { fpuSprs, sizeof(fpuSprs) },
+ };
+
+ // Parse & return on error
+ for (const auto &info: infos) {
+ // Fuck std::string_view.substr throwing exceptions
+ if (DecodeHex(tmp + n, m_commandData.data(), info.sz) != info.sz) {
+ return ReplyErrno(EILSEQ);
+ }
+ m_commandData.remove_prefix(2 * info.sz);
+ n += info.sz;
+ }
+
+ // Copy. Note: we don't check if cpsr (spsr_el2) was modified to return to EL2...
+ n = 0;
+ for (const auto &info: infos) {
+ std::copy(tmp + n, tmp + n + info.sz, info.dst);
+ n += info.sz;
+ }
+
+ *exceptionGetSpPtr(frame) = cpuSprs.sp;
+ frame->elr_el2 = cpuSprs.pc;
+ frame->spsr_el2 = cpuSprs.cpsr;
+ fpuRegCache->fpsr = fpuSprs[0];
+ fpuRegCache->fpcr = fpuSprs[1];
+ fpuCommitRegisters();
+
+ return ReplyOk();
+ }
+
+ GDB_DEFINE_HANDLER(ReadRegister)
+ {
+ ENSURE(m_selectedCoreId == currentCoreCtx->coreId);
+
+ ExceptionStackFrame *frame = currentCoreCtx->guestFrame;
+ FpuRegisterCache *fpuRegCache = nullptr;
+
+ auto [nread, gdbRegNum] = ParseHexIntegerList<1>(m_commandData);
+ if (nread == 0) {
+ return ReplyErrno(EILSEQ);
+ }
+
+ // Check the register number
+ if (gdbRegNum >= 31 + 3 + 32 + 2) {
+ return ReplyErrno(EINVAL);
+ }
+
+ if (gdbRegNum > 31 + 3) {
+ // FPU register -- must read the FPU registers first
+ fpuRegCache = fpuReadRegisters();
+ }
+
+ return std::apply(SendHexPacket, GetRegisterPointerAndSize(gdbRegNum, frame, fpuRegCache));
+ }
+
+ GDB_DEFINE_HANDLER(WriteRegister)
+ {
+ ENSURE(m_selectedCoreId == currentCoreCtx->coreId);
+
+ char *tmp = GetWorkBuffer();
+ ExceptionStackFrame *frame = currentCoreCtx->guestFrame;
+ FpuRegisterCache *fpuRegCache = fpuGetRegisterCache();
+
+ auto [nread, gdbRegNum] = ParseHexIntegerList<1>(m_commandData, '=');
+ if (nread == 0) {
+ return ReplyErrno(EILSEQ);
+ }
+ m_commandData.remove_prefix(nread);
+
+ // Check the register number
+ if (gdbRegNum >= 31 + 3 + 32 + 2) {
+ return ReplyErrno(EINVAL);
+ }
+
+ auto [regPtr, sz] = GetRegisterPointerAndSize(gdbRegNum, frame, fpuRegCache);
+
+ // Decode, check for errors
+ if (m_commandData.size() != 2 * sz || DecodeHex(tmp, m_commandData) != sz) {
+ return ReplyErrno(EILSEQ);
+ }
+
+ std::copy(tmp, tmp + sz, regPtr);
+
+ if (gdbRegNum > 31 + 3) {
+ // FPU register -- must commit the FPU registers
+ fpuCommitRegisters();
+ }
+
+ return ReplyOk();
+ }
+
+}
diff --git a/thermosphere/src/gdb/regs.c b/thermosphere/src/gdb/regs.c
deleted file mode 100644
index 1ca3c4525..000000000
--- a/thermosphere/src/gdb/regs.c
+++ /dev/null
@@ -1,212 +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
-
-#include "../exceptions.h"
-#include "../fpu.h"
-
-#include "regs.h"
-#include "net.h"
-
-// GDB treats cpsr, fpsr, fpcr as 32-bit integers...
-
-GDB_DECLARE_HANDLER(ReadRegisters)
-{
- ENSURE(ctx->selectedThreadId == 1 + currentCoreCtx->coreId);
-
- ExceptionStackFrame *frame = currentCoreCtx->guestFrame;
- FpuRegisterCache *fpuRegCache = fpuReadRegisters();
-
- char *buf = ctx->buffer + 1;
- size_t n = 0;
-
- struct {
- u64 sp;
- u64 pc;
- u32 cpsr;
- } cpuSprs = {
- .sp = *exceptionGetSpPtr(frame),
- .pc = frame->elr_el2,
- .cpsr = (u32)frame->spsr_el2,
- };
-
- u32 fpuSprs[2] = {
- (u32)fpuRegCache->fpsr,
- (u32)fpuRegCache->fpcr,
- };
-
-
- n += GDB_EncodeHex(buf + n, frame->x, sizeof(frame->x));
- n += GDB_EncodeHex(buf + n, &cpuSprs, 8+8+4);
- n += GDB_EncodeHex(buf + n, fpuRegCache->q, sizeof(fpuRegCache->q));
- n += GDB_EncodeHex(buf + n, fpuSprs, sizeof(fpuSprs));
-
- return GDB_SendPacket(ctx, buf, n);
-}
-
-GDB_DECLARE_HANDLER(WriteRegisters)
-{
- ENSURE(ctx->selectedThreadId == 1 + currentCoreCtx->coreId);
-
- ExceptionStackFrame *frame = currentCoreCtx->guestFrame;
- FpuRegisterCache *fpuRegCache = fpuGetRegisterCache();
-
- char *buf = ctx->commandData;
- char *tmp = ctx->workBuffer;
-
- size_t n = 0;
- size_t m = 0;
-
- struct {
- u64 sp;
- u64 pc;
- u32 cpsr;
- } cpuSprs;
-
- u32 fpuSprs[2];
-
- struct {
- void *dst;
- size_t sz;
- } info[4] = {
- { frame->x, sizeof(frame->x) },
- { &cpuSprs, 8+8+4 },
- { fpuRegCache->q, sizeof(fpuRegCache->q) },
- { fpuSprs, sizeof(fpuSprs) },
- };
-
- // Parse & return on error
- for (u32 i = 0; i < 4; i++) {
- if (GDB_DecodeHex(tmp + m, buf + n, info[i].sz) != info[i].sz) {
- return GDB_ReplyErrno(ctx, EPERM);
- }
- n += 2 * info[i].sz;
- m += info[i].sz;
- }
-
- // Copy. Note: we don't check if cpsr (spsr_el2) was modified to return to EL2...
- m = 0;
- for (u32 i = 0; i < 4; i++) {
- memcpy(info[i].dst, tmp + m, info[i].sz);
- m += info[i].sz;
- }
- *exceptionGetSpPtr(frame) = cpuSprs.sp;
- frame->elr_el2 = cpuSprs.pc;
- frame->spsr_el2 = cpuSprs.cpsr;
- fpuRegCache->fpsr = fpuSprs[0];
- fpuRegCache->fpcr = fpuSprs[1];
- fpuCommitRegisters();
-
- return GDB_ReplyOk(ctx);
-}
-
-static void GDB_GetRegisterPointerAndSize(size_t *outSz, void **outPtr, unsigned long id, ExceptionStackFrame *frame, FpuRegisterCache *fpuRegCache)
-{
- switch (id) {
- case 0 ... 30:
- *outPtr = &frame->x[id];
- *outSz = 8;
- break;
- case 31:
- *outPtr = exceptionGetSpPtr(frame);
- *outSz = 8;
- break;
- case 32:
- *outPtr = &frame->spsr_el2;
- *outSz = 4;
- break;
- case 33 ... 64:
- *outPtr = &fpuRegCache->q[id - 33];
- *outSz = 16;
- case 65:
- *outPtr = &fpuRegCache->fpsr;
- *outSz = 4;
- case 66:
- *outPtr = &fpuRegCache->fpcr;
- *outSz = 4;
- default:
- __builtin_unreachable();
- return;
- }
-}
-
-GDB_DECLARE_HANDLER(ReadRegister)
-{
- ENSURE(ctx->selectedThreadId == 1 + currentCoreCtx->coreId);
-
- ExceptionStackFrame *frame = currentCoreCtx->guestFrame;
- FpuRegisterCache *fpuRegCache = NULL;
-
- unsigned long gdbRegNum;
-
- if (GDB_ParseHexIntegerList(&gdbRegNum, ctx->commandData, 1, 0) == NULL) {
- return GDB_ReplyErrno(ctx, EILSEQ);
- }
-
- // Check the register number
- if (gdbRegNum >= 31 + 3 + 32 + 2) {
- return GDB_ReplyErrno(ctx, EINVAL);
- }
-
- if (gdbRegNum > 31 + 3) {
- // FPU register -- must read the FPU registers first
- fpuRegCache = fpuReadRegisters();
- }
-
- size_t sz;
- void *regPtr;
- GDB_GetRegisterPointerAndSize(&sz, ®Ptr, gdbRegNum, frame, fpuRegCache);
-
- return GDB_SendHexPacket(ctx, regPtr, sz);
-}
-
-GDB_DECLARE_HANDLER(WriteRegister)
-{
- ENSURE(ctx->selectedThreadId == 1 + currentCoreCtx->coreId);
-
- ExceptionStackFrame *frame = currentCoreCtx->guestFrame;
- FpuRegisterCache *fpuRegCache = fpuGetRegisterCache();
-
- char *tmp = ctx->workBuffer;
- unsigned long gdbRegNum;
-
- const char *valueStart = GDB_ParseHexIntegerList(&gdbRegNum, ctx->commandData, 1, '=');
- if(valueStart == NULL || *valueStart != '=') {
- return GDB_ReplyErrno(ctx, EILSEQ);
- }
- valueStart++;
-
- // Check the register number
- if (gdbRegNum >= 31 + 3 + 32 + 2) {
- return GDB_ReplyErrno(ctx, EINVAL);
- }
-
- size_t sz;
- void *regPtr;
- GDB_GetRegisterPointerAndSize(&sz, ®Ptr, gdbRegNum, frame, fpuRegCache);
-
- // Check if we got 2 hex digits per byte
- if (strlen(valueStart) != 2 * sz) {
- return GDB_ReplyErrno(ctx, EILSEQ);
- }
-
- // Decode, check for errors
- if (GDB_DecodeHex(tmp, valueStart, sz) != sz) {
- return GDB_ReplyErrno(ctx, EILSEQ);
- }
-
- memcpy(regPtr, tmp, sz);
-
- if (gdbRegNum > 31 + 3) {
- // FPU register -- must commit the FPU registers
- fpuCommitRegisters();
- }
-
- return GDB_ReplyOk(ctx);
-}
diff --git a/thermosphere/src/gdb/regs.h b/thermosphere/src/gdb/regs.h
deleted file mode 100644
index 0f694e4f3..000000000
--- a/thermosphere/src/gdb/regs.h
+++ /dev/null
@@ -1,10 +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"