qemu

Форк
0
/
main.c 
1030 строк · 29.7 Кб
1
/*
2
 *  qemu user main
3
 *
4
 *  Copyright (c) 2003-2008 Fabrice Bellard
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18
 */
19

20
#include "qemu/osdep.h"
21
#include "qemu/help-texts.h"
22
#include "qemu/units.h"
23
#include "qemu/accel.h"
24
#include "qemu-version.h"
25
#include <sys/syscall.h>
26
#include <sys/resource.h>
27
#include <sys/shm.h>
28
#include <linux/binfmts.h>
29

30
#include "qapi/error.h"
31
#include "qemu.h"
32
#include "user-internals.h"
33
#include "qemu/path.h"
34
#include "qemu/queue.h"
35
#include "qemu/config-file.h"
36
#include "qemu/cutils.h"
37
#include "qemu/error-report.h"
38
#include "qemu/help_option.h"
39
#include "qemu/module.h"
40
#include "qemu/plugin.h"
41
#include "user/guest-base.h"
42
#include "exec/exec-all.h"
43
#include "exec/gdbstub.h"
44
#include "gdbstub/user.h"
45
#include "tcg/startup.h"
46
#include "qemu/timer.h"
47
#include "qemu/envlist.h"
48
#include "qemu/guest-random.h"
49
#include "elf.h"
50
#include "trace/control.h"
51
#include "target_elf.h"
52
#include "cpu_loop-common.h"
53
#include "crypto/init.h"
54
#include "fd-trans.h"
55
#include "signal-common.h"
56
#include "loader.h"
57
#include "user-mmap.h"
58
#include "tcg/perf.h"
59
#include "exec/page-vary.h"
60

61
#ifdef CONFIG_SEMIHOSTING
62
#include "semihosting/semihost.h"
63
#endif
64

65
#ifndef AT_FLAGS_PRESERVE_ARGV0
66
#define AT_FLAGS_PRESERVE_ARGV0_BIT 0
67
#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
68
#endif
69

70
char *exec_path;
71
char real_exec_path[PATH_MAX];
72

73
static bool opt_one_insn_per_tb;
74
static const char *argv0;
75
static const char *gdbstub;
76
static envlist_t *envlist;
77
static const char *cpu_model;
78
static const char *cpu_type;
79
static const char *seed_optarg;
80
unsigned long mmap_min_addr;
81
uintptr_t guest_base;
82
bool have_guest_base;
83

84
/*
85
 * Used to implement backwards-compatibility for the `-strace`, and
86
 * QEMU_STRACE options. Without this, the QEMU_LOG can be overwritten by
87
 * -strace, or vice versa.
88
 */
89
static bool enable_strace;
90

91
/*
92
 * The last log mask given by the user in an environment variable or argument.
93
 * Used to support command line arguments overriding environment variables.
94
 */
95
static int last_log_mask;
96
static const char *last_log_filename;
97

98
/*
99
 * When running 32-on-64 we should make sure we can fit all of the possible
100
 * guest address space into a contiguous chunk of virtual host memory.
101
 *
102
 * This way we will never overlap with our own libraries or binaries or stack
103
 * or anything else that QEMU maps.
104
 *
105
 * Many cpus reserve the high bit (or more than one for some 64-bit cpus)
106
 * of the address for the kernel.  Some cpus rely on this and user space
107
 * uses the high bit(s) for pointer tagging and the like.  For them, we
108
 * must preserve the expected address space.
109
 */
