nkeynes@362 | 1 | /**
|
nkeynes@376 | 2 | * $Id: x86dasm.c,v 1.3 2007-09-12 09:16:47 nkeynes Exp $
|
nkeynes@362 | 3 | *
|
nkeynes@362 | 4 | * Wrapper around i386-dis to supply the same behaviour as the other
|
nkeynes@362 | 5 | * disassembly functions.
|
nkeynes@362 | 6 | *
|
nkeynes@362 | 7 | * Copyright (c) 2005 Nathan Keynes.
|
nkeynes@362 | 8 | *
|
nkeynes@362 | 9 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@362 | 10 | * it under the terms of the GNU General Public License as published by
|
nkeynes@362 | 11 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@362 | 12 | * (at your option) any later version.
|
nkeynes@362 | 13 | *
|
nkeynes@362 | 14 | * This program is distributed in the hope that it will be useful,
|
nkeynes@362 | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@362 | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@362 | 17 | * GNU General Public License for more details.
|
nkeynes@362 | 18 | */
|
nkeynes@362 | 19 |
|
nkeynes@362 | 20 | #include <stdarg.h>
|
nkeynes@362 | 21 | #include "x86dasm.h"
|
nkeynes@362 | 22 | #include "bfd.h"
|
nkeynes@362 | 23 | #include "dis-asm.h"
|
nkeynes@362 | 24 | #include "sh4/sh4core.h"
|
nkeynes@362 | 25 |
|
nkeynes@362 | 26 | extern const struct reg_desc_struct sh4_reg_map[];
|
nkeynes@362 | 27 | const struct cpu_desc_struct x86_cpu_desc =
|
nkeynes@362 | 28 | { "x86", x86_disasm_instruction, NULL, mem_has_page,
|
nkeynes@362 | 29 | NULL, NULL, NULL, 1,
|
nkeynes@362 | 30 | (char *)&sh4r, sizeof(sh4r), sh4_reg_map,
|
nkeynes@362 | 31 | &sh4r.pc };
|
nkeynes@362 | 32 |
|
nkeynes@362 | 33 | static int x86_disasm_output( void *data, const char *format, ... );
|
nkeynes@362 | 34 | static int x86_read_memory( bfd_vma memaddr, bfd_byte *buffer, unsigned int length,
|
nkeynes@362 | 35 | struct disassemble_info *info );
|
nkeynes@362 | 36 | static int x86_print_address( bfd_vma memaddr, struct disassemble_info *info );
|
nkeynes@362 | 37 |
|
nkeynes@362 | 38 | static struct disassemble_info x86_disasm_info;
|
nkeynes@362 | 39 |
|
nkeynes@365 | 40 | static x86_symbol *x86_symtab;
|
nkeynes@365 | 41 | static int x86_num_symbols = 0;
|
nkeynes@365 | 42 |
|
nkeynes@376 | 43 | void x86_disasm_block(FILE *out, void *start, uint32_t len)
|
nkeynes@376 | 44 | {
|
nkeynes@376 | 45 | uint32_t start_addr = (uint32_t)start;
|
nkeynes@376 | 46 | uint32_t pc;
|
nkeynes@376 | 47 | x86_disasm_init( start, start_addr, len );
|
nkeynes@376 | 48 | for( pc = start_addr; pc < start_addr + len; ) {
|
nkeynes@376 | 49 | char buf[256];
|
nkeynes@376 | 50 | char op[256];
|
nkeynes@376 | 51 | uint32_t pc2 = x86_disasm_instruction( pc, buf, sizeof(buf), op );
|
nkeynes@376 | 52 | fprintf( out, "%08X: %-20s %s\n", pc, op, buf );
|
nkeynes@376 | 53 | pc = pc2;
|
nkeynes@376 | 54 | }
|
nkeynes@376 | 55 | }
|
nkeynes@376 | 56 |
|
nkeynes@362 | 57 | void x86_disasm_init(char *buf, uint32_t vma, int buflen)
|
nkeynes@362 | 58 | {
|
nkeynes@362 | 59 | init_disassemble_info( &x86_disasm_info, NULL, x86_disasm_output );
|
nkeynes@362 | 60 | x86_disasm_info.arch = bfd_arch_i386;
|
nkeynes@362 | 61 | x86_disasm_info.mach = bfd_mach_i386_i386_intel_syntax;
|
nkeynes@362 | 62 | x86_disasm_info.endian = BFD_ENDIAN_LITTLE;
|
nkeynes@362 | 63 | x86_disasm_info.buffer = buf;
|
nkeynes@362 | 64 | x86_disasm_info.buffer_vma = vma;
|
nkeynes@362 | 65 | x86_disasm_info.buffer_length = buflen;
|
nkeynes@365 | 66 | x86_disasm_info.print_address_func = x86_print_address;
|
nkeynes@362 | 67 | }
|
nkeynes@362 | 68 |
|
nkeynes@365 | 69 | void x86_set_symtab( x86_symbol *symtab, int num_symbols )
|
nkeynes@365 | 70 | {
|
nkeynes@365 | 71 | x86_symtab = symtab;
|
nkeynes@365 | 72 | x86_num_symbols = num_symbols;
|
nkeynes@365 | 73 | }
|
nkeynes@365 | 74 |
|
nkeynes@365 | 75 | static const char *x86_find_symbol( bfd_vma memaddr, struct disassemble_info *info )
|
nkeynes@365 | 76 | {
|
nkeynes@365 | 77 | int i;
|
nkeynes@365 | 78 | for( i=0; i<x86_num_symbols; i++ ) {
|
nkeynes@365 | 79 | if( x86_symtab[i].ptr == (void *)memaddr ) {
|
nkeynes@365 | 80 | return x86_symtab[i].name;
|
nkeynes@365 | 81 | }
|
nkeynes@365 | 82 | }
|
nkeynes@365 | 83 | return NULL;
|
nkeynes@365 | 84 | }
|
nkeynes@365 | 85 |
|
nkeynes@365 | 86 | static int x86_print_address( bfd_vma memaddr, struct disassemble_info *info )
|
nkeynes@365 | 87 | {
|
nkeynes@365 | 88 | const char *sym = x86_find_symbol(memaddr, info);
|
nkeynes@365 | 89 | info->fprintf_func( info->stream, "%08X", memaddr );
|
nkeynes@365 | 90 | if( sym != NULL ) {
|
nkeynes@365 | 91 | info->fprintf_func( info->stream, " <%s>", sym );
|
nkeynes@365 | 92 | }
|
nkeynes@365 | 93 | return 0;
|
nkeynes@365 | 94 | }
|
nkeynes@362 | 95 |
|
nkeynes@362 | 96 | uint32_t x86_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
|
nkeynes@362 | 97 | {
|
nkeynes@362 | 98 | int count, i;
|
nkeynes@362 | 99 |
|
nkeynes@362 | 100 | x86_disasm_info.stream = buf;
|
nkeynes@362 | 101 | buf[0] = 0;
|
nkeynes@362 | 102 | count = print_insn_i386_att( pc, &x86_disasm_info );
|
nkeynes@362 | 103 | if( count != 0 ) {
|
nkeynes@362 | 104 | char tmp[count];
|
nkeynes@362 | 105 | x86_disasm_info.read_memory_func( pc, tmp, count, &x86_disasm_info );
|
nkeynes@362 | 106 | for( i=0; i<count; i++ ) {
|
nkeynes@362 | 107 | sprintf( opcode, "%02X ", ((unsigned int)tmp[i])&0xFF );
|
nkeynes@362 | 108 | opcode += 3;
|
nkeynes@362 | 109 | }
|
nkeynes@362 | 110 | *(opcode-1) = '\0';
|
nkeynes@362 | 111 | }
|
nkeynes@362 | 112 | return pc + count;
|
nkeynes@362 | 113 | }
|
nkeynes@362 | 114 |
|
nkeynes@362 | 115 | int x86_disasm_output( void *data, const char *format, ... )
|
nkeynes@362 | 116 | {
|
nkeynes@362 | 117 | char *p = (char *)data;
|
nkeynes@362 | 118 | va_list ap;
|
nkeynes@362 | 119 | int n;
|
nkeynes@362 | 120 | p += strlen(p);
|
nkeynes@362 | 121 | va_start( ap, format );
|
nkeynes@362 | 122 | n = vsprintf( p, format, ap );
|
nkeynes@362 | 123 | va_end( ap );
|
nkeynes@362 | 124 | return n;
|
nkeynes@362 | 125 | }
|