OSDN Git Service

Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-tcg-plugins-150520...
[qmiga/qemu.git] / disas.c
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
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
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
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
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
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
86 generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
87 {
88   return 1;
89 }
90
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
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
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
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
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
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
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
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.  */
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
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
263 static void cap_dump_insn(disassemble_info *info, cs_insn *insn,
264                           const char *note)
265 {
266     fprintf_function print = info->fprintf_func;
267     int i, n, split;
268
269     print(info->stream, "0x%08" PRIx64 ": ", insn->address);
270
271     n = insn->size;
272     split = info->cap_insn_split;
273
274     /* Dump the first SPLIT bytes of the instruction.  */
275     cap_dump_insn_units(info, insn, 0, MIN(n, split));
276
277     /* Add padding up to SPLIT so that mnemonics line up.  */
278     if (n < split) {
279         int width = (split - n) / info->cap_insn_unit;
280         width *= (2 * info->cap_insn_unit + 1);
281         print(info->stream, "%*s", width, "");
282     }
283
284     /* Print the actual instruction.  */
285     print(info->stream, "  %-8s %s", insn->mnemonic, insn->op_str);
286     if (note) {
287         print(info->stream, "\t\t%s", note);
288     }
289     print(info->stream, "\n");
290
291     /* Dump any remaining part of the insn on subsequent lines.  */
292     for (i = split; i < n; i += split) {
293         print(info->stream, "0x%08" PRIx64 ": ", insn->address + i);
294         cap_dump_insn_units(info, insn, i, MIN(n, i + split));
295         print(info->stream, "\n");
296     }
297 }
298
299 /* Disassemble SIZE bytes at PC for the target.  */
300 static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
301 {
302     uint8_t cap_buf[1024];
303     csh handle;
304     cs_insn *insn;
305     size_t csize = 0;
306
307     if (cap_disas_start(info, &handle) != CS_ERR_OK) {
308         return false;
309     }
310     insn = cap_insn;
311
312     while (1) {
313         size_t tsize = MIN(sizeof(cap_buf) - csize, size);
314         const uint8_t *cbuf = cap_buf;
315
316         target_read_memory(pc + csize, cap_buf + csize, tsize, info);
317         csize += tsize;
318         size -= tsize;
319
320         while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
321             cap_dump_insn(info, insn, NULL);
322         }
323
324         /* If the target memory is not consumed, go back for more... */
325         if (size != 0) {
326             /* ... taking care to move any remaining fractional insn
327                to the beginning of the buffer.  */
328             if (csize != 0) {
329                 memmove(cap_buf, cbuf, csize);
330             }
331             continue;
332         }
333
334         /* Since the target memory is consumed, we should not have
335            a remaining fractional insn.  */
336         if (csize != 0) {
337             (*info->fprintf_func)(info->stream,
338                 "Disassembler disagrees with translator "
339                 "over instruction decoding\n"
340                 "Please report this to qemu-devel@nongnu.org\n");
341         }
342         break;
343     }
344
345     cs_close(&handle);
346     return true;
347 }
348
349 /* Disassemble SIZE bytes at CODE for the host.  */
350 static bool cap_disas_host(disassemble_info *info, void *code, size_t size,
351                            const char *note)
352 {
353     csh handle;
354     const uint8_t *cbuf;
355     cs_insn *insn;
356     uint64_t pc;
357
358     if (cap_disas_start(info, &handle) != CS_ERR_OK) {
359         return false;
360     }
361     insn = cap_insn;
362
363     cbuf = code;
364     pc = (uintptr_t)code;
365
366     while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
367         cap_dump_insn(info, insn, note);
368         note = NULL;
369     }
370     if (size != 0) {
371         (*info->fprintf_func)(info->stream,
372             "Disassembler disagrees with TCG over instruction encoding\n"
373             "Please report this to qemu-devel@nongnu.org\n");
374     }
375
376     cs_close(&handle);
377     return true;
378 }
379
380 #if !defined(CONFIG_USER_ONLY)
381 /* Disassemble COUNT insns at PC for the target.  */
382 static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
383 {
384     uint8_t cap_buf[32];
385     csh handle;
386     cs_insn *insn;
387     size_t csize = 0;
388
389     if (cap_disas_start(info, &handle) != CS_ERR_OK) {
390         return false;
391     }
392     insn = cap_insn;
393
394     while (1) {
395         /* We want to read memory for one insn, but generically we do not
396            know how much memory that is.  We have a small buffer which is
397            known to be sufficient for all supported targets.  Try to not
398            read beyond the page, Just In Case.  For even more simplicity,
399            ignore the actual target page size and use a 1k boundary.  If
400            that turns out to be insufficient, we'll come back around the
401            loop and read more.  */
402         uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024);
403         size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc);
404         const uint8_t *cbuf = cap_buf;
405
406         /* Make certain that we can make progress.  */
407         assert(tsize != 0);
408         info->read_memory_func(pc, cap_buf + csize, tsize, info);
409         csize += tsize;
410
411         if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
412             cap_dump_insn(info, insn, NULL);
413             if (--count <= 0) {
414                 break;
415             }
416         }
417         memmove(cap_buf, cbuf, csize);
418     }
419
420     cs_close(&handle);
421     return true;
422 }
423 #endif /* !CONFIG_USER_ONLY */
424 #else
425 # define cap_disas_target(i, p, s)  false
426 # define cap_disas_host(i, p, s, n)  false
427 # define cap_disas_monitor(i, p, c)  false
428 # define cap_disas_plugin(i, p, c) false
429 #endif /* CONFIG_CAPSTONE */
430
431 /* Disassemble this for me please... (debugging).  */
432 void target_disas(FILE *out, CPUState *cpu, target_ulong code,
433                   target_ulong size)
434 {
435     CPUClass *cc = CPU_GET_CLASS(cpu);
436     target_ulong pc;
437     int count;
438     CPUDebug s;
439
440     INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
441
442     s.cpu = cpu;
443     s.info.read_memory_func = target_read_memory;
444     s.info.buffer_vma = code;
445     s.info.buffer_length = size;
446     s.info.print_address_func = generic_print_address;
447     s.info.cap_arch = -1;
448     s.info.cap_mode = 0;
449     s.info.cap_insn_unit = 4;
450     s.info.cap_insn_split = 4;
451
452 #ifdef TARGET_WORDS_BIGENDIAN
453     s.info.endian = BFD_ENDIAN_BIG;
454 #else
455     s.info.endian = BFD_ENDIAN_LITTLE;
456 #endif
457
458     if (cc->disas_set_info) {
459         cc->disas_set_info(cpu, &s.info);
460     }
461
462     if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
463         return;
464     }
465
466     if (s.info.print_insn == NULL) {
467         s.info.print_insn = print_insn_od_target;
468     }
469
470     for (pc = code; size > 0; pc += count, size -= count) {
471         fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
472         count = s.info.print_insn(pc, &s.info);
473         fprintf(out, "\n");
474         if (count < 0)
475             break;
476         if (size < count) {
477             fprintf(out,
478                     "Disassembler disagrees with translator over instruction "
479                     "decoding\n"
480                     "Please report this to qemu-devel@nongnu.org\n");
481             break;
482         }
483     }
484 }
485
486 static __thread GString plugin_disas_output;
487
488 static int plugin_printf(FILE *stream, const char *fmt, ...)
489 {
490     va_list va;
491     GString *s = &plugin_disas_output;
492     int initial_len = s->len;
493
494     va_start(va, fmt);
495     g_string_append_vprintf(s, fmt, va);
496     va_end(va);
497
498     return s->len - initial_len;
499 }
500
501 static void plugin_print_address(bfd_vma addr, struct disassemble_info *info)
502 {
503     /* does nothing */
504 }
505
506
507 #ifdef CONFIG_CAPSTONE
508 /* Disassemble a single instruction directly into plugin output */
509 static
510 bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size)
511 {
512     uint8_t cap_buf[1024];
513     csh handle;
514     cs_insn *insn;
515     size_t csize = 0;
516     int count;
517     GString *s = &plugin_disas_output;
518
519     if (cap_disas_start(info, &handle) != CS_ERR_OK) {
520         return false;
521     }
522     insn = cap_insn;
523
524     size_t tsize = MIN(sizeof(cap_buf) - csize, size);
525     const uint8_t *cbuf = cap_buf;
526     target_read_memory(pc, cap_buf, tsize, info);
527
528     count = cs_disasm(handle, cbuf, size, 0, 1, &insn);
529
530     if (count) {
531         g_string_printf(s, "%s %s", insn->mnemonic, insn->op_str);
532     } else {
533         g_string_printf(s, "cs_disasm failed");
534     }
535
536     cs_close(&handle);
537     return true;
538 }
539 #endif
540
541 /*
542  * We should only be dissembling one instruction at a time here. If
543  * there is left over it usually indicates the front end has read more
544  * bytes than it needed.
545  */
546 char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size)
547 {
548     CPUClass *cc = CPU_GET_CLASS(cpu);
549     int count;
550     CPUDebug s;
551     GString *ds = g_string_set_size(&plugin_disas_output, 0);
552
553     g_assert(ds == &plugin_disas_output);
554
555     INIT_DISASSEMBLE_INFO(s.info, NULL, plugin_printf);
556
557     s.cpu = cpu;
558     s.info.read_memory_func = target_read_memory;
559     s.info.buffer_vma = addr;
560     s.info.buffer_length = size;
561     s.info.print_address_func = plugin_print_address;
562     s.info.cap_arch = -1;
563     s.info.cap_mode = 0;
564     s.info.cap_insn_unit = 4;
565     s.info.cap_insn_split = 4;
566
567 #ifdef TARGET_WORDS_BIGENDIAN
568     s.info.endian = BFD_ENDIAN_BIG;
569 #else
570     s.info.endian = BFD_ENDIAN_LITTLE;
571 #endif
572
573     if (cc->disas_set_info) {
574         cc->disas_set_info(cpu, &s.info);
575     }
576
577     if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) {
578         return g_strdup(ds->str);
579     }
580
581     if (s.info.print_insn == NULL) {
582         s.info.print_insn = print_insn_od_target;
583     }
584
585     count = s.info.print_insn(addr, &s.info);
586
587     /* The decoder probably read more than it needed it's not critical */
588     if (count < size) {
589         warn_report("%s: %zu bytes left over", __func__, size - count);
590     }
591
592     return g_strdup(ds->str);
593 }
594
595 /* Disassemble this for me please... (debugging). */
596 void disas(FILE *out, void *code, unsigned long size, const char *note)
597 {
598     uintptr_t pc;
599     int count;
600     CPUDebug s;
601     int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
602
603     INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
604     s.info.print_address_func = generic_print_host_address;
605
606     s.info.buffer = code;
607     s.info.buffer_vma = (uintptr_t)code;
608     s.info.buffer_length = size;
609     s.info.cap_arch = -1;
610     s.info.cap_mode = 0;
611     s.info.cap_insn_unit = 4;
612     s.info.cap_insn_split = 4;
613
614 #ifdef HOST_WORDS_BIGENDIAN
615     s.info.endian = BFD_ENDIAN_BIG;
616 #else
617     s.info.endian = BFD_ENDIAN_LITTLE;
618 #endif
619 #if defined(CONFIG_TCG_INTERPRETER)
620     print_insn = print_insn_tci;
621 #elif defined(__i386__)
622     s.info.mach = bfd_mach_i386_i386;
623     print_insn = print_insn_i386;
624     s.info.cap_arch = CS_ARCH_X86;
625     s.info.cap_mode = CS_MODE_32;
626     s.info.cap_insn_unit = 1;
627     s.info.cap_insn_split = 8;
628 #elif defined(__x86_64__)
629     s.info.mach = bfd_mach_x86_64;
630     print_insn = print_insn_i386;
631     s.info.cap_arch = CS_ARCH_X86;
632     s.info.cap_mode = CS_MODE_64;
633     s.info.cap_insn_unit = 1;
634     s.info.cap_insn_split = 8;
635 #elif defined(_ARCH_PPC)
636     s.info.disassembler_options = (char *)"any";
637     print_insn = print_insn_ppc;
638     s.info.cap_arch = CS_ARCH_PPC;
639 # ifdef _ARCH_PPC64
640     s.info.cap_mode = CS_MODE_64;
641 # endif
642 #elif defined(__riscv) && defined(CONFIG_RISCV_DIS)
643 #if defined(_ILP32) || (__riscv_xlen == 32)
644     print_insn = print_insn_riscv32;
645 #elif defined(_LP64)
646     print_insn = print_insn_riscv64;
647 #else
648 #error unsupported RISC-V ABI
649 #endif
650 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
651     print_insn = print_insn_arm_a64;
652     s.info.cap_arch = CS_ARCH_ARM64;
653 #elif defined(__alpha__)
654     print_insn = print_insn_alpha;
655 #elif defined(__sparc__)
656     print_insn = print_insn_sparc;
657     s.info.mach = bfd_mach_sparc_v9b;
658 #elif defined(__arm__)
659     print_insn = print_insn_arm;
660     s.info.cap_arch = CS_ARCH_ARM;
661     /* TCG only generates code for arm mode.  */
662 #elif defined(__MIPSEB__)
663     print_insn = print_insn_big_mips;
664 #elif defined(__MIPSEL__)
665     print_insn = print_insn_little_mips;
666 #elif defined(__m68k__)
667     print_insn = print_insn_m68k;
668 #elif defined(__s390__)
669     print_insn = print_insn_s390;
670 #elif defined(__hppa__)
671     print_insn = print_insn_hppa;
672 #endif
673
674     if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size, note)) {
675         return;
676     }
677
678     if (print_insn == NULL) {
679         print_insn = print_insn_od_host;
680     }
681     for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
682         fprintf(out, "0x%08" PRIxPTR ":  ", pc);
683         count = print_insn(pc, &s.info);
684         if (note) {
685             fprintf(out, "\t\t%s", note);
686             note = NULL;
687         }
688         fprintf(out, "\n");
689         if (count < 0) {
690             break;
691         }
692     }
693
694 }
695
696 /* Look up symbol for debugging purpose.  Returns "" if unknown. */
697 const char *lookup_symbol(target_ulong orig_addr)
698 {
699     const char *symbol = "";
700     struct syminfo *s;
701
702     for (s = syminfos; s; s = s->next) {
703         symbol = s->lookup_symbol(s, orig_addr);
704         if (symbol[0] != '\0') {
705             break;
706         }
707     }
708
709     return symbol;
710 }
711
712 #if !defined(CONFIG_USER_ONLY)
713
714 #include "monitor/monitor.h"
715
716 static int
717 physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
718                      struct disassemble_info *info)
719 {
720     CPUDebug *s = container_of(info, CPUDebug, info);
721
722     address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
723                        myaddr, length);
724     return 0;
725 }
726
727 /* Disassembler for the monitor.  */
728 void monitor_disas(Monitor *mon, CPUState *cpu,
729                    target_ulong pc, int nb_insn, int is_physical)
730 {
731     CPUClass *cc = CPU_GET_CLASS(cpu);
732     int count, i;
733     CPUDebug s;
734
735     INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf);
736
737     s.cpu = cpu;
738     s.info.read_memory_func
739         = (is_physical ? physical_read_memory : target_read_memory);
740     s.info.print_address_func = generic_print_address;
741     s.info.buffer_vma = pc;
742     s.info.cap_arch = -1;
743     s.info.cap_mode = 0;
744     s.info.cap_insn_unit = 4;
745     s.info.cap_insn_split = 4;
746
747 #ifdef TARGET_WORDS_BIGENDIAN
748     s.info.endian = BFD_ENDIAN_BIG;
749 #else
750     s.info.endian = BFD_ENDIAN_LITTLE;
751 #endif
752
753     if (cc->disas_set_info) {
754         cc->disas_set_info(cpu, &s.info);
755     }
756
757     if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
758         return;
759     }
760
761     if (!s.info.print_insn) {
762         monitor_printf(mon, "0x" TARGET_FMT_lx
763                        ": Asm output not supported on this arch\n", pc);
764         return;
765     }
766
767     for(i = 0; i < nb_insn; i++) {
768         monitor_printf(mon, "0x" TARGET_FMT_lx ":  ", pc);
769         count = s.info.print_insn(pc, &s.info);
770         monitor_printf(mon, "\n");
771         if (count < 0)
772             break;
773         pc += count;
774     }
775 }
776 #endif