Statistics
| Branch: | Revision:

root / disas.c @ b67d5959

History | View | Annotate | Download (4.8 kB)

1 b9adb4a6 bellard
/* General "disassemble this chunk" code.  Used for debugging. */
2 5bbe9299 bellard
#include "config.h"
3 b9adb4a6 bellard
#include "dis-asm.h"
4 b9adb4a6 bellard
#include "disas.h"
5 b9adb4a6 bellard
#include "elf.h"
6 aa0aa4fa bellard
#include <errno.h>
7 b9adb4a6 bellard
8 b9adb4a6 bellard
/* Filled in by elfload.c.  Simplistic, but will do for now. */
9 b9adb4a6 bellard
unsigned int disas_num_syms;
10 b9adb4a6 bellard
void *disas_symtab;
11 b9adb4a6 bellard
const char *disas_strtab;
12 b9adb4a6 bellard
13 aa0aa4fa bellard
/* Get LENGTH bytes from info's buffer, at target address memaddr.
14 aa0aa4fa bellard
   Transfer them to myaddr.  */
15 aa0aa4fa bellard
int
16 aa0aa4fa bellard
buffer_read_memory (memaddr, myaddr, length, info)
17 aa0aa4fa bellard
     bfd_vma memaddr;
18 aa0aa4fa bellard
     bfd_byte *myaddr;
19 aa0aa4fa bellard
     int length;
20 aa0aa4fa bellard
     struct disassemble_info *info;
21 aa0aa4fa bellard
{
22 aa0aa4fa bellard
  if (memaddr < info->buffer_vma
23 aa0aa4fa bellard
      || memaddr + length > info->buffer_vma + info->buffer_length)
24 aa0aa4fa bellard
    /* Out of bounds.  Use EIO because GDB uses it.  */
25 aa0aa4fa bellard
    return EIO;
26 aa0aa4fa bellard
  memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
27 aa0aa4fa bellard
  return 0;
28 aa0aa4fa bellard
}
29 aa0aa4fa bellard
30 aa0aa4fa bellard
/* Print an error message.  We can assume that this is in response to
31 aa0aa4fa bellard
   an error return from buffer_read_memory.  */
32 aa0aa4fa bellard
void
33 aa0aa4fa bellard
perror_memory (status, memaddr, info)
34 aa0aa4fa bellard
     int status;
35 aa0aa4fa bellard
     bfd_vma memaddr;
36 aa0aa4fa bellard
     struct disassemble_info *info;
