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