1c566080cSAlex Bennée /* 2c566080cSAlex Bennée * GDB Syscall Handling 3c566080cSAlex Bennée * 4c566080cSAlex Bennée * GDB can execute syscalls on the guests behalf, currently used by 5c566080cSAlex Bennée * the various semihosting extensions. As this interfaces with a guest 6c566080cSAlex Bennée * ABI we need to build it per-guest (although in reality its a 32 or 7c566080cSAlex Bennée * 64 bit target_ulong that is the only difference). 8c566080cSAlex Bennée * 9c566080cSAlex Bennée * Copyright (c) 2003-2005 Fabrice Bellard 10c566080cSAlex Bennée * Copyright (c) 2023 Linaro Ltd 11c566080cSAlex Bennée * 12c566080cSAlex Bennée * SPDX-License-Identifier: LGPL-2.0+ 13c566080cSAlex Bennée */ 14c566080cSAlex Bennée 15c566080cSAlex Bennée #include "qemu/osdep.h" 16c566080cSAlex Bennée #include "qemu/error-report.h" 17c566080cSAlex Bennée #include "cpu.h" 18c566080cSAlex Bennée #include "semihosting/semihost.h" 19c566080cSAlex Bennée #include "sysemu/runstate.h" 20c566080cSAlex Bennée #include "gdbstub/user.h" 21c566080cSAlex Bennée #include "gdbstub/syscalls.h" 22c566080cSAlex Bennée #include "trace.h" 23c566080cSAlex Bennée #include "internals.h" 24c566080cSAlex Bennée 25c566080cSAlex Bennée /* Syscall specific state */ 26c566080cSAlex Bennée typedef struct { 27c566080cSAlex Bennée char syscall_buf[256]; 28c566080cSAlex Bennée gdb_syscall_complete_cb current_syscall_cb; 29c566080cSAlex Bennée } GDBSyscallState; 30c566080cSAlex Bennée 31c566080cSAlex Bennée static GDBSyscallState gdbserver_syscall_state; 32c566080cSAlex Bennée 33c566080cSAlex Bennée /* 34c566080cSAlex Bennée * Return true if there is a GDB currently connected to the stub 35c566080cSAlex Bennée * and attached to a CPU 36c566080cSAlex Bennée */ 37c566080cSAlex Bennée static bool gdb_attached(void) 38c566080cSAlex Bennée { 39c566080cSAlex Bennée return gdbserver_state.init && gdbserver_state.c_cpu; 40c566080cSAlex Bennée } 41c566080cSAlex Bennée 42c566080cSAlex Bennée static enum { 43c566080cSAlex Bennée GDB_SYS_UNKNOWN, 44c566080cSAlex Bennée GDB_SYS_ENABLED, 45c566080cSAlex Bennée GDB_SYS_DISABLED, 46c566080cSAlex Bennée } gdb_syscall_mode; 47c566080cSAlex Bennée 48c566080cSAlex Bennée /* Decide if either remote gdb syscalls or native file IO should be used. */ 49c566080cSAlex Bennée int use_gdb_syscalls(void) 50c566080cSAlex Bennée { 51c566080cSAlex Bennée SemihostingTarget target = semihosting_get_target(); 52c566080cSAlex Bennée if (target == SEMIHOSTING_TARGET_NATIVE) { 53c566080cSAlex Bennée /* -semihosting-config target=native */ 54c566080cSAlex Bennée return false; 55c566080cSAlex Bennée } else if (target == SEMIHOSTING_TARGET_GDB) { 56c566080cSAlex Bennée /* -semihosting-config target=gdb */ 57c566080cSAlex Bennée return true; 58c566080cSAlex Bennée } 59c566080cSAlex Bennée 60c566080cSAlex Bennée /* -semihosting-config target=auto */ 61c566080cSAlex Bennée /* On the first call check if gdb is connected and remember. */ 62c566080cSAlex Bennée if (gdb_syscall_mode == GDB_SYS_UNKNOWN) { 63c566080cSAlex Bennée gdb_syscall_mode = gdb_attached() ? GDB_SYS_ENABLED : GDB_SYS_DISABLED; 64c566080cSAlex Bennée } 65c566080cSAlex Bennée return gdb_syscall_mode == GDB_SYS_ENABLED; 66c566080cSAlex Bennée } 67c566080cSAlex Bennée 68c566080cSAlex Bennée /* called when the stub detaches */ 69c566080cSAlex Bennée void gdb_disable_syscalls(void) 70c566080cSAlex Bennée { 71c566080cSAlex Bennée gdb_syscall_mode = GDB_SYS_DISABLED; 72c566080cSAlex Bennée } 73c566080cSAlex Bennée 74c566080cSAlex Bennée void gdb_syscall_reset(void) 75c566080cSAlex Bennée { 76c566080cSAlex Bennée gdbserver_syscall_state.current_syscall_cb = NULL; 77c566080cSAlex Bennée } 78c566080cSAlex Bennée 79c566080cSAlex Bennée bool gdb_handled_syscall(void) 80c566080cSAlex Bennée { 81c566080cSAlex Bennée if (gdbserver_syscall_state.current_syscall_cb) { 82c566080cSAlex Bennée gdb_put_packet(gdbserver_syscall_state.syscall_buf); 83c566080cSAlex Bennée return true; 84c566080cSAlex Bennée } 85c566080cSAlex Bennée 86c566080cSAlex Bennée return false; 87c566080cSAlex Bennée } 88c566080cSAlex Bennée 89c566080cSAlex Bennée /* 90c566080cSAlex Bennée * Send a gdb syscall request. 91c566080cSAlex Bennée * This accepts limited printf-style format specifiers, specifically: 92c566080cSAlex Bennée * %x - target_ulong argument printed in hex. 93c566080cSAlex Bennée * %lx - 64-bit argument printed in hex. 94c566080cSAlex Bennée * %s - string pointer (target_ulong) and length (int) pair. 95c566080cSAlex Bennée */ 96c566080cSAlex Bennée void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va) 97c566080cSAlex Bennée { 98c566080cSAlex Bennée char *p; 99c566080cSAlex Bennée char *p_end; 100c566080cSAlex Bennée target_ulong addr; 101c566080cSAlex Bennée uint64_t i64; 102c566080cSAlex Bennée 103c566080cSAlex Bennée if (!gdb_attached()) { 104c566080cSAlex Bennée return; 105c566080cSAlex Bennée } 106c566080cSAlex Bennée 107c566080cSAlex Bennée gdbserver_syscall_state.current_syscall_cb = cb; 108*131f387dSAlex Bennée 109c566080cSAlex Bennée p = &gdbserver_syscall_state.syscall_buf[0]; 110c566080cSAlex Bennée p_end = &gdbserver_syscall_state.syscall_buf[sizeof(gdbserver_syscall_state.syscall_buf)]; 111c566080cSAlex Bennée *(p++) = 'F'; 112c566080cSAlex Bennée while (*fmt) { 113c566080cSAlex Bennée if (*fmt == '%') { 114c566080cSAlex Bennée fmt++; 115c566080cSAlex Bennée switch (*fmt++) { 116c566080cSAlex Bennée case 'x': 117c566080cSAlex Bennée addr = va_arg(va, target_ulong); 118c566080cSAlex Bennée p += snprintf(p, p_end - p, TARGET_FMT_lx, addr); 119c566080cSAlex Bennée break; 120c566080cSAlex Bennée case 'l': 121c566080cSAlex Bennée if (*(fmt++) != 'x') { 122c566080cSAlex Bennée goto bad_format; 123c566080cSAlex Bennée } 124c566080cSAlex Bennée i64 = va_arg(va, uint64_t); 125c566080cSAlex Bennée p += snprintf(p, p_end - p, "%" PRIx64, i64); 126c566080cSAlex Bennée break; 127c566080cSAlex Bennée case 's': 128c566080cSAlex Bennée addr = va_arg(va, target_ulong); 129c566080cSAlex Bennée p += snprintf(p, p_end - p, TARGET_FMT_lx "/%x", 130c566080cSAlex Bennée addr, va_arg(va, int)); 131c566080cSAlex Bennée break; 132c566080cSAlex Bennée default: 133c566080cSAlex Bennée bad_format: 134c566080cSAlex Bennée error_report("gdbstub: Bad syscall format string '%s'", 135c566080cSAlex Bennée fmt - 1); 136c566080cSAlex Bennée break; 137c566080cSAlex Bennée } 138c566080cSAlex Bennée } else { 139c566080cSAlex Bennée *(p++) = *(fmt++); 140c566080cSAlex Bennée } 141c566080cSAlex Bennée } 142c566080cSAlex Bennée *p = 0; 143*131f387dSAlex Bennée 144*131f387dSAlex Bennée gdb_syscall_handling(gdbserver_syscall_state.syscall_buf); 145c566080cSAlex Bennée } 146c566080cSAlex Bennée 147c566080cSAlex Bennée void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) 148c566080cSAlex Bennée { 149c566080cSAlex Bennée va_list va; 150c566080cSAlex Bennée 151c566080cSAlex Bennée va_start(va, fmt); 152c566080cSAlex Bennée gdb_do_syscallv(cb, fmt, va); 153c566080cSAlex Bennée va_end(va); 154c566080cSAlex Bennée } 155c566080cSAlex Bennée 156c566080cSAlex Bennée /* 157c566080cSAlex Bennée * GDB Command Handlers 158c566080cSAlex Bennée */ 159c566080cSAlex Bennée 160c566080cSAlex Bennée void gdb_handle_file_io(GArray *params, void *user_ctx) 161c566080cSAlex Bennée { 162c566080cSAlex Bennée if (params->len >= 1 && gdbserver_syscall_state.current_syscall_cb) { 163c566080cSAlex Bennée uint64_t ret; 164c566080cSAlex Bennée int err; 165c566080cSAlex Bennée 166c566080cSAlex Bennée ret = get_param(params, 0)->val_ull; 167c566080cSAlex Bennée if (params->len >= 2) { 168c566080cSAlex Bennée err = get_param(params, 1)->val_ull; 169c566080cSAlex Bennée } else { 170c566080cSAlex Bennée err = 0; 171c566080cSAlex Bennée } 172c566080cSAlex Bennée 173c566080cSAlex Bennée /* Convert GDB error numbers back to host error numbers. */ 174c566080cSAlex Bennée #define E(X) case GDB_E##X: err = E##X; break 175c566080cSAlex Bennée switch (err) { 176c566080cSAlex Bennée case 0: 177c566080cSAlex Bennée break; 178c566080cSAlex Bennée E(PERM); 179c566080cSAlex Bennée E(NOENT); 180c566080cSAlex Bennée E(INTR); 181c566080cSAlex Bennée E(BADF); 182c566080cSAlex Bennée E(ACCES); 183c566080cSAlex Bennée E(FAULT); 184c566080cSAlex Bennée E(BUSY); 185c566080cSAlex Bennée E(EXIST); 186c566080cSAlex Bennée E(NODEV); 187c566080cSAlex Bennée E(NOTDIR); 188c566080cSAlex Bennée E(ISDIR); 189c566080cSAlex Bennée E(INVAL); 190c566080cSAlex Bennée E(NFILE); 191c566080cSAlex Bennée E(MFILE); 192c566080cSAlex Bennée E(FBIG); 193c566080cSAlex Bennée E(NOSPC); 194c566080cSAlex Bennée E(SPIPE); 195c566080cSAlex Bennée E(ROFS); 196c566080cSAlex Bennée E(NAMETOOLONG); 197c566080cSAlex Bennée default: 198c566080cSAlex Bennée err = EINVAL; 199c566080cSAlex Bennée break; 200c566080cSAlex Bennée } 201c566080cSAlex Bennée #undef E 202c566080cSAlex Bennée 203c566080cSAlex Bennée gdbserver_syscall_state.current_syscall_cb(gdbserver_state.c_cpu, 204c566080cSAlex Bennée ret, err); 205c566080cSAlex Bennée gdbserver_syscall_state.current_syscall_cb = NULL; 206c566080cSAlex Bennée } 207c566080cSAlex Bennée 208c566080cSAlex Bennée if (params->len >= 3 && get_param(params, 2)->opcode == (uint8_t)'C') { 209c566080cSAlex Bennée gdb_put_packet("T02"); 210c566080cSAlex Bennée return; 211c566080cSAlex Bennée } 212c566080cSAlex Bennée 213c566080cSAlex Bennée gdb_continue(); 214c566080cSAlex Bennée } 215