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