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