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