--- hw/elf_ops.h | 32 ++++++++++++++++++++++++++++++-- hw/loader.c | 7 +++++++ hw/loader.h | 3 +++ 3 files changed, 40 insertions(+), 2 deletions(-)
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; -- 1.6.0.2