qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Nathan Froyd <froydnj@codesourcery.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 1/6] sysemu: add section_callback argument to ELF loader
Date: Mon,  3 Aug 2009 07:45:06 -0700	[thread overview]
Message-ID: <1249310711-8873-2-git-send-email-froydnj@codesourcery.com> (raw)
In-Reply-To: <1249310711-8873-1-git-send-email-froydnj@codesourcery.com>

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 <froydnj@codesourcery.com>
---
 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 699651c..0acbcc7 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 0cbcf9c..6f025a9 100644
--- a/loader.c
+++ b/loader.c
@@ -305,9 +305,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];
@@ -342,10 +343,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);
@@ -356,6 +357,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 HOST_WORDS_BIGENDIAN
diff --git a/sysemu.h b/sysemu.h
index 6af88d8..b26cf40 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -241,6 +241,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

  reply	other threads:[~2009-08-03 14:52 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-03 14:45 [Qemu-devel] [PATCH 0/6] target-mips: add MDI semihosting, v2 Nathan Froyd
2009-08-03 14:45 ` Nathan Froyd [this message]
2009-08-03 14:45 ` [Qemu-devel] [PATCH 2/6] add softmmu_target_strlen Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 3/6] add implementation of MIPS semihosting Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 4/6] target-mips: add MDI semihosting support to mipssim machine Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 5/6] enable --semihosting option for TARGET_MIPS Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 6/6] gdbstub: add qSymbol handling " Nathan Froyd
  -- strict thread matches above, loose matches on Subject: below --
2009-07-17 20:33 [Qemu-devel] [PATCH 0/6] target-mips: add MDI semihosting Nathan Froyd
2009-07-17 20:33 ` [Qemu-devel] [PATCH 1/6] sysemu: add section_callback argument to ELF loader Nathan Froyd

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1249310711-8873-2-git-send-email-froydnj@codesourcery.com \
    --to=froydnj@codesourcery.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).