Support more function.
This commit is contained in:
parent
06775f841a
commit
3514600e30
|
@ -59,6 +59,9 @@
|
|||
"ctype.h": "c",
|
||||
"gdbstub.h": "c",
|
||||
"pthread.h": "c",
|
||||
"enums.h": "c"
|
||||
"enums.h": "c",
|
||||
"ctime": "c",
|
||||
"iomanip": "c",
|
||||
"sstream": "c"
|
||||
}
|
||||
}
|
|
@ -3,6 +3,39 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Helper function for error checking after strtol() and the like
|
||||
*/
|
||||
static int check_strtox_error(const char *nptr, char *ep, const char **endptr, bool check_zero, int libc_errno) {
|
||||
assert(ep >= nptr);
|
||||
|
||||
/* Windows has a bug in that it fails to parse 0 from "0x" in base 16 */
|
||||
if (check_zero && ep == nptr && libc_errno == 0) {
|
||||
char *tmp;
|
||||
|
||||
errno = 0;
|
||||
if (strtol(nptr, &tmp, 10) == 0 && errno == 0 && (*tmp == 'x' || *tmp == 'X')) {
|
||||
ep = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (endptr) {
|
||||
*endptr = ep;
|
||||
}
|
||||
|
||||
/* Turn "no conversion" into an error */
|
||||
if (libc_errno == 0 && ep == nptr) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Fail when we're expected to consume the string, but didn't */
|
||||
if (!endptr && *ep) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -libc_errno;
|
||||
}
|
||||
|
||||
int qemu_strtoul(const char *nptr, const char **endptr, int base, unsigned long *result) {
|
||||
char *ep;
|
||||
|
||||
|
@ -21,7 +54,7 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base, unsigned long
|
|||
if (errno == ERANGE) {
|
||||
*result = -1;
|
||||
}
|
||||
return 0;
|
||||
return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
|
||||
}
|
||||
|
||||
int qemu_strtou64(const char *nptr, const char **endptr, int base, uint64_t *result) {
|
||||
|
@ -44,5 +77,5 @@ int qemu_strtou64(const char *nptr, const char **endptr, int base, uint64_t *res
|
|||
if (errno == ERANGE) {
|
||||
*result = -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
|
||||
}
|
|
@ -220,7 +220,10 @@ static void gdb_set_cpu_pc(vaddr pc) {
|
|||
cpu_set_pc(cpu, pc);
|
||||
}
|
||||
|
||||
void gdb_append_thread_id(CPUState *cpu, GString *buf) { g_string_append_printf(buf, "%02x", 1); }
|
||||
void gdb_append_thread_id(CPUState *cpu, GString *buf) {
|
||||
g_string_append_printf(buf, "p%02x.%02x", 1, 1);
|
||||
// g_string_append_printf(buf, "%02x", 1);
|
||||
}
|
||||
|
||||
static GDBThreadIdKind read_thread_id(const char *buf, const char **end_buf, uint32_t *pid, uint32_t *tid) {
|
||||
unsigned long p, t;
|
||||
|
@ -345,10 +348,10 @@ static int gdb_handle_vcont(const char *p) {
|
|||
break;
|
||||
|
||||
case GDB_ALL_THREADS:
|
||||
process = gdb_get_process();
|
||||
if (!process->attached) {
|
||||
return -EINVAL;
|
||||
}
|
||||
// process = gdb_get_process();
|
||||
// if (!process->attached) {
|
||||
// return -EINVAL;
|
||||
// }
|
||||
cpu = get_cpu();
|
||||
if (cpu) {
|
||||
if (newstates[cpu->cpu_index] == 1) {
|
||||
|
@ -856,7 +859,6 @@ static void handle_v_commands(GArray *params, void *user_ctx) {
|
|||
if (!params->len) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!process_string_cmd(gdb_get_cmd_param(params, 0)->data, gdb_v_commands_table, ARRAY_SIZE(gdb_v_commands_table))) {
|
||||
gdb_put_packet("");
|
||||
}
|
||||
|
@ -915,6 +917,11 @@ static void handle_query_curr_tid(GArray *params, void *user_ctx) {
|
|||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_query_gdb_server_version(GArray *params, void *user_ctx) {
|
||||
g_string_printf(gdb_state.str_buf, "name:system-riscv;version:1.9;");
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_query_threads(GArray *params, void *user_ctx) {
|
||||
if (!gdb_state.query_cpu) {
|
||||
gdb_put_packet("l");
|
||||
|
@ -925,11 +932,6 @@ static void handle_query_threads(GArray *params, void *user_ctx) {
|
|||
gdb_state.query_cpu = 0;
|
||||
}
|
||||
|
||||
static void handle_query_gdb_server_version(GArray *params, void *user_ctx) {
|
||||
g_string_printf(gdb_state.str_buf, "name:qemu-system-riscv;version:1.9;");
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
|
||||
static void handle_query_first_threads(GArray *params, void *user_ctx) {
|
||||
gdb_state.query_cpu = get_cpu();
|
||||
handle_query_threads(params, user_ctx);
|
||||
|
|
|
@ -240,4 +240,6 @@ void cpu_register_gdb_commands();
|
|||
int cpu_common_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
void gdb_vm_state_change();
|
||||
|
||||
#endif /* GDBSTUB_INTERNALS_H */
|
||||
|
|
155
gdbstub/system.c
155
gdbstub/system.c
|
@ -10,7 +10,9 @@
|
|||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "commands.h"
|
||||
#include "cpu.h"
|
||||
|
@ -312,40 +314,71 @@ bool runstate_is_running() {
|
|||
/////// local cpu operation
|
||||
///////
|
||||
|
||||
void vm_stop() { get_cpu()->running = false; }
|
||||
void vm_start() { get_cpu()->running = true; }
|
||||
void vm_stop() {
|
||||
std::cout << "CPU=>vm_stop" << std::endl;
|
||||
get_cpu()->running = false;
|
||||
}
|
||||
void vm_start() {
|
||||
std::cout << "CPU=>vm_start" << std::endl;
|
||||
get_cpu()->running = true;
|
||||
}
|
||||
|
||||
void cpu_synchronize_state(CPUState *cpu) {}
|
||||
void gdb_exit(int i) {};
|
||||
void gdb_qemu_exit(int i) {};
|
||||
|
||||
void gdb_breakpoint_remove_all(CPUState *cs) {}
|
||||
int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) { return 0; }
|
||||
int gdb_breakpoint_remove(CPUState *cs, int type, vaddr addr, vaddr len) { return 0; }
|
||||
void gdb_breakpoint_remove_all(CPUState *cs) { std::cout << "CPU=>gdb_breakpoint_remove_all" << std::endl; }
|
||||
int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) {
|
||||
std::cout << "CPU=>gdb_breakpoint_insert" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
int gdb_breakpoint_remove(CPUState *cs, int type, vaddr addr, vaddr len) {
|
||||
std::cout << "CPU=>gdb_breakpoint_remove" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cpu_physical_memory_write(hwaddr addr, const void *buf, hwaddr len) {}
|
||||
static inline void cpu_physical_memory_read(hwaddr addr, const void *buf, hwaddr len) {}
|
||||
static inline void cpu_physical_memory_write(hwaddr addr, const void *buf, hwaddr len) {
|
||||
std::cout << "CPU=>memory_write addr:0x" << std::hex << addr << " len:0x" << len << std::endl;
|
||||
std::cout << "CPU=>memory_write data:";
|
||||
for (int i = 0; i < len; i++) {
|
||||
uint8_t d = *((uint8_t *)buf + i);
|
||||
std::cout << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(d);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
static inline void cpu_physical_memory_read(hwaddr addr, const void *buf, hwaddr len) {
|
||||
std::cout << "CPU=>memory_read addr:0x" << std::hex << addr << " len:0x" << len << std::endl;
|
||||
}
|
||||
|
||||
bool runstate_needs_reset(void) { return false; }
|
||||
bool vm_prepare_start(bool step_requested) { return true; }
|
||||
bool vm_prepare_start(bool step_requested) { return false; }
|
||||
|
||||
void gdb_handle_file_io(GArray *params, void *user_ctx) {}
|
||||
void gdb_handle_file_io(GArray *params, void *user_ctx) { std::cout << "CPU=>gdb_handle_file_io" << std::endl; }
|
||||
void gdb_disable_syscalls(void) {}
|
||||
|
||||
void cpu_single_step(CPUState *cpu, int enabled) {}
|
||||
void cpu_single_step(CPUState *cpu, int enabled) { std::cout << "CPU=>cpu_single_step" << std::endl; }
|
||||
|
||||
void cpu_resume(CPUState *cpu) {
|
||||
cpu->stop = false;
|
||||
cpu->stopped = false;
|
||||
std::cout << "CPU=>cpu_resume" << std::endl;
|
||||
|
||||
// g_autoptr(GString) buf = g_string_new(NULL);
|
||||
// g_string_printf(buf, "T%02xthread:p01.01;", 05);
|
||||
// gdb_put_packet(buf->str);
|
||||
}
|
||||
|
||||
int cpu_common_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg) {
|
||||
uint64_t val = 0;
|
||||
g_byte_array_append(buf, (uint8_t *)&val, 8);
|
||||
std::cout << "CPU=>read_register reg:0x" << reg << std::endl;
|
||||
return 8;
|
||||
}
|
||||
|
||||
int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg) { return 0; }
|
||||
int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg) {
|
||||
std::cout << "CPU=>write_register reg:0x" << reg << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gdb_target_memory_rw_debug(CPUState *cpu, hwaddr addr, uint8_t *buf, int len, bool is_write) {
|
||||
if (is_write) {
|
||||
|
@ -357,7 +390,105 @@ int gdb_target_memory_rw_debug(CPUState *cpu, hwaddr addr, uint8_t *buf, int len
|
|||
}
|
||||
|
||||
void gdb_continue(void) {
|
||||
std::cout << "CPU=>gdb_continue" << std::endl;
|
||||
|
||||
if (!runstate_needs_reset()) {
|
||||
vm_start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static void gdb_vm_state_change() {
|
||||
// CPUState *cpu = gdbserver_state.c_cpu;
|
||||
// g_autoptr(GString) buf = g_string_new(NULL);
|
||||
// g_autoptr(GString) tid = g_string_new(NULL);
|
||||
// const char *type;
|
||||
// int ret;
|
||||
|
||||
// if (running || gdbserver_state.state == RS_INACTIVE) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// /* Is there a GDB syscall waiting to be sent? */
|
||||
// if (gdb_handled_syscall()) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (cpu == NULL) {
|
||||
// /* No process attached */
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (!gdbserver_state.allow_stop_reply) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// gdb_append_thread_id(cpu, tid);
|
||||
|
||||
// switch (state) {
|
||||
// case RUN_STATE_DEBUG:
|
||||
// if (cpu->watchpoint_hit) {
|
||||
// switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) {
|
||||
// case BP_MEM_READ:
|
||||
// type = "r";
|
||||
// break;
|
||||
// case BP_MEM_ACCESS:
|
||||
// type = "a";
|
||||
// break;
|
||||
// default:
|
||||
// type = "";
|
||||
// break;
|
||||
// }
|
||||
// trace_gdbstub_hit_watchpoint(type, gdb_get_cpu_index(cpu), cpu->watchpoint_hit->vaddr);
|
||||
// g_string_printf(buf, "T%02xthread:%s;%swatch:%" VADDR_PRIx ";", GDB_SIGNAL_TRAP, tid->str, type,
|
||||
// cpu->watchpoint_hit->vaddr);
|
||||
// cpu->watchpoint_hit = NULL;
|
||||
// goto send_packet;
|
||||
// } else {
|
||||
// trace_gdbstub_hit_break();
|
||||
// }
|
||||
// if (tcg_enabled()) {
|
||||
// tb_flush(cpu);
|
||||
// }
|
||||
// ret = GDB_SIGNAL_TRAP;
|
||||
// break;
|
||||
// case RUN_STATE_PAUSED:
|
||||
// trace_gdbstub_hit_paused();
|
||||
// ret = GDB_SIGNAL_INT;
|
||||
// break;
|
||||
// case RUN_STATE_SHUTDOWN:
|
||||
// trace_gdbstub_hit_shutdown();
|
||||
// ret = GDB_SIGNAL_QUIT;
|
||||
// break;
|
||||
// case RUN_STATE_IO_ERROR:
|
||||
// trace_gdbstub_hit_io_error();
|
||||
// ret = GDB_SIGNAL_STOP;
|
||||
// break;
|
||||
// case RUN_STATE_WATCHDOG:
|
||||
// trace_gdbstub_hit_watchdog();
|
||||
// ret = GDB_SIGNAL_ALRM;
|
||||
// break;
|
||||
// case RUN_STATE_INTERNAL_ERROR:
|
||||
// trace_gdbstub_hit_internal_error();
|
||||
// ret = GDB_SIGNAL_ABRT;
|
||||
// break;
|
||||
// case RUN_STATE_SAVE_VM:
|
||||
// case RUN_STATE_RESTORE_VM:
|
||||
// return;
|
||||
// case RUN_STATE_FINISH_MIGRATE:
|
||||
// ret = GDB_SIGNAL_XCPU;
|
||||
// break;
|
||||
// default:
|
||||
// trace_gdbstub_hit_unknown(state);
|
||||
// ret = GDB_SIGNAL_UNKNOWN;
|
||||
// break;
|
||||
// }
|
||||
// gdb_set_stop_cpu(cpu);
|
||||
// g_string_printf(buf, "T%02xthread:%s;", ret, tid->str);
|
||||
|
||||
// send_packet:
|
||||
// gdb_put_packet(buf->str);
|
||||
// gdbserver_state.allow_stop_reply = false;
|
||||
|
||||
// /* disable single step if it was enabled */
|
||||
// cpu_single_step(cpu, 0);
|
||||
// }
|
|
@ -90,7 +90,7 @@ void conn_recv_packet(conn_t *conn) {
|
|||
|
||||
packet_t *conn_pop_packet(conn_t *conn) {
|
||||
packet_t *pkt = pktbuf_pop_packet(&conn->pktbuf);
|
||||
if (pkt) printf("packet = %s\n", pkt->data);
|
||||
if (pkt) printf("receive = %s\n", pkt->data);
|
||||
return pkt;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue