Created
July 25, 2019 08:02
-
-
Save YiChenChai/06382e49a4dcd49a1d64f240fa8c35df to your computer and use it in GitHub Desktop.
Small patch to add GDB remote file download capabilities to QEMU
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/gdbstub.c b/gdbstub.c | |
index b470aec..54cc026 100644 | |
--- a/gdbstub.c | |
+++ b/gdbstub.c | |
@@ -1907,6 +1907,91 @@ static void handle_v_kill(GdbCmdContext *gdb_ctx, void *user_ctx) | |
exit(0); | |
} | |
+static void handle_v_file_open(GdbCmdContext *gdb_ctx, void *user_ctx) | |
+{ | |
+ const char *hex_name = gdb_ctx->params[0].data; | |
+ char *p; | |
+ int len = 0; | |
+ int fd; | |
+ unsigned long mask, mode; | |
+ CPUState *cpu; | |
+ GDBProcess *process; | |
+ | |
+ while (hex_name[len] != ',') len++; | |
+ hextomem(gdb_ctx->mem_buf, hex_name, len); | |
+ gdb_ctx->mem_buf[len / 2 + 1] = '\0'; | |
+ p = (char *)gdb_ctx->mem_buf; | |
+ // error_report("Param 1: %s", (char*)(gdb_ctx->mem_buf)); | |
+ // error_report("Param 2: %lu", gdb_ctx->params[1].val_ul); | |
+ // error_report("Param 3: %lu", gdb_ctx->params[2].val_ul); | |
+ mask = gdb_ctx->params[1].val_ul; | |
+ mode = gdb_ctx->params[2].val_ul; | |
+ | |
+ process = gdb_get_cpu_process(gdb_ctx->s, gdb_ctx->s->g_cpu); | |
+ cpu = get_first_cpu_in_process(gdb_ctx->s, process); | |
+ fd = do_openat(cpu->env_ptr, AT_FDCWD, p, mask, mode); | |
+ error_report("FD: %d", fd); | |
+ snprintf(gdb_ctx->str_buf, 1024, "F%d", fd); | |
+ put_packet(gdb_ctx->s, gdb_ctx->str_buf); | |
+} | |
+ | |
+static void handle_v_file_read(GdbCmdContext *gdb_ctx, void *user_ctx) | |
+{ | |
+ unsigned long fd, sz, offset; | |
+ fd = gdb_ctx->params[0].val_ul; | |
+ sz = gdb_ctx->params[1].val_ul; | |
+ offset = gdb_ctx->params[2].val_ul; | |
+ | |
+ // error_report("Read param 2: %lu", gdb_ctx->params[1].val_ul); | |
+ // error_report("Read param 3: %lu", gdb_ctx->params[2].val_ul); | |
+ | |
+ lseek(fd, offset, SEEK_SET); | |
+ if (sz > 1024) sz = 1024; | |
+ int ret = -TARGET_ERESTARTSYS; | |
+ CPUState *cpu; | |
+ GDBProcess *process; | |
+ process = gdb_get_cpu_process(gdb_ctx->s, gdb_ctx->s->g_cpu); | |
+ cpu = get_first_cpu_in_process(gdb_ctx->s, process); | |
+ while (ret == -TARGET_ERESTARTSYS) { | |
+ process_pending_signals(cpu->env_ptr); | |
+ ret = safe_read_wrap(fd, gdb_ctx->mem_buf, sz); | |
+ } | |
+ if (is_error(ret)) { | |
+ snprintf(gdb_ctx->str_buf, 1024, "F%d,%x", -1, -ret); | |
+ put_packet(gdb_ctx->s, gdb_ctx->str_buf); | |
+ } | |
+ else { | |
+ int idx, j; | |
+ idx = snprintf(gdb_ctx->str_buf, 4096, "F%x;", ret); | |
+ // error_report("Debug: %s", (char*)gdb_ctx->mem_buf); | |
+ j = idx; | |
+ for (int i = 0; i < ret; i++) { | |
+ char c; | |
+ c = gdb_ctx->mem_buf[i]; | |
+ if (c == '}' || c == '#' || c == '$' || c == '*' || c == '\0') { | |
+ gdb_ctx->str_buf[j++] = '}'; | |
+ gdb_ctx->str_buf[j++] = c ^ ' '; | |
+ } | |
+ else { gdb_ctx->str_buf[j++] = c; } | |
+ } | |
+ gdb_ctx->str_buf[j++] = '\0'; | |
+ // error_report("String Debug: %s", (char*)gdb_ctx->str_buf); | |
+ put_packet(gdb_ctx->s, gdb_ctx->str_buf); | |
+ } | |
+} | |
+ | |
+static void handle_v_file_close(GdbCmdContext *gdb_ctx, void *user_ctx) | |
+{ | |
+ unsigned long fd; | |
+ int ret; | |
+ fd = gdb_ctx->params[0].val_ul; | |
+ ret = close(fd); | |
+ if (ret < 0) { | |
+ snprintf(gdb_ctx->str_buf, 4096, "F%x,%x", -1, -ret); | |
+ } | |
+ else snprintf(gdb_ctx->str_buf, 4096, "F%x", ret); | |
+ put_packet(gdb_ctx->s, gdb_ctx->str_buf); | |
+} | |
static GdbCmdParseEntry gdb_v_commands_table[] = { | |
/* Order is important if has same prefix */ | |
{ | |
@@ -1931,6 +2016,24 @@ static GdbCmdParseEntry gdb_v_commands_table[] = { | |
.cmd = "Kill;", | |
.cmd_startswith = 1 | |
}, | |
+ { | |
+ .handler = handle_v_file_open, | |
+ .cmd = "File:open:", | |
+ .cmd_startswith = 1, | |
+ .schema = "s,l,l0" | |
+ }, | |
+ { | |
+ .handler = handle_v_file_read, | |
+ .cmd = "File:pread:", | |
+ .cmd_startswith = 1, | |
+ .schema = "l,l,l0" | |
+ }, | |
+ { | |
+ .handler = handle_v_file_close, | |
+ .cmd = "File:close:", | |
+ .cmd_startswith = 1, | |
+ .schema = "l0" | |
+ }, | |
}; | |
static void handle_v_commands(GdbCmdContext *gdb_ctx, void *user_ctx) | |
@@ -2977,7 +3080,11 @@ static void create_default_process(GDBState *s) | |
/* We need an available PID slot for this process */ | |
assert(max_pid < UINT32_MAX); | |
+ #ifdef CONFIG_USER_ONLY | |
+ process->pid = getpid(); | |
+ #else | |
process->pid = max_pid + 1; | |
+ #endif | |
process->attached = false; | |
process->target_xml[0] = '\0'; | |
} | |
diff --git a/linux-user/qemu.h b/linux-user/qemu.h | |
index 4258e41..5cf255d 100644 | |
--- a/linux-user/qemu.h | |
+++ b/linux-user/qemu.h | |
@@ -675,3 +675,6 @@ void preexit_cleanup(CPUArchState *env, int code); | |
#include "target_structs.h" | |
#endif /* QEMU_H */ | |
+ | |
+int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode); | |
+ssize_t safe_read_wrap(int fd, void * buff, size_t count); | |
\ No newline at end of file | |
diff --git a/linux-user/syscall.c b/linux-user/syscall.c | |
index 8367cb1..12ac85c 100644 | |
--- a/linux-user/syscall.c | |
+++ b/linux-user/syscall.c | |
@@ -769,6 +769,9 @@ safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len, | |
int, flags) | |
safe_syscall2(int, nanosleep, const struct timespec *, req, | |
struct timespec *, rem) | |
+abi_long safe_read_wrap(int fd, void * buff, size_t count) { | |
+ return get_errno(safe_read(fd, buff, count)); | |
+} | |
#ifdef TARGET_NR_clock_nanosleep | |
safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, | |
const struct timespec *, req, struct timespec *, rem) | |
@@ -7061,7 +7064,7 @@ static int open_hardware(void *cpu_env, int fd) | |
} | |
#endif | |
-static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode) | |
+int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode) | |
{ | |
struct fake_open { | |
const char *filename; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment