GDBstub base implementation (gdb is happy)

This commit is contained in:
vhaudiquet 2023-10-08 13:02:50 +02:00
parent c466d7d175
commit 43629abbd4
2 changed files with 145 additions and 36 deletions

View File

@ -1,5 +1,7 @@
#include "gdbstub.h" #include "gdbstub.h"
#include "cpu/rv32cpu.h"
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -16,13 +18,80 @@ typedef struct sockaddr_in sockaddr_in_t;
typedef struct sockaddr sockaddr_t; typedef struct sockaddr sockaddr_t;
#define GDBSTUB_PORT 1234 #define GDBSTUB_PORT 1234
#define PACKET_BUFFER_SIZE 2048
socket_t gdbstub_server_socket; socket_t gdbstub_server_socket;
socket_t gdb_socket; socket_t gdb_socket;
void gdbstub_thread_gdb();
/* /*
* Starts a server that will listen for GDB connections * Receive a packet from client gdb
*/ * Ignores the ACK on the way, and only returns the packet (not initial '$' symbol)
*/
static void gdbstub_recv_packet(char* packet, ssize_t* size)
{
char data;
recv(gdb_socket, &data, 1, 0);
// Start of packet symbol is '$'
// Skip data that is not packet (should only be ACK '+')
if(data != '$')
return gdbstub_recv_packet(packet, size);
// Receive packet until end of packet '#' symbol
size_t i = 0;
do
{
recv(gdb_socket, packet + i, 1, 0);
i++;
} while(packet[i - 1] != '#');
// Receive checksum after end of packet symbol
recv(gdb_socket, packet + i, 1, 0);
recv(gdb_socket, packet + i + 1, 1, 0);
if(size) *size = i + 2;
}
/*
* Send a packet to client gdb
* Pass only the packet data as parameter to this function
*/
static void gdbstub_send_packet(char* packet, ssize_t size)
{
// Compute packet checksum
char end[4] = {0};
uint8_t sum = 0;
for(size_t i = 0; i < size; i++)
{
sum += packet[i];
}
snprintf(end, 4, "#%02x", sum);
// Send ACK to last packet, and begin of packet symbol
char begin[2] = {'+', '$'};
send(gdb_socket, begin, 2, 0);
// Send the actual data of packet
send(gdb_socket, packet, size, 0);
// Send 'end of packet' and checksum
send(gdb_socket, end, 3, 0);
}
/*
* Send a packet to client gdb saying we don't support asked feature
*/
static void gdbstub_send_unsupported()
{
char unsupported[] = "+$#00";
send(gdb_socket, unsupported, 5, 0);
}
/*
* Starts a server that will listen for GDB connections
*/
void gdbstub_start() void gdbstub_start()
{ {
socket_t sock = socket(AF_INET, SOCK_STREAM, 0); socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
@ -52,8 +121,8 @@ void gdbstub_start()
} }
/* /*
* Wait for a client (gdb) to connect to this server * Wait for a client (gdb) to connect to this server
*/ */
void gdbstub_wait_for_connection() void gdbstub_wait_for_connection()
{ {
sockaddr_in_t csin = {0}; sockaddr_in_t csin = {0};
@ -68,4 +137,44 @@ void gdbstub_wait_for_connection()
} }
gdb_socket = c_socket; gdb_socket = c_socket;
gdbstub_thread_gdb();
}
void gdbstub_thread_gdb()
{
while(1)
{
char packet[PACKET_BUFFER_SIZE];
ssize_t packet_size;
gdbstub_recv_packet(packet, &packet_size);
// printf("<-: %.*s\n", (int) packet_size, packet);
// Analyse packet to respond correctly
if(packet[0] == '?')
{
char* resp = "S05";
gdbstub_send_packet(resp, 3);
}
else if(packet[0] == 'g')
{
char resp[32 * 8 + 8 + 1] = {0};
// All general purpose registers in host byte order as chars
for(size_t i = 0; i < 32; i++)
{
uint32_t value = htonl(cpu0->regs.x[i]);
snprintf(resp + i * 8, 9, "%08x", value);
}
// PC register
uint32_t pc = htonl(cpu0->pc);
snprintf(resp + 32 * 8, 9, "%08x", pc);
// Final packet size, send packet
size_t size = 32 * 8 + 8;
gdbstub_send_packet(resp, size);
}
else gdbstub_send_unsupported();
}
} }

View File

@ -181,7 +181,7 @@ static void print_help()
printf(" " OPTION_SEPARATOR "h, " OPTION_SEPARATOR "?, --help\t\tPrint this help message\n"); printf(" " OPTION_SEPARATOR "h, " OPTION_SEPARATOR "?, --help\t\tPrint this help message\n");
printf(" " OPTION_SEPARATOR "v, --version\t\t\tPrint version information\n"); printf(" " OPTION_SEPARATOR "v, --version\t\t\tPrint version information\n");
printf(" " OPTION_SEPARATOR "m, --memory\t\t\tSet the simulated memory size, in MiB (max 4096)\n"); printf(" " OPTION_SEPARATOR "m, --memory\t\t\tSet the simulated memory size, in MiB (max 4096)\n");
printf(" " OPTION_SEPARATOR "s, --gdb-stub\t\t\tLaunch a gdb stub server, for remote gdb debugging\n"); printf(" " OPTION_SEPARATOR "s, --gdb-stub\t\tLaunch a gdb stub server (remote gdb debugging)\n");
} }
static void print_version() static void print_version()