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