Move RDB server logic to separate file
This commit is contained in:
		
							parent
							
								
									6ed78636a5
								
							
						
					
					
						commit
						1b273171ad
					
				| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
#ifndef RDBSERVER_REQUEST_H
 | 
					#ifndef RDBSERVER_REQUEST_H
 | 
				
			||||||
#define RDBSERVER_REQUEST_H
 | 
					#define RDBSERVER_REQUEST_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cmdbuf.h>
 | 
				
			||||||
#include <stddef.h>
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define INBUF_LEN 256
 | 
					#define INBUF_LEN 256
 | 
				
			||||||
| 
						 | 
					@ -29,15 +30,14 @@ typedef struct RdbRequest {
 | 
				
			||||||
        size_t index;
 | 
					        size_t index;
 | 
				
			||||||
    } inbuf;
 | 
					    } inbuf;
 | 
				
			||||||
    rdb_read_state_t state;
 | 
					    rdb_read_state_t state;
 | 
				
			||||||
    char *cmd;
 | 
					    char *outbuf;
 | 
				
			||||||
    size_t cmdlen;
 | 
					    size_t outbuflen;
 | 
				
			||||||
    size_t outlen;
 | 
					 | 
				
			||||||
    char chk;
 | 
					    char chk;
 | 
				
			||||||
} RdbRequest;
 | 
					} RdbRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void rdb_request_init(RdbRequest *req, int connfd, char *cmd, size_t cmdlen);
 | 
					void rdb_request_init(RdbRequest *req, int connfd, char *cmd, size_t cmdlen);
 | 
				
			||||||
void rdb_request_reset(RdbRequest *req);
 | 
					void rdb_request_reset(RdbRequest *req);
 | 
				
			||||||
void rdb_request_set_blocking(RdbRequest *req, bool blocking);
 | 
					void rdb_request_set_blocking(RdbRequest *req, bool blocking);
 | 
				
			||||||
