Skip to contentSkip to conversation

Fix symbol lookup for mips64* targets

PATCH In review Stefan Weil 4 participants 13 messages Oct 2, 2008 – Oct 20, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fix symbol lookup for mips64* targets

For 64 bit targets, lookup_symbol() compares a 64-bit target address with a 32 bit symbol address. This only works for addresses less than 2^32.

MIPS64 kernels use addresses larger than 0xffffffff80000000, so qemu.log never shows symbolic names.

My patch is a workaround which works with Qemu's 32 bit address hack. Please apply it to Qemu trunk.

Maybe a better solution would use symbol addresses without shortening them to 32 bits.

Regards
Stefan

Fix symbol lookup for mips64* targets.

disas.c +5 -0
Index: disas.c
===================================================================
@@ -309,6 +309,11 @@
     struct syminfo *s;
     target_ulong addr;
 
+#if defined(TARGET_MIPS64)
+    /* Adresses in syminfos are 32 bit values. */
+    orig_addr &= 0xffffffff;
+#endif
+
     for (s = syminfos; s; s = s->next) {
 	sym = s->disas_symtab;
 	for (i = 0; i < s->disas_num_syms; i++) {
#1 lore raw
Quoted 8 lines · Stefan Weil

For 64 bit targets, lookup_symbol() compares a 64-bit target address
with a 32 bit symbol address. This only works for addresses less than 2^32.

MIPS64 kernels use addresses larger than 0xffffffff80000000, so qemu.log never shows symbolic names.

My patch is a workaround which works with Qemu's 32 bit address hack. Please apply it to Qemu trunk.

This applies to all architectures, not just MIPS64, so it need not be conditional to TARGET_MIPS64.

Quoted 2 lines

Maybe a better solution would use symbol addresses without shortening them to 32 bits.

Yes. That would mean using elf_sym instead of Elf32_sym in places where symbols are used and removing the SZ==64 hacks in elf_ops.h.

#2 lore raw

PATCH 1/1 Improve symbol lookup (was: Re: [Qemu-devel] [PATCH] Fix symbol lookup for mips64* targets)

Quoted 5 lines · Blue Swirl
Quoted 4 lines · Stefan Weil

For 64 bit targets, lookup_symbol() compares a 64-bit target address with a 32 bit symbol address. This only works for addresses less than 2^32.

Quoted 11 lines
Quoted 5 lines

MIPS64 kernels use addresses larger than 0xffffffff80000000, so qemu.log never shows symbolic names.

My patch is a workaround which works with Qemu's 32 bit address hack. Please apply it to Qemu trunk.

This applies to all architectures, not just MIPS64, so it need not be conditional to TARGET_MIPS64.

Quoted 2 lines

Maybe a better solution would use symbol addresses without shortening them to 32 bits.

Here is the better solution (at least I hope so).

Quoted 4 lines

Yes. That would mean using elf_sym instead of Elf32_sym in places where symbols are used and removing the SZ==64 hacks in elf_ops.h.

So I did. Here is a short summary of my new patch:

* Use function pointers for symbol lookup (currently for elf32 and elf64, could be expanded).
This also fixes the bug with mips elf64 symbols in current Qemu trunk.

* Use quicksort and binary search for symbol lookup.

* Remove unneeded entries from symbol table.
This reduced a typical table size (linux mips kernel) from 1764487 to
11656 entries.

* In disas.c, the patch also fixes some warnings from old fashioned function prototypes.

In loader.c, two defines control some compile time options (could be removed in
production code):
#define CONFIG_BINARY_SYMBOL_SEARCH
#define CONFIG_REDUCE_SYMBOL_TABLE

I tested the new code using 32 bit and 64 bit linux mips kernels and Qemu logging (-d in_asm).
The speed improvement is extremely large - both because of the much smaller table and
the binary search.

Stefan

* Use function pointers for symbol lookup (currently for elf32 and elf64, could be expanded). This also fixes the bug with mips elf64 symbols in current Qemu trunk.

* Use quicksort and binary search for symbol lookup.

* Remove unneeded entries from symbol table.
This reduced a typical table size (linux mips kernel) from 1764487 to 11656 entries.

* In disas.c, the patch also fixes some warnings from old fashioned function prototypes.

loader.c +2 -0
Index: loader.c
===================================================================
@@ -251,6 +251,8 @@
     return ptr;
 }
 
+#define CONFIG_BINARY_SYMBOL_SEARCH
+#define CONFIG_REDUCE_SYMBOL_TABLE
 
 #define ELF_CLASS   ELFCLASS32
 #include "elf.h"
disas.c +12 -39

85 lines not on this page · raw message

disas.h +16 -4
Index: disas.h
===================================================================
@@ -10,12 +10,24 @@
 /* Look up symbol for debugging purpose.  Returns "" if unknown. */
 const char *lookup_symbol(target_ulong orig_addr);
 
-/* Filled in by elfload.c.  Simplistic, but will do for now. */
-extern struct syminfo {
+struct syminfo;
+struct elf32_sym;
+struct elf64_sym;
+
+typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_ulong orig_addr);
+
+struct syminfo {
+    lookup_symbol_t lookup_symbol;
     unsigned int disas_num_syms;
-    void *disas_symtab;
+    union {
+      struct elf32_sym *elf32;
+      struct elf64_sym *elf64;
+    } disas_symtab;
     const char *disas_strtab;
     struct syminfo *next;
-} *syminfos;
+};
 
