symbol fix
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 29 Apr 2003 20:40:07 +0000 (20:40 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 29 Apr 2003 20:40:07 +0000 (20:40 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@103 c046a42c-6fe2-441c-8c8c-71466251a162

elf.h
linux-user/elfload.c

diff --git a/elf.h b/elf.h
index d87526a..fcd3fec 100644 (file)
--- a/elf.h
+++ b/elf.h
@@ -1,5 +1,5 @@
-#ifndef _ELF_H
-#define _ELF_H
+#ifndef _QEMU_ELF_H
+#define _QEMU_ELF_H
 
 #include <inttypes.h>
 
@@ -996,6 +996,7 @@ typedef struct elf64_note {
 #define elf_phdr       elf32_phdr
 #define elf_note       elf32_note
 #define elf_shdr       elf32_shdr
+#define elf_sym                elf32_sym
 
 #ifdef ELF_USES_RELOCA
 # define ELF_RELOC      Elf32_Rela
@@ -1009,6 +1010,7 @@ typedef struct elf64_note {
 #define elf_phdr       elf64_phdr
 #define elf_note       elf64_note
 #define elf_shdr       elf64_shdr
+#define elf_sym                elf64_sym
 
 #ifdef ELF_USES_RELOCA
 # define ELF_RELOC      Elf64_Rela
@@ -1029,4 +1031,4 @@ typedef struct elf64_note {
 #endif
 
 
-#endif /* _ELF_H */
+#endif /* _QEMU_ELF_H */
index 2974c01..edb3176 100644 (file)
@@ -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);