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 | ... | ... |