Search
lxdream.org :: lxdream/src/x86dasm/x86dasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/x86dasm/x86dasm.c
changeset 1065:bc1cc0c54917
prev1026:a0aa3c503103
prev571:9bc09948d0f2
next1087:d54c499b48c7
author nkeynes
date Sun Jul 05 13:52:50 2009 +1000 (12 years ago)
permissions -rw-r--r--
last change No-op merge lxdream-mmu to remove head (actually merged long ago)
file annotate diff log raw
nkeynes@362
     1
/**
nkeynes@561
     2
 * $Id$
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@480
    21
#include <string.h>
nkeynes@755
    22
#include "x86dasm/x86dasm.h"
nkeynes@755
    23
#include "x86dasm/bfd.h"
nkeynes@755
    24
#include "x86dasm/dis-asm.h"
nkeynes@564
    25
#include "sh4/sh4.h"
nkeynes@527
    26
#include "sh4/sh4trans.h"
nkeynes@362
    27
nkeynes@362
    28
const struct cpu_desc_struct x86_cpu_desc = 
nkeynes@755
    29
    { "x86", (disasm_func_t)x86_disasm_instruction, NULL, mem_has_page, 
nkeynes@1026
    30
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 
nkeynes@1026
    31
      NULL, 0, NULL, 0, 0,  
nkeynes@362
    32
      &sh4r.pc };
nkeynes@362
    33
nkeynes@362
    34
static int x86_disasm_output( void *data, const char *format, ... );
nkeynes@429
    35
static void x86_print_address( bfd_vma memaddr, struct disassemble_info *info );
nkeynes@362
    36
nkeynes@362
    37
static struct disassemble_info x86_disasm_info;
nkeynes@362
    38
nkeynes@365
    39
static x86_symbol *x86_symtab;
nkeynes@365
    40
static int x86_num_symbols = 0;   
nkeynes@365
    41
nkeynes@515
    42
nkeynes@515
    43
void xlat_disasm_block( FILE *out, void *block )
nkeynes@515
    44
{
nkeynes@571
    45
    uint32_t buflen = xlat_get_code_size(block);
nkeynes@515
    46
    x86_set_symtab( NULL, 0 );
nkeynes@515
    47
    x86_disasm_block( out, block, buflen );
nkeynes@515
    48
}
nkeynes@515
    49
nkeynes@376
    50
void x86_disasm_block(FILE *out, void *start, uint32_t len)
nkeynes@376
    51
{
nkeynes@527
    52
    uintptr_t start_addr = (uintptr_t)start;
nkeynes@925
    53
    uintptr_t pc;
nkeynes@376
    54
    x86_disasm_init( start, start_addr, len );
nkeynes@376
    55
    for( pc = start_addr; pc < start_addr + len;  ) {
nkeynes@376
    56
	char buf[256];
nkeynes@376
    57
	char op[256];
nkeynes@925
    58
	uintptr_t pc2 = x86_disasm_instruction( pc, buf, sizeof(buf), op );
nkeynes@968
    59
	fprintf( out, "%08X: %-20s %s\n", (unsigned int)pc, op, buf );
nkeynes@376
    60
	pc = pc2;
nkeynes@376
    61
    }
nkeynes@376
    62
}
nkeynes@376
    63
nkeynes@527
    64
void x86_disasm_init(unsigned char *buf, uintptr_t vma, int buflen)
nkeynes@362
    65
{
nkeynes@362
    66
    init_disassemble_info( &x86_disasm_info, NULL, x86_disasm_output );
nkeynes@362
    67
    x86_disasm_info.arch = bfd_arch_i386;
nkeynes@925
    68
#if SIZEOF_VOID_P == 8
nkeynes@527
    69
    x86_disasm_info.mach =  bfd_mach_x86_64_intel_syntax;
nkeynes@527
    70
#else
nkeynes@362
    71
    x86_disasm_info.mach = bfd_mach_i386_i386_intel_syntax;
nkeynes@527
    72
#endif
nkeynes@362
    73
    x86_disasm_info.endian = BFD_ENDIAN_LITTLE;
nkeynes@362
    74
    x86_disasm_info.buffer = buf;
nkeynes@362
    75
    x86_disasm_info.buffer_vma = vma;
nkeynes@362
    76
    x86_disasm_info.buffer_length = buflen;
nkeynes@365
    77
    x86_disasm_info.print_address_func = x86_print_address;
nkeynes@362
    78
}
nkeynes@362
    79
nkeynes@365
    80
void x86_set_symtab( x86_symbol *symtab, int num_symbols )
nkeynes@365
    81
{
nkeynes@365
    82
    x86_symtab = symtab;
nkeynes@365
    83
    x86_num_symbols = num_symbols;
nkeynes@365
    84
}
nkeynes@365
    85
nkeynes@365
    86
static const char *x86_find_symbol( bfd_vma memaddr, struct disassemble_info *info )
nkeynes@365
    87
{
nkeynes@365
    88
    int i;
nkeynes@365
    89
    for( i=0; i<x86_num_symbols; i++ ) {
nkeynes@527
    90
	if( x86_symtab[i].ptr == (void *)(uintptr_t)memaddr ) {
nkeynes@365
    91
	    return x86_symtab[i].name;
nkeynes@365
    92
	}
nkeynes@365
    93
    }
nkeynes@365
    94
    return NULL;
nkeynes@365
    95
}
nkeynes@365
    96
nkeynes@429
    97
static void x86_print_address( bfd_vma memaddr, struct disassemble_info *info )
nkeynes@365
    98
{
nkeynes@365
    99
    const char *sym = x86_find_symbol(memaddr, info);
nkeynes@365
   100
    info->fprintf_func( info->stream, "%08X", memaddr );
nkeynes@365
   101
    if( sym != NULL ) {
nkeynes@365
   102
	info->fprintf_func( info->stream, " <%s>", sym );
nkeynes@365
   103
    }
nkeynes@365
   104
}
nkeynes@362
   105
nkeynes@920
   106
void x86_print_symbolic_operand( char *buf, int hex, unsigned int disp )
nkeynes@920
   107
{
nkeynes@920
   108
    const char *sym = x86_find_symbol(disp, NULL);
nkeynes@920
   109
    if( sym != NULL ) {
nkeynes@920
   110
        snprintf( buf, 50, "<%s>", sym );
nkeynes@920
   111
    } else if( hex ) {
nkeynes@920
   112
        sprintf( buf, "0x%x", disp );
nkeynes@920
   113
    } else {
nkeynes@920
   114
        sprintf( buf, "%d", (int)disp );
nkeynes@920
   115
    }
nkeynes@920
   116
}
nkeynes@920
   117
nkeynes@925
   118
uintptr_t x86_disasm_instruction( uintptr_t pc, char *buf, int len, char *opcode )
nkeynes@362
   119
{
nkeynes@362
   120
    int count, i;
nkeynes@362
   121
nkeynes@362
   122
    x86_disasm_info.stream = buf;
nkeynes@362
   123
    buf[0] = 0;
nkeynes@362
   124
    count = print_insn_i386_att( pc, &x86_disasm_info );
nkeynes@362
   125
    if( count != 0 ) {
nkeynes@429
   126
	unsigned char tmp[count];
nkeynes@362
   127
	x86_disasm_info.read_memory_func( pc, tmp, count, &x86_disasm_info );
nkeynes@362
   128
	for( i=0; i<count; i++ ) {
nkeynes@362
   129
	    sprintf( opcode, "%02X ", ((unsigned int)tmp[i])&0xFF );
nkeynes@362
   130
	    opcode += 3;
nkeynes@362
   131
	}
nkeynes@362
   132
	*(opcode-1) = '\0';
nkeynes@362
   133
    }
nkeynes@362
   134
    return pc + count;
nkeynes@362
   135
}
nkeynes@362
   136
nkeynes@362
   137
int x86_disasm_output( void *data, const char *format, ... )
nkeynes@362
   138
{
nkeynes@362
   139
    char *p = (char *)data;
nkeynes@362
   140
    va_list ap;
nkeynes@362
   141
    int n;
nkeynes@362
   142
    p += strlen(p);
nkeynes@362
   143
    va_start( ap, format );
nkeynes@362
   144
    n = vsprintf( p, format, ap );
nkeynes@362
   145
    va_end( ap );
nkeynes@362
   146
    return n;
nkeynes@362
   147
}
.