37 aa0aa4fa bellard
{
38 aa0aa4fa bellard
  if (status != EIO)
39 aa0aa4fa bellard
    /* Can't happen.  */
40 aa0aa4fa bellard
    (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
41 aa0aa4fa bellard
  else
42 aa0aa4fa bellard
    /* Actually, address between memaddr and memaddr + len was
43 aa0aa4fa bellard
       out of bounds.  */
44 aa0aa4fa bellard
    (*info->fprintf_func) (info->stream,
45 d44b29c2 bellard
                           "Address 0x%llx is out of bounds.\n", memaddr);
46 aa0aa4fa bellard
}
47 aa0aa4fa bellard
48 aa0aa4fa bellard
/* This could be in a separate file, to save miniscule amounts of space
49 aa0aa4fa bellard
   in statically linked executables.  */
50 aa0aa4fa bellard
51 aa0aa4fa bellard
/* Just print the address is hex.  This is included for completeness even
52 aa0aa4fa bellard
   though both GDB and objdump provide their own (to print symbolic
53 aa0aa4fa bellard
   addresses).  */
54 aa0aa4fa bellard
55 aa0aa4fa bellard
void
56 aa0aa4fa bellard
generic_print_address (addr, info)
57 aa0aa4fa bellard
     bfd_vma addr;
58 aa0aa4fa bellard
     struct disassemble_info *info;
59 aa0aa4fa bellard
{
60 d44b29c2 bellard
  (*info->fprintf_func) (info->stream, "0x%llx", addr);
61 aa0aa4fa bellard
}
62 aa0aa4fa bellard
63 aa0aa4fa bellard
/* Just return the given address.  */
64 aa0aa4fa bellard
65 aa0aa4fa bellard
int
66 aa0aa4fa bellard
generic_symbol_at_address (addr, info)
67 aa0aa4fa bellard
     bfd_vma addr;
68 aa0aa4fa bellard
     struct disassemble_info * info;
69 aa0aa4fa bellard
{
70 aa0aa4fa bellard
  return 1;
71 aa0aa4fa bellard
}
72 aa0aa4fa bellard
73 aa0aa4fa bellard
bfd_vma bfd_getl32 (const bfd_byte *addr)
74 aa0aa4fa bellard
{
75 aa0aa4fa bellard
  unsigned long v;
76 aa0aa4fa bellard
77 aa0aa4fa bellard
  v = (unsigned long) addr[0];
78 aa0aa4fa bellard
  v |= (unsigned long) addr[1] << 8;
79 aa0aa4fa bellard
  v |= (unsigned long) addr[2] << 16;
80 aa0aa4fa bellard
  v |= (unsigned long) addr[3] << 24;
81 aa0aa4fa bellard
  return (bfd_vma) v;
82 aa0aa4fa bellard
}
83 aa0aa4fa bellard
84 aa0aa4fa bellard
bfd_vma bfd_getb32 (const bfd_byte *addr)
85 aa0aa4fa bellard
{
86 aa0aa4fa bellard
  unsigned long v;
87 aa0aa4fa bellard
88 aa0aa4fa bellard
  v = (unsigned long) addr[0] << 24;
89 aa0aa4fa bellard
  v |= (unsigned long) addr[1] << 16;
90 aa0aa4fa bellard
  v |= (unsigned long) addr[2] << 8;
91 aa0aa4fa bellard
  v |= (unsigned long) addr[3];
92 aa0aa4fa bellard
  return (bfd_vma) v;
93 aa0aa4fa bellard
}
94 aa0aa4fa bellard
95 95cbfc64 bellard
/* Disassemble this for me please... (debugging). 'flags' is only used
96 95cbfc64 bellard
   for i386: non zero means 16 bit code */
97 95cbfc64 bellard
void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
98 b9adb4a6 bellard
{
99 b9adb4a6 bellard
    uint8_t *pc;
100 b9adb4a6 bellard
    int count;
101 b9adb4a6 bellard
    struct disassemble_info disasm_info;
102 b9adb4a6 bellard
    int (*print_insn)(bfd_vma pc, disassemble_info *info);
103 b9adb4a6 bellard
104 b9adb4a6 bellard
    INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
105 b9adb4a6 bellard
106 b9adb4a6 bellard
    disasm_info.buffer = code;
107 b9adb4a6 bellard
    disasm_info.buffer_vma = (unsigned long)code;
108 b9adb4a6 bellard
    disasm_info.buffer_length = size;
109 b9adb4a6 bellard
110 95cbfc64 bellard
    if (is_host) {
111 b9adb4a6 bellard
#ifdef WORDS_BIGENDIAN
112 b9adb4a6 bellard
        disasm_info.endian = BFD_ENDIAN_BIG;
113 b9adb4a6 bellard
#else
114 b9adb4a6 bellard
        disasm_info.endian = BFD_ENDIAN_LITTLE;
115 b9adb4a6 bellard
#endif
116 b9adb4a6 bellard
#ifdef __i386__
117 b9adb4a6 bellard
        disasm_info.mach = bfd_mach_i386_i386;
118 b9adb4a6 bellard
        print_insn = print_insn_i386;
119 b9adb4a6 bellard
#elif defined(__powerpc__)
120 b9adb4a6 bellard
        print_insn = print_insn_ppc;
121 a993ba85 bellard
#elif defined(__alpha__)
122 a993ba85 bellard
        print_insn = print_insn_alpha;
123 aa0aa4fa bellard
#elif defined(__sparc__)
124 aa0aa4fa bellard
        print_insn = print_insn_sparc;
125 aa0aa4fa bellard
#elif defined(__arm__) 
126 aa0aa4fa bellard
        print_insn = print_insn_arm;
127 b9adb4a6 bellard
#else
128 b9adb4a6 bellard
        fprintf(out, "Asm output not supported on this arch\n");
129 b9adb4a6 bellard
        return;
130 b9adb4a6 bellard
#endif
131 b9adb4a6 bellard
    } else {
132 95cbfc64 bellard
#ifdef TARGET_WORDS_BIGENDIAN
133 95cbfc64 bellard
        disasm_info.endian = BFD_ENDIAN_BIG;
134 95cbfc64 bellard
#else
135 b9adb4a6 bellard
        disasm_info.endian = BFD_ENDIAN_LITTLE;
136 95cbfc64 bellard
#endif
137 95cbfc64 bellard
#if defined(TARGET_I386)
138 95cbfc64 bellard
        if (!flags)
139 b9adb4a6 bellard
            disasm_info.mach = bfd_mach_i386_i386;
140 b9adb4a6 bellard
        else
141 b9adb4a6 bellard
            disasm_info.mach = bfd_mach_i386_i8086;
142 b9adb4a6 bellard
        print_insn = print_insn_i386;
143 95cbfc64 bellard
#elif defined(TARGET_ARM)
144 95cbfc64 bellard
        print_insn = print_insn_arm;
145 95cbfc64 bellard
#else
146 95cbfc64 bellard
        fprintf(out, "Asm output not supported on this arch\n");
147 95cbfc64 bellard
        return;
148 95cbfc64 bellard
#endif
149 b9adb4a6 bellard
    }
150 b9adb4a6 bellard
151 b9adb4a6 bellard
    for (pc = code; pc < (uint8_t *)code + size; pc += count) {
152 b9adb4a6 bellard
        fprintf(out, "0x%08lx:  ", (long)pc);
153 aa0aa4fa bellard
#ifdef __arm__
154 aa0aa4fa bellard
        /* since data are included in the code, it is better to
155 aa0aa4fa bellard
           display code data too */
156 95cbfc64 bellard
        if (is_host) {
157 aa0aa4fa bellard
            fprintf(out, "%08x  ", (int)bfd_getl32((const bfd_byte *)pc));
158 aa0aa4fa bellard
        }
159 aa0aa4fa bellard
#endif
160 08351fb3 bellard
        count = print_insn((unsigned long)pc, &disasm_info);
161 b9adb4a6 bellard
        fprintf(out, "\n");
162 b9adb4a6 bellard
        if (count < 0)
163 b9adb4a6 bellard
            break;
164 b9adb4a6 bellard
    }
165 b9adb4a6 bellard
}
166 b9adb4a6 bellard
167 b9adb4a6 bellard
/* Look up symbol for debugging purpose.  Returns "" if unknown. */
168 b9adb4a6 bellard
const char *lookup_symbol(void *orig_addr)
169 b9adb4a6 bellard
{
170 b9adb4a6 bellard
    unsigned int i;
171 b9adb4a6 bellard
    /* Hack, because we know this is x86. */
172 b9adb4a6 bellard
    Elf32_Sym *sym = disas_symtab;
173 b9adb4a6 bellard
174 b9adb4a6 bellard
    for (i = 0; i < disas_num_syms; i++) {
175 b9adb4a6 bellard
        if (sym[i].st_shndx == SHN_UNDEF
176 b9adb4a6 bellard
            || sym[i].st_shndx >= SHN_LORESERVE)
177 b9adb4a6 bellard
            continue;
178 b9adb4a6 bellard
179 b9adb4a6 bellard
        if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
180 b9adb4a6 bellard
            continue;
181 b9adb4a6 bellard
182 b9adb4a6 bellard
        if ((long)orig_addr >= sym[i].st_value
183 b9adb4a6 bellard
            && (long)orig_addr < sym[i].st_value + sym[i].st_size)
184 b9adb4a6 bellard
            return disas_strtab + sym[i].st_name;
185 b9adb4a6 bellard
    }
186 b9adb4a6 bellard
    return "";
187 b9adb4a6 bellard
}