blob: c1397d3933673c5b8f5da6d53a7ef60fe5e5ad10 [file] [log] [blame]
bellardb9adb4a2003-04-29 20:41:16 +00001/* General "disassemble this chunk" code. Used for debugging. */
Peter Maydelld38ea872016-01-29 17:50:05 +00002#include "qemu/osdep.h"
Markus Armbruster3979fca2019-04-17 21:18:04 +02003#include "disas/dis-asm.h"
bellardb9adb4a2003-04-29 20:41:16 +00004#include "elf.h"
Markus Armbruster30cc9832019-04-17 21:18:03 +02005#include "qemu/qemu-print.h"
bellardb9adb4a2003-04-29 20:41:16 +00006
bellardc6105c02003-10-27 21:13:58 +00007#include "cpu.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +02008#include "disas/disas.h"
Richard Henderson8ca80762017-09-14 09:41:12 -07009#include "disas/capstone.h"
bellardc6105c02003-10-27 21:13:58 +000010
Blue Swirlf4359b92012-09-08 12:40:00 +000011typedef struct CPUDebug {
12 struct disassemble_info info;
Peter Crosthwaited49190c2015-05-24 14:20:41 -070013 CPUState *cpu;
Blue Swirlf4359b92012-09-08 12:40:00 +000014} CPUDebug;
15
bellardb9adb4a2003-04-29 20:41:16 +000016/* Filled in by elfload.c. Simplistic, but will do for now. */
bellarde80cfcf2004-12-19 23:18:01 +000017struct syminfo *syminfos = NULL;
bellardb9adb4a2003-04-29 20:41:16 +000018
bellardaa0aa4f2003-06-09 15:23:31 +000019/* Get LENGTH bytes from info's buffer, at target address memaddr.
20 Transfer them to myaddr. */
21int
pbrook3a742b72008-10-22 15:55:18 +000022buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
23 struct disassemble_info *info)
bellardaa0aa4f2003-06-09 15:23:31 +000024{
bellardc6105c02003-10-27 21:13:58 +000025 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;
bellardaa0aa4f2003-06-09 15:23:31 +000031}
32
bellardc6105c02003-10-27 21:13:58 +000033/* Get LENGTH bytes from info's buffer, at target address memaddr.
34 Transfer them to myaddr. */
35static int
bellardc27004e2005-01-03 23:35:10 +000036target_read_memory (bfd_vma memaddr,
37 bfd_byte *myaddr,
38 int length,
39 struct disassemble_info *info)
bellardc6105c02003-10-27 21:13:58 +000040{
Blue Swirlf4359b92012-09-08 12:40:00 +000041 CPUDebug *s = container_of(info, CPUDebug, info);
Philippe Mathieu-Daudé6766ba52020-05-18 17:53:04 +020042 int r;
Blue Swirlf4359b92012-09-08 12:40:00 +000043
Philippe Mathieu-Daudé6766ba52020-05-18 17:53:04 +020044 r = cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
45
46 return r ? EIO : 0;
bellardc6105c02003-10-27 21:13:58 +000047}
bellardc6105c02003-10-27 21:13:58 +000048
bellardaa0aa4f2003-06-09 15:23:31 +000049/* Print an error message. We can assume that this is in response to
50 an error return from buffer_read_memory. */
51void
pbrook3a742b72008-10-22 15:55:18 +000052perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
bellardaa0aa4f2003-06-09 15:23:31 +000053{
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,
bellard26a76462006-06-25 18:15:32 +000061 "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
bellardaa0aa4f2003-06-09 15:23:31 +000062}
63
Jim Meyeringa31f0532012-05-09 05:12:04 +000064/* This could be in a separate file, to save minuscule amounts of space
bellardaa0aa4f2003-06-09 15:23:31 +000065 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
71void
pbrook3a742b72008-10-22 15:55:18 +000072generic_print_address (bfd_vma addr, struct disassemble_info *info)
bellardaa0aa4f2003-06-09 15:23:31 +000073{
bellard26a76462006-06-25 18:15:32 +000074 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
bellardaa0aa4f2003-06-09 15:23:31 +000075}
76
Peter Maydell636bd282012-06-25 04:55:55 +000077/* Print address in hex, truncated to the width of a host virtual address. */
78static void
79generic_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
bellardaa0aa4f2003-06-09 15:23:31 +000085/* Just return the given address. */
86
87int
pbrook3a742b72008-10-22 15:55:18 +000088generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
bellardaa0aa4f2003-06-09 15:23:31 +000089{
90 return 1;
91}
92
Aurelien Jarno903ec552010-03-29 02:12:51 +020093bfd_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
bellardaa0aa4f2003-06-09 15:23:31 +0000108bfd_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
119bfd_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
bellard6af0bf92005-07-02 14:58:51 +0000130bfd_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
139bfd_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
Richard Hendersonc46ffd52013-08-16 23:29:45 -0700148static 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
167static int print_insn_od_host(bfd_vma pc, disassemble_info *info)
168{
169 return print_insn_objdump(pc, info, "OBJD-H");
170}
171
172static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
173{
174 return print_insn_objdump(pc, info, "OBJD-T");
175}
176
Richard Henderson8ca80762017-09-14 09:41:12 -0700177#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. */
181static __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. */
190static 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
Richard Henderson15fa1a02017-11-07 13:19:18 +0100225static 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
Alex Bennée16b22e02020-05-13 18:51:33 +0100265static void cap_dump_insn(disassemble_info *info, cs_insn *insn,
266 const char *note)
Richard Henderson15fa1a02017-11-07 13:19:18 +0100267{
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. */
Alex Bennée16b22e02020-05-13 18:51:33 +0100287 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");
Richard Henderson15fa1a02017-11-07 13:19:18 +0100292
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
Richard Henderson8ca80762017-09-14 09:41:12 -0700301/* Disassemble SIZE bytes at PC for the target. */
302static 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)) {
Alex Bennée16b22e02020-05-13 18:51:33 +0100323 cap_dump_insn(info, insn, NULL);
Richard Henderson8ca80762017-09-14 09:41:12 -0700324 }
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 qemu-devel@nongnu.org\n");
343 }
344 break;
345 }
346
347 cs_close(&handle);
348 return true;
349}
350
351/* Disassemble SIZE bytes at CODE for the host. */
Alex Bennée16b22e02020-05-13 18:51:33 +0100352static bool cap_disas_host(disassemble_info *info, void *code, size_t size,
353 const char *note)
Richard Henderson8ca80762017-09-14 09:41:12 -0700354{
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)) {
Alex Bennée16b22e02020-05-13 18:51:33 +0100369 cap_dump_insn(info, insn, note);
370 note = NULL;
Richard Henderson8ca80762017-09-14 09:41:12 -0700371 }
372 if (size != 0) {
373 (*info->fprintf_func)(info->stream,
374 "Disassembler disagrees with TCG over instruction encoding\n"
375 "Please report this to qemu-devel@nongnu.org\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. */
384static 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)) {
Alex Bennée16b22e02020-05-13 18:51:33 +0100414 cap_dump_insn(info, insn, NULL);
Richard Henderson8ca80762017-09-14 09:41:12 -0700415 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
Alex Bennée16b22e02020-05-13 18:51:33 +0100428# define cap_disas_host(i, p, s, n) false
Richard Henderson8ca80762017-09-14 09:41:12 -0700429# define cap_disas_monitor(i, p, c) false
Alex Bennéecbafa232019-05-22 10:27:14 +0100430# define cap_disas_plugin(i, p, c) false
Richard Henderson8ca80762017-09-14 09:41:12 -0700431#endif /* CONFIG_CAPSTONE */
432
Richard Henderson1d484742017-09-14 08:38:35 -0700433/* Disassemble this for me please... (debugging). */
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700434void target_disas(FILE *out, CPUState *cpu, target_ulong code,
Richard Henderson1d484742017-09-14 08:38:35 -0700435 target_ulong size)
bellardb9adb4a2003-04-29 20:41:16 +0000436{
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700437 CPUClass *cc = CPU_GET_CLASS(cpu);
bellardc27004e2005-01-03 23:35:10 +0000438 target_ulong pc;
bellardb9adb4a2003-04-29 20:41:16 +0000439 int count;
Blue Swirlf4359b92012-09-08 12:40:00 +0000440 CPUDebug s;
bellardb9adb4a2003-04-29 20:41:16 +0000441
Blue Swirlf4359b92012-09-08 12:40:00 +0000442 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
bellardb9adb4a2003-04-29 20:41:16 +0000443
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700444 s.cpu = cpu;
Blue Swirlf4359b92012-09-08 12:40:00 +0000445 s.info.read_memory_func = target_read_memory;
446 s.info.buffer_vma = code;
447 s.info.buffer_length = size;
Peter Crosthwaite9504c542015-07-05 13:50:32 -0700448 s.info.print_address_func = generic_print_address;
Richard Henderson8ca80762017-09-14 09:41:12 -0700449 s.info.cap_arch = -1;
450 s.info.cap_mode = 0;
Richard Henderson15fa1a02017-11-07 13:19:18 +0100451 s.info.cap_insn_unit = 4;
452 s.info.cap_insn_split = 4;
bellardc27004e2005-01-03 23:35:10 +0000453
454#ifdef TARGET_WORDS_BIGENDIAN
Blue Swirlf4359b92012-09-08 12:40:00 +0000455 s.info.endian = BFD_ENDIAN_BIG;
bellardc27004e2005-01-03 23:35:10 +0000456#else
Blue Swirlf4359b92012-09-08 12:40:00 +0000457 s.info.endian = BFD_ENDIAN_LITTLE;
bellardc6105c02003-10-27 21:13:58 +0000458#endif
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700459
460 if (cc->disas_set_info) {
461 cc->disas_set_info(cpu, &s.info);
462 }
463
Richard Henderson8ca80762017-09-14 09:41:12 -0700464 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
465 return;
466 }
467
Peter Crosthwaite2de295c2015-06-23 20:57:32 -0700468 if (s.info.print_insn == NULL) {
469 s.info.print_insn = print_insn_od_target;
Richard Hendersonc46ffd52013-08-16 23:29:45 -0700470 }
bellardc27004e2005-01-03 23:35:10 +0000471
blueswir17e000c22009-02-13 21:44:41 +0000472 for (pc = code; size > 0; pc += count, size -= count) {
bellardfa15e032005-01-31 23:32:31 +0000473 fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
Peter Crosthwaite2de295c2015-06-23 20:57:32 -0700474 count = s.info.print_insn(pc, &s.info);
bellardc27004e2005-01-03 23:35:10 +0000475 fprintf(out, "\n");
476 if (count < 0)
477 break;
malc754d00a2009-04-21 22:26:22 +0000478 if (size < count) {
479 fprintf(out,
480 "Disassembler disagrees with translator over instruction "
481 "decoding\n"
482 "Please report this to qemu-devel@nongnu.org\n");
483 break;
484 }
bellardc27004e2005-01-03 23:35:10 +0000485 }
486}
487
Alex Bennéecbafa232019-05-22 10:27:14 +0100488static __thread GString plugin_disas_output;
489
490static 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
503static 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 */
511static
512bool 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 */
548char *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
bellardc27004e2005-01-03 23:35:10 +0000597/* Disassemble this for me please... (debugging). */
Alex Bennéee5ef4ec2020-05-13 18:51:32 +0100598void disas(FILE *out, void *code, unsigned long size, const char *note)
bellardc27004e2005-01-03 23:35:10 +0000599{
Stefan Weilb0b0f1c2012-04-12 15:44:35 +0200600 uintptr_t pc;
bellardc27004e2005-01-03 23:35:10 +0000601 int count;
Blue Swirlf4359b92012-09-08 12:40:00 +0000602 CPUDebug s;
Richard Hendersonc46ffd52013-08-16 23:29:45 -0700603 int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
bellardc27004e2005-01-03 23:35:10 +0000604
Blue Swirlf4359b92012-09-08 12:40:00 +0000605 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
606 s.info.print_address_func = generic_print_host_address;
bellardc6105c02003-10-27 21:13:58 +0000607
Blue Swirlf4359b92012-09-08 12:40:00 +0000608 s.info.buffer = code;
609 s.info.buffer_vma = (uintptr_t)code;
610 s.info.buffer_length = size;
Richard Henderson8ca80762017-09-14 09:41:12 -0700611 s.info.cap_arch = -1;
612 s.info.cap_mode = 0;
Richard Henderson15fa1a02017-11-07 13:19:18 +0100613 s.info.cap_insn_unit = 4;
614 s.info.cap_insn_split = 4;
bellardb9adb4a2003-04-29 20:41:16 +0000615
Juan Quintelae2542fe2009-07-27 16:13:06 +0200616#ifdef HOST_WORDS_BIGENDIAN
Blue Swirlf4359b92012-09-08 12:40:00 +0000617 s.info.endian = BFD_ENDIAN_BIG;
bellardb9adb4a2003-04-29 20:41:16 +0000618#else
Blue Swirlf4359b92012-09-08 12:40:00 +0000619 s.info.endian = BFD_ENDIAN_LITTLE;
bellardb9adb4a2003-04-29 20:41:16 +0000620#endif
Stefan Weil5826e512011-10-05 20:03:53 +0200621#if defined(CONFIG_TCG_INTERPRETER)
622 print_insn = print_insn_tci;
623#elif defined(__i386__)
Blue Swirlf4359b92012-09-08 12:40:00 +0000624 s.info.mach = bfd_mach_i386_i386;
bellardc27004e2005-01-03 23:35:10 +0000625 print_insn = print_insn_i386;
Richard Hendersonb666d2a2017-09-14 09:50:05 -0700626 s.info.cap_arch = CS_ARCH_X86;
627 s.info.cap_mode = CS_MODE_32;
Richard Henderson15fa1a02017-11-07 13:19:18 +0100628 s.info.cap_insn_unit = 1;
629 s.info.cap_insn_split = 8;
bellardbc51c5c2004-03-17 23:46:04 +0000630#elif defined(__x86_64__)
Blue Swirlf4359b92012-09-08 12:40:00 +0000631 s.info.mach = bfd_mach_x86_64;
bellardc27004e2005-01-03 23:35:10 +0000632 print_insn = print_insn_i386;
Richard Hendersonb666d2a2017-09-14 09:50:05 -0700633 s.info.cap_arch = CS_ARCH_X86;
634 s.info.cap_mode = CS_MODE_64;
Richard Henderson15fa1a02017-11-07 13:19:18 +0100635 s.info.cap_insn_unit = 1;
636 s.info.cap_insn_split = 8;
malce58ffeb2009-01-14 18:39:49 +0000637#elif defined(_ARCH_PPC)
Richard Henderson66d4f6a2013-01-31 11:16:21 -0800638 s.info.disassembler_options = (char *)"any";
bellardc27004e2005-01-03 23:35:10 +0000639 print_insn = print_insn_ppc;
Richard Hendersonac226892017-09-14 10:38:40 -0700640 s.info.cap_arch = CS_ARCH_PPC;
641# ifdef _ARCH_PPC64
642 s.info.cap_mode = CS_MODE_64;
643# endif
Alistair Francis91468b22018-12-19 19:20:09 +0000644#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
Claudio Fontana999b53e2014-02-05 17:27:28 +0000652#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
653 print_insn = print_insn_arm_a64;
Richard Henderson110f6c72017-09-14 09:51:06 -0700654 s.info.cap_arch = CS_ARCH_ARM64;
bellarda993ba82003-05-11 12:25:45 +0000655#elif defined(__alpha__)
bellardc27004e2005-01-03 23:35:10 +0000656 print_insn = print_insn_alpha;
bellardaa0aa4f2003-06-09 15:23:31 +0000657#elif defined(__sparc__)
bellardc27004e2005-01-03 23:35:10 +0000658 print_insn = print_insn_sparc;
Blue Swirlf4359b92012-09-08 12:40:00 +0000659 s.info.mach = bfd_mach_sparc_v9b;
ths5fafdf22007-09-16 21:08:06 +0000660#elif defined(__arm__)
bellardc27004e2005-01-03 23:35:10 +0000661 print_insn = print_insn_arm;
Richard Henderson110f6c72017-09-14 09:51:06 -0700662 s.info.cap_arch = CS_ARCH_ARM;
663 /* TCG only generates code for arm mode. */
bellard6af0bf92005-07-02 14:58:51 +0000664#elif defined(__MIPSEB__)
665 print_insn = print_insn_big_mips;
666#elif defined(__MIPSEL__)
667 print_insn = print_insn_little_mips;
bellard48024e42005-11-06 16:52:11 +0000668#elif defined(__m68k__)
669 print_insn = print_insn_m68k;
ths8f860bb2007-07-31 23:44:21 +0000670#elif defined(__s390__)
671 print_insn = print_insn_s390;
Richard Henderson429b31a2016-09-29 10:55:53 -0700672#elif defined(__hppa__)
673 print_insn = print_insn_hppa;
bellardb9adb4a2003-04-29 20:41:16 +0000674#endif
Richard Henderson8ca80762017-09-14 09:41:12 -0700675
Alex Bennée16b22e02020-05-13 18:51:33 +0100676 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size, note)) {
Richard Henderson8ca80762017-09-14 09:41:12 -0700677 return;
678 }
679
Richard Hendersonc46ffd52013-08-16 23:29:45 -0700680 if (print_insn == NULL) {
681 print_insn = print_insn_od_host;
682 }
Stefan Weilb0b0f1c2012-04-12 15:44:35 +0200683 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
684 fprintf(out, "0x%08" PRIxPTR ": ", pc);
Blue Swirlf4359b92012-09-08 12:40:00 +0000685 count = print_insn(pc, &s.info);
Alex Bennéee5ef4ec2020-05-13 18:51:32 +0100686 if (note) {
687 fprintf(out, "\t\t%s", note);
688 note = NULL;
689 }
690 fprintf(out, "\n");
691 if (count < 0) {
692 break;
693 }
bellardb9adb4a2003-04-29 20:41:16 +0000694 }
Alex Bennéee5ef4ec2020-05-13 18:51:32 +0100695
bellardb9adb4a2003-04-29 20:41:16 +0000696}
697
698/* Look up symbol for debugging purpose. Returns "" if unknown. */
bellardc27004e2005-01-03 23:35:10 +0000699const char *lookup_symbol(target_ulong orig_addr)
bellardb9adb4a2003-04-29 20:41:16 +0000700{
pbrook49918a72008-10-22 15:11:31 +0000701 const char *symbol = "";
bellarde80cfcf2004-12-19 23:18:01 +0000702 struct syminfo *s;
ths3b46e622007-09-17 08:09:54 +0000703
bellarde80cfcf2004-12-19 23:18:01 +0000704 for (s = syminfos; s; s = s->next) {
pbrook49918a72008-10-22 15:11:31 +0000705 symbol = s->lookup_symbol(s, orig_addr);
706 if (symbol[0] != '\0') {
707 break;
708 }
bellardb9adb4a2003-04-29 20:41:16 +0000709 }
pbrook49918a72008-10-22 15:11:31 +0000710
711 return symbol;
bellardb9adb4a2003-04-29 20:41:16 +0000712}
bellard9307c4c2004-04-04 12:57:25 +0000713
714#if !defined(CONFIG_USER_ONLY)
715
Paolo Bonzini83c90892012-12-17 18:19:49 +0100716#include "monitor/monitor.h"
bellard3d2cfdf2004-08-01 21:49:07 +0000717
bellard9307c4c2004-04-04 12:57:25 +0000718static int
Richard Hendersonb8d87202017-09-19 09:40:40 -0500719physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
blueswir1a5f1b962008-08-17 20:21:51 +0000720 struct disassemble_info *info)
bellard9307c4c2004-04-04 12:57:25 +0000721{
Peter Maydellf2c6abc2018-12-14 13:30:49 +0000722 CPUDebug *s = container_of(info, CPUDebug, info);
Philippe Mathieu-Daudé6766ba52020-05-18 17:53:04 +0200723 MemTxResult res;
Peter Maydellf2c6abc2018-12-14 13:30:49 +0000724
Philippe Mathieu-Daudé6766ba52020-05-18 17:53:04 +0200725 res = address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
726 myaddr, length);
727 return res == MEMTX_OK ? 0 : EIO;
bellard9307c4c2004-04-04 12:57:25 +0000728}
729
Richard Henderson1d484742017-09-14 08:38:35 -0700730/* Disassembler for the monitor. */
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700731void monitor_disas(Monitor *mon, CPUState *cpu,
Richard Henderson1d484742017-09-14 08:38:35 -0700732 target_ulong pc, int nb_insn, int is_physical)
bellard9307c4c2004-04-04 12:57:25 +0000733{
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700734 CPUClass *cc = CPU_GET_CLASS(cpu);
bellard9307c4c2004-04-04 12:57:25 +0000735 int count, i;
Blue Swirlf4359b92012-09-08 12:40:00 +0000736 CPUDebug s;
bellard9307c4c2004-04-04 12:57:25 +0000737
Markus Armbruster30cc9832019-04-17 21:18:03 +0200738 INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf);
bellard9307c4c2004-04-04 12:57:25 +0000739
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700740 s.cpu = cpu;
Richard Hendersonb8d87202017-09-19 09:40:40 -0500741 s.info.read_memory_func
742 = (is_physical ? physical_read_memory : target_read_memory);
Peter Crosthwaite9504c542015-07-05 13:50:32 -0700743 s.info.print_address_func = generic_print_address;
Blue Swirlf4359b92012-09-08 12:40:00 +0000744 s.info.buffer_vma = pc;
Richard Henderson8ca80762017-09-14 09:41:12 -0700745 s.info.cap_arch = -1;
746 s.info.cap_mode = 0;
Richard Henderson15fa1a02017-11-07 13:19:18 +0100747 s.info.cap_insn_unit = 4;
748 s.info.cap_insn_split = 4;
bellard9307c4c2004-04-04 12:57:25 +0000749
750#ifdef TARGET_WORDS_BIGENDIAN
Blue Swirlf4359b92012-09-08 12:40:00 +0000751 s.info.endian = BFD_ENDIAN_BIG;
bellard9307c4c2004-04-04 12:57:25 +0000752#else
Blue Swirlf4359b92012-09-08 12:40:00 +0000753 s.info.endian = BFD_ENDIAN_LITTLE;
bellard9307c4c2004-04-04 12:57:25 +0000754#endif
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700755
756 if (cc->disas_set_info) {
757 cc->disas_set_info(cpu, &s.info);
758 }
759
Richard Henderson8ca80762017-09-14 09:41:12 -0700760 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
761 return;
762 }
763
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700764 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 }
bellard9307c4c2004-04-04 12:57:25 +0000769
770 for(i = 0; i < nb_insn; i++) {
aliguori376253e2009-03-05 23:01:23 +0000771 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
Peter Crosthwaite2de295c2015-06-23 20:57:32 -0700772 count = s.info.print_insn(pc, &s.info);
aliguori376253e2009-03-05 23:01:23 +0000773 monitor_printf(mon, "\n");
bellard9307c4c2004-04-04 12:57:25 +0000774 if (count < 0)
775 break;
776 pc += count;
777 }
778}
779#endif