qemu

Форк
0
/
user-target.c 
426 строк · 9.9 Кб
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 "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
    CPUClass *cc;
237
    cc = CPU_GET_CLASS(cpu);
238
    if (cc->memory_rw_debug) {
239
        return cc->memory_rw_debug(cpu, addr, buf, len, is_write);
240
    }
241
    return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
242
}
243

244
void gdb_handle_query_xfer_auxv(GArray *params, void *user_ctx)
245
{
246
    TaskState *ts;
247
    unsigned long offset, len, saved_auxv, auxv_len;
248

249
    if (params->len < 2) {
250
        gdb_put_packet("E22");
251
        return;
252
    }
253

254
    offset = gdb_get_cmd_param(params, 0)->val_ul;
255
    len = gdb_get_cmd_param(params, 1)->val_ul;
256
    ts = get_task_state(gdbserver_state.c_cpu);
257
    saved_auxv = ts->info->saved_auxv;
258
    auxv_len = ts->info->auxv_len;
259

260
    if (offset >= auxv_len) {
261
        gdb_put_packet("E00");
262
        return;
263
    }
264

265
    if (len > (MAX_PACKET_LENGTH - 5) / 2) {
266
        len = (MAX_PACKET_LENGTH - 5) / 2;
267
    }
268

269
    if (len < auxv_len - offset) {
270
        g_string_assign(gdbserver_state.str_buf, "m");
271
    } else {
272
        g_string_assign(gdbserver_state.str_buf, "l");
273
        len = auxv_len - offset;
274
    }
275

276
    g_byte_array_set_size(gdbserver_state.mem_buf, len);
277
    if (target_memory_rw_debug(gdbserver_state.g_cpu, saved_auxv + offset,
278
                               gdbserver_state.mem_buf->data, len, false)) {
279
        gdb_put_packet("E14");
280
        return;
281
    }
282

283
    gdb_memtox(gdbserver_state.str_buf,
284
           (const char *)gdbserver_state.mem_buf->data, len);
285
    gdb_put_packet_binary(gdbserver_state.str_buf->str,
286
                      gdbserver_state.str_buf->len, true);
287
}
288
#endif
289

290
static const char *get_filename_param(GArray *params, int i)
291
{
292
    const char *hex_filename = gdb_get_cmd_param(params, i)->data;
293
    gdb_hextomem(gdbserver_state.mem_buf, hex_filename,
294
                 strlen(hex_filename) / 2);
295
    g_byte_array_append(gdbserver_state.mem_buf, (const guint8 *)"", 1);
296
    return (const char *)gdbserver_state.mem_buf->data;
297
}
298

299
static void hostio_reply_with_data(const void *buf, size_t n)
300
{
301
    g_string_printf(gdbserver_state.str_buf, "F%zx;", n);
302
    gdb_memtox(gdbserver_state.str_buf, buf, n);
303
    gdb_put_packet_binary(gdbserver_state.str_buf->str,
304
                          gdbserver_state.str_buf->len, true);
305
}
306

307
void gdb_handle_v_file_open(GArray *params, void *user_ctx)
308
{
309
    const char *filename = get_filename_param(params, 0);
310
    uint64_t flags = gdb_get_cmd_param(params, 1)->val_ull;
311
    uint64_t mode = gdb_get_cmd_param(params, 2)->val_ull;
312

313
#ifdef CONFIG_LINUX
314
    int fd = do_guest_openat(cpu_env(gdbserver_state.g_cpu), 0, filename,
315
                             flags, mode, false);
316
#else
317
    int fd = open(filename, flags, mode);
318
#endif
319
    if (fd < 0) {
320
        g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
321
    } else {
322
        g_string_printf(gdbserver_state.str_buf, "F%d", fd);
323
    }
324
    gdb_put_strbuf();
325
}
326

327
void gdb_handle_v_file_close(GArray *params, void *user_ctx)
328
{
329
    int fd = gdb_get_cmd_param(params, 0)->val_ul;
330

331
    if (close(fd) == -1) {
332
        g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
333
        gdb_put_strbuf();
334
        return;
335
    }
336

337
    gdb_put_packet("F00");
338
}
339

340
void gdb_handle_v_file_pread(GArray *params, void *user_ctx)
341
{
342
    int fd = gdb_get_cmd_param(params, 0)->val_ul;
343
    size_t count = gdb_get_cmd_param(params, 1)->val_ull;
344
    off_t offset = gdb_get_cmd_param(params, 2)->val_ull;
345

346
    size_t bufsiz = MIN(count, BUFSIZ);
347
    g_autofree char *buf = g_try_malloc(bufsiz);
348
    if (buf == NULL) {
349
        gdb_put_packet("E12");
350
        return;
351
    }
352

353
    ssize_t n = pread(fd, buf, bufsiz, offset);
354
    if (n < 0) {
355
        g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
356
        gdb_put_strbuf();
357
        return;
358
    }
359
    hostio_reply_with_data(buf, n);
360
}
361

362
void gdb_handle_v_file_readlink(GArray *params, void *user_ctx)
363
{
364
    const char *filename = get_filename_param(params, 0);
365

366
    g_autofree char *buf = g_try_malloc(BUFSIZ);
367
    if (buf == NULL) {
368
        gdb_put_packet("E12");
369
        return;
370
    }
371

372
#ifdef CONFIG_LINUX
373
    ssize_t n = do_guest_readlink(filename, buf, BUFSIZ);
374
#else
375
    ssize_t n = readlink(filename, buf, BUFSIZ);
376
#endif
377
    if (n < 0) {
378
        g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
379
        gdb_put_strbuf();
380
        return;
381
    }
382
    hostio_reply_with_data(buf, n);
383
}
384

385
void gdb_handle_query_xfer_exec_file(GArray *params, void *user_ctx)
386
{
387
    uint32_t pid = gdb_get_cmd_param(params, 0)->val_ul;
388
    uint32_t offset = gdb_get_cmd_param(params, 1)->val_ul;
389
    uint32_t length = gdb_get_cmd_param(params, 2)->val_ul;
390

391
    GDBProcess *process = gdb_get_process(pid);
392
    if (!process) {
393
        gdb_put_packet("E00");
394
        return;
395
    }
396

397
    CPUState *cpu = gdb_get_first_cpu_in_process(process);
398
    if (!cpu) {
399
        gdb_put_packet("E00");
400
        return;
401
    }
402

403
    TaskState *ts = get_task_state(cpu);
404
    if (!ts || !ts->bprm || !ts->bprm->filename) {
405
        gdb_put_packet("E00");
406
        return;
407
    }
408

409
    size_t total_length = strlen(ts->bprm->filename);
410
    if (offset > total_length) {
411
        gdb_put_packet("E00");
412
        return;
413
    }
414
    if (offset + length > total_length) {
415
        length = total_length - offset;
416
    }
417

418
    g_string_printf(gdbserver_state.str_buf, "l%.*s", length,
419
                    ts->bprm->filename + offset);
420
    gdb_put_strbuf();
421
}
422

423
int gdb_target_sigtrap(void)
424
{
425
    return TARGET_SIGTRAP;
426
}
427

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.