xref: /openbmc/qemu/gdbstub/user-target.c (revision 651ccdfa)
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 
15 /*
16  * Map target signal numbers to GDB protocol signal numbers and vice
17  * versa.  For user emulation's currently supported systems, we can
18  * assume most signals are defined.
19  */
20 
21 static int gdb_signal_table[] = {
22     0,
23     TARGET_SIGHUP,
24     TARGET_SIGINT,
25     TARGET_SIGQUIT,
26     TARGET_SIGILL,
27     TARGET_SIGTRAP,
28     TARGET_SIGABRT,
29     -1, /* SIGEMT */
30     TARGET_SIGFPE,
31     TARGET_SIGKILL,
32     TARGET_SIGBUS,
33     TARGET_SIGSEGV,
34     TARGET_SIGSYS,
35     TARGET_SIGPIPE,
36     TARGET_SIGALRM,
37     TARGET_SIGTERM,
38     TARGET_SIGURG,
39     TARGET_SIGSTOP,
40     TARGET_SIGTSTP,
41     TARGET_SIGCONT,
42     TARGET_SIGCHLD,
43     TARGET_SIGTTIN,
44     TARGET_SIGTTOU,
45     TARGET_SIGIO,
46     TARGET_SIGXCPU,
47     TARGET_SIGXFSZ,
48     TARGET_SIGVTALRM,
49     TARGET_SIGPROF,
50     TARGET_SIGWINCH,
51     -1, /* SIGLOST */
52     TARGET_SIGUSR1,
53     TARGET_SIGUSR2,
54 #ifdef TARGET_SIGPWR
55     TARGET_SIGPWR,
56 #else
57     -1,
58 #endif
59     -1, /* SIGPOLL */
60     -1,
61     -1,
62     -1,
63     -1,
64     -1,
65     -1,
66     -1,
67     -1,
68     -1,
69     -1,
70     -1,
71 #ifdef __SIGRTMIN
72     __SIGRTMIN + 1,
73     __SIGRTMIN + 2,
74     __SIGRTMIN + 3,
75     __SIGRTMIN + 4,
76     __SIGRTMIN + 5,
77     __SIGRTMIN + 6,
78     __SIGRTMIN + 7,
79     __SIGRTMIN + 8,
80     __SIGRTMIN + 9,
81     __SIGRTMIN + 10,
82     __SIGRTMIN + 11,
83     __SIGRTMIN + 12,
84     __SIGRTMIN + 13,
85     __SIGRTMIN + 14,
86     __SIGRTMIN + 15,
87     __SIGRTMIN + 16,
88     __SIGRTMIN + 17,
89     __SIGRTMIN + 18,
90     __SIGRTMIN + 19,
91     __SIGRTMIN + 20,
92     __SIGRTMIN + 21,
93     __SIGRTMIN + 22,
94     __SIGRTMIN + 23,
95     __SIGRTMIN + 24,
96     __SIGRTMIN + 25,
97     __SIGRTMIN + 26,
98     __SIGRTMIN + 27,
99     __SIGRTMIN + 28,
100     __SIGRTMIN + 29,
101     __SIGRTMIN + 30,
102     __SIGRTMIN + 31,
103     -1, /* SIGCANCEL */
104     __SIGRTMIN,
105     __SIGRTMIN + 32,
106     __SIGRTMIN + 33,
107     __SIGRTMIN + 34,
108     __SIGRTMIN + 35,
109     __SIGRTMIN + 36,
110     __SIGRTMIN + 37,
111     __SIGRTMIN + 38,
112     __SIGRTMIN + 39,
113     __SIGRTMIN + 40,
114     __SIGRTMIN + 41,
115     __SIGRTMIN + 42,
116     __SIGRTMIN + 43,
117     __SIGRTMIN + 44,
118     __SIGRTMIN + 45,
119     __SIGRTMIN + 46,
120     __SIGRTMIN + 47,
121     __SIGRTMIN + 48,
122     __SIGRTMIN + 49,
123     __SIGRTMIN + 50,
124     __SIGRTMIN + 51,
125     __SIGRTMIN + 52,
126     __SIGRTMIN + 53,
127     __SIGRTMIN + 54,
128     __SIGRTMIN + 55,
129     __SIGRTMIN + 56,
130     __SIGRTMIN + 57,
131     __SIGRTMIN + 58,
132     __SIGRTMIN + 59,
133     __SIGRTMIN + 60,
134     __SIGRTMIN + 61,
135     __SIGRTMIN + 62,
136     __SIGRTMIN + 63,
137     __SIGRTMIN + 64,
138     __SIGRTMIN + 65,
139     __SIGRTMIN + 66,
140     __SIGRTMIN + 67,
141     __SIGRTMIN + 68,
142     __SIGRTMIN + 69,
143     __SIGRTMIN + 70,
144     __SIGRTMIN + 71,
145     __SIGRTMIN + 72,
146     __SIGRTMIN + 73,
147     __SIGRTMIN + 74,
148     __SIGRTMIN + 75,
149     __SIGRTMIN + 76,
150     __SIGRTMIN + 77,
151     __SIGRTMIN + 78,
152     __SIGRTMIN + 79,
153     __SIGRTMIN + 80,
154     __SIGRTMIN + 81,
155     __SIGRTMIN + 82,
156     __SIGRTMIN + 83,
157     __SIGRTMIN + 84,
158     __SIGRTMIN + 85,
159     __SIGRTMIN + 86,
160     __SIGRTMIN + 87,
161     __SIGRTMIN + 88,
162     __SIGRTMIN + 89,
163     __SIGRTMIN + 90,
164     __SIGRTMIN + 91,
165     __SIGRTMIN + 92,
166     __SIGRTMIN + 93,
167     __SIGRTMIN + 94,
168     __SIGRTMIN + 95,
169     -1, /* SIGINFO */
170     -1, /* UNKNOWN */
171     -1, /* DEFAULT */
172     -1,
173     -1,
174     -1,
175     -1,
176     -1,
177     -1
178 #endif
179 };
180 
181 int gdb_signal_to_target(int sig)
182 {
183     if (sig < ARRAY_SIZE(gdb_signal_table)) {
184         return gdb_signal_table[sig];
185     } else {
186         return -1;
187     }
188 }
189 
190 int gdb_target_signal_to_gdb(int sig)
191 {
192     int i;
193     for (i = 0; i < ARRAY_SIZE(gdb_signal_table); i++) {
194         if (gdb_signal_table[i] == sig) {
195             return i;
196         }
197     }
198     return GDB_SIGNAL_UNKNOWN;
199 }
200 
201 int gdb_get_cpu_index(CPUState *cpu)
202 {
203     TaskState *ts = (TaskState *) cpu->opaque;
204     return ts ? ts->ts_tid : -1;
205 }
206 
207 /*
208  * User-mode specific command helpers
209  */
210 
211 void gdb_handle_query_offsets(GArray *params, void *user_ctx)
212 {
213     TaskState *ts;
214 
215     ts = gdbserver_state.c_cpu->opaque;
216     g_string_printf(gdbserver_state.str_buf,
217                     "Text=" TARGET_ABI_FMT_lx
218                     ";Data=" TARGET_ABI_FMT_lx
219                     ";Bss=" TARGET_ABI_FMT_lx,
220                     ts->info->code_offset,
221                     ts->info->data_offset,
222                     ts->info->data_offset);
223     gdb_put_strbuf();
224 }
225 
226 #if defined(CONFIG_LINUX)
227 /* Partial user only duplicate of helper in gdbstub.c */
228 static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
229                                          uint8_t *buf, int len, bool is_write)
230 {
231     CPUClass *cc;
232     cc = CPU_GET_CLASS(cpu);
233     if (cc->memory_rw_debug) {
234         return cc->memory_rw_debug(cpu, addr, buf, len, is_write);
235     }
236     return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
237 }
238 
239 void gdb_handle_query_xfer_auxv(GArray *params, void *user_ctx)
240 {
241     TaskState *ts;
242     unsigned long offset, len, saved_auxv, auxv_len;
243 
244     if (params->len < 2) {
245         gdb_put_packet("E22");
246         return;
247     }
248 
249     offset = get_param(params, 0)->val_ul;
250     len = get_param(params, 1)->val_ul;
251     ts = gdbserver_state.c_cpu->opaque;
252     saved_auxv = ts->info->saved_auxv;
253     auxv_len = ts->info->auxv_len;
254 
255     if (offset >= auxv_len) {
256         gdb_put_packet("E00");
257         return;
258     }
259 
260     if (len > (MAX_PACKET_LENGTH - 5) / 2) {
261         len = (MAX_PACKET_LENGTH - 5) / 2;
262     }
263 
264     if (len < auxv_len - offset) {
265         g_string_assign(gdbserver_state.str_buf, "m");
266     } else {
267         g_string_assign(gdbserver_state.str_buf, "l");
268         len = auxv_len - offset;
269     }
270 
271     g_byte_array_set_size(gdbserver_state.mem_buf, len);
272     if (target_memory_rw_debug(gdbserver_state.g_cpu, saved_auxv + offset,
273                                gdbserver_state.mem_buf->data, len, false)) {
274         gdb_put_packet("E14");
275         return;
276     }
277 
278     gdb_memtox(gdbserver_state.str_buf,
279            (const char *)gdbserver_state.mem_buf->data, len);
280     gdb_put_packet_binary(gdbserver_state.str_buf->str,
281                       gdbserver_state.str_buf->len, true);
282 }
283 #endif
284