168 lines
12 KiB
Diff
168 lines
12 KiB
Diff
|
From 864b2c7da05bc29a94b3e792b100dd5189576942 Mon Sep 17 00:00:00 2001
|
||
|
From: Alexander Graf <agraf@suse.de>
|
||
|
Date: Fri, 30 Sep 2011 19:40:36 +0200
|
||
|
Subject: [PATCH] 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>
|
||
|
---
|
||
|
Makefile.target | 8 ++++++++
|
||
|
linux-user/binfmt.c | 42 ++++++++++++++++++++++++++++++++++++++++++
|
||
|
scripts/qemu-binfmt-conf.sh | 34 +++++++++++++++++-----------------
|
||
|
3 files changed, 67 insertions(+), 17 deletions(-)
|
||
|
create mode 100644 linux-user/binfmt.c
|
||
|
|
||
|
Index: qemu-0.14.1/Makefile.target
|
||
|
===================================================================
|
||
|
--- qemu-0.14.1.orig/Makefile.target
|
||
|
+++ qemu-0.14.1/Makefile.target
|
||
|
@@ -33,6 +33,10 @@ endif
|
||
|
PROGS=$(QEMU_PROG)
|
||
|
STPFILES=
|
||
|
|
||
|
+ifdef CONFIG_LINUX_USER
|
||
|
+PROGS+=$(QEMU_PROG)-binfmt
|
||
|
+endif
|
||
|
+
|
||
|
ifndef CONFIG_HAIKU
|
||
|
LIBS+=-lm
|
||
|
endif
|
||
|
@@ -131,6 +135,8 @@ obj-y += $(addprefix ../libuser/, $(user
|
||
|
obj-y += $(addprefix ../libdis-user/, $(libdis-y))
|
||
|
obj-y += $(libobj-y)
|
||
|
|
||
|
+obj-binfmt-y += binfmt.o
|
||
|
+
|
||
|
endif #CONFIG_LINUX_USER
|
||
|
|
||
|
#########################################################
|
||
|
@@ -346,6 +352,8 @@ obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml
|
||
|
$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
|
||
|
$(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y))
|
||
|
|
||
|
+$(QEMU_PROG)-binfmt: $(obj-binfmt-y)
|
||
|
+ $(call LINK,$^)
|
||
|
|
||
|
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
|
||
|
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
|
||
|
Index: qemu-0.14.1/linux-user/binfmt.c
|
||
|
===================================================================
|
||
|
--- /dev/null
|
||
|
+++ qemu-0.14.1/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);
|
||
|
+}
|
||
|
Index: qemu-0.14.1/scripts/qemu-binfmt-conf.sh
|
||
|
===================================================================
|
||
|
--- qemu-0.14.1.orig/scripts/qemu-binfmt-conf.sh
|
||
|
+++ qemu-0.14.1/scripts/qemu-binfmt-conf.sh
|
||
|
@@ -34,36 +34,36 @@ esac
|
||
|
|
||
|
# register the interpreter for each cpu except for the native one
|
||
|
if [ $cpu != "i386" ] ; then
|
||
|
- echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
|
||
|
- echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-i386-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
fi
|
||
|
if [ $cpu != "alpha" ] ; then
|
||
|
- echo ':alpha:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-alpha:' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':alpha:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-alpha-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
fi
|
||
|
if [ $cpu != "arm" ] ; then
|
||
|
- echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register
|
||
|
- echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-armeb:' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-armeb-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
fi
|
||
|
if [ $cpu != "sparc" ] ; then
|
||
|
- echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sparc-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
fi
|
||
|
if [ $cpu != "ppc" ] ; then
|
||
|
- echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-ppc-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
fi
|
||
|
if [ $cpu != "m68k" ] ; then
|
||
|
echo 'Please check cpu value and header information for m68k!'
|
||
|
- echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-m68k-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
fi
|
||
|
if [ $cpu != "mips" ] ; then
|
||
|
# FIXME: We could use the other endianness on a MIPS host.
|
||
|
- echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register
|
||
|
- echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register
|
||
|
- echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mipsn32:' > /proc/sys/fs/binfmt_misc/register
|
||
|
- echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsn32el:' > /proc/sys/fs/binfmt_misc/register
|
||
|
- echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register
|
||
|
- echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsel-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mipsn32-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsn32el-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips64-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mips64el-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
fi
|
||
|
if [ $cpu != "sh" ] ; then
|
||
|
- echo ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-sh4:' > /proc/sys/fs/binfmt_misc/register
|
||
|
- echo ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sh4eb:' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-sh4-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
+ echo ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-sh4eb-binfmt:P' > /proc/sys/fs/binfmt_misc/register
|
||
|
fi
|