+/* Filled in by elfload.c.  Simplistic, but will do for now. */
+extern struct syminfo *syminfos;
+
 #endif /* _QEMU_DISAS_H */
elf_ops.h +88 -23

147 lines not on this page · raw message

#3 lore raw

Re: [Qemu-devel] [PATCH] Improve symbol lookup

Quoted 48 lines · Stefan Weil
Quoted 6 lines · Blue Swirl
Quoted 4 lines · Stefan Weil

For 64 bit targets, lookup_symbol() compares a 64-bit target address with a 32 bit symbol address. This only works for addresses less than 2^32.

Quoted 13 lines
Quoted 6 lines

MIPS64 kernels use addresses larger than 0xffffffff80000000, so qemu.log never shows symbolic names.

My patch is a workaround which works with Qemu's 32 bit address hack. Please apply it to Qemu trunk.

This applies to all architectures, not just MIPS64, so it need not be conditional to TARGET_MIPS64.

Quoted 3 lines

Maybe a better solution would use symbol addresses without shortening them to 32 bits.

Here is the better solution (at least I hope so).

Quoted 4 lines

Yes. That would mean using elf_sym instead of Elf32_sym in places where symbols are used and removing the SZ==64 hacks in elf_ops.h.

So I did. Here is a short summary of my new patch:

* Use function pointers for symbol lookup (currently for elf32 and elf64, could be expanded).
This also fixes the bug with mips elf64 symbols in current Qemu trunk.

* Use quicksort and binary search for symbol lookup.

* Remove unneeded entries from symbol table.
This reduced a typical table size (linux mips kernel) from 1764487 to
11656 entries.

* In disas.c, the patch also fixes some warnings from old fashioned function prototypes.

In loader.c, two defines control some compile time options (could be removed in
production code):
#define CONFIG_BINARY_SYMBOL_SEARCH
#define CONFIG_REDUCE_SYMBOL_TABLE

Quoted 9 lines

I tested the new code using 32 bit and 64 bit linux mips kernels and Qemu logging (-d in_asm).
The speed improvement is extremely large - both because of the much smaller table and
the binary search.

Stefan

Please note:

The current patch only supports system emulation.
User emulation needs more fixes to compile again.

Stefan

#4 lore raw

Re: [Qemu-devel] [PATCH] Improve symbol lookup

Quoted 3 lines · Stefan Weil

The current patch only supports system emulation.
User emulation needs more fixes to compile again.

I will take a look at it this week-end unless someone beats me to it.

Laurent

#5 lore raw

Re: [Qemu-devel] [PATCH] Improve symbol lookup for system and user mode

In reply to Stefan Weil
Quoted 29 lines
Quoted 27 lines · Stefan Weil

Here is a short summary of my new patch:

* Use function pointers for symbol lookup (currently for elf32 and elf64, could be expanded).
This also fixes the bug with mips elf64 symbols in current Qemu trunk.

* Use quicksort and binary search for symbol lookup.

* Remove unneeded entries from symbol table.
This reduced a typical table size (linux mips kernel) from 1764487 to 11656 entries.