rdb_read_result_t rdb_request_read(RdbRequest *req, size_t *len);
 | 
					rdb_read_result_t rdb_request_read(RdbRequest *req, CommandBuf *cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					#ifndef RDBSERVER_SERVER_H_
 | 
				
			||||||
 | 
					#define RDBSERVER_SERVER_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <client.h>
 | 
				
			||||||
 | 
					#include <cmdbuf.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <vb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int handle_command(RdbClient *client, CommandBuf *cmd, VB *sim, bool *running);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										218
									
								
								main.c
								
								
								
								
							
							
						
						
									
										218
									
								
								main.c
								
								
								
								
							| 
						 | 
					@ -1,9 +1,8 @@
 | 
				
			||||||
#include <client.h>
 | 
					#include <client.h>
 | 
				
			||||||
#include <cmdbuf.h>
 | 
					#include <cmdbuf.h>
 | 
				
			||||||
#include <request.h>
 | 
					#include <request.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <server.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <netinet/in.h>
 | 
					#include <netinet/in.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
| 
						 | 
					@ -11,217 +10,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const size_t BUFLEN = 8096;
 | 
					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",
 | 
					 | 
				
			||||||
    "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",
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const uint32_t PC_INDEX = 32 + 13;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int handle_command(RdbClient *client, CommandBuf *cmd, VB *sim, bool *running) {
 | 
					 | 
				
			||||||
    rdb_client_begin_packet(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "\x03")) {
 | 
					 | 
				
			||||||
        *running = false;
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "T05thread:p1.t1;threads:p1.t1");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "QStartNoAckMode")) {
 | 
					 | 
				
			||||||
        client->should_ack = false;
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "OK");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_str(cmd, "qSupported")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "no-resumed+;multiprocess;vContSupported;QNonStop+");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "QThreadSuffixSupported")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "OK");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "QListThreadsInStopReply")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "OK");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "qHostInfo")) {
 | 
					 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "qProcessInfo")) {
 | 
					 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_str(cmd, "qRegisterInfo")) {
 | 
					 | 
				
			||||||
        uint32_t reg_no;
 | 
					 | 
				
			||||||
        if (!cmd_match_hex_number(cmd, ®_no)) return 1;
 | 
					 | 
				
			||||||
        if (reg_no <= PC_INDEX) {
 | 
					 | 
				
			||||||
            rdb_client_write_str(client, REGISTERS[reg_no]);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "qfThreadInfo")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "mp1.t1");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "qsThreadInfo")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "l");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "vCont?")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "c;C;s;S");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "qVAttachOrWaitSupported")) {
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "qC")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "QCp1.t1");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_str(cmd, "p")) {
 | 
					 | 
				
			||||||
        uint32_t reg_no;
 | 
					 | 
				
			||||||
        if (!cmd_match_hex_number(cmd, ®_no)) return 1;
 | 
					 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_str(cmd, "P")) {
 | 
					 | 
				
			||||||
        uint32_t reg_no;
 | 
					 | 
				
			||||||
        char reg_bytes[4];
 | 
					 | 
				
			||||||
        if (!cmd_match_hex_number(cmd, ®_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]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_str(cmd, "Hc-1")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "OK");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "c")) {
 | 
					 | 
				
			||||||
        printf("running until we hit a breakpoint or the server stops us\n");
 | 
					 | 
				
			||||||
        *running = true;
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_only_str(cmd, "?")) {
 | 
					 | 
				
			||||||
        rdb_client_write_str(client, "T00thread:p1.t1;threads:p1.t1;");
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (cmd_match_str(cmd, "qMemoryRegionInfo:")) {
 | 
					 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    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;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        printf("read %d bytes from %d\n", len, address);
 | 
					 | 
				
			||||||
        for (uint32_t i = 0; i < len; ++i) {
 | 
					 | 
				
			||||||
            uint8_t byte = vbRead(sim, address + i, VB_U8);
 | 
					 | 
				
			||||||
            rdb_client_write_i8_hex(client, byte);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fprintf(stderr, "Unrecognized command.\n");
 | 
					 | 
				
			||||||
    return rdb_client_send_packet(client);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int server(int connfd, VB *sim) {
 | 
					int server(int connfd, VB *sim) {
 | 
				
			||||||
    RdbRequest req;
 | 
					    RdbRequest req;
 | 
				
			||||||
    RdbClient client;
 | 
					    RdbClient client;
 | 
				
			||||||
    char buf[BUFLEN];
 | 
					    char buf[BUFLEN];
 | 
				
			||||||
    size_t len;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rdb_request_init(&req, connfd, buf, BUFLEN);
 | 
					    rdb_request_init(&req, connfd, buf, BUFLEN);
 | 
				
			||||||
    rdb_client_init(&client, connfd);
 | 
					    rdb_client_init(&client, connfd);
 | 
				
			||||||
| 
						 | 
					@ -229,7 +21,8 @@ int server(int connfd, VB *sim) {
 | 
				
			||||||
    bool running = false;
 | 
					    bool running = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (1) {
 | 
					    while (1) {
 | 
				
			||||||
        rdb_read_result_t result = rdb_request_read(&req, &len);
 | 
					        CommandBuf cmd;
 | 
				
			||||||
 | 
					        rdb_read_result_t result = rdb_request_read(&req, &cmd);
 | 
				
			||||||
        if (result == read_result_error) {
 | 
					        if (result == read_result_error) {
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
        } else if (result == read_result_disconnected) {
 | 
					        } else if (result == read_result_disconnected) {
 | 
				
			||||||
| 
						 | 
					@ -242,11 +35,8 @@ int server(int connfd, VB *sim) {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            printf("received command \"%.*s\"\n", (int) len, buf);
 | 
					            printf("received command \"%.*s\"\n", (int) cmd.len, cmd.buf);
 | 
				
			||||||
            fflush(stdout);
 | 
					            fflush(stdout);
 | 
				
			||||||
            CommandBuf cmd;
 | 
					 | 
				
			||||||
            cmd.buf = buf;
 | 
					 | 
				
			||||||
            cmd.len = len;
 | 
					 | 
				
			||||||
            int res = handle_command(&client, &cmd, sim, &running);
 | 
					            int res = handle_command(&client, &cmd, sim, &running);
 | 
				
			||||||
            if (res != 0) {
 | 
					            if (res != 0) {
 | 
				
			||||||
                return res;
 | 
					                return res;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								makefile
								
								
								
								
							
							
						
						
									
										3
									
								
								makefile
								
								
								
								
							| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
build:
 | 
					build:
 | 
				
			||||||
	@mkdir -p build
 | 
						@mkdir -p build
 | 
				
			||||||
	@gcc main.c client.c cmdbuf.c hex.c request.c ../vbtest/vb.c -I include -I ../vbtest \
 | 
						@gcc main.c client.c cmdbuf.c hex.c request.c server.c ../vbtest/vb.c \
 | 
				
			||||||
 | 
						-I include -I ../vbtest \
 | 
				
			||||||
	-Werror -Wall -Wextra -Wpedantic \
 | 
						-Werror -Wall -Wextra -Wpedantic \
 | 
				
			||||||
	-Wno-unused-parameter -Wno-unused-function \
 | 
						-Wno-unused-parameter -Wno-unused-function \
 | 
				
			||||||
	-o ./build/rdb
 | 
						-o ./build/rdb
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										22
									
								
								request.c
								
								
								
								
							
							
						
						
									
										22
									
								
								request.c
								
								
								
								
							| 
						 | 
					@ -5,10 +5,9 @@
 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void rdb_request_init(RdbRequest *req, int connfd, char *cmd, size_t cmdlen) {
 | 
					void rdb_request_init(RdbRequest *req, int connfd, char *buf, size_t buflen) {
 | 
				
			||||||
    req->connfd = connfd;
 | 
					    req->connfd = connfd;
 | 
				
			||||||
    req->cmd = cmd;
 | 
					    req->outbuf = buf;
 | 
				
			||||||
    req->cmdlen = cmdlen;
 | 
					 | 
				
			||||||
    req->blocking = true;
 | 
					    req->blocking = true;
 | 
				
			||||||
    rdb_request_reset(req);
 | 
					    rdb_request_reset(req);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -17,7 +16,6 @@ void rdb_request_reset(RdbRequest *req) {
 | 
				
			||||||
    req->state = read_state_header;
 | 
					    req->state = read_state_header;
 | 
				
			||||||
    req->inbuf.len = 0;
 | 
					    req->inbuf.len = 0;
 | 
				
			||||||
    req->inbuf.index = 0;
 | 
					    req->inbuf.index = 0;
 | 
				
			||||||
    req->outlen = 0;
 | 
					 | 
				
			||||||
    req->chk = 0;
 | 
					    req->chk = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,12 +45,15 @@ static rdb_read_result_t read_char(RdbRequest *req, char *in) {
 | 
				
			||||||
    return read_result_success;
 | 
					    return read_result_success;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rdb_read_result_t rdb_request_read(RdbRequest *req, size_t *len) {
 | 
					rdb_read_result_t rdb_request_read(RdbRequest *req, CommandBuf *cmd) {
 | 
				
			||||||
    rdb_read_result_t res;
 | 
					    rdb_read_result_t res;
 | 
				
			||||||
    char in;
 | 
					    char in;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (req->state) {
 | 
					    switch (req->state) {
 | 
				
			||||||
    case read_state_header:
 | 
					    case read_state_header:
 | 
				
			||||||
 | 
					        cmd->buf = req->outbuf;
 | 
				
			||||||
 | 
					        cmd->len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // read any acknowledgements and continue
 | 
					        // read any acknowledgements and continue
 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
            res = read_char(req, &in);
 | 
					            res = read_char(req, &in);
 | 
				
			||||||
| 
						 | 
					@ -66,8 +67,8 @@ rdb_read_result_t rdb_request_read(RdbRequest *req, size_t *len) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (in == '\x03') {
 | 
					        if (in == '\x03') {
 | 
				
			||||||
            // interrupt from the server
 | 
					            // interrupt from the server
 | 
				
			||||||
            req->cmd[0] = in;
 | 
					            cmd->buf[0] = in;
 | 
				
			||||||
            req->outlen = 1;
 | 
					            cmd->len = 1;
 | 
				
			||||||
            return read_result_success;
 | 
					            return read_result_success;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,17 +99,17 @@ rdb_read_result_t rdb_request_read(RdbRequest *req, size_t *len) {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (req->outlen >= req->cmdlen) {
 | 
					            if (cmd->len >= req->outbuflen) {
 | 
				
			||||||
                // ran out of room in the buffer
 | 
					                // ran out of room in the buffer
 | 
				
			||||||
                fprintf(stderr, "packet too big for buffer\n");
 | 
					                fprintf(stderr, "packet too big for buffer\n");
 | 
				
			||||||
                return read_result_error;
 | 
					                return read_result_error;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (req->state == read_state_body_escape) {
 | 
					            if (req->state == read_state_body_escape) {
 | 
				
			||||||
                req->cmd[req->outlen++] = in ^ 0x20;
 | 
					                cmd->buf[cmd->len++] = in ^ 0x20;
 | 
				
			||||||
                req->state = read_state_body;
 | 
					                req->state = read_state_body;
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                req->cmd[req->outlen++] = in;
 | 
					                cmd->buf[cmd->len++] = in;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        req->state = read_state_checksum_1;
 | 
					        req->state = read_state_checksum_1;
 | 
				
			||||||
| 
						 | 
					@ -144,7 +145,6 @@ rdb_read_result_t rdb_request_read(RdbRequest *req, size_t *len) {
 | 
				
			||||||
            return read_result_error;
 | 
					            return read_result_error;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        *len = req->outlen;
 | 
					 | 
				
			||||||
        return read_result_success;
 | 
					        return read_result_success;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        fprintf(stderr, "invalid state\n");
 | 
					        fprintf(stderr, "invalid state\n");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,228 @@
 | 
				
			||||||
 | 
					#include <server.h>
 | 
				
			||||||
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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",
 | 
				
			||||||
 | 
					    "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",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const uint32_t PC_INDEX = 32 + 13;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int handle_command(RdbClient *client, CommandBuf *cmd, VB *sim, bool *running) {
 | 
				
			||||||
 | 
					    rdb_client_begin_packet(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "QStartNoAckMode")) {
 | 
				
			||||||
 | 
					        // The debugger is asking us to no longer ACK messages.
 | 
				
			||||||
 | 
					        // Note that we ack THIS response, because we already called rdb_client_begin_packet.
 | 
				
			||||||
 | 
					        client->should_ack = false;
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "OK");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_str(cmd, "qSupported")) {
 | 
				
			||||||
 | 
					        // The debugger is asking for a list of features we support.
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "no-resumed+;multiprocess;vContSupported;QNonStop+");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "QThreadSuffixSupported")) {
 | 
				
			||||||
 | 
					        // The debugger is asking us to include the current thread as a suffix to some responses.
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "OK");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "QListThreadsInStopReply")) {
 | 
				
			||||||
 | 
					        // The debugger is asking us to list all threads whenever we stop running.
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "OK");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "qHostInfo")) {
 | 
				
			||||||
 | 
					        // The debugger is asking us to describe the "host machine" getting debugged.
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "qProcessInfo")) {
 | 
				
			||||||
 | 
					        // The debugger is asking us to describe the "process" getting debugged.
 | 
				
			||||||
 | 
					        // We make up a process with id 1.
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_str(cmd, "qRegisterInfo")) {
 | 
				
			||||||
 | 
					        // The debugger is asking for information about a specific register.
 | 
				
			||||||
 | 
					        uint32_t reg_no;
 | 
				
			||||||
 | 
					        if (!cmd_match_hex_number(cmd, ®_no)) return 1;
 | 
				
			||||||
 | 
					        if (reg_no <= PC_INDEX) {
 | 
				
			||||||
 | 
					            rdb_client_write_str(client, REGISTERS[reg_no]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "qfThreadInfo")) {
 | 
				
			||||||
 | 
					        // The debugger is asking us to list all threads. Return a list with "thread 1".
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "mp1.t1");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "qsThreadInfo")) {
 | 
				
			||||||
 | 
					        // The debugger is asking us to list all threads.
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "l");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "vCont?")) {
 | 
				
			||||||
 | 
					        // The debugger is asking which vCont commands we support.
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "c;C;s;S");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "qC")) {
 | 
				
			||||||
 | 
					        // The debugger is asking for the current thread id. Return "thread 1".
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "QCp1.t1");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_str(cmd, "p")) {
 | 
				
			||||||
 | 
					        // read a register.
 | 
				
			||||||
 | 
					        uint32_t reg_no;
 | 
				
			||||||
 | 
					        if (!cmd_match_hex_number(cmd, ®_no)) return 1;
 | 
				
			||||||
 | 
					        if (reg_no > PC_INDEX) {
 | 
				
			||||||
 | 
					            return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_str(cmd, "P")) {
 | 
				
			||||||
 | 
					        // write a register.
 | 
				
			||||||
 | 
					        uint32_t reg_no;
 | 
				
			||||||
 | 
					        char reg_bytes[4];
 | 
				
			||||||
 | 
					        if (!cmd_match_hex_number(cmd, ®_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]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (reg_no > PC_INDEX) {
 | 
				
			||||||
 | 
					            return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        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");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_str(cmd, "Hc-1")) {
 | 
				
			||||||
 | 
					        // Set the "current thread" for future commands to all threads (thread -1).
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "OK");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "c")) {
 | 
				
			||||||
 | 
					        // The debugger has told us to run until we are stopped.
 | 
				
			||||||
 | 
					        // Don't send a response to this until we receive an ETX (when the debugger pauses us).
 | 
				
			||||||
 | 
					        *running = true;
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "\x03")) {
 | 
				
			||||||
 | 
					        // Received an ETX, indicating that the server wants to cancel the "c" command from before.
 | 
				
			||||||
 | 
					        *running = false;
 | 
				
			||||||
 | 
					        // Send the response to the "c" command from before.
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "T05thread:p1.t1;threads:p1.t1");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (cmd_match_only_str(cmd, "?")) {
 | 
				
			||||||
 | 
					        // The debugger has asked us why we stopped
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "T");
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, *running ? "00" : "05");
 | 
				
			||||||
 | 
					        rdb_client_write_str(client, "thread:p1.t1;threads:p1.t1;");
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (uint32_t i = 0; i < len; ++i) {
 | 
				
			||||||
 | 
					            uint8_t byte = vbRead(sim, address + i, VB_U8);
 | 
				
			||||||
 | 
					            rdb_client_write_i8_hex(client, byte);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fprintf(stderr, "Unrecognized command.\n");
 | 
				
			||||||
 | 
					    return rdb_client_send_packet(client);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue