diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-04-29 20:40:07 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-04-29 20:40:07 +0000 |
commit | 689f936f7ea68c0539f73246d582e5c85ae50f12 (patch) | |
tree | 236f92dbce80e7f51abe72ab1e0c374247adc631 /linux-user/elfload.c | |
parent | 6977fbfd8bff90f4dbe4e79c2f77921ce0ba34ff (diff) |
symbol fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@103 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/elfload.c')
-rw-r--r-- | linux-user/elfload.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 2974c01fe0..edb3176bcb 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -11,6 +11,7 @@ #include <string.h> #include "qemu.h" +#include "disas.h" #ifdef TARGET_I386 @@ -195,6 +196,28 @@ static void bswap_phdr(Elf32_Phdr *phdr) bswap32s(&phdr->p_flags); /* Segment flags */ bswap32s(&phdr->p_align); /* Segment alignment */ } + +static void bswap_shdr(Elf32_Shdr *shdr) +{ + bswap32s(&shdr->sh_name); + bswap32s(&shdr->sh_type); + bswap32s(&shdr->sh_flags); + bswap32s(&shdr->sh_addr); + bswap32s(&shdr->sh_offset); + bswap32s(&shdr->sh_size); + bswap32s(&shdr->sh_link); + bswap32s(&shdr->sh_info); + bswap32s(&shdr->sh_addralign); + bswap32s(&shdr->sh_entsize); +} + +static void bswap_sym(Elf32_Sym *sym) +{ + bswap32s(&sym->st_name); + bswap32s(&sym->st_value); + bswap32s(&sym->st_size); + bswap16s(&sym->st_shndx); +} #endif static void * get_free_page(void) @@ -656,7 +679,56 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, return ((unsigned long) interp_elf_ex->e_entry) + load_addr; } +/* Best attempt to load symbols from this ELF object. */ +static void load_symbols(struct elfhdr *hdr, int fd) +{ + unsigned int i; + struct elf_shdr sechdr, symtab, strtab; + char *strings; + + lseek(fd, hdr->e_shoff, SEEK_SET); + for (i = 0; i < hdr->e_shnum; i++) { + if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) + return; +#ifdef BSWAP_NEEDED + bswap_shdr(&sechdr); +#endif + if (sechdr.sh_type == SHT_SYMTAB) { + symtab = sechdr; + lseek(fd, hdr->e_shoff + + sizeof(sechdr) * sechdr.sh_link, SEEK_SET); + if (read(fd, &strtab, sizeof(strtab)) + != sizeof(strtab)) + return; +#ifdef BSWAP_NEEDED + bswap_shdr(&strtab); +#endif + goto found; + } + } + return; /* Shouldn't happen... */ + + found: + /* Now know where the strtab and symtab are. Snarf them. */ + disas_symtab = malloc(symtab.sh_size); + disas_strtab = strings = malloc(strtab.sh_size); + if (!disas_symtab || !disas_strtab) + return; + + lseek(fd, symtab.sh_offset, SEEK_SET); + if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size) + return; +#ifdef BSWAP_NEEDED + for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++) + bswap_sym(disas_symtab + sizeof(struct elf_sym)*i); +#endif + + lseek(fd, strtab.sh_offset, SEEK_SET); + if (read(fd, strings, strtab.sh_size) != strtab.sh_size) + return; + disas_num_syms = symtab.sh_size / sizeof(struct elf_sym); +} static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, struct image_info * info) @@ -989,6 +1061,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r free(elf_phdata); + if (loglevel) + load_symbols(&elf_ex, bprm->fd); + if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); |