gdb-server/main.c

357 lines
14 KiB
C
Raw Normal View History

2024-10-01 22:48:28 +00:00
#include <client.h>
2024-10-06 22:47:44 +00:00
#include <cmdbuf.h>
2024-10-07 04:55:44 +00:00
#include <request.h>
2024-10-01 22:48:28 +00:00
#include <stdbool.h>
#include <stdio.h>
2024-10-02 01:24:48 +00:00
#include <stdlib.h>
2024-10-01 22:48:28 +00:00
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
2024-10-02 01:24:48 +00:00
#include <vb.h>
2024-10-01 22:48:28 +00:00
const size_t BUFLEN = 8096;
const char* REGISTERS[] = {
"name:r0;bitsize:32;offset:0;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r1;bitsize:32;offset:4;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:fp;alt-name:r2;bitsize:32;offset:8;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0;generic:fp",
"name:sp;alt-name:r3;bitsize:32;offset:12;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0;generic:sp",
"name:gp;alt-name:r4;bitsize:32;offset:16;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:tp;alt-name:r5;bitsize:32;offset:20;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r6;bitsize:32;offset:24;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0;generic:arg1",
"name:r7;bitsize:32;offset:28;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0;generic:arg2",
"name:r8;bitsize:32;offset:32;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0;generic:arg3",
"name:r9;bitsize:32;offset:36;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0;generic:arg4",
"name:r10;bitsize:32;offset:40;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r11;bitsize:32;offset:44;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r12;bitsize:32;offset:48;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r13;bitsize:32;offset:52;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r14;bitsize:32;offset:56;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r15;bitsize:32;offset:60;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r16;bitsize:32;offset:64;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r17;bitsize:32;offset:68;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r18;bitsize:32;offset:72;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r19;bitsize:32;offset:76;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r20;bitsize:32;offset:80;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r21;bitsize:32;offset:84;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r22;bitsize:32;offset:88;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r23;bitsize:32;offset:92;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r24;bitsize:32;offset:96;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r25;bitsize:32;offset:100;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r26;bitsize:32;offset:104;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r27;bitsize:32;offset:108;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r28;bitsize:32;offset:112;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r29;bitsize:32;offset:116;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:r30;bitsize:32;offset:120;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0",
"name:lp;alt-name:r31;bitsize:32;offset:124;encoding:uint;format:hex;set:General Purpose Registers;dwarf:0;generic:ra",
2024-10-02 01:24:48 +00:00
"name:eipc;alt-name:sr0;bitsize:32;offset:128;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:eipsw;alt-name:sr1;bitsize:32;offset:132;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:fepc;alt-name:sr2;bitsize:32;offset:136;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:fepsw;alt-name:sr3;bitsize:32;offset:140;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:ecr;alt-name:sr4;bitsize:32;offset:144;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:psw;alt-name:sr5;bitsize:32;offset:148;encoding:uint;format:hex;set:Special Registers;dwarf:0;generic:flags",
"name:pir;alt-name:sr6;bitsize:32;offset:152;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:tkcw;alt-name:sr7;bitsize:32;offset:156;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:chcw;alt-name:sr24;bitsize:32;offset:160;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:adtre;alt-name:sr25;bitsize:32;offset:164;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:sr29;bitsize:32;offset:168;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:sr30;bitsize:32;offset:172;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:sr31;bitsize:32;offset:176;encoding:uint;format:hex;set:Special Registers;dwarf:0",
"name:pc;bitsize:32;offset:180;encoding:uint;format:hex;set:Special Registers;dwarf:0;generic:pc",
2024-10-01 22:48:28 +00:00
};
2024-10-02 01:24:48 +00:00
const uint32_t SYSTEM_REGISTERS[] = {
VB_EIPC,
VB_EIPSW,
VB_FEPC,
VB_FEPSW,
VB_ECR,
VB_PSW,
VB_PIR,
VB_TKCW,
VB_CHCW,
VB_ADTRE,
29,
30,
31,
};
2024-10-06 22:47:44 +00:00
const uint32_t PC_INDEX = 32 + 13;
2024-10-02 01:24:48 +00:00
2024-10-06 22:47:44 +00:00
int handle_command(RdbClient *client, CommandBuf *cmd, VB *sim) {
2024-10-01 22:48:28 +00:00
rdb_client_begin_packet(client);
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "\x03")) {
2024-10-02 01:24:48 +00:00
rdb_client_write_str(client, "T05thread:p1.t1;threads:p1.t1");
2024-10-01 22:48:28 +00:00
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "QStartNoAckMode")) {
2024-10-01 22:48:28 +00:00
client->should_ack = false;
rdb_client_write_str(client, "OK");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_str(cmd, "qSupported")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "no-resumed+;multiprocess;vContSupported;QNonStop+");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "QThreadSuffixSupported")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "OK");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "QListThreadsInStopReply")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "OK");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "qHostInfo")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "triple:");
rdb_client_write_str_hex(client, "v810-unknown-vb");
rdb_client_write_str(client, ";endian:little;ptrsize:4;");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "qProcessInfo")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "pid:1;triple:");
rdb_client_write_str_hex(client, "v810-unknown-vb");
rdb_client_write_str(client, "endian:little;ptrsize:4;");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_str(cmd, "qRegisterInfo")) {
uint32_t reg_no;
if (!cmd_match_hex_number(cmd, &reg_no)) return 1;
if (reg_no <= PC_INDEX) {
rdb_client_write_str(client, REGISTERS[reg_no]);
2024-10-01 22:48:28 +00:00
}
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "qfThreadInfo")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "mp1.t1");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "qsThreadInfo")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "l");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "vCont?")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "c;C;s;S");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "qVAttachOrWaitSupported")) {
2024-10-01 22:48:28 +00:00
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "qC")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "QCp1.t1");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_str(cmd, "p")) {
uint32_t reg_no;
if (!cmd_match_hex_number(cmd, &reg_no)) return 1;
2024-10-02 01:24:48 +00:00
int32_t reg_value;
if (reg_no == PC_INDEX) {
reg_value = vbGetProgramCounter(sim);
} else if (reg_no > 31) {
reg_value = vbGetSystemRegister(sim, SYSTEM_REGISTERS[reg_no - 32]);
} else {
reg_value = vbGetProgramRegister(sim, reg_no);
}
rdb_client_write_i32_hex(client, reg_value);
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_str(cmd, "P")) {
uint32_t reg_no;
char reg_bytes[4];
if (!cmd_match_hex_number(cmd, &reg_no)) return -1;
if (!cmd_match_str(cmd, "=")) return -1;
if (!cmd_match_hex_bytes(cmd, 4, reg_bytes)) return -1;
int32_t reg_value = ((uint32_t) (reg_bytes[3]) << 24) |
((uint32_t) (reg_bytes[2]) << 16) |
((uint32_t) (reg_bytes[1]) << 8) |
((uint32_t) reg_bytes[0]);
2024-10-02 01:24:48 +00:00
if (reg_no == PC_INDEX) {
vbSetProgramCounter(sim, reg_value);
} else if (reg_no > 31) {
vbSetSystemRegister(sim, SYSTEM_REGISTERS[reg_no - 32], reg_value);
} else {
vbSetProgramRegister(sim, reg_no, reg_value);
}
rdb_client_write_str(client, "OK");
2024-10-01 22:48:28 +00:00
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_str(cmd, "Hc-1")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "OK");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "c")) {
2024-10-01 22:48:28 +00:00
printf("running until we hit a breakpoint or the server stops us\n");
return 0;
}
2024-10-06 22:47:44 +00:00
if (cmd_match_only_str(cmd, "?")) {
2024-10-02 01:24:48 +00:00
rdb_client_write_str(client, "T00thread:p1.t1;threads:p1.t1;");
2024-10-01 22:48:28 +00:00
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_str(cmd, "qMemoryRegionInfo:")) {
2024-10-01 22:48:28 +00:00
rdb_client_write_str(client, "start:0;size:100000000;permissions:rx;name:");
rdb_client_write_str_hex(client, "ROM");
rdb_client_write_str(client, ";");
return rdb_client_send_packet(client);
}
2024-10-06 22:47:44 +00:00
if (cmd_match_str(cmd, "m")) {
// read memory
uint32_t address;
uint32_t len;
if (!cmd_match_hex_number(cmd, &address)) return -1;
if (!cmd_match_str(cmd, ",")) return -1;
if (!cmd_match_hex_number(cmd, &len)) return -1;
2024-10-01 22:48:28 +00:00
printf("read %d bytes from %d\n", len, address);
2024-10-06 22:47:44 +00:00
for (uint32_t i = 0; i < len; ++i) {
2024-10-02 01:27:40 +00:00
uint8_t byte = vbRead(sim, address + i, VB_U8);
rdb_client_write_i8_hex(client, byte);
2024-10-01 22:48:28 +00:00
}
return rdb_client_send_packet(client);
}
2024-10-07 04:55:44 +00:00
fprintf(stderr, "Unrecognized command.\n");
2024-10-01 22:48:28 +00:00
return rdb_client_send_packet(client);
}
2024-10-02 01:24:48 +00:00
int server(int connfd, VB *sim) {
2024-10-07 04:55:44 +00:00
RdbRequest req;
2024-10-01 22:48:28 +00:00
RdbClient client;
2024-10-07 04:55:44 +00:00
char buf[BUFLEN];
size_t len;
rdb_request_init(&req, connfd, buf, BUFLEN);
2024-10-01 22:48:28 +00:00
rdb_client_init(&client, connfd);
while (1) {
2024-10-07 04:55:44 +00:00
rdb_read_result_t result = rdb_request_read(&req, &len);
if (result == read_result_error) {
return -1;
} else if (result == read_result_disconnected) {
2024-10-01 22:48:28 +00:00
printf("client has disconnected\n");
return 0;
2024-10-07 04:55:44 +00:00
} else if (result == read_result_pending) {
// TODO: should run the emulator while we wait
continue;
2024-10-01 22:48:28 +00:00
} else {
printf("received command \"%.*s\"\n", (int) len, buf);
fflush(stdout);
2024-10-06 22:47:44 +00:00
CommandBuf cmd;
cmd.buf = buf;
cmd.len = len;
int res = handle_command(&client, &cmd, sim);
2024-10-01 22:48:28 +00:00
if (res != 0) {
return res;
}
2024-10-07 04:55:44 +00:00
rdb_request_reset(&req);
2024-10-01 22:48:28 +00:00
}
}
2024-10-02 01:24:48 +00:00
}
int readROM(VB *sim, char *filename) {
FILE *file = fopen(filename, "rb");
long size;
if (!file) {
perror("could not open file");
return 1;
}
if (fseek(file, 0, SEEK_END)) {
perror("could not seek file end");
return 1;
}
size = ftell(file);
if (size == -1) {
perror("could not read file size");
return 1;
}
if (fseek(file, 0, SEEK_SET)) {
perror("could not seek file start");
return 1;
}
2024-10-06 21:19:14 +00:00
uint8_t *rom = malloc(size);
if (!rom) {
perror("could not allocate ROM");
return 1;
}
fread(rom, 1, size, file);
2024-10-02 01:24:48 +00:00
if (ferror(file)) {
perror("could not read file");
return 1;
}
if (fclose(file)) {
perror("could not close file");
return 1;
}
2024-10-06 21:19:14 +00:00
vbSetCartROM(sim, rom, size);
2024-10-01 22:48:28 +00:00
2024-10-02 01:24:48 +00:00
return 0;
2024-10-01 22:48:28 +00:00
}
int main(int argc, char** argv) {
2024-10-02 01:24:48 +00:00
if (argc < 2) {
fprintf(stderr, "Please pass a ROM file\n");
return 1;
}
2024-10-06 21:19:14 +00:00
VB *sim = malloc(vbSizeOf());
if (!sim) {
return 1;
}
vbInit(sim);
if (readROM(sim, argv[1])) {
2024-10-02 01:24:48 +00:00
return 1;
}
2024-10-06 21:19:14 +00:00
vbSetProgramCounter(sim, 0x07000000);
2024-10-02 01:24:48 +00:00
2024-10-01 22:48:28 +00:00
short port;
2024-10-02 01:24:48 +00:00
if (argc > 2) {
2024-10-01 22:48:28 +00:00
char *end;
2024-10-02 01:24:48 +00:00
port = (short) strtol(argv[2], &end, 10);
if (argv[2] == end) {
2024-10-01 22:48:28 +00:00
perror("could not parse port");
return 1;
}
} else {
port = 8080;
}
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
perror("could not open socket");
return 1;
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
perror("could not bind socket");
return 1;
}
if (listen(fd, 1) == -1) {
perror("could not listen on socket");
return 1;
}
printf("connecting\n");
int connfd;
struct sockaddr_in cliaddr;
socklen_t cliaddrlen = sizeof(cliaddr);
connfd = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen);
if (connfd == -1) {
perror("could not accept connection");
return 1;
}
printf("connected\n");
2024-10-06 21:19:14 +00:00
int response = server(connfd, sim);
2024-10-01 22:48:28 +00:00
return close(connfd)
|| close(fd)
|| response;
}