110
#ifndef MAX_RESERVED_VA
111
# if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
112
#  if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
113
      (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
114
#   define MAX_RESERVED_VA(CPU)  0xfffffffful
115
#  else
116
#   define MAX_RESERVED_VA(CPU)  ((1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
117
#  endif
118
# else
119
#  define MAX_RESERVED_VA(CPU)  0
120
# endif
121
#endif
122

123
unsigned long reserved_va;
124

125
static void usage(int exitcode);
126

127
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
128
const char *qemu_uname_release;
129

130
#if !defined(TARGET_DEFAULT_STACK_SIZE)
131
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
132
   we allocate a bigger stack. Need a better solution, for example
133
   by remapping the process stack directly at the right place */
134
#define TARGET_DEFAULT_STACK_SIZE	8 * 1024 * 1024UL
135
#endif
136

137
unsigned long guest_stack_size = TARGET_DEFAULT_STACK_SIZE;
138

139
/***********************************************************/
140
/* Helper routines for implementing atomic operations.  */
141

142
/* Make sure everything is in a consistent state for calling fork().  */
143
void fork_start(void)
144
{
145
    start_exclusive();
146
    mmap_fork_start();
147
    cpu_list_lock();
148
    qemu_plugin_user_prefork_lock();
149
    gdbserver_fork_start();
150
}
151

152
void fork_end(pid_t pid)
153
{
154
    bool child = pid == 0;
155

156
    qemu_plugin_user_postfork(child);
157
    mmap_fork_end(child);
158
    if (child) {
159
        CPUState *cpu, *next_cpu;
160
        /* Child processes created by fork() only have a single thread.
161
           Discard information about the parent threads.  */
162
        CPU_FOREACH_SAFE(cpu, next_cpu) {
163
            if (cpu != thread_cpu) {
164
                QTAILQ_REMOVE_RCU(&cpus_queue, cpu, node);
165
            }
166
        }
167
        qemu_init_cpu_list();
168
        get_task_state(thread_cpu)->ts_tid = qemu_get_thread_id();
169
    } else {
170
        cpu_list_unlock();
171
    }
172
    gdbserver_fork_end(thread_cpu, pid);
173
    /*
174
     * qemu_init_cpu_list() reinitialized the child exclusive state, but we
175
     * also need to keep current_cpu consistent, so call end_exclusive() for
176
     * both child and parent.
177
     */
178
    end_exclusive();
179
}
180

181
__thread CPUState *thread_cpu;
182

183
bool qemu_cpu_is_self(CPUState *cpu)
184
{
185
    return thread_cpu == cpu;
186
}
187

188
void qemu_cpu_kick(CPUState *cpu)
189
{
190
    cpu_exit(cpu);
191
}
192

193
void task_settid(TaskState *ts)
194
{
195
    if (ts->ts_tid == 0) {
196
        ts->ts_tid = (pid_t)syscall(SYS_gettid);
197
    }
198
}
199

200
void stop_all_tasks(void)
201
{
202
    /*
203
     * We trust that when using NPTL, start_exclusive()
204
     * handles thread stopping correctly.
205
     */
206
    start_exclusive();
207
}
208

209
/* Assumes contents are already zeroed.  */
210
void init_task_state(TaskState *ts)
211
{
212
    long ticks_per_sec;
213
    struct timespec bt;
214

215
    ts->used = 1;
216
    ts->sigaltstack_used = (struct target_sigaltstack) {
217
        .ss_sp = 0,
218
        .ss_size = 0,
219
        .ss_flags = TARGET_SS_DISABLE,
220
    };
221

222
    /* Capture task start time relative to system boot */
223

224
    ticks_per_sec = sysconf(_SC_CLK_TCK);
225

226
    if ((ticks_per_sec > 0) && !clock_gettime(CLOCK_BOOTTIME, &bt)) {
227
        /* start_boottime is expressed in clock ticks */
228
        ts->start_boottime = bt.tv_sec * (uint64_t) ticks_per_sec;
229
        ts->start_boottime += bt.tv_nsec * (uint64_t) ticks_per_sec /
230
                              NANOSECONDS_PER_SECOND;
231
    }
232
}
233

234
CPUArchState *cpu_copy(CPUArchState *env)
235
{
236
    CPUState *cpu = env_cpu(env);
237
    CPUState *new_cpu = cpu_create(cpu_type);
238
    CPUArchState *new_env = cpu_env(new_cpu);
239
    CPUBreakpoint *bp;
240

241
    /* Reset non arch specific state */
242
    cpu_reset(new_cpu);
243

244
    new_cpu->tcg_cflags = cpu->tcg_cflags;
245
    memcpy(new_env, env, sizeof(CPUArchState));
246
#if defined(TARGET_I386) || defined(TARGET_X86_64)
247
    new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
248
                                    PROT_READ | PROT_WRITE,
249
                                    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
250
    memcpy(g2h_untagged(new_env->gdt.base), g2h_untagged(env->gdt.base),
251
           sizeof(uint64_t) * TARGET_GDT_ENTRIES);
252
    OBJECT(new_cpu)->free = OBJECT(cpu)->free;
253
#endif
254

255
    /* Clone all break/watchpoints.
256
       Note: Once we support ptrace with hw-debug register access, make sure
257
       BP_CPU break/watchpoints are handled correctly on clone. */
258
    QTAILQ_INIT(&new_cpu->breakpoints);
259
    QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
260
        cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL);
261
    }
262

263
    return new_env;
264
}
265

266
static void handle_arg_help(const char *arg)
267
{
268
    usage(EXIT_SUCCESS);
269
}
270

