Compare commits

...

4 Commits

Author SHA1 Message Date
λP.(P izzy) 8f499819ae
Merge c2b2dc70b6 into 7ac2eb2d71 2024-09-18 01:14:56 -03:00
RSDuck 7ac2eb2d71 attempt at fixing Windows build 2024-09-15 07:38:28 +02:00
RSDuck a3d696121e rework gdb packet parsing
it should be a bit more robust now
2024-09-15 07:30:53 +02:00
izder456 c2b2dc70b6 allow build with ENABLE_JIT=ON on OpenBSD Targets 2024-05-27 12:21:04 -05:00
6 changed files with 193 additions and 252 deletions

View File

@ -82,6 +82,8 @@
#define CONTEXT_PC uc_mcontext.mc_rip #define CONTEXT_PC uc_mcontext.mc_rip
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
#define CONTEXT_PC uc_mcontext.__gregs[_REG_RIP] #define CONTEXT_PC uc_mcontext.__gregs[_REG_RIP]
#elif defined(_OpenBSD__)
#define CONTEXT_PC sc_rip
#endif #endif
#elif defined(__aarch64__) #elif defined(__aarch64__)
#if defined(_WIN32) #if defined(_WIN32)
@ -94,6 +96,8 @@
#define CONTEXT_PC uc_mcontext.mc_gpregs.gp_elr #define CONTEXT_PC uc_mcontext.mc_gpregs.gp_elr
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
#define CONTEXT_PC uc_mcontext.__gregs[_REG_PC] #define CONTEXT_PC uc_mcontext.__gregs[_REG_PC]
#elif defined(_OpenBSD__)
#define CONTEXT_PC sc_exr
#endif #endif
#endif #endif

View File

@ -1,12 +1,13 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <string.h>
#include "../CRC32.h" #include "../CRC32.h"
#include "../Platform.h" #include "../Platform.h"
#include "hexutil.h" #include "hexutil.h"
#include "GdbProto.h" #include "GdbStub.h"
using namespace melonDS; using namespace melonDS;
using Platform::Log; using Platform::Log;
@ -878,6 +879,7 @@ ExecResult GdbStub::Handle_v_Stopped(GdbStub* stub, const u8* cmd, ssize_t len)
ExecResult GdbStub::Handle_v_MustReplyEmpty(GdbStub* stub, const u8* cmd, ssize_t len) ExecResult GdbStub::Handle_v_MustReplyEmpty(GdbStub* stub, const u8* cmd, ssize_t len)
{ {
printf("must reply empty\n");
stub->Resp(NULL, 0); stub->Resp(NULL, 0);
return ExecResult::Ok; return ExecResult::Ok;
} }
@ -886,6 +888,7 @@ ExecResult GdbStub::Handle_v_Cont(GdbStub* stub, const u8* cmd, ssize_t len)
{ {
if (len < 1) if (len < 1)
{ {
printf("insufficient length");
stub->RespStr("E01"); stub->RespStr("E01");
return ExecResult::Ok; return ExecResult::Ok;
} }
@ -902,6 +905,7 @@ ExecResult GdbStub::Handle_v_Cont(GdbStub* stub, const u8* cmd, ssize_t len)
stub->RespStr("OK"); stub->RespStr("OK");
return ExecResult::MustBreak; return ExecResult::MustBreak;
default: default:
printf("invalid continue %c %s\n", cmd[0], cmd);
stub->RespStr("E01"); stub->RespStr("E01");
return ExecResult::Ok; return ExecResult::Ok;
} }

View File

