/* * Target specific user-mode handling * * Copyright (c) 2003-2005 Fabrice Bellard * Copyright (c) 2022 Linaro Ltd * * SPDX-License-Identifier: LGPL-2.0+ */ #include "qemu/osdep.h" #include "exec/gdbstub.h" #include "qemu.h" #include "internals.h" /* * Map target signal numbers to GDB protocol signal numbers and vice * versa. For user emulation's currently supported systems, we can * assume most signals are defined. */ static int gdb_signal_table[] = { 0, TARGET_SIGHUP, TARGET_SIGINT, TARGET_SIGQUIT, TARGET_SIGILL, TARGET_SIGTRAP, TARGET_SIGABRT, -1, /* SIGEMT */ TARGET_SIGFPE, TARGET_SIGKILL, TARGET_SIGBUS, TARGET_SIGSEGV, TARGET_SIGSYS, TARGET_SIGPIPE, TARGET_SIGALRM, TARGET_SIGTERM, TARGET_SIGURG, TARGET_SIGSTOP, TARGET_SIGTSTP, TARGET_SIGCONT, TARGET_SIGCHLD, TARGET_SIGTTIN, TARGET_SIGTTOU, TARGET_SIGIO, TARGET_SIGXCPU, TARGET_SIGXFSZ, TARGET_SIGVTALRM, TARGET_SIGPROF, TARGET_SIGWINCH, -1, /* SIGLOST */ TARGET_SIGUSR1, TARGET_SIGUSR2, #ifdef TARGET_SIGPWR TARGET_SIGPWR, #else -1, #endif -1, /* SIGPOLL */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, #ifdef __SIGRTMIN __SIGRTMIN + 1, __SIGRTMIN + 2, __SIGRTMIN + 3, __SIGRTMIN + 4, __SIGRTMIN + 5, __SIGRTMIN + 6, __SIGRTMIN + 7, __SIGRTMIN + 8, __SIGRTMIN + 9, __SIGRTMIN + 10, __SIGRTMIN + 11, __SIGRTMIN + 12, __SIGRTMIN + 13, __SIGRTMIN + 14, __SIGRTMIN + 15, __SIGRTMIN + 16, __SIGRTMIN + 17, __SIGRTMIN + 18, __SIGRTMIN + 19, __SIGRTMIN + 20, __SIGRTMIN + 21, __SIGRTMIN + 22, __SIGRTMIN + 23, __SIGRTMIN + 24, __SIGRTMIN + 25, __SIGRTMIN + 26, __SIGRTMIN + 27, __SIGRTMIN + 28, __SIGRTMIN + 29, __SIGRTMIN + 30, __SIGRTMIN + 31, -1, /* SIGCANCEL */ __SIGRTMIN, __SIGRTMIN + 32, __SIGRTMIN + 33, __SIGRTMIN + 34, __SIGRTMIN + 35, __SIGRTMIN + 36, __SIGRTMIN + 37, __SIGRTMIN + 38, __SIGRTMIN + 39, __SIGRTMIN + 40, __SIGRTMIN + 41, __SIGRTMIN + 42, __SIGRTMIN + 43, __SIGRTMIN + 44, __SIGRTMIN + 45, __SIGRTMIN + 46, __SIGRTMIN + 47, __SIGRTMIN + 48, __SIGRTMIN + 49, __SIGRTMIN + 50, __SIGRTMIN + 51, __SIGRTMIN + 52, __SIGRTMIN + 53, __SIGRTMIN + 54, __SIGRTMIN + 55, __SIGRTMIN + 56, __SIGRTMIN + 57, __SIGRTMIN + 58, __SIGRTMIN + 59, __SIGRTMIN + 60, __SIGRTMIN + 61, __SIGRTMIN + 62, __SIGRTMIN + 63, __SIGRTMIN + 64, __SIGRTMIN + 65, __SIGRTMIN + 66, __SIGRTMIN + 67, __SIGRTMIN + 68, __SIGRTMIN + 69, __SIGRTMIN + 70, __SIGRTMIN + 71, __SIGRTMIN + 72, __SIGRTMIN + 73, __SIGRTMIN + 74, __SIGRTMIN + 75, __SIGRTMIN + 76, __SIGRTMIN + 77, __SIGRTMIN + 78, __SIGRTMIN + 79, __SIGRTMIN + 80, __SIGRTMIN + 81, __SIGRTMIN + 82, __SIGRTMIN + 83, __SIGRTMIN + 84, __SIGRTMIN + 85, __SIGRTMIN + 86, __SIGRTMIN + 87, __SIGRTMIN + 88, __SIGRTMIN + 89, __SIGRTMIN + 90, __SIGRTMIN + 91, __SIGRTMIN + 92, __SIGRTMIN + 93, __SIGRTMIN + 94, __SIGRTMIN + 95, -1, /* SIGINFO */ -1, /* UNKNOWN */ -1, /* DEFAULT */ -1, -1, -1, -1, -1, -1 #endif }; int gdb_signal_to_target(int sig) { if (sig < ARRAY_SIZE(gdb_signal_table)) { return gdb_signal_table[sig]; } else { return -1; } } int gdb_target_signal_to_gdb(int sig) { int i; for (i = 0; i < ARRAY_SIZE(gdb_signal_table); i++) { if (gdb_signal_table[i] == sig) { return i; } } return GDB_SIGNAL_UNKNOWN; } int gdb_get_cpu_index(CPUState *cpu) { TaskState *ts = (TaskState *) cpu->opaque; return ts ? ts->ts_tid : -1; } /* * User-mode specific command helpers */ void gdb_handle_query_offsets(GArray *params, void *user_ctx) { TaskState *ts; ts = gdbserver_state.c_cpu->opaque; g_string_printf(gdbserver_state.str_buf, "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx ";Bss=" TARGET_ABI_FMT_lx, ts->info->code_offset, ts->info->data_offset, ts->info->data_offset); gdb_put_strbuf(); } #if defined(CONFIG_LINUX) /* Partial user only duplicate of helper in gdbstub.c */ static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr, uint8_t *buf, int len, bool is_write) { CPUClass *cc; cc = CPU_GET_CLASS(cpu); if (cc->memory_rw_debug) { return cc->memory_rw_debug(cpu, addr, buf, len, is_write); } return cpu_memory_rw_debug(cpu, addr, buf, len, is_write); } void gdb_handle_query_xfer_auxv(GArray *params, void *user_ctx) { TaskState *ts; unsigned long offset, len, saved_auxv, auxv_len; if (params->len < 2) { gdb_put_packet("E22"); return; } offset = get_param(params, 0)->val_ul; len = get_param(params, 1)->val_ul; ts = gdbserver_state.c_cpu->opaque; saved_auxv = ts->info->saved_auxv; auxv_len = ts->info->auxv_len; if (offset >= auxv_len) { gdb_put_packet("E00"); return; } if (len > (MAX_PACKET_LENGTH - 5) / 2) { len = (MAX_PACKET_LENGTH - 5) / 2; } if (len < auxv_len - offset) { g_string_assign(gdbserver_state.str_buf, "m"); } else { g_string_assign(gdbserver_state.str_buf, "l"); len = auxv_len - offset; } g_byte_array_set_size(gdbserver_state.mem_buf, len); if (target_memory_rw_debug(gdbserver_state.g_cpu, saved_auxv + offset, gdbserver_state.mem_buf->data, len, false)) { gdb_put_packet("E14"); return; } gdb_memtox(gdbserver_state.str_buf, (const char *)gdbserver_state.mem_buf->data, len); gdb_put_packet_binary(gdbserver_state.str_buf->str, gdbserver_state.str_buf->len, true); } #endif