Atmosphere/thermosphere/src/gdb/thread.c

119 lines
3.3 KiB
C

/*
* 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 "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) {
return GDB_ReplyErrno(ctx, EILSEQ);
}
u32 coreMask = ctx->attachedCoreList;
return (coreMask & BIT(threadId)) != 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;
int n = 1;
buf[0] = 'm';
u32 coreMask = ctx->attachedCoreList;
FOREACH_BIT (tmp, coreId, coreMask) {
n += sprintf(buf + n, "%x,", 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, "m", 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);
}