mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 09:36:35 +00:00
thermosphere: cpp rewrite: constexpr string parsing, rewrote gdb/thread
This commit is contained in:
parent
b445fe1bf4
commit
2077062b79
9 changed files with 252 additions and 168 deletions
|
@ -27,6 +27,8 @@
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../transport_interface.h"
|
#include "../transport_interface.h"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#define _REENT_ONLY
|
#define _REENT_ONLY
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
|
||||||
|
@ -35,7 +37,7 @@
|
||||||
#define DECLARE_VERBOSE_HANDLER(name) DECLARE_HANDLER(Verbose##name)
|
#define DECLARE_VERBOSE_HANDLER(name) DECLARE_HANDLER(Verbose##name)
|
||||||
#define DECLARE_XFER_HANDLER(name) DECLARE_HANDLER(Xfer##name)
|
#define DECLARE_XFER_HANDLER(name) DECLARE_HANDLER(Xfer##name)
|
||||||
|
|
||||||
namespace ams::hyp::gdb {
|
namespace ams::hvisor::gdb {
|
||||||
|
|
||||||
struct PackedGdbHioRequest {
|
struct PackedGdbHioRequest {
|
||||||
// TODO revamp
|
// TODO revamp
|
||||||
|
@ -79,8 +81,8 @@ namespace ams::hyp::gdb {
|
||||||
|
|
||||||
u32 m_attachedCoreList = 0;
|
u32 m_attachedCoreList = 0;
|
||||||
|
|
||||||
int m_selectedThreadId = 0;
|
int m_selectedCoreId = 0;
|
||||||
int m_selectedThreadIdForContinuing = 0;
|
int m_selectedCoreIdForContinuing = 0;
|
||||||
|
|
||||||
u32 m_sentDebugEventCoreList = 0;
|
u32 m_sentDebugEventCoreList = 0;
|
||||||
u32 m_acknowledgedDebugEventCoreList = 0;
|
u32 m_acknowledgedDebugEventCoreList = 0;
|
||||||
|
@ -97,8 +99,8 @@ namespace ams::hyp::gdb {
|
||||||
|
|
||||||
size_t m_targetXmlLen = 0;
|
size_t m_targetXmlLen = 0;
|
||||||
|
|
||||||
char *m_commandData = nullptr;
|
char m_commandLetter = '\0';
|
||||||
char *m_commandEnd = nullptr;
|
std::string_view m_commandData{};
|
||||||
size_t m_lastSentPacketSize = 0ul;
|
size_t m_lastSentPacketSize = 0ul;
|
||||||
char *m_buffer = nullptr;
|
char *m_buffer = nullptr;
|
||||||
char *m_workBuffer = nullptr;
|
char *m_workBuffer = nullptr;
|
||||||
|
@ -109,11 +111,12 @@ namespace ams::hyp::gdb {
|
||||||
// Comms
|
// Comms
|
||||||
int ReceivePacket();
|
int ReceivePacket();
|
||||||
int DoSendPacket();
|
int DoSendPacket();
|
||||||
int SendPacket(const char *packetData, size_t len);
|
int SendPacket(std::string_view packetData);
|
||||||
int SendFormattedPacket(const char *packetDataFmt, ...);
|
int SendFormattedPacket(const char *packetDataFmt, ...);
|
||||||
int SendHexPacket(const void *packetData, size_t len);
|
int SendHexPacket(const void *packetData, size_t len);
|
||||||
int SendNotificationPacket(const char *packetData, size_t len);
|
int SendNotificationPacket(std::string_view packetData);
|
||||||
int SendStreamData(const char *streamData, size_t offset, size_t length, size_t totalSize, bool forceEmptyLast);
|
int SendStreamData(std::string_view streamData, size_t offset, size_t length, bool forceEmptyLast);
|
||||||
|
int ReplyOk();
|
||||||
int ReplyEmpty();
|
int ReplyEmpty();
|
||||||
int ReplyErrno(int no);
|
int ReplyErrno(int no);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "hyp_gdb_context.hpp"
|
#include "hvisor_gdb_context.hpp"
|
||||||
|
|
||||||
// 512+24 is the ideal size as IDA will try to read exactly 0x100 bytes at a time.
|
// 512+24 is the ideal size as IDA will try to read exactly 0x100 bytes at a time.
|
||||||
// IDA seems to want additional bytes as well.
|
// IDA seems to want additional bytes as well.
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#define GDB_VERBOSE_HANDLER(name) GDB_HANDLER(Verbose##name)
|
#define GDB_VERBOSE_HANDLER(name) GDB_HANDLER(Verbose##name)
|
||||||
#define GDB_XFER_HANDLER(name) GDB_HANDLER(Xfer##name)
|
#define GDB_XFER_HANDLER(name) GDB_HANDLER(Xfer##name)
|
||||||
|
|
||||||
#define GDB_DEFINE_HANDLER(name) int Context::HANDLER(name)()
|
#define GDB_DEFINE_HANDLER(name) int Context::GDB_HANDLER(name)()
|
||||||
#define GDB_DEFINE_QUERY_HANDLER(name) DEFINE_HANDLER(Query##name)
|
#define GDB_DEFINE_QUERY_HANDLER(name) GDB_DEFINE_HANDLER(Query##name)
|
||||||
#define GDB_DECLARE_VERBOSE_HANDLER(name) DEFINE_HANDLER(Verbose##name)
|
#define GDB_DECLARE_VERBOSE_HANDLER(name) GDB_DEFINE_HANDLER(Verbose##name)
|
||||||
#define GDB_DECLARE_Xfer_HANDLER(name) DEFINE_HANDLER(Xfer##name)
|
#define GDB_DECLARE_XFER_HANDLER(name) GDB_DEFINE_HANDLER(Xfer##name)
|
|
@ -16,10 +16,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "hyp_gdb_packet_data.hpp"
|
#include "hvisor_gdb_packet_data.hpp"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
namespace ams::hyp::gdb {
|
namespace ams::hvisor::gdb {
|
||||||
|
|
||||||
u8 ComputeChecksum(std::string_view packetData)
|
u8 ComputeChecksum(std::string_view packetData)
|
||||||
{
|
{
|
||||||
return std::accumulate(packetData.cbegin(), packetData.cend(), u8{0u});
|
return std::accumulate(packetData.cbegin(), packetData.cend(), u8{0u});
|
||||||
|
@ -98,4 +99,5 @@ namespace ams::hyp::gdb {
|
||||||
|
|
||||||
return dst8 - reinterpret_cast<u8 *>(dst);
|
return dst8 - reinterpret_cast<u8 *>(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
namespace ams::hyp::gdb {
|
namespace ams::hvisor::gdb {
|
||||||
|
|
||||||
constexpr unsigned long DecodeHexDigit(char src)
|
constexpr unsigned long DecodeHexDigit(char src)
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,9 @@ namespace ams::hyp::gdb {
|
||||||
{
|
{
|
||||||
unsigned long res = 0;
|
unsigned long res = 0;
|
||||||
long mult = 1;
|
long mult = 1;
|
||||||
auto errval = std::tuple{false, 0ul, str.end()};
|
auto errval = std::tuple{0ul, 0ul};
|
||||||
|
|
||||||
|
size_t total = 0;
|
||||||
|
|
||||||
if ((base == 0 && !allowPrefix) || base > 16 || str.empty()) {
|
if ((base == 0 && !allowPrefix) || base > 16 || str.empty()) {
|
||||||
return errval;
|
return errval;
|
||||||
|
@ -48,12 +50,14 @@ namespace ams::hyp::gdb {
|
||||||
return errval;
|
return errval;
|
||||||
}
|
}
|
||||||
str.remove_prefix(1);
|
str.remove_prefix(1);
|
||||||
|
++total;
|
||||||
} else if (str[0] == '-') {
|
} else if (str[0] == '-') {
|
||||||
if (!allowPrefix) {
|
if (!allowPrefix) {
|
||||||
return errval;
|
return errval;
|
||||||
}
|
}
|
||||||
str.remove_prefix(1);
|
str.remove_prefix(1);
|
||||||
mult = -1;
|
mult = -1;
|
||||||
|
++total;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str.empty()) {
|
if (str.empty()) {
|
||||||
|
@ -68,11 +72,9 @@ namespace ams::hyp::gdb {
|
||||||
} else {
|
} else {
|
||||||
str.remove_prefix(2);
|
str.remove_prefix(2);
|
||||||
base = 16;
|
base = 16;
|
||||||
|
total += 2;
|
||||||
}
|
}
|
||||||
} else if (base == 0 || str[0] == '0') {
|
} else if (base == 0 && str[0] == '0') {
|
||||||
if (!allowPrefix) {
|
|
||||||
return errval;
|
|
||||||
}
|
|
||||||
base = 8;
|
base = 8;
|
||||||
} else if (base == 0) {
|
} else if (base == 0) {
|
||||||
base = 10;
|
base = 10;
|
||||||
|
@ -92,13 +94,61 @@ namespace ams::hyp::gdb {
|
||||||
|
|
||||||
res *= base;
|
res *= base;
|
||||||
res += v;
|
res += v;
|
||||||
|
++total;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::tuple{true, res * mult, it};
|
return std::tuple{total, res * mult};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view::iterator ParseIntegerList(unsigned long *dst, std::string_view str, size_t nb, char sep, char lastSep, u32 base, bool allowPrefix);
|
template<size_t N>
|
||||||
std::string_view::iterator ParseHexIntegerList(unsigned long *dst, std::string_view str, size_t nb, char lastSep);
|
constexpr auto ParseIntegerList(std::string_view str, u32 base, bool allowPrefix, char sep, char lastSep = '\0')
|
||||||
|
{
|
||||||
|
// First element is parsed size
|
||||||
|
std::array<unsigned long, 1+N> res{ 0 };
|
||||||
|
|
||||||
|
size_t total = 0;
|
||||||
|
for (size_t i = 0; i < N && !str.empty(); i++) {
|
||||||
|
auto [nread, val] = ParseInteger(str, base, allowPrefix);
|
||||||
|
|
||||||
|
// Parse failure
|
||||||
|
if (nread == 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
str.remove_prefix(nread);
|
||||||
|
|
||||||
|
// Check separators
|
||||||
|
if (i != N - 1) {
|
||||||
|
if (str.empty() || str[0] != sep)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
str.remove_prefix(1);
|
||||||
|
++total;
|
||||||
|
} else if (i == N - 1) {
|
||||||
|
if (lastSep == '\0') && !str.empty()) {
|
||||||
|
return res;
|
||||||
|
} else if (lastSep != '\0') {
|
||||||
|
if (str.empty() || str[0] != lastSep)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
str.remove_prefix(1);
|
||||||
|
++total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total += nread;
|
||||||
|
res[1 + i] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
res[0] = total;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N>
|
||||||
|
constexpr auto ParseHexIntegerList(std::string_view str, char lastSep = '\0')
|
||||||
|
{
|
||||||
|
return ParseIntegerList<N>(str, 16, false, ',', lastSep);
|
||||||
|
}
|
||||||
|
|
||||||
u8 ComputeChecksum(std::string_view packetData);
|
u8 ComputeChecksum(std::string_view packetData);
|
||||||
size_t EncodeHex(char *dst, const void *src, size_t len);
|
size_t EncodeHex(char *dst, const void *src, size_t len);
|
147
thermosphere/src/gdb/hvisor_gdb_thread.cpp
Normal file
147
thermosphere/src/gdb/hvisor_gdb_thread.cpp
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Luma3DS.
|
||||||
|
* Copyright (C) 2016-2019 Aurora Wright, TuxSH
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: (MIT OR GPL-2.0-or-later)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "hvisor_gdb_defines_internal.hpp"
|
||||||
|
#include "hvisor_gdb_packet_data.hpp"
|
||||||
|
|
||||||
|
#include "../core_ctx.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ams::hvisor::gdb {
|
||||||
|
|
||||||
|
int ConvertTidToCoreId(unsigned long tid)
|
||||||
|
{
|
||||||
|
switch (tid) {
|
||||||
|
case ULONG_MAX:
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
return currentCoreCtx->coreId;
|
||||||
|
default:
|
||||||
|
return currentCoreCtx->coreId - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<int> ParseConvertExactlyOneTid(std::string_view str)
|
||||||
|
{
|
||||||
|
if (str.size() == 2 && str[0] == '-' && str[1] == '1') {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
auto [n, tid] = ParseHexIntegerList<1>(str);
|
||||||
|
if (n != 0 && tid < MAX_CORE + 1) {
|
||||||
|
return ConvertTidToCoreId(tid);
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hg<tid>, Hc<tid>
|
||||||
|
GDB_DEFINE_HANDLER(SetThreadId)
|
||||||
|
{
|
||||||
|
if (!m_commandData.starts_with('g') && !m_commandData.starts_with('c')) {
|
||||||
|
return ReplyErrno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
char kind = m_commandData[0];
|
||||||
|
m_commandData.remove_prefix(1);
|
||||||
|
|
||||||
|
auto coreIdOpt = ParseConvertExactlyOneTid(m_commandData);
|
||||||
|
if (!coreIdOpt) {
|
||||||
|
return ReplyErrno(EILSEQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
int coreId = *coreIdOpt;
|
||||||
|
if (kind == 'g') {
|
||||||
|
if (coreId = -1) {
|
||||||
|
return ReplyErrno(EINVAL);
|
||||||
|
}
|
||||||
|
m_selectedCoreId = coreId;
|
||||||
|
MigrateRxIrq(m_selectedCoreId);
|
||||||
|
} else {
|
||||||
|
m_selectedCoreIdForContinuing = coreId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReplyOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
GDB_DEFINE_HANDLER(IsThreadAlive)
|
||||||
|
{
|
||||||
|
int coreId = ParseConvertExactlyOneTid(m_commandData).value_or(-1);
|
||||||
|
if (coreId < 0) {
|
||||||
|
return ReplyErrno(EILSEQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the core off?
|
||||||
|
if (m_attachedCoreList & BIT(coreId)) {
|
||||||
|
return ReplyOk();
|
||||||
|
} else {
|
||||||
|
return ReplyErrno(ESRCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GDB_DEFINE_QUERY_HANDLER(CurrentThreadId)
|
||||||
|
{
|
||||||
|
return SendFormattedPacket("QC%x", 1 + currentCoreCtx->coreId);
|
||||||
|
}
|
||||||
|
|
||||||
|
GDB_DEFINE_QUERY_HANDLER(fThreadInfo)
|
||||||
|
{
|
||||||
|
// We have made our GDB packet big enough to list all the thread ids (coreIds + 1 for each coreId)
|
||||||
|
char *buf = GetInPlaceOutputBuffer();
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
for (int coreId: util::BitsOf{m_attachedCoreList}) {
|
||||||
|
n += sprintf(buf + n, "%lx,", 1u + coreId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove trailing comma
|
||||||
|
--n;
|
||||||
|
|
||||||
|
return SendStreamData(std::string_view{buf, n}, 0, n, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
GDB_DEFINE_QUERY_HANDLER(sThreadInfo)
|
||||||
|
{
|
||||||
|
// We have made our GDB packet big enough to list all the thread ids (coreIds + 1 for each coreId) in fThreadInfo
|
||||||
|
// Note: we assume GDB doesn't accept notifications during the sequence transfer...
|
||||||
|
return SendPacket("l");
|
||||||
|
}
|
||||||
|
|
||||||
|
GDB_DEFINE_QUERY_HANDLER(ThreadEvents)
|
||||||
|
{
|
||||||
|
if (m_commandData.size() != 1) {
|
||||||
|
return ReplyErrno(EILSEQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_commandData[0]) {
|
||||||
|
case '0':
|
||||||
|
m_catchThreadEvents = false;
|
||||||
|
return ReplyOk();
|
||||||
|
case '1':
|
||||||
|
m_catchThreadEvents = true;
|
||||||
|
return ReplyOk();
|
||||||
|
default:
|
||||||
|
return ReplyErrno(EILSEQ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GDB_DEFINE_QUERY_HANDLER(ThreadExtraInfo)
|
||||||
|
{
|
||||||
|
int coreId = ParseConvertExactlyOneTid(m_commandData).value_or(-1);
|
||||||
|
if (coreId < 0) {
|
||||||
|
return ReplyErrno(EILSEQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t n = sprintf(m_workBuffer, "TODO");
|
||||||
|
|
||||||
|
return SendHexPacket(m_workBuffer, n);
|
||||||
|
}
|
||||||
|
}
|
26
thermosphere/src/gdb/hvisor_gdb_thread.hpp
Normal file
26
thermosphere/src/gdb/hvisor_gdb_thread.hpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hvisor_gdb_context.hpp"
|
||||||
|
|
||||||
|
namespace ams::hvisor::gdb {
|
||||||
|
|
||||||
|
int ConvertTidToCoreId(unsigned long tid);
|
||||||
|
std::optional<int> ParseConvertExactlyOneTid(std::string_view str);
|
||||||
|
|
||||||
|
}
|
|
@ -8,8 +8,3 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
|
||||||
GDB_DECLARE_HANDLER(ReadRegisters);
|
|
||||||
GDB_DECLARE_HANDLER(WriteRegisters);
|
|
||||||
GDB_DECLARE_HANDLER(ReadRegister);
|
|
||||||
GDB_DECLARE_HANDLER(WriteRegister);
|
|
||||||
|
|
|
@ -1,119 +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 <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "thread.h"
|
|
||||||
#include "net.h"
|
|
||||||
#include "../core_ctx.h"
|
|
||||||
|
|
||||||
GDB_DECLARE_HANDLER(SetThreadId)
|
|
||||||
{
|
|
||||||
// Id = 0 means any thread
|
|
||||||
if (ctx->commandData[0] == 'g') {
|
|
||||||
if(strcmp(ctx->commandData + 1, "-1") == 0) {
|
|
||||||
return GDB_ReplyErrno(ctx, EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long id;
|
|
||||||
if (GDB_ParseHexIntegerList(&id, ctx->commandData + 1, 1, 0) == NULL) {
|
|
||||||
return GDB_ReplyErrno(ctx, EILSEQ);
|
|
||||||
} else if (id >= MAX_CORE + 1) {
|
|
||||||
return GDB_ReplyErrno(ctx, EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->selectedThreadId = id == 0 ? (int)currentCoreCtx->coreId + 1 : (int)id;
|
|
||||||
GDB_MigrateRxIrq(ctx, (u32)(ctx->selectedThreadId - 1));
|
|
||||||
return GDB_ReplyOk(ctx);
|
|
||||||
} else if (ctx->commandData[0] == 'c') {
|
|
||||||
if(strcmp(ctx->commandData + 1, "-1") == 0) {
|
|
||||||
ctx->selectedThreadIdForContinuing = -1;
|
|
||||||
} else {
|
|
||||||
unsigned long id;
|
|
||||||
if (GDB_ParseHexIntegerList(&id, ctx->commandData + 1, 1, 0) == NULL) {
|
|
||||||
return GDB_ReplyErrno(ctx, EILSEQ);
|
|
||||||
} else if (id >= MAX_CORE + 1) {
|
|
||||||
return GDB_ReplyErrno(ctx, EINVAL);
|
|
||||||
}
|
|
||||||
ctx->selectedThreadIdForContinuing = id == 0 ? (int)currentCoreCtx->coreId + 1 : (int)id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GDB_ReplyOk(ctx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return GDB_ReplyErrno(ctx, EPERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
GDB_DECLARE_HANDLER(IsThreadAlive)
|
|
||||||
{
|
|
||||||
unsigned long threadId;
|
|
||||||
|
|
||||||
if (GDB_ParseHexIntegerList(&threadId, ctx->commandData, 1, 0) == NULL || threadId < 1) {
|
|
||||||
return GDB_ReplyErrno(ctx, EILSEQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 coreMask = ctx->attachedCoreList;
|
|
||||||
return (coreMask & BIT(threadId - 1)) != 0 ? GDB_ReplyOk(ctx) : GDB_ReplyErrno(ctx, ESRCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(CurrentThreadId)
|
|
||||||
{
|
|
||||||
return GDB_SendFormattedPacket(ctx, "QC%x", 1 + currentCoreCtx->coreId);
|
|
||||||
}
|
|
||||||
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(fThreadInfo)
|
|
||||||
{
|
|
||||||
// We have made our GDB packet big enough to list all the thread ids (coreIds + 1 for each coreId)
|
|
||||||
char *buf = ctx->buffer + 1;
|
|
||||||
size_t n = 0;
|
|
||||||
|
|
||||||
u32 coreMask = ctx->attachedCoreList;
|
|
||||||
|
|
||||||
FOREACH_BIT (tmp, coreId, coreMask) {
|
|
||||||
n += sprintf(buf + n, "%lx,", 1 + coreId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove trailing comma
|
|
||||||
buf[--n] = 0;
|
|
||||||
|
|
||||||
return GDB_SendStreamData(ctx, buf, 0, n, n, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(sThreadInfo)
|
|
||||||
{
|
|
||||||
// We have made our GDB packet big enough to list all the thread ids (coreIds + 1 for each coreId) in fThreadInfo
|
|
||||||
// Note: we assume GDB doesn't accept notifications during the sequence transfer...
|
|
||||||
return GDB_SendPacket(ctx, "l", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(ThreadEvents)
|
|
||||||
{
|
|
||||||
switch (ctx->commandData[0]) {
|
|
||||||
case '0':
|
|
||||||
ctx->catchThreadEvents = false;
|
|
||||||
return GDB_ReplyOk(ctx);
|
|
||||||
case '1':
|
|
||||||
ctx->catchThreadEvents = true;
|
|
||||||
return GDB_ReplyOk(ctx);
|
|
||||||
default:
|
|
||||||
return GDB_ReplyErrno(ctx, EILSEQ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(ThreadExtraInfo)
|
|
||||||
{
|
|
||||||
unsigned long id;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if(GDB_ParseHexIntegerList(&id, ctx->commandData, 1, 0) == NULL)
|
|
||||||
return GDB_ReplyErrno(ctx, EILSEQ);
|
|
||||||
|
|
||||||
n = sprintf(ctx->workBuffer, "TODO");
|
|
||||||
|
|
||||||
return GDB_SendHexPacket(ctx, ctx->workBuffer, n);
|
|
||||||
}
|
|
|
@ -1,20 +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(SetThreadId);
|
|
||||||
GDB_DECLARE_HANDLER(IsThreadAlive);
|
|
||||||
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(CurrentThreadId);
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(fThreadInfo);
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(sThreadInfo);
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(ThreadEvents);
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(ThreadExtraInfo);
|
|
||||||
GDB_DECLARE_QUERY_HANDLER(GetTLSAddr);
|
|
Loading…
Reference in a new issue