271
static void handle_arg_log(const char *arg)
272
{
273
    last_log_mask = qemu_str_to_log_mask(arg);
274
    if (!last_log_mask) {
275
        qemu_print_log_usage(stdout);
276
        exit(EXIT_FAILURE);
277
    }
278
}
279

280
static void handle_arg_dfilter(const char *arg)
281
{
282
    qemu_set_dfilter_ranges(arg, &error_fatal);
283
}
284

285
static void handle_arg_log_filename(const char *arg)
286
{
287
    last_log_filename = arg;
288
}
289

290
static void handle_arg_set_env(const char *arg)
291
{
292
    char *r, *p, *token;
293
    r = p = strdup(arg);
294
    while ((token = strsep(&p, ",")) != NULL) {
295
        if (envlist_setenv(envlist, token) != 0) {
296
            usage(EXIT_FAILURE);
297
        }
298
    }
299
    free(r);
300
}
301

302
static void handle_arg_unset_env(const char *arg)
303
{
304
    char *r, *p, *token;
305
    r = p = strdup(arg);
306
    while ((token = strsep(&p, ",")) != NULL) {
307
        if (envlist_unsetenv(envlist, token) != 0) {
308
            usage(EXIT_FAILURE);
309
        }
310
    }
311
    free(r);
312
}
313

314
static void handle_arg_argv0(const char *arg)
315
{
316
    argv0 = strdup(arg);
317
}
318

319
static void handle_arg_stack_size(const char *arg)
320
{
321
    char *p;
322
    guest_stack_size = strtoul(arg, &p, 0);
323
    if (guest_stack_size == 0) {
324
        usage(EXIT_FAILURE);
325
    }
326

327
    if (*p == 'M') {
328
        guest_stack_size *= MiB;
329
    } else if (*p == 'k' || *p == 'K') {
330
        guest_stack_size *= KiB;
331
    }
332
}
333

334
static void handle_arg_ld_prefix(const char *arg)
335
{
336
    interp_prefix = strdup(arg);
337
}
338

339
static void handle_arg_pagesize(const char *arg)
340
{
341
    unsigned size, want = qemu_real_host_page_size();
342

343
    if (qemu_strtoui(arg, NULL, 10, &size) || size != want) {
344
        warn_report("Deprecated page size option cannot "
345
                    "change host page size (%u)", want);
346
    }
347
}
348

349
static void handle_arg_seed(const char *arg)
350
{
351
    seed_optarg = arg;
352
}
353

354
static void handle_arg_gdb(const char *arg)
355
{
356
    gdbstub = g_strdup(arg);
357
}
358

359
static void handle_arg_uname(const char *arg)
360
{
361
    qemu_uname_release = strdup(arg);
362
}
363

364
static void handle_arg_cpu(const char *arg)
365
{
366
    cpu_model = strdup(arg);
367
    if (cpu_model == NULL || is_help_option(cpu_model)) {
368
        list_cpus();
369
        exit(EXIT_FAILURE);
370
    }
371
}
372

373
static void handle_arg_guest_base(const char *arg)
374
{
375
    guest_base = strtol(arg, NULL, 0);
376
    have_guest_base = true;
377
}
378

379
static void handle_arg_reserved_va(const char *arg)
380
{
381
    char *p;
382
    int shift = 0;
383
    unsigned long val;
384

385
    val = strtoul(arg, &p, 0);
386
    switch (*p) {
387
    case 'k':
388
    case 'K':
389
        shift = 10;
390
        break;
391
    case 'M':
392
        shift = 20;
393
        break;
394
    case 'G':
395
        shift = 30;
396
        break;
397
    }
398
    if (shift) {
399
        unsigned long unshifted = val;
400
        p++;
401
        val <<= shift;
402
        if (val >> shift != unshifted) {
403
            fprintf(stderr, "Reserved virtual address too big\n");
404
            exit(EXIT_FAILURE);
405
        }
406
    }
407
    if (*p) {
408
        fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
409
        exit(EXIT_FAILURE);
410
    }
411
    /* The representation is size - 1, with 0 remaining "default". */
412
    reserved_va = val ? val - 1 : 0;
413
}
414

415
static void handle_arg_one_insn_per_tb(const char *arg)
416
{
417
    opt_one_insn_per_tb = true;
418
}
419

420
static void handle_arg_strace(const char *arg)
421
{
422
    enable_strace = true;
423
}
424

425
static void handle_arg_version(const char *arg)
426
{
427
    printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
428
           "\n" QEMU_COPYRIGHT "\n");
