aboutsummaryrefslogtreecommitdiffstats
path: root/xen
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-01-23 09:42:12 +0000
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-01-23 09:42:12 +0000
commit079ff2d32c3db5a45cdbc8fb05be279544bdc111 (patch)
tree8670aba405b6fd42651dcf6f17f42164945f2e62 /xen
parent7b8c36701d267971f189b435362bce8ff2266e79 (diff)
downloadxen-079ff2d32c3db5a45cdbc8fb05be279544bdc111.tar.gz
xen-079ff2d32c3db5a45cdbc8fb05be279544bdc111.tar.bz2
xen-079ff2d32c3db5a45cdbc8fb05be279544bdc111.zip
libelf-loader: introduce elf_load_image
Implement a new function, called elf_load_image, to perform the actually copy of the elf image and clearing the padding. The function is implemented as memcpy and memset when the library is built as part of the tools, but it is implemented as raw_copy_to_guest and raw_clear_guest when built as part of Xen, so that it can be safely called with an HVM style dom0. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com> Committed-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen')
-rw-r--r--xen/arch/x86/domain_build.c7
-rw-r--r--xen/common/libelf/libelf-loader.c30
-rw-r--r--xen/include/xen/libelf.h2
3 files changed, 34 insertions, 5 deletions
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index 1b3818fc7f..b3c5d4cc72 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -903,7 +903,12 @@ int __init construct_dom0(
/* Copy the OS image and free temporary buffer. */
elf.dest = (void*)vkern_start;
- elf_load_binary(&elf);
+ rc = elf_load_binary(&elf);
+ if ( rc < 0 )
+ {
+ printk("Failed to load the kernel binary\n");
+ return rc;
+ }
bootstrap_map(NULL);
if ( UNSET_ADDR != parms.virt_hypercall )
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
index 1ccf7d35a6..ab58b8b86a 100644
--- a/xen/common/libelf/libelf-loader.c
+++ b/xen/common/libelf/libelf-loader.c
@@ -107,11 +107,34 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback,
elf->log_caller_data = log_caller_data;
elf->verbose = verbose;
}
+
+static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
+{
+ memcpy(dst, src, filesz);
+ memset(dst + filesz, 0, memsz - filesz);
+ return 0;
+}
#else
+#include <asm/guest_access.h>
+
void elf_set_verbose(struct elf_binary *elf)
{
elf->verbose = 1;
}
+
+static int elf_load_image(void *dst, const void *src, uint64_t filesz, uint64_t memsz)
+{
+ int rc;
+ if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
+ return -1;
+ rc = raw_copy_to_guest(dst, src, filesz);
+ if ( rc != 0 )
+ return -1;
+ rc = raw_clear_guest(dst + filesz, memsz - filesz);
+ if ( rc != 0 )
+ return -1;
+ return 0;
+}
#endif
/* Calculate the required additional kernel space for the elf image */
@@ -237,7 +260,7 @@ void elf_parse_binary(struct elf_binary *elf)
__FUNCTION__, elf->pstart, elf->pend);
}
-void elf_load_binary(struct elf_binary *elf)
+int elf_load_binary(struct elf_binary *elf)
{
const elf_phdr *phdr;
uint64_t i, count, paddr, offset, filesz, memsz;
@@ -256,11 +279,12 @@ void elf_load_binary(struct elf_binary *elf)
dest = elf_get_ptr(elf, paddr);
elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n",
__func__, i, dest, dest + filesz);
- memcpy(dest, elf->image + offset, filesz);
- memset(dest + filesz, 0, memsz - filesz);
+ if ( elf_load_image(dest, elf->image + offset, filesz, memsz) != 0 )
+ return -1;
}
elf_load_bsdsyms(elf);
+ return 0;
}
void *elf_get_ptr(struct elf_binary *elf, unsigned long addr)
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
index 9de84eb267..d77bda6f5d 100644
--- a/xen/include/xen/libelf.h
+++ b/xen/include/xen/libelf.h
@@ -198,7 +198,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*,
#endif
void elf_parse_binary(struct elf_binary *elf);
-void elf_load_binary(struct elf_binary *elf);
+int elf_load_binary(struct elf_binary *elf);
void *elf_get_ptr(struct elf_binary *elf, unsigned long addr);
uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol);