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