alpha disas (Falk Hueffner)
[qemu] / disas.c
1 /* General "disassemble this chunk" code.  Used for debugging. */
2 #include "dis-asm.h"
3 #include "disas.h"
4 #include "elf.h"
5
6 /* Filled in by elfload.c.  Simplistic, but will do for now. */
7 unsigned int disas_num_syms;
8 void *disas_symtab;
9 const char *disas_strtab;
10
11 /* Disassemble this for me please... (debugging). */
12 void disas(FILE *out, void *code, unsigned long size, enum disas_type type)
13 {
14     uint8_t *pc;
15     int count;
16     struct disassemble_info disasm_info;
17     int (*print_insn)(bfd_vma pc, disassemble_info *info);
18
19     INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
20
21     disasm_info.buffer = code;
22     disasm_info.buffer_vma = (unsigned long)code;
23     disasm_info.buffer_length = size;
24
25     if (type == DISAS_TARGET) {
26 #ifdef WORDS_BIGENDIAN
27         disasm_info.endian = BFD_ENDIAN_BIG;
28 #else
29         disasm_info.endian = BFD_ENDIAN_LITTLE;
30 #endif
31 #ifdef __i386__
32         disasm_info.mach = bfd_mach_i386_i386;
33         print_insn = print_insn_i386;
34 #elif defined(__powerpc__)
35         print_insn = print_insn_ppc;
36 #elif defined(__alpha__)
37         print_insn = print_insn_alpha;
38 #else
39         fprintf(out, "Asm output not supported on this arch\n");
40         return;
41 #endif
42     } else {
43         /* Currently only source supported in x86. */
44         disasm_info.endian = BFD_ENDIAN_LITTLE;
45         if (type == DISAS_I386_I386)
46             disasm_info.mach = bfd_mach_i386_i386;
47         else
48             disasm_info.mach = bfd_mach_i386_i8086;
49         print_insn = print_insn_i386;
50     }
51
52     for (pc = code; pc < (uint8_t *)code + size; pc += count) {
53         fprintf(out, "0x%08lx:  ", (long)pc);
54         count = print_insn((long)pc, &disasm_info);
55         fprintf(out, "\n");
56         if (count < 0)
57             break;
58     }
59 }
60
61 /* Look up symbol for debugging purpose.  Returns "" if unknown. */
62 const char *lookup_symbol(void *orig_addr)
63 {
64     unsigned int i;
65     /* Hack, because we know this is x86. */
66     Elf32_Sym *sym = disas_symtab;
67
68     for (i = 0; i < disas_num_syms; i++) {
69         if (sym[i].st_shndx == SHN_UNDEF
70             || sym[i].st_shndx >= SHN_LORESERVE)
71             continue;
72
73         if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
74             continue;
75
76         if ((long)orig_addr >= sym[i].st_value
77             && (long)orig_addr < sym[i].st_value + sym[i].st_size)
78             return disas_strtab + sym[i].st_name;
79     }
80     return "";
81 }