mirror of https://github.com/mgba-emu/mgba.git
Begin GDB stub
This commit is contained in:
parent
38aac38a0c
commit
244f197742
|
@ -4,6 +4,7 @@ set(BINARY_NAME gbac CACHE INTERNAL "Name of output binaries")
|
|||
set(CMAKE_C_FLAGS_DEBUG "-g -Wall -Wextra --std=gnu99")
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 -Wall -Wextra --std=gnu99")
|
||||
set(USE_CLI_DEBUGGER ON CACHE BOOL "Whether or not to enable the CLI-mode ARM debugger")
|
||||
set(USE_GDB_STUB ON CACHE BOOL "Whether or not to enable the GDB stub ARM debugger")
|
||||
set(BUILD_SDL ON CACHE BOOL "Build SDL frontend")
|
||||
set(BUILD_PERF ON CACHE BOOL "Build performance profiling tool")
|
||||
file(GLOB ARM_SRC ${CMAKE_SOURCE_DIR}/src/arm/*.c)
|
||||
|
@ -37,6 +38,10 @@ if(USE_CLI_DEBUGGER)
|
|||
else()
|
||||
set(DEBUGGER_LIB "")
|
||||
endif()
|
||||
|
||||
if(USE_GDB_STUB)
|
||||
set(DEBUGGER_SRC "${DEBUGGER_SRC};${CMAKE_SOURCE_DIR}/src/debugger/gdb-stub.c")
|
||||
endif()
|
||||
source_group("ARM debugger" FILES ${DEBUGGER_SRC})
|
||||
|
||||
add_library(${BINARY_NAME} SHARED ${ARM_SRC} ${GBA_SRC} ${DEBUGGER_SRC} ${RENDERER_SRC} ${UTIL_SRC} ${OS_SRC})
|
||||
|
|
|
@ -29,7 +29,9 @@ void ARMDebuggerInit(struct ARMDebugger* debugger, struct ARMCore* cpu) {
|
|||
debugger->breakpoints = 0;
|
||||
debugger->memoryShim.p = debugger;
|
||||
debugger->memoryShim.watchpoints = 0;
|
||||
debugger->init(debugger);
|
||||
if (debugger->init) {
|
||||
debugger->init(debugger);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMDebuggerDeinit(struct ARMDebugger* debugger) {
|
||||
|
@ -56,7 +58,11 @@ void ARMDebuggerRun(struct ARMDebugger* debugger) {
|
|||
case DEBUGGER_RUNNING:
|
||||
break;
|
||||
case DEBUGGER_PAUSED:
|
||||
debugger->paused(debugger);
|
||||
if (debugger->paused) {
|
||||
debugger->paused(debugger);
|
||||
} else {
|
||||
debugger->state = DEBUGGER_RUNNING;
|
||||
}
|
||||
break;
|
||||
case DEBUGGER_EXITING:
|
||||
case DEBUGGER_SHUTDOWN:
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
#include "gdb-stub.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void _gdbStubDeinit(struct ARMDebugger* debugger) {
|
||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||
if (stub->socket >= 0) {
|
||||
GDBStubShutdown(stub);
|
||||
}
|
||||
}
|
||||
|
||||
void GDBStubCreate(struct GDBStub* stub) {
|
||||
stub->socket = -1;
|
||||
stub->connection = -1;
|
||||
stub->d.init = 0;
|
||||
stub->d.deinit = _gdbStubDeinit;
|
||||
stub->d.paused = 0;
|
||||
}
|
||||
|
||||
int GDBStubListen(struct GDBStub* stub, int port, uint32_t bindAddress) {
|
||||
if (stub->socket >= 0) {
|
||||
GDBStubShutdown(stub);
|
||||
}
|
||||
// TODO: support IPv6
|
||||
stub->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (stub->socket < 0) {
|
||||
printf("Couldn't open socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sockaddr_in bindInfo = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(port),
|
||||
.sin_addr = {
|
||||
.s_addr = htonl(bindAddress)
|
||||
}
|
||||
};
|
||||
int err = bind(stub->socket, (const struct sockaddr*) &bindInfo, sizeof(struct sockaddr_in));
|
||||
if (err) {
|
||||
goto cleanup;
|
||||
}
|
||||
err = listen(stub->socket, 1);
|
||||
if (err) {
|
||||
goto cleanup;
|
||||
}
|
||||
int flags = fcntl(stub->socket, F_GETFL);
|
||||
if (flags == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
flags |= O_NONBLOCK;
|
||||
fcntl(stub->socket, F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
return 1;
|
||||
|
||||
cleanup:
|
||||
close(stub->socket);
|
||||
stub->socket = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GDBStubHangup(struct GDBStub* stub) {
|
||||
if (stub->connection >= 0) {
|
||||
close(stub->connection);
|
||||
stub->connection = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void GDBStubShutdown(struct GDBStub* stub) {
|
||||
GDBStubHangup(stub);
|
||||
if (stub->socket >= 0) {
|
||||
close(stub->socket);
|
||||
stub->socket = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void GDBStubUpdate(struct GDBStub* stub) {
|
||||
if (stub->connection == -1) {
|
||||
stub->connection = accept(stub->socket, 0, 0);
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||
return;
|
||||
}
|
||||
if (stub->connection >= 0) {
|
||||
int flags = fcntl(stub->connection, F_GETFL);
|
||||
if (flags == -1) {
|
||||
goto connectionLost;
|
||||
}
|
||||
flags |= O_NONBLOCK;
|
||||
fcntl(stub->connection, F_SETFL, flags | O_NONBLOCK);
|
||||
} else {
|
||||
goto connectionLost;
|
||||
}
|
||||
}
|
||||
while (1) {
|
||||
ssize_t messageLen = recv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1, 0);
|
||||
if (messageLen == 0) {
|
||||
goto connectionLost;
|
||||
}
|
||||
if (messageLen == -1) {
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||
return;
|
||||
}
|
||||
goto connectionLost;
|
||||
}
|
||||
stub->line[messageLen] = '\0';
|
||||
printf("Received message: %s\n", stub->line);
|
||||
}
|
||||
return;
|
||||
|
||||
connectionLost:
|
||||
// TODO: add logging support to the debugging interface
|
||||
printf("Connection lost\n");
|
||||
GDBStubHangup(stub);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef GDB_STUB_H
|
||||
#define GDB_STUB_H
|
||||
|
||||
#include "debugger.h"
|
||||
|
||||
#define GDB_STUB_MAX_LINE 256
|
||||
|
||||
struct GDBStub {
|
||||
struct ARMDebugger d;
|
||||
|
||||
char line[GDB_STUB_MAX_LINE];
|
||||
|
||||
int socket;
|
||||
int connection;
|
||||
};
|
||||
|
||||
void GDBStubCreate(struct GDBStub*);
|
||||
int GDBStubListen(struct GDBStub*, int port, uint32_t bindAddress);
|
||||
|
||||
void GDBStubHangup(struct GDBStub*);
|
||||
void GDBStubShutdown(struct GDBStub*);
|
||||
|
||||
void GDBStubUpdate(struct GDBStub*);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue