qemu/disas.c
<<
>>
Prefs
   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
  43    cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
  44    return 0;
  45}
  46
  47/* Print an error message.  We can assume that this is in response to
  48   an error return from buffer_read_memory.  */
  49void
  50perror_memory (int status, bfd_vma memaddr, struct disassemble_info *info)
  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,
  59                           "Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
  60}
  61
  62/* This could be in a separate file, to save minuscule amounts of space
  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
  70generic_print_address (bfd_vma addr, struct disassemble_info *info)
  71{
  72    (*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
  73}
  74
  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
  83/* Just return the given address.  */
  84
  85int
  86generic_symbol_at_address (bfd_vma addr, struct disassemble_info *info)
  87{
  88  return 1;
  89}
  90
  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
 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
 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
 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
 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
 223static void cap_dump_insn_units(disassemble_info *info, cs_insn *insn,
 224                                int i, int n)
 225{
 226    fprintf_function print = info->fprintf_func;
 227    FILE *stream = info->stream;
 228
 229    switch (info->cap_insn_unit) {
 230    case 4:
 231        if (info->endian == BFD_ENDIAN_BIG) {
 232            for (; i < n; i += 4) {
 233                print(stream, " %08x", ldl_be_p(insn->bytes + i));
 234
 235            }
 236        } else {
 237            for (; i < n; i += 4) {
 238                print(stream, " %08x", ldl_le_p(insn->bytes + i));
 239            }
 240        }
 241        break;
 242
 243    case 2:
 244        if (info->endian == BFD_ENDIAN_BIG) {
 245            for (; i < n; i += 2) {
 246                print(stream, " %04x", lduw_be_p(insn->bytes + i));
 247            }
 248        } else {
 249            for (; i < n; i += 2) {
 250                print(stream, " %04x", lduw_le_p(insn->bytes + i));
 251            }
 252        }
 253        break;
 254
 255    default:
 256        for (; i < n; i++) {
 257            print(stream, " %02x", insn->bytes[i]);
 258        }
 259        break;
 260    }
 261}
 262
 263static void cap_dump_insn(disassemble_info *info, cs_insn *insn)
 264{
 265    fprintf_function print = info->fprintf_func;
 266    int i, n, split;
 267
 268    print(info->stream, "0x%08" PRIx64 ": ", insn->address);
 269
 270    n = insn->size;
 271    split = info->cap_insn_split;
 272
 273    /* Dump the first SPLIT bytes of the instruction.  */
 274    cap_dump_insn_units(info, insn, 0, MIN(n, split));
 275
 276    /* Add padding up to SPLIT so that mnemonics line up.  */
 277    if (n < split) {
 278        int width = (split - n) / info->cap_insn_unit;
 279        width *= (2 * info->cap_insn_unit + 1);
 280        print(info->stream, "%*s", width, "");
 281    }
 282
 283    /* Print the actual instruction.  */
 284    print(info->stream, "  %-8s %s\n", insn->mnemonic, insn->op_str);
 285
 286    /* Dump any remaining part of the insn on subsequent lines.  */
 287    for (i = split; i < n; i += split) {
 288        print(info->stream, "0x%08" PRIx64 ": ", insn->address + i);
 289        cap_dump_insn_units(info, insn, i, MIN(n, i + split));
 290        print(info->stream, "\n");
 291    }
 292}
 293
 294/* Disassemble SIZE bytes at PC for the target.  */
 295static bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size)
 296{
 297    uint8_t cap_buf[1024];
 298    csh handle;
 299    cs_insn *insn;
 300    size_t csize = 0;
 301
 302    if (cap_disas_start(info, &handle) != CS_ERR_OK) {
 303        return false;
 304    }
 305    insn = cap_insn;
 306
 307    while (1) {
 308        size_t tsize = MIN(sizeof(cap_buf) - csize, size);
 309        const uint8_t *cbuf = cap_buf;
 310
 311        target_read_memory(pc + csize, cap_buf + csize, tsize, info);
 312        csize += tsize;
 313        size -= tsize;
 314
 315        while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
 316           cap_dump_insn(info, insn);
 317        }
 318
 319        /* If the target memory is not consumed, go back for more... */
 320        if (size != 0) {
 321            /* ... taking care to move any remaining fractional insn
 322               to the beginning of the buffer.  */
 323            if (csize != 0) {
 324                memmove(cap_buf, cbuf, csize);
 325            }
 326            continue;
 327        }
 328
 329        /* Since the target memory is consumed, we should not have
 330           a remaining fractional insn.  */
 331        if (csize != 0) {
 332            (*info->fprintf_func)(info->stream,
 333                "Disassembler disagrees with translator "
 334                "over instruction decoding\n"
 335                "Please report this to qemu-devel@nongnu.org\n");
 336        }
 337        break;
 338    }
 339
 340    cs_close(&handle);
 341    return true;
 342}
 343
 344/* Disassemble SIZE bytes at CODE for the host.  */
 345static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
 346{
 347    csh handle;
 348    const uint8_t *cbuf;
 349    cs_insn *insn;
 350    uint64_t pc;
 351
 352    if (cap_disas_start(info, &handle) != CS_ERR_OK) {
 353        return false;
 354    }
 355    insn = cap_insn;
 356
 357    cbuf = code;
 358    pc = (uintptr_t)code;
 359
 360    while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
 361       cap_dump_insn(info, insn);
 362    }
 363    if (size != 0) {
 364        (*info->fprintf_func)(info->stream,
 365            "Disassembler disagrees with TCG over instruction encoding\n"
 366            "Please report this to qemu-devel@nongnu.org\n");
 367    }
 368
 369    cs_close(&handle);
 370    return true;
 371}
 372
 373#if !defined(CONFIG_USER_ONLY)
 374/* Disassemble COUNT insns at PC for the target.  */
 375static bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count)
 376{
 377    uint8_t cap_buf[32];
 378    csh handle;
 379    cs_insn *insn;
 380    size_t csize = 0;
 381
 382    if (cap_disas_start(info, &handle) != CS_ERR_OK) {
 383        return false;
 384    }
 385    insn = cap_insn;
 386
 387    while (1) {
 388        /* We want to read memory for one insn, but generically we do not
 389           know how much memory that is.  We have a small buffer which is
 390           known to be sufficient for all supported targets.  Try to not
 391           read beyond the page, Just In Case.  For even more simplicity,
 392           ignore the actual target page size and use a 1k boundary.  If
 393           that turns out to be insufficient, we'll come back around the
 394           loop and read more.  */
 395        uint64_t epc = QEMU_ALIGN_UP(pc + csize + 1, 1024);
 396        size_t tsize = MIN(sizeof(cap_buf) - csize, epc - pc);
 397        const uint8_t *cbuf = cap_buf;
 398
 399        /* Make certain that we can make progress.  */
 400        assert(tsize != 0);
 401        info->read_memory_func(pc, cap_buf + csize, tsize, info);
 402        csize += tsize;
 403
 404        if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
 405            cap_dump_insn(info, insn);
 406            if (--count <= 0) {
 407                break;
 408            }
 409        }
 410        memmove(cap_buf, cbuf, csize);
 411    }
 412
 413    cs_close(&handle);
 414    return true;
 415}
 416#endif /* !CONFIG_USER_ONLY */
 417#else
 418# define cap_disas_target(i, p, s)  false
 419# define cap_disas_host(i, p, s)  false
 420# define cap_disas_monitor(i, p, c)  false
 421# define cap_disas_plugin(i, p, c) false
 422#endif /* CONFIG_CAPSTONE */
 423
 424/* Disassemble this for me please... (debugging).  */
 425void target_disas(FILE *out, CPUState *cpu, target_ulong code,
 426                  target_ulong size)
 427{
 428    CPUClass *cc = CPU_GET_CLASS(cpu);
 429    target_ulong pc;
 430    int count;
 431    CPUDebug s;
 432
 433    INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
 434
 435    s.cpu = cpu;
 436    s.info.read_memory_func = target_read_memory;
 437    s.info.buffer_vma = code;
 438    s.info.buffer_length = size;
 439    s.info.print_address_func = generic_print_address;
 440    s.info.cap_arch = -1;
 441    s.info.cap_mode = 0;
 442    s.info.cap_insn_unit = 4;
 443    s.info.cap_insn_split = 4;
 444
 445#ifdef TARGET_WORDS_BIGENDIAN
 446    s.info.endian = BFD_ENDIAN_BIG;
 447#else
 448    s.info.endian = BFD_ENDIAN_LITTLE;
 449#endif
 450
 451    if (cc->disas_set_info) {
 452        cc->disas_set_info(cpu, &s.info);
 453    }
 454
 455    if (s.info.cap_arch >= 0 && cap_disas_target(&s.info, code, size)) {
 456        return;
 457    }
 458
 459    if (s.info.print_insn == NULL) {
 460        s.info.print_insn = print_insn_od_target;
 461    }
 462
 463    for (pc = code; size > 0; pc += count, size -= count) {
 464        fprintf(out, "0x" TARGET_FMT_lx ":  ", pc);
 465        count = s.info.print_insn(pc, &s.info);
 466        fprintf(out, "\n");
 467        if (count < 0)
 468            break;
 469        if (size < count) {
 470            fprintf(out,
 471                    "Disassembler disagrees with translator over instruction "
 472                    "decoding\n"
 473                    "Please report this to qemu-devel@nongnu.org\n");
 474            break;
 475        }
 476    }
 477}
 478
 479static __thread GString plugin_disas_output;
 480
 481static int plugin_printf(FILE *stream, const char *fmt, ...)
 482{
 483    va_list va;
 484    GString *s = &plugin_disas_output;
 485    int initial_len = s->len;
 486
 487    va_start(va, fmt);
 488    g_string_append_vprintf(s, fmt, va);
 489    va_end(va);
 490
 491    return s->len - initial_len;
 492}
 493
 494static void plugin_print_address(bfd_vma addr, struct disassemble_info *info)
 495{
 496    /* does nothing */
 497}
 498
 499
 500#ifdef CONFIG_CAPSTONE
 501/* Disassemble a single instruction directly into plugin output */
 502static
 503bool cap_disas_plugin(disassemble_info *info, uint64_t pc, size_t size)
 504{
 505    uint8_t cap_buf[1024];
 506    csh handle;
 507    cs_insn *insn;
 508    size_t csize = 0;
 509    int count;
 510    GString *s = &plugin_disas_output;
 511
 512    if (cap_disas_start(info, &handle) != CS_ERR_OK) {
 513        return false;
 514    }
 515    insn = cap_insn;
 516
 517    size_t tsize = MIN(sizeof(cap_buf) - csize, size);
 518    const uint8_t *cbuf = cap_buf;
 519    target_read_memory(pc, cap_buf, tsize, info);
 520
 521    count = cs_disasm(handle, cbuf, size, 0, 1, &insn);
 522
 523    if (count) {
 524        g_string_printf(s, "%s %s", insn->mnemonic, insn->op_str);
 525    } else {
 526        g_string_printf(s, "cs_disasm failed");
 527    }
 528
 529    cs_close(&handle);
 530    return true;
 531}
 532#endif
 533
 534/*
 535 * We should only be dissembling one instruction at a time here. If
 536 * there is left over it usually indicates the front end has read more
 537 * bytes than it needed.
 538 */
 539char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size)
 540{
 541    CPUClass *cc = CPU_GET_CLASS(cpu);
 542    int count;
 543    CPUDebug s;
 544    GString *ds = g_string_set_size(&plugin_disas_output, 0);
 545
 546    g_assert(ds == &plugin_disas_output);
 547
 548    INIT_DISASSEMBLE_INFO(s.info, NULL, plugin_printf);
 549
 550    s.cpu = cpu;
 551    s.info.read_memory_func = target_read_memory;
 552    s.info.buffer_vma = addr;
 553    s.info.buffer_length = size;
 554    s.info.print_address_func = plugin_print_address;
 555    s.info.cap_arch = -1;
 556    s.info.cap_mode = 0;
 557    s.info.cap_insn_unit = 4;
 558    s.info.cap_insn_split = 4;
 559
 560#ifdef TARGET_WORDS_BIGENDIAN
 561    s.info.endian = BFD_ENDIAN_BIG;
 562#else
 563    s.info.endian = BFD_ENDIAN_LITTLE;
 564#endif
 565
 566    if (cc->disas_set_info) {
 567        cc->disas_set_info(cpu, &s.info);
 568    }
 569
 570    if (s.info.cap_arch >= 0 && cap_disas_plugin(&s.info, addr, size)) {
 571        return g_strdup(ds->str);
 572    }
 573
 574    if (s.info.print_insn == NULL) {
 575        s.info.print_insn = print_insn_od_target;
 576    }
 577
 578    count = s.info.print_insn(addr, &s.info);
 579
 580    /* The decoder probably read more than it needed it's not critical */
 581    if (count < size) {
 582        warn_report("%s: %zu bytes left over", __func__, size - count);
 583    }
 584
 585    return g_strdup(ds->str);
 586}
 587
 588/* Disassemble this for me please... (debugging). */
 589void disas(FILE *out, void *code, unsigned long size)
 590{
 591    uintptr_t pc;
 592    int count;
 593    CPUDebug s;
 594    int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
 595
 596    INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
 597    s.info.print_address_func = generic_print_host_address;
 598
 599    s.info.buffer = code;
 600    s.info.buffer_vma = (uintptr_t)code;
 601    s.info.buffer_length = size;
 602    s.info.cap_arch = -1;
 603    s.info.cap_mode = 0;
 604    s.info.cap_insn_unit = 4;
 605    s.info.cap_insn_split = 4;
 606
 607#ifdef HOST_WORDS_BIGENDIAN
 608    s.info.endian = BFD_ENDIAN_BIG;
 609#else
 610    s.info.endian = BFD_ENDIAN_LITTLE;
 611#endif
 612#if defined(CONFIG_TCG_INTERPRETER)
 613    print_insn = print_insn_tci;
 614#elif defined(__i386__)
 615    s.info.mach = bfd_mach_i386_i386;
 616    print_insn = print_insn_i386;
 617    s.info.cap_arch = CS_ARCH_X86;
 618    s.info.cap_mode = CS_MODE_32;
 619    s.info.cap_insn_unit = 1;
 620    s.info.cap_insn_split = 8;
 621#elif defined(__x86_64__)
 622    s.info.mach = bfd_mach_x86_64;
 623    print_insn = print_insn_i386;
 624    s.info.cap_arch = CS_ARCH_X86;
 625    s.info.cap_mode = CS_MODE_64;
 626    s.info.cap_insn_unit = 1;
 627    s.info.cap_insn_split = 8;
 628#elif defined(_ARCH_PPC)
 629    s.info.disassembler_options = (char *)"any";
 630    print_insn = print_insn_ppc;
 631    s.info.cap_arch = CS_ARCH_PPC;
 632# ifdef _ARCH_PPC64
 633    s.info.cap_mode = CS_MODE_64;
 634# endif
 635#elif defined(__riscv) && defined(CONFIG_RISCV_DIS)
 636#if defined(_ILP32) || (__riscv_xlen == 32)
 637    print_insn = print_insn_riscv32;
 638#elif defined(_LP64)
 639    print_insn = print_insn_riscv64;
 640#else
 641#error unsupported RISC-V ABI
 642#endif
 643#elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
 644    print_insn = print_insn_arm_a64;
 645    s.info.cap_arch = CS_ARCH_ARM64;
 646#elif defined(__alpha__)
 647    print_insn = print_insn_alpha;
 648#elif defined(__sparc__)
 649    print_insn = print_insn_sparc;
 650    s.info.mach = bfd_mach_sparc_v9b;
 651#elif defined(__arm__)
 652    print_insn = print_insn_arm;
 653    s.info.cap_arch = CS_ARCH_ARM;
 654    /* TCG only generates code for arm mode.  */
 655#elif defined(__MIPSEB__)
 656    print_insn = print_insn_big_mips;
 657#elif defined(__MIPSEL__)
 658    print_insn = print_insn_little_mips;
 659#elif defined(__m68k__)
 660    print_insn = print_insn_m68k;
 661#elif defined(__s390__)
 662    print_insn = print_insn_s390;
 663#elif defined(__hppa__)
 664    print_insn = print_insn_hppa;
 665#endif
 666
 667    if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
 668        return;
 669    }
 670
 671    if (print_insn == NULL) {
 672        print_insn = print_insn_od_host;
 673    }
 674    for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
 675        fprintf(out, "0x%08" PRIxPTR ":  ", pc);
 676        count = print_insn(pc, &s.info);
 677        fprintf(out, "\n");
 678        if (count < 0)
 679            break;
 680    }
 681}
 682
 683/* Look up symbol for debugging purpose.  Returns "" if unknown. */
 684const char *lookup_symbol(target_ulong orig_addr)
 685{
 686    const char *symbol = "";
 687    struct syminfo *s;
 688
 689    for (s = syminfos; s; s = s->next) {
 690        symbol = s->lookup_symbol(s, orig_addr);
 691        if (symbol[0] != '\0') {
 692            break;
 693        }
 694    }
 695
 696    return symbol;
 697}
 698
 699#if !defined(CONFIG_USER_ONLY)
 700
 701#include "monitor/monitor.h"
 702
 703static int
 704physical_read_memory(bfd_vma memaddr, bfd_byte *myaddr, int length,
 705                     struct disassemble_info *info)
 706{
 707    CPUDebug *s = container_of(info, CPUDebug, info);
 708
 709    address_space_read(s->cpu->as, memaddr, MEMTXATTRS_UNSPECIFIED,
 710                       myaddr, length);
 711    return 0;
 712}
 713
 714/* Disassembler for the monitor.  */
 715void monitor_disas(Monitor *mon, CPUState *cpu,
 716                   target_ulong pc, int nb_insn, int is_physical)
 717{
 718    CPUClass *cc = CPU_GET_CLASS(cpu);
 719    int count, i;
 720    CPUDebug s;
 721
 722    INIT_DISASSEMBLE_INFO(s.info, NULL, qemu_fprintf);
 723
 724    s.cpu = cpu;
 725    s.info.read_memory_func
 726        = (is_physical ? physical_read_memory : target_read_memory);
 727    s.info.print_address_func = generic_print_address;
 728    s.info.buffer_vma = pc;
 729    s.info.cap_arch = -1;
 730    s.info.cap_mode = 0;
 731    s.info.cap_insn_unit = 4;
 732    s.info.cap_insn_split = 4;
 733
 734#ifdef TARGET_WORDS_BIGENDIAN
 735    s.info.endian = BFD_ENDIAN_BIG;
 736#else
 737    s.info.endian = BFD_ENDIAN_LITTLE;
 738#endif
 739
 740    if (cc->disas_set_info) {
 741        cc->disas_set_info(cpu, &s.info);
 742    }
 743
 744    if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) {
 745        return;
 746    }
 747
 748    if (!s.info.print_insn) {
 749        monitor_printf(mon, "0x" TARGET_FMT_lx
 750                       ": Asm output not supported on this arch\n", pc);
 751        return;
 752    }
 753
 754    for(i = 0; i < nb_insn; i++) {
 755        monitor_printf(mon, "0x" TARGET_FMT_lx ":  ", pc);
 756        count = s.info.print_insn(pc, &s.info);
 757        monitor_printf(mon, "\n");
 758        if (count < 0)
 759            break;
 760        pc += count;
 761    }
 762}
 763#endif
 764