Commit 689f936f7ea68c0539f73246d582e5c85ae50f12
1 parent
6977fbfd
symbol fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@103 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
80 additions
and
3 deletions
elf.h
| 1 | -#ifndef _ELF_H | |
| 2 | -#define _ELF_H | |
| 1 | +#ifndef _QEMU_ELF_H | |
| 2 | +#define _QEMU_ELF_H | |
| 3 | 3 | |
| 4 | 4 | #include <inttypes.h> |
| 5 | 5 | |
| ... | ... | @@ -996,6 +996,7 @@ typedef struct elf64_note { |
| 996 | 996 | #define elf_phdr elf32_phdr |
| 997 | 997 | #define elf_note elf32_note |
| 998 | 998 | #define elf_shdr elf32_shdr |
| 999 | +#define elf_sym elf32_sym | |
| 999 | 1000 | |
| 1000 | 1001 | #ifdef ELF_USES_RELOCA |
| 1001 | 1002 | # define ELF_RELOC Elf32_Rela |
| ... | ... | @@ -1009,6 +1010,7 @@ typedef struct elf64_note { |
| 1009 | 1010 | #define elf_phdr elf64_phdr |
| 1010 | 1011 | #define elf_note elf64_note |
| 1011 | 1012 | #define elf_shdr elf64_shdr |
| 1013 | +#define elf_sym elf64_sym | |
| 1012 | 1014 | |
| 1013 | 1015 | #ifdef ELF_USES_RELOCA |
| 1014 | 1016 | # define ELF_RELOC Elf64_Rela |
| ... | ... | @@ -1029,4 +1031,4 @@ typedef struct elf64_note { |
| 1029 | 1031 | #endif |
| 1030 | 1032 | |
| 1031 | 1033 | |
| 1032 | -#endif /* _ELF_H */ | |
| 1034 | +#endif /* _QEMU_ELF_H */ | ... | ... |
linux-user/elfload.c
| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | #include <string.h> |
| 12 | 12 | |
| 13 | 13 | #include "qemu.h" |
| 14 | +#include "disas.h" | |
| 14 | 15 | |
| 15 | 16 | #ifdef TARGET_I386 |
| 16 | 17 | |
| ... | ... | @@ -195,6 +196,28 @@ static void bswap_phdr(Elf32_Phdr *phdr) |
| 195 | 196 | bswap32s(&phdr->p_flags); /* Segment flags */ |
| 196 | 197 | bswap32s(&phdr->p_align); /* Segment alignment */ |
| 197 | 198 | } |
| 199 | + | |
| 200 | +static void bswap_shdr(Elf32_Shdr *shdr) | |
| 201 | +{ | |
| 202 | + bswap32s(&shdr->sh_name); | |
| 203 | + bswap32s(&shdr->sh_type); | |
| 204 | + bswap32s(&shdr->sh_flags); | |
| 205 | + bswap32s(&shdr->sh_addr); | |
| 206 | + bswap32s(&shdr->sh_offset); | |
| 207 | + bswap32s(&shdr->sh_size); | |
| 208 | + bswap32s(&shdr->sh_link); | |
| 209 | + bswap32s(&shdr->sh_info); | |
| 210 | + bswap32s(&shdr->sh_addralign); | |
| 211 | + bswap32s(&shdr->sh_entsize); | |
| 212 | +} | |
| 213 | + | |
| 214 | +static void bswap_sym(Elf32_Sym *sym) | |
| 215 | +{ | |
| 216 | + bswap32s(&sym->st_name); | |
| 217 | + bswap32s(&sym->st_value); | |
| 218 | + bswap32s(&sym->st_size); | |
| 219 | + bswap16s(&sym->st_shndx); | |
| 220 | +} | |
| 198 | 221 | #endif |
| 199 | 222 | |
| 200 | 223 | static void * get_free_page(void) |
| ... | ... | @@ -656,7 +679,56 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
| 656 | 679 | return ((unsigned long) interp_elf_ex->e_entry) + load_addr; |
| 657 | 680 | } |
| 658 | 681 | |
| 682 | +/* Best attempt to load symbols from this ELF object. */ | |
| 683 | +static void load_symbols(struct elfhdr *hdr, int fd) | |
| 684 | +{ | |
| 685 | + unsigned int i; | |
| 686 | + struct elf_shdr sechdr, symtab, strtab; | |
| 687 | + char *strings; | |
| 688 | + | |
| 689 | + lseek(fd, hdr->e_shoff, SEEK_SET); | |
| 690 | + for (i = 0; i < hdr->e_shnum; i++) { | |
| 691 | + if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) | |
| 692 | + return; | |
| 693 | +#ifdef BSWAP_NEEDED | |
| 694 | + bswap_shdr(&sechdr); | |
| 695 | +#endif | |
| 696 | + if (sechdr.sh_type == SHT_SYMTAB) { | |
| 697 | + symtab = sechdr; | |
| 698 | + lseek(fd, hdr->e_shoff | |
| 699 | + + sizeof(sechdr) * sechdr.sh_link, SEEK_SET); | |
| 700 | + if (read(fd, &strtab, sizeof(strtab)) | |
| 701 | + != sizeof(strtab)) | |
| 702 | + return; | |
| 703 | +#ifdef BSWAP_NEEDED | |
| 704 | + bswap_shdr(&strtab); | |
| 705 | +#endif | |
| 706 | + goto found; | |
| 707 | + } | |
| 708 | + } | |
| 709 | + return; /* Shouldn't happen... */ | |
| 710 | + | |
| 711 | + found: | |
| 712 | + /* Now know where the strtab and symtab are. Snarf them. */ | |
| 713 | + disas_symtab = malloc(symtab.sh_size); | |
| 714 | + disas_strtab = strings = malloc(strtab.sh_size); | |
| 715 | + if (!disas_symtab || !disas_strtab) | |
| 716 | + return; | |
| 717 | + | |
| 718 | + lseek(fd, symtab.sh_offset, SEEK_SET); | |
| 719 | + if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size) | |
| 720 | + return; | |
| 659 | 721 | |
| 722 | +#ifdef BSWAP_NEEDED | |
| 723 | + for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++) | |
| 724 | + bswap_sym(disas_symtab + sizeof(struct elf_sym)*i); | |
| 725 | +#endif | |
| 726 | + | |
| 727 | + lseek(fd, strtab.sh_offset, SEEK_SET); | |
| 728 | + if (read(fd, strings, strtab.sh_size) != strtab.sh_size) | |
| 729 | + return; | |
| 730 | + disas_num_syms = symtab.sh_size / sizeof(struct elf_sym); | |
| 731 | +} | |
| 660 | 732 | |
| 661 | 733 | static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
| 662 | 734 | struct image_info * info) |
| ... | ... | @@ -989,6 +1061,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r |
| 989 | 1061 | |
| 990 | 1062 | free(elf_phdata); |
| 991 | 1063 | |
| 1064 | + if (loglevel) | |
| 1065 | + load_symbols(&elf_ex, bprm->fd); | |
| 1066 | + | |
| 992 | 1067 | if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); |
| 993 | 1068 | info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); |
| 994 | 1069 | ... | ... |