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 |