@ -5,12 +5,14 @@
#include <winsock2.h> #include <winsock2.h>
#endif #endif
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <algorithm>
#ifndef _WIN32 #ifndef _WIN32
#include <poll.h> #include <poll.h>
@ -21,8 +23,7 @@
#include "../Platform.h" #include "../Platform.h"
#include "hexutil.h" #include "hexutil.h"
#include "GdbProto.h" #include "GdbStub.h"
using namespace melonDS; using namespace melonDS;
using Platform::Log; using Platform::Log;
@ -42,87 +43,128 @@ namespace Gdb
* vKill;pid * vKill;pid
* qRcmd? qSupported? * qRcmd? qSupported?
*/ */
u8 Cmdbuf[GDBPROTO_BUFFER_CAPACITY];
ssize_t Cmdlen;
namespace Proto
Gdb::ReadResult GdbStub::TryParsePacket(size_t start, size_t& packetStart, size_t& packetSize, size_t& packetContentSize)
{ {
RecvBuffer[RecvBufferFilled] = '\0';
u8 PacketBuf[GDBPROTO_BUFFER_CAPACITY]; //Log(LogLevel::Debug, "[GDB] Trying to parse packet %s %d %d\n", &RecvBuffer[0], start, RecvBufferFilled);
u8 RespBuf[GDBPROTO_BUFFER_CAPACITY+5]; size_t i = start;
while (i < RecvBufferFilled)
ReadResult MsgRecv(int connfd, u8 cmd_dest[/*static GDBPROTO_BUFFER_CAPACITY*/]) {
{ char curChar = RecvBuffer[i++];
static ssize_t dataoff = 0; if (curChar == '\x04') return ReadResult::Eof;
else if (curChar == '\x03')
ssize_t recv_total = dataoff;
ssize_t cksumoff = -1;
u8 sum = 0;
bool first = true;
//printf("--- dataoff=%zd\n", dataoff);
if (dataoff != 0) {
printf("--- got preexisting: %s\n", PacketBuf);
ssize_t datastart = 0;
while (true)
{ {
if (PacketBuf[datastart] == '\x04') return ReadResult::Eof; packetStart = i - 1;
else if (PacketBuf[datastart] == '+' || PacketBuf[datastart] == '-') packetSize = packetContentSize = 1;
return ReadResult::Break;
}
else if (curChar == '+' || curChar == '-') continue;
else if (curChar == '$')
{
packetStart = i;
uint8_t checksumGot = 0;
while (i < RecvBufferFilled)
{ {
/*if (PacketBuf[datastart] == '+') SendAck(connfd); curChar = RecvBuffer[i];
else SendNak(connfd);*/ if (curChar == '#' && i + 2 < RecvBufferFilled)
++datastart; {
continue; u8 checksumShould = (hex2nyb(RecvBuffer[i+1]) << 4)
} | hex2nyb(RecvBuffer[i+2]);
else if (PacketBuf[datastart] == '$')
{ Log(LogLevel::Debug, "[GDB] found pkt, checksumGot: %02x vs %02x\n", checksumShould, checksumGot);
++datastart;
break; if (checksumShould != checksumGot)
} {
else return ReadResult::CksumErr;
{ }
__builtin_trap();
return ReadResult::Wut; packetContentSize = i - packetStart;
packetSize = packetContentSize + 3;
return ReadResult::CmdRecvd;
}
else
{
checksumGot += curChar;
}
i++;
} }
} }
printf("--- datastart=%zd\n", datastart); else
for (ssize_t i = datastart; i < dataoff; ++i)
{ {
if (PacketBuf[i] == '#') Log(LogLevel::Error, "[GDB] Received unknown character %c (%d)\n", curChar, curChar);
{ return ReadResult::Wut;
cksumoff = i + 1;
printf("--- cksumoff=%zd\n", cksumoff);
break;
}
sum += PacketBuf[i];
}
if (cksumoff >= 0)
{
recv_total = dataoff - datastart + 1;
dataoff = cksumoff + 2 - datastart + 1;
cksumoff -= datastart - 1;
memmove(&PacketBuf[1], &PacketBuf[datastart], recv_total);
PacketBuf[0] = '$';
PacketBuf[recv_total] = 0;
printf("=== cksumoff=%zi recv_total=%zi datastart=%zi dataoff=%zi\n==> %s\n",
cksumoff, recv_total, datastart, dataoff, PacketBuf);
//break;
} }
} }
while (cksumoff < 0) return ReadResult::NoPacket;
{ }
u8* pkt = &PacketBuf[dataoff];
ssize_t n, blehoff = 0;
memset(pkt, 0, sizeof(PacketBuf) - dataoff); Gdb::ReadResult GdbStub::ParseAndSetupPacket()
{
// This complicated logic seems to be unfortunately necessary
// to handle the case of packet resends when we answered too slowly.
// GDB only expects a single response (as it assumes the previous packet was dropped)
size_t i = 0;
size_t prevPacketStart = SIZE_MAX, prevPacketSize, prevPacketContentSize;
size_t packetStart, packetSize, packetContentSize;
ReadResult result, prevResult;
while (true)
{
ReadResult result = TryParsePacket(i, packetStart, packetSize, packetContentSize);
if (result == ReadResult::NoPacket)
break;
if (result != ReadResult::CmdRecvd && result != ReadResult::Break)
return result;
// looks like there is a different packet coming up
// so we quit here
if (prevPacketStart != SIZE_MAX &&
(packetContentSize != prevPacketContentSize ||
memcmp(&RecvBuffer[packetStart], &RecvBuffer[prevPacketStart], prevPacketContentSize) != 0))
{
Log(LogLevel::Debug, "[GDB] found differing packet further back %zu %zu\n", packetContentSize, prevPacketContentSize);
break;
}
i = packetStart + packetSize;
prevPacketStart = packetStart;
prevPacketSize = packetSize;
prevPacketContentSize = packetContentSize;
prevResult = result;
}
if (prevPacketStart != SIZE_MAX)
{
memcpy(&Cmdbuf[0], &RecvBuffer[prevPacketStart], prevPacketContentSize);
Cmdbuf[prevPacketContentSize] = '\0';
Cmdlen = static_cast<ssize_t>(prevPacketContentSize);
RecvBufferFilled -= prevPacketStart + prevPacketSize;
if (RecvBufferFilled > 0)
memmove(&RecvBuffer[0], &RecvBuffer[prevPacketStart + prevPacketSize], RecvBufferFilled);
assert(prevResult == ReadResult::CmdRecvd || prevResult == ReadResult::Break);
return prevResult;
}
assert(result == ReadResult::NoPacket);
return ReadResult::NoPacket;
}
ReadResult GdbStub::MsgRecv()
{
{
ReadResult result = ParseAndSetupPacket();
if (result != ReadResult::NoPacket)
return result;
}
bool first = true;
while (true)
{
int flag = 0; int flag = 0;
#if MOCKTEST #if MOCKTEST
static bool FIRST = false; static bool FIRST = false;
@ -142,113 +184,35 @@ ReadResult MsgRecv(int connfd, u8 cmd_dest[/*static GDBPROTO_BUFFER_CAPACITY*/])
#else #else
#ifndef _WIN32 #ifndef _WIN32
if (first) flag |= MSG_DONTWAIT; if (first) flag |= MSG_DONTWAIT;
n = recv(connfd, pkt, sizeof(PacketBuf) - dataoff, flag); ssize_t receivedNum = recv(ConnFd, &RecvBuffer[RecvBufferFilled], sizeof(RecvBuffer) - RecvBufferFilled, flag);
Log(LogLevel::Debug, "[GDB] receiving from stream %d\n", receivedNum);
#else #else
// fuck windows // fuck windows
n = recv(connfd, (char*)pkt, sizeof(PacketBuf) - dataoff, flag); ssize_t receivedNum = recv(ConnFd, (char*)&RecvBuffer[RecvBufferFilled], sizeof(RecvBuffer) - RecvBufferFilled, flag);
#endif #endif
#endif #endif
if (n <= 0) if (receivedNum <= 0)
{ {
if (first) return ReadResult::NoPacket; if (first) return ReadResult::NoPacket;
else else
{ {
Log(LogLevel::Debug, "[GDB] recv() error %zi, errno=%d (%s)\n", n, errno, strerror(errno)); Log(LogLevel::Debug, "[GDB] recv() error %zi, errno=%d (%s)\n", receivedNum, errno, strerror(errno));
return ReadResult::Eof; return ReadResult::Eof;
} }
} }
RecvBufferFilled += static_cast<u32>(receivedNum);
Log(LogLevel::Debug, "[GDB] recv() %zd bytes: '%s' (%02x)\n", n, pkt, pkt[0]); ReadResult result = ParseAndSetupPacket();
first = false; if (result != ReadResult::NoPacket)
return result;
do
{
if (dataoff == 0)
{
if (pkt[blehoff] == '\x04') return ReadResult::Eof;
else if (pkt[blehoff] == '\x03') return ReadResult::Break;
else if (pkt[blehoff] != '$')
{
++blehoff;
--n;
}
else break;
if (n == 0) goto next_outer;
}
}
while (true);
if (blehoff > 0)
{
memmove(pkt, &pkt[blehoff], n - blehoff + 1);
n -= blehoff - 1; // ???
}
recv_total += n;
Log(LogLevel::Debug, "[GDB] recv() after skipping: n=%zd, recv_total=%zd\n", n, recv_total);
for (ssize_t i = (dataoff == 0) ? 1 : 0; i < n; ++i)
{
u8 v = pkt[i];
if (v == '#')
{
cksumoff = dataoff + i + 1;
break;
}
sum += pkt[i];
}
if (cksumoff < 0)
{
// oops, need more data
dataoff += n;
}
next_outer:;
} }
u8 ck = (hex2nyb(PacketBuf[cksumoff+0]) << 4)
| hex2nyb(PacketBuf[cksumoff+1]);
Log(LogLevel::Debug, "[GDB] got pkt, checksum: %02x vs %02x\n", ck, sum);
if (ck != sum)
{
//__builtin_trap();
return ReadResult::CksumErr;
}
if (cksumoff + 2 > recv_total)
{
Log(LogLevel::Error, "[GDB] BIG MISTAKE: %zi > %zi which shouldn't happen!\n", cksumoff + 2, recv_total);
//__builtin_trap();
return ReadResult::Wut;
}
else
{
Cmdlen = cksumoff - 2;
memcpy(Cmdbuf, &PacketBuf[1], Cmdlen);
Cmdbuf[Cmdlen] = 0;
if (cksumoff + 2 < recv_total) {
// huh, we have the start of the next packet
dataoff = recv_total - (cksumoff + 2);
memmove(PacketBuf, &PacketBuf[cksumoff + 2], (size_t)dataoff);
PacketBuf[dataoff] = 0;
Log(LogLevel::Debug, "[GDB] got more: cksumoff=%zd, recvtotal=%zd, remain=%zd\n==> %s\n", cksumoff, recv_total, dataoff, PacketBuf);
}
else dataoff = 0;
}
return ReadResult::CmdRecvd;
} }
int SendAck(int connfd) int GdbStub::SendAck()
{ {
if (NoAck) return 1;
Log(LogLevel::Debug, "[GDB] send ack\n"); Log(LogLevel::Debug, "[GDB] send ack\n");
u8 v = '+'; u8 v = '+';
#if MOCKTEST #if MOCKTEST
@ -257,14 +221,16 @@ int SendAck(int connfd)
#ifdef _WIN32 #ifdef _WIN32
// fuck windows // fuck windows
return send(connfd, (const char*)&v, 1, 0); return send(ConnFd, (const char*)&v, 1, 0);
#else #else
return send(connfd, &v, 1, 0); return send(ConnFd, &v, 1, 0);
#endif #endif
} }
int SendNak(int connfd) int GdbStub::SendNak()
{ {
if (NoAck) return 1;
Log(LogLevel::Debug, "[GDB] send nak\n"); Log(LogLevel::Debug, "[GDB] send nak\n");
u8 v = '-'; u8 v = '-';
#if MOCKTEST #if MOCKTEST
@ -273,13 +239,13 @@ int SendNak(int connfd)
#ifdef _WIN32 #ifdef _WIN32
// fuck windows // fuck windows
return send(connfd, (const char*)&v, 1, 0); return send(ConnFd, (const char*)&v, 1, 0);
#else #else
return send(connfd, &v, 1, 0); return send(ConnFd, &v, 1, 0);
#endif #endif
} }
int WaitAckBlocking(int connfd, u8* ackp, int to_ms) int GdbStub::WaitAckBlocking(u8* ackp, int to_ms)
{ {
#if MOCKTEST #if MOCKTEST
*ackp = '+'; *ackp = '+';
@ -289,18 +255,18 @@ int WaitAckBlocking(int connfd, u8* ackp, int to_ms)
#ifdef _WIN32 #ifdef _WIN32
fd_set infd, outfd, errfd; fd_set infd, outfd, errfd;
FD_ZERO(&infd); FD_ZERO(&outfd); FD_ZERO(&errfd); FD_ZERO(&infd); FD_ZERO(&outfd); FD_ZERO(&errfd);
FD_SET(connfd, &infd); FD_SET(ConnFd, &infd);
struct timeval to; struct timeval to;
to.tv_sec = to_ms / 1000; to.tv_sec = to_ms / 1000;
to.tv_usec = (to_ms % 1000) * 1000; to.tv_usec = (to_ms % 1000) * 1000;
int r = select(connfd+1, &infd, &outfd, &errfd, &to); int r = select(ConnFd+1, &infd, &outfd, &errfd, &to);
if (FD_ISSET(connfd, &errfd)) return -1; if (FD_ISSET(ConnFd, &errfd)) return -1;
else if (FD_ISSET(connfd, &infd)) else if (FD_ISSET(ConnFd, &infd))
{ {
r = recv(connfd, (char*)ackp, 1, 0); r = recv(ConnFd, (char*)ackp, 1, 0);
if (r < 0) return r; if (r < 0) return r;
return 0; return 0;
} }
@ -309,7 +275,7 @@ int WaitAckBlocking(int connfd, u8* ackp, int to_ms)
#else #else
struct pollfd pfd; struct pollfd pfd;
pfd.fd = connfd; pfd.fd = ConnFd;
pfd.events = POLLIN; pfd.events = POLLIN;
pfd.revents = 0; pfd.revents = 0;
@ -319,14 +285,14 @@ int WaitAckBlocking(int connfd, u8* ackp, int to_ms)
if (pfd.revents & (POLLHUP|POLLERR)) return -69; if (pfd.revents & (POLLHUP|POLLERR)) return -69;
r = recv(connfd, ackp, 1, 0); r = recv(ConnFd, ackp, 1, 0);
if (r < 0) return r; if (r < 0) return r;
return (r == 1) ? 0 : -1; return (r == 1) ? 0 : -1;
#endif #endif
} }
int Resp(int connfd, const u8* data1, size_t len1, const u8* data2, size_t len2, bool noack) int GdbStub::Resp(const u8* data1, size_t len1, const u8* data2, size_t len2, bool noack)
{ {
u8 cksum = 0; u8 cksum = 0;
int tries = 0; int tries = 0;
@ -359,22 +325,22 @@ int Resp(int connfd, const u8* data1, size_t len1, const u8* data2, size_t len2,
ssize_t r; ssize_t r;
u8 ack; u8 ack;
Log(LogLevel::Debug, "[GDB] send resp: '%s'\n", RespBuf); Log(LogLevel::Debug, "[GDB] send resp: '%s'\n", &RespBuf[0]);
#if MOCKTEST #if MOCKTEST
r = totallen+4; r = totallen+4;
#else #else
#ifdef _WIN32 #ifdef _WIN32
r = send(connfd, (const char*)RespBuf, totallen+4, 0); r = send(ConnFd, (const char*)&RespBuf[0], totallen+4, 0);
#else #else
r = send(connfd, RespBuf, totallen+4, 0); r = send(ConnFd, &RespBuf[0], totallen+4, 0);
#endif #endif
#endif #endif
if (r < 0) return r; if (r < 0) return r;
if (noack) break; if (noack) break;
r = WaitAckBlocking(connfd, &ack, 2000); r = WaitAckBlocking(&ack, 2000);
//Log(LogLevel::Debug, "[GDB] got ack: '%c'\n", ack); Log(LogLevel::Debug, "[GDB] got ack: '%c'\n", ack);
if (r == 0 && ack == '+') break; if (r == 0 && ack == '+') break;
++tries; ++tries;
@ -386,5 +352,4 @@ int Resp(int connfd, const u8* data1, size_t len1, const u8* data2, size_t len2,
} }
}

View File

@ -1,41 +0,0 @@
#ifndef GDBPROTO_H_
#define GDBPROTO_H_
#include <string.h>
#include <sys/types.h>
#include "GdbStub.h" /* class GdbStub */
#define MOCKTEST 0
namespace Gdb {
using namespace melonDS;
constexpr int GDBPROTO_BUFFER_CAPACITY = 1024+128;
extern u8 Cmdbuf[GDBPROTO_BUFFER_CAPACITY];
extern ssize_t Cmdlen;
namespace Proto {
extern u8 PacketBuf[GDBPROTO_BUFFER_CAPACITY];
extern u8 RespBuf[GDBPROTO_BUFFER_CAPACITY+5];
Gdb::ReadResult MsgRecv(int connfd, u8 cmd_dest[/*static GDBPROTO_BUFFER_CAPACITY*/]);
int SendAck(int connfd);
int SendNak(int connfd);
int Resp(int connfd, const u8* data1, size_t len1, const u8* data2, size_t len2, bool noack);
int WaitAckBlocking(int connfd, u8* ackp, int to_ms);
}
}
#endif

View File

@ -23,7 +23,7 @@
#include "../Platform.h" #include "../Platform.h"
#include "GdbProto.h" #include "GdbStub.h"
using namespace melonDS; using namespace melonDS;
using Platform::Log; using Platform::Log;
@ -304,7 +304,7 @@ StubState GdbStub::Poll(bool wait)
if (ConnFd < 0) return StubState::NoConn; if (ConnFd < 0) return StubState::NoConn;
u8 a; u8 a;
if (Proto::WaitAckBlocking(ConnFd, &a, 1000) < 0) if (WaitAckBlocking(&a, 1000) < 0)
{ {
Log(LogLevel::Error, "[GDB] inital handshake: didn't receive inital ack!\n"); Log(LogLevel::Error, "[GDB] inital handshake: didn't receive inital ack!\n");
close(ConnFd); close(ConnFd);
@ -380,7 +380,7 @@ StubState GdbStub::Poll(bool wait)
#endif #endif
#endif #endif
ReadResult res = Proto::MsgRecv(ConnFd, Cmdbuf); ReadResult res = MsgRecv();
switch (res) switch (res)
{ {
@ -422,11 +422,12 @@ ExecResult GdbStub::SubcmdExec(const u8* cmd, ssize_t len, const SubcmdHandler*
// check if prefix matches // check if prefix matches
if (!strncmp((const char*)cmd, handlers[i].SubStr, strlen(handlers[i].SubStr))) if (!strncmp((const char*)cmd, handlers[i].SubStr, strlen(handlers[i].SubStr)))
{ {
if (SendAck() < 0) // ack should have already been sent by CmdExec
/*if (SendAck() < 0)
{ {
Log(LogLevel::Error, "[GDB] send packet ack failed!\n"); Log(LogLevel::Error, "[GDB] send packet ack failed!\n");
return ExecResult::NetErr; return ExecResult::NetErr;
} }*/
return handlers[i].Handler(this, &cmd[strlen(handlers[i].SubStr)], len-strlen(handlers[i].SubStr)); return handlers[i].Handler(this, &cmd[strlen(handlers[i].SubStr)], len-strlen(handlers[i].SubStr));
} }
} }
@ -444,7 +445,7 @@ ExecResult GdbStub::SubcmdExec(const u8* cmd, ssize_t len, const SubcmdHandler*
ExecResult GdbStub::CmdExec(const CmdHandler* handlers) ExecResult GdbStub::CmdExec(const CmdHandler* handlers)
{ {
Log(LogLevel::Debug, "[GDB] command in: '%s'\n", Cmdbuf); Log(LogLevel::Debug, "[GDB] command in: '%s'\n", &Cmdbuf[0]);
for (size_t i = 0; handlers[i].Handler != NULL; ++i) for (size_t i = 0; handlers[i].Handler != NULL; ++i)
{ {
@ -644,24 +645,13 @@ StubState GdbStub::CheckWatchpt(u32 addr, int kind, bool enter, bool stay)
return StubState::CheckNoHit; return StubState::CheckNoHit;
} }
int GdbStub::SendAck()
{
if (NoAck) return 1;
return Proto::SendAck(ConnFd);
}
int GdbStub::SendNak()
{
if (NoAck) return 1;
return Proto::SendNak(ConnFd);
}
int GdbStub::Resp(const u8* data1, size_t len1, const u8* data2, size_t len2) int GdbStub::Resp(const u8* data1, size_t len1, const u8* data2, size_t len2)
{ {
return Proto::Resp(ConnFd, data1, len1, data2, len2, NoAck); return Resp(data1, len1, data2, len2, NoAck);
} }
int GdbStub::RespC(const char* data1, size_t len1, const u8* data2, size_t len2) int GdbStub::RespC(const char* data1, size_t len1, const u8* data2, size_t len2)
{ {
return Proto::Resp(ConnFd, (const u8*)data1, len1, data2, len2, NoAck); return Resp((const u8*)data1, len1, data2, len2, NoAck);
} }
#if defined(__GCC__) || defined(__clang__) #if defined(__GCC__) || defined(__clang__)
__attribute__((__format__(printf, 2/*includes implicit this*/, 3))) __attribute__((__format__(printf, 2/*includes implicit this*/, 3)))
@ -670,19 +660,19 @@ int GdbStub::RespFmt(const char* fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
int r = vsnprintf((char*)&Proto::RespBuf[1], sizeof(Proto::RespBuf)-5, fmt, args); int r = vsnprintf((char*)&RespBuf[1], sizeof(RespBuf)-5, fmt, args);
va_end(args); va_end(args);
if (r < 0) return r; if (r < 0) return r;
if ((size_t)r >= sizeof(Proto::RespBuf)-5) if ((size_t)r >= sizeof(RespBuf)-5)
{ {
Log(LogLevel::Error, "[GDB] truncated response in send_fmt()! (lost %zd bytes)\n", Log(LogLevel::Error, "[GDB] truncated response in send_fmt()! (lost %zd bytes)\n",
(ssize_t)r - (ssize_t)(sizeof(Proto::RespBuf)-5)); (ssize_t)r - (ssize_t)(sizeof(RespBuf)-5));
r = sizeof(Proto::RespBuf)-5; r = sizeof(RespBuf)-5;
} }
return Resp(&Proto::RespBuf[1], r); return Resp(&RespBuf[1], r);
} }
int GdbStub::RespStr(const char* str) int GdbStub::RespStr(const char* str)

View File

@ -86,6 +86,8 @@ enum class ExecResult
Continue Continue
}; };
constexpr int GDBPROTO_BUFFER_CAPACITY = 1024+128;
class GdbStub; class GdbStub;
typedef ExecResult (*GdbProtoCmd)(GdbStub* stub, const u8* cmd, ssize_t len); typedef ExecResult (*GdbProtoCmd)(GdbStub* stub, const u8* cmd, ssize_t len);
@ -141,9 +143,6 @@ public:
Gdb::ExecResult CmdExec(const CmdHandler* handlers); Gdb::ExecResult CmdExec(const CmdHandler* handlers);
public: public:
int SendAck();
int SendNak();
int Resp(const u8* data1, size_t len1, const u8* data2 = NULL, size_t len2 = 0); int Resp(const u8* data1, size_t len1, const u8* data2 = NULL, size_t len2 = 0);
int RespC(const char* data1, size_t len1, const u8* data2 = NULL, size_t len2 = 0); int RespC(const char* data1, size_t len1, const u8* data2 = NULL, size_t len2 = 0);
#if defined(__GCC__) || defined(__clang__) #if defined(__GCC__) || defined(__clang__)
@ -158,7 +157,20 @@ private:
void Disconnect(); void Disconnect();
StubState HandlePacket(); StubState HandlePacket();
private: Gdb::ReadResult MsgRecv();
Gdb::ReadResult TryParsePacket(size_t start, size_t& packetStart, size_t& packetSize, size_t& packetContentSize);
Gdb::ReadResult ParseAndSetupPacket();
void SetupCommand(size_t packetStart, size_t packetSize);
int SendAck();
int SendNak();
int Resp(const u8* data1, size_t len1, const u8* data2, size_t len2, bool noack);
int WaitAckBlocking(u8* ackp, int to_ms);
StubCallbacks* Cb; StubCallbacks* Cb;
//struct sockaddr_in server, client; //struct sockaddr_in server, client;
@ -172,6 +184,13 @@ private:
bool StatFlag; bool StatFlag;
bool NoAck; bool NoAck;
std::array<u8, GDBPROTO_BUFFER_CAPACITY> RecvBuffer;
u32 RecvBufferFilled = 0;
std::array<u8, GDBPROTO_BUFFER_CAPACITY> RespBuf;
std::array<u8, GDBPROTO_BUFFER_CAPACITY> Cmdbuf;
ssize_t Cmdlen;
std::map<u32, BpWp> BpList; std::map<u32, BpWp> BpList;
std::vector<BpWp> WpList; std::vector<BpWp> WpList;