Search
lxdream.org :: lxdream/src/xlat/xlatdasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/xlat/xlatdasm.c
changeset 1264:74ad81710528
prev1263:b3de98d19faf
author nkeynes
date Tue Mar 06 12:19:08 2012 +1000 (8 years ago)
permissions -rw-r--r--
last change Move x86dasm/* files under xlat/disasm
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@1263
    22
#include "xlat/xltcache.h"
nkeynes@1263
    23
#include "xlat/xlatdasm.h"
nkeynes@1264
    24
#include "xlat/disasm/bfd.h"
nkeynes@1264
    25
#include "xlat/disasm/dis-asm.h"
nkeynes@564
    26
#include "sh4/sh4.h"
nkeynes@362
    27
nkeynes@1263
    28
#if defined(__i386__)
nkeynes@1263
    29
#define HOST_CPU_NAME "x86"
nkeynes@1263
    30
#define HOST_PRINT print_insn_i386_att
nkeynes@1263
    31
#define HOST_SYNTAX bfd_mach_i386_i386_intel_syntax
nkeynes@1263
    32
#elif defined(__x86_64__) || defined(__amd64__)
nkeynes@1263
    33
#define HOST_CPU_NAME "x86"
nkeynes@1263
    34
#define HOST_PRINT print_insn_i386_att
nkeynes@1263
    35
#define HOST_SYNTAX bfd_mach_x86_64_intel_syntax
nkeynes@1263
    36
#elif defined(__arm__)
nkeynes@1263
    37
#define HOST_CPU_NAME "arm"
nkeynes@1263
    38
#define HOST_PRINT print_insn_little_arm
nkeynes@1263
    39
#define HOST_SYNTAX bfd_mach_arm_unknown
nkeynes@1263
    40
#else
nkeynes@1263
    41
#error Unidentified host platform
nkeynes@1263
    42
#endif
nkeynes@1263
    43
nkeynes@1263
    44
const struct cpu_desc_struct xlat_cpu_desc =
nkeynes@1263
    45
    { HOST_CPU_NAME, (disasm_func_t)xlat_disasm_instruction, NULL, mem_has_page,
nkeynes@1026
    46
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 
nkeynes@1026
    47
      NULL, 0, NULL, 0, 0,  
nkeynes@362
    48
      &sh4r.pc };
nkeynes@362
    49
nkeynes@1263
    50
static int xlat_disasm_output( void *data, const char *format, ... );
nkeynes@1263
    51
static void xlat_print_address( bfd_vma memaddr, struct disassemble_info *info );
nkeynes@362
    52
nkeynes@1263
    53
static struct disassemble_info xlat_disasm_info;
nkeynes@362
    54
nkeynes@1263
    55
static xlat_symbol *xlat_symtab;
nkeynes@1263
    56
static int xlat_num_symbols = 0;
nkeynes@365
    57
nkeynes@1087
    58
void xlat_dump_block( void *block )
nkeynes@1087
    59
{
nkeynes@1087
    60
    xlat_disasm_block( stderr, block );
nkeynes@1087
    61
}
nkeynes@515
    62
nkeynes@515
    63
void xlat_disasm_block( FILE *out, void *block )
nkeynes@515
    64
{
nkeynes@571
    65
    uint32_t buflen = xlat_get_code_size(block);
nkeynes@1263
    66
    xlat_disasm_region( out, block, buflen );
nkeynes@515
    67
}
nkeynes@515
    68
nkeynes@1263
    69
void xlat_disasm_region(FILE *out, void *start, uint32_t len)
nkeynes@376
    70
{
nkeynes@527
    71
    uintptr_t start_addr = (uintptr_t)start;
nkeynes@925
    72
    uintptr_t pc;
nkeynes@376
    73
    for( pc = start_addr; pc < start_addr + len;  ) {
nkeynes@376
    74
	char buf[256];
nkeynes@376
    75
	char op[256];
nkeynes@1263
    76
	uintptr_t pc2 = xlat_disasm_instruction( pc, buf, sizeof(buf), op );
nkeynes@968
    77
	fprintf( out, "%08X: %-20s %s\n", (unsigned int)pc, op, buf );
nkeynes@376
    78
	pc = pc2;
nkeynes@376
    79
    }
nkeynes@376
    80
}
nkeynes@376
    81
nkeynes@1263
    82
void xlat_disasm_init( xlat_symbol *symtab, int num_symbols )
nkeynes@362
    83
{
nkeynes@1263
    84
    init_disassemble_info( &xlat_disasm_info, NULL, xlat_disasm_output );
nkeynes@1263
    85
    xlat_disasm_info.arch = bfd_arch_i386;
nkeynes@1263
    86
    xlat_disasm_info.mach = HOST_SYNTAX;
nkeynes@1263
    87
    xlat_disasm_info.endian = BFD_ENDIAN_LITTLE;
nkeynes@1263
    88
    xlat_disasm_info.buffer = 0;
nkeynes@1263
    89
    xlat_disasm_info.print_address_func = xlat_print_address;
nkeynes@1263
    90
    xlat_symtab = symtab;
nkeynes@1263
    91
    xlat_num_symbols = num_symbols;
nkeynes@362
    92
}
nkeynes@362
    93
nkeynes@1263
    94
static const char *xlat_find_symbol( bfd_vma memaddr, struct disassemble_info *info )
nkeynes@365
    95
{
nkeynes@365
    96
    int i;
nkeynes@1263
    97
    for( i=0; i<xlat_num_symbols; i++ ) {
nkeynes@1263
    98
	if( xlat_symtab[i].ptr == (void *)(uintptr_t)memaddr ) {
nkeynes@1263
    99
	    return xlat_symtab[i].name;
nkeynes@365
   100
	}
nkeynes@365
   101
    }
nkeynes@365
   102
    return NULL;
nkeynes@365
   103
}
nkeynes@365
   104
nkeynes@1263
   105
static void xlat_print_address( bfd_vma memaddr, struct disassemble_info *info )
nkeynes@365
   106
{
nkeynes@1263
   107
    const char *sym = xlat_find_symbol(memaddr, info);
nkeynes@365
   108
    info->fprintf_func( info->stream, "%08X", memaddr );
nkeynes@365
   109
    if( sym != NULL ) {
nkeynes@365
   110
	info->fprintf_func( info->stream, " <%s>", sym );
nkeynes@365
   111
    }
nkeynes@365
   112
}
nkeynes@362
   113
nkeynes@1263
   114
void xlat_print_symbolic_operand( char *buf, int hex, uintptr_t disp )
nkeynes@920
   115
{
nkeynes@1263
   116
    const char *sym = xlat_find_symbol(disp, NULL);
nkeynes@920
   117
    if( sym != NULL ) {
nkeynes@920
   118
        snprintf( buf, 50, "<%s>", sym );
nkeynes@920
   119
    } else if( hex ) {
nkeynes@1263
   120
        sprintf( buf, "0x%lx", disp );
nkeynes@920
   121
    } else {
nkeynes@920
   122
        sprintf( buf, "%d", (int)disp );
nkeynes@920
   123
    }
nkeynes@920
   124
}
nkeynes@920
   125
nkeynes@1263
   126
uintptr_t xlat_disasm_instruction( uintptr_t pc, char *buf, int len, char *opcode )
nkeynes@362
   127
{
nkeynes@362
   128
    int count, i;
nkeynes@362
   129
nkeynes@1263
   130
    xlat_disasm_info.stream = buf;
nkeynes@362
   131
    buf[0] = 0;
nkeynes@1263
   132
    count = HOST_PRINT( pc, &xlat_disasm_info );
nkeynes@362
   133
    if( count != 0 ) {
nkeynes@429
   134
	unsigned char tmp[count];
nkeynes@1263
   135
	xlat_disasm_info.read_memory_func( pc, tmp, count, &xlat_disasm_info );
nkeynes@362
   136
	for( i=0; i<count; i++ ) {
nkeynes@362
   137
	    sprintf( opcode, "%02X ", ((unsigned int)tmp[i])&0xFF );
nkeynes@362
   138
	    opcode += 3;
nkeynes@362
   139
	}
nkeynes@362
   140
	*(opcode-1) = '\0';
nkeynes@362
   141
    }
nkeynes@362
   142
    return pc + count;
nkeynes@362
   143
}
nkeynes@362
   144
nkeynes@1263
   145
static int xlat_disasm_output( void *data, const char *format, ... )
nkeynes@362
   146
{
nkeynes@362
   147
    char *p = (char *)data;
nkeynes@362
   148
    va_list ap;
nkeynes@362
   149
    int n;
nkeynes@362
   150
    p += strlen(p);
nkeynes@362
   151
    va_start( ap, format );
nkeynes@362
   152
    n = vsprintf( p, format, ap );
nkeynes@362
   153
    va_end( ap );
nkeynes@362
   154
    return n;
nkeynes@362
   155
}
.