symbian-qemu-0.9.1-12/qemu-symbian-svp/disas.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /* General "disassemble this chunk" code.  Used for debugging. */
       
     2 #include "config.h"
       
     3 #include "dis-asm.h"
       
     4 #include "elf.h"
       
     5 #include <errno.h>
       
     6 
       
     7 #include "cpu.h"
       
     8 #include "exec-all.h"
       
     9 #include "disas.h"
       
    10 
       
    11 /* Filled in by elfload.c.  Simplistic, but will do for now. */
       
    12 struct syminfo *syminfos = NULL;
       
    13 
       
    14 /* Get LENGTH bytes from info's buffer, at target address memaddr.
       
    15    Transfer them to myaddr.  */
       
    16 int
       
    17 buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
       
    18                    struct disassemble_info *info)
       
    19 {
       
    20     if (memaddr < info->buffer_vma
       
    21         || memaddr + length > info->buffer_vma + info->buffer_length)
       
    22         /* Out of bounds.  Use EIO because GDB uses it.  */
       
    23         return EIO;
       
    24     memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
       
    25     return 0;
       
    26 }
       
    27 
       
    28 /* Get LENGTH bytes from info's buffer, at target address memaddr.
       
    29    Transfer them to myaddr.  */
       
    30 static int
       
    31 target_read_memory (bfd_vma memaddr,
       
    32                     bfd_byte *myaddr,
       
    33                     int length,
       
    34                     struct disassemble_info *info)
       
    35 {
       
    36     int i;
       
    37     for(i = 0; i < length; i++) {
       
    38         myaddr[i] = ldub_code(memaddr + i);
       
    39     }
       
    40     return 0;
       
    41 }
       
    42 
       
    43 /* Print an error message.  We can assume that this is in response to
       
    44    an error return from buffer_read_memory.  */
       
    45 void
       
    46 perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
       
    47 {
       
    48   if (status != EIO)
       
    49     /* Can't happen.  */
       
    50     (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
       
    51   else
       
    52     /* Actually, address between memaddr and memaddr + len was
       
    53        out of bounds.  */
       
    54     (*info->fprintf_func) (info->stream,
       
    55 			   "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
       
    56 }
       
    57 
       
    58 /* This could be in a separate file, to save miniscule amounts of space
       
    59    in statically linked executables.  */
       
    60 
       
    61 /* Just print the address is hex.  This is included for completeness even
       
    62    though both GDB and objdump provide their own (to print symbolic
       
    63    addresses).  */
       
    64 
       
    65 void
       
    66 generic_print_address (bfd_vma addr, struct disassemble_info *info)
       
    67 {
       
    68     (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
       
    69 }
       
    70 
       
    71 /* Just return the given address.  */
       
    72 
       
    73 int
       
    74 generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
       
    75 {
       
    76   return 1;
       
    77 }
       
    78 
       
    79 bfd_vma bfd_getl32 (const bfd_byte *addr)
       
    80 {
       
    81   unsigned long v;
       
    82 
       
    83   v = (unsigned long) addr[0];
       
    84   v |= (unsigned long) addr[1] << 8;
       
    85   v |= (unsigned long) addr[2] << 16;
       
    86   v |= (unsigned long) addr[3] << 24;
       
    87   return (bfd_vma) v;
       
    88 }
       
    89 
       
    90 bfd_vma bfd_getb32 (const bfd_byte *addr)
       
    91 {
       
    92   unsigned long v;
       
    93 
       
    94   v = (unsigned long) addr[0] << 24;
       
    95   v |= (unsigned long) addr[1] << 16;
       
    96   v |= (unsigned long) addr[2] << 8;
       
    97   v |= (unsigned long) addr[3];
       
    98   return (bfd_vma) v;
       
    99 }
       
   100 
       
   101 bfd_vma bfd_getl16 (const bfd_byte *addr)
       
   102 {
       
   103   unsigned long v;
       
   104 
       
   105   v = (unsigned long) addr[0];
       
   106   v |= (unsigned long) addr[1] << 8;
       
   107   return (bfd_vma) v;
       
   108 }
       
   109 
       
   110 bfd_vma bfd_getb16 (const bfd_byte *addr)
       
   111 {
       
   112   unsigned long v;
       
   113 
       
   114   v = (unsigned long) addr[0] << 24;
       
   115   v |= (unsigned long) addr[1] << 16;
       
   116   return (bfd_vma) v;
       
   117 }
       
   118 
       
   119 #ifdef TARGET_ARM
       
   120 static int
       
   121 print_insn_thumb1(bfd_vma pc, disassemble_info *info)
       
   122 {
       
   123   return print_insn_arm(pc | 1, info);
       
   124 }
       
   125 #endif
       
   126 
       
   127 /* Disassemble this for me please... (debugging). 'flags' has the following
       
   128    values:
       
   129     i386 - nonzero means 16 bit code
       
   130     arm  - bit 0 = thumb, bit 1 = reverse endian
       
   131     ppc  - nonzero means little endian
       
   132     other targets - unused
       
   133  */
       
   134 void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
       
   135 {
       
   136     target_ulong pc;
       
   137     int count;
       
   138     struct disassemble_info disasm_info;
       
   139     int (*print_insn)(bfd_vma pc, disassemble_info *info);
       
   140 
       
   141     INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
       
   142 
       
   143     disasm_info.read_memory_func = target_read_memory;
       
   144     disasm_info.buffer_vma = code;
       
   145     disasm_info.buffer_length = size;
       
   146 
       
   147 #ifdef TARGET_WORDS_BIGENDIAN
       
   148     disasm_info.endian = BFD_ENDIAN_BIG;
       
   149 #else
       
   150     disasm_info.endian = BFD_ENDIAN_LITTLE;
       
   151 #endif
       
   152 #if defined(TARGET_I386)
       
   153     if (flags == 2)
       
   154         disasm_info.mach = bfd_mach_x86_64;
       
   155     else if (flags == 1)
       
   156         disasm_info.mach = bfd_mach_i386_i8086;
       
   157     else
       
   158         disasm_info.mach = bfd_mach_i386_i386;
       
   159     print_insn = print_insn_i386;
       
   160 #elif defined(TARGET_ARM)
       
   161     if (flags & 1)
       
   162 	print_insn = print_insn_thumb1;
       
   163     else
       
   164 	print_insn = print_insn_arm;
       
   165     if (flags & 2) {
       
   166 #ifdef TARGET_WORDS_BIGENDIAN
       
   167         disasm_info.endian = BFD_ENDIAN_LITTLE;
       
   168 #else
       
   169         disasm_info.endian = BFD_ENDIAN_BIG;
       
   170 #endif
       
   171     }
       
   172 #elif defined(TARGET_SPARC)
       
   173     print_insn = print_insn_sparc;
       
   174 #ifdef TARGET_SPARC64
       
   175     disasm_info.mach = bfd_mach_sparc_v9b;
       
   176 #endif
       
   177 #elif defined(TARGET_PPC)
       
   178     if (flags >> 16)
       
   179         disasm_info.endian = BFD_ENDIAN_LITTLE;
       
   180     if (flags & 0xFFFF) {
       
   181         /* If we have a precise definitions of the instructions set, use it */
       
   182         disasm_info.mach = flags & 0xFFFF;
       
   183     } else {
       
   184 #ifdef TARGET_PPC64
       
   185         disasm_info.mach = bfd_mach_ppc64;
       
   186 #else
       
   187         disasm_info.mach = bfd_mach_ppc;
       
   188 #endif
       
   189     }
       
   190     print_insn = print_insn_ppc;
       
   191 #elif defined(TARGET_M68K)
       
   192     print_insn = print_insn_m68k;
       
   193 #elif defined(TARGET_MIPS)
       
   194 #ifdef TARGET_WORDS_BIGENDIAN
       
   195     print_insn = print_insn_big_mips;
       
   196 #else
       
   197     print_insn = print_insn_little_mips;
       
   198 #endif
       
   199 #elif defined(TARGET_SH4)
       
   200     disasm_info.mach = bfd_mach_sh4;
       
   201     print_insn = print_insn_sh;
       
   202 #elif defined(TARGET_ALPHA)
       
   203     disasm_info.mach = bfd_mach_alpha;
       
   204     print_insn = print_insn_alpha;
       
   205 #elif defined(TARGET_CRIS)
       
   206     disasm_info.mach = bfd_mach_cris_v32;
       
   207     print_insn = print_insn_crisv32;
       
   208 #else
       
   209     fprintf(out, "0x" TARGET_FMT_lx
       
   210 	    ": Asm output not supported on this arch\n", code);
       
   211     return;
       
   212 #endif
       
   213 
       
   214     for (pc = code; pc < code + size; pc += count) {
       
   215 	fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
       
   216 	count = print_insn(pc, &disasm_info);
       
   217 #if 0
       
   218         {
       
   219             int i;
       
   220             uint8_t b;
       
   221             fprintf(out, " {");
       
   222             for(i = 0; i < count; i++) {
       
   223                 target_read_memory(pc + i, &b, 1, &disasm_info);
       
   224                 fprintf(out, " %02x", b);
       
   225             }
       
   226             fprintf(out, " }");
       
   227         }
       
   228 #endif
       
   229 	fprintf(out, "\n");
       
   230 	if (count < 0)
       
   231 	    break;
       
   232     }
       
   233 }
       
   234 
       
   235 /* Disassemble this for me please... (debugging). */
       
   236 void disas(FILE *out, void *code, unsigned long size)
       
   237 {
       
   238     unsigned long pc;
       
   239     int count;
       
   240     struct disassemble_info disasm_info;
       
   241     int (*print_insn)(bfd_vma pc, disassemble_info *info);
       
   242 
       
   243     INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
       
   244 
       
   245     disasm_info.buffer = code;
       
   246     disasm_info.buffer_vma = (unsigned long)code;
       
   247     disasm_info.buffer_length = size;
       
   248 
       
   249 #ifdef WORDS_BIGENDIAN
       
   250     disasm_info.endian = BFD_ENDIAN_BIG;
       
   251 #else
       
   252     disasm_info.endian = BFD_ENDIAN_LITTLE;
       
   253 #endif
       
   254 #if defined(__i386__)
       
   255     disasm_info.mach = bfd_mach_i386_i386;
       
   256     print_insn = print_insn_i386;
       
   257 #elif defined(__x86_64__)
       
   258     disasm_info.mach = bfd_mach_x86_64;
       
   259     print_insn = print_insn_i386;
       
   260 #elif defined(__powerpc__)
       
   261     print_insn = print_insn_ppc;
       
   262 #elif defined(__alpha__)
       
   263     print_insn = print_insn_alpha;
       
   264 #elif defined(__sparc__)
       
   265     print_insn = print_insn_sparc;
       
   266 #if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
       
   267     disasm_info.mach = bfd_mach_sparc_v9b;
       
   268 #endif
       
   269 #elif defined(__arm__)
       
   270     print_insn = print_insn_arm;
       
   271 #elif defined(__MIPSEB__)
       
   272     print_insn = print_insn_big_mips;
       
   273 #elif defined(__MIPSEL__)
       
   274     print_insn = print_insn_little_mips;
       
   275 #elif defined(__m68k__)
       
   276     print_insn = print_insn_m68k;
       
   277 #elif defined(__s390__)
       
   278     print_insn = print_insn_s390;
       
   279 #elif defined(__hppa__)
       
   280     print_insn = print_insn_hppa;
       
   281 #else
       
   282     fprintf(out, "0x%lx: Asm output not supported on this arch\n",
       
   283 	    (long) code);
       
   284     return;
       
   285 #endif
       
   286     for (pc = (unsigned long)code; pc < (unsigned long)code + size; pc += count) {
       
   287 	fprintf(out, "0x%08lx:  ", pc);
       
   288 #ifdef __arm__
       
   289         /* since data is included in the code, it is better to
       
   290            display code data too */
       
   291         fprintf(out, "%08x  ", (int)bfd_getl32((const bfd_byte *)pc));
       
   292 #endif
       
   293 	count = print_insn(pc, &disasm_info);
       
   294 	fprintf(out, "\n");
       
   295 	if (count < 0)
       
   296 	    break;
       
   297     }
       
   298 }
       
   299 
       
   300 /* Look up symbol for debugging purpose.  Returns "" if unknown. */
       
   301 const char *lookup_symbol(target_ulong orig_addr)
       
   302 {
       
   303     const char *symbol = "";
       
   304     struct syminfo *s;
       
   305 
       
   306     for (s = syminfos; s; s = s->next) {
       
   307         symbol = s->lookup_symbol(s, orig_addr);
       
   308         if (symbol[0] != '\0') {
       
   309             break;
       
   310         }
       
   311     }
       
   312 
       
   313     return symbol;
       
   314 }
       
   315 
       
   316 #if !defined(CONFIG_USER_ONLY)
       
   317 
       
   318 void term_vprintf(const char *fmt, va_list ap);
       
   319 void term_printf(const char *fmt, ...);
       
   320 
       
   321 static int monitor_disas_is_physical;
       
   322 static CPUState *monitor_disas_env;
       
   323 
       
   324 static int
       
   325 monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
       
   326                      struct disassemble_info *info)
       
   327 {
       
   328     if (monitor_disas_is_physical) {
       
   329         cpu_physical_memory_rw(memaddr, myaddr, length, 0);
       
   330     } else {
       
   331         cpu_memory_rw_debug(monitor_disas_env, memaddr,myaddr, length, 0);
       
   332     }
       
   333     return 0;
       
   334 }
       
   335 
       
   336 static int monitor_fprintf(FILE *stream, const char *fmt, ...)
       
   337 {
       
   338     va_list ap;
       
   339     va_start(ap, fmt);
       
   340     term_vprintf(fmt, ap);
       
   341     va_end(ap);
       
   342     return 0;
       
   343 }
       
   344 
       
   345 void monitor_disas(CPUState *env,
       
   346                    target_ulong pc, int nb_insn, int is_physical, int flags)
       
   347 {
       
   348     int count, i;
       
   349     struct disassemble_info disasm_info;
       
   350     int (*print_insn)(bfd_vma pc, disassemble_info *info);
       
   351 
       
   352     INIT_DISASSEMBLE_INFO(disasm_info, NULL, monitor_fprintf);
       
   353 
       
   354     monitor_disas_env = env;
       
   355     monitor_disas_is_physical = is_physical;
       
   356     disasm_info.read_memory_func = monitor_read_memory;
       
   357 
       
   358     disasm_info.buffer_vma = pc;
       
   359 
       
   360 #ifdef TARGET_WORDS_BIGENDIAN
       
   361     disasm_info.endian = BFD_ENDIAN_BIG;
       
   362 #else
       
   363     disasm_info.endian = BFD_ENDIAN_LITTLE;
       
   364 #endif
       
   365 #if defined(TARGET_I386)
       
   366     if (flags == 2)
       
   367         disasm_info.mach = bfd_mach_x86_64;
       
   368     else if (flags == 1)
       
   369         disasm_info.mach = bfd_mach_i386_i8086;
       
   370     else
       
   371         disasm_info.mach = bfd_mach_i386_i386;
       
   372     print_insn = print_insn_i386;
       
   373 #elif defined(TARGET_ARM)
       
   374     print_insn = print_insn_arm;
       
   375 #elif defined(TARGET_ALPHA)
       
   376     print_insn = print_insn_alpha;
       
   377 #elif defined(TARGET_SPARC)
       
   378     print_insn = print_insn_sparc;
       
   379 #ifdef TARGET_SPARC64
       
   380     disasm_info.mach = bfd_mach_sparc_v9b;
       
   381 #endif
       
   382 #elif defined(TARGET_PPC)
       
   383 #ifdef TARGET_PPC64
       
   384     disasm_info.mach = bfd_mach_ppc64;
       
   385 #else
       
   386     disasm_info.mach = bfd_mach_ppc;
       
   387 #endif
       
   388     print_insn = print_insn_ppc;
       
   389 #elif defined(TARGET_M68K)
       
   390     print_insn = print_insn_m68k;
       
   391 #elif defined(TARGET_MIPS)
       
   392 #ifdef TARGET_WORDS_BIGENDIAN
       
   393     print_insn = print_insn_big_mips;
       
   394 #else
       
   395     print_insn = print_insn_little_mips;
       
   396 #endif
       
   397 #else
       
   398     term_printf("0x" TARGET_FMT_lx
       
   399 		": Asm output not supported on this arch\n", pc);
       
   400     return;
       
   401 #endif
       
   402 
       
   403     for(i = 0; i < nb_insn; i++) {
       
   404 	term_printf("0x" TARGET_FMT_lx ":  ", pc);
       
   405 	count = print_insn(pc, &disasm_info);
       
   406 	term_printf("\n");
       
   407 	if (count < 0)
       
   408 	    break;
       
   409         pc += count;
       
   410     }
       
   411 }
       
   412 #endif