aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2017-08-29 17:33:34 +0100
committerWill Deacon <will.deacon@arm.com>2017-08-30 09:47:05 +0100
commit93dd1288081497146b3a7ad98e40c5b2635c3148 (patch)
treef0744452c3ec5e8606122ad65620b4ff1a4ff5b5
parent23a9388e9f20d81a3752b78f698f542cb6338a10 (diff)
downloadkvmtool-93dd1288081497146b3a7ad98e40c5b2635c3148.tar.gz
Makefile: avoid using linker for embedding guest_init binaries
At the moment we use the linker to convert the compiled guest_init binary into an ELF object file, so it can be embedded into the kvmtool binary and accessed later easily at runtime. Now this has two problems: 1) This approach does not work for MIPS, because the linker defaults to a different ABI than the compiler, so the GCC generated object files are not compatible with this converted binary. 2) The size symbol as it's used at the moment in the object file is subject to relocation, which leads to wrong results when using PIE builds, which is now the default for some distributions. Fix those two problems at once by using some shell tools to create a C source file containing the guest_init binary, which then gets compiled into a proper object file with the normal compiler and its flags. The size of the guest init binaries is now simply a variable, which does not get mangled at all. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--Makefile9
-rw-r--r--builtin-setup.c18
-rw-r--r--config/utilities.mak8
3 files changed, 21 insertions, 14 deletions
diff --git a/Makefile b/Makefile
index 8b6326b7..a2901b92 100644
--- a/Makefile
+++ b/Makefile
@@ -392,18 +392,18 @@ $(GUEST_PRE_INIT): $(ARCH_PRE_INIT)
$(E) " COMPILE " $@
$(Q) $(CC) -s $(PIE_FLAGS) -nostdlib $< -o $@
-guest/guest_pre_init.o: $(GUEST_PRE_INIT)
+guest/guest_pre_init.c: $(GUEST_PRE_INIT)
$(E) " CONVERT " $@
- $(Q) $(LD) -r -b binary -o $@ $<
+ $(Q) $(call binary-to-C,$<,pre_init_binary,$@)
endif
$(GUEST_INIT): guest/init.c
$(E) " COMPILE " $@
$(Q) $(CC) $(GUEST_INIT_FLAGS) $< -o $@
-guest/guest_init.o: $(GUEST_INIT)
+guest/guest_init.c: $(GUEST_INIT)
$(E) " CONVERT " $@
- $(Q) $(LD) -r -b binary -o $@ $<
+ $(Q) $(call binary-to-C,$<,init_binary,$@)
%.s: %.c
$(Q) $(CC) -o $@ -S $(CFLAGS) -fverbose-asm $<
@@ -494,6 +494,7 @@ clean:
$(Q) rm -f tests/boot/boot_test.iso
$(Q) rm -rf tests/boot/rootfs/
$(Q) rm -f $(DEPS) $(STATIC_DEPS) $(OBJS) $(OTHEROBJS) $(OBJS_DYNOPT) $(STATIC_OBJS) $(PROGRAM) $(PROGRAM_ALIAS) $(PROGRAM)-static $(GUEST_INIT) $(GUEST_PRE_INIT) $(GUEST_OBJS)
+ $(Q) rm -f guest/guest_init.c guest/guest_pre_init.c
$(Q) rm -f cscope.*
$(Q) rm -f tags
$(Q) rm -f TAGS
diff --git a/builtin-setup.c b/builtin-setup.c
index 8be8d628..b24d2a18 100644
--- a/builtin-setup.c
+++ b/builtin-setup.c
@@ -123,7 +123,7 @@ static const char *guestfs_symlinks[] = {
#ifdef CONFIG_GUEST_INIT
static int extract_file(const char *guestfs_name, const char *filename,
- const void *data, const void *_size)
+ const void *data, size_t size)
{
char path[PATH_MAX];
int fd, ret;
@@ -138,7 +138,7 @@ static int extract_file(const char *guestfs_name, const char *filename,
die("Fail to setup %s", path);
}
- ret = xwrite(fd, data, (size_t)_size);
+ ret = xwrite(fd, data, size);
if (ret < 0)
die("Fail to setup %s", path);
close(fd);
@@ -146,10 +146,10 @@ static int extract_file(const char *guestfs_name, const char *filename,
return 0;
}
-extern char _binary_guest_init_start;
-extern char _binary_guest_init_size;
-extern char _binary_guest_pre_init_start;
-extern char _binary_guest_pre_init_size;
+extern unsigned char init_binary[];
+extern unsigned long init_binary_size;
+extern unsigned char pre_init_binary[];
+extern unsigned long pre_init_binary_size;
int kvm_setup_guest_init(const char *guestfs_name)
{
@@ -157,14 +157,12 @@ int kvm_setup_guest_init(const char *guestfs_name)
#ifdef CONFIG_GUEST_PRE_INIT
err = extract_file(guestfs_name, "virt/pre_init",
- &_binary_guest_pre_init_start,
- &_binary_guest_pre_init_size);
+ pre_init_binary, pre_init_binary_size);
if (err)
return err;
#endif
err = extract_file(guestfs_name, "virt/init",
- &_binary_guest_init_start,
- &_binary_guest_init_size);
+ init_binary, init_binary_size);
return err;
}
#else
diff --git a/config/utilities.mak b/config/utilities.mak
index 92af49bf..612ed1fc 100644
--- a/config/utilities.mak
+++ b/config/utilities.mak
@@ -194,3 +194,11 @@ try-build = $(shell sh -c \
echo "$(1)" | \
$(CC) -x c - $(2) $(3) -o "$$TMP" > /dev/null 2>&1 && echo y; \
rm -f "$$TMP"')
+
+# binary-to-C
+# create a C source file describing the binary input file as an array
+# Usage: $(call binary-to-C,binary-file,C-symbol-name,C-output-file)
+binary-to-C = stat -c "unsigned long $(2)_size = %s;" $1 > $3; \
+ echo "unsigned char $(2)[] = {" >> $3; \
+ od -v -tx1 -An -w12 $1 | sed -e "s/ \(..\)/0x\1, /g" >> $3; \
+ echo "};" >> $3