Begin GDB stub
Jeffrey Pfau jeffrey@endrift.com
Sat, 01 Feb 2014 03:05:10 -0800
4 files changed,
156 insertions(+),
2 deletions(-)
M
CMakeLists.txt
→
CMakeLists.txt
@@ -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)@@ -36,6 +37,10 @@ set(DEBUGGER_SRC "${DEBUGGER_SRC};${CMAKE_SOURCE_DIR}/src/debugger/cli-debugger.c")
set(DEBUGGER_LIB "edit") 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})
M
src/debugger/debugger.c
→
src/debugger/debugger.c
@@ -29,7 +29,9 @@ debugger->state = DEBUGGER_PAUSED;
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 @@ switch (debugger->state) {
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:
A
src/debugger/gdb-stub.c
@@ -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); +}
A
src/debugger/gdb-stub.h
@@ -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