<html>
<body>
  <div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream/src</tt></b></td></tr>
<tr><td><tt><a href="#file1">loader.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+40</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">645ccec8dfb0 -> d18488c8668b</td></tr>
<tr class="alt" style=";" ><td><tt>sh4/<a href="#file2">sh4.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+14</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">645ccec8dfb0 -> d18488c8668b</td></tr>
<tr><td><tt>   /<a href="#file3">sh4dasm.h</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+1</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">645ccec8dfb0 -> d18488c8668b</td></tr>
<tr class="alt" style=";" ><td><tt>   /<a href="#file4">sh4dasm.in</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+74</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">645ccec8dfb0 -> d18488c8668b</td></tr>
<tr><td><tt>   /<a href="#file5">sh4trans.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+24</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-6</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">645ccec8dfb0 -> d18488c8668b</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+153</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-6</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >5 modified files</small><br />
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
Add support for extracting the ELF symbol table and printing symbol names
alongside the SH4 disassembly
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>loader.c</b></big> <small id="info" style="color: #888888;" >645ccec8dfb0 -> d18488c8668b</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/loader.c
+++ lxdream/src/loader.c
@@ -34,6 +34,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "drivers/cdrom/cdrom.h"
 #include "drivers/cdrom/isofs.h"
 #include "gdrom/gdrom.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "sh4/sh4.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 const char bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";
 const char iso_magic[6] = "\001CD001";
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -242,6 +243,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     Elf32_Ehdr head;
     Elf32_Phdr phdr;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    Elf32_Shdr shdr;
+    Elf32_Sym sym;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     int i;
 
     if( read( fd, &head, sizeof(head) ) != sizeof(head) )
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -265,6 +268,43 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
     }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    /* Find symbol table */
+    uint32_t symtabOffset = 0, symtabSize = 0, symtabEntSize = 0;
+    uint32_t strtabOffset = 0, strtabSize = 0;
+    for( int i = 0; i < head.e_shnum; i++ ) {
+        lseek( fd, head.e_shoff + i * head.e_shentsize, SEEK_SET );
+        read( fd, &shdr, sizeof( shdr ) );
+        if( shdr.sh_type == SHT_SYMTAB ) {
+            symtabOffset = shdr.sh_offset;
+            symtabSize = shdr.sh_size;
+            symtabEntSize = shdr.sh_entsize;
+        } else if( shdr.sh_type == SHT_STRTAB ) {
+            strtabOffset = shdr.sh_offset;
+            strtabSize = shdr.sh_size;
+        }
+    }
+    /* Extract symbols */
+    if( symtabOffset != 0 && strtabOffset != 0 ) {
+        unsigned numSymtabEntries = symtabSize / symtabEntSize;
+        char *data = g_malloc( numSymtabEntries * sizeof( struct sh4_symbol ) + strtabSize );
+        struct sh4_symbol *symtab = ( struct sh4_symbol * )data;
+        char *strings = data + ( numSymtabEntries * sizeof( struct sh4_symbol ) );
+        lseek( fd, strtabOffset, SEEK_SET );
+        read( fd, strings, strtabSize );
+        strings[strtabSize-1] = '\0'; /* Should already be 0, but just in case */
+        for( int i = 0; i < numSymtabEntries; i++ ) {
+            lseek( fd, symtabOffset + ( i * symtabEntSize ), SEEK_SET );
+            read( fd, &sym, sizeof( sym ) );
+            if( sym.st_name < strtabSize )
+               symtab[i].name = &strings[sym.st_name];
+            else
+               symtab[i].name = NULL;
+            symtab[i].address = sym.st_value;
+            symtab[i].size = sym.st_size;
+        }
+        sh4_set_symbol_table( symtab, numSymtabEntries, ( sh4_symtab_destroy_cb )free );
+    }
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     file_load_postload( filename, head.e_entry );
     return TRUE;
 }
</pre></div>
<hr /><a name="file2" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>sh4.h</b></big> <small id="info" style="color: #888888;" >645ccec8dfb0 -> d18488c8668b</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4.h
+++ lxdream/src/sh4/sh4.h
@@ -161,7 +161,21 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  */
 gboolean sh4_get_profile_blocks();
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+struct sh4_symbol {
+       const char *name;
+       sh4addr_t address;
+       unsigned size;
+};
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+typedef void (*sh4_symtab_destroy_cb)(struct sh4_symbol *table, unsigned size);
+
+/**
+ * Set the active symbol table used for disassembly. The table will be modified
+ * to sort it by address and eliminate duplicates.
+ * The callback supplied is invoked whenever the table is changed
+ * or removed.
+ */
+void sh4_set_symbol_table( struct sh4_symbol *table, unsigned symtab_size, sh4_symtab_destroy_cb callback );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #ifdef __cplusplus
 }
</pre></div>
<hr /><a name="file3" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>sh4dasm.h</b></big> <small id="info" style="color: #888888;" >645ccec8dfb0 -> d18488c8668b</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4dasm.h
+++ lxdream/src/sh4/sh4dasm.h
@@ -29,6 +29,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 uint32_t sh4_disasm_instruction( uint32_t pc, char *buf, int len, char * );
 void sh4_disasm_region( FILE *f, int from, int to );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+const char *sh4_disasm_get_symbol( sh4addr_t addr );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #ifdef __cplusplus
 }