429
    exit(EXIT_SUCCESS);
430
}
431

432
static void handle_arg_trace(const char *arg)
433
{
434
    trace_opt_parse(arg);
435
}
436

437
#if defined(TARGET_XTENSA)
438
static void handle_arg_abi_call0(const char *arg)
439
{
440
    xtensa_set_abi_call0();
441
}
442
#endif
443

444
static void handle_arg_perfmap(const char *arg)
445
{
446
    perf_enable_perfmap();
447
}
448

449
static void handle_arg_jitdump(const char *arg)
450
{
451
    perf_enable_jitdump();
452
}
453

454
static QemuPluginList plugins = QTAILQ_HEAD_INITIALIZER(plugins);
455

456
#ifdef CONFIG_PLUGIN
457
static void handle_arg_plugin(const char *arg)
458
{
459
    qemu_plugin_opt_parse(arg, &plugins);
460
}
461
#endif
462

463
struct qemu_argument {
464
    const char *argv;
465
    const char *env;
466
    bool has_arg;
467
    void (*handle_opt)(const char *arg);
468
    const char *example;
469
    const char *help;
470
};
471

472
static const struct qemu_argument arg_table[] = {
473
    {"h",          "",                 false, handle_arg_help,
474
     "",           "print this help"},
475
    {"help",       "",                 false, handle_arg_help,
476
     "",           ""},
477
    {"g",          "QEMU_GDB",         true,  handle_arg_gdb,
478
     "port",       "wait gdb connection to 'port'"},
479
    {"L",          "QEMU_LD_PREFIX",   true,  handle_arg_ld_prefix,
480
     "path",       "set the elf interpreter prefix to 'path'"},
481
    {"s",          "QEMU_STACK_SIZE",  true,  handle_arg_stack_size,
482
     "size",       "set the stack size to 'size' bytes"},
483
    {"cpu",        "QEMU_CPU",         true,  handle_arg_cpu,
484
     "model",      "select CPU (-cpu help for list)"},
485
    {"E",          "QEMU_SET_ENV",     true,  handle_arg_set_env,
486
     "var=value",  "sets targets environment variable (see below)"},
487
    {"U",          "QEMU_UNSET_ENV",   true,  handle_arg_unset_env,
488
     "var",        "unsets targets environment variable (see below)"},
489
    {"0",          "QEMU_ARGV0",       true,  handle_arg_argv0,
490
     "argv0",      "forces target process argv[0] to be 'argv0'"},
491
    {"r",          "QEMU_UNAME",       true,  handle_arg_uname,
492
     "uname",      "set qemu uname release string to 'uname'"},
493
    {"B",          "QEMU_GUEST_BASE",  true,  handle_arg_guest_base,
494
     "address",    "set guest_base address to 'address'"},
495
    {"R",          "QEMU_RESERVED_VA", true,  handle_arg_reserved_va,
496
     "size",       "reserve 'size' bytes for guest virtual address space"},
497
    {"d",          "QEMU_LOG",         true,  handle_arg_log,
498
     "item[,...]", "enable logging of specified items "
499
     "(use '-d help' for a list of items)"},
500
    {"dfilter",    "QEMU_DFILTER",     true,  handle_arg_dfilter,
501
     "range[,...]","filter logging based on address range"},
502
    {"D",          "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
503
     "logfile",     "write logs to 'logfile' (default stderr)"},
504
    {"p",          "QEMU_PAGESIZE",    true,  handle_arg_pagesize,
505
     "pagesize",   "deprecated change to host page size"},
506
    {"one-insn-per-tb",
507
                   "QEMU_ONE_INSN_PER_TB",  false, handle_arg_one_insn_per_tb,
508
     "",           "run with one guest instruction per emulated TB"},
509
    {"strace",     "QEMU_STRACE",      false, handle_arg_strace,
510
     "",           "log system calls"},
511
    {"seed",       "QEMU_RAND_SEED",   true,  handle_arg_seed,
512
     "",           "Seed for pseudo-random number generator"},
513
    {"trace",      "QEMU_TRACE",       true,  handle_arg_trace,
514
     "",           "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
515
#ifdef CONFIG_PLUGIN
516
    {"plugin",     "QEMU_PLUGIN",      true,  handle_arg_plugin,
517
     "",           "[file=]<file>[,<argname>=<argvalue>]"},
518
#endif
519
    {"version",    "QEMU_VERSION",     false, handle_arg_version,
520
     "",           "display version information and exit"},
521
#if defined(TARGET_XTENSA)
522
    {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0,
523
     "",           "assume CALL0 Xtensa ABI"},
524
#endif
525
    {"perfmap",    "QEMU_PERFMAP",     false, handle_arg_perfmap,
526
     "",           "Generate a /tmp/perf-${pid}.map file for perf"},
527
    {"jitdump",    "QEMU_JITDUMP",     false, handle_arg_jitdump,
528
     "",           "Generate a jit-${pid}.dump file for perf"},
529
    {NULL, NULL, false, NULL, NULL, NULL}
530
};
531

532
static void usage(int exitcode)
533
{
534
    const struct qemu_argument *arginfo;
535
    int maxarglen;
536
    int maxenvlen;
537

538
    printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
539
           "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
540
           "\n"
541
           "Options and associated environment variables:\n"
542
           "\n");
543

544
    /* Calculate column widths. We must always have at least enough space
545
     * for the column header.
546
     */
547
    maxarglen = strlen("Argument");
548
    maxenvlen = strlen("Env-variable");
549

550
    for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
551
        int arglen = strlen(arginfo->argv);
552
        if (arginfo->has_arg) {
553
            arglen += strlen(arginfo->example) + 1;
554
        }
555
        if (strlen(arginfo->env) > maxenvlen) {
556
            maxenvlen = strlen(arginfo->env);
557
        }
558
        if (arglen > maxarglen) {
559
            maxarglen = arglen;
560
        }
561
    }
