summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorMatthew Parlane <parlane@gmail.com>2013-01-08 20:26:07 +1300
committerMatthew Parlane <parlane@gmail.com>2013-01-08 20:26:07 +1300
commit9f13e69be46b07c64bedb9b225f06fb8f738bb7e (patch)
tree06a2d9ac5e8bbf5d1f5daf4c03ff774d12d39d0a /Source/Core
parentb7fd1225ba18d0ba1c6fc734575958e61a4c4d86 (diff)
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.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/Core.cpp42
-rw-r--r--Source/Core/Core/Src/HW/CPU.cpp8
-rw-r--r--Source/Core/Core/Src/PowerPC/GDBStub.cpp216
-rw-r--r--Source/Core/Core/Src/PowerPC/GDBStub.h5
-rw-r--r--Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp3
5 files changed, 126 insertions, 148 deletions
diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index 0fa1d44134..f864b35328 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -104,9 +104,6 @@ std::string g_stateFileName;
std::thread g_EmuThread;
static std::thread g_cpu_thread;
-#ifdef USE_GDBSTUB
-static std::thread g_gdb_thread;
-#endif
static bool g_requestRefreshInfo = false;
static int g_pauseAndLockDepth = 0;
@@ -328,6 +325,15 @@ void CpuThread()
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.
CCPU::Run();
@@ -453,20 +459,6 @@ void EmuThread()
cpuThreadFunc = FifoPlayerThread;
else
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
if (_CoreParameter.bCPUThread)
@@ -507,19 +499,17 @@ void EmuThread()
// Wait for g_cpu_thread to exit
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str());
-
- g_cpu_thread.join();
-
- 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());
+ 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();
+ INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str());
+
VolumeHandler::EjectVolume();
FileMon::Close();
diff --git a/Source/Core/Core/Src/HW/CPU.cpp b/Source/Core/Core/Src/HW/CPU.cpp
index a7a272e263..fd9a1603b8 100644
--- a/Source/Core/Core/Src/HW/CPU.cpp
+++ b/Source/Core/Core/Src/HW/CPU.cpp
@@ -31,7 +31,7 @@
namespace
{
static Common::Event m_StepEvent;
- static Common::Event *m_SyncEvent;
+ static Common::Event *m_SyncEvent = NULL;
static std::mutex m_csCpuOccupied;
}
@@ -42,13 +42,13 @@ void CCPU::Init(int cpu_core)
cpu_core = Movie::GetCPUMode();
}
PowerPC::Init(cpu_core);
- m_SyncEvent = 0;
+ m_SyncEvent = NULL;
}
void CCPU::Shutdown()
{
PowerPC::Shutdown();
- m_SyncEvent = 0;
+ m_SyncEvent = NULL;
}
void CCPU::Run()
@@ -84,7 +84,7 @@ reswitch:
//4: update disasm dialog
if (m_SyncEvent) {
m_SyncEvent->Set();
- m_SyncEvent = 0;
+ m_SyncEvent = NULL;
}
Host_UpdateDisasmDialog();
break;
diff --git a/Source/Core/Core/Src/PowerPC/GDBStub.cpp b/Source/Core/Core/Src/PowerPC/GDBStub.cpp
index 1ba5433638..745287e575 100644
--- a/Source/Core/Core/Src/PowerPC/GDBStub.cpp
+++ b/Source/Core/Core/Src/PowerPC/GDBStub.cpp
@@ -34,6 +34,7 @@
#endif
#include <stdarg.h>
+#include "Host.h"
#define GDB_BFR_MAX 10000
#define GDB_MAX_BP 10
@@ -53,6 +54,7 @@ static u32 cmd_len;
static u32 sig = 0;
static u32 send_signal = 0;
+static u32 step_break = 0;
typedef struct {
u32 active;
@@ -102,8 +104,8 @@ static void mem2hex(u8 *dst, u8 *src, u32 len)
static void hex2mem(u8 *dst, u8 *src, u32 len)
{
while (len-- > 0) {
- *dst = hex2char(*src++) << 4;
- *dst++ |= hex2char(*src++);
+ *dst++ = (hex2char(*src) << 4) | hex2char(*(src+1));
+ src += 2;
}
}
@@ -266,7 +268,11 @@ static void gdb_read_command()
while ((c = gdb_read_byte()) != GDB_STUB_END) {
cmd_bfr[cmd_len++] = c;
if (cmd_len == sizeof cmd_bfr)
+ {
ERROR_LOG(GDB_STUB, "gdb: cmd_bfr overflow\n");
+ gdb_nak();
+ return;
+ }
}
chk_read = hex2char(gdb_read_byte()) << 4;
@@ -279,9 +285,11 @@ static void gdb_read_command()
cmd_len = 0;
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);
+ gdb_ack();
}
static int gdb_data_available() {
@@ -312,6 +320,9 @@ static void gdb_reply(const char *reply)
u8 *ptr;
int n;
+ if(!gdb_active())
+ return;
+
memset(cmd_bfr, 0, sizeof cmd_bfr);
cmd_len = strlen(reply);
@@ -335,7 +346,10 @@ static void gdb_reply(const char *reply)
while (left > 0) {
n = send(sock, ptr, left, 0);
if (n < 0)
+ {
ERROR_LOG(GDB_STUB, "gdb: send failed");
+ return gdb_deinit();
+ }
left -= n;
ptr += n;
}
@@ -343,7 +357,6 @@ static void gdb_reply(const char *reply)
static void gdb_handle_query()
{
- gdb_ack();
DEBUG_LOG(GDB_STUB, "gdb: query '%s'\n", cmd_bfr+1);
if (!strcmp((const char *)(cmd_bfr+1), "TStatus"))
@@ -356,10 +369,10 @@ static void gdb_handle_query()
static void gdb_handle_set_thread()
{
- gdb_ack();
if (memcmp(cmd_bfr, "Hg0", 3) == 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");
gdb_reply("E01");
}
@@ -367,8 +380,6 @@ static void gdb_handle_set_thread()
static void gdb_handle_signal()
{
char bfr[128];
-
- gdb_ack();
memset(bfr, 0, sizeof bfr);
sprintf(bfr, "T%02x%02x:%08x;%02x:%08x;", sig, 64, PC, 1, GPR(1));
gdb_reply(bfr);
@@ -397,7 +408,6 @@ static void gdb_read_register()
id = hex2char(cmd_bfr[1]) << 4;
id |= hex2char(cmd_bfr[2]);
- gdb_ack();
switch (id) {
case 0 ... 31:
wbe32hex(reply, GPR(id));
@@ -443,16 +453,15 @@ static void gdb_read_registers()
u8 * bufptr = bfr;
u32 i;
- gdb_ack();
memset(bfr, 0, sizeof bfr);
for (i = 0; i < 32; i++) {
- wbe32hex(bufptr + i*4, GPR(i));
+ wbe32hex(bufptr + i*8, GPR(i));
}
bufptr += 32 * 4;
for (i = 0; i < 32; i++) {
- wbe64hex(bufptr + i*4, riPS0(i));
+ wbe64hex(bufptr + i*16, riPS0(i));
}
bufptr += 64 * 4;
@@ -496,8 +505,6 @@ static u64 re64hex(u8 *p)
static void gdb_write_registers()
{
- gdb_ack();
-
u32 i;
u8 * bufptr = cmd_bfr;
@@ -530,8 +537,6 @@ static void gdb_write_register()
{
u32 id;
- gdb_ack();
-
id = hex2char(cmd_bfr[1]) << 4;
id |= hex2char(cmd_bfr[2]);
@@ -584,8 +589,6 @@ static void gdb_read_mem()
u32 addr, len;
u32 i;
- gdb_ack();
-
i = 1;
addr = 0;
while (cmd_bfr[i] != ',')
@@ -599,8 +602,10 @@ static void gdb_read_mem()
if (len*2 > sizeof reply)
gdb_reply("E01");
-
- mem2hex(reply, Memory::GetPointer(addr), len);
+ u8 * data = Memory::GetPointer(addr);
+ if (!data)
+ return gdb_reply("E0");
+ mem2hex(reply, data, len);
reply[len*2] = '\0';
gdb_reply((char *)reply);
}
@@ -610,8 +615,6 @@ static void gdb_write_mem()
u32 addr, len;
u32 i;
- gdb_ack();
-
i = 1;
addr = 0;
while (cmd_bfr[i] != ',')
@@ -623,15 +626,21 @@ static void gdb_write_mem()
len = (len << 4) | hex2char(cmd_bfr[i++]);
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");
}
+static void gdb_step()
+{
+ step_break = 1;
+ send_signal = 1;
+}
+
static void gdb_continue()
{
- gdb_ack();
- CCPU::EnableStepping(false);
- m_GdbWaitEvent.Set();
send_signal = 1;
}
@@ -656,8 +665,6 @@ static void _gdb_add_bp()
u32 type;
u32 i, addr = 0, len = 0;
- gdb_ack();
-
type = hex2char(cmd_bfr[1]);
switch (type) {
case 0:
@@ -694,8 +701,6 @@ static void gdb_remove_bp()
{
u32 type, addr, len, i;
- gdb_ack();
-
type = hex2char(cmd_bfr[1]);
switch (type) {
case 0:
@@ -730,63 +735,66 @@ static void gdb_remove_bp()
gdb_reply("OK");
}
-static void gdb_parse_command()
+void gdb_handle_exception()
{
- if (cmd_len == 0)
- return;
-
- switch(cmd_bfr[0]) {
- case 'q':
- gdb_handle_query();
- break;
- case 'H':
- gdb_handle_set_thread();
- break;
- case '?':
- gdb_handle_signal();
- break;
- case 'k':
- gdb_ack();
- gdb_deinit();
- INFO_LOG(GDB_STUB, "killed by gdb");
- break;
- case 'g':
- gdb_read_registers();
- break;
- case 'G':
- gdb_write_registers();
- break;
- case 'p':
- gdb_read_register();
- break;
- case 'P':
- gdb_write_register();
- break;
- case 'm':
- gdb_read_mem();
- break;
- case 'M':
- gdb_write_mem();
- break;
- case 's':
- case 'C':
- case 'c':
- gdb_continue();
- break;
- case 'v':
- gdb_ack();
- gdb_reply("");
- break;
- case 'z':
- gdb_remove_bp();
- break;
- case 'Z':
- _gdb_add_bp();
- break;
- default:
- gdb_ack();
- gdb_reply("");
- break;
+ while (gdb_active()) {
+ if(!gdb_data_available())
+ continue;
+ gdb_read_command();
+ if (cmd_len == 0)
+ continue;
+
+ switch(cmd_bfr[0]) {
+ case 'q':
+ gdb_handle_query();
+ break;
+ case 'H':
+ gdb_handle_set_thread();
+ break;
+ case '?':
+ gdb_handle_signal();
+ break;
+ case 'k':
+ gdb_deinit();
+ INFO_LOG(GDB_STUB, "killed by gdb");
+ return;
+ case 'g':
+ gdb_read_registers();
+ break;
+ case 'G':
+ gdb_write_registers();
+ break;
+ case 'p':
+ gdb_read_register();
+ break;
+ case 'P':
+ gdb_write_register();
+ break;
+ case 'm':
+ gdb_read_mem();
+ break;
+ case 'M':
+ gdb_write_mem();
+ PowerPC::ppcState.iCache.Reset();
+ Host_UpdateDisasmDialog();
+ break;
+ case 's':
+ gdb_step();
+ return;
+ case 'C':
+ case 'c':
+ gdb_continue();
+ return;
+ case 'z':
+ gdb_remove_bp();
+ break;
+ case 'Z':
+ _gdb_add_bp();
+ break;
+ default:
+ gdb_reply("");
+ break;
+ }
}
}
@@ -804,8 +812,6 @@ void gdb_init(u32 port)
WSAStartup(MAKEWORD(2,2), &InitData);
#endif
- m_GdbWaitEvent.Reset();
-
memset(bp_x, 0, sizeof bp_x);
memset(bp_r, 0, sizeof bp_r);
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");
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)
ERROR_LOG(GDB_STUB, "Failed to accept gdb client");
INFO_LOG(GDB_STUB, "Client connected.\n");
@@ -853,18 +859,15 @@ void gdb_deinit()
{
if (tmpsock != -1)
{
- close(tmpsock);
+ shutdown(tmpsock, SHUT_RDWR);
tmpsock = -1;
}
if (sock != -1)
{
- close(sock);
+ shutdown(sock, SHUT_RDWR);
sock = -1;
}
- m_GdbWaitEvent.Set();
- m_GdbWaitEvent.Reset();
-
#ifdef _WIN32
WSACleanup();
#endif
@@ -875,25 +878,6 @@ bool gdb_active()
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)
{
if (sock == -1)
@@ -914,6 +898,14 @@ int gdb_bp_x(u32 addr)
if (sock == -1)
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);
}
diff --git a/Source/Core/Core/Src/PowerPC/GDBStub.h b/Source/Core/Core/Src/PowerPC/GDBStub.h
index 4fcaa76298..cf01d22c8b 100644
--- a/Source/Core/Core/Src/PowerPC/GDBStub.h
+++ b/Source/Core/Core/Src/PowerPC/GDBStub.h
@@ -45,8 +45,7 @@ void gdb_init(u32 port);
void gdb_deinit();
bool gdb_active();
-void gdb_thread();
-void gdb_handle_events();
+void gdb_handle_exception();
int gdb_signal(u32 signal);
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);
-static Common::Event m_GdbWaitEvent;
-
#endif
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp
index f7604a4f12..094c12b38c 100644
--- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp
@@ -110,8 +110,7 @@ int Interpreter::SingleStepInner(void)
Host_UpdateDisasmDialog();
gdb_signal(SIGTRAP);
- gdb_handle_events();
- m_GdbWaitEvent.Wait();
+ gdb_handle_exception();
}
#endif