GDB Stub now works with ida and gdb.
Implemented stepping correctly. TODO: Peek incoming data to socket for an interrupt. Memory breakpoints. Fix bug with initial step from entry point. Tidy up code. Wishlist: Implement some common query packets. Jit support.
This commit is contained in:
parent
b7fd1225ba
commit
9f13e69be4
|
@ -104,9 +104,6 @@ std::string g_stateFileName;
|
||||||
std::thread g_EmuThread;
|
std::thread g_EmuThread;
|
||||||
|
|
||||||
static std::thread g_cpu_thread;
|
static std::thread g_cpu_thread;
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
static std::thread g_gdb_thread;
|
|
||||||
#endif
|
|
||||||
static bool g_requestRefreshInfo = false;
|
static bool g_requestRefreshInfo = false;
|
||||||
static int g_pauseAndLockDepth = 0;
|
static int g_pauseAndLockDepth = 0;
|
||||||
|
|
||||||
|
@ -328,6 +325,15 @@ void CpuThread()
|
||||||
|
|
||||||
g_bStarted = true;
|
g_bStarted = true;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_GDBSTUB
|
||||||
|
if(_CoreParameter.iGDBPort > 0)
|
||||||
|
{
|
||||||
|
gdb_init(_CoreParameter.iGDBPort);
|
||||||
|
gdb_handle_exception();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Enter CPU run loop. When we leave it - we are done.
|
// Enter CPU run loop. When we leave it - we are done.
|
||||||
CCPU::Run();
|
CCPU::Run();
|
||||||
|
|
||||||
|
@ -454,20 +460,6 @@ void EmuThread()
|
||||||
else
|
else
|
||||||
cpuThreadFunc = CpuThread;
|
cpuThreadFunc = CpuThread;
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
if(_CoreParameter.iGDBPort > 0)
|
|
||||||
{
|
|
||||||
INFO_LOG(GDB_STUB, "Trying to start the GDB Stub listening on port %d.", _CoreParameter.iGDBPort);
|
|
||||||
Core::SetState(Core::CORE_PAUSE);
|
|
||||||
gdb_init(_CoreParameter.iGDBPort);
|
|
||||||
|
|
||||||
g_gdb_thread = std::thread(gdb_thread);
|
|
||||||
|
|
||||||
//gdb_signal(SIGTRAP);
|
|
||||||
gdb_add_bp(GDB_BP_TYPE_X, 0x80004050, 4);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ENTER THE VIDEO THREAD LOOP
|
// ENTER THE VIDEO THREAD LOOP
|
||||||
if (_CoreParameter.bCPUThread)
|
if (_CoreParameter.bCPUThread)
|
||||||
{
|
{
|
||||||
|
@ -508,18 +500,16 @@ void EmuThread()
|
||||||
// Wait for g_cpu_thread to exit
|
// Wait for g_cpu_thread to exit
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str());
|
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str());
|
||||||
|
|
||||||
|
#ifdef USE_GDBSTUB
|
||||||
|
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB ...").c_str());
|
||||||
|
gdb_deinit();
|
||||||
|
INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
g_cpu_thread.join();
|
g_cpu_thread.join();
|
||||||
|
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());
|
INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());
|
||||||
|
|
||||||
#ifdef USE_GDBSTUB
|
|
||||||
// Wait for g_gdb_thread to exit
|
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB thread ...").c_str());
|
|
||||||
gdb_deinit();
|
|
||||||
g_gdb_thread.join();
|
|
||||||
INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB thread stopped.").c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VolumeHandler::EjectVolume();
|
VolumeHandler::EjectVolume();
|
||||||
FileMon::Close();
|
FileMon::Close();
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static Common::Event m_StepEvent;
|
static Common::Event m_StepEvent;
|
||||||
static Common::Event *m_SyncEvent;
|
static Common::Event *m_SyncEvent = NULL;
|
||||||
static std::mutex m_csCpuOccupied;
|
static std::mutex m_csCpuOccupied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,13 +42,13 @@ void CCPU::Init(int cpu_core)
|
||||||
cpu_core = Movie::GetCPUMode();
|
cpu_core = Movie::GetCPUMode();
|
||||||
}
|
}
|
||||||
PowerPC::Init(cpu_core);
|
PowerPC::Init(cpu_core);
|
||||||
m_SyncEvent = 0;
|
m_SyncEvent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCPU::Shutdown()
|
void CCPU::Shutdown()
|
||||||
{
|
{
|
||||||
PowerPC::Shutdown();
|
PowerPC::Shutdown();
|
||||||
m_SyncEvent = 0;
|
m_SyncEvent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCPU::Run()
|
void CCPU::Run()
|
||||||
|
@ -84,7 +84,7 @@ reswitch:
|
||||||
//4: update disasm dialog
|
//4: update disasm dialog
|
||||||
if (m_SyncEvent) {
|
if (m_SyncEvent) {
|
||||||
m_SyncEvent->Set();
|
m_SyncEvent->Set();
|
||||||
m_SyncEvent = 0;
|
m_SyncEvent = NULL;
|
||||||
}
|
}
|
||||||
Host_UpdateDisasmDialog();
|
Host_UpdateDisasmDialog();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "Host.h"
|
||||||
|
|
||||||
#define GDB_BFR_MAX 10000
|
#define GDB_BFR_MAX 10000
|
||||||
#define GDB_MAX_BP 10
|
#define GDB_MAX_BP 10
|
||||||
|
@ -53,6 +54,7 @@ static u32 cmd_len;
|
||||||
|
|
||||||
static u32 sig = 0;
|
static u32 sig = 0;
|
||||||
static u32 send_signal = 0;
|
static u32 send_signal = 0;
|
||||||
|
static u32 step_break = 0;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 active;
|
u32 active;
|
||||||
|
@ -102,8 +104,8 @@ static void mem2hex(u8 *dst, u8 *src, u32 len)
|
||||||
static void hex2mem(u8 *dst, u8 *src, u32 len)
|
static void hex2mem(u8 *dst, u8 *src, u32 len)
|
||||||
{
|
{
|
||||||
while (len-- > 0) {
|
while (len-- > 0) {
|
||||||
*dst = hex2char(*src++) << 4;
|
*dst++ = (hex2char(*src) << 4) | hex2char(*(src+1));
|
||||||
*dst++ |= hex2char(*src++);
|
src += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +268,11 @@ static void gdb_read_command()
|
||||||
while ((c = gdb_read_byte()) != GDB_STUB_END) {
|
while ((c = gdb_read_byte()) != GDB_STUB_END) {
|
||||||
cmd_bfr[cmd_len++] = c;
|
cmd_bfr[cmd_len++] = c;
|
||||||
if (cmd_len == sizeof cmd_bfr)
|
if (cmd_len == sizeof cmd_bfr)
|
||||||
|
{
|
||||||
ERROR_LOG(GDB_STUB, "gdb: cmd_bfr overflow\n");
|
ERROR_LOG(GDB_STUB, "gdb: cmd_bfr overflow\n");
|
||||||
|
gdb_nak();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chk_read = hex2char(gdb_read_byte()) << 4;
|
chk_read = hex2char(gdb_read_byte()) << 4;
|
||||||
|
@ -279,9 +285,11 @@ static void gdb_read_command()
|
||||||
cmd_len = 0;
|
cmd_len = 0;
|
||||||
|
|
||||||
gdb_nak();
|
gdb_nak();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_LOG(GDB_STUB, "gdb: read command %c with a length of %d: %s\n", cmd_bfr[0], cmd_len, cmd_bfr);
|
DEBUG_LOG(GDB_STUB, "gdb: read command %c with a length of %d: %s\n", cmd_bfr[0], cmd_len, cmd_bfr);
|
||||||
|
gdb_ack();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gdb_data_available() {
|
static int gdb_data_available() {
|
||||||
|
@ -312,6 +320,9 @@ static void gdb_reply(const char *reply)
|
||||||
u8 *ptr;
|
u8 *ptr;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
if(!gdb_active())
|
||||||
|
return;
|
||||||
|
|
||||||
memset(cmd_bfr, 0, sizeof cmd_bfr);
|
memset(cmd_bfr, 0, sizeof cmd_bfr);
|
||||||
|
|
||||||
cmd_len = strlen(reply);
|
cmd_len = strlen(reply);
|
||||||
|
@ -335,7 +346,10 @@ static void gdb_reply(const char *reply)
|
||||||
while (left > 0) {
|
while (left > 0) {
|
||||||
n = send(sock, ptr, left, 0);
|
n = send(sock, ptr, left, 0);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
|
{
|
||||||
ERROR_LOG(GDB_STUB, "gdb: send failed");
|
ERROR_LOG(GDB_STUB, "gdb: send failed");
|
||||||
|
return gdb_deinit();
|
||||||
|
}
|
||||||
left -= n;
|
left -= n;
|
||||||
ptr += n;
|
ptr += n;
|
||||||
}
|
}
|
||||||
|
@ -343,7 +357,6 @@ static void gdb_reply(const char *reply)
|
||||||
|
|
||||||
static void gdb_handle_query()
|
static void gdb_handle_query()
|
||||||
{
|
{
|
||||||
gdb_ack();
|
|
||||||
DEBUG_LOG(GDB_STUB, "gdb: query '%s'\n", cmd_bfr+1);
|
DEBUG_LOG(GDB_STUB, "gdb: query '%s'\n", cmd_bfr+1);
|
||||||
|
|
||||||
if (!strcmp((const char *)(cmd_bfr+1), "TStatus"))
|
if (!strcmp((const char *)(cmd_bfr+1), "TStatus"))
|
||||||
|
@ -356,10 +369,10 @@ static void gdb_handle_query()
|
||||||
|
|
||||||
static void gdb_handle_set_thread()
|
static void gdb_handle_set_thread()
|
||||||
{
|
{
|
||||||
gdb_ack();
|
|
||||||
if (memcmp(cmd_bfr, "Hg0", 3) == 0 ||
|
if (memcmp(cmd_bfr, "Hg0", 3) == 0 ||
|
||||||
memcmp(cmd_bfr, "Hc-1", 4) == 0 ||
|
memcmp(cmd_bfr, "Hc-1", 4) == 0 ||
|
||||||
memcmp(cmd_bfr, "Hc0", 4) == 0)
|
memcmp(cmd_bfr, "Hc0", 4) == 0 ||
|
||||||
|
memcmp(cmd_bfr, "Hc1", 4) == 0)
|
||||||
return gdb_reply("OK");
|
return gdb_reply("OK");
|
||||||
gdb_reply("E01");
|
gdb_reply("E01");
|
||||||
}
|
}
|
||||||
|
@ -367,8 +380,6 @@ static void gdb_handle_set_thread()
|
||||||
static void gdb_handle_signal()
|
static void gdb_handle_signal()
|
||||||
{
|
{
|
||||||
char bfr[128];
|
char bfr[128];
|
||||||
|
|
||||||
gdb_ack();
|
|
||||||
memset(bfr, 0, sizeof bfr);
|
memset(bfr, 0, sizeof bfr);
|
||||||
sprintf(bfr, "T%02x%02x:%08x;%02x:%08x;", sig, 64, PC, 1, GPR(1));
|
sprintf(bfr, "T%02x%02x:%08x;%02x:%08x;", sig, 64, PC, 1, GPR(1));
|
||||||
gdb_reply(bfr);
|
gdb_reply(bfr);
|
||||||
|
@ -397,7 +408,6 @@ static void gdb_read_register()
|
||||||
id = hex2char(cmd_bfr[1]) << 4;
|
id = hex2char(cmd_bfr[1]) << 4;
|
||||||
id |= hex2char(cmd_bfr[2]);
|
id |= hex2char(cmd_bfr[2]);
|
||||||
|
|
||||||
gdb_ack();
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 0 ... 31:
|
case 0 ... 31:
|
||||||
wbe32hex(reply, GPR(id));
|
wbe32hex(reply, GPR(id));
|
||||||
|
@ -443,16 +453,15 @@ static void gdb_read_registers()
|
||||||
u8 * bufptr = bfr;
|
u8 * bufptr = bfr;
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
gdb_ack();
|
|
||||||
memset(bfr, 0, sizeof bfr);
|
memset(bfr, 0, sizeof bfr);
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
wbe32hex(bufptr + i*4, GPR(i));
|
wbe32hex(bufptr + i*8, GPR(i));
|
||||||
}
|
}
|
||||||
bufptr += 32 * 4;
|
bufptr += 32 * 4;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
wbe64hex(bufptr + i*4, riPS0(i));
|
wbe64hex(bufptr + i*16, riPS0(i));
|
||||||
}
|
}
|
||||||
bufptr += 64 * 4;
|
bufptr += 64 * 4;
|
||||||
|
|
||||||
|
@ -496,8 +505,6 @@ static u64 re64hex(u8 *p)
|
||||||
|
|
||||||
static void gdb_write_registers()
|
static void gdb_write_registers()
|
||||||
{
|
{
|
||||||
gdb_ack();
|
|
||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
u8 * bufptr = cmd_bfr;
|
u8 * bufptr = cmd_bfr;
|
||||||
|
|
||||||
|
@ -530,8 +537,6 @@ static void gdb_write_register()
|
||||||
{
|
{
|
||||||
u32 id;
|
u32 id;
|
||||||
|
|
||||||
gdb_ack();
|
|
||||||
|
|
||||||
id = hex2char(cmd_bfr[1]) << 4;
|
id = hex2char(cmd_bfr[1]) << 4;
|
||||||
id |= hex2char(cmd_bfr[2]);
|
id |= hex2char(cmd_bfr[2]);
|
||||||
|
|
||||||
|
@ -584,8 +589,6 @@ static void gdb_read_mem()
|
||||||
u32 addr, len;
|
u32 addr, len;
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
gdb_ack();
|
|
||||||
|
|
||||||
i = 1;
|
i = 1;
|
||||||
addr = 0;
|
addr = 0;
|
||||||
while (cmd_bfr[i] != ',')
|
while (cmd_bfr[i] != ',')
|
||||||
|
@ -599,8 +602,10 @@ static void gdb_read_mem()
|
||||||
|
|
||||||
if (len*2 > sizeof reply)
|
if (len*2 > sizeof reply)
|
||||||
gdb_reply("E01");
|
gdb_reply("E01");
|
||||||
|
u8 * data = Memory::GetPointer(addr);
|
||||||
mem2hex(reply, Memory::GetPointer(addr), len);
|
if (!data)
|
||||||
|
return gdb_reply("E0");
|
||||||
|
mem2hex(reply, data, len);
|
||||||
reply[len*2] = '\0';
|
reply[len*2] = '\0';
|
||||||
gdb_reply((char *)reply);
|
gdb_reply((char *)reply);
|
||||||
}
|
}
|
||||||
|
@ -610,8 +615,6 @@ static void gdb_write_mem()
|
||||||
u32 addr, len;
|
u32 addr, len;
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
gdb_ack();
|
|
||||||
|
|
||||||
i = 1;
|
i = 1;
|
||||||
addr = 0;
|
addr = 0;
|
||||||
while (cmd_bfr[i] != ',')
|
while (cmd_bfr[i] != ',')
|
||||||
|
@ -623,15 +626,21 @@ static void gdb_write_mem()
|
||||||
len = (len << 4) | hex2char(cmd_bfr[i++]);
|
len = (len << 4) | hex2char(cmd_bfr[i++]);
|
||||||
DEBUG_LOG(GDB_STUB, "gdb: write memory: %08x bytes to %08x\n", len, addr);
|
DEBUG_LOG(GDB_STUB, "gdb: write memory: %08x bytes to %08x\n", len, addr);
|
||||||
|
|
||||||
hex2mem(Memory::GetPointer(addr), cmd_bfr + i, len);
|
u8 * dst = Memory::GetPointer(addr);
|
||||||
|
if (!dst)
|
||||||
|
return gdb_reply("E00");
|
||||||
|
hex2mem(dst, cmd_bfr + i + 1, len);
|
||||||
gdb_reply("OK");
|
gdb_reply("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gdb_step()
|
||||||
|
{
|
||||||
|
step_break = 1;
|
||||||
|
send_signal = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void gdb_continue()
|
static void gdb_continue()
|
||||||
{
|
{
|
||||||
gdb_ack();
|
|
||||||
CCPU::EnableStepping(false);
|
|
||||||
m_GdbWaitEvent.Set();
|
|
||||||
send_signal = 1;
|
send_signal = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,8 +665,6 @@ static void _gdb_add_bp()
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 i, addr = 0, len = 0;
|
u32 i, addr = 0, len = 0;
|
||||||
|
|
||||||
gdb_ack();
|
|
||||||
|
|
||||||
type = hex2char(cmd_bfr[1]);
|
type = hex2char(cmd_bfr[1]);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -694,8 +701,6 @@ static void gdb_remove_bp()
|
||||||
{
|
{
|
||||||
u32 type, addr, len, i;
|
u32 type, addr, len, i;
|
||||||
|
|
||||||
gdb_ack();
|
|
||||||
|
|
||||||
type = hex2char(cmd_bfr[1]);
|
type = hex2char(cmd_bfr[1]);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -730,63 +735,66 @@ static void gdb_remove_bp()
|
||||||
gdb_reply("OK");
|
gdb_reply("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gdb_parse_command()
|
void gdb_handle_exception()
|
||||||
{
|
{
|
||||||
if (cmd_len == 0)
|
while (gdb_active()) {
|
||||||
return;
|
if(!gdb_data_available())
|
||||||
|
continue;
|
||||||
|
gdb_read_command();
|
||||||
|
if (cmd_len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
switch(cmd_bfr[0]) {
|
switch(cmd_bfr[0]) {
|
||||||
case 'q':
|
case 'q':
|
||||||
gdb_handle_query();
|
gdb_handle_query();
|
||||||
break;
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
gdb_handle_set_thread();
|
gdb_handle_set_thread();
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
gdb_handle_signal();
|
gdb_handle_signal();
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
gdb_ack();
|
gdb_deinit();
|
||||||
gdb_deinit();
|
INFO_LOG(GDB_STUB, "killed by gdb");
|
||||||
INFO_LOG(GDB_STUB, "killed by gdb");
|
return;
|
||||||
break;
|
case 'g':
|
||||||
case 'g':
|
gdb_read_registers();
|
||||||
gdb_read_registers();
|
break;
|
||||||
break;
|
case 'G':
|
||||||
case 'G':
|
gdb_write_registers();
|
||||||
gdb_write_registers();
|
break;
|
||||||
break;
|
case 'p':
|
||||||
case 'p':
|
gdb_read_register();
|
||||||
gdb_read_register();
|
break;
|
||||||
break;
|
case 'P':
|
||||||
case 'P':
|
gdb_write_register();
|
||||||
gdb_write_register();
|
break;
|
||||||
break;
|
case 'm':
|
||||||
case 'm':
|
gdb_read_mem();
|
||||||
gdb_read_mem();
|
break;
|
||||||
break;
|
case 'M':
|
||||||
case 'M':
|
gdb_write_mem();
|
||||||
gdb_write_mem();
|
PowerPC::ppcState.iCache.Reset();
|
||||||
break;
|
Host_UpdateDisasmDialog();
|
||||||
case 's':
|
break;
|
||||||
case 'C':
|
case 's':
|
||||||
case 'c':
|
gdb_step();
|
||||||
gdb_continue();
|
return;
|
||||||
break;
|
case 'C':
|
||||||
case 'v':
|
case 'c':
|
||||||
gdb_ack();
|
gdb_continue();
|
||||||
gdb_reply("");
|
return;
|
||||||
break;
|
case 'z':
|
||||||
case 'z':
|
gdb_remove_bp();
|
||||||
gdb_remove_bp();
|
break;
|
||||||
break;
|
case 'Z':
|
||||||
case 'Z':
|
_gdb_add_bp();
|
||||||
_gdb_add_bp();
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
gdb_reply("");
|
||||||
gdb_ack();
|
break;
|
||||||
gdb_reply("");
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,8 +812,6 @@ void gdb_init(u32 port)
|
||||||
WSAStartup(MAKEWORD(2,2), &InitData);
|
WSAStartup(MAKEWORD(2,2), &InitData);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_GdbWaitEvent.Reset();
|
|
||||||
|
|
||||||
memset(bp_x, 0, sizeof bp_x);
|
memset(bp_x, 0, sizeof bp_x);
|
||||||
memset(bp_r, 0, sizeof bp_r);
|
memset(bp_r, 0, sizeof bp_r);
|
||||||
memset(bp_w, 0, sizeof bp_w);
|
memset(bp_w, 0, sizeof bp_w);
|
||||||
|
@ -831,8 +837,8 @@ void gdb_init(u32 port)
|
||||||
ERROR_LOG(GDB_STUB, "Failed to listen to gdb socket");
|
ERROR_LOG(GDB_STUB, "Failed to listen to gdb socket");
|
||||||
|
|
||||||
INFO_LOG(GDB_STUB, "Waiting for gdb to connect...\n");
|
INFO_LOG(GDB_STUB, "Waiting for gdb to connect...\n");
|
||||||
sock = accept(tmpsock, (struct sockaddr *)&saddr_client, &len);
|
|
||||||
|
|
||||||
|
sock = accept(tmpsock, (struct sockaddr *)&saddr_client, &len);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
ERROR_LOG(GDB_STUB, "Failed to accept gdb client");
|
ERROR_LOG(GDB_STUB, "Failed to accept gdb client");
|
||||||
INFO_LOG(GDB_STUB, "Client connected.\n");
|
INFO_LOG(GDB_STUB, "Client connected.\n");
|
||||||
|
@ -853,18 +859,15 @@ void gdb_deinit()
|
||||||
{
|
{
|
||||||
if (tmpsock != -1)
|
if (tmpsock != -1)
|
||||||
{
|
{
|
||||||
close(tmpsock);
|
shutdown(tmpsock, SHUT_RDWR);
|
||||||
tmpsock = -1;
|
tmpsock = -1;
|
||||||
}
|
}
|
||||||
if (sock != -1)
|
if (sock != -1)
|
||||||
{
|
{
|
||||||
close(sock);
|
shutdown(sock, SHUT_RDWR);
|
||||||
sock = -1;
|
sock = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_GdbWaitEvent.Set();
|
|
||||||
m_GdbWaitEvent.Reset();
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
#endif
|
#endif
|
||||||
|
@ -875,25 +878,6 @@ bool gdb_active()
|
||||||
return tmpsock != -1 || sock != -1;
|
return tmpsock != -1 || sock != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdb_thread()
|
|
||||||
{
|
|
||||||
while(sock != -1)
|
|
||||||
{
|
|
||||||
gdb_handle_events();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdb_handle_events()
|
|
||||||
{
|
|
||||||
if (sock == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (sock != -1 && gdb_data_available()) {
|
|
||||||
gdb_read_command();
|
|
||||||
gdb_parse_command();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int gdb_signal(u32 s)
|
int gdb_signal(u32 s)
|
||||||
{
|
{
|
||||||
if (sock == -1)
|
if (sock == -1)
|
||||||
|
@ -914,6 +898,14 @@ int gdb_bp_x(u32 addr)
|
||||||
if (sock == -1)
|
if (sock == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (step_break)
|
||||||
|
{
|
||||||
|
step_break = 0;
|
||||||
|
|
||||||
|
DEBUG_LOG(GDB_STUB, "Step was successful.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return gdb_bp_check(addr, GDB_BP_TYPE_X);
|
return gdb_bp_check(addr, GDB_BP_TYPE_X);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,7 @@ void gdb_init(u32 port);
|
||||||
void gdb_deinit();
|
void gdb_deinit();
|
||||||
bool gdb_active();
|
bool gdb_active();
|
||||||
|
|
||||||
void gdb_thread();
|
void gdb_handle_exception();
|
||||||
void gdb_handle_events();
|
|
||||||
int gdb_signal(u32 signal);
|
int gdb_signal(u32 signal);
|
||||||
|
|
||||||
int gdb_bp_x(u32 addr);
|
int gdb_bp_x(u32 addr);
|
||||||
|
@ -56,6 +55,4 @@ int gdb_bp_a(u32 addr);
|
||||||
|
|
||||||
bool gdb_add_bp(u32 type, u32 addr, u32 len);
|
bool gdb_add_bp(u32 type, u32 addr, u32 len);
|
||||||
|
|
||||||
static Common::Event m_GdbWaitEvent;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -110,8 +110,7 @@ int Interpreter::SingleStepInner(void)
|
||||||
Host_UpdateDisasmDialog();
|
Host_UpdateDisasmDialog();
|
||||||
|
|
||||||
gdb_signal(SIGTRAP);
|
gdb_signal(SIGTRAP);
|
||||||
gdb_handle_events();
|
gdb_handle_exception();
|
||||||
m_GdbWaitEvent.Wait();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue