123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- /*
- * 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"
- #ifdef CONFIG_LINUX
- #include "linux-user/loader.h"
- #include "linux-user/qemu.h"
- #endif
- /*
- * 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
- static const char *get_filename_param(GArray *params, int i)
- {
- const char *hex_filename = get_param(params, i)->data;
- gdb_hextomem(gdbserver_state.mem_buf, hex_filename,
- strlen(hex_filename) / 2);
- g_byte_array_append(gdbserver_state.mem_buf, (const guint8 *)"", 1);
- return (const char *)gdbserver_state.mem_buf->data;
- }
- static void hostio_reply_with_data(const void *buf, size_t n)
- {
- g_string_printf(gdbserver_state.str_buf, "F%zx;", n);
- gdb_memtox(gdbserver_state.str_buf, buf, n);
- gdb_put_packet_binary(gdbserver_state.str_buf->str,
- gdbserver_state.str_buf->len, true);
- }
- void gdb_handle_v_file_open(GArray *params, void *user_ctx)
- {
- const char *filename = get_filename_param(params, 0);
- uint64_t flags = get_param(params, 1)->val_ull;
- uint64_t mode = get_param(params, 2)->val_ull;
- #ifdef CONFIG_LINUX
- int fd = do_guest_openat(gdbserver_state.g_cpu->env_ptr, 0, filename,
- flags, mode, false);
- #else
- int fd = open(filename, flags, mode);
- #endif
- if (fd < 0) {
- g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
- } else {
- g_string_printf(gdbserver_state.str_buf, "F%d", fd);
- }
- gdb_put_strbuf();
- }
- void gdb_handle_v_file_close(GArray *params, void *user_ctx)
- {
- int fd = get_param(params, 0)->val_ul;
- if (close(fd) == -1) {
- g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
- gdb_put_strbuf();
- return;
- }
- gdb_put_packet("F00");
- }
- void gdb_handle_v_file_pread(GArray *params, void *user_ctx)
- {
- int fd = get_param(params, 0)->val_ul;
- size_t count = get_param(params, 1)->val_ull;
- off_t offset = get_param(params, 2)->val_ull;
- size_t bufsiz = MIN(count, BUFSIZ);
- g_autofree char *buf = g_try_malloc(bufsiz);
- if (buf == NULL) {
- gdb_put_packet("E12");
- return;
- }
- ssize_t n = pread(fd, buf, bufsiz, offset);
- if (n < 0) {
- g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
- gdb_put_strbuf();
- return;
- }
- hostio_reply_with_data(buf, n);
- }
- void gdb_handle_v_file_readlink(GArray *params, void *user_ctx)
- {
- const char *filename = get_filename_param(params, 0);
- g_autofree char *buf = g_try_malloc(BUFSIZ);
- if (buf == NULL) {
- gdb_put_packet("E12");
- return;
- }
- #ifdef CONFIG_LINUX
- ssize_t n = do_guest_readlink(filename, buf, BUFSIZ);
- #else
- ssize_t n = readlink(filename, buf, BUFSIZ);
- #endif
- if (n < 0) {
- g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
- gdb_put_strbuf();
- return;
- }
- hostio_reply_with_data(buf, n);
- }
- void gdb_handle_query_xfer_exec_file(GArray *params, void *user_ctx)
- {
- uint32_t pid = get_param(params, 0)->val_ul;
- uint32_t offset = get_param(params, 1)->val_ul;
- uint32_t length = get_param(params, 2)->val_ul;
- GDBProcess *process = gdb_get_process(pid);
- if (!process) {
- gdb_put_packet("E00");
- return;
- }
- CPUState *cpu = gdb_get_first_cpu_in_process(process);
- if (!cpu) {
- gdb_put_packet("E00");
- return;
- }
- TaskState *ts = cpu->opaque;
- if (!ts || !ts->bprm || !ts->bprm->filename) {
- gdb_put_packet("E00");
- return;
- }
- size_t total_length = strlen(ts->bprm->filename);
- if (offset > total_length) {
- gdb_put_packet("E00");
- return;
- }
- if (offset + length > total_length) {
- length = total_length - offset;
- }
- g_string_printf(gdbserver_state.str_buf, "l%.*s", length,
- ts->bprm->filename + offset);
- gdb_put_strbuf();
- }
|