]> git.proxmox.com Git - mirror_qemu.git/blame - disas.c
Merge remote-tracking branch 'remotes/mdroth/tags/qga-pull-2017-10-26-tag' into staging
[mirror_qemu.git] / disas.c
CommitLineData
b9adb4a6 1/* General "disassemble this chunk" code. Used for debugging. */
d38ea87a 2#include "qemu/osdep.h"
37b9de46 3#include "qemu-common.h"
76cad711 4#include "disas/bfd.h"
b9adb4a6
FB
5#include "elf.h"
6
c6105c0a 7#include "cpu.h"
76cad711 8#include "disas/disas.h"
8ca80760 9#include "disas/capstone.h"
c6105c0a 10
f4359b9f
BS
11typedef struct CPUDebug {
12 struct disassemble_info info;
d49190c4 13 CPUState *cpu;
f4359b9f
BS
14} CPUDebug;
15
b9adb4a6 16/* Filled in by elfload.c. Simplistic, but will do for now. */
e80cfcfc 17struct syminfo *syminfos = NULL;
b9adb4a6 18
aa0aa4fa
FB
19/* Get LENGTH bytes from info's buffer, at target address memaddr.
20 Transfer them to myaddr. */
21int
3a742b76
PB
22buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
23 struct disassemble_info *info)
aa0aa4fa 24{
c6105c0a
FB
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. */
28 return EIO;
29 memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
30 return 0;
aa0aa4fa
FB
31}
32
c6105c0a
FB
33/* Get LENGTH bytes from info's buffer, at target address memaddr.
34 Transfer them to myaddr. */
35static int
c27004ec
FB
36target_read_memory (bfd_vma memaddr,
37 bfd_byte *myaddr,
38 int length,
39 struct disassemble_info *info)
c6105c0a 40{
f4359b9f
BS
41 CPUDebug *s = container_of(info, CPUDebug, info);
42
d49190c4 43 cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
c6105c0a
FB
44 return 0;
45}
c6105c0a 46
aa0aa4fa
FB
47/* Print an error message. We can assume that this is in response to
48 an error return from buffer_read_memory. */
49void
3a742b76 50perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
aa0aa4fa
FB
51{
52 if (status != EIO)
53 /* Can't happen. */
54 (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
55 else
56 /* Actually, address between memaddr and memaddr + len was
57 out of bounds. */
58 (*info->fprintf_func) (info->stream,
26a76461 59 "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
aa0aa4fa
FB
60}
61
a31f0531 62/* This could be in a separate file, to save minuscule amounts of space
aa0aa4fa
FB
63 in statically linked executables. */
64
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
67 addresses). */
68
69void
3a742b76 70generic_print_address (bfd_vma addr, struct disassemble_info *info)
aa0aa4fa 71{
26a76461 72 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
aa0aa4fa
FB
73}
74
636bd289
PM
75/* Print address in hex, truncated to the width of a host virtual address. */
76static void
77generic_print_host_address(bfd_vma addr, struct disassemble_info *info)
78{
79 uint64_t mask = ~0ULL >> (64 - (sizeof(void *) * 8));
80 generic_print_address(addr & mask, info);
81}
82
aa0aa4fa
FB
83/* Just return the given address. */
84
85int
3a742b76 86generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
aa0aa4fa
FB
87{
88 return 1;
89}
90
903ec55c
AJ
91bfd_vma bfd_getl64 (const bfd_byte *addr)
92{
93 unsigned long long v;
94
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;
103 return (bfd_vma) v;
104}
105
aa0aa4fa
FB
106bfd_vma bfd_getl32 (const bfd_byte *addr)
107{
108 unsigned long v;
109
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;
114 return (bfd_vma) v;
115}
116
117bfd_vma bfd_getb32 (const bfd_byte *addr)
118{
119 unsigned long v;
120
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];
125 return (bfd_vma) v;
126}
127
6af0bf9c
FB
128bfd_vma bfd_getl16 (const bfd_byte *addr)
129{
130 unsigned long v;
131
132 v = (unsigned long) addr[0];
133 v |= (unsigned long) addr[1] << 8;
134 return (bfd_vma) v;
135}
136
137bfd_vma bfd_getb16 (const bfd_byte *addr)
138{
139 unsigned long v;
140
141 v = (unsigned long) addr[0] << 24;
142 v |= (unsigned long) addr[1] << 16;
143 return (bfd_vma) v;
144}
145
c46ffd57
RH
146static int print_insn_objdump(bfd_vma pc, disassemble_info *info,
147 const char *prefix)
148{
149 int i, n = info->buffer_length;
150 uint8_t *buf = g_malloc(n);
151
152 info->read_memory_func(pc, buf, n, info);
153
154 for (i = 0; i < n; ++i) {
155 if (i % 32 == 0) {
156 info->fprintf_func(info->stream, "\n%s: ", prefix);
157 }
158 info->fprintf_func(info->stream, "%02x", buf[i]);
159 }
160
161 g_free(buf);
162 return n;
163}
164
165static int print_insn_od_host(bfd_vma pc, disassemble_info *info)
166{
167 return print_insn_objdump(pc, info, "OBJD-H");
168}
169
170static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
171{
172 return print_insn_objdump(pc, info, "OBJD-T");
173}
174
8ca80760
RH
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. */
179static __thread cs_insn *cap_insn;
180
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. */
188static cs_err cap_disas_start(disassemble_info *info, csh *handle)
189{
190 cs_mode cap_mode = info->cap_mode;
191 cs_err err;
192
193 cap_mode += (info->endian == BFD_ENDIAN_BIG ? CS_MODE_BIG_ENDIAN
194 : CS_MODE_LITTLE_ENDIAN);
195
196 err = cs_open(info->cap_arch, cap_mode, handle);
197 if (err != CS_ERR_OK) {
198 return err;
199 }
200
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);
207 }
208
209 /* "Disassemble" unknown insns as ".byte W,X,Y,Z". */
210 cs_option(*handle, CS_OPT_SKIPDATA, CS_OPT_ON);
211
212 /* Allocate temp space for cs_disasm_iter. */
213 if (cap_insn == NULL) {
214 cap_insn = cs_malloc(*handle);
215 if (cap_insn == NULL) {
216 cs_close(handle);
217 return CS_ERR_MEM;
218 }
219 }
220 return CS_ERR_OK;
221}
222
223/* Disassemble SIZE bytes at PC for the target. */
224static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
225{
226 uint8_t cap_buf[1024];
227 csh handle;
228 cs_insn *insn;
229 size_t csize = 0;
230
231 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
232 return false;
233 }
234 insn = cap_insn;
235
236 while (1) {
237 size_t tsize = MIN(sizeof(cap_buf) - csize, size);
238 const uint8_t *cbuf = cap_buf;
239
240 target_read_memory(pc + csize, cap_buf + csize, tsize, info);
241 csize += tsize;
242 size -= tsize;
243
244 while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
245 (*info->fprintf_func)(info->stream,
246 "0x%08" PRIx64 ": %-12s %s\n",
247 insn->address, insn->mnemonic,
248 insn->op_str);
249 }
250
251 /* If the target memory is not consumed, go back for more... */
252 if (size != 0) {
253 /* ... taking care to move any remaining fractional insn
254 to the beginning of the buffer. */
255 if (csize != 0) {
256 memmove(cap_buf, cbuf, csize);
257 }
258 continue;
259 }
260
261 /* Since the target memory is consumed, we should not have
262 a remaining fractional insn. */
263 if (csize != 0) {
264 (*info->fprintf_func)(info->stream,
265 "Disassembler disagrees with translator "
266 "over instruction decoding\n"
267 "Please report this to qemu-devel@nongnu.org\n");
268 }
269 break;
270 }
271
272 cs_close(&handle);
273 return true;
274}
275
276/* Disassemble SIZE bytes at CODE for the host. */
277static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
278{
279 csh handle;
280 const uint8_t *cbuf;
281 cs_insn *insn;
282 uint64_t pc;
283
284 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
285 return false;
286 }
287 insn = cap_insn;
288
289 cbuf = code;
290 pc = (uintptr_t)code;
291
292 while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
293 (*info->fprintf_func)(info->stream,
294 "0x%08" PRIx64 ": %-12s %s\n",
295 insn->address, insn->mnemonic,
296 insn->op_str);
297 }
298 if (size != 0) {
299 (*info->fprintf_func)(info->stream,
300 "Disassembler disagrees with TCG over instruction encoding\n"
301 "Please report this to qemu-devel@nongnu.org\n");
302 }
303
304 cs_close(&handle);
305 return true;
306}
307
308#if !defined(CONFIG_USER_ONLY)
309/* Disassemble COUNT insns at PC for the target. */
310static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
311{
312 uint8_t cap_buf[32];
313 csh handle;
314 cs_insn *insn;
315 size_t csize = 0;
316
317 if (cap_disas_start(info, &handle) != CS_ERR_OK) {
318 return false;
319 }
320 insn = cap_insn;
321
322 while (1) {
323 /* We want to read memory for one insn, but generically we do not
324 know how much memory that is. We have a small buffer which is
325 known to be sufficient for all supported targets. Try to not
326 read beyond the page, Just In Case. For even more simplicity,
327 ignore the actual target page size and use a 1k boundary. If
328 that turns out to be insufficient, we'll come back around the
329 loop and read more. */
330 uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024);
331 size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc);
332 const uint8_t *cbuf = cap_buf;
333
334 /* Make certain that we can make progress. */
335 assert(tsize != 0);
336 info->read_memory_func(pc, cap_buf + csize, tsize, info);
337 csize += tsize;
338
339 if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
340 (*info->fprintf_func)(info->stream,
341 "0x%08" PRIx64 ": %-12s %s\n",
342 insn->address, insn->mnemonic,
343 insn->op_str);
344 if (--count <= 0) {
345 break;
346 }
347 }
348 memmove(cap_buf, cbuf, csize);
349 }
350
351 cs_close(&handle);
352 return true;
353}
354#endif /* !CONFIG_USER_ONLY */
355#else
356# define cap_disas_target(i, p, s) false
357# define cap_disas_host(i, p, s) false
358# define cap_disas_monitor(i, p, c) false
359#endif /* CONFIG_CAPSTONE */
360
1d48474d 361/* Disassemble this for me please... (debugging). */
d49190c4 362void target_disas(FILE *out, CPUState *cpu, target_ulong code,
1d48474d 363 target_ulong size)
b9adb4a6 364{
37b9de46 365 CPUClass *cc = CPU_GET_CLASS(cpu);
c27004ec 366 target_ulong pc;
b9adb4a6 367 int count;
f4359b9f 368 CPUDebug s;
b9adb4a6 369
f4359b9f 370 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
b9adb4a6 371
d49190c4 372 s.cpu = cpu;
f4359b9f
BS
373 s.info.read_memory_func = target_read_memory;
374 s.info.buffer_vma = code;
375 s.info.buffer_length = size;
9504c544 376 s.info.print_address_func = generic_print_address;
8ca80760
RH
377 s.info.cap_arch = -1;
378 s.info.cap_mode = 0;
c27004ec
FB
379
380#ifdef TARGET_WORDS_BIGENDIAN
f4359b9f 381 s.info.endian = BFD_ENDIAN_BIG;
c27004ec 382#else
f4359b9f 383 s.info.endian = BFD_ENDIAN_LITTLE;
c27004ec 384#endif
37b9de46
PC
385
386 if (cc->disas_set_info) {
387 cc->disas_set_info(cpu, &s.info);
388 }
389
8ca80760
RH
390 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
391 return;
392 }
393
2de295c5
PC
394 if (s.info.print_insn == NULL) {
395 s.info.print_insn = print_insn_od_target;
c46ffd57 396 }
c6105c0a 397
7e000c2e 398 for (pc = code; size > 0; pc += count, size -= count) {
fa15e030 399 fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
2de295c5 400 count = s.info.print_insn(pc, &s.info);
c27004ec
FB
401 fprintf(out, "\n");
402 if (count < 0)
403 break;
754d00ae 404 if (size < count) {
405 fprintf(out,
406 "Disassembler disagrees with translator over instruction "
407 "decoding\n"
408 "Please report this to qemu-devel@nongnu.org\n");
409 break;
410 }
c27004ec
FB
411 }
412}
413
414/* Disassemble this for me please... (debugging). */
415void disas(FILE *out, void *code, unsigned long size)
416{
b0b0f1c9 417 uintptr_t pc;
c27004ec 418 int count;
f4359b9f 419 CPUDebug s;
c46ffd57 420 int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
c27004ec 421
f4359b9f
BS
422 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
423 s.info.print_address_func = generic_print_host_address;
c27004ec 424
f4359b9f
BS
425 s.info.buffer = code;
426 s.info.buffer_vma = (uintptr_t)code;
427 s.info.buffer_length = size;
8ca80760
RH
428 s.info.cap_arch = -1;
429 s.info.cap_mode = 0;
b9adb4a6 430
e2542fe2 431#ifdef HOST_WORDS_BIGENDIAN
f4359b9f 432 s.info.endian = BFD_ENDIAN_BIG;
b9adb4a6 433#else
f4359b9f 434 s.info.endian = BFD_ENDIAN_LITTLE;
b9adb4a6 435#endif
5826e519
SW
436#if defined(CONFIG_TCG_INTERPRETER)
437 print_insn = print_insn_tci;
438#elif defined(__i386__)
f4359b9f 439 s.info.mach = bfd_mach_i386_i386;
c27004ec 440 print_insn = print_insn_i386;
b666d2a4
RH
441 s.info.cap_arch = CS_ARCH_X86;
442 s.info.cap_mode = CS_MODE_32;
bc51c5c9 443#elif defined(__x86_64__)
f4359b9f 444 s.info.mach = bfd_mach_x86_64;
c27004ec 445 print_insn = print_insn_i386;
b666d2a4
RH
446 s.info.cap_arch = CS_ARCH_X86;
447 s.info.cap_mode = CS_MODE_64;
e58ffeb3 448#elif defined(_ARCH_PPC)
66d4f6a3 449 s.info.disassembler_options = (char *)"any";
c27004ec 450 print_insn = print_insn_ppc;
ac226899
RH
451 s.info.cap_arch = CS_ARCH_PPC;
452# ifdef _ARCH_PPC64
453 s.info.cap_mode = CS_MODE_64;
454# endif
999b53ec
CF
455#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
456 print_insn = print_insn_arm_a64;
110f6c70 457 s.info.cap_arch = CS_ARCH_ARM64;
a993ba85 458#elif defined(__alpha__)
c27004ec 459 print_insn = print_insn_alpha;
aa0aa4fa 460#elif defined(__sparc__)
c27004ec 461 print_insn = print_insn_sparc;
f4359b9f 462 s.info.mach = bfd_mach_sparc_v9b;
5fafdf24 463#elif defined(__arm__)
c27004ec 464 print_insn = print_insn_arm;
110f6c70
RH
465 s.info.cap_arch = CS_ARCH_ARM;
466 /* TCG only generates code for arm mode. */
6af0bf9c
FB
467#elif defined(__MIPSEB__)
468 print_insn = print_insn_big_mips;
469#elif defined(__MIPSEL__)
470 print_insn = print_insn_little_mips;
48024e4a
FB
471#elif defined(__m68k__)
472 print_insn = print_insn_m68k;
8f860bb8
TS
473#elif defined(__s390__)
474 print_insn = print_insn_s390;
429b31a2
RH
475#elif defined(__hppa__)
476 print_insn = print_insn_hppa;
b9adb4a6 477#endif
8ca80760
RH
478
479 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
480 return;
481 }
482
c46ffd57
RH
483 if (print_insn == NULL) {
484 print_insn = print_insn_od_host;
485 }
b0b0f1c9
SW
486 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
487 fprintf(out, "0x%08" PRIxPTR ": ", pc);
f4359b9f 488 count = print_insn(pc, &s.info);
b9adb4a6
FB
489 fprintf(out, "\n");
490 if (count < 0)
491 break;
492 }
493}
494
495/* Look up symbol for debugging purpose. Returns "" if unknown. */
c27004ec 496const char *lookup_symbol(target_ulong orig_addr)
b9adb4a6 497{
49918a75 498 const char *symbol = "";
e80cfcfc 499 struct syminfo *s;
3b46e624 500
e80cfcfc 501 for (s = syminfos; s; s = s->next) {
49918a75
PB
502 symbol = s->lookup_symbol(s, orig_addr);
503 if (symbol[0] != '\0') {
504 break;
505 }
b9adb4a6 506 }
49918a75
PB
507
508 return symbol;
b9adb4a6 509}
9307c4c1
FB
510
511#if !defined(CONFIG_USER_ONLY)
512
83c9089e 513#include "monitor/monitor.h"
3d2cfdf1 514
9307c4c1 515static int
b8d87208 516physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
a5f1b965 517 struct disassemble_info *info)
9307c4c1 518{
b8d87208 519 cpu_physical_memory_read(memaddr, myaddr, length);
9307c4c1
FB
520 return 0;
521}
522
1d48474d 523/* Disassembler for the monitor. */
d49190c4 524void monitor_disas(Monitor *mon, CPUState *cpu,
1d48474d 525 target_ulong pc, int nb_insn, int is_physical)
9307c4c1 526{
37b9de46 527 CPUClass *cc = CPU_GET_CLASS(cpu);
9307c4c1 528 int count, i;
f4359b9f 529 CPUDebug s;
9307c4c1 530
f4359b9f 531 INIT_DISASSEMBLE_INFO(s.info, (FILE *)mon, monitor_fprintf);
9307c4c1 532
d49190c4 533 s.cpu = cpu;
b8d87208
RH
534 s.info.read_memory_func
535 = (is_physical ? physical_read_memory : target_read_memory);
9504c544 536 s.info.print_address_func = generic_print_address;
f4359b9f 537 s.info.buffer_vma = pc;
8ca80760
RH
538 s.info.cap_arch = -1;
539 s.info.cap_mode = 0;
9307c4c1
FB
540
541#ifdef TARGET_WORDS_BIGENDIAN
f4359b9f 542 s.info.endian = BFD_ENDIAN_BIG;
9307c4c1 543#else
f4359b9f 544 s.info.endian = BFD_ENDIAN_LITTLE;
9307c4c1 545#endif
37b9de46
PC
546
547 if (cc->disas_set_info) {
548 cc->disas_set_info(cpu, &s.info);
549 }
550
8ca80760
RH
551 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
552 return;
553 }
554
37b9de46
PC
555 if (!s.info.print_insn) {
556 monitor_printf(mon, "0x" TARGET_FMT_lx
557 ": Asm output not supported on this arch\n", pc);
558 return;
559 }
9307c4c1
FB
560
561 for(i = 0; i < nb_insn; i++) {
376253ec 562 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
2de295c5 563 count = s.info.print_insn(pc, &s.info);
376253ec 564 monitor_printf(mon, "\n");
9307c4c1
FB
565 if (count < 0)
566 break;
567 pc += count;
568 }
569}
570#endif