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.
This commit is contained in:
Gabriel Corona
2015-05-05 01:15:16 +02:00
parent 80fe5e0a55
commit 04cb6fccd6
6 changed files with 69 additions and 17 deletions

View File

@ -16,6 +16,7 @@
#else
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#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;
}