4 * GDB can execute syscalls on the guests behalf, currently used by
5 * the various semihosting extensions.
7 * Copyright (c) 2003-2005 Fabrice Bellard
8 * Copyright (c) 2023 Linaro Ltd
10 * SPDX-License-Identifier: LGPL-2.0+
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"
20 #include "internals.h"
22 /* Syscall specific state */
24 char syscall_buf
[256];
25 gdb_syscall_complete_cb current_syscall_cb
;
28 static GDBSyscallState gdbserver_syscall_state
;
31 * Return true if there is a GDB currently connected to the stub
32 * and attached to a CPU
34 static bool gdb_attached(void)
36 return gdbserver_state
.init
&& gdbserver_state
.c_cpu
;
45 /* Decide if either remote gdb syscalls or native file IO should be used. */
46 int use_gdb_syscalls(void)
48 SemihostingTarget target
= semihosting_get_target();
49 if (target
== SEMIHOSTING_TARGET_NATIVE
) {
50 /* -semihosting-config target=native */
52 } else if (target
== SEMIHOSTING_TARGET_GDB
) {
53 /* -semihosting-config target=gdb */
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
;
62 return gdb_syscall_mode
== GDB_SYS_ENABLED
;
65 /* called when the stub detaches */
66 void gdb_disable_syscalls(void)
68 gdb_syscall_mode
= GDB_SYS_DISABLED
;
71 void gdb_syscall_reset(void)
73 gdbserver_syscall_state
.current_syscall_cb
= NULL
;
76 bool gdb_handled_syscall(void)
78 if (gdbserver_syscall_state
.current_syscall_cb
) {
79 gdb_put_packet(gdbserver_syscall_state
.syscall_buf
);
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.
93 void gdb_do_syscall(gdb_syscall_complete_cb cb
, const char *fmt
, ...)
98 if (!gdb_attached()) {
102 gdbserver_syscall_state
.current_syscall_cb
= cb
;
105 p
= gdbserver_syscall_state
.syscall_buf
;
106 p_end
= p
+ sizeof(gdbserver_syscall_state
.syscall_buf
);
116 i32
= va_arg(va
, uint32_t);
117 p
+= snprintf(p
, p_end
- p
, "%" PRIx32
, i32
);
120 if (*(fmt
++) != 'x') {
123 i64
= va_arg(va
, uint64_t);
124 p
+= snprintf(p
, p_end
- p
, "%" PRIx64
, i64
);
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
);
133 error_report("gdbstub: Bad syscall format string '%s'",
144 gdb_syscall_handling(gdbserver_syscall_state
.syscall_buf
);
148 * GDB Command Handlers
151 void gdb_handle_file_io(GArray
*params
, void *user_ctx
)
153 if (params
->len
>= 1 && gdbserver_syscall_state
.current_syscall_cb
) {
157 ret
= get_param(params
, 0)->val_ull
;
158 if (params
->len
>= 2) {
159 err
= get_param(params
, 1)->val_ull
;
164 /* Convert GDB error numbers back to host error numbers. */
165 #define E(X) case GDB_E##X: err = E##X; break
194 gdbserver_syscall_state
.current_syscall_cb(gdbserver_state
.c_cpu
,
196 gdbserver_syscall_state
.current_syscall_cb
= NULL
;
199 if (params
->len
>= 3 && get_param(params
, 2)->opcode
== (uint8_t)'C') {
200 gdb_put_packet("T02");