</pre></div>
<hr /><a name="file4" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>sh4dasm.in</b></big> <small id="info" style="color: #888888;" >645ccec8dfb0 -> d18488c8668b</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4dasm.in
+++ lxdream/src/sh4/sh4dasm.in
@@ -21,6 +21,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "sh4/mmu.h"
 #include "mem.h"
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include <string.h>
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define UNIMP(ir) snprintf( buf, len, "???     " )
 
 uint32_t sh4_disasm_instruction( sh4vma_t pc, char *buf, int len, char *opcode )
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -275,6 +277,74 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static struct sh4_symbol *sh4_symbol_table = NULL;
+static unsigned sh4_symbol_table_size = 0;
+static sh4_symtab_destroy_cb sh4_symbol_table_cb = NULL;
+
+
+static void swap_symbol( struct sh4_symbol *a, struct sh4_symbol *b ) {
+    struct sh4_symbol tmp;
+    if( a == b )
+        return;
+    memcpy( &tmp, a, sizeof( struct sh4_symbol ) );
+    memcpy( a, b, sizeof( struct sh4_symbol ) );
+    memcpy( b, &tmp, sizeof( struct sh4_symbol ) );
+}
+
+static unsigned sort_symtab( struct sh4_symbol *table, unsigned numSymtabEntries ) {
+    /* Implement via simple selection sort for now; usually we don't have very
+     * large symbol tables.
+     */
+    for( unsigned i = 0; i < numSymtabEntries; i++ ) {
+        struct sh4_symbol *next_entry = &table[i];
+        for( unsigned j = i + 1; j < numSymtabEntries; ) {
+            if( table[j].address < next_entry->address ) {
+                next_entry = &table[j];
+                j++;
+            } else if( table[j].address == next_entry->address ) {
+                /* Duplicate - kill it */
+                swap_symbol( &table[j], &table[--numSymtabEntries] );
+            } else {
+                j++;
+            }
+        }
+        swap_symbol( &table[i], next_entry );
+    }
+    return numSymtabEntries;
+}
+
+const char *sh4_disasm_get_symbol( sh4addr_t addr )
+{
+       int l = 0, h = sh4_symbol_table_size;
+       while( l != h ) {
+           int i = l + (h-l)/2;
+           int iaddr = sh4_symbol_table[i].address;
+           if( iaddr == addr ) {
+               return sh4_symbol_table[i].name;
+           } else if( iaddr > addr ) {
+               h = i;
+           } else { /* iaddr < addr */
+               l = i+1;
+           }
+       }
+       return NULL;
+}
+
+void sh4_set_symbol_table( struct sh4_symbol *table, unsigned size, sh4_symtab_destroy_cb callback )
+{
+    if( sh4_symbol_table_cb != NULL ) {
+        sh4_symbol_table_cb(sh4_symbol_table, sh4_symbol_table_size);
+    }
+    sh4_symbol_table = table;
+    sh4_symbol_table_cb = callback;
+    if( table == NULL ) {
+        sh4_symbol_table_size = 0;
+    } else {
+        sh4_symbol_table_size = sort_symtab(table, size);
+    }
+}
+    
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void sh4_disasm_region( FILE *f, int from, int to )
 {
     int pc;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -285,6 +355,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         buf[0] = '\0';
         sh4_disasm_instruction( pc,
                                 buf, sizeof(buf), opcode );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        const char *sym = sh4_disasm_get_symbol( pc );
+        if( sym != 0 ) {
+            fprintf( f, "%s:\n", sym );
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         fprintf( f, "  %08x:  %s  %s\n", pc, opcode, buf );
     }
 }
</pre></div>
<hr /><a name="file5" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>sh4trans.c</b></big> <small id="info" style="color: #888888;" >645ccec8dfb0 -> d18488c8668b</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4trans.c
+++ lxdream/src/sh4/sh4trans.c
@@ -294,6 +294,16 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     sh4_translate_disasm_block( stderr, code, sh4_pc, NULL );
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void sh4_translate_dump_block_phys( uint32_t sh4_pma )
+{
+    void *code = xlat_get_code( sh4_pma );
+    if( code == NULL ) {
+        fprintf( stderr, "** No translated block for address %08x **\n", sh4_pma );
+        return;
+    }
+    sh4_translate_disasm_block( stderr, code, sh4_pma, NULL );
+
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 static struct xlat_symbol xlat_symbol_table[] = {
     { "sh4r+128", ((char *)&sh4r)+128 },
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -338,6 +348,20 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     for( target_pc = target_start; target_pc < target_end;  ) {
         uintptr_t pc2 = xlat_disasm_instruction( target_pc, buf, sizeof(buf), op );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+        if( source_recov_table < source_recov_end &&
+            target_pc >= (target_start + source_recov_table->xlat_offset) ) {
+            source_recov_table++;
+            if( source_end < (source_start + (source_recov_table->sh4_icount)*2) )
+                source_end = source_start + (source_recov_table->sh4_icount)*2;
+        }
+
+        if( source_pc < source_end ) {
+               const char *sym = sh4_disasm_get_symbol(source_pc);
+               if( sym != 0 ) {
+                       fprintf( out, "%s:\n", sym );
+               }
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #if SIZEOF_VOID_P == 8
         fprintf( out, "%c%016lx: %-30s %-40s", (target_pc == (uintptr_t)native_pc ? '*' : ' '),
                       target_pc, op, buf );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -345,12 +369,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         fprintf( out, "%c%08lx: %-30s %-40s", (target_pc == (uintptr_t)native_pc ? '*' : ' '),
                       target_pc, op, buf );
 #endif
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        if( source_recov_table < source_recov_end &&
-            target_pc >= (target_start + source_recov_table->xlat_offset) ) {
-            source_recov_table++;
-            if( source_end < (source_start + (source_recov_table->sh4_icount)*2) )
-                source_end = source_start + (source_recov_table->sh4_icount)*2;
-        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
         if( source_pc < source_end ) {
             uint32_t source_pc2 = sh4_disasm_instruction( source_pc, buf, sizeof(buf), op );
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>