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