* In disas.c, the patch also fixes some warnings from old fashioned function prototypes.

In loader.c, two defines control some compile time options (could be removed in
production code):
#define CONFIG_BINARY_SYMBOL_SEARCH
#define CONFIG_REDUCE_SYMBOL_TABLE

I tested the new code using 32 bit and 64 bit linux mips kernels and Qemu logging (-d in_asm).
The speed improvement is extremely large - both because of the much smaller table and
the binary search.

Quoted 10 lines
Quoted 2 lines

Stefan

Please note:

The current patch only supports system emulation.
User emulation needs more fixes to compile again.

Stefan

Here is an updated patch which now supports binary symbol lookup for both system emulation and user emulation.

User emulation was tested using qemu-x86_64 and a simple application with symbol information.

The new patch no longer includes compile time options for the old linear symbol search.

I hope this new patch will be included in Qemu trunk.

Regards
Stefan

* Use function pointers for symbol lookup (currently for elf32 and elf64, could be expanded). This also fixes the bug with mips elf64 symbols in current Qemu trunk.

* Use quicksort and binary search for symbol lookup.

* Remove unneeded entries from symbol table.
This reduced a typical table size (linux mips kernel) from 1764487 to 11656 entries.

* In disas.c, the patch also fixes some warnings from old fashioned function prototypes.

elfload.c +94 -44
Index: linux-user/elfload.c
===================================================================
@@ -984,80 +984,130 @@
 	return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
 }
 
+static int symfind(const void *s0, const void *s1)
+{
+    struct elf_sym *key = (struct elf_sym *)s0;
+    struct elf_sym *sym = (struct elf_sym *)s1;
+    int result = 0;
+    if (key->st_value < sym->st_value) {
+        result = -1;
+    } else if (key->st_value > sym->st_value + sym->st_size) {
+        result = 1;
+    }
+    return result;
+}
+
+static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
+{
+#if ELF_CLASS == ELFCLASS32
+    struct elf_sym *syms = s->disas_symtab.elf32;
+#else
+    struct elf_sym *syms = s->disas_symtab.elf64;
+#endif
+
+    // binary search
+    struct elf_sym key;
+    struct elf_sym *sym;
+
+    key.st_value = orig_addr;
+
+    sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
+    if (sym != 0) {
+        return s->disas_strtab + sym->st_name;
+    }
+
+    return "";
+}
+
+static int symcmp(const void *s0, const void *s1)
+{
+    struct elf_sym *sym0 = (struct elf_sym *)s0;
+    struct elf_sym *sym1 = (struct elf_sym *)s1;
+    return (sym0->st_value < sym1->st_value)
+        ? -1
+        : ((sym0->st_value > sym1->st_value) ? 1 : 0);
+}
+
 /* Best attempt to load symbols from this ELF object. */
 static void load_symbols(struct elfhdr *hdr, int fd)
 {
-    unsigned int i;
+    unsigned int i, nsyms;
     struct elf_shdr sechdr, symtab, strtab;
     char *strings;
     struct syminfo *s;
-#if (ELF_CLASS == ELFCLASS64)
-    // Disas uses 32 bit symbols
-    struct elf32_sym *syms32 = NULL;
-    struct elf_sym *sym;
-#endif
+    struct elf_sym *syms;
 
     lseek(fd, hdr->e_shoff, SEEK_SET);
     for (i = 0; i < hdr->e_shnum; i++) {
-	if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
-	    return;
+        if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
+            return;
 #ifdef BSWAP_NEEDED
-	bswap_shdr(&sechdr);
+        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;
+        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);
+            bswap_shdr(&strtab);
 #endif
-	    goto found;
-	}
+            goto found;
+        }
     }
     return; /* Shouldn't happen... */
 
  found:
     /* Now know where the strtab and symtab are.  Snarf them. */
     s = malloc(sizeof(*s));
-    s->disas_symtab = malloc(symtab.sh_size);
-#if (ELF_CLASS == ELFCLASS64)
-    syms32 = malloc(symtab.sh_size / sizeof(struct elf_sym)
-                    * sizeof(struct elf32_sym));
-#endif
+    syms = malloc(symtab.sh_size);
+    if (!syms)
+        return;
     s->disas_strtab = strings = malloc(strtab.sh_size);