562

563
    printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
564
            maxenvlen, "Env-variable");
565

566
    for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
567
        if (arginfo->has_arg) {
568
            printf("-%s %-*s %-*s %s\n", arginfo->argv,
569
                   (int)(maxarglen - strlen(arginfo->argv) - 1),
570
                   arginfo->example, maxenvlen, arginfo->env, arginfo->help);
571
        } else {
572
            printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
573
                    maxenvlen, arginfo->env,
574
                    arginfo->help);
575
        }
576
    }
577

578
    printf("\n"
579
           "Defaults:\n"
580
           "QEMU_LD_PREFIX  = %s\n"
581
           "QEMU_STACK_SIZE = %ld byte\n",
582
           interp_prefix,
583
           guest_stack_size);
584

585
    printf("\n"
586
           "You can use -E and -U options or the QEMU_SET_ENV and\n"
587
           "QEMU_UNSET_ENV environment variables to set and unset\n"
588
           "environment variables for the target process.\n"
589
           "It is possible to provide several variables by separating them\n"
590
           "by commas in getsubopt(3) style. Additionally it is possible to\n"
591
           "provide the -E and -U options multiple times.\n"
592
           "The following lines are equivalent:\n"
593
           "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
594
           "    -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
595
           "    QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
596
           "Note that if you provide several changes to a single variable\n"
597
           "the last change will stay in effect.\n"
598
           "\n"
599
           QEMU_HELP_BOTTOM "\n");
600

601
    exit(exitcode);
602
}
603

604
static int parse_args(int argc, char **argv)
605
{
606
    const char *r;
607
    int optind;
608
    const struct qemu_argument *arginfo;
609

610
    for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
611
        if (arginfo->env == NULL) {
612
            continue;
613
        }
614

615
        r = getenv(arginfo->env);
616
        if (r != NULL) {
617
            arginfo->handle_opt(r);
618
        }
619
    }
620

621
    optind = 1;
622
    for (;;) {
623
        if (optind >= argc) {
624
            break;
625
        }
626
        r = argv[optind];
627
        if (r[0] != '-') {
628
            break;
629
        }
630
        optind++;
631
        r++;
632
        if (!strcmp(r, "-")) {
633
            break;
634
        }
635
        /* Treat --foo the same as -foo.  */
636
        if (r[0] == '-') {
637
            r++;
638
        }
639

640
        for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
641
            if (!strcmp(r, arginfo->argv)) {
642
                if (arginfo->has_arg) {
643
                    if (optind >= argc) {
644
                        (void) fprintf(stderr,
645
                            "qemu: missing argument for option '%s'\n", r);
646
                        exit(EXIT_FAILURE);
647
                    }
648
                    arginfo->handle_opt(argv[optind]);
649
                    optind++;
650
                } else {
651
                    arginfo->handle_opt(NULL);
652
                }
653
                break;
654
            }
655
        }
656

657
        /* no option matched the current argv */
658
        if (arginfo->handle_opt == NULL) {
659
            (void) fprintf(stderr, "qemu: unknown option '%s'\n", r);
660
            exit(EXIT_FAILURE);
661
        }
