added ARM and Sparc disassemblers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@214 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
84fa15d854
commit
aa0aa4fa31
31
dis-asm.h
31
dis-asm.h
@ -73,16 +73,20 @@ enum bfd_architecture
|
|||||||
bfd_arch_a29k, /* AMD 29000 */
|
bfd_arch_a29k, /* AMD 29000 */
|
||||||
bfd_arch_sparc, /* SPARC */
|
bfd_arch_sparc, /* SPARC */
|
||||||
#define bfd_mach_sparc 1
|
#define bfd_mach_sparc 1
|
||||||
/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
|
/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
|
||||||
#define bfd_mach_sparc_sparclet 2
|
#define bfd_mach_sparc_sparclet 2
|
||||||
#define bfd_mach_sparc_sparclite 3
|
#define bfd_mach_sparc_sparclite 3
|
||||||
#define bfd_mach_sparc_v8plus 4
|
#define bfd_mach_sparc_v8plus 4
|
||||||
#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns */
|
#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */
|
||||||
#define bfd_mach_sparc_v9 6
|
#define bfd_mach_sparc_sparclite_le 6
|
||||||
#define bfd_mach_sparc_v9a 7 /* with ultrasparc add'ns */
|
#define bfd_mach_sparc_v9 7
|
||||||
/* Nonzero if MACH has the v9 instruction set. */
|
#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */
|
||||||
|
#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */
|
||||||
|
#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */
|
||||||
|
/* Nonzero if MACH has the v9 instruction set. */
|
||||||
#define bfd_mach_sparc_v9_p(mach) \
|
#define bfd_mach_sparc_v9_p(mach) \
|
||||||
((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9a)
|
((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
|
||||||
|
&& (mach) != bfd_mach_sparc_sparclite_le)
|
||||||
bfd_arch_mips, /* MIPS Rxxxx */
|
bfd_arch_mips, /* MIPS Rxxxx */
|
||||||
#define bfd_mach_mips3000 3000
|
#define bfd_mach_mips3000 3000
|
||||||
#define bfd_mach_mips3900 3900
|
#define bfd_mach_mips3900 3900
|
||||||
@ -279,6 +283,9 @@ typedef struct disassemble_info {
|
|||||||
zero if unknown. */
|
zero if unknown. */
|
||||||
bfd_vma target2; /* Second target address for dref2 */
|
bfd_vma target2; /* Second target address for dref2 */
|
||||||
|
|
||||||
|
/* Command line options specific to the target disassembler. */
|
||||||
|
char * disassembler_options;
|
||||||
|
|
||||||
} disassemble_info;
|
} disassemble_info;
|
||||||
|
|
||||||
|
|
||||||
@ -299,8 +306,7 @@ extern int print_insn_h8300s PARAMS ((bfd_vma, disassemble_info*));
|
|||||||
extern int print_insn_h8500 PARAMS ((bfd_vma, disassemble_info*));
|
extern int print_insn_h8500 PARAMS ((bfd_vma, disassemble_info*));
|
||||||
extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
|
extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
|
||||||
extern disassembler_ftype arc_get_disassembler PARAMS ((int, int));
|
extern disassembler_ftype arc_get_disassembler PARAMS ((int, int));
|
||||||
extern int print_insn_big_arm PARAMS ((bfd_vma, disassemble_info*));
|
extern int print_insn_arm PARAMS ((bfd_vma, disassemble_info*));
|
||||||
extern int print_insn_little_arm PARAMS ((bfd_vma, disassemble_info*));
|
|
||||||
extern int print_insn_sparc PARAMS ((bfd_vma, disassemble_info*));
|
extern int print_insn_sparc PARAMS ((bfd_vma, disassemble_info*));
|
||||||
extern int print_insn_big_a29k PARAMS ((bfd_vma, disassemble_info*));
|
extern int print_insn_big_a29k PARAMS ((bfd_vma, disassemble_info*));
|
||||||
extern int print_insn_little_a29k PARAMS ((bfd_vma, disassemble_info*));
|
extern int print_insn_little_a29k PARAMS ((bfd_vma, disassemble_info*));
|
||||||
@ -381,6 +387,15 @@ extern int generic_symbol_at_address
|
|||||||
(INFO).bytes_per_line = 0, \
|
(INFO).bytes_per_line = 0, \
|
||||||
(INFO).bytes_per_chunk = 0, \
|
(INFO).bytes_per_chunk = 0, \
|
||||||
(INFO).display_endian = BFD_ENDIAN_UNKNOWN, \
|
(INFO).display_endian = BFD_ENDIAN_UNKNOWN, \
|
||||||
|
(INFO).disassembler_options = NULL, \
|
||||||
(INFO).insn_info_valid = 0
|
(INFO).insn_info_valid = 0
|
||||||
|
|
||||||
|
#define _(x) x
|
||||||
|
|
||||||
|
/* from libbfd */
|
||||||
|
|
||||||
|
bfd_vma bfd_getl32 (const bfd_byte *addr);
|
||||||
|
bfd_vma bfd_getb32 (const bfd_byte *addr);
|
||||||
|
typedef enum bfd_boolean {false, true} boolean;
|
||||||
|
|
||||||
#endif /* ! defined (DIS_ASM_H) */
|
#endif /* ! defined (DIS_ASM_H) */
|
||||||
|
79
dis-buf.c
79
dis-buf.c
@ -1,79 +0,0 @@
|
|||||||
/* Disassemble from a buffer, for GNU.
|
|
||||||
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
||||||
|
|
||||||
#include "dis-asm.h"
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
/* Get LENGTH bytes from info's buffer, at target address memaddr.
|
|
||||||
Transfer them to myaddr. */
|
|
||||||
int
|
|
||||||
buffer_read_memory (memaddr, myaddr, length, info)
|
|
||||||
bfd_vma memaddr;
|
|
||||||
bfd_byte *myaddr;
|
|
||||||
int length;
|
|
||||||
struct disassemble_info *info;
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print an error message. We can assume that this is in response to
|
|
||||||
an error return from buffer_read_memory. */
|
|
||||||
void
|
|
||||||
perror_memory (status, memaddr, info)
|
|
||||||
int status;
|
|
||||||
bfd_vma memaddr;
|
|
||||||
struct disassemble_info *info;
|
|
||||||
{
|
|
||||||
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,
|
|
||||||
"Address 0x%x is out of bounds.\n", memaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
generic_print_address (addr, info)
|
|
||||||
bfd_vma addr;
|
|
||||||
struct disassemble_info *info;
|
|
||||||
{
|
|
||||||
(*info->fprintf_func) (info->stream, "0x%x", addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Just return the given address. */
|
|
||||||
|
|
||||||
int
|
|
||||||
generic_symbol_at_address (addr, info)
|
|
||||||
bfd_vma addr;
|
|
||||||
struct disassemble_info * info;
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
94
disas.c
94
disas.c
@ -2,12 +2,95 @@
|
|||||||
#include "dis-asm.h"
|
#include "dis-asm.h"
|
||||||
#include "disas.h"
|
#include "disas.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/* Filled in by elfload.c. Simplistic, but will do for now. */
|
/* Filled in by elfload.c. Simplistic, but will do for now. */
|
||||||
unsigned int disas_num_syms;
|
unsigned int disas_num_syms;
|
||||||
void *disas_symtab;
|
void *disas_symtab;
|
||||||
const char *disas_strtab;
|
const char *disas_strtab;
|
||||||
|
|
||||||
|
/* Get LENGTH bytes from info's buffer, at target address memaddr.
|
||||||
|
Transfer them to myaddr. */
|
||||||
|
int
|
||||||
|
buffer_read_memory (memaddr, myaddr, length, info)
|
||||||
|
bfd_vma memaddr;
|
||||||
|
bfd_byte *myaddr;
|
||||||
|
int length;
|
||||||
|
struct disassemble_info *info;
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print an error message. We can assume that this is in response to
|
||||||
|
an error return from buffer_read_memory. */
|
||||||
|
void
|
||||||
|
perror_memory (status, memaddr, info)
|
||||||
|
int status;
|
||||||
|
bfd_vma memaddr;
|
||||||
|
struct disassemble_info *info;
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
"Address 0x%x is out of bounds.\n", memaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
generic_print_address (addr, info)
|
||||||
|
bfd_vma addr;
|
||||||
|
struct disassemble_info *info;
|
||||||
|
{
|
||||||
|
(*info->fprintf_func) (info->stream, "0x%x", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just return the given address. */
|
||||||
|
|
||||||
|
int
|
||||||
|
generic_symbol_at_address (addr, info)
|
||||||
|
bfd_vma addr;
|
||||||
|
struct disassemble_info * info;
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* Disassemble this for me please... (debugging). */
|
/* Disassemble this for me please... (debugging). */
|
||||||
void disas(FILE *out, void *code, unsigned long size, enum disas_type type)
|
void disas(FILE *out, void *code, unsigned long size, enum disas_type type)
|
||||||
{
|
{
|
||||||
@ -35,6 +118,10 @@ void disas(FILE *out, void *code, unsigned long size, enum disas_type type)
|
|||||||
print_insn = print_insn_ppc;
|
print_insn = print_insn_ppc;
|
||||||
#elif defined(__alpha__)
|
#elif defined(__alpha__)
|
||||||
print_insn = print_insn_alpha;
|
print_insn = print_insn_alpha;
|
||||||
|
#elif defined(__sparc__)
|
||||||
|
print_insn = print_insn_sparc;
|
||||||
|
#elif defined(__arm__)
|
||||||
|
print_insn = print_insn_arm;
|
||||||
#else
|
#else
|
||||||
fprintf(out, "Asm output not supported on this arch\n");
|
fprintf(out, "Asm output not supported on this arch\n");
|
||||||
return;
|
return;
|
||||||
@ -51,6 +138,13 @@ void disas(FILE *out, void *code, unsigned long size, enum disas_type type)
|
|||||||
|
|
||||||
for (pc = code; pc < (uint8_t *)code + size; pc += count) {
|
for (pc = code; pc < (uint8_t *)code + size; pc += count) {
|
||||||
fprintf(out, "0x%08lx: ", (long)pc);
|
fprintf(out, "0x%08lx: ", (long)pc);
|
||||||
|
#ifdef __arm__
|
||||||
|
/* since data are included in the code, it is better to
|
||||||
|
display code data too */
|
||||||
|
if (type == DISAS_TARGET) {
|
||||||
|
fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
count = print_insn((unsigned long)pc, &disasm_info);
|
count = print_insn((unsigned long)pc, &disasm_info);
|
||||||
fprintf(out, "\n");
|
fprintf(out, "\n");
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
|
@ -1164,8 +1164,8 @@ int
|
|||||||
print_insn_x86 (pc, info, aflag, dflag)
|
print_insn_x86 (pc, info, aflag, dflag)
|
||||||
bfd_vma pc;
|
bfd_vma pc;
|
||||||
disassemble_info *info;
|
disassemble_info *info;
|
||||||
int aflag;
|
int volatile aflag;
|
||||||
int dflag;
|
int volatile dflag;
|
||||||
{
|
{
|
||||||
struct dis386 *dp;
|
struct dis386 *dp;
|
||||||
int i;
|
int i;
|
||||||
|
3214
sparc-dis.c
Normal file
3214
sparc-dis.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user