Skip to content

Commit

Permalink
Add symbol table callback function interface to load_elf
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Clark committed Feb 9, 2018
1 parent 7003ee6 commit 17272f5
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 15 deletions.
18 changes: 16 additions & 2 deletions hw/core/loader.c
Expand Up @@ -449,6 +449,20 @@ int load_elf_ram(const char *filename,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab, AddressSpace *as,
bool load_rom)
{
return load_elf_ram_sym(filename, translate_fn, translate_opaque,
pentry, lowaddr, highaddr, big_endian,
elf_machine, clear_lsb, data_swab, as,
load_rom, NULL);
}

/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_ram_sym(const char *filename,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, int big_endian,
int elf_machine, int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom, symbol_fn_t sym_cb)
{
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
uint8_t e_ident[EI_NIDENT];
Expand Down Expand Up @@ -488,11 +502,11 @@ int load_elf_ram(const char *filename,
if (e_ident[EI_CLASS] == ELFCLASS64) {
ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
data_swab, as, load_rom);
data_swab, as, load_rom, sym_cb);
} else {
ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
data_swab, as, load_rom);
data_swab, as, load_rom, sym_cb);
}

fail:
Expand Down
28 changes: 16 additions & 12 deletions include/hw/elf_ops.h
Expand Up @@ -105,7 +105,7 @@ 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, symbol_fn_t sym_cb)
{
struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
struct elf_sym *syms = NULL;
Expand Down Expand Up @@ -133,10 +133,22 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,

nsyms = symtab->sh_size / sizeof(struct elf_sym);

/* String table */
if (symtab->sh_link >= ehdr->e_shnum)
goto fail;
strtab = &shdr_table[symtab->sh_link];

str = load_at(fd, strtab->sh_offset, strtab->sh_size);
if (!str)
goto fail;

i = 0;
while (i < nsyms) {
if (must_swab)
glue(bswap_sym, SZ)(&syms[i]);
if (sym_cb)
sym_cb(str + syms[i].st_name, syms[i].st_info,
syms[i].st_value, syms[i].st_size);
/* We are only interested in function symbols.
Throw everything else away. */
if (syms[i].st_shndx == SHN_UNDEF ||
Expand All @@ -163,15 +175,6 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
}
}

/* String table */
if (symtab->sh_link >= ehdr->e_shnum)
goto fail;
strtab = &shdr_table[symtab->sh_link];

str = load_at(fd, strtab->sh_offset, strtab->sh_size);
if (!str)
goto fail;

/* Commit */
s = g_malloc0(sizeof(*s));
s->lookup_symbol = glue(lookup_symbol, SZ);
Expand Down Expand Up @@ -264,7 +267,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom)
AddressSpace *as, bool load_rom,
symbol_fn_t sym_cb)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
Expand Down Expand Up @@ -329,7 +333,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, sym_cb);

size = ehdr.e_phnum * sizeof(phdr[0]);
if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff) {
Expand Down
17 changes: 16 additions & 1 deletion include/hw/loader.h
Expand Up @@ -65,7 +65,7 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
#define ELF_LOAD_WRONG_ENDIAN -4
const char *load_elf_strerror(int error);

/** load_elf_ram:
/** load_elf_ram_sym:
* @filename: Path of ELF file
* @translate_fn: optional function to translate load addresses
* @translate_opaque: opaque data passed to @translate_fn
Expand All @@ -82,6 +82,7 @@ const char *load_elf_strerror(int error);
* @as: The AddressSpace to load the ELF to. The value of address_space_memory
* is used if nothing is supplied here.
* @load_rom : Load ELF binary as ROM
* @sym_cb: Callback function for symbol table entries
*
* Load an ELF file's contents to the emulated system's address space.
* Clients may optionally specify a callback to perform address
Expand All @@ -94,6 +95,20 @@ const char *load_elf_strerror(int error);
* If @elf_machine is EM_NONE then the machine type will be read from the
* ELF header and no checks will be carried out against the machine type.
*/
typedef void (*symbol_fn_t)(const char *st_name, int st_info,
uint64_t st_value, uint64_t st_size);

int load_elf_ram_sym(const char *filename,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, int big_endian,
int elf_machine, int clear_lsb, int data_swab,
AddressSpace *as, bool load_rom, symbol_fn_t sym_cb);

/** load_elf_ram:
* Same as load_elf_ram_sym(), but doesn't allow the caller to specify a
* symbol callback function
*/
int load_elf_ram(const char *filename,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
Expand Down

0 comments on commit 17272f5

Please sign in to comment.