662
    }
663

664
    if (optind >= argc) {
665
        (void) fprintf(stderr, "qemu: no user program specified\n");
666
        exit(EXIT_FAILURE);
667
    }
668

669
    exec_path = argv[optind];
670

671
    return optind;
672
}
673

674
int main(int argc, char **argv, char **envp)
675
{
676
    struct target_pt_regs regs1, *regs = &regs1;
677
    struct image_info info1, *info = &info1;
678
    struct linux_binprm bprm;
679
    TaskState *ts;
680
    CPUArchState *env;
681
    CPUState *cpu;
682
    int optind;
683
    char **target_environ, **wrk;
684
    char **target_argv;
685
    int target_argc;
686
    int i;
687
    int ret;
688
    int execfd;
689
    int host_page_size;
690
    unsigned long max_reserved_va;
691
    bool preserve_argv0;
692

693
    error_init(argv[0]);
694
    module_call_init(MODULE_INIT_TRACE);
695
    qemu_init_cpu_list();
696
    module_call_init(MODULE_INIT_QOM);
697

698
    envlist = envlist_create();
699

700
    /*
701
     * add current environment into the list
702
     * envlist_setenv adds to the front of the list; to preserve environ
703
     * order add from back to front
704
     */
705
    for (wrk = environ; *wrk != NULL; wrk++) {
706
        continue;
707
    }
708
    while (wrk != environ) {
709
        wrk--;
710
        (void) envlist_setenv(envlist, *wrk);
711
    }
712

713
    /* Read the stack limit from the kernel.  If it's "unlimited",
714
       then we can do little else besides use the default.  */
715
    {
716
        struct rlimit lim;
717
        if (getrlimit(RLIMIT_STACK, &lim) == 0
718
            && lim.rlim_cur != RLIM_INFINITY
719
            && lim.rlim_cur == (target_long)lim.rlim_cur
720
            && lim.rlim_cur > guest_stack_size) {
721
            guest_stack_size = lim.rlim_cur;
722
        }
723
    }
724

725
    cpu_model = NULL;
726

727
    qemu_add_opts(&qemu_trace_opts);
728
    qemu_plugin_add_opts();
729

730
    optind = parse_args(argc, argv);
731

732
    qemu_set_log_filename_flags(last_log_filename,
733
                                last_log_mask | (enable_strace * LOG_STRACE),
734
                                &error_fatal);
735

736
    if (!trace_init_backends()) {
737
        exit(1);
738
    }
739
    trace_init_file();
740
    qemu_plugin_load_list(&plugins, &error_fatal);
741

742
    /* Zero out regs */
743
    memset(regs, 0, sizeof(struct target_pt_regs));
744

745
    /* Zero out image_info */
746
    memset(info, 0, sizeof(struct image_info));
747

748
    memset(&bprm, 0, sizeof (bprm));
749

750
    /* Scan interp_prefix dir for replacement files. */
751
    init_paths(interp_prefix);
752

753
    init_qemu_uname_release();
754

755
    /*
756
     * Manage binfmt-misc open-binary flag
757
     */
758
    errno = 0;
759
    execfd = qemu_getauxval(AT_EXECFD);
760
    if (errno != 0) {
761
        execfd = open(exec_path, O_RDONLY);
762
        if (execfd < 0) {
763
            printf("Error while loading %s: %s\n", exec_path, strerror(errno));
764
            _exit(EXIT_FAILURE);
765
        }
766
    }
767

768
    /* Resolve executable file name to full path name */
769
    if (realpath(exec_path, real_exec_path)) {
770
        exec_path = real_exec_path;
771
    }
772

773
    /*
774
     * get binfmt_misc flags
775
     */
776
    preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0);
777

778
    /*
779
     * Manage binfmt-misc preserve-arg[0] flag
780
     *    argv[optind]     full path to the binary
781
     *    argv[optind + 1] original argv[0]
782
     */
783
    if (optind + 1 < argc && preserve_argv0) {
784
        optind++;
785
    }
786

787
    if (cpu_model == NULL) {
788
        cpu_model = cpu_get_model(get_elf_eflags(execfd));
789
    }
790
    cpu_type = parse_cpu_option(cpu_model);
791

792
    /* init tcg before creating CPUs */
793
    {
794
        AccelState *accel = current_accel();
795
        AccelClass *ac = ACCEL_GET_CLASS(accel);
796

797
        accel_init_interfaces(ac);
798
        object_property_set_bool(OBJECT(accel), "one-insn-per-tb",
799
                                 opt_one_insn_per_tb, &error_abort);
800
        ac->init_machine(NULL);
801
    }
