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 | #include <inttypes.h> | 4 | #include <inttypes.h> |
| 5 | 5 | ||
| @@ -996,6 +996,7 @@ typedef struct elf64_note { | @@ -996,6 +996,7 @@ typedef struct elf64_note { | ||
| 996 | #define elf_phdr elf32_phdr | 996 | #define elf_phdr elf32_phdr |
| 997 | #define elf_note elf32_note | 997 | #define elf_note elf32_note |
| 998 | #define elf_shdr elf32_shdr | 998 | #define elf_shdr elf32_shdr |
| 999 | +#define elf_sym elf32_sym | ||
| 999 | 1000 | ||
| 1000 | #ifdef ELF_USES_RELOCA | 1001 | #ifdef ELF_USES_RELOCA |
| 1001 | # define ELF_RELOC Elf32_Rela | 1002 | # define ELF_RELOC Elf32_Rela |
| @@ -1009,6 +1010,7 @@ typedef struct elf64_note { | @@ -1009,6 +1010,7 @@ typedef struct elf64_note { | ||
| 1009 | #define elf_phdr elf64_phdr | 1010 | #define elf_phdr elf64_phdr |
| 1010 | #define elf_note elf64_note | 1011 | #define elf_note elf64_note |
| 1011 | #define elf_shdr elf64_shdr | 1012 | #define elf_shdr elf64_shdr |
| 1013 | +#define elf_sym elf64_sym | ||
| 1012 | 1014 | ||
| 1013 | #ifdef ELF_USES_RELOCA | 1015 | #ifdef ELF_USES_RELOCA |
| 1014 | # define ELF_RELOC Elf64_Rela | 1016 | # define ELF_RELOC Elf64_Rela |
| @@ -1029,4 +1031,4 @@ typedef struct elf64_note { | @@ -1029,4 +1031,4 @@ typedef struct elf64_note { | ||
| 1029 | #endif | 1031 | #endif |
| 1030 | 1032 | ||
| 1031 | 1033 | ||
| 1032 | -#endif /* _ELF_H */ | 1034 | +#endif /* _QEMU_ELF_H */ |
linux-user/elfload.c
| @@ -11,6 +11,7 @@ | @@ -11,6 +11,7 @@ | ||
| 11 | #include <string.h> | 11 | #include <string.h> |
| 12 | 12 | ||
| 13 | #include "qemu.h" | 13 | #include "qemu.h" |
| 14 | +#include "disas.h" | ||
| 14 | 15 | ||
| 15 | #ifdef TARGET_I386 | 16 | #ifdef TARGET_I386 |
| 16 | 17 | ||
| @@ -195,6 +196,28 @@ static void bswap_phdr(Elf32_Phdr *phdr) | @@ -195,6 +196,28 @@ static void bswap_phdr(Elf32_Phdr *phdr) | ||
| 195 | bswap32s(&phdr->p_flags); /* Segment flags */ | 196 | bswap32s(&phdr->p_flags); /* Segment flags */ |
| 196 | bswap32s(&phdr->p_align); /* Segment alignment */ | 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 | #endif | 221 | #endif |
| 199 | 222 | ||
| 200 | static void * get_free_page(void) | 223 | static void * get_free_page(void) |
| @@ -656,7 +679,56 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | @@ -656,7 +679,56 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | ||
| 656 | return ((unsigned long) interp_elf_ex->e_entry) + load_addr; | 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 | static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, | 733 | static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, |
| 662 | struct image_info * info) | 734 | struct image_info * info) |
| @@ -989,6 +1061,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | @@ -989,6 +1061,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | ||
| 989 | 1061 | ||
| 990 | free(elf_phdata); | 1062 | free(elf_phdata); |
| 991 | 1063 | ||
| 1064 | + if (loglevel) | ||
| 1065 | + load_symbols(&elf_ex, bprm->fd); | ||
| 1066 | + | ||
| 992 | if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); | 1067 | if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); |
| 993 | info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); | 1068 | info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); |
| 994 | 1069 |