2 |
#include "dis-asm.h" |
#include "dis-asm.h" |
3 |
#include "disas.h" |
#include "disas.h" |
4 |
#include "elf.h" |
#include "elf.h" |
5 |
|
#include <errno.h> |
6 |
|
|
7 |
/* Filled in by elfload.c. Simplistic, but will do for now. */ |
/* Filled in by elfload.c. Simplistic, but will do for now. */ |
8 |
unsigned int disas_num_syms; |
unsigned int disas_num_syms; |
9 |
void *disas_symtab; |
void *disas_symtab; |
10 |
const char *disas_strtab; |
const char *disas_strtab; |
11 |
|
|
12 |
|
/* Get LENGTH bytes from info's buffer, at target address memaddr. |
13 |
|
Transfer them to myaddr. */ |
14 |
|
int |
15 |
|
buffer_read_memory (memaddr, myaddr, length, info) |
16 |
|
bfd_vma memaddr; |
17 |
|
bfd_byte *myaddr; |
18 |
|
int length; |
19 |
|
struct disassemble_info *info; |
20 |
|
{ |
21 |
|
if (memaddr < info->buffer_vma |
22 |
|
|| memaddr + length > info->buffer_vma + info->buffer_length) |
23 |
|
/* Out of bounds. Use EIO because GDB uses it. */ |
24 |
|
return EIO; |
25 |
|
memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length); |
26 |
|
return 0; |
27 |
|
} |
28 |
|
|
29 |
|
/* Print an error message. We can assume that this is in response to |
30 |
|
an error return from buffer_read_memory. */ |
31 |
|
void |
32 |
|
perror_memory (status, memaddr, info) |
33 |
|
int status; |
34 |
|
bfd_vma memaddr; |
35 |
|
struct disassemble_info *info; |
36 |
|
{ |
37 |
|
if (status != EIO) |
38 |
|
/* Can't happen. */ |
39 |
|
(*info->fprintf_func) (info->stream, "Unknown error %d\n", status); |
40 |
|
else |
41 |
|
/* Actually, address between memaddr and memaddr + len was |
42 |
|
out of bounds. */ |
43 |
|
(*info->fprintf_func) (info->stream, |
44 |
|
"Address 0x%x is out of bounds.\n", memaddr); |
45 |
|
} |
46 |
|
|
47 |
|
/* This could be in a separate file, to save miniscule amounts of space |
48 |
|
in statically linked executables. */ |
49 |
|
|
50 |
|
/* Just print the address is hex. This is included for completeness even |
51 |
|
though both GDB and objdump provide their own (to print symbolic |
52 |
|
addresses). */ |
53 |
|
|
54 |
|
void |
55 |
|
generic_print_address (addr, info) |
56 |
|
bfd_vma addr; |
57 |
|
struct disassemble_info *info; |
58 |
|
{ |
59 |
|
(*info->fprintf_func) (info->stream, "0x%x", addr); |
60 |
|
} |
61 |
|
|
62 |
|
/* Just return the given address. */ |
63 |
|
|
64 |
|
int |
65 |
|
generic_symbol_at_address (addr, info) |
66 |
|
bfd_vma addr; |
67 |
|
struct disassemble_info * info; |
68 |
|
{ |
69 |
|
return 1; |
70 |
|
} |
71 |
|
|
72 |
|
bfd_vma bfd_getl32 (const bfd_byte *addr) |
73 |
|
{ |
74 |
|
unsigned long v; |
75 |
|
|
76 |
|
v = (unsigned long) addr[0]; |
77 |
|
v |= (unsigned long) addr[1] << 8; |
78 |
|
v |= (unsigned long) addr[2] << 16; |
79 |
|
v |= (unsigned long) addr[3] << 24; |
80 |
|
return (bfd_vma) v; |
81 |
|
} |
82 |
|
|
83 |
|
bfd_vma bfd_getb32 (const bfd_byte *addr) |
84 |
|
{ |
85 |
|
unsigned long v; |
86 |
|
|
87 |
|
v = (unsigned long) addr[0] << 24; |
88 |
|
v |= (unsigned long) addr[1] << 16; |
89 |
|
v |= (unsigned long) addr[2] << 8; |
90 |
|
v |= (unsigned long) addr[3]; |
91 |
|
return (bfd_vma) v; |
92 |
|
} |
93 |
|
|
94 |
/* Disassemble this for me please... (debugging). */ |
/* Disassemble this for me please... (debugging). */ |
95 |
void disas(FILE *out, void *code, unsigned long size, enum disas_type type) |
void disas(FILE *out, void *code, unsigned long size, enum disas_type type) |
96 |
{ |
{ |
118 |
print_insn = print_insn_ppc; |
print_insn = print_insn_ppc; |
119 |
#elif defined(__alpha__) |
#elif defined(__alpha__) |
120 |
print_insn = print_insn_alpha; |
print_insn = print_insn_alpha; |
121 |
|
#elif defined(__sparc__) |
122 |
|
print_insn = print_insn_sparc; |
123 |
|
#elif defined(__arm__) |
124 |
|
print_insn = print_insn_arm; |
125 |
#else |
#else |
126 |
fprintf(out, "Asm output not supported on this arch\n"); |
fprintf(out, "Asm output not supported on this arch\n"); |
127 |
return; |
return; |
138 |
|
|
139 |
for (pc = code; pc < (uint8_t *)code + size; pc += count) { |
for (pc = code; pc < (uint8_t *)code + size; pc += count) { |
140 |
fprintf(out, "0x%08lx: ", (long)pc); |
fprintf(out, "0x%08lx: ", (long)pc); |
141 |
|
#ifdef __arm__ |
142 |
|
/* since data are included in the code, it is better to |
143 |
|
display code data too */ |
144 |
|
if (type == DISAS_TARGET) { |
145 |
|
fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc)); |
146 |
|
} |
147 |
|
#endif |
148 |
count = print_insn((unsigned long)pc, &disasm_info); |
count = print_insn((unsigned long)pc, &disasm_info); |
149 |
fprintf(out, "\n"); |
fprintf(out, "\n"); |
150 |
if (count < 0) |
if (count < 0) |