802

803
    /*
804
     * Finalize page size before creating CPUs.
805
     * This will do nothing if !TARGET_PAGE_BITS_VARY.
806
     * The most efficient setting is to match the host.
807
     */
808
    host_page_size = qemu_real_host_page_size();
809
    set_preferred_target_page_bits(ctz32(host_page_size));
810
    finalize_target_page_bits();
811

812
    cpu = cpu_create(cpu_type);
813
    env = cpu_env(cpu);
814
    cpu_reset(cpu);
815
    thread_cpu = cpu;
816

817
    /*
818
     * Reserving too much vm space via mmap can run into problems with rlimits,
819
     * oom due to page table creation, etc.  We will still try it, if directed
820
     * by the command-line option, but not by default. Unless we're running a
821
     * target address space of 32 or fewer bits on a host with 64 bits.
822
     */
823
    max_reserved_va = MAX_RESERVED_VA(cpu);
824
    if (reserved_va != 0) {
825
        if ((reserved_va + 1) % host_page_size) {
826
            char *s = size_to_str(host_page_size);
827
            fprintf(stderr, "Reserved virtual address not aligned mod %s\n", s);
828
            g_free(s);
829
            exit(EXIT_FAILURE);
830
        }
831
        if (max_reserved_va && reserved_va > max_reserved_va) {
832
            fprintf(stderr, "Reserved virtual address too big\n");
833
            exit(EXIT_FAILURE);
834
        }
835
    } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) {
836
        /* MAX_RESERVED_VA + 1 is a large power of 2, so is aligned. */
837
        reserved_va = max_reserved_va;
838
    }
839

840
    /*
841
     * Temporarily disable
842
     *   "comparison is always false due to limited range of data type"
843
     * due to comparison between (possible) uint64_t and uintptr_t.
844
     */
845
#pragma GCC diagnostic push
846
#pragma GCC diagnostic ignored "-Wtype-limits"
847
#pragma GCC diagnostic ignored "-Wtautological-compare"
848

849
    /*
850
     * Select an initial value for task_unmapped_base that is in range.
851
     */
852
    if (reserved_va) {
853
        if (TASK_UNMAPPED_BASE < reserved_va) {
854
            task_unmapped_base = TASK_UNMAPPED_BASE;
855
        } else {
856
            /* The most common default formula is TASK_SIZE / 3. */
857
            task_unmapped_base = TARGET_PAGE_ALIGN(reserved_va / 3);
858
        }
859
    } else if (TASK_UNMAPPED_BASE < UINTPTR_MAX) {
860
        task_unmapped_base = TASK_UNMAPPED_BASE;
861
    } else {
862
        /* 32-bit host: pick something medium size. */
863
        task_unmapped_base = 0x10000000;
864
    }
865
    mmap_next_start = task_unmapped_base;
866

867
    /* Similarly for elf_et_dyn_base. */
868
    if (reserved_va) {
869
        if (ELF_ET_DYN_BASE < reserved_va) {
870
            elf_et_dyn_base = ELF_ET_DYN_BASE;
871
        } else {
872
            /* The most common default formula is TASK_SIZE / 3 * 2. */
873
            elf_et_dyn_base = TARGET_PAGE_ALIGN(reserved_va / 3) * 2;
874
        }
875
    } else if (ELF_ET_DYN_BASE < UINTPTR_MAX) {
876
        elf_et_dyn_base = ELF_ET_DYN_BASE;
877
    } else {
878
        /* 32-bit host: pick something medium size. */
879
        elf_et_dyn_base = 0x18000000;
880
    }
881

882
#pragma GCC diagnostic pop
883

884
    {
885
        Error *err = NULL;
886
        if (seed_optarg != NULL) {
887
            qemu_guest_random_seed_main(seed_optarg, &err);
888
        } else {
889
            qcrypto_init(&err);
890
        }
891
        if (err) {
892
            error_reportf_err(err, "cannot initialize crypto: ");
893
            exit(1);
894
        }
895
    }
896

897
    target_environ = envlist_to_environ(envlist, NULL);
898
    envlist_free(envlist);
899

900
    /*
901
     * Read in mmap_min_addr kernel parameter.  This value is used
902
     * When loading the ELF image to determine whether guest_base
903
     * is needed.  It is also used in mmap_find_vma.
904
     */