-    if (!s->disas_symtab || !s->disas_strtab)
-	return;
+    if (!s->disas_strtab)
+        return;
 
     lseek(fd, symtab.sh_offset, SEEK_SET);
-    if (read(fd, s->disas_symtab, symtab.sh_size) != symtab.sh_size)
-	return;
+    if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
+        return;
 
-    for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++) {
+    nsyms = symtab.sh_size / sizeof(struct elf_sym);
+
+    for (i = 0; i < nsyms; i++) {
 #ifdef BSWAP_NEEDED
-	bswap_sym(s->disas_symtab + sizeof(struct elf_sym)*i);
+        bswap_sym(syms + i);
 #endif
-#if (ELF_CLASS == ELFCLASS64)
-        sym = s->disas_symtab + sizeof(struct elf_sym)*i;
-        syms32[i].st_name = sym->st_name;
-        syms32[i].st_info = sym->st_info;
-        syms32[i].st_other = sym->st_other;
-        syms32[i].st_shndx = sym->st_shndx;
-        syms32[i].st_value = sym->st_value & 0xffffffff;
-        syms32[i].st_size = sym->st_size & 0xffffffff;
+        // Throw away entries which we do not need.
+        while ((syms[i].st_shndx == SHN_UNDEF ||
+                syms[i].st_shndx >= SHN_LORESERVE ||
+                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) && i < --nsyms) {
+            syms[i] = syms[nsyms];
+#ifdef BSWAP_NEEDED
+            bswap_sym(syms + i);
 #endif
+        }
+#if defined(TARGET_ARM) || defined (TARGET_MIPS)
+        /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
+        syms[i].st_value &= ~(target_ulong)1;
+#endif
     }
+    syms = realloc(syms, nsyms * sizeof(*syms));
 
-#if (ELF_CLASS == ELFCLASS64)
-    free(s->disas_symtab);
-    s->disas_symtab = syms32;
-#endif
+    qsort(syms, nsyms, sizeof(*syms), symcmp);
+
     lseek(fd, strtab.sh_offset, SEEK_SET);
     if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
-	return;
-    s->disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
+        return;
+    s->disas_num_syms = nsyms;
+#if ELF_CLASS == ELFCLASS32
+    s->disas_symtab.elf32 = syms;
+    s->lookup_symbol = lookup_symbolxx;
+#else
+    s->disas_symtab.elf64 = syms;
+    s->lookup_symbol = lookup_symbolxx;
+#endif
     s->next = syminfos;
     syminfos = s;
 }
disas.c +12 -39

85 lines not on this page · raw message

disas.h +16 -4
Index: disas.h
===================================================================
@@ -10,12 +10,24 @@
 /* Look up symbol for debugging purpose.  Returns "" if unknown. */
 const char *lookup_symbol(target_ulong orig_addr);
 
-/* Filled in by elfload.c.  Simplistic, but will do for now. */
-extern struct syminfo {
+struct syminfo;
+struct elf32_sym;
+struct elf64_sym;
+
+typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_ulong orig_addr);
+
+struct syminfo {
+    lookup_symbol_t lookup_symbol;
     unsigned int disas_num_syms;
-    void *disas_symtab;
+    union {
+      struct elf32_sym *elf32;
+      struct elf64_sym *elf64;
+    } disas_symtab;
     const char *disas_strtab;
     struct syminfo *next;
-} *syminfos;
+};
 
+/* Filled in by elfload.c.  Simplistic, but will do for now. */
+extern struct syminfo *syminfos;
+
 #endif /* _QEMU_DISAS_H */
elf_ops.h +60 -23

119 lines not on this page · raw message

#6 lore raw

Re: [Qemu-devel] [PATCH] Improve symbol lookup for system and user mode

Quoted 8 lines · Stefan Weil
Quoted 8 lines
Quoted 6 lines · Stefan Weil

Here is a short summary of my new patch:

* Use function pointers for symbol lookup (currently for elf32 and elf64, could be expanded).
This also fixes the bug with mips elf64 symbols in current Qemu trunk.

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

* Use quicksort and binary search for symbol lookup.

* Remove unneeded entries from symbol table.
This reduced a typical table size (linux mips kernel) from 1764487 to 11656 entries.

