From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MRuE5-0000Cs-Dj for qemu-devel@nongnu.org; Fri, 17 Jul 2009 16:40:17 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MRuE0-00008a-8H for qemu-devel@nongnu.org; Fri, 17 Jul 2009 16:40:16 -0400 Received: from [199.232.76.173] (port=47342 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MRuE0-00008T-1P for qemu-devel@nongnu.org; Fri, 17 Jul 2009 16:40:12 -0400 Received: from mx20.gnu.org ([199.232.41.8]:30876) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1MRuDz-0002wP-4x for qemu-devel@nongnu.org; Fri, 17 Jul 2009 16:40:11 -0400 Received: from mail.codesourcery.com ([65.74.133.4]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MRuDu-0006fX-3c for qemu-devel@nongnu.org; Fri, 17 Jul 2009 16:40:08 -0400 From: Nathan Froyd Date: Fri, 17 Jul 2009 13:33:17 -0700 Message-Id: <1247862802-13033-2-git-send-email-froydnj@codesourcery.com> In-Reply-To: <1247862802-13033-1-git-send-email-froydnj@codesourcery.com> References: <1247862802-13033-1-git-send-email-froydnj@codesourcery.com> Subject: [Qemu-devel] [PATCH 1/6] sysemu: add section_callback argument to ELF loader List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Some targets indicate properties of the program with special sections in the ELF file--MIPS in particular. This infrastructure is useful for grovelling through those sections. Signed-off-by: Nathan Froyd --- elf_ops.h | 34 +++++++++++++++++++++++++++++++--- loader.c | 19 ++++++++++++++----- sysemu.h | 5 +++++ 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/elf_ops.h b/elf_ops.h index 72cd83e..9bede1b 100644 --- a/elf_ops.h +++ b/elf_ops.h @@ -98,7 +98,13 @@ static int glue(symcmp, SZ)(const void *s0, const void *s1) : ((sym0->st_value > sym1->st_value) ? 1 : 0); } -static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab) +/* Load function symbols for later groveling. If SECTION_CALLBACK is + non-NULL, it will be called with information about each section in + the binary. This interface enables to the caller to mine the binary + for useful information about the ABI, such as whether the CPU chosen is + compatible with the binary. */ +static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, + section_callback_t section_callback) { struct elf_shdr *symtab, *strtab, *shdr_table = NULL; struct elf_sym *syms = NULL; @@ -117,6 +123,27 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab) } } + /* Permit machines to grovel through the ELF file looking for + interesting bits of information. */ + if (section_callback && ehdr->e_shstrndx != SHN_UNDEF) { + char *shstr = NULL; + struct elf_shdr *shstrtab = &shdr_table[ehdr->e_shstrndx]; + + shstr = load_at(fd, shstrtab->sh_offset, shstrtab->sh_size); + if (!shstr) + goto fail_callback; + + for (i = 0; i < ehdr->e_shnum; i++) { + struct elf_shdr *sh = shdr_table + i; + + section_callback(fd, must_swab, sh->sh_size, sh->sh_offset, + &shstr[sh->sh_name]); + } + + fail_callback: + free (shstr); + } + symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB); if (!symtab) goto fail; @@ -179,7 +206,8 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab) static int glue(load_elf, SZ)(int fd, int64_t address_offset, int must_swab, uint64_t *pentry, - uint64_t *lowaddr, uint64_t *highaddr) + uint64_t *lowaddr, uint64_t *highaddr, + section_callback_t section_callback) { struct elfhdr ehdr; struct elf_phdr *phdr = NULL, *ph; @@ -213,7 +241,7 @@ static int glue(load_elf, SZ)(int fd, int64_t address_offset, if (pentry) *pentry = (uint64_t)(elf_sword)ehdr.e_entry; - glue(load_symbols, SZ)(&ehdr, fd, must_swab); + glue(load_symbols, SZ)(&ehdr, fd, must_swab, section_callback); size = ehdr.e_phnum * sizeof(phdr[0]); lseek(fd, ehdr.e_phoff, SEEK_SET); diff --git a/loader.c b/loader.c index 54580e4..7caf395 100644 --- a/loader.c +++ b/loader.c @@ -302,9 +302,10 @@ static void *load_at(int fd, int offset, int size) #define SZ 64 #include "elf_ops.h" -/* return < 0 if error, otherwise the number of bytes loaded in memory */ -int load_elf(const char *filename, int64_t address_offset, - uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr) +int load_elf_introspect(const char *filename, int64_t address_offset, + uint64_t *pentry, uint64_t *lowaddr, + uint64_t *highaddr, + section_callback_t section_callback) { int fd, data_order, host_data_order, must_swab, ret; uint8_t e_ident[EI_NIDENT]; @@ -339,10 +340,10 @@ int load_elf(const char *filename, int64_t address_offset, lseek(fd, 0, SEEK_SET); if (e_ident[EI_CLASS] == ELFCLASS64) { ret = load_elf64(fd, address_offset, must_swab, pentry, - lowaddr, highaddr); + lowaddr, highaddr, section_callback); } else { ret = load_elf32(fd, address_offset, must_swab, pentry, - lowaddr, highaddr); + lowaddr, highaddr, section_callback); } close(fd); @@ -353,6 +354,14 @@ int load_elf(const char *filename, int64_t address_offset, return -1; } +/* return < 0 if error, otherwise the number of bytes loaded in memory */ +int load_elf(const char *filename, int64_t address_offset, + uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr) +{ + return load_elf_introspect (filename, address_offset, pentry, lowaddr, + highaddr, NULL); +} + static void bswap_uboot_header(uboot_image_header_t *hdr) { #ifndef WORDS_BIGENDIAN diff --git a/sysemu.h b/sysemu.h index df19f02..5f685a7 100644 --- a/sysemu.h +++ b/sysemu.h @@ -245,6 +245,11 @@ int load_image(const char *filename, uint8_t *addr); /* deprecated */ int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz); int load_elf(const char *filename, int64_t address_offset, uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr); +typedef void (*section_callback_t)(int fd, int must_swab, + uint64_t size, uint64_t offset, char *name); +int load_elf_introspect(const char *filename, int64_t address_offset, + uint64_t *pentry, uint64_t *lowaddr, + uint64_t *highaddr, section_callback_t callback); int load_aout(const char *filename, target_phys_addr_t addr, int max_sz); int load_uimage(const char *filename, target_ulong *ep, target_ulong *loadaddr, int *is_linux); -- 1.6.3.2