2 * Target specific user-mode handling
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 * Copyright (c) 2022 Linaro Ltd
7 * SPDX-License-Identifier: LGPL-2.0+
10 #include "qemu/osdep.h"
11 #include "exec/gdbstub.h"
13 #include "internals.h"
15 #include "linux-user/loader.h"
16 #include "linux-user/qemu.h"
20 * Map target signal numbers to GDB protocol signal numbers and vice
21 * versa. For user emulation's currently supported systems, we can
22 * assume most signals are defined.
25 static int gdb_signal_table
[] = {
185 int gdb_signal_to_target(int sig
)
187 if (sig
< ARRAY_SIZE(gdb_signal_table
)) {
188 return gdb_signal_table
[sig
];
194 int gdb_target_signal_to_gdb(int sig
)
197 for (i
= 0; i
< ARRAY_SIZE(gdb_signal_table
); i
++) {
198 if (gdb_signal_table
[i
] == sig
) {
202 return GDB_SIGNAL_UNKNOWN
;
205 int gdb_get_cpu_index(CPUState
*cpu
)
207 TaskState
*ts
= get_task_state(cpu
);
208 return ts
? ts
->ts_tid
: -1;
212 * User-mode specific command helpers
215 void gdb_handle_query_offsets(GArray
*params
, void *user_ctx
)
219 ts
= get_task_state(gdbserver_state
.c_cpu
);
220 g_string_printf(gdbserver_state
.str_buf
,
221 "Text=" TARGET_ABI_FMT_lx
222 ";Data=" TARGET_ABI_FMT_lx
223 ";Bss=" TARGET_ABI_FMT_lx
,
224 ts
->info
->code_offset
,
225 ts
->info
->data_offset
,
226 ts
->info
->data_offset
);
230 #if defined(CONFIG_LINUX)
231 /* Partial user only duplicate of helper in gdbstub.c */
232 static inline int target_memory_rw_debug(CPUState
*cpu
, target_ulong addr
,
233 uint8_t *buf
, int len
, bool is_write
)
236 cc
= CPU_GET_CLASS(cpu
);
237 if (cc
->memory_rw_debug
) {
238 return cc
->memory_rw_debug(cpu
, addr
, buf
, len
, is_write
);
240 return cpu_memory_rw_debug(cpu
, addr
, buf
, len
, is_write
);
243 void gdb_handle_query_xfer_auxv(GArray
*params
, void *user_ctx
)
246 unsigned long offset
, len
, saved_auxv
, auxv_len
;
248 if (params
->len
< 2) {
249 gdb_put_packet("E22");
253 offset
= get_param(params
, 0)->val_ul
;
254 len
= get_param(params
, 1)->val_ul
;
255 ts
= get_task_state(gdbserver_state
.c_cpu
);
256 saved_auxv
= ts
->info
->saved_auxv
;
257 auxv_len
= ts
->info
->auxv_len
;
259 if (offset
>= auxv_len
) {
260 gdb_put_packet("E00");
264 if (len
> (MAX_PACKET_LENGTH
- 5) / 2) {
265 len
= (MAX_PACKET_LENGTH
- 5) / 2;
268 if (len
< auxv_len
- offset
) {
269 g_string_assign(gdbserver_state
.str_buf
, "m");
271 g_string_assign(gdbserver_state
.str_buf
, "l");
272 len
= auxv_len
- offset
;
275 g_byte_array_set_size(gdbserver_state
.mem_buf
, len
);
276 if (target_memory_rw_debug(gdbserver_state
.g_cpu
, saved_auxv
+ offset
,
277 gdbserver_state
.mem_buf
->data
, len
, false)) {
278 gdb_put_packet("E14");
282 gdb_memtox(gdbserver_state
.str_buf
,
283 (const char *)gdbserver_state
.mem_buf
->data
, len
);
284 gdb_put_packet_binary(gdbserver_state
.str_buf
->str
,
285 gdbserver_state
.str_buf
->len
, true);
289 static const char *get_filename_param(GArray
*params
, int i
)
291 const char *hex_filename
= get_param(params
, i
)->data
;
292 gdb_hextomem(gdbserver_state
.mem_buf
, hex_filename
,
293 strlen(hex_filename
) / 2);
294 g_byte_array_append(gdbserver_state
.mem_buf
, (const guint8
*)"", 1);
295 return (const char *)gdbserver_state
.mem_buf
->data
;
298 static void hostio_reply_with_data(const void *buf
, size_t n
)
300 g_string_printf(gdbserver_state
.str_buf
, "F%zx;", n
);
301 gdb_memtox(gdbserver_state
.str_buf
, buf
, n
);
302 gdb_put_packet_binary(gdbserver_state
.str_buf
->str
,
303 gdbserver_state
.str_buf
->len
, true);
306 void gdb_handle_v_file_open(GArray
*params
, void *user_ctx
)
308 const char *filename
= get_filename_param(params
, 0);
309 uint64_t flags
= get_param(params
, 1)->val_ull
;
310 uint64_t mode
= get_param(params
, 2)->val_ull
;
313 int fd
= do_guest_openat(cpu_env(gdbserver_state
.g_cpu
), 0, filename
,
316 int fd
= open(filename
, flags
, mode
);
319 g_string_printf(gdbserver_state
.str_buf
, "F-1,%d", errno
);
321 g_string_printf(gdbserver_state
.str_buf
, "F%d", fd
);
326 void gdb_handle_v_file_close(GArray
*params
, void *user_ctx
)
328 int fd
= get_param(params
, 0)->val_ul
;
330 if (close(fd
) == -1) {
331 g_string_printf(gdbserver_state
.str_buf
, "F-1,%d", errno
);
336 gdb_put_packet("F00");
339 void gdb_handle_v_file_pread(GArray
*params
, void *user_ctx
)
341 int fd
= get_param(params
, 0)->val_ul
;
342 size_t count
= get_param(params
, 1)->val_ull
;
343 off_t offset
= get_param(params
, 2)->val_ull
;
345 size_t bufsiz
= MIN(count
, BUFSIZ
);
346 g_autofree
char *buf
= g_try_malloc(bufsiz
);
348 gdb_put_packet("E12");
352 ssize_t n
= pread(fd
, buf
, bufsiz
, offset
);
354 g_string_printf(gdbserver_state
.str_buf
, "F-1,%d", errno
);
358 hostio_reply_with_data(buf
, n
);
361 void gdb_handle_v_file_readlink(GArray
*params
, void *user_ctx
)
363 const char *filename
= get_filename_param(params
, 0);
365 g_autofree
char *buf
= g_try_malloc(BUFSIZ
);
367 gdb_put_packet("E12");
372 ssize_t n
= do_guest_readlink(filename
, buf
, BUFSIZ
);
374 ssize_t n
= readlink(filename
, buf
, BUFSIZ
);
377 g_string_printf(gdbserver_state
.str_buf
, "F-1,%d", errno
);
381 hostio_reply_with_data(buf
, n
);
384 void gdb_handle_query_xfer_exec_file(GArray
*params
, void *user_ctx
)
386 uint32_t pid
= get_param(params
, 0)->val_ul
;
387 uint32_t offset
= get_param(params
, 1)->val_ul
;
388 uint32_t length
= get_param(params
, 2)->val_ul
;
390 GDBProcess
*process
= gdb_get_process(pid
);
392 gdb_put_packet("E00");
396 CPUState
*cpu
= gdb_get_first_cpu_in_process(process
);
398 gdb_put_packet("E00");
402 TaskState
*ts
= get_task_state(cpu
);
403 if (!ts
|| !ts
->bprm
|| !ts
->bprm
->filename
) {
404 gdb_put_packet("E00");
408 size_t total_length
= strlen(ts
->bprm
->filename
);
409 if (offset
> total_length
) {
410 gdb_put_packet("E00");
413 if (offset
+ length
> total_length
) {
414 length
= total_length
- offset
;
417 g_string_printf(gdbserver_state
.str_buf
, "l%.*s", length
,
418 ts
->bprm
->filename
+ offset
);
422 int gdb_target_sigtrap(void)
424 return TARGET_SIGTRAP
;