diff --git a/linux-user/main.c b/linux-user/main.c index 8f6475bb99..42e61b3354 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -4781,6 +4781,10 @@ static int parse_args(int argc, char **argv) return optind; } +// args to pass to child instances of QEMU when spawning a child process +int qemu_argc; +char **qemu_argv; + int main(int argc, char **argv, char **envp) { struct target_pt_regs regs1, *regs = ®s1; @@ -5407,6 +5411,10 @@ int main(int argc, char **argv, char **envp) } gdb_handlesig(cpu, 0); } + + qemu_argc = optind; + qemu_argv = argv; + cpu_loop(env); /* never exits */ return 0; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 029bf0f188..0da52c0d94 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -467,6 +467,8 @@ void mmap_fork_end(int child); /* main.c */ extern unsigned long guest_stack_size; +extern int qemu_argc; +extern char **qemu_argv; /* user access */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ce1bf99aec..03869eba0e 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8290,6 +8290,38 @@ static int host_to_target_cpu_mask(const unsigned long *host_mask, } #endif +// executes the specified program in a QEMU VM +static int qemu_execve(const char *filename, char **argv, char **envp) +{ + int target_argc = 0; + char **exec_argv; + int i; + const char *fname = path(filename); + + // count number of arguments the target program is passing + while (argv[target_argc] != NULL) + target_argc++; + + exec_argv = g_malloc((qemu_argc + target_argc + 1) * sizeof(*exec_argv)); + + // add qemu args + for (i = 0; i < qemu_argc; i++) + exec_argv[i] = qemu_argv[i]; + + // add target program args + exec_argv[qemu_argc + 0] = (char *)fname; + for (i = 1; i < target_argc; i++) + exec_argv[qemu_argc + i] = argv[i]; + + // end with a null pointer + exec_argv[qemu_argc + target_argc] = NULL; + + int ret = safe_execve(exec_argv[0], exec_argv, envp); + + g_free(exec_argv); + return ret; +} + /* do_syscall() should always have a single exit point at the end so that actions, such as logging of syscall results, can be performed. All errnos that do_syscall() returns must be -TARGET_. */ @@ -8624,7 +8656,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, * before the execve completes and makes it the other * program's problem. */ - ret = get_errno(safe_execve(path(p), argp, envp)); + ret = get_errno(qemu_execve(p, argp, envp)); unlock_user(p, arg1, 0); goto execve_end;