1
/* General "disassemble this chunk" code. Used for debugging. */
2
# include "config.h"
3
4
# include "dis-asm.h"
# include "elf.h"
5
# include < errno . h >
6
7
8
# include "cpu.h"
# include "exec-all.h"
9
# include "disas.h"
10
11
/* Filled in by elfload.c. Simplistic, but will do for now. */
12
struct syminfo * syminfos = NULL ;
13
14
15
16
/* Get LENGTH bytes from info ' s buffer , at target address memaddr .
Transfer them to myaddr . */
int
17
18
buffer_read_memory ( bfd_vma memaddr , bfd_byte * myaddr , int length ,
struct disassemble_info * info )
19
{
20
21
22
23
24
25
if ( memaddr < info -> buffer_vma
|| memaddr + length > info -> buffer_vma + info -> buffer_length )
/* Out of bounds. Use EIO because GDB uses it. */
return EIO ;
memcpy ( myaddr , info -> buffer + ( memaddr - info -> buffer_vma ), length );
return 0 ;
26
27
}
28
29
30
/* Get LENGTH bytes from info ' s buffer , at target address memaddr .
Transfer them to myaddr . */
static int
31
32
33
34
target_read_memory ( bfd_vma memaddr ,
bfd_byte * myaddr ,
int length ,
struct disassemble_info * info )
35
36
37
{
int i ;
for ( i = 0 ; i < length ; i ++ ) {
38
myaddr [ i ] = ldub_code ( memaddr + i );
39
40
41
42
}
return 0 ;
}
43
44
45
/* Print an error message . We can assume that this is in response to
an error return from buffer_read_memory . */
void
46
perror_memory ( int status , bfd_vma memaddr , struct disassemble_info * info )
47
48
49
50
51
52
53
54
{
if ( status != EIO )
/* Can't happen. */
( * info -> fprintf_func ) ( info -> stream , "Unknown error %d \n " , status );
else
/* Actually , address between memaddr and memaddr + len was
out of bounds . */
( * info -> fprintf_func ) ( info -> stream ,
55
"Address 0x%" PRIx64 " is out of bounds. \n " , memaddr );
56
57
58
59
60
61
62
63
64
65
}
/* This could be in a separate file , to save miniscule amounts of space
in statically linked executables . */
/* Just print the address is hex . This is included for completeness even
though both GDB and objdump provide their own ( to print symbolic
addresses ). */
void
66
generic_print_address ( bfd_vma addr , struct disassemble_info * info )
67
{
68
( * info -> fprintf_func ) ( info -> stream , "0x%" PRIx64 , addr );
69
70
71
72
73
}
/* Just return the given address. */
int
74
generic_symbol_at_address ( bfd_vma addr , struct disassemble_info * info )
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
{
return 1 ;
}
bfd_vma bfd_getl32 ( const bfd_byte * addr )
{
unsigned long v ;
v = ( unsigned long ) addr [ 0 ];
v |= ( unsigned long ) addr [ 1 ] << 8 ;
v |= ( unsigned long ) addr [ 2 ] << 16 ;
v |= ( unsigned long ) addr [ 3 ] << 24 ;
return ( bfd_vma ) v ;
}
bfd_vma bfd_getb32 ( const bfd_byte * addr )
{
unsigned long v ;
v = ( unsigned long ) addr [ 0 ] << 24 ;
v |= ( unsigned long ) addr [ 1 ] << 16 ;
v |= ( unsigned long ) addr [ 2 ] << 8 ;
v |= ( unsigned long ) addr [ 3 ];
return ( bfd_vma ) v ;
}
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
bfd_vma bfd_getl16 ( const bfd_byte * addr )
{
unsigned long v ;
v = ( unsigned long ) addr [ 0 ];
v |= ( unsigned long ) addr [ 1 ] << 8 ;
return ( bfd_vma ) v ;
}
bfd_vma bfd_getb16 ( const bfd_byte * addr )
{
unsigned long v ;
v = ( unsigned long ) addr [ 0 ] << 24 ;
v |= ( unsigned long ) addr [ 1 ] << 16 ;
return ( bfd_vma ) v ;
}
119
120
121
122
123
124
125
126
# ifdef TARGET_ARM
static int
print_insn_thumb1 ( bfd_vma pc , disassemble_info * info )
{
return print_insn_arm ( pc | 1 , info );
}
# endif
ths
authored
18 years ago
127
/* Disassemble this for me please ... ( debugging ). ' flags ' has the following
128
129
values :
i386 - nonzero means 16 bit code
ths
authored
18 years ago
130
arm - nonzero means thumb code
131
ppc - nonzero means little endian
132
133
other targets - unused
*/
134
void target_disas ( FILE * out , target_ulong code , target_ulong size , int flags )
135
{
136
target_ulong pc ;
137
138
139
140
141
142
int count ;
struct disassemble_info disasm_info ;
int ( * print_insn )( bfd_vma pc , disassemble_info * info );
INIT_DISASSEMBLE_INFO ( disasm_info , out , fprintf );
143
144
145
146
147
148
149
150
151
152
153
154
disasm_info . read_memory_func = target_read_memory ;
disasm_info . buffer_vma = code ;
disasm_info . buffer_length = size ;
# ifdef TARGET_WORDS_BIGENDIAN
disasm_info . endian = BFD_ENDIAN_BIG ;
# else
disasm_info . endian = BFD_ENDIAN_LITTLE ;
# endif
# if defined ( TARGET_I386 )
if ( flags == 2 )
disasm_info . mach = bfd_mach_x86_64 ;
ths
authored
18 years ago
155
else if ( flags == 1 )
156
157
158
159
160
disasm_info . mach = bfd_mach_i386_i8086 ;
else
disasm_info . mach = bfd_mach_i386_i386 ;
print_insn = print_insn_i386 ;
# elif defined ( TARGET_ARM )
161
162
163
164
if ( flags )
print_insn = print_insn_thumb1 ;
else
print_insn = print_insn_arm ;
165
166
# elif defined ( TARGET_SPARC )
print_insn = print_insn_sparc ;
167
168
# ifdef TARGET_SPARC64
disasm_info . mach = bfd_mach_sparc_v9b ;
ths
authored
18 years ago
169
# endif
170
# elif defined ( TARGET_PPC )
171
if ( flags >> 16 )
172
disasm_info . endian = BFD_ENDIAN_LITTLE ;
173
174
175
176
if ( flags & 0xFFFF ) {
/* If we have a precise definitions of the instructions set, use it */
disasm_info . mach = flags & 0xFFFF ;
} else {
177
# ifdef TARGET_PPC64
178
disasm_info . mach = bfd_mach_ppc64 ;
179
# else
180
disasm_info . mach = bfd_mach_ppc ;
181
# endif
182
}
183
print_insn = print_insn_ppc ;
184
185
# elif defined ( TARGET_M68K )
print_insn = print_insn_m68k ;
186
# elif defined ( TARGET_MIPS )
187
# ifdef TARGET_WORDS_BIGENDIAN
188
print_insn = print_insn_big_mips ;
189
190
191
# else
print_insn = print_insn_little_mips ;
# endif
192
193
194
# elif defined ( TARGET_SH4 )
disasm_info . mach = bfd_mach_sh4 ;
print_insn = print_insn_sh ;
195
196
197
# elif defined ( TARGET_ALPHA )
disasm_info . mach = bfd_mach_alpha ;
print_insn = print_insn_alpha ;
ths
authored
17 years ago
198
199
200
# elif defined ( TARGET_CRIS )
disasm_info . mach = bfd_mach_cris_v32 ;
print_insn = print_insn_crisv32 ;
201
# else
202
203
fprintf ( out , "0x" TARGET_FMT_lx
": Asm output not supported on this arch \n " , code );
204
return ;
205
206
# endif
207
for ( pc = code ; size > 0 ; pc += count , size -= count ) {
208
fprintf ( out , "0x" TARGET_FMT_lx ": " , pc );
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
count = print_insn ( pc , & disasm_info );
# if 0
{
int i ;
uint8_t b ;
fprintf ( out , " {" );
for ( i = 0 ; i < count ; i ++ ) {
target_read_memory ( pc + i , & b , 1 , & disasm_info );
fprintf ( out , " %02x" , b );
}
fprintf ( out , " }" );
}
# endif
fprintf ( out , " \n " );
if ( count < 0 )
break ;
}
}
/* Disassemble this for me please... (debugging). */
void disas ( FILE * out , void * code , unsigned long size )
{
unsigned long pc ;
int count ;
struct disassemble_info disasm_info ;
int ( * print_insn )( bfd_vma pc , disassemble_info * info );
INIT_DISASSEMBLE_INFO ( disasm_info , out , fprintf );
238
239
240
241
242
disasm_info . buffer = code ;
disasm_info . buffer_vma = ( unsigned long ) code ;
disasm_info . buffer_length = size ;
# ifdef WORDS_BIGENDIAN
243
disasm_info . endian = BFD_ENDIAN_BIG ;
244
# else
245
disasm_info . endian = BFD_ENDIAN_LITTLE ;
246
# endif
247
# if defined ( __i386__ )
248
249
disasm_info . mach = bfd_mach_i386_i386 ;
print_insn = print_insn_i386 ;
250
# elif defined ( __x86_64__ )
251
252
disasm_info . mach = bfd_mach_x86_64 ;
print_insn = print_insn_i386 ;
malc
authored
16 years ago
253
# elif defined ( _ARCH_PPC )
254
print_insn = print_insn_ppc ;
255
# elif defined ( __alpha__ )
256
print_insn = print_insn_alpha ;
257
# elif defined ( __sparc__ )
258
print_insn = print_insn_sparc ;
259
260
261
# if defined ( __sparc_v8plus__ ) || defined ( __sparc_v8plusa__ ) || defined ( __sparc_v9__ )
disasm_info . mach = bfd_mach_sparc_v9b ;
# endif
ths
authored
18 years ago
262
# elif defined ( __arm__ )
263
print_insn = print_insn_arm ;
264
265
266
267
# elif defined ( __MIPSEB__ )
print_insn = print_insn_big_mips ;
# elif defined ( __MIPSEL__ )
print_insn = print_insn_little_mips ;
268
269
# elif defined ( __m68k__ )
print_insn = print_insn_m68k ;
ths
authored
18 years ago
270
271
# elif defined ( __s390__ )
print_insn = print_insn_s390 ;
272
273
# elif defined ( __hppa__ )
print_insn = print_insn_hppa ;
274
# else
275
276
fprintf ( out , "0x%lx: Asm output not supported on this arch \n " ,
( long ) code );
277
return ;
278
# endif
279
for ( pc = ( unsigned long ) code ; size > 0 ; pc += count , size -= count ) {
280
fprintf ( out , "0x%08lx: " , pc );
281
# ifdef __arm__
282
/* since data is included in the code , it is better to
283
display code data too */
284
fprintf ( out , "%08x " , ( int ) bfd_getl32 (( const bfd_byte * ) pc ));
285
# endif
286
count = print_insn ( pc , & disasm_info );
287
288
289
290
291
292
293
fprintf ( out , " \n " );
if ( count < 0 )
break ;
}
}
/* Look up symbol for debugging purpose. Returns "" if unknown. */
294
const char * lookup_symbol ( target_ulong orig_addr )
295
{
296
const char * symbol = "" ;
297
struct syminfo * s ;
ths
authored
18 years ago
298
299
for ( s = syminfos ; s ; s = s -> next ) {
300
301
302
303
symbol = s -> lookup_symbol ( s , orig_addr );
if ( symbol [ 0 ] != '\0' ) {
break ;
}
304
}
305
306
return symbol ;
307
}
308
309
310
# if ! defined ( CONFIG_USER_ONLY )
311
# include "monitor.h"
312
313
static int monitor_disas_is_physical ;
314
static CPUState * monitor_disas_env ;
315
316
static int
317
318
monitor_read_memory ( bfd_vma memaddr , bfd_byte * myaddr , int length ,
struct disassemble_info * info )
319
320
321
322
{
if ( monitor_disas_is_physical ) {
cpu_physical_memory_rw ( memaddr , myaddr , length , 0 );
} else {
323
cpu_memory_rw_debug ( monitor_disas_env , memaddr , myaddr , length , 0 );
324
325
326
327
}
return 0 ;
}
328
329
330
331
static int monitor_fprintf ( FILE * stream , const char * fmt , ...)
{
va_list ap ;
va_start ( ap , fmt );
332
monitor_vprintf (( Monitor * ) stream , fmt , ap );
333
334
335
336
va_end ( ap );
return 0 ;
}
337
void monitor_disas ( Monitor * mon , CPUState * env ,
338
target_ulong pc , int nb_insn , int is_physical , int flags )
339
340
341
342
343
{
int count , i ;
struct disassemble_info disasm_info ;
int ( * print_insn )( bfd_vma pc , disassemble_info * info );
344
INIT_DISASSEMBLE_INFO ( disasm_info , ( FILE * ) mon , monitor_fprintf );
345
346
monitor_disas_env = env ;
347
348
349
350
351
352
353
354
355
356
357
monitor_disas_is_physical = is_physical ;
disasm_info . read_memory_func = monitor_read_memory ;
disasm_info . buffer_vma = pc ;
# ifdef TARGET_WORDS_BIGENDIAN
disasm_info . endian = BFD_ENDIAN_BIG ;
# else
disasm_info . endian = BFD_ENDIAN_LITTLE ;
# endif
# if defined ( TARGET_I386 )
358
359
if ( flags == 2 )
disasm_info . mach = bfd_mach_x86_64 ;
ths
authored
18 years ago
360
else if ( flags == 1 )
361
disasm_info . mach = bfd_mach_i386_i8086 ;
362
363
else
disasm_info . mach = bfd_mach_i386_i386 ;
364
365
366
print_insn = print_insn_i386 ;
# elif defined ( TARGET_ARM )
print_insn = print_insn_arm ;
ths
authored
17 years ago
367
368
# elif defined ( TARGET_ALPHA )
print_insn = print_insn_alpha ;
369
370
# elif defined ( TARGET_SPARC )
print_insn = print_insn_sparc ;
371
372
373
# ifdef TARGET_SPARC64
disasm_info . mach = bfd_mach_sparc_v9b ;
# endif
374
# elif defined ( TARGET_PPC )
375
376
377
378
379
# ifdef TARGET_PPC64
disasm_info . mach = bfd_mach_ppc64 ;
# else
disasm_info . mach = bfd_mach_ppc ;
# endif
380
print_insn = print_insn_ppc ;
381
382
# elif defined ( TARGET_M68K )
print_insn = print_insn_m68k ;
383
# elif defined ( TARGET_MIPS )
384
# ifdef TARGET_WORDS_BIGENDIAN
385
print_insn = print_insn_big_mips ;
386
387
388
# else
print_insn = print_insn_little_mips ;
# endif
389
# else
390
391
monitor_printf ( mon , "0x" TARGET_FMT_lx
": Asm output not supported on this arch \n " , pc );
392
393
394
395
return ;
# endif
for ( i = 0 ; i < nb_insn ; i ++ ) {
396
monitor_printf ( mon , "0x" TARGET_FMT_lx ": " , pc );
397
count = print_insn ( pc , & disasm_info );
398
monitor_printf ( mon , " \n " );
399
400
401
402
403
404
if ( count < 0 )
break ;
pc += count ;
}
}
# endif