summaryrefslogtreecommitdiff
path: root/linux-user/binfmt.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2011-09-30 19:40:36 +0200
committerYury Usishchev <y.usishchev@samsung.com>2014-12-10 13:47:57 +0300
commit055d4830aa573fe144829ac73b9c956be9b5feb7 (patch)
treed8270397c3405d095ce5b9abd7b4768e91e03f27 /linux-user/binfmt.c
parente42dffc94cb2b1d9d53753f45e12bea1d191ed97 (diff)
downloadqemu-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.c42
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);
+}