src/debugger/gdb-stub.c (view raw)
1#include "gdb-stub.h"
2
3#include <errno.h>
4#include <fcntl.h>
5#include <netinet/in.h>
6#include <stdio.h>
7#include <sys/socket.h>
8#include <unistd.h>
9
10void _gdbStubDeinit(struct ARMDebugger* debugger) {
11 struct GDBStub* stub = (struct GDBStub*) debugger;
12 if (stub->socket >= 0) {
13 GDBStubShutdown(stub);
14 }
15}
16
17void GDBStubCreate(struct GDBStub* stub) {
18 stub->socket = -1;
19 stub->connection = -1;
20 stub->d.init = 0;
21 stub->d.deinit = _gdbStubDeinit;
22 stub->d.paused = 0;
23}
24
25int GDBStubListen(struct GDBStub* stub, int port, uint32_t bindAddress) {
26 if (stub->socket >= 0) {
27 GDBStubShutdown(stub);
28 }
29 // TODO: support IPv6
30 stub->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
31 if (stub->socket < 0) {
32 printf("Couldn't open socket\n");
33 return 0;
34 }
35
36 struct sockaddr_in bindInfo = {
37 .sin_family = AF_INET,
38 .sin_port = htons(port),
39 .sin_addr = {
40 .s_addr = htonl(bindAddress)
41 }
42 };
43 int err = bind(stub->socket, (const struct sockaddr*) &bindInfo, sizeof(struct sockaddr_in));
44 if (err) {
45 goto cleanup;
46 }
47 err = listen(stub->socket, 1);
48 if (err) {
49 goto cleanup;
50 }
51 int flags = fcntl(stub->socket, F_GETFL);
52 if (flags == -1) {
53 goto cleanup;
54 }
55 flags |= O_NONBLOCK;
56 fcntl(stub->socket, F_SETFL, flags | O_NONBLOCK);
57
58 return 1;
59
60cleanup:
61 close(stub->socket);
62 stub->socket = -1;
63 return 0;
64}
65
66void GDBStubHangup(struct GDBStub* stub) {
67 if (stub->connection >= 0) {
68 close(stub->connection);
69 stub->connection = -1;
70 }
71}
72
73void GDBStubShutdown(struct GDBStub* stub) {
74 GDBStubHangup(stub);
75 if (stub->socket >= 0) {
76 close(stub->socket);
77 stub->socket = -1;
78 }
79}
80
81void GDBStubUpdate(struct GDBStub* stub) {
82 if (stub->connection == -1) {
83 stub->connection = accept(stub->socket, 0, 0);
84 if (errno == EWOULDBLOCK || errno == EAGAIN) {
85 return;
86 }
87 if (stub->connection >= 0) {
88 int flags = fcntl(stub->connection, F_GETFL);
89 if (flags == -1) {
90 goto connectionLost;
91 }
92 flags |= O_NONBLOCK;
93 fcntl(stub->connection, F_SETFL, flags | O_NONBLOCK);
94 } else {
95 goto connectionLost;
96 }
97 }
98 while (1) {
99 ssize_t messageLen = recv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1, 0);
100 if (messageLen == 0) {
101 goto connectionLost;
102 }
103 if (messageLen == -1) {
104 if (errno == EWOULDBLOCK || errno == EAGAIN) {
105 return;
106 }
107 goto connectionLost;
108 }
109 stub->line[messageLen] = '\0';
110 printf("Received message: %s\n", stub->line);
111 }
112 return;
113
114connectionLost:
115 // TODO: add logging support to the debugging interface
116 printf("Connection lost\n");
117 GDBStubHangup(stub);
118}