blob: e392a2926e52319ea124a7450a67811f8cb1a2f5 [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"
Peter Crosthwaite37b9de42015-06-23 20:57:33 -07003#include "qemu-common.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +02004#include "disas/bfd.h"
bellardb9adb4a2003-04-29 20:41:16 +00005#include "elf.h"
6
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);
42
Peter Crosthwaited49190c2015-05-24 14:20:41 -070043 cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
bellardc6105c02003-10-27 21:13:58 +000044 return 0;
45}
bellardc6105c02003-10-27 21:13:58 +000046
bellardaa0aa4f2003-06-09 15:23:31 +000047/* Print an error message. We can assume that this is in response to
48 an error return from buffer_read_memory. */
49void
pbrook3a742b72008-10-22 15:55:18 +000050perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
bellardaa0aa4f2003-06-09 15:23:31 +000051{
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,
bellard26a76462006-06-25 18:15:32 +000059 "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
bellardaa0aa4f2003-06-09 15:23:31 +000060}
61
Jim Meyeringa31f0532012-05-09 05:12:04 +000062/* This could be in a separate file, to save minuscule amounts of space
bellardaa0aa4f2003-06-09 15:23:31 +000063 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
pbrook3a742b72008-10-22 15:55:18 +000070generic_print_address (bfd_vma addr, struct disassemble_info *info)
bellardaa0aa4f2003-06-09 15:23:31 +000071{
bellard26a76462006-06-25 18:15:32 +000072 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
bellardaa0aa4f2003-06-09 15:23:31 +000073}
74
Peter Maydell636bd282012-06-25 04:55:55 +000075/* 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
bellardaa0aa4f2003-06-09 15:23:31 +000083/* Just return the given address. */
84
85int
pbrook3a742b72008-10-22 15:55:18 +000086generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
bellardaa0aa4f2003-06-09 15:23:31 +000087{
88 return 1;
89}
90
Aurelien Jarno903ec552010-03-29 02:12:51 +020091bfd_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
bellardaa0aa4f2003-06-09 15:23:31 +0000106bfd_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
bellard6af0bf92005-07-02 14:58:51 +0000128bfd_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
Richard Hendersonc46ffd52013-08-16 23:29:45 -0700146static 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
Richard Henderson8ca80762017-09-14 09:41:12 -0700175#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
Richard Henderson1d484742017-09-14 08:38:35 -0700361/* Disassemble this for me please... (debugging). */
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700362void target_disas(FILE *out, CPUState *cpu, target_ulong code,
Richard Henderson1d484742017-09-14 08:38:35 -0700363 target_ulong size)
bellardb9adb4a2003-04-29 20:41:16 +0000364{
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700365 CPUClass *cc = CPU_GET_CLASS(cpu);
bellardc27004e2005-01-03 23:35:10 +0000366 target_ulong pc;
bellardb9adb4a2003-04-29 20:41:16 +0000367 int count;
Blue Swirlf4359b92012-09-08 12:40:00 +0000368 CPUDebug s;
bellardb9adb4a2003-04-29 20:41:16 +0000369
Blue Swirlf4359b92012-09-08 12:40:00 +0000370 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
bellardb9adb4a2003-04-29 20:41:16 +0000371
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700372 s.cpu = cpu;
Blue Swirlf4359b92012-09-08 12:40:00 +0000373 s.info.read_memory_func = target_read_memory;
374 s.info.buffer_vma = code;
375 s.info.buffer_length = size;
Peter Crosthwaite9504c542015-07-05 13:50:32 -0700376 s.info.print_address_func = generic_print_address;
Richard Henderson8ca80762017-09-14 09:41:12 -0700377 s.info.cap_arch = -1;
378 s.info.cap_mode = 0;
bellardc27004e2005-01-03 23:35:10 +0000379
380#ifdef TARGET_WORDS_BIGENDIAN
Blue Swirlf4359b92012-09-08 12:40:00 +0000381 s.info.endian = BFD_ENDIAN_BIG;
bellardc27004e2005-01-03 23:35:10 +0000382#else
Blue Swirlf4359b92012-09-08 12:40:00 +0000383 s.info.endian = BFD_ENDIAN_LITTLE;
bellardc6105c02003-10-27 21:13:58 +0000384#endif
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700385
386 if (cc->disas_set_info) {
387 cc->disas_set_info(cpu, &s.info);
388 }
389
Richard Henderson8ca80762017-09-14 09:41:12 -0700390 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
391 return;
392 }
393
Peter Crosthwaite2de295c2015-06-23 20:57:32 -0700394 if (s.info.print_insn == NULL) {
395 s.info.print_insn = print_insn_od_target;
Richard Hendersonc46ffd52013-08-16 23:29:45 -0700396 }
bellardc27004e2005-01-03 23:35:10 +0000397
blueswir17e000c22009-02-13 21:44:41 +0000398 for (pc = code; size > 0; pc += count, size -= count) {
bellardfa15e032005-01-31 23:32:31 +0000399 fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
Peter Crosthwaite2de295c2015-06-23 20:57:32 -0700400 count = s.info.print_insn(pc, &s.info);
bellardc27004e2005-01-03 23:35:10 +0000401 fprintf(out, "\n");
402 if (count < 0)
403 break;
malc754d00a2009-04-21 22:26:22 +0000404 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 }
bellardc27004e2005-01-03 23:35:10 +0000411 }
412}
413
414/* Disassemble this for me please... (debugging). */
415void disas(FILE *out, void *code, unsigned long size)
416{
Stefan Weilb0b0f1c2012-04-12 15:44:35 +0200417 uintptr_t pc;
bellardc27004e2005-01-03 23:35:10 +0000418 int count;
Blue Swirlf4359b92012-09-08 12:40:00 +0000419 CPUDebug s;
Richard Hendersonc46ffd52013-08-16 23:29:45 -0700420 int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
bellardc27004e2005-01-03 23:35:10 +0000421
Blue Swirlf4359b92012-09-08 12:40:00 +0000422 INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
423 s.info.print_address_func = generic_print_host_address;
bellardc6105c02003-10-27 21:13:58 +0000424
Blue Swirlf4359b92012-09-08 12:40:00 +0000425 s.info.buffer = code;
426 s.info.buffer_vma = (uintptr_t)code;
427 s.info.buffer_length = size;
Richard Henderson8ca80762017-09-14 09:41:12 -0700428 s.info.cap_arch = -1;
429 s.info.cap_mode = 0;
bellardb9adb4a2003-04-29 20:41:16 +0000430
Juan Quintelae2542fe2009-07-27 16:13:06 +0200431#ifdef HOST_WORDS_BIGENDIAN
Blue Swirlf4359b92012-09-08 12:40:00 +0000432 s.info.endian = BFD_ENDIAN_BIG;
bellardb9adb4a2003-04-29 20:41:16 +0000433#else
Blue Swirlf4359b92012-09-08 12:40:00 +0000434 s.info.endian = BFD_ENDIAN_LITTLE;
bellardb9adb4a2003-04-29 20:41:16 +0000435#endif
Stefan Weil5826e512011-10-05 20:03:53 +0200436#if defined(CONFIG_TCG_INTERPRETER)
437 print_insn = print_insn_tci;
438#elif defined(__i386__)
Blue Swirlf4359b92012-09-08 12:40:00 +0000439 s.info.mach = bfd_mach_i386_i386;
bellardc27004e2005-01-03 23:35:10 +0000440 print_insn = print_insn_i386;
bellardbc51c5c2004-03-17 23:46:04 +0000441#elif defined(__x86_64__)
Blue Swirlf4359b92012-09-08 12:40:00 +0000442 s.info.mach = bfd_mach_x86_64;
bellardc27004e2005-01-03 23:35:10 +0000443 print_insn = print_insn_i386;
malce58ffeb2009-01-14 18:39:49 +0000444#elif defined(_ARCH_PPC)
Richard Henderson66d4f6a2013-01-31 11:16:21 -0800445 s.info.disassembler_options = (char *)"any";
bellardc27004e2005-01-03 23:35:10 +0000446 print_insn = print_insn_ppc;
Claudio Fontana999b53e2014-02-05 17:27:28 +0000447#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
448 print_insn = print_insn_arm_a64;
bellarda993ba82003-05-11 12:25:45 +0000449#elif defined(__alpha__)
bellardc27004e2005-01-03 23:35:10 +0000450 print_insn = print_insn_alpha;
bellardaa0aa4f2003-06-09 15:23:31 +0000451#elif defined(__sparc__)
bellardc27004e2005-01-03 23:35:10 +0000452 print_insn = print_insn_sparc;
Blue Swirlf4359b92012-09-08 12:40:00 +0000453 s.info.mach = bfd_mach_sparc_v9b;
ths5fafdf22007-09-16 21:08:06 +0000454#elif defined(__arm__)
bellardc27004e2005-01-03 23:35:10 +0000455 print_insn = print_insn_arm;
bellard6af0bf92005-07-02 14:58:51 +0000456#elif defined(__MIPSEB__)
457 print_insn = print_insn_big_mips;
458#elif defined(__MIPSEL__)
459 print_insn = print_insn_little_mips;
bellard48024e42005-11-06 16:52:11 +0000460#elif defined(__m68k__)
461 print_insn = print_insn_m68k;
ths8f860bb2007-07-31 23:44:21 +0000462#elif defined(__s390__)
463 print_insn = print_insn_s390;
Richard Henderson429b31a2016-09-29 10:55:53 -0700464#elif defined(__hppa__)
465 print_insn = print_insn_hppa;
bellardb9adb4a2003-04-29 20:41:16 +0000466#endif
Richard Henderson8ca80762017-09-14 09:41:12 -0700467
468 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
469 return;
470 }
471
Richard Hendersonc46ffd52013-08-16 23:29:45 -0700472 if (print_insn == NULL) {
473 print_insn = print_insn_od_host;
474 }
Stefan Weilb0b0f1c2012-04-12 15:44:35 +0200475 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
476 fprintf(out, "0x%08" PRIxPTR ": ", pc);
Blue Swirlf4359b92012-09-08 12:40:00 +0000477 count = print_insn(pc, &s.info);
bellardb9adb4a2003-04-29 20:41:16 +0000478 fprintf(out, "\n");
479 if (count < 0)
480 break;
481 }
482}
483
484/* Look up symbol for debugging purpose. Returns "" if unknown. */
bellardc27004e2005-01-03 23:35:10 +0000485const char *lookup_symbol(target_ulong orig_addr)
bellardb9adb4a2003-04-29 20:41:16 +0000486{
pbrook49918a72008-10-22 15:11:31 +0000487 const char *symbol = "";
bellarde80cfcf2004-12-19 23:18:01 +0000488 struct syminfo *s;
ths3b46e622007-09-17 08:09:54 +0000489
bellarde80cfcf2004-12-19 23:18:01 +0000490 for (s = syminfos; s; s = s->next) {
pbrook49918a72008-10-22 15:11:31 +0000491 symbol = s->lookup_symbol(s, orig_addr);
492 if (symbol[0] != '\0') {
493 break;
494 }
bellardb9adb4a2003-04-29 20:41:16 +0000495 }
pbrook49918a72008-10-22 15:11:31 +0000496
497 return symbol;
bellardb9adb4a2003-04-29 20:41:16 +0000498}
bellard9307c4c2004-04-04 12:57:25 +0000499
500#if !defined(CONFIG_USER_ONLY)
501
Paolo Bonzini83c90892012-12-17 18:19:49 +0100502#include "monitor/monitor.h"
bellard3d2cfdf2004-08-01 21:49:07 +0000503
bellard9307c4c2004-04-04 12:57:25 +0000504static int monitor_disas_is_physical;
505
506static int
blueswir1a5f1b962008-08-17 20:21:51 +0000507monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
508 struct disassemble_info *info)
bellard9307c4c2004-04-04 12:57:25 +0000509{
Blue Swirlf4359b92012-09-08 12:40:00 +0000510 CPUDebug *s = container_of(info, CPUDebug, info);
511
bellard9307c4c2004-04-04 12:57:25 +0000512 if (monitor_disas_is_physical) {
Stefan Weil54f7b4a2011-04-10 18:23:39 +0200513 cpu_physical_memory_read(memaddr, myaddr, length);
bellard9307c4c2004-04-04 12:57:25 +0000514 } else {
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700515 cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
bellard9307c4c2004-04-04 12:57:25 +0000516 }
517 return 0;
518}
519
Richard Henderson1d484742017-09-14 08:38:35 -0700520/* Disassembler for the monitor. */
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700521void monitor_disas(Monitor *mon, CPUState *cpu,
Richard Henderson1d484742017-09-14 08:38:35 -0700522 target_ulong pc, int nb_insn, int is_physical)
bellard9307c4c2004-04-04 12:57:25 +0000523{
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700524 CPUClass *cc = CPU_GET_CLASS(cpu);
bellard9307c4c2004-04-04 12:57:25 +0000525 int count, i;
Blue Swirlf4359b92012-09-08 12:40:00 +0000526 CPUDebug s;
bellard9307c4c2004-04-04 12:57:25 +0000527
Blue Swirlf4359b92012-09-08 12:40:00 +0000528 INIT_DISASSEMBLE_INFO(s.info, (FILE *)mon, monitor_fprintf);
bellard9307c4c2004-04-04 12:57:25 +0000529
Peter Crosthwaited49190c2015-05-24 14:20:41 -0700530 s.cpu = cpu;
bellard9307c4c2004-04-04 12:57:25 +0000531 monitor_disas_is_physical = is_physical;
Blue Swirlf4359b92012-09-08 12:40:00 +0000532 s.info.read_memory_func = monitor_read_memory;
Peter Crosthwaite9504c542015-07-05 13:50:32 -0700533 s.info.print_address_func = generic_print_address;
Blue Swirlf4359b92012-09-08 12:40:00 +0000534 s.info.buffer_vma = pc;
Richard Henderson8ca80762017-09-14 09:41:12 -0700535 s.info.cap_arch = -1;
536 s.info.cap_mode = 0;
bellard9307c4c2004-04-04 12:57:25 +0000537
538#ifdef TARGET_WORDS_BIGENDIAN
Blue Swirlf4359b92012-09-08 12:40:00 +0000539 s.info.endian = BFD_ENDIAN_BIG;
bellard9307c4c2004-04-04 12:57:25 +0000540#else
Blue Swirlf4359b92012-09-08 12:40:00 +0000541 s.info.endian = BFD_ENDIAN_LITTLE;
bellard9307c4c2004-04-04 12:57:25 +0000542#endif
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700543
544 if (cc->disas_set_info) {
545 cc->disas_set_info(cpu, &s.info);
546 }
547
Richard Henderson8ca80762017-09-14 09:41:12 -0700548 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
549 return;
550 }
551
Peter Crosthwaite37b9de42015-06-23 20:57:33 -0700552 if (!s.info.print_insn) {
553 monitor_printf(mon, "0x" TARGET_FMT_lx
554 ": Asm output not supported on this arch\n", pc);
555 return;
556 }
bellard9307c4c2004-04-04 12:57:25 +0000557
558 for(i = 0; i < nb_insn; i++) {
aliguori376253e2009-03-05 23:01:23 +0000559 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc);
Peter Crosthwaite2de295c2015-06-23 20:57:32 -0700560 count = s.info.print_insn(pc, &s.info);
aliguori376253e2009-03-05 23:01:23 +0000561 monitor_printf(mon, "\n");
bellard9307c4c2004-04-04 12:57:25 +0000562 if (count < 0)
563 break;
564 pc += count;
565 }
566}
567#endif