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"
6 #include "qemu/qemu-print.h"
9 #include "disas/disas.h"
10 #include "disas/capstone.h"
12 typedef struct CPUDebug
{
13 struct disassemble_info info
;
17 /* Filled in by elfload.c. Simplistic, but will do for now. */
18 struct syminfo
*syminfos
= NULL
;
20 /* Get LENGTH bytes from info's buffer, at target address memaddr.
21 Transfer them to myaddr. */
23 buffer_read_memory(bfd_vma memaddr
, bfd_byte
*myaddr
, int length
,
24 struct disassemble_info
*info
)
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. */
30 memcpy (myaddr
, info
->buffer
+ (memaddr
- info
->buffer_vma
), length
);
34 /* Get LENGTH bytes from info's buffer, at target address memaddr.
35 Transfer them to myaddr. */
37 target_read_memory (bfd_vma memaddr
,
40 struct disassemble_info
*info
)
42 CPUDebug
*s
= container_of(info
, CPUDebug
, info
);
44 cpu_memory_rw_debug(s
->cpu
, memaddr
, myaddr
, length
, 0);
48 /* Print an error message. We can assume that this is in response to
49 an error return from buffer_read_memory. */
51 perror_memory (int status
, bfd_vma memaddr
, struct disassemble_info
*info
)
55 (*info
->fprintf_func
) (info
->stream
, "Unknown error %d\n", status
);
57 /* Actually, address between memaddr and memaddr + len was
59 (*info
->fprintf_func
) (info
->stream
,
60 "Address 0x%" PRIx64
" is out of bounds.\n", memaddr
);
63 /* This could be in a separate file, to save minuscule amounts of space
64 in statically linked executables. */
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
71 generic_print_address (bfd_vma addr
, struct disassemble_info
*info
)
73 (*info
->fprintf_func
) (info
->stream
, "0x%" PRIx64
, addr
);
76 /* Print address in hex, truncated to the width of a host virtual address. */
78 generic_print_host_address(bfd_vma addr
, struct disassemble_info
*info
)
80 uint64_t mask
= ~0ULL >> (64 - (sizeof(void *) * 8));
81 generic_print_address(addr
& mask
, info
);
84 /* Just return the given address. */
87 generic_symbol_at_address (bfd_vma addr
, struct disassemble_info
*info
)
92 bfd_vma
bfd_getl64 (const bfd_byte
*addr
)
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;
107 bfd_vma
bfd_getl32 (const bfd_byte
*addr
)
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;
118 bfd_vma
bfd_getb32 (const bfd_byte
*addr
)
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];
129 bfd_vma
bfd_getl16 (const bfd_byte
*addr
)
133 v
= (unsigned long) addr
[0];
134 v
|= (unsigned long) addr
[1] << 8;
138 bfd_vma
bfd_getb16 (const bfd_byte
*addr
)
142 v
= (unsigned long) addr
[0] << 24;
143 v
|= (unsigned long) addr
[1] << 16;
147 static int print_insn_objdump(bfd_vma pc
, disassemble_info
*info
,
150 int i
, n
= info
->buffer_length
;
151 uint8_t *buf
= g_malloc(n
);
153 info
->read_memory_func(pc
, buf
, n
, info
);
155 for (i
= 0; i
< n
; ++i
) {
157 info
->fprintf_func(info
->stream
, "\n%s: ", prefix
);
159 info
->fprintf_func(info
->stream
, "%02x", buf
[i
]);
166 static int print_insn_od_host(bfd_vma pc
, disassemble_info
*info
)
168 return print_insn_objdump(pc
, info
, "OBJD-H");
171 static int print_insn_od_target(bfd_vma pc
, disassemble_info
*info
)
173 return print_insn_objdump(pc
, info
, "OBJD-T");
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
;
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
)
191 cs_mode cap_mode
= info
->cap_mode
;
194 cap_mode
+= (info
->endian
== BFD_ENDIAN_BIG
? CS_MODE_BIG_ENDIAN
195 : CS_MODE_LITTLE_ENDIAN
);
197 err
= cs_open(info
->cap_arch
, cap_mode
, handle
);
198 if (err
!= CS_ERR_OK
) {
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
);
210 /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
211 cs_option(*handle
, CS_OPT_SKIPDATA
, CS_OPT_ON
);
213 /* Allocate temp space for cs_disasm_iter. */
214 if (cap_insn
== NULL
) {
215 cap_insn
= cs_malloc(*handle
);
216 if (cap_insn
== NULL
) {
224 static void cap_dump_insn_units(disassemble_info
*info
, cs_insn
*insn
,
227 fprintf_function print
= info
->fprintf_func
;
228 FILE *stream
= info
->stream
;
230 switch (info
->cap_insn_unit
) {
232 if (info
->endian
== BFD_ENDIAN_BIG
) {
233 for (; i
< n
; i
+= 4) {
234 print(stream
, " %08x", ldl_be_p(insn
->bytes
+ i
));
238 for (; i
< n
; i
+= 4) {
239 print(stream
, " %08x", ldl_le_p(insn
->bytes
+ i
));
245 if (info
->endian
== BFD_ENDIAN_BIG
) {
246 for (; i
< n
; i
+= 2) {
247 print(stream
, " %04x", lduw_be_p(insn
->bytes
+ i
));
250 for (; i
< n
; i
+= 2) {
251 print(stream
, " %04x", lduw_le_p(insn
->bytes
+ i
));
258 print(stream
, " %02x", insn
->bytes
[i
]);
264 static void cap_dump_insn(disassemble_info
*info
, cs_insn
*insn
)
266 fprintf_function print
= info
->fprintf_func
;
269 print(info
->stream
, "0x%08" PRIx64
": ", insn
->address
);
272 split
= info
->cap_insn_split
;
274 /* Dump the first SPLIT bytes of the instruction. */
275 cap_dump_insn_units(info
, insn
, 0, MIN(n
, split
));
277 /* Add padding up to SPLIT so that mnemonics line up. */
279 int width
= (split
- n
) / info
->cap_insn_unit
;
280 width
*= (2 * info
->cap_insn_unit
+ 1);
281 print(info
->stream
, "%*s", width
, "");
284 /* Print the actual instruction. */
285 print(info
->stream
, " %-8s %s\n", insn
->mnemonic
, insn
->op_str
);
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");
295 /* Disassemble SIZE bytes at PC for the target. */
296 static bool cap_disas_target(disassemble_info
*info
, uint64_t pc
, size_t size
)
298 uint8_t cap_buf
[1024];
303 if (cap_disas_start(info
, &handle
) != CS_ERR_OK
) {
309 size_t tsize
= MIN(sizeof(cap_buf
) - csize
, size
);
310 const uint8_t *cbuf
= cap_buf
;
312 target_read_memory(pc
+ csize
, cap_buf
+ csize
, tsize
, info
);
316 while (cs_disasm_iter(handle
, &cbuf
, &csize
, &pc
, insn
)) {
317 cap_dump_insn(info
, insn
);
320 /* If the target memory is not consumed, go back for more... */
322 /* ... taking care to move any remaining fractional insn
323 to the beginning of the buffer. */
325 memmove(cap_buf
, cbuf
, csize
);
330 /* Since the target memory is consumed, we should not have
331 a remaining fractional insn. */
333 (*info
->fprintf_func
)(info
->stream
,
334 "Disassembler disagrees with translator "
335 "over instruction decoding\n"
336 "Please report this to qemu-devel@nongnu.org\n");
345 /* Disassemble SIZE bytes at CODE for the host. */
346 static bool cap_disas_host(disassemble_info
*info
, void *code
, size_t size
)
353 if (cap_disas_start(info
, &handle
) != CS_ERR_OK
) {
359 pc
= (uintptr_t)code
;
361 while (cs_disasm_iter(handle
, &cbuf
, &size
, &pc
, insn
)) {
362 cap_dump_insn(info
, insn
);
365 (*info
->fprintf_func
)(info
->stream
,
366 "Disassembler disagrees with TCG over instruction encoding\n"
367 "Please report this to qemu-devel@nongnu.org\n");
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
)
383 if (cap_disas_start(info
, &handle
) != CS_ERR_OK
) {
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
;
400 /* Make certain that we can make progress. */
402 info
->read_memory_func(pc
, cap_buf
+ csize
, tsize
, info
);
405 if (cs_disasm_iter(handle
, &cbuf
, &csize
, &pc
, insn
)) {
406 cap_dump_insn(info
, insn
);
411 memmove(cap_buf
, cbuf
, csize
);
417 #endif /* !CONFIG_USER_ONLY */
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 */
424 /* Disassemble this for me please... (debugging). */
425 void target_disas(FILE *out
, CPUState
*cpu
, target_ulong code
,
428 CPUClass
*cc
= CPU_GET_CLASS(cpu
);
433 INIT_DISASSEMBLE_INFO(s
.info
, out
, fprintf
);
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;
442 s
.info
.cap_insn_unit
= 4;
443 s
.info
.cap_insn_split
= 4;
445 #ifdef TARGET_WORDS_BIGENDIAN
446 s
.info
.endian
= BFD_ENDIAN_BIG
;
448 s
.info
.endian
= BFD_ENDIAN_LITTLE
;
451 if (cc
->disas_set_info
) {
452 cc
->disas_set_info(cpu
, &s
.info
);
455 if (s
.info
.cap_arch
>= 0 && cap_disas_target(&s
.info
, code
, size
)) {
459 if (s
.info
.print_insn
== NULL
) {
460 s
.info
.print_insn
= print_insn_od_target
;
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
);
471 "Disassembler disagrees with translator over instruction "
473 "Please report this to qemu-devel@nongnu.org\n");
479 /* Disassemble this for me please... (debugging). */
480 void disas(FILE *out
, void *code
, unsigned long size
)
485 int (*print_insn
)(bfd_vma pc
, disassemble_info
*info
) = NULL
;
487 INIT_DISASSEMBLE_INFO(s
.info
, out
, fprintf
);
488 s
.info
.print_address_func
= generic_print_host_address
;
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;
495 s
.info
.cap_insn_unit
= 4;
496 s
.info
.cap_insn_split
= 4;
498 #ifdef HOST_WORDS_BIGENDIAN
499 s
.info
.endian
= BFD_ENDIAN_BIG
;
501 s
.info
.endian
= BFD_ENDIAN_LITTLE
;
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
;
524 s
.info
.cap_mode
= CS_MODE_64
;
526 #elif defined(__riscv) && defined(CONFIG_RISCV_DIS)
527 #if defined(_ILP32) || (__riscv_xlen == 32)
528 print_insn
= print_insn_riscv32
;
530 print_insn
= print_insn_riscv64
;
532 #error unsupported RISC-V ABI
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
;
558 if (s
.info
.cap_arch
>= 0 && cap_disas_host(&s
.info
, code
, size
)) {
562 if (print_insn
== NULL
) {
563 print_insn
= print_insn_od_host
;
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
);
574 /* Look up symbol for debugging purpose. Returns "" if unknown. */
575 const char *lookup_symbol(target_ulong orig_addr
)
577 const char *symbol
= "";
580 for (s
= syminfos
; s
; s
= s
->next
) {
581 symbol
= s
->lookup_symbol(s
, orig_addr
);
582 if (symbol
[0] != '\0') {
590 #if !defined(CONFIG_USER_ONLY)
592 #include "monitor/monitor.h"
595 physical_read_memory(bfd_vma memaddr
, bfd_byte
*myaddr
, int length
,
596 struct disassemble_info
*info
)
598 CPUDebug
*s
= container_of(info
, CPUDebug
, info
);
600 address_space_read(s
->cpu
->as
, memaddr
, MEMTXATTRS_UNSPECIFIED
,
605 /* Disassembler for the monitor. */
606 void monitor_disas(Monitor
*mon
, CPUState
*cpu
,
607 target_ulong pc
, int nb_insn
, int is_physical
)
609 CPUClass
*cc
= CPU_GET_CLASS(cpu
);
613 INIT_DISASSEMBLE_INFO(s
.info
, NULL
, qemu_fprintf
);
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;
622 s
.info
.cap_insn_unit
= 4;
623 s
.info
.cap_insn_split
= 4;
625 #ifdef TARGET_WORDS_BIGENDIAN
626 s
.info
.endian
= BFD_ENDIAN_BIG
;
628 s
.info
.endian
= BFD_ENDIAN_LITTLE
;
631 if (cc
->disas_set_info
) {
632 cc
->disas_set_info(cpu
, &s
.info
);
635 if (s
.info
.cap_arch
>= 0 && cap_disas_monitor(&s
.info
, pc
, nb_insn
)) {
639 if (!s
.info
.print_insn
) {
640 monitor_printf(mon
, "0x" TARGET_FMT_lx
641 ": Asm output not supported on this arch\n", pc
);
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");