OSDN Git Service

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