xref: /qemu/linux-user/main.c (revision 0b8fa32f)
131e31b8aSbellard /*
293ac68bcSbellard  *  qemu user main
331e31b8aSbellard  *
468d0f70eSbellard  *  Copyright (c) 2003-2008 Fabrice Bellard
531e31b8aSbellard  *
631e31b8aSbellard  *  This program is free software; you can redistribute it and/or modify
731e31b8aSbellard  *  it under the terms of the GNU General Public License as published by
831e31b8aSbellard  *  the Free Software Foundation; either version 2 of the License, or
931e31b8aSbellard  *  (at your option) any later version.
1031e31b8aSbellard  *
1131e31b8aSbellard  *  This program is distributed in the hope that it will be useful,
1231e31b8aSbellard  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1331e31b8aSbellard  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1431e31b8aSbellard  *  GNU General Public License for more details.
1531e31b8aSbellard  *
1631e31b8aSbellard  *  You should have received a copy of the GNU General Public License
178167ee88SBlue Swirl  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
1831e31b8aSbellard  */
1914a48c1dSMarkus Armbruster 
20d39594e9SPeter Maydell #include "qemu/osdep.h"
21b52713c1SPhilippe Mathieu-Daudé #include "qemu/units.h"
2214a48c1dSMarkus Armbruster #include "sysemu/tcg.h"
2367a1de0dSFam Zheng #include "qemu-version.h"
24edf8e2afSMika Westerberg #include <sys/syscall.h>
25703e0e89SRichard Henderson #include <sys/resource.h>
2631e31b8aSbellard 
27daa76aa4SMarkus Armbruster #include "qapi/error.h"
283ef693a0Sbellard #include "qemu.h"
29f348b6d1SVeronia Bahaa #include "qemu/path.h"
306533dd6eSLluís Vilanova #include "qemu/config-file.h"
31f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
32f5852efaSChristophe Fergeau #include "qemu/error-report.h"
33f348b6d1SVeronia Bahaa #include "qemu/help_option.h"
34*0b8fa32fSMarkus Armbruster #include "qemu/module.h"
352b41f10eSBlue Swirl #include "cpu.h"
3663c91552SPaolo Bonzini #include "exec/exec-all.h"
379002ec79SRichard Henderson #include "tcg.h"
381de7afc9SPaolo Bonzini #include "qemu/timer.h"
391de7afc9SPaolo Bonzini #include "qemu/envlist.h"
405ebdd774SRichard Henderson #include "qemu/guest-random.h"
41d8fd2954SPaul Brook #include "elf.h"
426533dd6eSLluís Vilanova #include "trace/control.h"
43542ca434SLaurent Vivier #include "target_elf.h"
44cd71c089SLaurent Vivier #include "cpu_loop-common.h"
45a573e9baSRichard Henderson #include "crypto/init.h"
4604a6dfebSaurel32 
47d088d664Saurel32 char *exec_path;
48d088d664Saurel32 
491b530a6dSaurel32 int singlestep;
508cb76755SStefan Weil static const char *filename;
518cb76755SStefan Weil static const char *argv0;
528cb76755SStefan Weil static int gdbstub_port;
538cb76755SStefan Weil static envlist_t *envlist;
5451fb256aSAndreas Färber static const char *cpu_model;
552278b939SIgor Mammedov static const char *cpu_type;
565ebdd774SRichard Henderson static const char *seed_optarg;
57379f6698SPaul Brook unsigned long mmap_min_addr;
58379f6698SPaul Brook unsigned long guest_base;
59379f6698SPaul Brook int have_guest_base;
60120a9848SPaolo Bonzini 
61288e65b9SAlexander Graf /*
62288e65b9SAlexander Graf  * When running 32-on-64 we should make sure we can fit all of the possible
63288e65b9SAlexander Graf  * guest address space into a contiguous chunk of virtual host memory.
64288e65b9SAlexander Graf  *
65288e65b9SAlexander Graf  * This way we will never overlap with our own libraries or binaries or stack
66288e65b9SAlexander Graf  * or anything else that QEMU maps.
6718e80c55SRichard Henderson  *
6818e80c55SRichard Henderson  * Many cpus reserve the high bit (or more than one for some 64-bit cpus)
6918e80c55SRichard Henderson  * of the address for the kernel.  Some cpus rely on this and user space
7018e80c55SRichard Henderson  * uses the high bit(s) for pointer tagging and the like.  For them, we
7118e80c55SRichard Henderson  * must preserve the expected address space.
72288e65b9SAlexander Graf  */
7318e80c55SRichard Henderson #ifndef MAX_RESERVED_VA
7418e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
7518e80c55SRichard Henderson #  if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
7618e80c55SRichard Henderson       (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
7718e80c55SRichard Henderson /* There are a number of places where we assign reserved_va to a variable
7818e80c55SRichard Henderson    of type abi_ulong and expect it to fit.  Avoid the last page.  */
7918e80c55SRichard Henderson #   define MAX_RESERVED_VA  (0xfffffffful & TARGET_PAGE_MASK)
80314992b1SAlexander Graf #  else
8118e80c55SRichard Henderson #   define MAX_RESERVED_VA  (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
82314992b1SAlexander Graf #  endif
83288e65b9SAlexander Graf # else
8418e80c55SRichard Henderson #  define MAX_RESERVED_VA  0
8518e80c55SRichard Henderson # endif
8618e80c55SRichard Henderson #endif
8718e80c55SRichard Henderson 
8868a1c816SPaul Brook unsigned long reserved_va;
891b530a6dSaurel32 
90d03f9c32SMeador Inge static void usage(int exitcode);
91fc9c5412SJohannes Schauer 
927ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
93e586822aSRiku Voipio const char *qemu_uname_release;
94586314f2Sbellard 
959de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
969de5e440Sbellard    we allocate a bigger stack. Need a better solution, for example
979de5e440Sbellard    by remapping the process stack directly at the right place */
98703e0e89SRichard Henderson unsigned long guest_stack_size = 8 * 1024 * 1024UL;
9931e31b8aSbellard 
10031e31b8aSbellard void gemu_log(const char *fmt, ...)
10131e31b8aSbellard {
10231e31b8aSbellard     va_list ap;
10331e31b8aSbellard 
10431e31b8aSbellard     va_start(ap, fmt);
10531e31b8aSbellard     vfprintf(stderr, fmt, ap);
10631e31b8aSbellard     va_end(ap);
10731e31b8aSbellard }
10831e31b8aSbellard 
1098fcd3692Sblueswir1 #if defined(TARGET_I386)
11005390248SAndreas Färber int cpu_get_pic_interrupt(CPUX86State *env)
11192ccca6aSbellard {
11292ccca6aSbellard     return -1;
11392ccca6aSbellard }
1148fcd3692Sblueswir1 #endif
11592ccca6aSbellard 
116d5975363Spbrook /***********************************************************/
117d5975363Spbrook /* Helper routines for implementing atomic operations.  */
118d5975363Spbrook 
119d5975363Spbrook /* Make sure everything is in a consistent state for calling fork().  */
120d5975363Spbrook void fork_start(void)
121d5975363Spbrook {
12206065c45SPeter Maydell     start_exclusive();
123d032d1b4SRiku Voipio     mmap_fork_start();
124024949caSPeter Maydell     cpu_list_lock();
125d5975363Spbrook }
126d5975363Spbrook 
127d5975363Spbrook void fork_end(int child)
128d5975363Spbrook {
129d032d1b4SRiku Voipio     mmap_fork_end(child);
130d5975363Spbrook     if (child) {
131bdc44640SAndreas Färber         CPUState *cpu, *next_cpu;
132d5975363Spbrook         /* Child processes created by fork() only have a single thread.
133d5975363Spbrook            Discard information about the parent threads.  */
134bdc44640SAndreas Färber         CPU_FOREACH_SAFE(cpu, next_cpu) {
135bdc44640SAndreas Färber             if (cpu != thread_cpu) {
136068a5ea0SEmilio G. Cota                 QTAILQ_REMOVE_RCU(&cpus, cpu, node);
137bdc44640SAndreas Färber             }
138bdc44640SAndreas Färber         }
139267f685bSPaolo Bonzini         qemu_init_cpu_list();
140f7ec7f7bSPeter Crosthwaite         gdbserver_fork(thread_cpu);
14106065c45SPeter Maydell         /* qemu_init_cpu_list() takes care of reinitializing the
14206065c45SPeter Maydell          * exclusive state, so we don't need to end_exclusive() here.
14306065c45SPeter Maydell          */
144d5975363Spbrook     } else {
145267f685bSPaolo Bonzini         cpu_list_unlock();
14606065c45SPeter Maydell         end_exclusive();
147d5975363Spbrook     }
148d5975363Spbrook }
149d5975363Spbrook 
150b44316fbSPeter Maydell __thread CPUState *thread_cpu;
15159faf6d6Sbellard 
152178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu)
153178f9429SSergey Fedorov {
154178f9429SSergey Fedorov     return thread_cpu == cpu;
155178f9429SSergey Fedorov }
156178f9429SSergey Fedorov 
157178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu)
158178f9429SSergey Fedorov {
159178f9429SSergey Fedorov     cpu_exit(cpu);
160178f9429SSergey Fedorov }
161178f9429SSergey Fedorov 
162edf8e2afSMika Westerberg void task_settid(TaskState *ts)
163edf8e2afSMika Westerberg {
164edf8e2afSMika Westerberg     if (ts->ts_tid == 0) {
165edf8e2afSMika Westerberg         ts->ts_tid = (pid_t)syscall(SYS_gettid);
166edf8e2afSMika Westerberg     }
167edf8e2afSMika Westerberg }
168edf8e2afSMika Westerberg 
169edf8e2afSMika Westerberg void stop_all_tasks(void)
170edf8e2afSMika Westerberg {
171edf8e2afSMika Westerberg     /*
172edf8e2afSMika Westerberg      * We trust that when using NPTL, start_exclusive()
173edf8e2afSMika Westerberg      * handles thread stopping correctly.
174edf8e2afSMika Westerberg      */
175edf8e2afSMika Westerberg     start_exclusive();
176edf8e2afSMika Westerberg }
177edf8e2afSMika Westerberg 
178c3a92833Spbrook /* Assumes contents are already zeroed.  */
179624f7979Spbrook void init_task_state(TaskState *ts)
180624f7979Spbrook {
181624f7979Spbrook     ts->used = 1;
182624f7979Spbrook }
1839de5e440Sbellard 
18430ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env)
18530ba0ee5SAndreas Färber {
18629a0af61SRichard Henderson     CPUState *cpu = env_cpu(env);
1872278b939SIgor Mammedov     CPUState *new_cpu = cpu_create(cpu_type);
18861c7480fSLeon Alrae     CPUArchState *new_env = new_cpu->env_ptr;
18930ba0ee5SAndreas Färber     CPUBreakpoint *bp;
19030ba0ee5SAndreas Färber     CPUWatchpoint *wp;
19130ba0ee5SAndreas Färber 
19230ba0ee5SAndreas Färber     /* Reset non arch specific state */
19375a34036SAndreas Färber     cpu_reset(new_cpu);
19430ba0ee5SAndreas Färber 
19530ba0ee5SAndreas Färber     memcpy(new_env, env, sizeof(CPUArchState));
19630ba0ee5SAndreas Färber 
19730ba0ee5SAndreas Färber     /* Clone all break/watchpoints.
19830ba0ee5SAndreas Färber        Note: Once we support ptrace with hw-debug register access, make sure
19930ba0ee5SAndreas Färber        BP_CPU break/watchpoints are handled correctly on clone. */
2001d085f6cSThierry Bultel     QTAILQ_INIT(&new_cpu->breakpoints);
2011d085f6cSThierry Bultel     QTAILQ_INIT(&new_cpu->watchpoints);
202f0c3c505SAndreas Färber     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
203b3310ab3SAndreas Färber         cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL);
20430ba0ee5SAndreas Färber     }
205ff4700b0SAndreas Färber     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
20605068c0dSPeter Maydell         cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL);
20730ba0ee5SAndreas Färber     }
20830ba0ee5SAndreas Färber 
20930ba0ee5SAndreas Färber     return new_env;
21030ba0ee5SAndreas Färber }
21130ba0ee5SAndreas Färber 
212fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg)
213fc9c5412SJohannes Schauer {
2144d1275c2SRiku Voipio     usage(EXIT_SUCCESS);
215fc9c5412SJohannes Schauer }
216fc9c5412SJohannes Schauer 
217fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg)
218fc9c5412SJohannes Schauer {
219fc9c5412SJohannes Schauer     int mask;
220fc9c5412SJohannes Schauer 
2214fde1ebaSPeter Maydell     mask = qemu_str_to_log_mask(arg);
222fc9c5412SJohannes Schauer     if (!mask) {
22359a6fa6eSPeter Maydell         qemu_print_log_usage(stdout);
2244d1275c2SRiku Voipio         exit(EXIT_FAILURE);
225fc9c5412SJohannes Schauer     }
226f2937a33SPaolo Bonzini     qemu_log_needs_buffers();
22724537a01SPeter Maydell     qemu_set_log(mask);
228fc9c5412SJohannes Schauer }
229fc9c5412SJohannes Schauer 
2308423fa90SAlex Bennée static void handle_arg_dfilter(const char *arg)
2318423fa90SAlex Bennée {
2328423fa90SAlex Bennée     qemu_set_dfilter_ranges(arg, NULL);
2338423fa90SAlex Bennée }
2348423fa90SAlex Bennée 
23550171d42S陳韋任 static void handle_arg_log_filename(const char *arg)
23650171d42S陳韋任 {
237daa76aa4SMarkus Armbruster     qemu_set_log_filename(arg, &error_fatal);
23850171d42S陳韋任 }
23950171d42S陳韋任 
240fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg)
241fc9c5412SJohannes Schauer {
242fc9c5412SJohannes Schauer     char *r, *p, *token;
243fc9c5412SJohannes Schauer     r = p = strdup(arg);
244fc9c5412SJohannes Schauer     while ((token = strsep(&p, ",")) != NULL) {
245fc9c5412SJohannes Schauer         if (envlist_setenv(envlist, token) != 0) {
2464d1275c2SRiku Voipio             usage(EXIT_FAILURE);
247fc9c5412SJohannes Schauer         }
248fc9c5412SJohannes Schauer     }
249fc9c5412SJohannes Schauer     free(r);
250fc9c5412SJohannes Schauer }
251fc9c5412SJohannes Schauer 
252fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg)
253fc9c5412SJohannes Schauer {
254fc9c5412SJohannes Schauer     char *r, *p, *token;
255fc9c5412SJohannes Schauer     r = p = strdup(arg);
256fc9c5412SJohannes Schauer     while ((token = strsep(&p, ",")) != NULL) {
257fc9c5412SJohannes Schauer         if (envlist_unsetenv(envlist, token) != 0) {
2584d1275c2SRiku Voipio             usage(EXIT_FAILURE);
259fc9c5412SJohannes Schauer         }
260fc9c5412SJohannes Schauer     }
261fc9c5412SJohannes Schauer     free(r);
262fc9c5412SJohannes Schauer }
263fc9c5412SJohannes Schauer 
264fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg)
265fc9c5412SJohannes Schauer {
266fc9c5412SJohannes Schauer     argv0 = strdup(arg);
267fc9c5412SJohannes Schauer }
268fc9c5412SJohannes Schauer 
269fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg)
270fc9c5412SJohannes Schauer {
271fc9c5412SJohannes Schauer     char *p;
272fc9c5412SJohannes Schauer     guest_stack_size = strtoul(arg, &p, 0);
273fc9c5412SJohannes Schauer     if (guest_stack_size == 0) {
2744d1275c2SRiku Voipio         usage(EXIT_FAILURE);
275fc9c5412SJohannes Schauer     }
276fc9c5412SJohannes Schauer 
277fc9c5412SJohannes Schauer     if (*p == 'M') {
278b52713c1SPhilippe Mathieu-Daudé         guest_stack_size *= MiB;
279fc9c5412SJohannes Schauer     } else if (*p == 'k' || *p == 'K') {
280b52713c1SPhilippe Mathieu-Daudé         guest_stack_size *= KiB;
281fc9c5412SJohannes Schauer     }
282fc9c5412SJohannes Schauer }
283fc9c5412SJohannes Schauer 
284fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg)
285fc9c5412SJohannes Schauer {
286fc9c5412SJohannes Schauer     interp_prefix = strdup(arg);
287fc9c5412SJohannes Schauer }
288fc9c5412SJohannes Schauer 
289fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg)
290fc9c5412SJohannes Schauer {
291fc9c5412SJohannes Schauer     qemu_host_page_size = atoi(arg);
292fc9c5412SJohannes Schauer     if (qemu_host_page_size == 0 ||
293fc9c5412SJohannes Schauer         (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
294fc9c5412SJohannes Schauer         fprintf(stderr, "page size must be a power of two\n");
2954d1275c2SRiku Voipio         exit(EXIT_FAILURE);
296fc9c5412SJohannes Schauer     }
297fc9c5412SJohannes Schauer }
298fc9c5412SJohannes Schauer 
2995ebdd774SRichard Henderson static void handle_arg_seed(const char *arg)
300c5e4a5a9SMagnus Reftel {
3015ebdd774SRichard Henderson     seed_optarg = arg;
302c5e4a5a9SMagnus Reftel }
303c5e4a5a9SMagnus Reftel 
304fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg)
305fc9c5412SJohannes Schauer {
306fc9c5412SJohannes Schauer     gdbstub_port = atoi(arg);
307fc9c5412SJohannes Schauer }
308fc9c5412SJohannes Schauer 
309fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg)
310fc9c5412SJohannes Schauer {
311fc9c5412SJohannes Schauer     qemu_uname_release = strdup(arg);
312fc9c5412SJohannes Schauer }
313fc9c5412SJohannes Schauer 
314fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg)
315fc9c5412SJohannes Schauer {
316fc9c5412SJohannes Schauer     cpu_model = strdup(arg);
317c8057f95SPeter Maydell     if (cpu_model == NULL || is_help_option(cpu_model)) {
318fc9c5412SJohannes Schauer         /* XXX: implement xxx_cpu_list for targets that still miss it */
319e916cbf8SPeter Maydell #if defined(cpu_list)
3200442428aSMarkus Armbruster         cpu_list();
321fc9c5412SJohannes Schauer #endif
3224d1275c2SRiku Voipio         exit(EXIT_FAILURE);
323fc9c5412SJohannes Schauer     }
324fc9c5412SJohannes Schauer }
325fc9c5412SJohannes Schauer 
326fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg)
327fc9c5412SJohannes Schauer {
328fc9c5412SJohannes Schauer     guest_base = strtol(arg, NULL, 0);
329fc9c5412SJohannes Schauer     have_guest_base = 1;
330fc9c5412SJohannes Schauer }
331fc9c5412SJohannes Schauer 
332fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg)
333fc9c5412SJohannes Schauer {
334fc9c5412SJohannes Schauer     char *p;
335fc9c5412SJohannes Schauer     int shift = 0;
336fc9c5412SJohannes Schauer     reserved_va = strtoul(arg, &p, 0);
337fc9c5412SJohannes Schauer     switch (*p) {
338fc9c5412SJohannes Schauer     case 'k':
339fc9c5412SJohannes Schauer     case 'K':
340fc9c5412SJohannes Schauer         shift = 10;
341fc9c5412SJohannes Schauer         break;
342fc9c5412SJohannes Schauer     case 'M':
343fc9c5412SJohannes Schauer         shift = 20;
344fc9c5412SJohannes Schauer         break;
345fc9c5412SJohannes Schauer     case 'G':
346fc9c5412SJohannes Schauer         shift = 30;
347fc9c5412SJohannes Schauer         break;
348fc9c5412SJohannes Schauer     }
349fc9c5412SJohannes Schauer     if (shift) {
350fc9c5412SJohannes Schauer         unsigned long unshifted = reserved_va;
351fc9c5412SJohannes Schauer         p++;
352fc9c5412SJohannes Schauer         reserved_va <<= shift;
35318e80c55SRichard Henderson         if (reserved_va >> shift != unshifted
35418e80c55SRichard Henderson             || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) {
355fc9c5412SJohannes Schauer             fprintf(stderr, "Reserved virtual address too big\n");
3564d1275c2SRiku Voipio             exit(EXIT_FAILURE);
357fc9c5412SJohannes Schauer         }
358fc9c5412SJohannes Schauer     }
359fc9c5412SJohannes Schauer     if (*p) {
360fc9c5412SJohannes Schauer         fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
3614d1275c2SRiku Voipio         exit(EXIT_FAILURE);
362fc9c5412SJohannes Schauer     }
363fc9c5412SJohannes Schauer }
364fc9c5412SJohannes Schauer 
365fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg)
366fc9c5412SJohannes Schauer {
367fc9c5412SJohannes Schauer     singlestep = 1;
368fc9c5412SJohannes Schauer }
369fc9c5412SJohannes Schauer 
370fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg)
371fc9c5412SJohannes Schauer {
372fc9c5412SJohannes Schauer     do_strace = 1;
373fc9c5412SJohannes Schauer }
374fc9c5412SJohannes Schauer 
375fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg)
376fc9c5412SJohannes Schauer {
3777e563bfbSThomas Huth     printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
3780781dd6eSThomas Huth            "\n" QEMU_COPYRIGHT "\n");
3794d1275c2SRiku Voipio     exit(EXIT_SUCCESS);
380fc9c5412SJohannes Schauer }
381fc9c5412SJohannes Schauer 
3826533dd6eSLluís Vilanova static char *trace_file;
3836533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg)
3846533dd6eSLluís Vilanova {
3856533dd6eSLluís Vilanova     g_free(trace_file);
3866533dd6eSLluís Vilanova     trace_file = trace_opt_parse(arg);
3876533dd6eSLluís Vilanova }
3886533dd6eSLluís Vilanova 
389fc9c5412SJohannes Schauer struct qemu_argument {
390fc9c5412SJohannes Schauer     const char *argv;
391fc9c5412SJohannes Schauer     const char *env;
392fc9c5412SJohannes Schauer     bool has_arg;
393fc9c5412SJohannes Schauer     void (*handle_opt)(const char *arg);
394fc9c5412SJohannes Schauer     const char *example;
395fc9c5412SJohannes Schauer     const char *help;
396fc9c5412SJohannes Schauer };
397fc9c5412SJohannes Schauer 
39842644ceeSJim Meyering static const struct qemu_argument arg_table[] = {
399fc9c5412SJohannes Schauer     {"h",          "",                 false, handle_arg_help,
400fc9c5412SJohannes Schauer      "",           "print this help"},
401daaf8c8eSMeador Inge     {"help",       "",                 false, handle_arg_help,
402daaf8c8eSMeador Inge      "",           ""},
403fc9c5412SJohannes Schauer     {"g",          "QEMU_GDB",         true,  handle_arg_gdb,
404fc9c5412SJohannes Schauer      "port",       "wait gdb connection to 'port'"},
405fc9c5412SJohannes Schauer     {"L",          "QEMU_LD_PREFIX",   true,  handle_arg_ld_prefix,
406fc9c5412SJohannes Schauer      "path",       "set the elf interpreter prefix to 'path'"},
407fc9c5412SJohannes Schauer     {"s",          "QEMU_STACK_SIZE",  true,  handle_arg_stack_size,
408fc9c5412SJohannes Schauer      "size",       "set the stack size to 'size' bytes"},
409fc9c5412SJohannes Schauer     {"cpu",        "QEMU_CPU",         true,  handle_arg_cpu,
410c8057f95SPeter Maydell      "model",      "select CPU (-cpu help for list)"},
411fc9c5412SJohannes Schauer     {"E",          "QEMU_SET_ENV",     true,  handle_arg_set_env,
412fc9c5412SJohannes Schauer      "var=value",  "sets targets environment variable (see below)"},
413fc9c5412SJohannes Schauer     {"U",          "QEMU_UNSET_ENV",   true,  handle_arg_unset_env,
414fc9c5412SJohannes Schauer      "var",        "unsets targets environment variable (see below)"},
415fc9c5412SJohannes Schauer     {"0",          "QEMU_ARGV0",       true,  handle_arg_argv0,
416fc9c5412SJohannes Schauer      "argv0",      "forces target process argv[0] to be 'argv0'"},
417fc9c5412SJohannes Schauer     {"r",          "QEMU_UNAME",       true,  handle_arg_uname,
418fc9c5412SJohannes Schauer      "uname",      "set qemu uname release string to 'uname'"},
419fc9c5412SJohannes Schauer     {"B",          "QEMU_GUEST_BASE",  true,  handle_arg_guest_base,
420fc9c5412SJohannes Schauer      "address",    "set guest_base address to 'address'"},
421fc9c5412SJohannes Schauer     {"R",          "QEMU_RESERVED_VA", true,  handle_arg_reserved_va,
422fc9c5412SJohannes Schauer      "size",       "reserve 'size' bytes for guest virtual address space"},
423fc9c5412SJohannes Schauer     {"d",          "QEMU_LOG",         true,  handle_arg_log,
424989b697dSPeter Maydell      "item[,...]", "enable logging of specified items "
425989b697dSPeter Maydell      "(use '-d help' for a list of items)"},
4268423fa90SAlex Bennée     {"dfilter",    "QEMU_DFILTER",     true,  handle_arg_dfilter,
4278423fa90SAlex Bennée      "range[,...]","filter logging based on address range"},
42850171d42S陳韋任     {"D",          "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
429989b697dSPeter Maydell      "logfile",     "write logs to 'logfile' (default stderr)"},
430fc9c5412SJohannes Schauer     {"p",          "QEMU_PAGESIZE",    true,  handle_arg_pagesize,
431fc9c5412SJohannes Schauer      "pagesize",   "set the host page size to 'pagesize'"},
432fc9c5412SJohannes Schauer     {"singlestep", "QEMU_SINGLESTEP",  false, handle_arg_singlestep,
433fc9c5412SJohannes Schauer      "",           "run in singlestep mode"},
434fc9c5412SJohannes Schauer     {"strace",     "QEMU_STRACE",      false, handle_arg_strace,
435fc9c5412SJohannes Schauer      "",           "log system calls"},
4365ebdd774SRichard Henderson     {"seed",       "QEMU_RAND_SEED",   true,  handle_arg_seed,
437c5e4a5a9SMagnus Reftel      "",           "Seed for pseudo-random number generator"},
4386533dd6eSLluís Vilanova     {"trace",      "QEMU_TRACE",       true,  handle_arg_trace,
4396533dd6eSLluís Vilanova      "",           "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
440fc9c5412SJohannes Schauer     {"version",    "QEMU_VERSION",     false, handle_arg_version,
4411386d4c0SPeter Maydell      "",           "display version information and exit"},
442fc9c5412SJohannes Schauer     {NULL, NULL, false, NULL, NULL, NULL}
443fc9c5412SJohannes Schauer };
444fc9c5412SJohannes Schauer 
445d03f9c32SMeador Inge static void usage(int exitcode)
446fc9c5412SJohannes Schauer {
44742644ceeSJim Meyering     const struct qemu_argument *arginfo;
448fc9c5412SJohannes Schauer     int maxarglen;
449fc9c5412SJohannes Schauer     int maxenvlen;
450fc9c5412SJohannes Schauer 
4512e59915dSPaolo Bonzini     printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
4522e59915dSPaolo Bonzini            "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
453fc9c5412SJohannes Schauer            "\n"
454fc9c5412SJohannes Schauer            "Options and associated environment variables:\n"
455fc9c5412SJohannes Schauer            "\n");
456fc9c5412SJohannes Schauer 
45763ec54d7SPeter Maydell     /* Calculate column widths. We must always have at least enough space
45863ec54d7SPeter Maydell      * for the column header.
45963ec54d7SPeter Maydell      */
46063ec54d7SPeter Maydell     maxarglen = strlen("Argument");
46163ec54d7SPeter Maydell     maxenvlen = strlen("Env-variable");
462fc9c5412SJohannes Schauer 
463fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
46463ec54d7SPeter Maydell         int arglen = strlen(arginfo->argv);
46563ec54d7SPeter Maydell         if (arginfo->has_arg) {
46663ec54d7SPeter Maydell             arglen += strlen(arginfo->example) + 1;
46763ec54d7SPeter Maydell         }
468fc9c5412SJohannes Schauer         if (strlen(arginfo->env) > maxenvlen) {
469fc9c5412SJohannes Schauer             maxenvlen = strlen(arginfo->env);
470fc9c5412SJohannes Schauer         }
47163ec54d7SPeter Maydell         if (arglen > maxarglen) {
47263ec54d7SPeter Maydell             maxarglen = arglen;
473fc9c5412SJohannes Schauer         }
474fc9c5412SJohannes Schauer     }
475fc9c5412SJohannes Schauer 
47663ec54d7SPeter Maydell     printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
47763ec54d7SPeter Maydell             maxenvlen, "Env-variable");
478fc9c5412SJohannes Schauer 
479fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
480fc9c5412SJohannes Schauer         if (arginfo->has_arg) {
481fc9c5412SJohannes Schauer             printf("-%s %-*s %-*s %s\n", arginfo->argv,
48263ec54d7SPeter Maydell                    (int)(maxarglen - strlen(arginfo->argv) - 1),
48363ec54d7SPeter Maydell                    arginfo->example, maxenvlen, arginfo->env, arginfo->help);
484fc9c5412SJohannes Schauer         } else {
48563ec54d7SPeter Maydell             printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
486fc9c5412SJohannes Schauer                     maxenvlen, arginfo->env,
487fc9c5412SJohannes Schauer                     arginfo->help);
488fc9c5412SJohannes Schauer         }
489fc9c5412SJohannes Schauer     }
490fc9c5412SJohannes Schauer 
491fc9c5412SJohannes Schauer     printf("\n"
492fc9c5412SJohannes Schauer            "Defaults:\n"
493fc9c5412SJohannes Schauer            "QEMU_LD_PREFIX  = %s\n"
494989b697dSPeter Maydell            "QEMU_STACK_SIZE = %ld byte\n",
495fc9c5412SJohannes Schauer            interp_prefix,
496989b697dSPeter Maydell            guest_stack_size);
497fc9c5412SJohannes Schauer 
498fc9c5412SJohannes Schauer     printf("\n"
499fc9c5412SJohannes Schauer            "You can use -E and -U options or the QEMU_SET_ENV and\n"
500fc9c5412SJohannes Schauer            "QEMU_UNSET_ENV environment variables to set and unset\n"
501fc9c5412SJohannes Schauer            "environment variables for the target process.\n"
502fc9c5412SJohannes Schauer            "It is possible to provide several variables by separating them\n"
503fc9c5412SJohannes Schauer            "by commas in getsubopt(3) style. Additionally it is possible to\n"
504fc9c5412SJohannes Schauer            "provide the -E and -U options multiple times.\n"
505fc9c5412SJohannes Schauer            "The following lines are equivalent:\n"
506fc9c5412SJohannes Schauer            "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
507fc9c5412SJohannes Schauer            "    -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
508fc9c5412SJohannes Schauer            "    QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
509fc9c5412SJohannes Schauer            "Note that if you provide several changes to a single variable\n"
510f5048cb7SEric Blake            "the last change will stay in effect.\n"
511f5048cb7SEric Blake            "\n"
512f5048cb7SEric Blake            QEMU_HELP_BOTTOM "\n");
513fc9c5412SJohannes Schauer 
514d03f9c32SMeador Inge     exit(exitcode);
515fc9c5412SJohannes Schauer }
516fc9c5412SJohannes Schauer 
517fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv)
518fc9c5412SJohannes Schauer {
519fc9c5412SJohannes Schauer     const char *r;
520fc9c5412SJohannes Schauer     int optind;
52142644ceeSJim Meyering     const struct qemu_argument *arginfo;
522fc9c5412SJohannes Schauer 
523fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
524fc9c5412SJohannes Schauer         if (arginfo->env == NULL) {
525fc9c5412SJohannes Schauer             continue;
526fc9c5412SJohannes Schauer         }
527fc9c5412SJohannes Schauer 
528fc9c5412SJohannes Schauer         r = getenv(arginfo->env);
529fc9c5412SJohannes Schauer         if (r != NULL) {
530fc9c5412SJohannes Schauer             arginfo->handle_opt(r);
531fc9c5412SJohannes Schauer         }
532fc9c5412SJohannes Schauer     }
533fc9c5412SJohannes Schauer 
534fc9c5412SJohannes Schauer     optind = 1;
535fc9c5412SJohannes Schauer     for (;;) {
536fc9c5412SJohannes Schauer         if (optind >= argc) {
537fc9c5412SJohannes Schauer             break;
538fc9c5412SJohannes Schauer         }
539fc9c5412SJohannes Schauer         r = argv[optind];
540fc9c5412SJohannes Schauer         if (r[0] != '-') {
541fc9c5412SJohannes Schauer             break;
542fc9c5412SJohannes Schauer         }
543fc9c5412SJohannes Schauer         optind++;
544fc9c5412SJohannes Schauer         r++;
545fc9c5412SJohannes Schauer         if (!strcmp(r, "-")) {
546fc9c5412SJohannes Schauer             break;
547fc9c5412SJohannes Schauer         }
548ba02577cSMeador Inge         /* Treat --foo the same as -foo.  */
549ba02577cSMeador Inge         if (r[0] == '-') {
550ba02577cSMeador Inge             r++;
551ba02577cSMeador Inge         }
552fc9c5412SJohannes Schauer 
553fc9c5412SJohannes Schauer         for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
554fc9c5412SJohannes Schauer             if (!strcmp(r, arginfo->argv)) {
5551386d4c0SPeter Maydell                 if (arginfo->has_arg) {
556fc9c5412SJohannes Schauer                     if (optind >= argc) {
557138940bfSMeador Inge                         (void) fprintf(stderr,
558138940bfSMeador Inge                             "qemu: missing argument for option '%s'\n", r);
5594d1275c2SRiku Voipio                         exit(EXIT_FAILURE);
560fc9c5412SJohannes Schauer                     }
561fc9c5412SJohannes Schauer                     arginfo->handle_opt(argv[optind]);
562fc9c5412SJohannes Schauer                     optind++;
5631386d4c0SPeter Maydell                 } else {
5641386d4c0SPeter Maydell                     arginfo->handle_opt(NULL);
565fc9c5412SJohannes Schauer                 }
566fc9c5412SJohannes Schauer                 break;
567fc9c5412SJohannes Schauer             }
568fc9c5412SJohannes Schauer         }
569fc9c5412SJohannes Schauer 
570fc9c5412SJohannes Schauer         /* no option matched the current argv */
571fc9c5412SJohannes Schauer         if (arginfo->handle_opt == NULL) {
572138940bfSMeador Inge             (void) fprintf(stderr, "qemu: unknown option '%s'\n", r);
5734d1275c2SRiku Voipio             exit(EXIT_FAILURE);
574fc9c5412SJohannes Schauer         }
575fc9c5412SJohannes Schauer     }
576fc9c5412SJohannes Schauer 
577fc9c5412SJohannes Schauer     if (optind >= argc) {
578138940bfSMeador Inge         (void) fprintf(stderr, "qemu: no user program specified\n");
5794d1275c2SRiku Voipio         exit(EXIT_FAILURE);
580fc9c5412SJohannes Schauer     }
581fc9c5412SJohannes Schauer 
582fc9c5412SJohannes Schauer     filename = argv[optind];
583fc9c5412SJohannes Schauer     exec_path = argv[optind];
584fc9c5412SJohannes Schauer 
585fc9c5412SJohannes Schauer     return optind;
586fc9c5412SJohannes Schauer }
587fc9c5412SJohannes Schauer 
588902b3d5cSmalc int main(int argc, char **argv, char **envp)
58931e31b8aSbellard {
59001ffc75bSbellard     struct target_pt_regs regs1, *regs = &regs1;
59131e31b8aSbellard     struct image_info info1, *info = &info1;
592edf8e2afSMika Westerberg     struct linux_binprm bprm;
59348e15fc2SNathan Froyd     TaskState *ts;
5949349b4f9SAndreas Färber     CPUArchState *env;
595db6b81d4SAndreas Färber     CPUState *cpu;
596586314f2Sbellard     int optind;
59704a6dfebSaurel32     char **target_environ, **wrk;
5987d8cec95Saurel32     char **target_argv;
5997d8cec95Saurel32     int target_argc;
6007d8cec95Saurel32     int i;
601fd4d81ddSArnaud Patard     int ret;
60203cfd8faSLaurent Vivier     int execfd;
60331e31b8aSbellard 
604f5852efaSChristophe Fergeau     error_init(argv[0]);
605fe4db84dSDaniel P. Berrange     module_call_init(MODULE_INIT_TRACE);
606267f685bSPaolo Bonzini     qemu_init_cpu_list();
607ce008c1fSAndreas Färber     module_call_init(MODULE_INIT_QOM);
608ce008c1fSAndreas Färber 
609ec45bbe5SSaurav Sachidanand     envlist = envlist_create();
61004a6dfebSaurel32 
61104a6dfebSaurel32     /* add current environment into the list */
61204a6dfebSaurel32     for (wrk = environ; *wrk != NULL; wrk++) {
61304a6dfebSaurel32         (void) envlist_setenv(envlist, *wrk);
61404a6dfebSaurel32     }
61504a6dfebSaurel32 
616703e0e89SRichard Henderson     /* Read the stack limit from the kernel.  If it's "unlimited",
617703e0e89SRichard Henderson        then we can do little else besides use the default.  */
618703e0e89SRichard Henderson     {
619703e0e89SRichard Henderson         struct rlimit lim;
620703e0e89SRichard Henderson         if (getrlimit(RLIMIT_STACK, &lim) == 0
62181bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur != RLIM_INFINITY
62281bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur == (target_long)lim.rlim_cur) {
623703e0e89SRichard Henderson             guest_stack_size = lim.rlim_cur;
624703e0e89SRichard Henderson         }
625703e0e89SRichard Henderson     }
626703e0e89SRichard Henderson 
627b1f9be31Sj_mayer     cpu_model = NULL;
628b5ec5ce0Sjohn cooper 
6296533dd6eSLluís Vilanova     qemu_add_opts(&qemu_trace_opts);
6306533dd6eSLluís Vilanova 
631fc9c5412SJohannes Schauer     optind = parse_args(argc, argv);
6324b5dfd82SPeter Maydell 
6336533dd6eSLluís Vilanova     if (!trace_init_backends()) {
6346533dd6eSLluís Vilanova         exit(1);
6356533dd6eSLluís Vilanova     }
6366533dd6eSLluís Vilanova     trace_init_file(trace_file);
6376533dd6eSLluís Vilanova 
63831e31b8aSbellard     /* Zero out regs */
63901ffc75bSbellard     memset(regs, 0, sizeof(struct target_pt_regs));
64031e31b8aSbellard 
64131e31b8aSbellard     /* Zero out image_info */
64231e31b8aSbellard     memset(info, 0, sizeof(struct image_info));
64331e31b8aSbellard 
644edf8e2afSMika Westerberg     memset(&bprm, 0, sizeof (bprm));
645edf8e2afSMika Westerberg 
64674cd30b8Sbellard     /* Scan interp_prefix dir for replacement files. */
64774cd30b8Sbellard     init_paths(interp_prefix);
64874cd30b8Sbellard 
6494a24a758SPeter Maydell     init_qemu_uname_release();
6504a24a758SPeter Maydell 
651768fe76eSYunQiang Su     execfd = qemu_getauxval(AT_EXECFD);
652768fe76eSYunQiang Su     if (execfd == 0) {
653768fe76eSYunQiang Su         execfd = open(filename, O_RDONLY);
654768fe76eSYunQiang Su         if (execfd < 0) {
655768fe76eSYunQiang Su             printf("Error while loading %s: %s\n", filename, strerror(errno));
656768fe76eSYunQiang Su             _exit(EXIT_FAILURE);
657768fe76eSYunQiang Su         }
658768fe76eSYunQiang Su     }
659768fe76eSYunQiang Su 
66046027c07Sbellard     if (cpu_model == NULL) {
661768fe76eSYunQiang Su         cpu_model = cpu_get_model(get_elf_eflags(execfd));
662aaed909aSbellard     }
663c1c8cfe5SEduardo Habkost     cpu_type = parse_cpu_option(cpu_model);
6642278b939SIgor Mammedov 
6652b5249b8SIgor Mammedov     /* init tcg before creating CPUs and to get qemu_host_page_size */
666d5ab9713SJan Kiszka     tcg_exec_init(0);
6672278b939SIgor Mammedov 
668dc18baaeSLaurent Vivier     /* Reserving *too* much vm space via mmap can run into problems
669dc18baaeSLaurent Vivier        with rlimits, oom due to page table creation, etc.  We will still try it,
670dc18baaeSLaurent Vivier        if directed by the command-line option, but not by default.  */
671dc18baaeSLaurent Vivier     if (HOST_LONG_BITS == 64 &&
672dc18baaeSLaurent Vivier         TARGET_VIRT_ADDR_SPACE_BITS <= 32 &&
673dc18baaeSLaurent Vivier         reserved_va == 0) {
674dc18baaeSLaurent Vivier         /* reserved_va must be aligned with the host page size
675dc18baaeSLaurent Vivier          * as it is used with mmap()
676dc18baaeSLaurent Vivier          */
677dc18baaeSLaurent Vivier         reserved_va = MAX_RESERVED_VA & qemu_host_page_mask;
678dc18baaeSLaurent Vivier     }
679dc18baaeSLaurent Vivier 
6802278b939SIgor Mammedov     cpu = cpu_create(cpu_type);
6812994fd96SEduardo Habkost     env = cpu->env_ptr;
6820ac46af3SAndreas Färber     cpu_reset(cpu);
683b55a37c9SBlue Swirl 
684db6b81d4SAndreas Färber     thread_cpu = cpu;
68554936004Sbellard 
686b92c47c1Sths     if (getenv("QEMU_STRACE")) {
687b92c47c1Sths         do_strace = 1;
688b92c47c1Sths     }
689b92c47c1Sths 
6905ebdd774SRichard Henderson     if (seed_optarg == NULL) {
6915ebdd774SRichard Henderson         seed_optarg = getenv("QEMU_RAND_SEED");
6925ebdd774SRichard Henderson     }
693a573e9baSRichard Henderson     {
694a573e9baSRichard Henderson         Error *err = NULL;
6955ebdd774SRichard Henderson         if (seed_optarg != NULL) {
696a573e9baSRichard Henderson             qemu_guest_random_seed_main(seed_optarg, &err);
697a573e9baSRichard Henderson         } else {
698a573e9baSRichard Henderson             qcrypto_init(&err);
699a573e9baSRichard Henderson         }
700a573e9baSRichard Henderson         if (err) {
701a573e9baSRichard Henderson             error_reportf_err(err, "cannot initialize crypto: ");
702a573e9baSRichard Henderson             exit(1);
703a573e9baSRichard Henderson         }
704c5e4a5a9SMagnus Reftel     }
705c5e4a5a9SMagnus Reftel 
70604a6dfebSaurel32     target_environ = envlist_to_environ(envlist, NULL);
70704a6dfebSaurel32     envlist_free(envlist);
708b12b6a18Sths 
709379f6698SPaul Brook     /*
7102b5249b8SIgor Mammedov      * Now that page sizes are configured in tcg_exec_init() we can do
711379f6698SPaul Brook      * proper page alignment for guest_base.
712379f6698SPaul Brook      */
713379f6698SPaul Brook     guest_base = HOST_PAGE_ALIGN(guest_base);
71468a1c816SPaul Brook 
71597cc7560SDr. David Alan Gilbert     if (reserved_va || have_guest_base) {
716806d1021SMeador Inge         guest_base = init_guest_space(guest_base, reserved_va, 0,
717806d1021SMeador Inge                                       have_guest_base);
718806d1021SMeador Inge         if (guest_base == (unsigned long)-1) {
719097b8cb8SPeter Maydell             fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
720097b8cb8SPeter Maydell                     "space for use as guest address space (check your virtual "
721097b8cb8SPeter Maydell                     "memory ulimit setting or reserve less using -R option)\n",
722097b8cb8SPeter Maydell                     reserved_va);
7234d1275c2SRiku Voipio             exit(EXIT_FAILURE);
72497cc7560SDr. David Alan Gilbert         }
725806d1021SMeador Inge 
726806d1021SMeador Inge         if (reserved_va) {
727806d1021SMeador Inge             mmap_next_start = reserved_va;
728806d1021SMeador Inge         }
72997cc7560SDr. David Alan Gilbert     }
730379f6698SPaul Brook 
731379f6698SPaul Brook     /*
732379f6698SPaul Brook      * Read in mmap_min_addr kernel parameter.  This value is used
733379f6698SPaul Brook      * When loading the ELF image to determine whether guest_base
73414f24e14SRichard Henderson      * is needed.  It is also used in mmap_find_vma.
735379f6698SPaul Brook      */
73614f24e14SRichard Henderson     {
737379f6698SPaul Brook         FILE *fp;
738379f6698SPaul Brook 
739379f6698SPaul Brook         if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
740379f6698SPaul Brook             unsigned long tmp;
741379f6698SPaul Brook             if (fscanf(fp, "%lu", &tmp) == 1) {
742379f6698SPaul Brook                 mmap_min_addr = tmp;
74313829020SPaolo Bonzini                 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", mmap_min_addr);
744379f6698SPaul Brook             }
745379f6698SPaul Brook             fclose(fp);
746379f6698SPaul Brook         }
747379f6698SPaul Brook     }
748379f6698SPaul Brook 
7497d8cec95Saurel32     /*
7507d8cec95Saurel32      * Prepare copy of argv vector for target.
7517d8cec95Saurel32      */
7527d8cec95Saurel32     target_argc = argc - optind;
7537d8cec95Saurel32     target_argv = calloc(target_argc + 1, sizeof (char *));
7547d8cec95Saurel32     if (target_argv == NULL) {
7557d8cec95Saurel32         (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
7564d1275c2SRiku Voipio         exit(EXIT_FAILURE);
7577d8cec95Saurel32     }
7587d8cec95Saurel32 
7597d8cec95Saurel32     /*
7607d8cec95Saurel32      * If argv0 is specified (using '-0' switch) we replace
7617d8cec95Saurel32      * argv[0] pointer with the given one.
7627d8cec95Saurel32      */
7637d8cec95Saurel32     i = 0;
7647d8cec95Saurel32     if (argv0 != NULL) {
7657d8cec95Saurel32         target_argv[i++] = strdup(argv0);
7667d8cec95Saurel32     }
7677d8cec95Saurel32     for (; i < target_argc; i++) {
7687d8cec95Saurel32         target_argv[i] = strdup(argv[optind + i]);
7697d8cec95Saurel32     }
7707d8cec95Saurel32     target_argv[target_argc] = NULL;
7717d8cec95Saurel32 
772c78d65e8SMarkus Armbruster     ts = g_new0(TaskState, 1);
773edf8e2afSMika Westerberg     init_task_state(ts);
774edf8e2afSMika Westerberg     /* build Task State */
775edf8e2afSMika Westerberg     ts->info = info;
776edf8e2afSMika Westerberg     ts->bprm = &bprm;
7770429a971SAndreas Färber     cpu->opaque = ts;
778edf8e2afSMika Westerberg     task_settid(ts);
779edf8e2afSMika Westerberg 
78003cfd8faSLaurent Vivier     ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
781fd4d81ddSArnaud Patard         info, &bprm);
782fd4d81ddSArnaud Patard     if (ret != 0) {
783885c1d10SPeter Maydell         printf("Error while loading %s: %s\n", filename, strerror(-ret));
7844d1275c2SRiku Voipio         _exit(EXIT_FAILURE);
78531e31b8aSbellard     }
78631e31b8aSbellard 
787b12b6a18Sths     for (wrk = target_environ; *wrk; wrk++) {
788ec45bbe5SSaurav Sachidanand         g_free(*wrk);
789b12b6a18Sths     }
790b12b6a18Sths 
791ec45bbe5SSaurav Sachidanand     g_free(target_environ);
792b12b6a18Sths 
79313829020SPaolo Bonzini     if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
794379f6698SPaul Brook         qemu_log("guest_base  0x%lx\n", guest_base);
79593fcfe39Saliguori         log_page_dump();
79654936004Sbellard 
79793fcfe39Saliguori         qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
79893fcfe39Saliguori         qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code);
7997c4ee5bcSRichard Henderson         qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n", info->start_code);
8007c4ee5bcSRichard Henderson         qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n", info->start_data);
80193fcfe39Saliguori         qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data);
8027c4ee5bcSRichard Henderson         qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", info->start_stack);
80393fcfe39Saliguori         qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
80493fcfe39Saliguori         qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
8057c4ee5bcSRichard Henderson         qemu_log("argv_start  0x" TARGET_ABI_FMT_lx "\n", info->arg_start);
8067c4ee5bcSRichard Henderson         qemu_log("env_start   0x" TARGET_ABI_FMT_lx "\n",
8077c4ee5bcSRichard Henderson                  info->arg_end + (abi_ulong)sizeof(abi_ulong));
8087c4ee5bcSRichard Henderson         qemu_log("auxv_start  0x" TARGET_ABI_FMT_lx "\n", info->saved_auxv);
8092e77eac6Sblueswir1     }
81031e31b8aSbellard 
81153a5960aSpbrook     target_set_brk(info->brk);
81231e31b8aSbellard     syscall_init();
81366fb9763Sbellard     signal_init();
81431e31b8aSbellard 
8159002ec79SRichard Henderson     /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
8169002ec79SRichard Henderson        generating the prologue until now so that the prologue can take
8179002ec79SRichard Henderson        the real value of GUEST_BASE into account.  */
818b1311c4aSEmilio G. Cota     tcg_prologue_init(tcg_ctx);
819e8feb96fSEmilio G. Cota     tcg_region_init();
8209002ec79SRichard Henderson 
821cd71c089SLaurent Vivier     target_cpu_copy_regs(env, regs);
822cd71c089SLaurent Vivier 
82374c33bedSbellard     if (gdbstub_port) {
824ff7a981aSPeter Maydell         if (gdbserver_start(gdbstub_port) < 0) {
825ff7a981aSPeter Maydell             fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
826ff7a981aSPeter Maydell                     gdbstub_port);
8274d1275c2SRiku Voipio             exit(EXIT_FAILURE);
828ff7a981aSPeter Maydell         }
829db6b81d4SAndreas Färber         gdb_handlesig(cpu, 0);
8301fddef4bSbellard     }
8311b6b029eSbellard     cpu_loop(env);
8321b6b029eSbellard     /* never exits */
83331e31b8aSbellard     return 0;
83431e31b8aSbellard }
835