diff options
Diffstat (limited to 'common/elf.c')
-rw-r--r-- | common/elf.c | 37 |
1 files changed, 20 insertions, 17 deletions
diff --git a/common/elf.c b/common/elf.c index f10fb77953..62f793010f 100644 --- a/common/elf.c +++ b/common/elf.c @@ -10,6 +10,7 @@ #include <libfile.h> #include <memory.h> #include <unistd.h> +#include <zero_page.h> #include <linux/fs.h> #include <linux/list_sort.h> @@ -59,14 +60,13 @@ static int request_elf_segment(struct elf_image *elf, void *phdr) { void *dst = (void *) (phys_addr_t) elf_phdr_p_paddr(elf, phdr); int ret; - u64 p_filesz = elf_phdr_p_filesz(elf, phdr); u64 p_memsz = elf_phdr_p_memsz(elf, phdr); /* we care only about PT_LOAD segments */ if (elf_phdr_p_type(elf, phdr) != PT_LOAD) return 0; - if (!p_filesz) + if (!p_memsz) return 0; if (dst < elf->low_addr) @@ -74,9 +74,9 @@ static int request_elf_segment(struct elf_image *elf, void *phdr) if (dst + p_memsz > elf->high_addr) elf->high_addr = dst + p_memsz; - pr_debug("Requesting segment 0x%p (%llu bytes)\n", dst, p_filesz); + pr_debug("Requesting segment 0x%p (%llu bytes)\n", dst, p_memsz); - ret = elf_request_region(elf, (resource_size_t)dst, p_filesz, phdr); + ret = elf_request_region(elf, (resource_size_t)dst, p_memsz, phdr); if (ret) return ret; @@ -101,7 +101,7 @@ static int elf_section_cmp(void *priv, struct list_head *a, struct list_head *b) static int load_elf_to_memory(struct elf_image *elf) { void *dst; - int ret, fd = -1; + int ret = 0, fd = -1; u64 p_filesz, p_memsz, p_offset; struct elf_section *r; struct list_head *list = &elf->list; @@ -109,11 +109,13 @@ static int load_elf_to_memory(struct elf_image *elf) if (elf->filename) { fd = open(elf->filename, O_RDONLY); if (fd < 0) { - pr_err("could not open: %s\n", errno_str()); + pr_err("could not open: %m\n"); return -errno; } } + zero_page_access(); + list_for_each_entry(r, list, list) { p_offset = elf_phdr_p_offset(elf, r->phdr); p_filesz = elf_phdr_p_filesz(elf, r->phdr); @@ -128,15 +130,13 @@ static int load_elf_to_memory(struct elf_image *elf) if (ret == -1) { pr_err("lseek at offset 0x%llx failed\n", p_offset); - close(fd); - return ret; + goto out; } if (read_full(fd, dst, p_filesz) < 0) { - pr_err("could not read elf segment: %s\n", - errno_str()); - close(fd); - return -errno; + pr_err("could not read elf segment: %m\n"); + ret = -errno; + goto out; } } else { memcpy(dst, elf->hdr_buf + p_offset, p_filesz); @@ -146,9 +146,12 @@ static int load_elf_to_memory(struct elf_image *elf) memset(dst + p_filesz, 0x00, p_memsz - p_filesz); } +out: + zero_page_faulting(); + close(fd); - return 0; + return ret >= 0 ? 0 : ret; } static int load_elf_image_segments(struct elf_image *elf) @@ -256,13 +259,13 @@ static struct elf_image *elf_check_init(const char *filename) /* First pass is to read elf header only */ fd = open(filename, O_RDONLY); if (fd < 0) { - pr_err("could not open: %s\n", errno_str()); + pr_err("could not open: %m\n"); ret = -errno; goto err_free_elf; } if (read_full(fd, &hdr, sizeof(hdr)) < 0) { - pr_err("could not read elf header: %s\n", errno_str()); + pr_err("could not read elf header: %m\n"); close(fd); ret = -errno; goto err_free_elf; @@ -290,13 +293,13 @@ static struct elf_image *elf_check_init(const char *filename) */ fd = open(filename, O_RDONLY); if (fd < 0) { - pr_err("could not open: %s\n", errno_str()); + pr_err("could not open: %m\n"); ret = -errno; goto err_free_hdr_buf; } if (read_full(fd, elf->hdr_buf, hdr_size) < 0) { - pr_err("could not read elf program headers: %s\n", errno_str()); + pr_err("could not read elf program headers: %m\n"); ret = -errno; close(fd); goto err_free_hdr_buf; |