From 9ee3c029425a20ed16831c92c4cb3e192a909a61 Mon Sep 17 00:00:00 2001 From: bellard Date: Wed, 26 Apr 2006 22:05:26 +0000 Subject: added entry parameter to ELF loader git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1859 c046a42c-6fe2-441c-8c8c-71466251a162 --- elf_ops.h | 13 ++++++++++--- hw/sun4m.c | 4 ++-- hw/sun4u.c | 4 ++-- loader.c | 7 ++++--- vl.h | 2 +- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/elf_ops.h b/elf_ops.h index a7d027e1ab..4da755e1b3 100644 --- a/elf_ops.h +++ b/elf_ops.h @@ -138,13 +138,14 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab) return -1; } -int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend, int must_swab) +int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend, + int must_swab, uint64_t *pentry) { struct elfhdr ehdr; struct elf_phdr *phdr = NULL, *ph; int size, i, total_size; elf_word mem_size, addr; - uint8_t *data; + uint8_t *data = NULL; if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) goto fail; @@ -152,6 +153,9 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend, int must_swab) glue(bswap_ehdr, SZ)(&ehdr); } + if (pentry) + *pentry = (uint64_t)ehdr.e_entry; + glue(load_symbols, SZ)(&ehdr, fd, must_swab); size = ehdr.e_phnum * sizeof(phdr[0]); @@ -176,7 +180,8 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend, int must_swab) /* XXX: avoid allocating */ data = qemu_mallocz(mem_size); if (ph->p_filesz > 0) { - lseek(fd, ph->p_offset, SEEK_SET); + if (lseek(fd, ph->p_offset, SEEK_SET) < 0) + goto fail; if (read(fd, data, ph->p_filesz) != ph->p_filesz) goto fail; } @@ -187,10 +192,12 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend, int must_swab) total_size += mem_size; qemu_free(data); + data = NULL; } } return total_size; fail: + qemu_free(data); qemu_free(phdr); return -1; } diff --git a/hw/sun4m.c b/hw/sun4m.c index 014ed09264..3619005d71 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -269,7 +269,7 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device, prom_offset | IO_MEM_ROM); snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE); - ret = load_elf(buf, 0); + ret = load_elf(buf, 0, NULL); if (ret < 0) { snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB); ret = load_image(buf, phys_ram_base + prom_offset); @@ -282,7 +282,7 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device, kernel_size = 0; if (linux_boot) { - kernel_size = load_elf(kernel_filename, -0xf0000000); + kernel_size = load_elf(kernel_filename, -0xf0000000, NULL); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); if (kernel_size < 0) diff --git a/hw/sun4u.c b/hw/sun4u.c index bb40697c4e..208d3dd63a 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -283,7 +283,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, prom_offset | IO_MEM_ROM); snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE); - ret = load_elf(buf, 0); + ret = load_elf(buf, 0, NULL); if (ret < 0) { snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB); ret = load_image(buf, phys_ram_base + prom_offset); @@ -298,7 +298,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, initrd_size = 0; if (linux_boot) { /* XXX: put correct offset */ - kernel_size = load_elf(kernel_filename, 0); + kernel_size = load_elf(kernel_filename, 0, NULL); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); if (kernel_size < 0) diff --git a/loader.c b/loader.c index c4bde55c13..b2d6423fed 100644 --- a/loader.c +++ b/loader.c @@ -194,7 +194,8 @@ static void *load_at(int fd, int offset, int size) #include "elf_ops.h" /* return < 0 if error, otherwise the number of bytes loaded in memory */ -int load_elf(const char *filename, int64_t virt_to_phys_addend) +int load_elf(const char *filename, int64_t virt_to_phys_addend, + uint64_t *pentry) { int fd, data_order, must_swab, ret; uint8_t e_ident[EI_NIDENT]; @@ -220,9 +221,9 @@ int load_elf(const char *filename, int64_t virt_to_phys_addend) lseek(fd, 0, SEEK_SET); if (e_ident[EI_CLASS] == ELFCLASS64) { - ret = load_elf64(fd, virt_to_phys_addend, must_swab); + ret = load_elf64(fd, virt_to_phys_addend, must_swab, pentry); } else { - ret = load_elf32(fd, virt_to_phys_addend, must_swab); + ret = load_elf32(fd, virt_to_phys_addend, must_swab, pentry); } close(fd); diff --git a/vl.h b/vl.h index 964ca8a8fe..fdf8c6867e 100644 --- a/vl.h +++ b/vl.h @@ -878,7 +878,7 @@ void slavio_pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu); /* loader.c */ int get_image_size(const char *filename); int load_image(const char *filename, uint8_t *addr); -int load_elf(const char *filename, int64_t virt_to_phys_addend); +int load_elf(const char *filename, int64_t virt_to_phys_addend, uint64_t *pentry); int load_aout(const char *filename, uint8_t *addr); /* slavio_timer.c */ -- cgit v1.2.3