diff options
author | Alexander Graf <agraf@suse.de> | 2011-09-30 19:40:36 +0200 |
---|---|---|
committer | Yury Usishchev <y.usishchev@samsung.com> | 2014-12-10 13:47:57 +0300 |
commit | 055d4830aa573fe144829ac73b9c956be9b5feb7 (patch) | |
tree | d8270397c3405d095ce5b9abd7b4768e91e03f27 /linux-user/binfmt.c | |
parent | e42dffc94cb2b1d9d53753f45e12bea1d191ed97 (diff) | |
download | qemu-055d4830aa573fe144829ac73b9c956be9b5feb7.tar.gz qemu-055d4830aa573fe144829ac73b9c956be9b5feb7.tar.bz2 qemu-055d4830aa573fe144829ac73b9c956be9b5feb7.zip |
linux-user: add binfmt wrapper for argv[0] handling
When using qemu's linux-user binaries through binfmt, argv[0] gets lost
along the execution because qemu only gets passed in the full file name
to the executable while argv[0] can be something completely different.
This breaks in some subtile situations, such as the grep and make test
suites.
This patch adds a wrapper binary called qemu-$TARGET-binfmt that can be
used with binfmt's P flag which passes the full path _and_ argv[0] to
the binfmt handler.
The binary would be smart enough to be versatile and only exist in the
system once, creating the qemu binary path names from its own argv[0].
However, this seemed like it didn't fit the make system too well, so
we're currently creating a new binary for each target archictecture.
CC: Reinhard Max <max@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
[AF: Rebased onto new Makefile infrastructure, twice]
[AF: Updated for aarch64 for v2.0.0-rc1]
[AF: Rebased onto Makefile changes for v2.1.0-rc0]
Signed-off-by: Andreas Färber <afaerber@suse.de>
Diffstat (limited to 'linux-user/binfmt.c')
-rw-r--r-- | linux-user/binfmt.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/linux-user/binfmt.c b/linux-user/binfmt.c new file mode 100644 index 000000000..cd1f513b3 --- /dev/null +++ b/linux-user/binfmt.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include <stdarg.h> +#include <unistd.h> +#include <libgen.h> +#include <string.h> +#include <stdlib.h> + + +int main(int argc, char **argv, char **envp) +{ + char *binfmt; + char **new_argv; + + /* + * Check if our file name ends with -binfmt + */ + binfmt = argv[0] + strlen(argv[0]) - strlen("-binfmt"); + if (strcmp(binfmt, "-binfmt")) { + fprintf(stderr, "%s: Invalid executable name\n", argv[0]); + exit(1); + } + if (argc < 3) { + fprintf(stderr, "%s: Please use me through binfmt with P flag\n", + argv[0]); + exit(1); + } + + binfmt[0] = '\0'; + /* Now argv[0] is the real qemu binary name */ + + new_argv = (char **)malloc((argc + 2) * sizeof(*new_argv)); + if (argc > 3) { + memcpy(&new_argv[4], &argv[3], (argc - 3) * sizeof(*new_argv)); + } + new_argv[0] = argv[0]; + new_argv[1] = (char *)"-0"; + new_argv[2] = argv[2]; + new_argv[3] = argv[1]; + new_argv[argc + 1] = NULL; + + return execve(new_argv[0], new_argv, envp); +} |