diff mbox

[04/40] elf: add section analyzer

Message ID 1288623713-28062-5-git-send-email-agraf@suse.de
State New
Headers show

Commit Message

Alexander Graf Nov. 1, 2010, 3:01 p.m. UTC
---
 hw/elf_ops.h |   32 ++++++++++++++++++++++++++++++--
 hw/loader.c  |    7 +++++++
 hw/loader.h  |    3 +++
 3 files changed, 40 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index 5bcba7e..6a042c5 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -100,13 +100,14 @@  static int glue(symcmp, SZ)(const void *s0, const void *s1)
 }
 
 static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
-                                  int clear_lsb)
+                                  int clear_lsb, ElfHandlers *handlers)
 {
     struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
     struct elf_sym *syms = NULL;
     struct syminfo *s;
     int nsyms, i;
     char *str = NULL;
+    char *secstr = NULL;
 
     shdr_table = load_at(fd, ehdr->e_shoff,
                          sizeof(struct elf_shdr) * ehdr->e_shnum);
@@ -172,6 +173,32 @@  static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
     if (!str)
         goto fail;
 
+    /* Section string table */
+    if (ehdr->e_shstrndx >= ehdr->e_shnum)
+        goto fail;
+    strtab = &shdr_table[ehdr->e_shstrndx];
+
+    secstr = load_at(fd, strtab->sh_offset, strtab->sh_size);
+    if (!secstr)
+        goto fail;
+
+    /* External section analyzer */
+    for (i = 0; i < ehdr->e_shnum; i++) {
+        struct elf_shdr *cursec = &shdr_table[i];
+        uint8_t *section, *name;
+
+        if (!cursec->sh_size) {
+            continue;
+        }
+
+        name = (uint8_t*)&secstr[cursec->sh_name];
+        section = load_at(fd, cursec->sh_offset, cursec->sh_size);
+        handlers->section_fn(handlers->section_opaque, name, cursec->sh_size,
+                             section);
+        qemu_free(section);
+    }
+
+
     /* Commit */
     s = qemu_mallocz(sizeof(*s));
     s->lookup_symbol = glue(lookup_symbol, SZ);
@@ -185,6 +212,7 @@  static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
  fail:
     qemu_free(syms);
     qemu_free(str);
+    qemu_free(secstr);
     qemu_free(shdr_table);
     return -1;
 }
@@ -273,7 +301,7 @@  static int glue(load_elf, SZ)(const char *name, int fd,
     if (pentry)
    	*pentry = (uint64_t)(elf_sword)ehdr.e_entry;
 
-    glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb);
+    glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb, handlers);
 
     size = ehdr.e_phnum * sizeof(phdr[0]);
     lseek(fd, ehdr.e_phoff, SEEK_SET);
diff --git a/hw/loader.c b/hw/loader.c
index 6a43fda..cf3c1ad 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -234,6 +234,11 @@  static void elf_default_note(void *opaque, uint8_t *name, uint32_t name_len,
 {
 }
 
+static void elf_default_section(void *opaque, uint8_t *name, uint32_t len,
+                                uint8_t *data)
+{
+}
+
 static uint64_t elf_default_translate(void *opaque, uint64_t addr)
 {
     return addr;
@@ -251,6 +256,8 @@  ElfHandlers elf_default_handlers = {
     .note_opaque = NULL,
     .header_notify_fn = elf_default_header_notify,
     .header_notify_opaque = NULL,
+    .section_fn = elf_default_section,
+    .section_opaque = NULL,
 };
 
 
diff --git a/hw/loader.h b/hw/loader.h
index 090b815..6351644 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -14,6 +14,9 @@  typedef struct ElfHandlers {
     void *note_opaque;
     void (*header_notify_fn)(void *opaque, void *ehdr, int bits);
     void *header_notify_opaque;
+    void (*section_fn)(void *opaque, uint8_t *name, uint32_t len,
+                       uint8_t *data);
+    void *section_opaque;
 } ElfHandlers;
 
 extern ElfHandlers elf_default_handlers;