qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio
at master 779 lines 22 kB view raw
1/* General "disassemble this chunk" code. Used for debugging. */ 2#include "qemu/osdep.h" 3#include "disas/dis-asm.h" 4#include "elf.h" 5#include "qemu/qemu-print.h" 6 7#include "cpu.h" 8#include "disas/disas.h" 9#include "disas/capstone.h" 10 11typedef struct CPUDebug { 12 struct disassemble_info info; 13 CPUState *cpu; 14} CPUDebug; 15 16/* Filled in by elfload.c. Simplistic, but will do for now. */ 17struct syminfo *syminfos = NULL; 18 19/* Get LENGTH bytes from info's buffer, at target address memaddr. 20 Transfer them to myaddr. */ 21int 22buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, 23 struct disassemble_info *info) 24{ 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; 31} 32 33/* Get LENGTH bytes from info's buffer, at target address memaddr. 34 Transfer them to myaddr. */ 35static int 36target_read_memory (bfd_vma memaddr, 37 bfd_byte *myaddr, 38 int length, 39 struct disassemble_info *info) 40{ 41 CPUDebug *s = container_of(info, CPUDebug, info); 42 int r; 43 44 r = cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); 45 46 return r ? EIO : 0; 47} 48 49/* Print an error message. We can assume that this is in response to 50 an error return from buffer_read_memory. */ 51void 52perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info) 53{ 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, 61 "Address 0x%" PRIx64 " is out of bounds.\n", memaddr); 62} 63 64/* This could be in a separate file, to save minuscule amounts of space 65 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 72generic_print_address (bfd_vma addr, struct disassemble_info *info) 73{ 74 (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr); 75} 76 77/* 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 85/* Just return the given address. */ 86 87int 88generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info) 89{ 90 return 1; 91} 92 93bfd_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 108bfd_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 130bfd_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 148static 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 177#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 225static 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 265static void cap_dump_insn(disassemble_info *info, cs_insn *insn, 266 const char *note) 267{ 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. */ 287 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"); 292 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 301/* 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)) { 323 cap_dump_insn(info, insn, NULL); 324 } 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. */ 352static bool cap_disas_host(disassemble_info *info, void *code, size_t size, 353 const char *note) 354{ 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)) { 369 cap_dump_insn(info, insn, note); 370 note = NULL; 371 } 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)) { 414 cap_dump_insn(info, insn, NULL); 415 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 428# define cap_disas_host(i, p, s, n) false 429# define cap_disas_monitor(i, p, c) false 430# define cap_disas_plugin(i, p, c) false 431#endif /* CONFIG_CAPSTONE */ 432 433/* Disassemble this for me please... (debugging). */ 434void target_disas(FILE *out, CPUState *cpu, target_ulong code, 435 target_ulong size) 436{ 437 CPUClass *cc = CPU_GET_CLASS(cpu); 438 target_ulong pc; 439 int count; 440 CPUDebug s; 441 442 INIT_DISASSEMBLE_INFO(s.info, out, fprintf); 443 444 s.cpu = cpu; 445 s.info.read_memory_func = target_read_memory; 446 s.info.buffer_vma = code; 447 s.info.buffer_length = size; 448 s.info.print_address_func = generic_print_address; 449 s.info.cap_arch = -1; 450 s.info.cap_mode = 0; 451 s.info.cap_insn_unit = 4; 452 s.info.cap_insn_split = 4; 453 454#ifdef TARGET_WORDS_BIGENDIAN 455 s.info.endian = BFD_ENDIAN_BIG; 456#else 457 s.info.endian = BFD_ENDIAN_LITTLE; 458#endif 459 460 if (cc->disas_set_info) { 461 cc->disas_set_info(cpu, &s.info); 462 } 463 464 if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) { 465 return; 466 } 467 468 if (s.info.print_insn == NULL) { 469 s.info.print_insn = print_insn_od_target; 470 } 471 472 for (pc = code; size > 0; pc += count, size -= count) { 473 fprintf(out, "0x" TARGET_FMT_lx ": ", pc); 474 count = s.info.print_insn(pc, &s.info); 475 fprintf(out, "\n"); 476 if (count < 0) 477 break; 478 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 } 485 } 486} 487 488static __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 597/* Disassemble this for me please... (debugging). */ 598void disas(FILE *out, void *code, unsigned long size, const char *note) 599{ 600 uintptr_t pc; 601 int count; 602 CPUDebug s; 603 int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL; 604 605 INIT_DISASSEMBLE_INFO(s.info, out, fprintf); 606 s.info.print_address_func = generic_print_host_address; 607 608 s.info.buffer = code; 609 s.info.buffer_vma = (uintptr_t)code; 610 s.info.buffer_length = size; 611 s.info.cap_arch = -1; 612 s.info.cap_mode = 0; 613 s.info.cap_insn_unit = 4; 614 s.info.cap_insn_split = 4; 615 616#ifdef HOST_WORDS_BIGENDIAN 617 s.info.endian = BFD_ENDIAN_BIG; 618#else 619 s.info.endian = BFD_ENDIAN_LITTLE; 620#endif 621#if defined(CONFIG_TCG_INTERPRETER) 622 print_insn = print_insn_tci; 623#elif defined(__i386__) 624 s.info.mach = bfd_mach_i386_i386; 625 print_insn = print_insn_i386; 626 s.info.cap_arch = CS_ARCH_X86; 627 s.info.cap_mode = CS_MODE_32; 628 s.info.cap_insn_unit = 1; 629 s.info.cap_insn_split = 8; 630#elif defined(__x86_64__) 631 s.info.mach = bfd_mach_x86_64; 632 print_insn = print_insn_i386; 633 s.info.cap_arch = CS_ARCH_X86; 634 s.info.cap_mode = CS_MODE_64; 635 s.info.cap_insn_unit = 1; 636 s.info.cap_insn_split = 8; 637#elif defined(_ARCH_PPC) 638 s.info.disassembler_options = (char *)"any"; 639 print_insn = print_insn_ppc; 640 s.info.cap_arch = CS_ARCH_PPC; 641# ifdef _ARCH_PPC64 642 s.info.cap_mode = CS_MODE_64; 643# endif 644#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 652#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS) 653 print_insn = print_insn_arm_a64; 654 s.info.cap_arch = CS_ARCH_ARM64; 655#elif defined(__alpha__) 656 print_insn = print_insn_alpha; 657#elif defined(__sparc__) 658 print_insn = print_insn_sparc; 659 s.info.mach = bfd_mach_sparc_v9b; 660#elif defined(__arm__) 661 print_insn = print_insn_arm; 662 s.info.cap_arch = CS_ARCH_ARM; 663 /* TCG only generates code for arm mode. */ 664#elif defined(__MIPSEB__) 665 print_insn = print_insn_big_mips; 666#elif defined(__MIPSEL__) 667 print_insn = print_insn_little_mips; 668#elif defined(__m68k__) 669 print_insn = print_insn_m68k; 670#elif defined(__s390__) 671 print_insn = print_insn_s390; 672#elif defined(__hppa__) 673 print_insn = print_insn_hppa; 674#endif 675 676 if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size, note)) { 677 return; 678 } 679 680 if (print_insn == NULL) { 681 print_insn = print_insn_od_host; 682 } 683 for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) { 684 fprintf(out, "0x%08" PRIxPTR ": ", pc); 685 count = print_insn(pc, &s.info); 686 if (note) { 687 fprintf(out, "\t\t%s", note); 688 note = NULL; 689 } 690 fprintf(out, "\n"); 691 if (count < 0) { 692 break; 693 } 694 } 695 696} 697 698/* Look up symbol for debugging purpose. Returns "" if unknown. */ 699const char *lookup_symbol(target_ulong orig_addr) 700{ 701 const char *symbol = ""; 702 struct syminfo *s; 703 704 for (s = syminfos; s; s = s->next) { 705 symbol = s->lookup_symbol(s, orig_addr); 706 if (symbol[0] != '\0') { 707 break; 708 } 709 } 710 711 return symbol; 712} 713 714#if !defined(CONFIG_USER_ONLY) 715 716#include "monitor/monitor.h" 717 718static int 719physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length, 720 struct disassemble_info *info) 721{ 722 CPUDebug *s = container_of(info, CPUDebug, info); 723 MemTxResult res; 724 725 res = address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED, 726 myaddr, length); 727 return res == MEMTX_OK ? 0 : EIO; 728} 729 730/* Disassembler for the monitor. */ 731void monitor_disas(Monitor *mon, CPUState *cpu, 732 target_ulong pc, int nb_insn, int is_physical) 733{ 734 CPUClass *cc = CPU_GET_CLASS(cpu); 735 int count, i; 736 CPUDebug s; 737 738 INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf); 739 740 s.cpu = cpu; 741 s.info.read_memory_func 742 = (is_physical ? physical_read_memory : target_read_memory); 743 s.info.print_address_func = generic_print_address; 744 s.info.buffer_vma = pc; 745 s.info.cap_arch = -1; 746 s.info.cap_mode = 0; 747 s.info.cap_insn_unit = 4; 748 s.info.cap_insn_split = 4; 749 750#ifdef TARGET_WORDS_BIGENDIAN 751 s.info.endian = BFD_ENDIAN_BIG; 752#else 753 s.info.endian = BFD_ENDIAN_LITTLE; 754#endif 755 756 if (cc->disas_set_info) { 757 cc->disas_set_info(cpu, &s.info); 758 } 759 760 if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) { 761 return; 762 } 763 764 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 } 769 770 for(i = 0; i < nb_insn; i++) { 771 monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc); 772 count = s.info.print_insn(pc, &s.info); 773 monitor_printf(mon, "\n"); 774 if (count < 0) 775 break; 776 pc += count; 777 } 778} 779#endif