From 04cb6fccd62b162c0a7e4dd0d5b50c6fc7321114 Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Tue, 5 May 2015 01:15:16 +0200 Subject: [PATCH] GDB stub over UNIX socket This is available with the `GDBSocket` option in `~/.dolphin-emu/Config/Dolphin.ini`. GDB can connect to it with: $ powerpc-eabi-gdb (gdb) target remote |socat STDIO UNIX:foo.sock Because I don't like so much binding the GDB stub socket to 0.0.0.0. On Linux, with a suitable umask, we can make sure that another local user cannot connect to the socket. --- Source/Core/Core/ConfigManager.cpp | 6 +++ Source/Core/Core/Core.cpp | 8 ++++ Source/Core/Core/CoreParameter.cpp | 3 ++ Source/Core/Core/CoreParameter.h | 3 ++ Source/Core/Core/PowerPC/GDBStub.cpp | 65 ++++++++++++++++++++-------- Source/Core/Core/PowerPC/GDBStub.h | 1 + 6 files changed, 69 insertions(+), 17 deletions(-) diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 08f030d07a..7201d1b79e 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -218,6 +218,9 @@ void SConfig::SaveGeneralSettings(IniFile& ini) general->Set("WirelessMac", m_WirelessMac); #ifdef USE_GDBSTUB +#ifndef _WIN32 + general->Set("GDBSocket", m_LocalCoreStartupParameter.gdb_socket); +#endif general->Set("GDBPort", m_LocalCoreStartupParameter.iGDBPort); #endif } @@ -421,6 +424,9 @@ void SConfig::LoadGeneralSettings(IniFile& ini) general->Get("ShowLag", &m_ShowLag, false); general->Get("ShowFrameCount", &m_ShowFrameCount, false); #ifdef USE_GDBSTUB +#ifndef _WIN32 + general->Get("GDBSocket", &m_LocalCoreStartupParameter.gdb_socket, ""); +#endif general->Get("GDBPort", &(m_LocalCoreStartupParameter.iGDBPort), -1); #endif diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index fc63203d04..eb3f8ab9b6 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -325,6 +325,14 @@ static void CpuThread() #ifdef USE_GDBSTUB + #ifndef _WIN32 + if (!_CoreParameter.gdb_socket.empty()) + { + gdb_init_local(_CoreParameter.gdb_socket.data()); + gdb_break(); + } + else + #endif if (_CoreParameter.iGDBPort > 0) { gdb_init(_CoreParameter.iGDBPort); diff --git a/Source/Core/Core/CoreParameter.cpp b/Source/Core/Core/CoreParameter.cpp index bce8101b09..82243a0c33 100644 --- a/Source/Core/Core/CoreParameter.cpp +++ b/Source/Core/Core/CoreParameter.cpp @@ -65,6 +65,9 @@ void SCoreStartupParameter::LoadDefaults() #ifdef USE_GDBSTUB iGDBPort = -1; + #ifndef _WIN32 + gdb_socket = ""; + #endif #endif iCPUCore = PowerPC::CORE_JIT64; diff --git a/Source/Core/Core/CoreParameter.h b/Source/Core/Core/CoreParameter.h index 381128a1f0..6c8aafda6c 100644 --- a/Source/Core/Core/CoreParameter.h +++ b/Source/Core/Core/CoreParameter.h @@ -133,6 +133,9 @@ struct SCoreStartupParameter bool bEnableDebugging; #ifdef USE_GDBSTUB int iGDBPort; + #ifndef _WIN32 + std::string gdb_socket; + #endif #endif bool bAutomaticStart; bool bBootToPause; diff --git a/Source/Core/Core/PowerPC/GDBStub.cpp b/Source/Core/Core/PowerPC/GDBStub.cpp index 0123e71276..a5ac7252fa 100644 --- a/Source/Core/Core/PowerPC/GDBStub.cpp +++ b/Source/Core/Core/PowerPC/GDBStub.cpp @@ -16,6 +16,7 @@ #else #include #include +#include #include #endif @@ -33,7 +34,6 @@ static int tmpsock = -1; static int sock = -1; -static struct sockaddr_in saddr_server, saddr_client; static u8 cmd_bfr[GDB_BFR_MAX]; static u32 cmd_len; @@ -800,9 +800,52 @@ WSADATA InitData; // exported functions +static void gdb_init_generic(int domain, + const sockaddr *server_addr, socklen_t server_addrlen, + sockaddr *client_addr, socklen_t *client_addrlen); + +#ifndef _WIN32 +void gdb_init_local(const char *socket) +{ + unlink(socket); + + sockaddr_un addr = {} + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, socket); + + gdb_init_generic(PF_LOCAL, (const sockaddr *)&addr, sizeof(addr), + NULL, NULL); +} +#endif + void gdb_init(u32 port) { - socklen_t len; + sockaddr_in saddr_server = {}; + sockaddr_in saddr_client; + + saddr_server.sin_family = AF_INET; + saddr_server.sin_port = htons(port); + saddr_server.sin_addr.s_addr = INADDR_ANY; + + socklen_t client_addrlen = sizeof(saddr_client); + + gdb_init_generic(PF_INET, + (const sockaddr *)&saddr_server, sizeof(saddr_server), + (sockaddr *)&saddr_client, &client_addrlen); + + saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); + /*if (((saddr_client.sin_addr.s_addr >> 24) & 0xff) != 127 || + * ((saddr_client.sin_addr.s_addr >> 16) & 0xff) != 0 || + * ((saddr_client.sin_addr.s_addr >> 8) & 0xff) != 0 || + * ((saddr_client.sin_addr.s_addr >> 0) & 0xff) != 1) + * ERROR_LOG(GDB_STUB, "gdb: incoming connection not from localhost"); + */ +} + +static void gdb_init_generic(int domain, + const sockaddr *server_addr, socklen_t server_addrlen, + sockaddr *client_addr, socklen_t *client_addrlen) +{ int on; #ifdef _WIN32 WSAStartup(MAKEWORD(2,2), &InitData); @@ -813,7 +856,7 @@ void gdb_init(u32 port) memset(bp_w, 0, sizeof bp_w); memset(bp_a, 0, sizeof bp_a); - tmpsock = socket(AF_INET, SOCK_STREAM, 0); + tmpsock = socket(domain, SOCK_STREAM, 0); if (tmpsock == -1) ERROR_LOG(GDB_STUB, "Failed to create gdb socket"); @@ -821,12 +864,7 @@ void gdb_init(u32 port) if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) < 0) ERROR_LOG(GDB_STUB, "Failed to setsockopt"); - memset(&saddr_server, 0, sizeof saddr_server); - saddr_server.sin_family = AF_INET; - saddr_server.sin_port = htons(port); - saddr_server.sin_addr.s_addr = INADDR_ANY; - - if (bind(tmpsock, (struct sockaddr *)&saddr_server, sizeof saddr_server) < 0) + if (bind(tmpsock, server_addr, server_addrlen) < 0) ERROR_LOG(GDB_STUB, "Failed to bind gdb socket"); if (listen(tmpsock, 1) < 0) @@ -834,18 +872,11 @@ void gdb_init(u32 port) INFO_LOG(GDB_STUB, "Waiting for gdb to connect...\n"); - sock = accept(tmpsock, (struct sockaddr *)&saddr_client, &len); + sock = accept(tmpsock, client_addr, client_addrlen); if (sock < 0) ERROR_LOG(GDB_STUB, "Failed to accept gdb client"); INFO_LOG(GDB_STUB, "Client connected.\n"); - saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); - /*if (((saddr_client.sin_addr.s_addr >> 24) & 0xff) != 127 || - * ((saddr_client.sin_addr.s_addr >> 16) & 0xff) != 0 || - * ((saddr_client.sin_addr.s_addr >> 8) & 0xff) != 0 || - * ((saddr_client.sin_addr.s_addr >> 0) & 0xff) != 1) - * ERROR_LOG(GDB_STUB, "gdb: incoming connection not from localhost"); - */ close(tmpsock); tmpsock = -1; } diff --git a/Source/Core/Core/PowerPC/GDBStub.h b/Source/Core/Core/PowerPC/GDBStub.h index cf3f642e24..3e93d102fe 100644 --- a/Source/Core/Core/PowerPC/GDBStub.h +++ b/Source/Core/Core/PowerPC/GDBStub.h @@ -30,6 +30,7 @@ typedef enum { } gdb_bp_type; void gdb_init(u32 port); +void gdb_init_local(const char *socket); void gdb_deinit(); bool gdb_active(); void gdb_break();