1 /* General "disassemble this chunk" code.  Used for debugging. */
2 #include "qemu/osdep.h"
3 #include "disas/dis-asm.h"
4 #include "elf.h"
5 #include "qemu/qemu-print.h"
6 
7 #include "cpu.h"
8 #include "disas/disas.h"
9 #include "disas/capstone.h"
10 
11 typedef struct CPUDebug {
12     struct disassemble_info info;
13     CPUState *cpu;
14 } CPUDebug;
15 
16 /* Filled in by elfload.c.  Simplistic, but will do for now. */
17 struct syminfo *syminfos = NULL;
18 
19 /* Get LENGTH bytes from info's buffer, at target address memaddr.
20    Transfer them to myaddr.  */
21 int
buffer_read_memory(bfd_vma memaddr,bfd_byte * myaddr,int length,struct disassemble_info * info)22 buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
23                    struct disassemble_info *info)
24 {
25     if (memaddr < info->buffer_vma
26         || memaddr + length > info->buffer_vma + info->buffer_length)
27         /* Out of bounds.  Use EIO because GDB uses it.  */
28         return EIO;
29     memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
30     return 0;
31 }
32 
33 /* Get LENGTH bytes from info's buffer, at target address memaddr.
34    Transfer them to myaddr.  */
35 static int
target_read_memory(bfd_vma memaddr,bfd_byte * myaddr,int length,struct disassemble_info * info)36 target_read_memory (bfd_vma memaddr,
37                     bfd_byte *myaddr,
38                     int length,
39                     struct disassemble_info *info)
40 {
41     CPUDebug *s = container_of(info, CPUDebug, info);
42 
43     cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
44     return 0;
45 }
46 
47 /* Print an error message.  We can assume that this is in response to
48    an error return from buffer_read_memory.  */
49 void
perror_memory(int status,bfd_vma memaddr,struct disassemble_info * info)50 perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
51 {
52   if (status != EIO)
53     /* Can't happen.  */
54     (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
55   else
56     /* Actually, address between memaddr and memaddr + len was
57        out of bounds.  */
58     (*info->fprintf_func) (info->stream,
59 			   "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
60 }
61 
62 /* This could be in a separate file, to save minuscule amounts of space
63    in statically linked executables.  */
64 
65 /* Just print the address is hex.  This is included for completeness even
66    though both GDB and objdump provide their own (to print symbolic
67    addresses).  */
68 
69 void
generic_print_address(bfd_vma addr,struct disassemble_info * info)70 generic_print_address (bfd_vma addr, struct disassemble_info *info)
71 {
72     (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
73 }
74 
75 /* Print address in hex, truncated to the width of a host virtual address. */
76 static void
generic_print_host_address(bfd_vma addr,struct disassemble_info * info)77 generic_print_host_address(bfd_vma addr, struct disassemble_info *info)
78 {
79     uint64_t mask = ~0ULL >> (64 - (sizeof(void *) * 8));
80     generic_print_address(addr & mask, info);
81 }
82 
83 /* Just return the given address.  */
84 
85 int
generic_symbol_at_address(bfd_vma addr,struct disassemble_info * info)86 generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
87 {
88   return 1;
89 }
90 
bfd_getl64(const bfd_byte * addr)91 bfd_vma bfd_getl64 (const bfd_byte *addr)
92 {
93   unsigned long long v;
94 
95   v = (unsigned long long) addr[0];
96   v |= (unsigned long long) addr[1] << 8;
97   v |= (unsigned long long) addr[2] << 16;
98   v |= (unsigned long long) addr[3] << 24;
99   v |= (unsigned long long) addr[4] << 32;
100   v |= (unsigned long long) addr[5] << 40;
101   v |= (unsigned long long) addr[6] << 48;
102   v |= (unsigned long long) addr[7] << 56;
103   return (bfd_vma) v;
104 }
105 
bfd_getl32(const bfd_byte * addr)106 bfd_vma bfd_getl32 (const bfd_byte *addr)
107 {
108   unsigned long v;
109 
110   v = (unsigned long) addr[0];
111   v |= (unsigned long) addr[1] << 8;
112   v |= (unsigned long) addr[2] << 16;
113   v |= (unsigned long) addr[3] << 24;
114   return (bfd_vma) v;
115 }
116 
bfd_getb32(const bfd_byte * addr)117 bfd_vma bfd_getb32 (const bfd_byte *addr)
118 {
119   unsigned long v;
120 
121   v = (unsigned long) addr[0] << 24;
122   v |= (unsigned long) addr[1] << 16;
123   v |= (unsigned long) addr[2] << 8;
124   v |= (unsigned long) addr[3];
125   return (bfd_vma) v;
126 }
127 
bfd_getl16(const bfd_byte * addr)128 bfd_vma bfd_getl16 (const bfd_byte *addr)
129 {
130   unsigned long v;
131 
132   v = (unsigned long) addr[0];
133   v |= (unsigned long) addr[1] << 8;
134   return (bfd_vma) v;
135 }
136 
bfd_getb16(const bfd_byte * addr)137 bfd_vma bfd_getb16 (const bfd_byte *addr)
138 {
139   unsigned long v;
140 
141   v = (unsigned long) addr[0] << 24;
142   v |= (unsigned long) addr[1] << 16;
143   return (bfd_vma) v;
144 }
145 
print_insn_objdump(bfd_vma pc,disassemble_info * info,const char * prefix)146 static int print_insn_objdump(bfd_vma pc, disassemble_info *info,
147                               const char *prefix)
148 {
149     int i, n = info->buffer_length;
150     uint8_t *buf = g_malloc(n);
151 
152     info->read_memory_func(pc, buf, n, info);
153 
154     for (i = 0; i < n; ++i) {
155         if (i % 32 == 0) {
156             info->fprintf_func(info->stream, "\n%s: ", prefix);
157         }
158         info->fprintf_func(info->stream, "%02x", buf[i]);
159     }
160 
161     g_free(buf);
162     return n;
163 }
164 
print_insn_od_host(bfd_vma pc,disassemble_info * info)165 static int print_insn_od_host(bfd_vma pc, disassemble_info *info)
166 {
167     return print_insn_objdump(pc, info, "OBJD-H");
168 }
169 
print_insn_od_target(bfd_vma pc,disassemble_info * info)170 static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
171 {
172     return print_insn_objdump(pc, info, "OBJD-T");
173 }
174 
175 #ifdef CONFIG_CAPSTONE
176 /* Temporary storage for the capstone library.  This will be alloced via
177    malloc with a size private to the library; thus there's no reason not
178    to share this across calls and across host vs target disassembly.  */
179 static __thread cs_insn *cap_insn;
180 
181 /* Initialize the Capstone library.  */
182 /* ??? It would be nice to cache this.  We would need one handle for the
183    host and one for the target.  For most targets we can reset specific
184    parameters via cs_option(CS_OPT_MODE, new_mode), but we cannot change
185    CS_ARCH_* in this way.  Thus we would need to be able to close and
186    re-open the target handle with a different arch for the target in order
187    to handle AArch64 vs AArch32 mode switching.  */
cap_disas_start(disassemble_info * info,csh * handle)188 static cs_err cap_disas_start(disassemble_info *info, csh *handle)
189 {
190     cs_mode cap_mode = info->cap_mode;
191     cs_err err;
192 
193     cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN
194                  : CS_MODE_LITTLE_ENDIAN);
195 
196     err = cs_open(info->cap_arch, cap_mode, handle);
197     if (err != CS_ERR_OK) {
198         return err;
199     }
200 
201     /* ??? There probably ought to be a better place to put this.  */
202     if (info->cap_arch == CS_ARCH_X86) {
203         /* We don't care about errors (if for some reason the library
204            is compiled without AT&T syntax); the user will just have
205            to deal with the Intel syntax.  */
206         cs_option(*handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
207     }
208 
209     /* "Disassemble" unknown insns as ".byte W,X,Y,Z".  */
210     cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON);
211 
212     /* Allocate temp space for cs_disasm_iter.  */
213     if (cap_insn == NULL) {
214         cap_insn = cs_malloc(*handle);
215         if (cap_insn == NULL) {
216             cs_close(handle);
217             return CS_ERR_MEM;
218         }
219     }
220     return CS_ERR_OK;
221 }
222 
cap_dump_insn_units(disassemble_info * info,cs_insn * insn,int i,int n)223 static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn,
224                                 int i, int n)
225 {
226     fprintf_function print = info->fprintf_func;
227     FILE *stream = info->stream;
228 
229     switch (info->cap_insn_unit) {
230     case 4:
231         if (info->endian == BFD_ENDIAN_BIG) {
232             for (; i < n; i += 4) {
233                 print(stream, " %08x", ldl_be_p(insn->bytes + i));
234 
235             }
236         } else {
237             for (; i < n; i += 4) {
238                 print(stream, " %08x", ldl_le_p(insn->bytes + i));
239             }
240         }
241         break;
242 
243     case 2:
244         if (info->endian == BFD_ENDIAN_BIG) {
245             for (; i < n; i += 2) {
246                 print(stream, " %04x", lduw_be_p(insn->bytes + i));
247             }
248         } else {
249             for (; i < n; i += 2) {
250                 print(stream, " %04x", lduw_le_p(insn->bytes + i));
251             }
252         }
253         break;
254 
255     default:
256         for (; i < n; i++) {
257             print(stream, " %02x", insn->bytes[i]);
258         }
259         break;
260     }
261 }
262 
cap_dump_insn(disassemble_info * info,cs_insn * insn)263 static void cap_dump_insn(disassemble_info *info, cs_insn *insn)
264 {
265     fprintf_function print = info->fprintf_func;
266     int i, n, split;
267 
268     print(info->stream, "0x%08" PRIx64 ": ", insn->address);
269 
270     n = insn->size;
271     split = info->cap_insn_split;
272 
273     /* Dump the first SPLIT bytes of the instruction.  */
274     cap_dump_insn_units(info, insn, 0, MIN(n, split));
275 
276     /* Add padding up to SPLIT so that mnemonics line up.  */
277     if (n < split) {
278         int width = (split - n) / info->cap_insn_unit;
279         width *= (2 * info->cap_insn_unit + 1);
280         print(info->stream, "%*s", width, "");
281     }
282 
283     /* Print the actual instruction.  */
284     print(info->stream, "  %-8s %s\n", insn->mnemonic, insn->op_str);
285 
286     /* Dump any remaining part of the insn on subsequent lines.  */
287     for (i = split; i < n; i += split) {
288         print(info->stream, "0x%08" PRIx64 ": ", insn->address + i);
289         cap_dump_insn_units(info, insn, i, MIN(n, i + split));
290         print(info->stream, "\n");
291     }
292 }
293 
294 /* Disassemble SIZE bytes at PC for the target.  */
cap_disas_target(disassemble_info * info,uint64_t pc,size_t size)295 static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
296 {
297     uint8_t cap_buf[1024];
298     csh handle;
299     cs_insn *insn;
300     size_t csize = 0;
301 
302     if (cap_disas_start(info, &handle) != CS_ERR_OK) {
303         return false;
304     }
305     insn = cap_insn;
306 
307     while (1) {
308         size_t tsize = MIN(sizeof(cap_buf) - csize, size);
309         const uint8_t *cbuf = cap_buf;
310 
311         target_read_memory(pc + csize, cap_buf + csize, tsize, info);
312         csize += tsize;
313         size -= tsize;
314 
315         while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
316            cap_dump_insn(info, insn);
317         }
318 
319         /* If the target memory is not consumed, go back for more... */
320         if (size != 0) {
321             /* ... taking care to move any remaining fractional insn
322                to the beginning of the buffer.  */
323             if (csize != 0) {
324                 memmove(cap_buf, cbuf, csize);
325             }
326             continue;
327         }
328 
329         /* Since the target memory is consumed, we should not have
330            a remaining fractional insn.  */
331         if (csize != 0) {
332             (*info->fprintf_func)(info->stream,
333                 "Disassembler disagrees with translator "
334                 "over instruction decoding\n"
335                 "Please report this to qemu-devel@nongnu.org\n");
336         }
337         break;
338     }
339 
340     cs_close(&handle);
341     return true;
342 }
343 
344 /* Disassemble SIZE bytes at CODE for the host.  */
cap_disas_host(disassemble_info * info,void * code,size_t size)345 static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
346 {
347     csh handle;
348     const uint8_t *cbuf;
349     cs_insn *insn;
350     uint64_t pc;
351 
352     if (cap_disas_start(info, &handle) != CS_ERR_OK) {
353         return false;
354     }
355     insn = cap_insn;
356 
357     cbuf = code;
358     pc = (uintptr_t)code;
359 
360     while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
361        cap_dump_insn(info, insn);
362     }
363     if (size != 0) {
364         (*info->fprintf_func)(info->stream,
365             "Disassembler disagrees with TCG over instruction encoding\n"
366             "Please report this to qemu-devel@nongnu.org\n");
367     }
368 
369     cs_close(&handle);
370     return true;
371 }
372 
373 #if !defined(CONFIG_USER_ONLY)
374 /* Disassemble COUNT insns at PC for the target.  */
cap_disas_monitor(disassemble_info * info,uint64_t pc,int count)375 static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
376 {
377     uint8_t cap_buf[32];
378     csh handle;
379     cs_insn *insn;
380     size_t csize = 0;
381 
382     if (cap_disas_start(info, &handle) != CS_ERR_OK) {
383         return false;
384     }
385     insn = cap_insn;
386 
387     while (1) {
388         /* We want to read memory for one insn, but generically we do not
389            know how much memory that is.  We have a small buffer which is
390            known to be sufficient for all supported targets.  Try to not
391            read beyond the page, Just In Case.  For even more simplicity,
392            ignore the actual target page size and use a 1k boundary.  If
393            that turns out to be insufficient, we'll come back around the
394            loop and read more.  */
395         uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024);
396         size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc);
397         const uint8_t *cbuf = cap_buf;
398 
399         /* Make certain that we can make progress.  */
400         assert(tsize != 0);
401         info->read_memory_func(pc, cap_buf + csize, tsize, info);
402         csize += tsize;
403 
404         if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
405             cap_dump_insn(info, insn);
406             if (--count <= 0) {
407                 break;
408             }
409         }
410         memmove(cap_buf, cbuf, csize);
411     }
412 
413     cs_close(&handle);
414     return true;
415 }
416 #endif /* !CONFIG_USER_ONLY */
417 #else
418 # define cap_disas_target(i, p, s)  false
419 # define cap_disas_host(i, p, s)  false
420 # define cap_disas_monitor(i, p, c)  false
421 # define cap_disas_plugin(i, p, c) false
422 #endif /* CONFIG_CAPSTONE */
423 
424 /* Disassemble this for me please... (debugging).  */
target_disas(FILE * out,CPUState * cpu,target_ulong code,target_ulong size)425 void target_disas(FILE *out, CPUState *cpu, target_ulong code,
426                   target_ulong size)
427 {
428     CPUClass *cc = CPU_GET_CLASS(cpu);
429     target_ulong pc;
430     int count;
431     CPUDebug s;
432 
433     INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
434 
435     s.cpu = cpu;
436     s.info.read_memory_func = target_read_memory;
437     s.info.buffer_vma = code;
438     s.info.buffer_length = size;
439     s.info.print_address_func = generic_print_address;
440     s.info.cap_arch = -1;
441     s.info.cap_mode = 0;
442     s.info.cap_insn_unit = 4;
443     s.info.cap_insn_split = 4;
444 
445 #ifdef TARGET_WORDS_BIGENDIAN
446     s.info.endian = BFD_ENDIAN_BIG;
447 #else
448     s.info.endian = BFD_ENDIAN_LITTLE;
449 #endif
450 
451     if (cc->disas_set_info) {
452         cc->disas_set_info(cpu, &s.info);
453     }
454 
455     if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
456         return;
457     }
458 
459     if (s.info.print_insn == NULL) {
460         s.info.print_insn = print_insn_od_target;
461     }
462 
463     for (pc = code; size > 0; pc += count, size -= count) {
464 	fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
465 	count = s.info.print_insn(pc, &s.info);
466 	fprintf(out, "\n");
467 	if (count < 0)
468 	    break;
469         if (size < count) {
470             fprintf(out,
471                     "Disassembler disagrees with translator over instruction "
472                     "decoding\n"
473                     "Please report this to qemu-devel@nongnu.org\n");
474             break;
475         }
476     }
477 }
478 
479 static __thread GString plugin_disas_output;
480 
plugin_printf(FILE * stream,const char * fmt,...)481 static int plugin_printf(FILE *stream, const char *fmt, ...)
482 {
483     va_list va;
484     GString *s = &plugin_disas_output;
485     int initial_len = s->len;
486 
487     va_start(va, fmt);
488     g_string_append_vprintf(s, fmt, va);
489     va_end(va);
490 
491     return s->len - initial_len;
492 }
493 
plugin_print_address(bfd_vma addr,struct disassemble_info * info)494 static void plugin_print_address(bfd_vma addr, struct disassemble_info *info)
495 {
496     /* does nothing */
497 }
498 
499 
500 #ifdef CONFIG_CAPSTONE
501 /* Disassemble a single instruction directly into plugin output */
502 static
cap_disas_plugin(disassemble_info * info,uint64_t pc,size_t size)503 bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size)
504 {
505     uint8_t cap_buf[1024];
506     csh handle;
507     cs_insn *insn;
508     size_t csize = 0;
509     int count;
510     GString *s = &plugin_disas_output;
511 
512     if (cap_disas_start(info, &handle) != CS_ERR_OK) {
513         return false;
514     }
515     insn = cap_insn;
516 
517     size_t tsize = MIN(sizeof(cap_buf) - csize, size);
518     const uint8_t *cbuf = cap_buf;
519     target_read_memory(pc, cap_buf, tsize, info);
520 
521     count = cs_disasm(handle, cbuf, size, 0, 1, &insn);
522 
523     if (count) {
524         g_string_printf(s, "%s %s", insn->mnemonic, insn->op_str);
525     } else {
526         g_string_printf(s, "cs_disasm failed");
527     }
528 
529     cs_close(&handle);
530     return true;
531 }
532 #endif
533 
534 /*
535  * We should only be dissembling one instruction at a time here. If
536  * there is left over it usually indicates the front end has read more
537  * bytes than it needed.
538  */
plugin_disas(CPUState * cpu,uint64_t addr,size_t size)539 char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size)
540 {
541     CPUClass *cc = CPU_GET_CLASS(cpu);
542     int count;
543     CPUDebug s;
544     GString *ds = g_string_set_size(&plugin_disas_output, 0);
545 
546     g_assert(ds == &plugin_disas_output);
547 
548     INIT_DISASSEMBLE_INFO(s.info, NULL, plugin_printf);
549 
550     s.cpu = cpu;
551     s.info.read_memory_func = target_read_memory;
552     s.info.buffer_vma = addr;
553     s.info.buffer_length = size;
554     s.info.print_address_func = plugin_print_address;
555     s.info.cap_arch = -1;
556     s.info.cap_mode = 0;
557     s.info.cap_insn_unit = 4;
558     s.info.cap_insn_split = 4;
559 
560 #ifdef TARGET_WORDS_BIGENDIAN
561     s.info.endian = BFD_ENDIAN_BIG;
562 #else
563     s.info.endian = BFD_ENDIAN_LITTLE;
564 #endif
565 
566     if (cc->disas_set_info) {
567         cc->disas_set_info(cpu, &s.info);
568     }
569 
570     if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) {
571         return g_strdup(ds->str);
572     }
573 
574     if (s.info.print_insn == NULL) {
575         s.info.print_insn = print_insn_od_target;
576     }
577 
578     count = s.info.print_insn(addr, &s.info);
579 
580     /* The decoder probably read more than it needed it's not critical */
581     if (count < size) {
582         warn_report("%s: %zu bytes left over", __func__, size - count);
583     }
584 
585     return g_strdup(ds->str);
586 }
587 
588 /* Disassemble this for me please... (debugging). */
disas(FILE * out,void * code,unsigned long size)589 void disas(FILE *out, void *code, unsigned long size)
590 {
591     uintptr_t pc;
592     int count;
593     CPUDebug s;
594     int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
595 
596     INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
597     s.info.print_address_func = generic_print_host_address;
598 
599     s.info.buffer = code;
600     s.info.buffer_vma = (uintptr_t)code;
601     s.info.buffer_length = size;
602     s.info.cap_arch = -1;
603     s.info.cap_mode = 0;
604     s.info.cap_insn_unit = 4;
605     s.info.cap_insn_split = 4;
606 
607 #ifdef HOST_WORDS_BIGENDIAN
608     s.info.endian = BFD_ENDIAN_BIG;
609 #else
610     s.info.endian = BFD_ENDIAN_LITTLE;
611 #endif
612 #if defined(CONFIG_TCG_INTERPRETER)
613     print_insn = print_insn_tci;
614 #elif defined(__i386__)
615     s.info.mach = bfd_mach_i386_i386;
616     print_insn = print_insn_i386;
617     s.info.cap_arch = CS_ARCH_X86;
618     s.info.cap_mode = CS_MODE_32;
619     s.info.cap_insn_unit = 1;
620     s.info.cap_insn_split = 8;
621 #elif defined(__x86_64__)
622     s.info.mach = bfd_mach_x86_64;
623     print_insn = print_insn_i386;
624     s.info.cap_arch = CS_ARCH_X86;
625     s.info.cap_mode = CS_MODE_64;
626     s.info.cap_insn_unit = 1;
627     s.info.cap_insn_split = 8;
628 #elif defined(_ARCH_PPC)
629     s.info.disassembler_options = (char *)"any";
630     print_insn = print_insn_ppc;
631     s.info.cap_arch = CS_ARCH_PPC;
632 # ifdef _ARCH_PPC64
633     s.info.cap_mode = CS_MODE_64;
634 # endif
635 #elif defined(__riscv) && defined(CONFIG_RISCV_DIS)
636 #if defined(_ILP32) || (__riscv_xlen == 32)
637     print_insn = print_insn_riscv32;
638 #elif defined(_LP64)
639     print_insn = print_insn_riscv64;
640 #else
641 #error unsupported RISC-V ABI
642 #endif
643 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
644     print_insn = print_insn_arm_a64;
645     s.info.cap_arch = CS_ARCH_ARM64;
646 #elif defined(__alpha__)
647     print_insn = print_insn_alpha;
648 #elif defined(__sparc__)
649     print_insn = print_insn_sparc;
650     s.info.mach = bfd_mach_sparc_v9b;
651 #elif defined(__arm__)
652     print_insn = print_insn_arm;
653     s.info.cap_arch = CS_ARCH_ARM;
654     /* TCG only generates code for arm mode.  */
655 #elif defined(__MIPSEB__)
656     print_insn = print_insn_big_mips;
657 #elif defined(__MIPSEL__)
658     print_insn = print_insn_little_mips;
659 #elif defined(__m68k__)
660     print_insn = print_insn_m68k;
661 #elif defined(__s390__)
662     print_insn = print_insn_s390;
663 #elif defined(__hppa__)
664     print_insn = print_insn_hppa;
665 #endif
666 
667     if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
668         return;
669     }
670 
671     if (print_insn == NULL) {
672         print_insn = print_insn_od_host;
673     }
674     for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
675         fprintf(out, "0x%08" PRIxPTR ":  ", pc);
676         count = print_insn(pc, &s.info);
677 	fprintf(out, "\n");
678 	if (count < 0)
679 	    break;
680     }
681 }
682 
683 /* Look up symbol for debugging purpose.  Returns "" if unknown. */
lookup_symbol(target_ulong orig_addr)684 const char *lookup_symbol(target_ulong orig_addr)
685 {
686     const char *symbol = "";
687     struct syminfo *s;
688 
689     for (s = syminfos; s; s = s->next) {
690         symbol = s->lookup_symbol(s, orig_addr);
691         if (symbol[0] != '\0') {
692             break;
693         }
694     }
695 
696     return symbol;
697 }
698 
699 #if !defined(CONFIG_USER_ONLY)
700 
701 #include "monitor/monitor.h"
702 
703 static int
physical_read_memory(bfd_vma memaddr,bfd_byte * myaddr,int length,struct disassemble_info * info)704 physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
705                      struct disassemble_info *info)
706 {
707     CPUDebug *s = container_of(info, CPUDebug, info);
708 
709     address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
710                        myaddr, length);
711     return 0;
712 }
713 
714 /* Disassembler for the monitor.  */
monitor_disas(Monitor * mon,CPUState * cpu,target_ulong pc,int nb_insn,int is_physical)715 void monitor_disas(Monitor *mon, CPUState *cpu,
716                    target_ulong pc, int nb_insn, int is_physical)
717 {
718     CPUClass *cc = CPU_GET_CLASS(cpu);
719     int count, i;
720     CPUDebug s;
721 
722     INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf);
723 
724     s.cpu = cpu;
725     s.info.read_memory_func
726         = (is_physical ? physical_read_memory : target_read_memory);
727     s.info.print_address_func = generic_print_address;
728     s.info.buffer_vma = pc;
729     s.info.cap_arch = -1;
730     s.info.cap_mode = 0;
731     s.info.cap_insn_unit = 4;
732     s.info.cap_insn_split = 4;
733 
734 #ifdef TARGET_WORDS_BIGENDIAN
735     s.info.endian = BFD_ENDIAN_BIG;
736 #else
737     s.info.endian = BFD_ENDIAN_LITTLE;
738 #endif
739 
740     if (cc->disas_set_info) {
741         cc->disas_set_info(cpu, &s.info);
742     }
743 
744     if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
745         return;
746     }
747 
748     if (!s.info.print_insn) {
749         monitor_printf(mon, "0x" TARGET_FMT_lx
750                        ": Asm output not supported on this arch\n", pc);
751         return;
752     }
753 
754     for(i = 0; i < nb_insn; i++) {
755 	monitor_printf(mon, "0x" TARGET_FMT_lx ":  ", pc);
756         count = s.info.print_insn(pc, &s.info);
757 	monitor_printf(mon, "\n");
758 	if (count < 0)
759 	    break;
760         pc += count;
761     }
762 }
763 #endif
764