* In disas.c, the patch also fixes some warnings from old fashioned function prototypes.

This should be a separate patch.

Quoted 28 lines
Quoted 13 lines
Quoted 13 lines

In loader.c, two defines control some compile time options (could be removed in
production code):
#define CONFIG_BINARY_SYMBOL_SEARCH
#define CONFIG_REDUCE_SYMBOL_TABLE

I tested the new code using 32 bit and 64 bit linux mips kernels and Qemu logging (-d in_asm).
The speed improvement is extremely large - both because of the much smaller table and
the binary search.

Quoted 10 lines
Quoted 2 lines

Stefan

Please note:

The current patch only supports system emulation.
User emulation needs more fixes to compile again.

Stefan

Here is an updated patch which now supports binary symbol lookup for both system emulation and user emulation.

Quoted 7 lines

User emulation was tested using qemu-x86_64 and a simple application with symbol information.

The new patch no longer includes compile time options for the old linear symbol search.

I hope this new patch will be included in Qemu trunk.

There are some white space only changes, these should be taken out.

For some reason, loading a bios with symbols on Sparc32 corrupts the bios but Sparc64 works. This happens also without your patch.

#7 lore raw

Re: [Qemu-devel] [PATCH] Improve symbol lookup (was: Re: [Qemu-devel] [PATCH] Fix symbol lookup for mips64* targets)

In reply to Stefan Weil
Quoted 22 lines · Stefan Weil

So I did. Here is a short summary of my new patch:

* Use function pointers for symbol lookup (currently for elf32 and elf64, could be expanded).
This also fixes the bug with mips elf64 symbols in current Qemu trunk.

* Use quicksort and binary search for symbol lookup.

* Remove unneeded entries from symbol table.
This reduced a typical table size (linux mips kernel) from 1764487 to
11656 entries.

* In disas.c, the patch also fixes some warnings from old fashioned function prototypes.

In loader.c, two defines control some compile time options (could be removed in
production code):
#define CONFIG_BINARY_SYMBOL_SEARCH
#define CONFIG_REDUCE_SYMBOL_TABLE

Quoted 5 lines

I tested the new code using 32 bit and 64 bit linux mips kernels and Qemu logging (-d in_asm).
The speed improvement is extremely large - both because of the much smaller table and
the binary search.

Nice! Did you profile the time spent looking up symbols when running some big executable with a big symbol table?

Laurent

#8 lore raw
In reply to Stefan Weil
Quoted 25 lines · Stefan Weil

For 64 bit targets, lookup_symbol() compares a 64-bit target address with a 32 bit symbol address. This only works for addresses less than 2^32.

MIPS64 kernels use addresses larger than 0xffffffff80000000, so qemu.log never shows symbolic names.

My patch is a workaround which works with Qemu's 32 bit address hack. Please apply it to Qemu trunk.

Maybe a better solution would use symbol addresses without shortening them to 32 bits.

Regards
Stefan

Fix symbol lookup for mips64* targets.

Index: disas.c
===================================================================

disas.c line 314

Quoted 6 lines
disas.c +3 -0
@@ -309,6 +309,11 @@
     struct syminfo *s;
     target_ulong addr;
 
+#if defined(TARGET_MIPS64)
+    /* Adresses in syminfos are 32 bit values. */
+    orig_addr &= 0xffffffff;

This isn't true in general, not all MIPS64 kernels use the -msym32 optimization.

Thiemo

#9 lore raw
Quoted 41 lines · Thiemo Seufer
Quoted 27 lines · Stefan Weil

For 64 bit targets, lookup_symbol() compares a 64-bit target address with a 32 bit symbol address. This only works for addresses less than 2^32.

MIPS64 kernels use addresses larger than 0xffffffff80000000, so qemu.log never shows symbolic names.

My patch is a workaround which works with Qemu's 32 bit address hack. Please apply it to Qemu trunk.

Maybe a better solution would use symbol addresses without shortening them to 32 bits.

Regards
Stefan

Fix symbol lookup for mips64* targets.

Index: disas.c
===================================================================

disas.c line 315

Quoted 7 lines
disas.c +3 -0
@@ -309,6 +309,11 @@
     struct syminfo *s;
     target_ulong addr;
 
