xref: /qemu/gdbstub/user-target.c (revision 0cc14182aba961f4c34a21dd202ce6e4a87470f5)
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