1 /* General "disassemble this chunk" code. Used for debugging. */
2 #include "qemu/osdep.h"
3 #include "qemu-common.h"
8 #include "disas/disas.h"
9 #include "disas/capstone.h"
11 typedef struct CPUDebug
{
12 struct disassemble_info info
;
16 /* Filled in by elfload.c. Simplistic, but will do for now. */
17 struct syminfo
*syminfos
= NULL
;
19 /* Get LENGTH bytes from info's buffer, at target address memaddr.
20 Transfer them to myaddr. */
22 buffer_read_memory(bfd_vma memaddr
, bfd_byte
*myaddr
, int length
,
23 struct disassemble_info
*info
)
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. */
29 memcpy (myaddr
, info
->buffer
+ (memaddr
- info
->buffer_vma
), length
);
33 /* Get LENGTH bytes from info's buffer, at target address memaddr.
34 Transfer them to myaddr. */
36 target_read_memory (bfd_vma memaddr
,
39 struct disassemble_info
*info
)
41 CPUDebug
*s
= container_of(info
, CPUDebug
, info
);
43 cpu_memory_rw_debug(s
->cpu
, memaddr
, myaddr
, length
, 0);
47 /* Print an error message. We can assume that this is in response to
48 an error return from buffer_read_memory. */
50 perror_memory (int status
, bfd_vma memaddr
, struct disassemble_info
*info
)
54 (*info
->fprintf_func
) (info
->stream
, "Unknown error %d\n", status
);
56 /* Actually, address between memaddr and memaddr + len was
58 (*info
->fprintf_func
) (info
->stream
,
59 "Address 0x%" PRIx64
" is out of bounds.\n", memaddr
);
62 /* This could be in a separate file, to save minuscule amounts of space
63 in statically linked executables. */
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
70 generic_print_address (bfd_vma addr
, struct disassemble_info
*info
)
72 (*info
->fprintf_func
) (info
->stream
, "0x%" PRIx64
, addr
);
75 /* Print address in hex, truncated to the width of a host virtual address. */
77 generic_print_host_address(bfd_vma addr
, struct disassemble_info
*info
)
79 uint64_t mask
= ~0ULL >> (64 - (sizeof(void *) * 8));
80 generic_print_address(addr
& mask
, info
);
83 /* Just return the given address. */
86 generic_symbol_at_address (bfd_vma addr
, struct disassemble_info
*info
)
91 bfd_vma
bfd_getl64 (const bfd_byte
*addr
)
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;
106 bfd_vma
bfd_getl32 (const bfd_byte
*addr
)
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;
117 bfd_vma
bfd_getb32 (const bfd_byte
*addr
)
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];
128 bfd_vma
bfd_getl16 (const bfd_byte
*addr
)
132 v
= (unsigned long) addr
[0];
133 v
|= (unsigned long) addr
[1] << 8;
137 bfd_vma
bfd_getb16 (const bfd_byte
*addr
)
141 v
= (unsigned long) addr
[0] << 24;
142 v
|= (unsigned long) addr
[1] << 16;
146 static int print_insn_objdump(bfd_vma pc
, disassemble_info
*info
,
149 int i
, n
= info
->buffer_length
;
150 uint8_t *buf
= g_malloc(n
);
152 info
->read_memory_func(pc
, buf
, n
, info
);
154 for (i
= 0; i
< n
; ++i
) {
156 info
->fprintf_func(info
->stream
, "\n%s: ", prefix
);
158 info
->fprintf_func(info
->stream
, "%02x", buf
[i
]);
165 static int print_insn_od_host(bfd_vma pc
, disassemble_info
*info
)
167 return print_insn_objdump(pc
, info
, "OBJD-H");
170 static int print_insn_od_target(bfd_vma pc
, disassemble_info
*info
)
172 return print_insn_objdump(pc
, info
, "OBJD-T");
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
;
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
)
190 cs_mode cap_mode
= info
->cap_mode
;
193 cap_mode
+= (info
->endian
== BFD_ENDIAN_BIG
? CS_MODE_BIG_ENDIAN
194 : CS_MODE_LITTLE_ENDIAN
);
196 err
= cs_open(info
->cap_arch
, cap_mode
, handle
);
197 if (err
!= CS_ERR_OK
) {
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
);
209 /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
210 cs_option(*handle
, CS_OPT_SKIPDATA
, CS_OPT_ON
);
212 /* Allocate temp space for cs_disasm_iter. */
213 if (cap_insn
== NULL
) {
214 cap_insn
= cs_malloc(*handle
);
215 if (cap_insn
== NULL
) {
223 static void cap_dump_insn_units(disassemble_info
*info
, cs_insn
*insn
,
226 fprintf_function print
= info
->fprintf_func
;
227 FILE *stream
= info
->stream
;
229 switch (info
->cap_insn_unit
) {
231 if (info
->endian
== BFD_ENDIAN_BIG
) {
232 for (; i
< n
; i
+= 4) {
233 print(stream
, " %08x", ldl_be_p(insn
->bytes
+ i
));
237 for (; i
< n
; i
+= 4) {
238 print(stream
, " %08x", ldl_le_p(insn
->bytes
+ i
));
244 if (info
->endian
== BFD_ENDIAN_BIG
) {
245 for (; i
< n
; i
+= 2) {
246 print(stream
, " %04x", lduw_be_p(insn
->bytes
+ i
));
249 for (; i
< n
; i
+= 2) {
250 print(stream
, " %04x", lduw_le_p(insn
->bytes
+ i
));
257 print(stream
, " %02x", insn
->bytes
[i
]);
263 static void cap_dump_insn(disassemble_info
*info
, cs_insn
*insn
)
265 fprintf_function print
= info
->fprintf_func
;
268 print(info
->stream
, "0x%08" PRIx64
": ", insn
->address
);
271 split
= info
->cap_insn_split
;
273 /* Dump the first SPLIT bytes of the instruction. */
274 cap_dump_insn_units(info
, insn
, 0, MIN(n
, split
));
276 /* Add padding up to SPLIT so that mnemonics line up. */
278 int width
= (split
- n
) / info
->cap_insn_unit
;
279 width
*= (2 * info
->cap_insn_unit
+ 1);
280 print(info
->stream
, "%*s", width
, "");
283 /* Print the actual instruction. */
284 print(info
->stream
, " %-8s %s\n", insn
->mnemonic
, insn
->op_str
);
286 /* Dump any remaining part of the insn on subsequent lines. */
287 for (i
= split
; i
< n
; i
+= split
) {
288 print(info
->stream
, "0x%08" PRIx64
": ", insn
->address
+ i
);
289 cap_dump_insn_units(info
, insn
, i
, MIN(n
, i
+ split
));
290 print(info
->stream
, "\n");
294 /* Disassemble SIZE bytes at PC for the target. */
295 static bool cap_disas_target(disassemble_info
*info
, uint64_t pc
, size_t size
)
297 uint8_t cap_buf
[1024];
302 if (cap_disas_start(info
, &handle
) != CS_ERR_OK
) {
308 size_t tsize
= MIN(sizeof(cap_buf
) - csize
, size
);
309 const uint8_t *cbuf
= cap_buf
;
311 target_read_memory(pc
+ csize
, cap_buf
+ csize
, tsize
, info
);
315 while (cs_disasm_iter(handle
, &cbuf
, &csize
, &pc
, insn
)) {
316 cap_dump_insn(info
, insn
);
319 /* If the target memory is not consumed, go back for more... */
321 /* ... taking care to move any remaining fractional insn
322 to the beginning of the buffer. */
324 memmove(cap_buf
, cbuf
, csize
);
329 /* Since the target memory is consumed, we should not have
330 a remaining fractional insn. */
332 (*info
->fprintf_func
)(info
->stream
,
333 "Disassembler disagrees with translator "
334 "over instruction decoding\n"
335 "Please report this to qemu-devel@nongnu.org\n");
344 /* Disassemble SIZE bytes at CODE for the host. */
345 static bool cap_disas_host(disassemble_info
*info
, void *code
, size_t size
)
352 if (cap_disas_start(info
, &handle
) != CS_ERR_OK
) {
358 pc
= (uintptr_t)code
;
360 while (cs_disasm_iter(handle
, &cbuf
, &size
, &pc
, insn
)) {
361 cap_dump_insn(info
, insn
);
364 (*info
->fprintf_func
)(info
->stream
,
365 "Disassembler disagrees with TCG over instruction encoding\n"
366 "Please report this to qemu-devel@nongnu.org\n");
373 #if !defined(CONFIG_USER_ONLY)
374 /* Disassemble COUNT insns at PC for the target. */
375 static bool cap_disas_monitor(disassemble_info
*info
, uint64_t pc
, int count
)
382 if (cap_disas_start(info
, &handle
) != CS_ERR_OK
) {
388 /* We want to read memory for one insn, but generically we do not
389 know how much memory that is. We have a small buffer which is
390 known to be sufficient for all supported targets. Try to not
391 read beyond the page, Just In Case. For even more simplicity,
392 ignore the actual target page size and use a 1k boundary. If
393 that turns out to be insufficient, we'll come back around the
394 loop and read more. */
395 uint64_t epc
= QEMU_ALIGN_UP(pc
+ csize
+ 1, 1024);
396 size_t tsize
= MIN(sizeof(cap_buf
) - csize
, epc
- pc
);
397 const uint8_t *cbuf
= cap_buf
;
399 /* Make certain that we can make progress. */
401 info
->read_memory_func(pc
, cap_buf
+ csize
, tsize
, info
);
404 if (cs_disasm_iter(handle
, &cbuf
, &csize
, &pc
, insn
)) {
405 cap_dump_insn(info
, insn
);
410 memmove(cap_buf
, cbuf
, csize
);
416 #endif /* !CONFIG_USER_ONLY */
418 # define cap_disas_target(i, p, s) false
419 # define cap_disas_host(i, p, s) false
420 # define cap_disas_monitor(i, p, c) false
421 #endif /* CONFIG_CAPSTONE */
423 /* Disassemble this for me please... (debugging). */
424 void target_disas(FILE *out
, CPUState
*cpu
, target_ulong code
,
427 CPUClass
*cc
= CPU_GET_CLASS(cpu
);
432 INIT_DISASSEMBLE_INFO(s
.info
, out
, fprintf
);
435 s
.info
.read_memory_func
= target_read_memory
;
436 s
.info
.buffer_vma
= code
;
437 s
.info
.buffer_length
= size
;
438 s
.info
.print_address_func
= generic_print_address
;
439 s
.info
.cap_arch
= -1;
441 s
.info
.cap_insn_unit
= 4;
442 s
.info
.cap_insn_split
= 4;
444 #ifdef TARGET_WORDS_BIGENDIAN
445 s
.info
.endian
= BFD_ENDIAN_BIG
;
447 s
.info
.endian
= BFD_ENDIAN_LITTLE
;
450 if (cc
->disas_set_info
) {
451 cc
->disas_set_info(cpu
, &s
.info
);
454 if (s
.info
.cap_arch
>= 0 && cap_disas_target(&s
.info
, code
, size
)) {
458 if (s
.info
.print_insn
== NULL
) {
459 s
.info
.print_insn
= print_insn_od_target
;
462 for (pc
= code
; size
> 0; pc
+= count
, size
-= count
) {
463 fprintf(out
, "0x" TARGET_FMT_lx
": ", pc
);
464 count
= s
.info
.print_insn(pc
, &s
.info
);
470 "Disassembler disagrees with translator over instruction "
472 "Please report this to qemu-devel@nongnu.org\n");
478 /* Disassemble this for me please... (debugging). */
479 void disas(FILE *out
, void *code
, unsigned long size
)
484 int (*print_insn
)(bfd_vma pc
, disassemble_info
*info
) = NULL
;
486 INIT_DISASSEMBLE_INFO(s
.info
, out
, fprintf
);
487 s
.info
.print_address_func
= generic_print_host_address
;
489 s
.info
.buffer
= code
;
490 s
.info
.buffer_vma
= (uintptr_t)code
;
491 s
.info
.buffer_length
= size
;
492 s
.info
.cap_arch
= -1;
494 s
.info
.cap_insn_unit
= 4;
495 s
.info
.cap_insn_split
= 4;
497 #ifdef HOST_WORDS_BIGENDIAN
498 s
.info
.endian
= BFD_ENDIAN_BIG
;
500 s
.info
.endian
= BFD_ENDIAN_LITTLE
;
502 #if defined(CONFIG_TCG_INTERPRETER)
503 print_insn
= print_insn_tci
;
504 #elif defined(__i386__)
505 s
.info
.mach
= bfd_mach_i386_i386
;
506 print_insn
= print_insn_i386
;
507 s
.info
.cap_arch
= CS_ARCH_X86
;
508 s
.info
.cap_mode
= CS_MODE_32
;
509 s
.info
.cap_insn_unit
= 1;
510 s
.info
.cap_insn_split
= 8;
511 #elif defined(__x86_64__)
512 s
.info
.mach
= bfd_mach_x86_64
;
513 print_insn
= print_insn_i386
;
514 s
.info
.cap_arch
= CS_ARCH_X86
;
515 s
.info
.cap_mode
= CS_MODE_64
;
516 s
.info
.cap_insn_unit
= 1;
517 s
.info
.cap_insn_split
= 8;
518 #elif defined(_ARCH_PPC)
519 s
.info
.disassembler_options
= (char *)"any";
520 print_insn
= print_insn_ppc
;
521 s
.info
.cap_arch
= CS_ARCH_PPC
;
523 s
.info
.cap_mode
= CS_MODE_64
;
525 #elif defined(__riscv__)
526 print_insn
= print_insn_riscv
;
527 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
528 print_insn
= print_insn_arm_a64
;
529 s
.info
.cap_arch
= CS_ARCH_ARM64
;
530 #elif defined(__alpha__)
531 print_insn
= print_insn_alpha
;
532 #elif defined(__sparc__)
533 print_insn
= print_insn_sparc
;
534 s
.info
.mach
= bfd_mach_sparc_v9b
;
535 #elif defined(__arm__)
536 print_insn
= print_insn_arm
;
537 s
.info
.cap_arch
= CS_ARCH_ARM
;
538 /* TCG only generates code for arm mode. */
539 #elif defined(__MIPSEB__)
540 print_insn
= print_insn_big_mips
;
541 #elif defined(__MIPSEL__)
542 print_insn
= print_insn_little_mips
;
543 #elif defined(__m68k__)
544 print_insn
= print_insn_m68k
;
545 #elif defined(__s390__)
546 print_insn
= print_insn_s390
;
547 #elif defined(__hppa__)
548 print_insn
= print_insn_hppa
;
551 if (s
.info
.cap_arch
>= 0 && cap_disas_host(&s
.info
, code
, size
)) {
555 if (print_insn
== NULL
) {
556 print_insn
= print_insn_od_host
;
558 for (pc
= (uintptr_t)code
; size
> 0; pc
+= count
, size
-= count
) {
559 fprintf(out
, "0x%08" PRIxPTR
": ", pc
);
560 count
= print_insn(pc
, &s
.info
);
567 /* Look up symbol for debugging purpose. Returns "" if unknown. */
568 const char *lookup_symbol(target_ulong orig_addr
)
570 const char *symbol
= "";
573 for (s
= syminfos
; s
; s
= s
->next
) {
574 symbol
= s
->lookup_symbol(s
, orig_addr
);
575 if (symbol
[0] != '\0') {
583 #if !defined(CONFIG_USER_ONLY)
585 #include "monitor/monitor.h"
588 physical_read_memory(bfd_vma memaddr
, bfd_byte
*myaddr
, int length
,
589 struct disassemble_info
*info
)
591 cpu_physical_memory_read(memaddr
, myaddr
, length
);
595 /* Disassembler for the monitor. */
596 void monitor_disas(Monitor
*mon
, CPUState
*cpu
,
597 target_ulong pc
, int nb_insn
, int is_physical
)
599 CPUClass
*cc
= CPU_GET_CLASS(cpu
);
603 INIT_DISASSEMBLE_INFO(s
.info
, (FILE *)mon
, monitor_fprintf
);
606 s
.info
.read_memory_func
607 = (is_physical
? physical_read_memory
: target_read_memory
);
608 s
.info
.print_address_func
= generic_print_address
;
609 s
.info
.buffer_vma
= pc
;
610 s
.info
.cap_arch
= -1;
612 s
.info
.cap_insn_unit
= 4;
613 s
.info
.cap_insn_split
= 4;
615 #ifdef TARGET_WORDS_BIGENDIAN
616 s
.info
.endian
= BFD_ENDIAN_BIG
;
618 s
.info
.endian
= BFD_ENDIAN_LITTLE
;
621 if (cc
->disas_set_info
) {
622 cc
->disas_set_info(cpu
, &s
.info
);
625 if (s
.info
.cap_arch
>= 0 && cap_disas_monitor(&s
.info
, pc
, nb_insn
)) {
629 if (!s
.info
.print_insn
) {
630 monitor_printf(mon
, "0x" TARGET_FMT_lx
631 ": Asm output not supported on this arch\n", pc
);
635 for(i
= 0; i
< nb_insn
; i
++) {
636 monitor_printf(mon
, "0x" TARGET_FMT_lx
": ", pc
);
637 count
= s
.info
.print_insn(pc
, &s
.info
);
638 monitor_printf(mon
, "\n");