+#if defined(TARGET_MIPS64)
+    /* Adresses in syminfos are 32 bit values. */
+    orig_addr &= 0xffffffff;
 

This isn't true in general, not all MIPS64 kernels use the -msym32 optimization.

Quoted 1 line

Thiemo

Nor does my MIPS64 kernel: it uses 64 bit symbol addresses.

The current Qemu loads these addresses, reduces them to 32 bit and stores the reduced 32 bit addresses. So the 32 bit addresses are made by Qemu. They have nothing to do with kernel compile flags.

In lookup_symbol, Qemu compares real 64 bit addresses to the reduced 32 bit addresses which does not work for addresses larger than 2^32. x86_64 kernels have no problem because they have small addresses. MIPS64 kernels have a problem because they have large addresses. I don't know whether ppc64 and sparc64 work, maybe someone who has such kernels can do a "nm vmlinux".

My patch is only a workaround which reduces the real 64 bit addresses to 32 bit, too.

I suggest to apply it to Qemu trunk (because it is small and it improves the current situation) and to add a note to the TODO list:
- store symbol addresses in full size (important for 64 bit targets)

Stefan

#10 lore raw

On Fri, Oct 3, 2008 at 12:09 PM, Stefan Weil <[email protected]> wrote:
[...]

Quoted 2 lines

add a note to the TODO list:
- store symbol addresses in full size (important for 64 bit targets)

And while you're at it add a note saying using linked lists for that is killing performance :-)

I have a hash-table based implementation somewhere if someone wants to take a look.

Laurent

#11 lore raw
Quoted 7 lines · Laurent Desnogues

On Fri, Oct 3, 2008 at 12:09 PM, Stefan Weil <[email protected]> wrote:
[...]

Quoted 2 lines

add a note to the TODO list:
- store symbol addresses in full size (important for 64 bit targets)

Quoted 5 lines

And while you're at it add a note saying using linked lists for that
is killing performance :-)

I have a hash-table based implementation somewhere if someone wants to take a look.

That would be interesting, please send.

#12 lore raw
In reply to Stefan Weil
Quoted 51 lines · Stefan Weil
Quoted 41 lines · Thiemo Seufer
Quoted 27 lines · Stefan Weil

For 64 bit targets, lookup_symbol() compares a 64-bit target address with a 32 bit symbol address. This only works for addresses less than 2^32.

MIPS64 kernels use addresses larger than 0xffffffff80000000, so qemu.log never shows symbolic names.

My patch is a workaround which works with Qemu's 32 bit address hack. Please apply it to Qemu trunk.

Maybe a better solution would use symbol addresses without shortening them to 32 bits.

Regards
Stefan

Fix symbol lookup for mips64* targets.

Index: disas.c
===================================================================

disas.c (Arbeitskopie) line 315

Quoted 7 lines
disas.c (Arbeitskopie) renamed from disas.c (Revision 5400) +3 -0
@@ -309,6 +309,11 @@
     struct syminfo *s;
     target_ulong addr;
 
+#if defined(TARGET_MIPS64)
+    /* Adresses in syminfos are 32 bit values. */
+    orig_addr &= 0xffffffff;
 

This isn't true in general, not all MIPS64 kernels use the -msym32 optimization.

Quoted 1 line

Thiemo

Nor does my MIPS64 kernel: it uses 64 bit symbol addresses.

The current Qemu loads these addresses, reduces them to 32 bit and stores the reduced 32 bit addresses. So the 32 bit addresses are made by Qemu. They have nothing to do with kernel compile flags.

Quoted 6 lines

In lookup_symbol, Qemu compares real 64 bit addresses to the reduced 32 bit addresses which does not work for addresses larger than 2^32. x86_64 kernels have no problem because they have small addresses. MIPS64 kernels have a problem because they have large addresses. I don't know whether ppc64 and sparc64 work, maybe someone who has such kernels can do a "nm vmlinux".

Sparc64 kernel is located below 4G.

Quoted 6 lines

My patch is only a workaround which reduces the real 64 bit addresses to 32 bit, too.

I suggest to apply it to Qemu trunk (because it is small and it improves the current situation) and to add a note to the TODO list:
- store symbol addresses in full size (important for 64 bit targets)

We could be more ambitious and make the symbol size depend on target. It does not look too hard.