905
    {
906
        FILE *fp;
907

908
        if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
909
            unsigned long tmp;
910
            if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) {
911
                mmap_min_addr = MAX(tmp, host_page_size);
912
                qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
913
                              mmap_min_addr);
914
            }
915
            fclose(fp);
916
        }
917
    }
918

919
    /*
920
     * We prefer to not make NULL pointers accessible to QEMU.
921
     * If we're in a chroot with no /proc, fall back to 1 page.
922
     */
923
    if (mmap_min_addr == 0) {
924
        mmap_min_addr = host_page_size;
925
        qemu_log_mask(CPU_LOG_PAGE,
926
                      "host mmap_min_addr=0x%lx (fallback)\n",
927
                      mmap_min_addr);
928
    }
929

930
    /*
931
     * Prepare copy of argv vector for target.
932
     */
933
    target_argc = argc - optind;
934
    target_argv = g_new0(char *, target_argc + 1);
935

936
    /*
937
     * If argv0 is specified (using '-0' switch) we replace
938
     * argv[0] pointer with the given one.
939
     */
940
    i = 0;
941
    if (argv0 != NULL) {
942
        target_argv[i++] = strdup(argv0);
943
    }
944
    for (; i < target_argc; i++) {
945
        target_argv[i] = strdup(argv[optind + i]);
946
    }
947
    target_argv[target_argc] = NULL;
948

949
    ts = g_new0(TaskState, 1);
950
    init_task_state(ts);
951
    /* build Task State */
952
    ts->info = info;
953
    ts->bprm = &bprm;
954
    cpu->opaque = ts;
955
    task_settid(ts);
956

957
    fd_trans_init();
958

959
    ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
960
        info, &bprm);
961
    if (ret != 0) {
962
        printf("Error while loading %s: %s\n", exec_path, strerror(-ret));
963
        _exit(EXIT_FAILURE);
964
    }
965

966
    for (wrk = target_environ; *wrk; wrk++) {
967
        g_free(*wrk);
968
    }
969

970
    g_free(target_environ);
971

972
    if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
973
        FILE *f = qemu_log_trylock();
974
        if (f) {
975
            fprintf(f, "guest_base  %p\n", (void *)guest_base);
976
            fprintf(f, "page layout changed following binary load\n");
977
            page_dump(f);
978

979
            fprintf(f, "end_code    0x" TARGET_ABI_FMT_lx "\n",
980
                    info->end_code);
981
            fprintf(f, "start_code  0x" TARGET_ABI_FMT_lx "\n",
982
                    info->start_code);
983
            fprintf(f, "start_data  0x" TARGET_ABI_FMT_lx "\n",
984
                    info->start_data);
985
            fprintf(f, "end_data    0x" TARGET_ABI_FMT_lx "\n",
986
                    info->end_data);
987
            fprintf(f, "start_stack 0x" TARGET_ABI_FMT_lx "\n",
988
                    info->start_stack);
989
            fprintf(f, "brk         0x" TARGET_ABI_FMT_lx "\n",
990
                    info->brk);
991
            fprintf(f, "entry       0x" TARGET_ABI_FMT_lx "\n",
992
                    info->entry);
993
            fprintf(f, "argv_start  0x" TARGET_ABI_FMT_lx "\n",
994
                    info->argv);
995
            fprintf(f, "env_start   0x" TARGET_ABI_FMT_lx "\n",
996
                    info->envp);
997
            fprintf(f, "auxv_start  0x" TARGET_ABI_FMT_lx "\n",
998
                    info->saved_auxv);
999
            qemu_log_unlock(f);
1000
        }
1001
    }
1002

1003
    target_set_brk(info->brk);
1004
    syscall_init();
1005
    signal_init();
1006

1007
    /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
1008
       generating the prologue until now so that the prologue can take
1009
       the real value of GUEST_BASE into account.  */
1010
    tcg_prologue_init();
1011

1012
    target_cpu_copy_regs(env, regs);
1013

1014
    if (gdbstub) {
1015
        if (gdbserver_start(gdbstub) < 0) {
1016
            fprintf(stderr, "qemu: could not open gdbserver on %s\n",
1017
                    gdbstub);
1018
            exit(EXIT_FAILURE);
1019
        }
1020
        gdb_handlesig(cpu, 0, NULL, NULL, 0);
1021
    }
1022

1023
#ifdef CONFIG_SEMIHOSTING
1024
    qemu_semihosting_guestfd_init();
1025
#endif
1026

1027
    cpu_loop(env);
1028
    /* never exits */
1029
    return 0;
1030
}
1031

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

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

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

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