6 #include <sys/socket.h>
15 #include "gdbserver.h"
18 unsigned int circular_buffer_t
<T
>::size() const
23 return end
+ capacity
- start
;
27 void circular_buffer_t
<T
>::consume(unsigned int bytes
)
29 start
= (start
+ bytes
) % capacity
;
33 unsigned int circular_buffer_t
<T
>::contiguous_empty_size() const
37 return capacity
- end
- 1;
39 return capacity
- end
;
41 return start
- end
- 1;
45 unsigned int circular_buffer_t
<T
>::contiguous_data_size() const
50 return capacity
- start
;
54 void circular_buffer_t
<T
>::data_added(unsigned int bytes
)
57 assert(end
<= capacity
);
63 void circular_buffer_t
<T
>::reset()
70 void circular_buffer_t
<T
>::append(const T
*src
, unsigned int count
)
72 unsigned int copy
= std::min(count
, contiguous_empty_size());
73 memcpy(contiguous_empty(), src
, copy
* sizeof(T
));
77 assert(count
< contiguous_empty_size());
78 memcpy(contiguous_empty(), src
, count
* sizeof(T
));
83 // Code inspired by/copied from OpenOCD server/server.c.
85 gdbserver_t::gdbserver_t(uint16_t port
) :
87 recv_buf(64 * 1024), send_buf(64 * 1024)
89 socket_fd
= socket(AF_INET
, SOCK_STREAM
, 0);
90 if (socket_fd
== -1) {
91 fprintf(stderr
, "error creating socket: %s\n", strerror(errno
));
95 int so_reuseaddr_option
= 1;
99 (void *)&so_reuseaddr_option
,
102 int oldopts
= fcntl(socket_fd
, F_GETFL
, 0);
103 fcntl(socket_fd
, F_SETFL
, oldopts
| O_NONBLOCK
);
105 struct sockaddr_in sin
;
106 memset(&sin
, 0, sizeof(sin
));
107 sin
.sin_family
= AF_INET
;
108 sin
.sin_addr
.s_addr
= INADDR_ANY
;
109 sin
.sin_port
= htons(port
);
111 if (bind(socket_fd
, (struct sockaddr
*)&sin
, sizeof(sin
)) == -1) {
112 fprintf(stderr
, "couldn't bind to socket: %s\n", strerror(errno
));
116 /* These setsockopt()s must happen before the listen() */
117 int window_size
= 128 * 1024;
118 setsockopt(socket_fd
, SOL_SOCKET
, SO_SNDBUF
,
119 (char *)&window_size
, sizeof(window_size
));
120 setsockopt(socket_fd
, SOL_SOCKET
, SO_RCVBUF
,
121 (char *)&window_size
, sizeof(window_size
));
123 if (listen(socket_fd
, 1) == -1) {
124 fprintf(stderr
, "couldn't listen on socket: %s\n", strerror(errno
));
129 void gdbserver_t::accept()
131 struct sockaddr client_addr
;
132 socklen_t address_size
= sizeof(client_addr
);
133 client_fd
= ::accept(socket_fd
, &client_addr
, &address_size
);
134 if (client_fd
== -1) {
135 if (errno
== EAGAIN
) {
136 // We'll try again in the next call.
138 fprintf(stderr
, "failed to accept on socket: %s (%d)\n", strerror(errno
), errno
);
142 int oldopts
= fcntl(client_fd
, F_GETFL
, 0);
143 fcntl(client_fd
, F_SETFL
, oldopts
| O_NONBLOCK
);
148 void gdbserver_t::read()
150 // Reading from a non-blocking socket still blocks if there is no data
153 size_t count
= recv_buf
.contiguous_empty_size();
155 ssize_t bytes
= ::read(client_fd
, recv_buf
.contiguous_empty(), count
);
157 if (errno
== EAGAIN
) {
158 // We'll try again the next call.
160 fprintf(stderr
, "failed to read on socket: %s (%d)\n", strerror(errno
), errno
);
163 } else if (bytes
== 0) {
164 // The remote disconnected.
169 printf("read %ld bytes\n", bytes
);
170 recv_buf
.data_added(bytes
);
174 void gdbserver_t::write()
176 if (send_buf
.empty())
179 while (!send_buf
.empty()) {
180 unsigned int count
= send_buf
.contiguous_data_size();
182 ssize_t bytes
= ::write(client_fd
, send_buf
.contiguous_data(), count
);
184 fprintf(stderr
, "failed to write to socket: %s (%d)\n", strerror(errno
), errno
);
186 } else if (bytes
== 0) {
187 // Client can't take any more data right now.
190 printf("wrote %ld bytes:\n", bytes
);
191 for (unsigned int i
= 0; i
< bytes
; i
++) {
192 printf("%c", send_buf
[i
]);
195 send_buf
.consume(bytes
);
200 void print_packet(const std::vector
<uint8_t> &packet
)
202 for (uint8_t c
: packet
) {
203 fprintf(stderr
, "%c", c
);
205 fprintf(stderr
, "\n");
208 uint8_t compute_checksum(const std::vector
<uint8_t> &packet
)
210 uint8_t checksum
= 0;
211 for (auto i
= packet
.begin() + 1; i
!= packet
.end() - 3; i
++ ) {
217 uint8_t character_hex_value(uint8_t character
)
219 if (character
>= '0' && character
<= '9')
220 return character
- '0';
221 if (character
>= 'a' && character
<= 'f')
222 return 10 + character
- 'a';
223 if (character
>= 'A' && character
<= 'F')
224 return 10 + character
- 'A';
228 uint8_t extract_checksum(const std::vector
<uint8_t> &packet
)
230 return character_hex_value(*(packet
.end() - 1)) +
231 16 * character_hex_value(*(packet
.end() - 2));
234 void gdbserver_t::process_requests()
236 // See https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html
238 while (!recv_buf
.empty()) {
239 std::vector
<uint8_t> packet
;
240 for (unsigned int i
= 0; i
< recv_buf
.size(); i
++) {
241 uint8_t b
= recv_buf
[i
];
243 if (packet
.empty() && expect_ack
&& b
== '+') {
244 fprintf(stderr
, "Received ack\n");
250 // Start of new packet.
251 if (!packet
.empty()) {
252 fprintf(stderr
, "Received malformed %ld-byte packet from debug client\n", packet
.size());
253 print_packet(packet
);
261 // Packets consist of $<packet-data>#<checksum>
262 // where <checksum> is
263 if (packet
.size() >= 4 &&
264 packet
[packet
.size()-3] == '#') {
265 handle_packet(packet
);
266 recv_buf
.consume(i
+1);
270 // There's a partial packet in the buffer. Wait until we get more data to
277 void gdbserver_t::handle_set_threadid(const std::vector
<uint8_t> &packet
)
279 if (packet
[2] == 'g' && packet
[3] == '0') {
280 // Use thread 0 for all operations.
287 void gdbserver_t::handle_halt_reason(const std::vector
<uint8_t> &packet
)
292 void gdbserver_t::handle_packet(const std::vector
<uint8_t> &packet
)
294 if (compute_checksum(packet
) != extract_checksum(packet
)) {
295 fprintf(stderr
, "Received %ld-byte packet with invalid checksum\n", packet
.size());
296 fprintf(stderr
, "Computed checksum: %x\n", compute_checksum(packet
));
297 print_packet(packet
);
302 fprintf(stderr
, "Received %ld-byte packet from debug client\n", packet
.size());
303 print_packet(packet
);
308 return handle_set_threadid(packet
);
310 return handle_halt_reason(packet
);
317 void gdbserver_t::handle()
327 this->process_requests();
330 void gdbserver_t::send(const char* msg
)
332 unsigned int length
= strlen(msg
);
333 send_buf
.append((const uint8_t *) msg
, length
);
336 void gdbserver_t::send_packet(const char* data
)
342 uint8_t checksum
= 0;
343 for ( ; *data
; data
++) {
346 char checksum_string
[3];
347 sprintf(checksum_string
, "%02x", checksum
);
348 send(checksum_string
);