1 /* 2 * Target specific user-mode handling 3 * 4 * Copyright (c) 2003-2005 Fabrice Bellard 5 * Copyright (c) 2022 Linaro Ltd 6 * 7 * SPDX-License-Identifier: LGPL-2.0-or-later 8 */ 9 10 #include "qemu/osdep.h" 11 #include "exec/gdbstub.h" 12 #include "gdbstub/commands.h" 13 #include "qemu.h" 14 #include "internals.h" 15 #ifdef CONFIG_LINUX 16 #include "linux-user/loader.h" 17 #include "linux-user/qemu.h" 18 #endif 19 20 /* 21 * Map target signal numbers to GDB protocol signal numbers and vice 22 * versa. For user emulation's currently supported systems, we can 23 * assume most signals are defined. 24 */ 25 26 static int gdb_signal_table[] = { 27 0, 28 TARGET_SIGHUP, 29 TARGET_SIGINT, 30 TARGET_SIGQUIT, 31 TARGET_SIGILL, 32 TARGET_SIGTRAP, 33 TARGET_SIGABRT, 34 -1, /* SIGEMT */ 35 TARGET_SIGFPE, 36 TARGET_SIGKILL, 37 TARGET_SIGBUS, 38 TARGET_SIGSEGV, 39 TARGET_SIGSYS, 40 TARGET_SIGPIPE, 41 TARGET_SIGALRM, 42 TARGET_SIGTERM, 43 TARGET_SIGURG, 44 TARGET_SIGSTOP, 45 TARGET_SIGTSTP, 46 TARGET_SIGCONT, 47 TARGET_SIGCHLD, 48 TARGET_SIGTTIN, 49 TARGET_SIGTTOU, 50 TARGET_SIGIO, 51 TARGET_SIGXCPU, 52 TARGET_SIGXFSZ, 53 TARGET_SIGVTALRM, 54 TARGET_SIGPROF, 55 TARGET_SIGWINCH, 56 -1, /* SIGLOST */ 57 TARGET_SIGUSR1, 58 TARGET_SIGUSR2, 59 #ifdef TARGET_SIGPWR 60 TARGET_SIGPWR, 61 #else 62 -1, 63 #endif 64 -1, /* SIGPOLL */ 65 -1, 66 -1, 67 -1, 68 -1, 69 -1, 70 -1, 71 -1, 72 -1, 73 -1, 74 -1, 75 -1, 76 #ifdef __SIGRTMIN 77 __SIGRTMIN + 1, 78 __SIGRTMIN + 2, 79 __SIGRTMIN + 3, 80 __SIGRTMIN + 4, 81 __SIGRTMIN + 5, 82 __SIGRTMIN + 6, 83 __SIGRTMIN + 7, 84 __SIGRTMIN + 8, 85 __SIGRTMIN + 9, 86 __SIGRTMIN + 10, 87 __SIGRTMIN + 11, 88 __SIGRTMIN + 12, 89 __SIGRTMIN + 13, 90 __SIGRTMIN + 14, 91 __SIGRTMIN + 15, 92 __SIGRTMIN + 16, 93 __SIGRTMIN + 17, 94 __SIGRTMIN + 18, 95 __SIGRTMIN + 19, 96 __SIGRTMIN + 20, 97 __SIGRTMIN + 21, 98 __SIGRTMIN + 22, 99 __SIGRTMIN + 23, 100 __SIGRTMIN + 24, 101 __SIGRTMIN + 25, 102 __SIGRTMIN + 26, 103 __SIGRTMIN + 27, 104 __SIGRTMIN + 28, 105 __SIGRTMIN + 29, 106 __SIGRTMIN + 30, 107 __SIGRTMIN + 31, 108 -1, /* SIGCANCEL */ 109 __SIGRTMIN, 110 __SIGRTMIN + 32, 111 __SIGRTMIN + 33, 112 __SIGRTMIN + 34, 113 __SIGRTMIN + 35, 114 __SIGRTMIN + 36, 115 __SIGRTMIN + 37, 116 __SIGRTMIN + 38, 117 __SIGRTMIN + 39, 118 __SIGRTMIN + 40, 119 __SIGRTMIN + 41, 120 __SIGRTMIN + 42, 121 __SIGRTMIN + 43, 122 __SIGRTMIN + 44, 123 __SIGRTMIN + 45, 124 __SIGRTMIN + 46, 125 __SIGRTMIN + 47, 126 __SIGRTMIN + 48, 127 __SIGRTMIN + 49, 128 __SIGRTMIN + 50, 129 __SIGRTMIN + 51, 130 __SIGRTMIN + 52, 131 __SIGRTMIN + 53, 132 __SIGRTMIN + 54, 133 __SIGRTMIN + 55, 134 __SIGRTMIN + 56, 135 __SIGRTMIN + 57, 136 __SIGRTMIN + 58, 137 __SIGRTMIN + 59, 138 __SIGRTMIN + 60, 139 __SIGRTMIN + 61, 140 __SIGRTMIN + 62, 141 __SIGRTMIN + 63, 142 __SIGRTMIN + 64, 143 __SIGRTMIN + 65, 144 __SIGRTMIN + 66, 145 __SIGRTMIN + 67, 146 __SIGRTMIN + 68, 147 __SIGRTMIN + 69, 148 __SIGRTMIN + 70, 149 __SIGRTMIN + 71, 150 __SIGRTMIN + 72, 151 __SIGRTMIN + 73, 152 __SIGRTMIN + 74, 153 __SIGRTMIN + 75, 154 __SIGRTMIN + 76, 155 __SIGRTMIN + 77, 156 __SIGRTMIN + 78, 157 __SIGRTMIN + 79, 158 __SIGRTMIN + 80, 159 __SIGRTMIN + 81, 160 __SIGRTMIN + 82, 161 __SIGRTMIN + 83, 162 __SIGRTMIN + 84, 163 __SIGRTMIN + 85, 164 __SIGRTMIN + 86, 165 __SIGRTMIN + 87, 166 __SIGRTMIN + 88, 167 __SIGRTMIN + 89, 168 __SIGRTMIN + 90, 169 __SIGRTMIN + 91, 170 __SIGRTMIN + 92, 171 __SIGRTMIN + 93, 172 __SIGRTMIN + 94, 173 __SIGRTMIN + 95, 174 -1, /* SIGINFO */ 175 -1, /* UNKNOWN */ 176 -1, /* DEFAULT */ 177 -1, 178 -1, 179 -1, 180 -1, 181 -1, 182 -1 183 #endif 184 }; 185 186 int gdb_signal_to_target(int sig) 187 { 188 if (sig < ARRAY_SIZE(gdb_signal_table)) { 189 return gdb_signal_table[sig]; 190 } else { 191 return -1; 192 } 193 } 194 195 int gdb_target_signal_to_gdb(int sig) 196 { 197 int i; 198 for (i = 0; i < ARRAY_SIZE(gdb_signal_table); i++) { 199 if (gdb_signal_table[i] == sig) { 200 return i; 201 } 202 } 203 return GDB_SIGNAL_UNKNOWN; 204 } 205 206 int gdb_get_cpu_index(CPUState *cpu) 207 { 208 TaskState *ts = get_task_state(cpu); 209 return ts ? ts->ts_tid : -1; 210 } 211 212 /* 213 * User-mode specific command helpers 214 */ 215 216 void gdb_handle_query_offsets(GArray *params, void *user_ctx) 217 { 218 TaskState *ts; 219 220 ts = get_task_state(gdbserver_state.c_cpu); 221 g_string_printf(gdbserver_state.str_buf, 222 "Text=" TARGET_ABI_FMT_lx 223 ";Data=" TARGET_ABI_FMT_lx 224 ";Bss=" TARGET_ABI_FMT_lx, 225 ts->info->code_offset, 226 ts->info->data_offset, 227 ts->info->data_offset); 228 gdb_put_strbuf(); 229 } 230 231 #if defined(CONFIG_LINUX) 232 /* Partial user only duplicate of helper in gdbstub.c */ 233 static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr, 234 uint8_t *buf, int len, bool is_write) 235 { 236 if (cpu->cc->memory_rw_debug) { 237 return cpu->cc->memory_rw_debug(cpu, addr, buf, len, is_write); 238 } 239 return cpu_memory_rw_debug(cpu, addr, buf, len, is_write); 240 } 241 242 void gdb_handle_query_xfer_auxv(GArray *params, void *user_ctx) 243 { 244 TaskState *ts; 245 unsigned long offset, len, saved_auxv, auxv_len; 246 247 if (params->len < 2) { 248 gdb_put_packet("E22"); 249 return; 250 } 251 252 offset = gdb_get_cmd_param(params, 0)->val_ul; 253 len = gdb_get_cmd_param(params, 1)->val_ul; 254 ts = get_task_state(gdbserver_state.c_cpu); 255 saved_auxv = ts->info->saved_auxv; 256 auxv_len = ts->info->auxv_len; 257 258 if (offset >= auxv_len) { 259 gdb_put_packet("E00"); 260 return; 261 } 262 263 if (len > (MAX_PACKET_LENGTH - 5) / 2) { 264 len = (MAX_PACKET_LENGTH - 5) / 2; 265 } 266 267 if (len < auxv_len - offset) { 268 g_string_assign(gdbserver_state.str_buf, "m"); 269 } else { 270 g_string_assign(gdbserver_state.str_buf, "l"); 271 len = auxv_len - offset; 272 } 273 274 g_byte_array_set_size(gdbserver_state.mem_buf, len); 275 if (target_memory_rw_debug(gdbserver_state.g_cpu, saved_auxv + offset, 276 gdbserver_state.mem_buf->data, len, false)) { 277 gdb_put_packet("E14"); 278 return; 279 } 280 281 gdb_memtox(gdbserver_state.str_buf, 282 (const char *)gdbserver_state.mem_buf->data, len); 283 gdb_put_packet_binary(gdbserver_state.str_buf->str, 284 gdbserver_state.str_buf->len, true); 285 } 286 #endif 287 288 static const char *get_filename_param(GArray *params, int i) 289 { 290 const char *hex_filename = gdb_get_cmd_param(params, i)->data; 291 gdb_hextomem(gdbserver_state.mem_buf, hex_filename, 292 strlen(hex_filename) / 2); 293 g_byte_array_append(gdbserver_state.mem_buf, (const guint8 *)"", 1); 294 return (const char *)gdbserver_state.mem_buf->data; 295 } 296 297 static void hostio_reply_with_data(const void *buf, size_t n) 298 { 299 g_string_printf(gdbserver_state.str_buf, "F%zx;", n); 300 gdb_memtox(gdbserver_state.str_buf, buf, n); 301 gdb_put_packet_binary(gdbserver_state.str_buf->str, 302 gdbserver_state.str_buf->len, true); 303 } 304 305 void gdb_handle_v_file_open(GArray *params, void *user_ctx) 306 { 307 const char *filename = get_filename_param(params, 0); 308 uint64_t flags = gdb_get_cmd_param(params, 1)->val_ull; 309 uint64_t mode = gdb_get_cmd_param(params, 2)->val_ull; 310 311 #ifdef CONFIG_LINUX 312 int fd = do_guest_openat(cpu_env(gdbserver_state.g_cpu), 0, filename, 313 flags, mode, false); 314 #else 315 int fd = open(filename, flags, mode); 316 #endif 317 if (fd < 0) { 318 g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno); 319 } else { 320 g_string_printf(gdbserver_state.str_buf, "F%x", fd); 321 } 322 gdb_put_strbuf(); 323 } 324 325 void gdb_handle_v_file_close(GArray *params, void *user_ctx) 326 { 327 int fd = gdb_get_cmd_param(params, 0)->val_ul; 328 329 if (close(fd) == -1) { 330 g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno); 331 gdb_put_strbuf(); 332 return; 333 } 334 335 gdb_put_packet("F00"); 336 } 337 338 void gdb_handle_v_file_pread(GArray *params, void *user_ctx) 339 { 340 int fd = gdb_get_cmd_param(params, 0)->val_ul; 341 size_t count = gdb_get_cmd_param(params, 1)->val_ull; 342 off_t offset = gdb_get_cmd_param(params, 2)->val_ull; 343 344 size_t bufsiz = MIN(count, BUFSIZ); 345 g_autofree char *buf = g_try_malloc(bufsiz); 346 if (buf == NULL) { 347 gdb_put_packet("E12"); 348 return; 349 } 350 351 ssize_t n = pread(fd, buf, bufsiz, offset); 352 if (n < 0) { 353 g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno); 354 gdb_put_strbuf(); 355 return; 356 } 357 hostio_reply_with_data(buf, n); 358 } 359 360 void gdb_handle_v_file_readlink(GArray *params, void *user_ctx) 361 { 362 const char *filename = get_filename_param(params, 0); 363 364 g_autofree char *buf = g_try_malloc(BUFSIZ); 365 if (buf == NULL) { 366 gdb_put_packet("E12"); 367 return; 368 } 369 370 #ifdef CONFIG_LINUX 371 ssize_t n = do_guest_readlink(filename, buf, BUFSIZ); 372 #else 373 ssize_t n = readlink(filename, buf, BUFSIZ); 374 #endif 375 if (n < 0) { 376 g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno); 377 gdb_put_strbuf(); 378 return; 379 } 380 hostio_reply_with_data(buf, n); 381 } 382 383 void gdb_handle_query_xfer_exec_file(GArray *params, void *user_ctx) 384 { 385 uint32_t pid = gdb_get_cmd_param(params, 0)->val_ul; 386 uint32_t offset = gdb_get_cmd_param(params, 1)->val_ul; 387 uint32_t length = gdb_get_cmd_param(params, 2)->val_ul; 388 389 GDBProcess *process = gdb_get_process(pid); 390 if (!process) { 391 gdb_put_packet("E00"); 392 return; 393 } 394 395 CPUState *cpu = gdb_get_first_cpu_in_process(process); 396 if (!cpu) { 397 gdb_put_packet("E00"); 398 return; 399 } 400 401 TaskState *ts = get_task_state(cpu); 402 if (!ts || !ts->bprm || !ts->bprm->filename) { 403 gdb_put_packet("E00"); 404 return; 405 } 406 407 size_t total_length = strlen(ts->bprm->filename); 408 if (offset > total_length) { 409 gdb_put_packet("E00"); 410 return; 411 } 412 if (offset + length > total_length) { 413 length = total_length - offset; 414 } 415 416 g_string_printf(gdbserver_state.str_buf, "l%.*s", length, 417 ts->bprm->filename + offset); 418 gdb_put_strbuf(); 419 } 420 421 int gdb_target_sigtrap(void) 422 { 423 return TARGET_SIGTRAP; 424 } 425