Compare commits
7 Commits
7ab0d47a70
...
2b6db0d0ac
Author | SHA1 | Date |
---|---|---|
Jakly | 2b6db0d0ac | |
RSDuck | 7ac2eb2d71 | |
RSDuck | a3d696121e | |
Jaklyy | f6b73decc7 | |
Jaklyy | 56638c89bc | |
Jaklyy | 5b8bd44c24 | |
Jaklyy | e52b259f4e |
|
@ -400,11 +400,7 @@ void A_LDM(ARM* cpu)
|
||||||
|
|
||||||
if (!(cpu->CurInstr & (1<<23)))
|
if (!(cpu->CurInstr & (1<<23)))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 16; i++)
|
base -= 4 * __builtin_popcount(cpu->CurInstr & 0xFFFF);
|
||||||
{
|
|
||||||
if (cpu->CurInstr & (1<<i))
|
|
||||||
base -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpu->CurInstr & (1<<21))
|
if (cpu->CurInstr & (1<<21))
|
||||||
{
|
{
|
||||||
|
@ -418,16 +414,17 @@ void A_LDM(ARM* cpu)
|
||||||
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
||||||
cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10, true);
|
cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10, true);
|
||||||
|
|
||||||
for (int i = 0; i < 15; i++)
|
u16 reglist = cpu->CurInstr & 0x7FFF;
|
||||||
|
while (reglist)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
int i = __builtin_ctz(reglist);
|
||||||
{
|
reglist ^= 1<<i;
|
||||||
if (preinc) base += 4;
|
|
||||||
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
if (preinc) base += 4;
|
||||||
else cpu->DataRead32S(base, &cpu->R[i]);
|
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
||||||
first = false;
|
else cpu->DataRead32S(base, &cpu->R[i]);
|
||||||
if (!preinc) base += 4;
|
first = false;
|
||||||
}
|
if (!preinc) base += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->CurInstr & (1<<15))
|
if (cpu->CurInstr & (1<<15))
|
||||||
|
@ -479,11 +476,7 @@ void A_STM(ARM* cpu)
|
||||||
|
|
||||||
if (!(cpu->CurInstr & (1<<23)))
|
if (!(cpu->CurInstr & (1<<23)))
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < 16; i++)
|
base -= 4 * __builtin_popcount(cpu->CurInstr & 0xFFFF);
|
||||||
{
|
|
||||||
if (cpu->CurInstr & (1<<i))
|
|
||||||
base -= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpu->CurInstr & (1<<21))
|
if (cpu->CurInstr & (1<<21))
|
||||||
cpu->R[baseid] = base;
|
cpu->R[baseid] = base;
|
||||||
|
@ -503,26 +496,27 @@ void A_STM(ARM* cpu)
|
||||||
cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10, true);
|
cpu->UpdateMode(cpu->CPSR, (cpu->CPSR&~0x1F)|0x10, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < 16; i++)
|
u16 reglist = cpu->CurInstr & 0xFFFF;
|
||||||
|
while (reglist)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
int i = __builtin_ctz(reglist);
|
||||||
|
reglist ^= 1<<i;
|
||||||
|
|
||||||
|
if (preinc) base += 4;
|
||||||
|
|
||||||
|
if (i == baseid && !isbanked)
|
||||||
{
|
{
|
||||||
if (preinc) base += 4;
|
if ((cpu->Num == 0) || (!(cpu->CurInstr & ((1<<i)-1))))
|
||||||
|
first ? cpu->DataWrite32(base, oldbase) : cpu->DataWrite32S(base, oldbase);
|
||||||
if (i == baseid && !isbanked)
|
|
||||||
{
|
|
||||||
if ((cpu->Num == 0) || (!(cpu->CurInstr & ((1<<i)-1))))
|
|
||||||
first ? cpu->DataWrite32(base, oldbase) : cpu->DataWrite32S(base, oldbase);
|
|
||||||
else
|
|
||||||
first ? cpu->DataWrite32(base, base) : cpu->DataWrite32S(base, base); // checkme
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
first ? cpu->DataWrite32(base, cpu->R[i]) : cpu->DataWrite32S(base, cpu->R[i]);
|
first ? cpu->DataWrite32(base, base) : cpu->DataWrite32S(base, base); // checkme
|
||||||
|
|
||||||
first = false;
|
|
||||||
|
|
||||||
if (!preinc) base += 4;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
first ? cpu->DataWrite32(base, cpu->R[i]) : cpu->DataWrite32S(base, cpu->R[i]);
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
if (!preinc) base += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->CurInstr & (1<<22))
|
if (cpu->CurInstr & (1<<22))
|
||||||
|
@ -700,31 +694,23 @@ void T_LDR_SPREL(ARM* cpu)
|
||||||
|
|
||||||
void T_PUSH(ARM* cpu)
|
void T_PUSH(ARM* cpu)
|
||||||
{
|
{
|
||||||
int nregs = 0;
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
if (cpu->CurInstr & (1<<i))
|
|
||||||
nregs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cpu->CurInstr & (1<<8))
|
|
||||||
nregs++;
|
|
||||||
|
|
||||||
u32 base = cpu->R[13];
|
u32 base = cpu->R[13];
|
||||||
base -= (nregs<<2);
|
base -= 4 * __builtin_popcount(cpu->CurInstr & 0x1FF);
|
||||||
|
|
||||||
cpu->R[13] = base;
|
cpu->R[13] = base;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
u8 reglist = cpu->CurInstr & 0xFF;
|
||||||
|
while (reglist)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
int i = __builtin_ctz(reglist);
|
||||||
{
|
reglist ^= 1<<i;
|
||||||
if (first) cpu->DataWrite32 (base, cpu->R[i]);
|
|
||||||
else cpu->DataWrite32S(base, cpu->R[i]);
|
if (first) cpu->DataWrite32 (base, cpu->R[i]);
|
||||||
first = false;
|
else cpu->DataWrite32S(base, cpu->R[i]);
|
||||||
base += 4;
|
first = false;
|
||||||
}
|
base += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->CurInstr & (1<<8))
|
if (cpu->CurInstr & (1<<8))
|
||||||
|
@ -741,15 +727,16 @@ void T_POP(ARM* cpu)
|
||||||
u32 base = cpu->R[13];
|
u32 base = cpu->R[13];
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
u8 reglist = cpu->CurInstr & 0xFF;
|
||||||
|
while (reglist)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
int i = __builtin_ctz(reglist);
|
||||||
{
|
reglist ^= 1<<i;
|
||||||
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
|
||||||
else cpu->DataRead32S(base, &cpu->R[i]);
|
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
||||||
first = false;
|
else cpu->DataRead32S(base, &cpu->R[i]);
|
||||||
base += 4;
|
first = false;
|
||||||
}
|
base += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->CurInstr & (1<<8))
|
if (cpu->CurInstr & (1<<8))
|
||||||
|
@ -771,15 +758,16 @@ void T_STMIA(ARM* cpu)
|
||||||
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
u8 reglist = cpu->CurInstr & 0xFF;
|
||||||
|
while (reglist)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
int i = __builtin_ctz(reglist);
|
||||||
{
|
reglist ^= 1<<i;
|
||||||
if (first) cpu->DataWrite32 (base, cpu->R[i]);
|
|
||||||
else cpu->DataWrite32S(base, cpu->R[i]);
|
if (first) cpu->DataWrite32 (base, cpu->R[i]);
|
||||||
first = false;
|
else cpu->DataWrite32S(base, cpu->R[i]);
|
||||||
base += 4;
|
first = false;
|
||||||
}
|
base += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check "Rb included in Rlist" case
|
// TODO: check "Rb included in Rlist" case
|
||||||
|
@ -792,15 +780,16 @@ void T_LDMIA(ARM* cpu)
|
||||||
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
u8 reglist = cpu->CurInstr & 0xFF;
|
||||||
|
while (reglist)
|
||||||
{
|
{
|
||||||
if (cpu->CurInstr & (1<<i))
|
int i = __builtin_ctz(reglist);
|
||||||
{
|
reglist ^= 1<<i;
|
||||||
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
|
||||||
else cpu->DataRead32S(base, &cpu->R[i]);
|
if (first) cpu->DataRead32 (base, &cpu->R[i]);
|
||||||
first = false;
|
else cpu->DataRead32S(base, &cpu->R[i]);
|
||||||
base += 4;
|
first = false;
|
||||||
}
|
base += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(cpu->CurInstr & (1<<((cpu->CurInstr >> 8) & 0x7))))
|
if (!(cpu->CurInstr & (1<<((cpu->CurInstr >> 8) & 0x7))))
|
||||||
|
|
|
@ -143,6 +143,8 @@ void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s
|
||||||
u32 vramaddr = (texparam & 0xFFFF) << 3;
|
u32 vramaddr = (texparam & 0xFFFF) << 3;
|
||||||
|
|
||||||
s32 width = 8 << ((texparam >> 20) & 0x7);
|
s32 width = 8 << ((texparam >> 20) & 0x7);
|
||||||
|
// since width is always a multple of 8 (thus a multiple of 2) we can replace all multiplications by width with a bitshift
|
||||||
|
s32 widthshift = 3 + ((texparam >> 20) & 0x7);
|
||||||
s32 height = 8 << ((texparam >> 23) & 0x7);
|
s32 height = 8 << ((texparam >> 23) & 0x7);
|
||||||
|
|
||||||
s >>= 4;
|
s >>= 4;
|
||||||
|
@ -192,7 +194,7 @@ void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s
|
||||||
{
|
{
|
||||||
case 1: // A3I5
|
case 1: // A3I5
|
||||||
{
|
{
|
||||||
vramaddr += ((t * width) + s);
|
vramaddr += ((t << widthshift) + s);
|
||||||
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
||||||
|
|
||||||
texpal <<= 4;
|
texpal <<= 4;
|
||||||
|
@ -203,7 +205,7 @@ void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s
|
||||||
|
|
||||||
case 2: // 4-color
|
case 2: // 4-color
|
||||||
{
|
{
|
||||||
vramaddr += (((t * width) + s) >> 2);
|
vramaddr += (((t << widthshift) + s) >> 2);
|
||||||
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
||||||
pixel >>= ((s & 0x3) << 1);
|
pixel >>= ((s & 0x3) << 1);
|
||||||
pixel &= 0x3;
|
pixel &= 0x3;
|
||||||
|
@ -216,7 +218,7 @@ void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s
|
||||||
|
|
||||||
case 3: // 16-color
|
case 3: // 16-color
|
||||||
{
|
{
|
||||||
vramaddr += (((t * width) + s) >> 1);
|
vramaddr += (((t << widthshift) + s) >> 1);
|
||||||
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
||||||
if (s & 0x1) pixel >>= 4;
|
if (s & 0x1) pixel >>= 4;
|
||||||
else pixel &= 0xF;
|
else pixel &= 0xF;
|
||||||
|
@ -229,7 +231,7 @@ void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s
|
||||||
|
|
||||||
case 4: // 256-color
|
case 4: // 256-color
|
||||||
{
|
{
|
||||||
vramaddr += ((t * width) + s);
|
vramaddr += ((t << widthshift) + s);
|
||||||
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
||||||
|
|
||||||
texpal <<= 4;
|
texpal <<= 4;
|
||||||
|
@ -240,7 +242,7 @@ void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s
|
||||||
|
|
||||||
case 5: // compressed
|
case 5: // compressed
|
||||||
{
|
{
|
||||||
vramaddr += ((t & 0x3FC) * (width>>2)) + (s & 0x3FC);
|
vramaddr += ((t & 0x3FC) << (widthshift-2)) + (s & 0x3FC);
|
||||||
vramaddr += (t & 0x3);
|
vramaddr += (t & 0x3);
|
||||||
vramaddr &= 0x7FFFF; // address used for all calcs wraps around after slot 3
|
vramaddr &= 0x7FFFF; // address used for all calcs wraps around after slot 3
|
||||||
|
|
||||||
|
@ -352,7 +354,7 @@ void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s
|
||||||
|
|
||||||
case 6: // A5I3
|
case 6: // A5I3
|
||||||
{
|
{
|
||||||
vramaddr += ((t * width) + s);
|
vramaddr += ((t << widthshift) + s);
|
||||||
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
u8 pixel = ReadVRAM_Texture<u8>(vramaddr, gpu);
|
||||||
|
|
||||||
texpal <<= 4;
|
texpal <<= 4;
|
||||||
|
@ -363,7 +365,7 @@ void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s
|
||||||
|
|
||||||
case 7: // direct color
|
case 7: // direct color
|
||||||
{
|
{
|
||||||
vramaddr += (((t * width) + s) << 1);
|
vramaddr += (((t << widthshift) + s) << 1);
|
||||||
*color = ReadVRAM_Texture<u16>(vramaddr, gpu);
|
*color = ReadVRAM_Texture<u16>(vramaddr, gpu);
|
||||||
*alpha = (*color & 0x8000) ? 31 : 0;
|
*alpha = (*color & 0x8000) ? 31 : 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,15 +101,15 @@ private:
|
||||||
|
|
||||||
if ((w0 & 0x1) && !(w1 & 0x1))
|
if ((w0 & 0x1) && !(w1 & 0x1))
|
||||||
{
|
{
|
||||||
this->w0n = w0 - 1;
|
this->w0n = w0 - 1 >> 1;
|
||||||
this->w0d = w0 + 1;
|
this->w0d = w0 + 1 >> 1;
|
||||||
this->w1d = w1;
|
this->w1d = w1 >> 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->w0n = w0 & 0xFFFE;
|
this->w0n = w0 >> 1;
|
||||||
this->w0d = w0 & 0xFFFE;
|
this->w0d = w0 >> 1;
|
||||||
this->w1d = w1 & 0xFFFE;
|
this->w1d = w1 >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->shift = 9;
|
this->shift = 9;
|
||||||
|
@ -138,7 +138,7 @@ private:
|
||||||
// this seems to be a proper division on hardware :/
|
// this seems to be a proper division on hardware :/
|
||||||
// I haven't been able to find cases that produce imperfect output
|
// I haven't been able to find cases that produce imperfect output
|
||||||
if (den == 0) yfactor = 0;
|
if (den == 0) yfactor = 0;
|
||||||
else yfactor = (s32)(num / den);
|
else yfactor = ((u32)num / den);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue