From 8724afdc73e0ddad86f46de1a3fbe0254575a76e Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 31 May 2009 20:58:20 +0000 Subject: Supported a new architecture (MIPS). git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@67 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 62 +++++ configure.ac | 1 + src/analysis/binary.c | 12 +- src/arch/Makefile.am | 3 +- src/arch/immediate.c | 20 +- src/arch/instruction.c | 58 +++- src/arch/instruction.h | 8 +- src/arch/mips/Makefile.am | 30 ++ src/arch/mips/instruction.c | 285 +++++++++++++++++++ src/arch/mips/instruction.h | 105 +++++++ src/arch/mips/op_add.c | 95 +++++++ src/arch/mips/op_and.c | 62 +++++ src/arch/mips/op_branch.c | 161 +++++++++++ src/arch/mips/op_jump.c | 114 ++++++++ src/arch/mips/op_load.c | 128 +++++++++ src/arch/mips/op_nop.c | 58 ++++ src/arch/mips/op_sr.c | 62 +++++ src/arch/mips/op_store.c | 95 +++++++ src/arch/mips/op_sub.c | 95 +++++++ src/arch/mips/opcodes.h | 107 ++++++++ src/arch/mips/operand.c | 649 ++++++++++++++++++++++++++++++++++++++++++++ src/arch/mips/operand.h | 156 +++++++++++ src/arch/mips/processor.c | 253 +++++++++++++++++ src/arch/mips/processor.h | 53 ++++ src/arch/mips/registers.c | 249 +++++++++++++++++ src/arch/mips/registers.h | 51 ++++ src/arch/processor.c | 4 +- src/arch/processor.h | 3 +- src/arch/x86/instruction.c | 507 ++++++++++++++++++++++++++++++++++ src/arch/x86/op_jump.c | 2 +- src/arch/x86/op_scas.c | 63 +++++ src/arch/x86/operand.c | 14 +- src/arch/x86/operand.h | 10 +- src/arch/x86/registers.c | 530 ++++++++++++++++++++++++++++++++++++ src/arch/x86/registers.h | 54 ++++ src/format/elf/e_elf.c | 20 +- src/format/exe_format.c | 20 +- src/format/exe_format.h | 3 +- 38 files changed, 4172 insertions(+), 30 deletions(-) create mode 100644 src/arch/mips/Makefile.am create mode 100644 src/arch/mips/instruction.c create mode 100644 src/arch/mips/instruction.h create mode 100644 src/arch/mips/op_add.c create mode 100644 src/arch/mips/op_and.c create mode 100644 src/arch/mips/op_branch.c create mode 100644 src/arch/mips/op_jump.c create mode 100644 src/arch/mips/op_load.c create mode 100644 src/arch/mips/op_nop.c create mode 100644 src/arch/mips/op_sr.c create mode 100644 src/arch/mips/op_store.c create mode 100644 src/arch/mips/op_sub.c create mode 100644 src/arch/mips/opcodes.h create mode 100644 src/arch/mips/operand.c create mode 100644 src/arch/mips/operand.h create mode 100644 src/arch/mips/processor.c create mode 100644 src/arch/mips/processor.h create mode 100644 src/arch/mips/registers.c create mode 100644 src/arch/mips/registers.h create mode 100644 src/arch/x86/instruction.c create mode 100644 src/arch/x86/op_scas.c create mode 100644 src/arch/x86/registers.c create mode 100644 src/arch/x86/registers.h diff --git a/ChangeLog b/ChangeLog index 48619cb..a722f65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,65 @@ +09-05-31 Cyrille Bagard + + * configure.ac: + Add the new Makefile from 'src/arch/mips' directory to AC_CONFIG_FILES. + + * src/analysis/binary.c: + Support a new architecture (MIPS). + + * src/arch/immediate.c: + Fix a bug when printing positive signed values. + + * src/arch/instruction.c: + * src/arch/instruction.h: + Improve the way operands are handled. + + * src/arch/Makefile.am: + Add mips/libarchmips.la to libarch_la_LIBADD and mips to SUBDIRS. + + * src/arch/mips/instruction.c: + * src/arch/mips/instruction.h: + * src/arch/mips/Makefile.am: + * src/arch/mips/op_add.c: + * src/arch/mips/op_and.c: + * src/arch/mips/op_branch.c: + * src/arch/mips/opcodes.h: + * src/arch/mips/operand.c: + * src/arch/mips/operand.h: + * src/arch/mips/op_jump.c: + * src/arch/mips/op_load.c: + * src/arch/mips/op_nop.c: + * src/arch/mips/op_sr.c: + * src/arch/mips/op_store.c: + * src/arch/mips/op_sub.c: + * src/arch/mips/processor.c: + * src/arch/mips/processor.h: + * src/arch/mips/registers.c: + * src/arch/mips/registers.h: + New entries: add enough support of the MIPS architecture to disassemble + a basic 'hello world' program. + + * src/arch/processor.c: + * src/arch/processor.h: + Support a new architecture (MIPS). + + * src/arch/x86/instruction.c: + New entries: add missing files from previous commit. + + * src/arch/x86/operand.c: + * src/arch/x86/operand.h: + * src/arch/x86/op_jump.c: + Typo. + + * src/arch/x86/op_scas.c: + * src/arch/x86/registers.c: + * src/arch/x86/registers.h: + New entries: add missing files from previous commit. + + * src/format/elf/e_elf.c: + * src/format/exe_format.c: + * src/format/exe_format.h: + Support a new architecture (MIPS). Make the loading more verbose. + 09-05-25 Cyrille Bagard * src/analysis/binary.c: diff --git a/configure.ac b/configure.ac index 68195e0..e533967 100644 --- a/configure.ac +++ b/configure.ac @@ -220,6 +220,7 @@ AC_CONFIG_FILES([Makefile src/analysis/Makefile src/arch/Makefile src/arch/jvm/Makefile + src/arch/mips/Makefile src/arch/x86/Makefile src/common/Makefile src/debug/Makefile diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 2c9166c..84401a3 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -116,14 +116,18 @@ openida_binary *load_binary_file(const char *filename) switch (get_exe_target_machine(result->format)) { - case FTM_386: - result->proc = get_arch_processor_for_type(APT_386); - break; - case FTM_JVM: result->proc = get_arch_processor_for_type(APT_JVM); break; + case FTM_MIPS: + result->proc = get_arch_processor_for_type(APT_MIPS); + break; + + case FTM_386: + result->proc = get_arch_processor_for_type(APT_386); + break; + default: goto lbf_error; break; diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index 0f4c9f5..6a1d45b 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -14,6 +14,7 @@ libarch_la_SOURCES = \ libarch_la_LIBADD = \ jvm/libarchjvm.la \ + mips/libarchmips.la \ x86/libarchx86.la libarch_la_LDFLAGS = @@ -26,4 +27,4 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = jvm x86 +SUBDIRS = jvm mips x86 diff --git a/src/arch/immediate.c b/src/arch/immediate.c index 7ef1220..f8c2474 100644 --- a/src/arch/immediate.c +++ b/src/arch/immediate.c @@ -370,16 +370,28 @@ static char *g_imm_operand_get_text(const GImmOperand *operand, const exe_format snprintf(result, 19, "0x%llx", operand->unsigned_imm.val64); break; case AOS_8_BITS_SIGNED: - snprintf(result, 19, "0x%hhx", ~operand->signed_imm.val8 + 1); + if (g_imm_operand_is_negative(operand)) + snprintf(result, 19, "0x%hhx", ~operand->signed_imm.val8 + 1); + else + snprintf(result, 19, "0x%hhx", operand->signed_imm.val8); break; case AOS_16_BITS_SIGNED: - snprintf(result, 19, "0x%hx", ~operand->signed_imm.val16 + 1); + if (g_imm_operand_is_negative(operand)) + snprintf(result, 19, "0x%hx", ~operand->signed_imm.val16 + 1); + else + snprintf(result, 19, "0x%hx", operand->signed_imm.val16); break; case AOS_32_BITS_SIGNED: - snprintf(result, 19, "0x%x", ~operand->signed_imm.val32 + 1); + if (g_imm_operand_is_negative(operand)) + snprintf(result, 19, "0x%x", ~operand->signed_imm.val32 + 1); + else + snprintf(result, 19, "0x%x", operand->signed_imm.val32); break; case AOS_64_BITS_SIGNED: - snprintf(result, 19, "0x%llx", ~operand->signed_imm.val64 + 1); + if (g_imm_operand_is_negative(operand)) + snprintf(result, 19, "0x%llx", ~operand->signed_imm.val64 + 1); + else + snprintf(result, 19, "0x%llx", operand->signed_imm.val64); break; } break; diff --git a/src/arch/instruction.c b/src/arch/instruction.c index 073f55c..21e72b7 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -134,7 +134,7 @@ void g_arch_instruction_get_location(GArchInstruction *instr, off_t *offset, off * Paramètres : instr = instance à mettre à jour. * * opererand = instruction à venir associer. * * * -* Description : Attache une seule opérande à une instruction. * +* Description : Attache un seul opérande à un instruction. * * * * Retour : - * * * @@ -158,7 +158,7 @@ void g_arch_instruction_attach_one_operand(GArchInstruction *instr, GArchOperand * operand1 = première instruction à venir associer. * * operand2 = seconde instruction à venir associer. * * * -* Description : Attache deux opérandes à une instruction. * +* Description : Attache deux opérandes à un instruction. * * * * Retour : - * * * @@ -179,6 +179,60 @@ void g_arch_instruction_attach_two_operands(GArchInstruction *instr, GArchOperan /****************************************************************************** * * +* Paramètres : instr = instance à mettre à jour. * +* opererand = instruction à venir associer. * +* * +* Description : Attache un opérande supplémentaire à une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand) +{ + instr->operands_count++; + instr->operands = (GArchOperand **)realloc(instr->operands, instr->operands_count * sizeof(GArchOperand *)); + + instr->operands[instr->operands_count - 1] = operand; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à mettre à jour. * +* opererand = instruction à venir dissocier. * +* * +* Description : Détache un opérande liée d'une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *operand) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < instr->operands_count; i++) + if (instr->operands[i] == operand) + break; + + if ((i + 1) < instr->operands_count) + memmove(&instr->operands[i], &instr->operands[i + 1], + (instr->operands_count - i - 1) * sizeof(GArchOperand *)); + + instr->operands_count--; + instr->operands = (GArchOperand **)realloc(instr->operands, instr->operands_count * sizeof(GArchOperand *)); + +} + + +/****************************************************************************** +* * * Paramètres : instr = instruction à traiter. * * format = format du binaire manipulé. * * syntax = type de représentation demandée. * diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 08f459f..ff0fd4a 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -73,12 +73,18 @@ void g_arch_instruction_set_location(GArchInstruction *, off_t, off_t, vmpa_t); /* Fournit la localisation d'une instruction. */ void g_arch_instruction_get_location(GArchInstruction *, off_t *, off_t *, vmpa_t *); -/* Attache une seule opérande à une instruction. */ +/* Attache un seul opérande à une instruction. */ void g_arch_instruction_attach_one_operand(GArchInstruction *, GArchOperand *); /* Attache deux opérandes à une instruction. */ void g_arch_instruction_attach_two_operands(GArchInstruction *, GArchOperand *, GArchOperand *); +/* Attache un opérande supplémentaire à une instruction. */ +void g_arch_instruction_attach_extra_operand(GArchInstruction *, GArchOperand *); + +/* Détache un opérande liée d'une instruction. */ +void g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *); + /* Traduit une instruction en version humainement lisible. */ char *g_arch_instruction_get_text(const GArchInstruction *, const exe_format *, AsmSyntax); diff --git a/src/arch/mips/Makefile.am b/src/arch/mips/Makefile.am new file mode 100644 index 0000000..7b25864 --- /dev/null +++ b/src/arch/mips/Makefile.am @@ -0,0 +1,30 @@ + +noinst_LTLIBRARIES = libarchmips.la + +libarchmips_la_SOURCES = \ + instruction.h instruction.c \ + op_add.c \ + op_and.c \ + op_branch.c \ + op_jump.c \ + op_load.c \ + op_nop.c \ + op_sr.c \ + op_store.c \ + op_sub.c \ + opcodes.h \ + operand.h operand.c \ + processor.h processor.c \ + registers.h registers.c + +libarchmips_la_CFLAGS = $(AM_CFLAGS) + + +INCLUDES = $(LIBGTK_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +SUBDIRS = diff --git a/src/arch/mips/instruction.c b/src/arch/mips/instruction.c new file mode 100644 index 0000000..54999a1 --- /dev/null +++ b/src/arch/mips/instruction.c @@ -0,0 +1,285 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.c - gestion des instructions de l'architecture MIPS + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "instruction.h" + + +#include "../instruction-int.h" +#include "../../common/endianness.h" + + + + + + + +/* Définition générique d'une instruction d'architecture mips (instance) */ +struct _GMipsInstruction +{ + GArchInstruction parent; /* A laisser en premier */ + + MipsOpcodes type; /* Position dans la liste */ + +}; + +/* Définition générique d'une instruction d'architecture mips (classe) */ +struct _GMipsInstructionClass +{ + GArchInstructionClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des instructions pour mips. */ +static void g_mips_instruction_class_init(GMipsInstructionClass *); + +/* Initialise une instance d'opérande d'architecture mips. */ +static void g_mips_instruction_init(GMipsInstruction *); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Répertoire de toutes les instructions MIPS */ +typedef struct _mips_instruction +{ + bin_t opcode; /* Opcode de l'instruction */ + + bool has_rt_mask; /* Condition sur les bits rt ? */ + bin_t rt_mask; /* Masque à retrouver 16<->20 */ + + bool has_funct; /* Extension d'opcode ? */ + bin_t funct; /* Seconde partie de l'opcode */ + + const char *keyword; /* Mot clef de la commande */ + +} mips_instruction; + + + +static mips_instruction _instructions[MOP_COUNT] = { + + [MOP_NOP] = { 0x00, false, 0x00, true, 0x00, "nop" }, + + [MOP_SRA] = { 0x00, false, 0x00, true, 0x03, "sra" }, + + + [MOP_JR] = { 0x00, false, 0x00, true, 0x08, "jr" }, + [MOP_JALR] = { 0x00, false, 0x00, true, 0x09, "jalr" }, + [MOP_JALR_HB] = { 0x00, false, 0x00, true, 0x09, "jalr.hb" }, /* Présent uniquement pour l'affichage */ + + + + [MOP_ADDU] = { 0x00, false, 0x00, true, 0x21, "addu" }, + [MOP_SUB] = { 0x00, false, 0x00, true, 0x22, "sub" }, + [MOP_SUBU] = { 0x00, false, 0x00, true, 0x23, "subu" }, + + [MOP_AND] = { 0x00, false, 0x00, true, 0x24, "and" }, + + + [MOP_BGEZAL] = { 0x04, true, 0x11, false, 0x00, "bgezal" }, + + + [MOP_BEQ] = { 0x10, false, 0x00, false, 0x00, "beq" }, + + [MOP_BNE] = { 0x14, false, 0x00, false, 0x00, "bne" }, + + [MOP_ADDIU] = { 0x24, false, 0x00, false, 0x00, "addiu" }, + + [MOP_BEQL] = { 0x50, false, 0x00, false, 0x00, "beql" }, + + + [MOP_LW] = { 0x8c, false, 0x00, false, 0x00, "lw" }, + + [MOP_LUI] = { 0x3c, false, 0x00, false, 0x00, "lui" }, + + + [MOP_LBU] = { 0x90, false, 0x00, false, 0x00, "lbu" }, + + [MOP_SB] = { 0xa0, false, 0x00, false, 0x00, "sb" }, + [MOP_SW] = { 0xac, false, 0x00, false, 0x00, "sw" } + +}; + + + + +/* Traduit une instruction en version humainement lisible. */ +static const char *mips_get_instruction_text(const GMipsInstruction *, const exe_format *, AsmSyntax); + + + + + + + + + +/* Indique le type défini pour une instruction d'architecture mips. */ +G_DEFINE_TYPE(GMipsInstruction, g_mips_instruction, G_TYPE_ARCH_INSTRUCTION); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des instructions pour MIPS. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_instruction_class_init(GMipsInstructionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser. * +* * +* Description : Initialise une instance d'instruction d'architecture MIPS. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_instruction_init(GMipsInstruction *instr) +{ + GArchInstruction *parent; /* Instance parente */ + + parent = G_ARCH_INSTRUCTION(instr); + + parent->get_text = (get_instruction_text_fc)mips_get_instruction_text; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'instruction à représenter. * +* * +* Description : Crée une instruction pour l'architecture MIPS. * +* * +* Retour : Architecture mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_mips_instruction_new(MipsOpcodes type) +{ + GArchInstruction *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_MIPS_INSTRUCTION, NULL); + + G_MIPS_INSTRUCTION(result)->type = type; + + return result; + +} + + + + + + + + + +/* ---------------------------------------------------------------------------------- */ +/* AIDE A LA MISE EN PLACE D'INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. * +* len = taille totale des données à analyser. * +* * +* Description : Recherche l'identifiant de la prochaine instruction. * +* * +* Retour : Identifiant de la prochaine instruction à tenter de charger. * +* * +* Remarques : - * +* * +******************************************************************************/ + +MipsOpcodes mips_guess_next_instruction(const bin_t *data, off_t pos, off_t len) +{ + MipsOpcodes result; /* Identifiant à retourner */ + uint32_t code; /* Code binaire à décoder */ + + if (!read_u32(&code, data, &pos, len, SRE_LITTLE/* FIXME */)) + return MOP_COUNT; + + for (result = 0; result < MOP_COUNT; result++) + { + if ((code & 0xfc000000) != (_instructions[result].opcode << 24)) continue; + + if (_instructions[result].has_rt_mask + && (code & 0x001f0000) != (_instructions[result].rt_mask << 16)) continue; + + if (_instructions[result].has_funct + && (code & 0x0000003f) != _instructions[result].funct) continue; + + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit une instruction en version humainement lisible. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *mips_get_instruction_text(const GMipsInstruction *instr, const exe_format *format, AsmSyntax syntax) +{ + const char *result; /* Chaîne à retourner */ + + result = strdup(_instructions[instr->type].keyword); + + return result; + +} diff --git a/src/arch/mips/instruction.h b/src/arch/mips/instruction.h new file mode 100644 index 0000000..79b63f9 --- /dev/null +++ b/src/arch/mips/instruction.h @@ -0,0 +1,105 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.h - prototypes pour la gestion des instructions de l'architecture MIPS + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#ifndef _ARCH_MIPS_INSTRUCTION_H +#define _ARCH_MIPS_INSTRUCTION_H + + +#include "../instruction.h" + + + + + + +/* Enumération de tous les opcodes */ +typedef enum _MipsOpcodes +{ + MOP_NOP, /* nop (0x00 ... 0x00) */ + + MOP_SRA, /* sra (0x00 ... 0x03) */ + + MOP_JR, /* jr (0x00 ... 0x08) */ + MOP_JALR, /* jalr (0x00 ... 0x09) */ + MOP_JALR_HB, /* jalr.hb (0x00 ... 0x09) */ + + + MOP_ADDU, /* addu (0x00 ... 0x21) */ + MOP_SUB, /* sub (0x00 ... 0x22) */ + MOP_SUBU, /* subu (0x00 ... 0x23) */ + + MOP_AND, /* and (0x00 ... 0x24) */ + + MOP_BGEZAL, /* bgezal (0x04 ... 0x11 ...) */ + + MOP_BEQ, /* beq (0x10) */ + MOP_BNE, /* bne (0x14) */ + + MOP_ADDIU, /* addiu (0x24) */ + + MOP_BEQL, /* beql (0x50) */ + + MOP_LW, /* lw (0x8c) */ + MOP_LUI, /* lui (0x3c) */ + + MOP_LBU, /* lbu (0x90) */ + + MOP_SB, /* sb (0xa0) */ + MOP_SW, /* sw (0xac) */ + + MOP_COUNT + + +} MipsOpcodes; + + +#define G_TYPE_MIPS_INSTRUCTION g_mips_instruction_get_type() +#define G_MIPS_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_mips_instruction_get_type(), GMipsInstruction)) +#define G_IS_MIPS_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_mips_instruction_get_type())) +#define G_MIPS_INSTRUCTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_mips_instruction_get_type(), GMipsInstructionIface)) + + +/* Définition générique d'une instruction d'architecture MIPS (instance) */ +typedef struct _GMipsInstruction GMipsInstruction; + +/* Définition générique d'une instruction d'architecture MIPS (classe) */ +typedef struct _GMipsInstructionClass GMipsInstructionClass; + + +/* Indique le type défini pour une instruction d'architecture MIPS. */ +GType g_mips_instruction_get_type(void); + +/* Crée une instruction pour l'architecture MIPS. */ +GArchInstruction *g_mips_instruction_new(MipsOpcodes); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Recherche l'identifiant de la prochaine instruction. */ +MipsOpcodes mips_guess_next_instruction(const bin_t *, off_t, off_t); + + + +#endif /* _ARCH_MIPS_INSTRUCTION_H */ diff --git a/src/arch/mips/op_add.c b/src/arch/mips/op_add.c new file mode 100644 index 0000000..a82cbf4 --- /dev/null +++ b/src/arch/mips/op_add.c @@ -0,0 +1,95 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_add.c - décodage des additions + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'addiu rt, rs, imm'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_add_immediate_unsigned(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_ADDIU); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RT, MIPS_OTP_RS, MIPS_OTP_IMMEDIATE)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'addu rd, rs, rt'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_add_unsigned(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_ADDU); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RD, MIPS_OTP_RS, MIPS_OTP_RT)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} diff --git a/src/arch/mips/op_and.c b/src/arch/mips/op_and.c new file mode 100644 index 0000000..1d3aae2 --- /dev/null +++ b/src/arch/mips/op_and.c @@ -0,0 +1,62 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_and.c - décodage des ET logiques + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'and rd, rs, rt'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_and(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_AND); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RD, MIPS_OTP_RS, MIPS_OTP_RT)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} diff --git a/src/arch/mips/op_branch.c b/src/arch/mips/op_branch.c new file mode 100644 index 0000000..04de039 --- /dev/null +++ b/src/arch/mips/op_branch.c @@ -0,0 +1,161 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_branch.c - décodage des sauts conditionnels + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'beq rs, rt, offset'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_branch_on_equal(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_BEQ); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RS, MIPS_OTP_RT, MIPS_OTP_OFFSET)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'beql rs, rt, offset'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_branch_on_equal_likely(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_BEQL); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RS, MIPS_OTP_RT, MIPS_OTP_OFFSET)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'bgezal rs, offset'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_branch_on_greater_than_or_equal_to_zero_and_link(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_BGEZAL); + + if (!mips_read_n_operands(result, data, pos, len, 2, MIPS_OTP_RS, MIPS_OTP_OFFSET)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'bne rs, rt, offset'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_branch_on_not_equal(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_BNE); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RS, MIPS_OTP_RT, MIPS_OTP_OFFSET)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} diff --git a/src/arch/mips/op_jump.c b/src/arch/mips/op_jump.c new file mode 100644 index 0000000..4faa6c6 --- /dev/null +++ b/src/arch/mips/op_jump.c @@ -0,0 +1,114 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_jump.c - décodage des sauts inconditionnels + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'jr rs'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_jump_register(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_JR); + + if (!mips_read_n_operands(result, data, pos, len, 1, MIPS_OTP_RS)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'jalr[.hb] [rd, ]rs'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_jump_and_link_register(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + off_t tmp; /* Pour ne pas toucher à 'pos' */ + uint32_t code; /* Code binaire à décoder */ + GArchOperand *operand; /* Opérande à analyser */ + const mips_register *reg; /* Registre implicite ? */ + + tmp = *pos; + + if (!read_u32(&code, data, &tmp, len, SRE_LITTLE/* FIXME */)) + return NULL; + + if (code & 0x400) result = g_mips_instruction_new(MOP_JALR_HB); + else result = g_mips_instruction_new(MOP_JALR); + + if (!mips_read_n_operands(result, data, pos, len, 2, MIPS_OTP_RD, MIPS_OTP_RS)) + { + /* TODO free(result);*/ + return NULL; + } + + operand = G_ARCH_INSTRUCTION(result)->operands[0]; + reg = g_mips_register_operand_get_register(G_MIPS_REGISTER_OPERAND(operand)); + + if (is_mips_register_return_address(reg)) + { + g_arch_instruction_detach_operand(G_ARCH_INSTRUCTION(result), operand); + /* TODO free(operand);*/ + } + + return result; + +} diff --git a/src/arch/mips/op_load.c b/src/arch/mips/op_load.c new file mode 100644 index 0000000..c8a308a --- /dev/null +++ b/src/arch/mips/op_load.c @@ -0,0 +1,128 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_load.c - décodage des chargements de données + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'lbu rt, offset(rs)'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_load_byte_unisgned(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_LBU); + + if (!mips_read_n_operands(result, data, pos, len, 2, MIPS_OTP_RT, MIPS_OTP_MEM_CONTENT)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'lui rt, imm'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_load_upper_immediate(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_LUI); + + if (!mips_read_n_operands(result, data, pos, len, 2, MIPS_OTP_RT, MIPS_OTP_IMMEDIATE)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'lw rt, offset(rs)'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_load_word(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_LW); + + if (!mips_read_n_operands(result, data, pos, len, 2, MIPS_OTP_RT, MIPS_OTP_MEM_CONTENT)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} diff --git a/src/arch/mips/op_nop.c b/src/arch/mips/op_nop.c new file mode 100644 index 0000000..972f4c0 --- /dev/null +++ b/src/arch/mips/op_nop.c @@ -0,0 +1,58 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_nop.c - décodage de l'instruction nulle + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* prefix = éventuel(s) préfixe(s) remarqué(s). * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'nop'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_nop(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_NOP); + + *pos += 4; + + return result; + +} diff --git a/src/arch/mips/op_sr.c b/src/arch/mips/op_sr.c new file mode 100644 index 0000000..f0ccf31 --- /dev/null +++ b/src/arch/mips/op_sr.c @@ -0,0 +1,62 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_sr.c - décodage des décallages à droite + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sra rd, rt, sa'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_shift_word_right_arithmetic(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_SRA); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RD, MIPS_OTP_RT, MIPS_OTP_SA)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} diff --git a/src/arch/mips/op_store.c b/src/arch/mips/op_store.c new file mode 100644 index 0000000..91307dd --- /dev/null +++ b/src/arch/mips/op_store.c @@ -0,0 +1,95 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_store.c - décodage des déchargements de données + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sb rt, offset(rs)'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_store_byte(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_SB); + + if (!mips_read_n_operands(result, data, pos, len, 2, MIPS_OTP_RT, MIPS_OTP_MEM_CONTENT)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sw rt, offset(rs)'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_store_word(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_SW); + + if (!mips_read_n_operands(result, data, pos, len, 2, MIPS_OTP_RT, MIPS_OTP_MEM_CONTENT)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} diff --git a/src/arch/mips/op_sub.c b/src/arch/mips/op_sub.c new file mode 100644 index 0000000..c6815a2 --- /dev/null +++ b/src/arch/mips/op_sub.c @@ -0,0 +1,95 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_sub.c - décodage des soustractions + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "opcodes.h" + + +#include "../instruction-int.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'subu rd, rs, rt'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_subtract_unsigned_word(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_SUBU); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RD, MIPS_OTP_RS, MIPS_OTP_RT)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'sub rd, rs, rt'. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *mips_read_instr_subtract_word(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, const GMipsProcessor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_mips_instruction_new(MOP_SUB); + + if (!mips_read_n_operands(result, data, pos, len, 3, MIPS_OTP_RD, MIPS_OTP_RS, MIPS_OTP_RT)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} diff --git a/src/arch/mips/opcodes.h b/src/arch/mips/opcodes.h new file mode 100644 index 0000000..276e752 --- /dev/null +++ b/src/arch/mips/opcodes.h @@ -0,0 +1,107 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * opcodes.h - prototypes pour la liste de tous les opcodes de l'architecture MIPS + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#ifndef _ARCH_MIPS_OPCODES_H +#define _ARCH_MIPS_OPCODES_H + + +#include "processor.h" +#include "instruction.h" + + + +/* Décode une instruction de type 'addiu rt, rs, imm'. */ +GArchInstruction *mips_read_instr_add_immediate_unsigned(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'addu rd, rs, rt'. */ +GArchInstruction *mips_read_instr_add_unsigned(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + +/* Décode une instruction de type 'and rd, rs, rt'. */ +GArchInstruction *mips_read_instr_and(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + +/* Décode une instruction de type 'beq rs, rt, offset'. */ +GArchInstruction *mips_read_instr_branch_on_equal(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'beql rs, rt, offset'. */ +GArchInstruction *mips_read_instr_branch_on_equal_likely(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'bgezal rs, offset'. */ +GArchInstruction *mips_read_instr_branch_on_greater_than_or_equal_to_zero_and_link(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'bne rs, rt, offset'. */ +GArchInstruction *mips_read_instr_branch_on_not_equal(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + +/* Décode une instruction de type 'jr rs'. */ +GArchInstruction *mips_read_instr_jump_register(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'jalr[.hb] [rd, ]rs'. */ +GArchInstruction *mips_read_instr_jump_and_link_register(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + +/* Décode une instruction de type 'lbu rt, offset(rs)'. */ +GArchInstruction *mips_read_instr_load_byte_unisgned(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'lui rt, imm'. */ +GArchInstruction *mips_read_instr_load_upper_immediate(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'lw rt, offset(rs)'. */ +GArchInstruction *mips_read_instr_load_word(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + +/* Décode une instruction de type 'nop'. */ +GArchInstruction *mips_read_instr_nop(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + +/* Décode une instruction de type 'sra rd, rt, sa'. */ +GArchInstruction *mips_read_instr_shift_word_right_arithmetic(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + +/* Décode une instruction de type 'sb rt, offset(rs)'. */ +GArchInstruction *mips_read_instr_store_byte(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'sw rt, offset(rs)'. */ +GArchInstruction *mips_read_instr_store_word(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + + +/* Décode une instruction de type 'subu rd, rs, rt'. */ +GArchInstruction *mips_read_instr_subtract_unsigned_word(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + +/* Décode une instruction de type 'sub rd, rs, rt'. */ +GArchInstruction *mips_read_instr_subtract_word(const bin_t *, off_t *, off_t, vmpa_t, const GMipsProcessor *); + + + + +#endif /* _ARCH_MIPS_OPCODES_H */ diff --git a/src/arch/mips/operand.c b/src/arch/mips/operand.c new file mode 100644 index 0000000..68599a4 --- /dev/null +++ b/src/arch/mips/operand.c @@ -0,0 +1,649 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * operand.h - prototypes pour la gestion des operandes de l'architecture MIPS + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "operand.h" + + +#include + + +#include "../immediate.h" +#include "../operand-int.h" +#include "../../common/endianness.h" +#include "../../common/extstr.h" + + + +/* ------------------------ COQUILLE VIDE POUR OPERANDE MIPS ------------------------ */ + + +/* Définition d'un opérande de la MIPS (instance) */ +struct _GMipsOperand +{ + GArchOperand parent; /* Instance parente */ + +}; + + +/* Définition d'un opérande de la MIPS (classe) */ +struct _GMipsOperandClass +{ + GArchOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes MIPS de base. */ +static void g_mips_operand_class_init(GMipsOperandClass *); + +/* Initialise une instance d'opérande de base pour MIPS. */ +static void g_mips_operand_init(GMipsOperand *); + + + +/* ----------------------- OPERANDES OFFRANT UN REGISTRE MIPS ----------------------- */ + + +/* Définition d'un opérande visant un registre MIPS (instance) */ +struct _GMipsRegisterOperand +{ + GMipsOperand parent; /* Instance parente */ + + mips_register *reg; /* Registre représenté */ + +}; + + +/* Définition d'un opérande visant un registre MIPS (classe) */ +struct _GMipsRegisterOperandClass +{ + GMipsOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes de registre MIPS. */ +static void g_mips_register_operand_class_init(GMipsRegisterOperandClass *); + +/* Initialise une instance d'opérande de registre MIPS. */ +static void g_mips_register_operand_init(GMipsRegisterOperand *); + +/* Traduit un opérande en version humainement lisible. */ +static char *g_mips_register_operand_get_text(const GMipsRegisterOperand *, const exe_format *, AsmSyntax); + + + +/* -------------------------- OPERANDES DE CONTENU MEMOIRE -------------------------- */ + + +/* Définition d'un opérande MIPS pointeur un contenu mémoire (instance) */ +struct _GMipsMemContentOperand +{ + GMipsOperand parent; /* Instance parente */ + + mips_register *base; /* Base de la lecture */ + GArchOperand *offset; /* Décallage à appliquer */ + +}; + + +/* Définition d'un opérande MIPS pointeur un contenu mémoire (classe) */ +struct _GMipsMemContentOperandClass +{ + GMipsOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes MIPS de contenu mémoire. */ +static void g_mips_mem_content_operand_class_init(GMipsMemContentOperandClass *); + +/* Initialise une instance d'opérande MIPS de contenu mémoire. */ +static void g_mips_mem_content_operand_init(GMipsMemContentOperand *); + +/* Traduit un opérande en version humainement lisible. */ +static char *g_mips_mem_content_operand_get_text(const GMipsMemContentOperand *, const exe_format *, AsmSyntax); + + + +/* ----------------------------- OPERANDES DE DECALLAGE ----------------------------- */ + + +/* Définition d'un opérande MIPS de décallage (instance) */ +struct _GMipsOffsetOperand +{ + GMipsOperand parent; /* Instance parente */ + + GArchOperand *offset; /* Décallage à appliquer */ + +}; + + +/* Définition d'un opérande MIPS de décallage (classe) */ +struct _GMipsOffsetOperandClass +{ + GMipsOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes MIPS de décallage. */ +static void g_mips_offset_operand_class_init(GMipsOffsetOperandClass *); + +/* Initialise une instance d'opérande MIPS de décallage. */ +static void g_mips_offset_operand_init(GMipsOffsetOperand *); + +/* Traduit un opérande en version humainement lisible. */ +static char *g_mips_offset_operand_get_text(const GMipsOffsetOperand *, const exe_format *, AsmSyntax); + + + +/* ---------------------------------------------------------------------------------- */ +/* COQUILLE VIDE POUR OPERANDE MIPS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande de MIPS. */ +G_DEFINE_TYPE(GMipsOperand, g_mips_operand, G_TYPE_ARCH_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes MIPS de base. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_operand_class_init(GMipsOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande de base pour MIPS. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_operand_init(GMipsOperand *operand) +{ + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERANDES OFFRANT UN REGISTRE MIPS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande de registre MIPS. */ +G_DEFINE_TYPE(GMipsRegisterOperand, g_mips_register_operand, G_TYPE_MIPS_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes de registre MIPS. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_register_operand_class_init(GMipsRegisterOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande de registre MIPS. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_register_operand_init(GMipsRegisterOperand *operand) +{ + GArchOperand *parent; /* Instance parente */ + + parent = G_ARCH_OPERAND(operand); + + parent->get_text = (get_operand_text_fc)g_mips_register_operand_get_text; + +} + + +/****************************************************************************** +* * +* Paramètres : index = identifiant du registre à représenter. * +* * +* Description : Crée un opérande visant un registre MIPS. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_mips_register_operand_new(bin_t index) +{ + GMipsRegisterOperand *result; /* Structure à retourner */ + mips_register *reg; /* Registre lu */ + + reg = get_mips_register(index); + + if (reg != NULL) + { + result = g_object_new(G_TYPE_MIPS_REGISTER_OPERAND, NULL); + + result->reg = reg; + + } + else result = NULL; + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_mips_register_operand_get_text(const GMipsRegisterOperand *operand, const exe_format *format, AsmSyntax syntax) +{ + char *result; /* Chaîne à retourner */ + + result = mips_register_as_text(operand->reg, syntax); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à consulter. * +* * +* Description : Fournit le registre MIPS représenté. * +* * +* Retour : Régistre MIPS représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const mips_register *g_mips_register_operand_get_register(const GMipsRegisterOperand *operand) +{ + return operand->reg; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERANDES DE CONTENU MEMOIRE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande MIPS de contenu mémoire. */ +G_DEFINE_TYPE(GMipsMemContentOperand, g_mips_mem_content_operand, G_TYPE_MIPS_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes MIPS de contenu mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_mem_content_operand_class_init(GMipsMemContentOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande MIPS de contenu mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_mem_content_operand_init(GMipsMemContentOperand *operand) +{ + GArchOperand *parent; /* Instance parente */ + + parent = G_ARCH_OPERAND(operand); + + parent->get_text = (get_operand_text_fc)g_mips_mem_content_operand_get_text; + +} + + +/****************************************************************************** +* * +* Paramètres : index = indice du registre de base. * +* offset = décallage supplémentaire à appliquer. * +* * +* Description : Crée un opérande MIPS de contenu mémoire. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_mips_mem_content_operand_new(bin_t index, int16_t offset) +{ + GMipsMemContentOperand *result; /* Structure à retourner */ + mips_register *base; /* Registre lu */ + + base = get_mips_register(index); + + if (base != NULL) + { + result = g_object_new(G_TYPE_MIPS_MEM_CONTENT_OPERAND, NULL); + + result->base = base; + result->offset = g_imm_operand_new_from_value(AOS_16_BITS_SIGNED, offset); + + } + else result = NULL; + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_mips_mem_content_operand_get_text(const GMipsMemContentOperand *operand, const exe_format *format, AsmSyntax syntax) +{ + char *result; /* Chaîne à retourner */ + char *tmp; /* Déplacement */ + + result = mips_register_as_text(operand->base, syntax); + + result = strprep(result, "["); + + if (g_imm_operand_is_negative(operand->offset)) result = stradd(result, "-"); + else result = stradd(result, "+"); + + tmp = g_arch_operand_get_text(G_ARCH_OPERAND(operand->offset), format, syntax); + result = stradd(result, tmp); + free(tmp); + + result = stradd(result, "]"); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OPERANDES DE DECALLAGE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande MIPS de décallage. */ +G_DEFINE_TYPE(GMipsOffsetOperand, g_mips_offset_operand, G_TYPE_MIPS_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes MIPS de décallage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_offset_operand_class_init(GMipsOffsetOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande MIPS de décallage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_offset_operand_init(GMipsOffsetOperand *operand) +{ + GArchOperand *parent; /* Instance parente */ + + parent = G_ARCH_OPERAND(operand); + + parent->get_text = (get_operand_text_fc)g_mips_offset_operand_get_text; + +} + + +/****************************************************************************** +* * +* Paramètres : offset = valeur de décallage à représenter. * +* * +* Description : Crée un opérande MIPS de décallage. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_mips_offset_operand_new(int16_t offset) +{ + GMipsOffsetOperand *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_MIPS_OFFSET_OPERAND, NULL); + + result->offset = g_imm_operand_new_from_value(AOS_16_BITS_SIGNED, offset); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_mips_offset_operand_get_text(const GMipsOffsetOperand *operand, const exe_format *format, AsmSyntax syntax) +{ + return g_arch_operand_get_text(G_ARCH_OPERAND(operand->offset), format, syntax); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* AIDE A LA CREATION D'OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont la définition est à compléter. [OUT]* +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* count = type du premier opérande. * +* ... = type des opérandes à interpréter. * +* * +* Description : Procède à la lecture de deux opérandes donnés. * +* * +* Retour : Bilan de l'opération : true en cas de succès, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool mips_read_n_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, unsigned int count, ...) +{ + bool result; /* Statut à retourner */ + uint32_t code; /* Code binaire à décoder */ + MipsOperandType type; /* Type d'opérand interprétée */ + va_list ap; /* Arguments potentiels */ + unsigned int i; /* Boucle de parcours */ + bin_t reg; /* Identifiant de registre */ + GArchOperand *op; /* Opérande décodé */ + + if (!read_u32(&code, data, pos, len, SRE_LITTLE/* FIXME */)) + return false; + + result = true; + + va_start(ap, count); + + for (i = 0; i < count; i++) + { + type = va_arg(ap, MipsOperandType); + + switch (type) + { + case MIPS_OTP_RS: + reg = (code & 0x3e00000) >> 21; + op = g_mips_register_operand_new(reg); + break; + + case MIPS_OTP_RT: + reg = (code & 0x1f0000) >> 16; + op = g_mips_register_operand_new(reg); + break; + + case MIPS_OTP_RD: + reg = (code & 0xf800) >> 11; + op = g_mips_register_operand_new(reg); + break; + + case MIPS_OTP_IMMEDIATE: + op = g_imm_operand_new_from_value(AOS_16_BITS, code & 0xffff); + break; + + + + + case MIPS_OTP_MEM_CONTENT: + op = g_mips_mem_content_operand_new((code & 0x3e00000) >> 21, code & 0xffff); + break; + + case MIPS_OTP_OFFSET: + op = g_mips_offset_operand_new(code & 0xffff); + break; + + case MIPS_OTP_SA: + op = g_imm_operand_new_from_value(AOS_8_BITS, (code & 0x7c0) >> 6); + break; + + default: + op = NULL; + break; + + } + + if (op == NULL) result = false; + else g_arch_instruction_attach_extra_operand(instr, op); + + } + + va_end(ap); + + return result; + +} diff --git a/src/arch/mips/operand.h b/src/arch/mips/operand.h new file mode 100644 index 0000000..22bd080 --- /dev/null +++ b/src/arch/mips/operand.h @@ -0,0 +1,156 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * operand.h - prototypes pour la gestion des operandes de l'architecture MIPS + * + * Copyright (C) 2008 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#ifndef _ARCH_MIPS_OPERAND_H +#define _ARCH_MIPS_OPERAND_H + + +#include + + +#include "registers.h" +#include "../instruction.h" + + + +/* ------------------------ COQUILLE VIDE POUR OPERANDE MIPS ------------------------ */ + + +#define G_TYPE_MIPS_OPERAND g_mips_operand_get_type() +#define G_MIPS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_mips_operand_get_type(), GMipsOperand)) +#define G_IS_MIPS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_mips_operand_get_type())) +#define G_MIPS_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_mips_operand_get_type(), GMipsOperandIface)) + + +/* Définition d'un opérande de MIPS (instance) */ +typedef struct _GMipsOperand GMipsOperand; + +/* Définition d'un opérande de MIPS (classe) */ +typedef struct _GMipsOperandClass GMipsOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de MIPS. */ +GType g_mips_operand_get_type(void); + + + +/* ----------------------- OPERANDES OFFRANT UN REGISTRE MIPS ----------------------- */ + + +#define G_TYPE_MIPS_REGISTER_OPERAND g_mips_register_operand_get_type() +#define G_MIPS_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_mips_register_operand_get_type(), GMipsRegisterOperand)) +#define G_IS_MIPS_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_mips_register_operand_get_type())) +#define G_MIPS_REGISTER_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_mips_register_operand_get_type(), GMipsRegisterOperandIface)) + + +/* Définition d'un opérande visant un registre MIPS (instance) */ +typedef struct _GMipsRegisterOperand GMipsRegisterOperand; + +/* Définition d'un opérande visant un registre MIPS (classe) */ +typedef struct _GMipsRegisterOperandClass GMipsRegisterOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de registre MIPS. */ +GType g_mips_register_operand_get_type(void); + +/* Crée un opérande visant un registre MIPS. */ +GArchOperand *g_mips_register_operand_new(bin_t); + +/* Fournit le registre MIPS représenté. */ +const mips_register *g_mips_register_operand_get_register(const GMipsRegisterOperand *); + + + +/* -------------------------- OPERANDES DE CONTENU MEMOIRE -------------------------- */ + + +#define G_TYPE_MIPS_MEM_CONTENT_OPERAND g_mips_mem_content_operand_get_type() +#define G_MIPS_MEM_CONTENT_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_mips_mem_content_operand_get_type(), GMipsMemContentOperand)) +#define G_IS_MIPS_MEM_CONTENT_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_mips_mem_content_operand_get_type())) +#define G_MIPS_MEM_CONTENT_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_mips_mem_content_operand_get_type(), GMipsMemContentOperandIface)) + + +/* Définition d'un opérande MIPS pointeur un contenu mémoire (instance) */ +typedef struct _GMipsMemContentOperand GMipsMemContentOperand; + +/* Définition d'un opérande MIPS pointeur un contenu mémoire (classe) */ +typedef struct _GMipsMemContentOperandClass GMipsMemContentOperandClass; + + +/* Indique le type défini par la GLib pour un opérande MIPS de contenu mémoire. */ +GType g_mips_mem_content_operand_get_type(void); + +/* Crée un opérande MIPS de contenu mémoire. */ +GArchOperand *g_mips_mem_content_operand_new(bin_t, int16_t); + + + +/* ----------------------------- OPERANDES DE DECALLAGE ----------------------------- */ + + +#define G_TYPE_MIPS_OFFSET_OPERAND g_mips_offset_operand_get_type() +#define G_MIPS_OFFSET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_mips_offset_operand_get_type(), GMipsOffsetOperand)) +#define G_IS_MIPS_OFFSET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_mips_offset_operand_get_type())) +#define G_MIPS_OFFSET_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_mips_offset_operand_get_type(), GMipsOffsetOperandIface)) + + +/* Définition d'un opérande MIPS de décallage (instance) */ +typedef struct _GMipsOffsetOperand GMipsOffsetOperand; + +/* Définition d'un opérande MIPS de décallage (classe) */ +typedef struct _GMipsOffsetOperandClass GMipsOffsetOperandClass; + + +/* Indique le type défini par la GLib pour un opérande MIPS de décallage. */ +GType g_mips_offset_operand_get_type(void); + +/* Crée un opérande MIPS de décallage. */ +GArchOperand *g_mips_offset_operand_new(int16_t); + + + +/* ------------------------- AIDE A LA CREATION D'OPERANDES ------------------------- */ + + +/* Types d'opérandes supportés */ +typedef enum _MIPSOperandType +{ + MIPS_OTP_RS, /* Registre rs (bits 21 -> 25) */ + MIPS_OTP_RT, /* Registre rs (bits 16 -> 20) */ + MIPS_OTP_RD, /* Registre rs (bits 11 -> 15) */ + MIPS_OTP_IMMEDIATE, /* Valeur imm. (bits 0 -> 15) */ + MIPS_OTP_TARGET_ADDRESS, /* Adresse (bits 0 -> 25) */ + + MIPS_OTP_MEM_CONTENT, /* Contenu mémoire [base+off] */ + MIPS_OTP_OFFSET, /* Décallage */ + MIPS_OTP_SA /* Valeur arithmétique */ + +} MipsOperandType; + + +/* Procède à la lecture de n opérandes donnés. */ +bool mips_read_n_operands(GArchInstruction *, const bin_t *data, off_t *pos, off_t, unsigned int, ...); + + + +#endif /* _ARCH_MIPS_OPERAND_H */ diff --git a/src/arch/mips/processor.c b/src/arch/mips/processor.c new file mode 100644 index 0000000..c28c7b4 --- /dev/null +++ b/src/arch/mips/processor.c @@ -0,0 +1,253 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * processor.c - gestion de l'architecture mips + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "processor.h" + + +#include "../processor-int.h" +#include "opcodes.h" + + + +/* Définition du processeur de la mips (instance) */ +struct _GMipsProcessor +{ + GArchProcessor parent; /* Instance parente */ + +}; + + +/* Définition du processeur de la mips (classe) */ +struct _GMipsProcessorClass +{ + GArchProcessorClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des lignes de descriptions initiales. */ +static void g_mips_processor_class_init(GMipsProcessorClass *); + +/* Initialise la classe des lignes de descriptions initiales. */ +static void g_mips_processor_init(GMipsProcessor *); + +/* Décode une instruction dans un flux de données. */ +static GArchInstruction *g_mips_processor_decode_instruction(const GMipsProcessor *, const bin_t *, off_t *, off_t, vmpa_t); + + +/* Indique le type défini par la GLib pour le processeur mips. */ +G_DEFINE_TYPE(GMipsProcessor, g_mips_processor, G_TYPE_ARCH_PROCESSOR); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des lignes de descriptions initiales. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_processor_class_init(GMipsProcessorClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : proc = instance à initialiser. * +* * +* Description : Initialise la classe des lignes de descriptions initiales. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_mips_processor_init(GMipsProcessor *proc) +{ + GArchProcessor *parent; /* Instance parente */ + + parent = G_ARCH_PROCESSOR(proc); + + parent->endianness = SRE_BIG; + + parent->decode = (decode_instruction_fc)g_mips_processor_decode_instruction; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée le support de l'architecture mips. * +* * +* Retour : Architecture mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchProcessor *g_mips_processor_new(void) +{ + GArchProcessor *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_MIPS_PROCESSOR, NULL); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : proc = architecture visée par la procédure. * +* data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* * +* Description : Décode une instruction dans un flux de données. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchInstruction *g_mips_processor_decode_instruction(const GMipsProcessor *proc, const bin_t *data, off_t *pos, off_t len, vmpa_t addr) +{ + GArchInstruction *result; /* Instruction à renvoyer */ + MipsOpcodes id; /* Identifiant d'instruction */ + + id = mips_guess_next_instruction(data, *pos, len); + + switch (id) + { + case MOP_NOP: + result = mips_read_instr_nop(data, pos, len, addr, proc); + break; + + + case MOP_SRA: + result = mips_read_instr_shift_word_right_arithmetic(data, pos, len, addr, proc); + break; + + + case MOP_JR: + result = mips_read_instr_jump_register(data, pos, len, addr, proc); + break; + + case MOP_JALR: + case MOP_JALR_HB: + result = mips_read_instr_jump_and_link_register(data, pos, len, addr, proc); + break; + + + + case MOP_ADDU: + result = mips_read_instr_add_unsigned(data, pos, len, addr, proc); + break; + + case MOP_SUB: + result = mips_read_instr_subtract_word(data, pos, len, addr, proc); + break; + + case MOP_SUBU: + result = mips_read_instr_subtract_unsigned_word(data, pos, len, addr, proc); + break; + + + + case MOP_AND: + result = mips_read_instr_and(data, pos, len, addr, proc); + break; + + + + case MOP_BGEZAL: + result = mips_read_instr_branch_on_greater_than_or_equal_to_zero_and_link(data, pos, len, addr, proc); + break; + + + case MOP_BEQ: + result = mips_read_instr_branch_on_equal(data, pos, len, addr, proc); + break; + + + case MOP_BNE: + result = mips_read_instr_branch_on_not_equal(data, pos, len, addr, proc); + break; + + + case MOP_ADDIU: + result = mips_read_instr_add_immediate_unsigned(data, pos, len, addr, proc); + break; + + + case MOP_BEQL: + result = mips_read_instr_branch_on_equal_likely(data, pos, len, addr, proc); + break; + + + case MOP_LW: + result = mips_read_instr_load_word(data, pos, len, addr, proc); + break; + + + case MOP_LUI: + result = mips_read_instr_load_upper_immediate(data, pos, len, addr, proc); + break; + + + + case MOP_LBU: + result = mips_read_instr_load_byte_unisgned(data, pos, len, addr, proc); + break; + + + case MOP_SB: + result = mips_read_instr_store_byte(data, pos, len, addr, proc); + break; + + case MOP_SW: + result = mips_read_instr_store_word(data, pos, len, addr, proc); + break; + + + default: + result = NULL; + break; + + } + + return result; + +} diff --git a/src/arch/mips/processor.h b/src/arch/mips/processor.h new file mode 100644 index 0000000..87a9ab1 --- /dev/null +++ b/src/arch/mips/processor.h @@ -0,0 +1,53 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * processor.h - prototypes pour la gestion de l'architecture mips + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#ifndef _ARCH_MIPS_PROCESSOR_H +#define _ARCH_MIPS_PROCESSOR_H + + +#include "../processor.h" + + + +#define G_TYPE_MIPS_PROCESSOR g_mips_processor_get_type() +#define G_MIPS_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_mips_processor_get_type(), GMipsProcessor)) +#define G_IS_MIPS_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_mips_processor_get_type())) +#define G_MIPS_PROCESSOR_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_mips_processor_get_type(), GMipsProcessorIface)) + + +/* Définition du processeur de la mips (instance) */ +typedef struct _GMipsProcessor GMipsProcessor; + +/* Définition du processeur de la mips (classe) */ +typedef struct _GMipsProcessorClass GMipsProcessorClass; + + +/* Indique le type défini par la GLib pour le processeur mips. */ +GType g_mips_processor_get_type(void); + +/* Crée le support de l'architecture mips. */ +GArchProcessor *g_mips_processor_new(void); + + + +#endif /* _ARCH_MIPS_PROCESSOR_H */ diff --git a/src/arch/mips/registers.c b/src/arch/mips/registers.c new file mode 100644 index 0000000..89e13ca --- /dev/null +++ b/src/arch/mips/registers.c @@ -0,0 +1,249 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * registers.c - aides auxiliaires relatives aux registres MIPS + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "registers.h" + + +#include +#include + + + +/* Registre MIPS */ +enum _mips_register +{ + MIPS_REG_ZERO = 0, /* Constante zéro */ + MIPS_REG_AT = 1, /* Temporaire assemblage */ + MIPS_REG_V_0 = 2, /* Retours et évaluations */ + MIPS_REG_V_1 = 3, /* Retours et évaluations */ + MIPS_REG_ARG_0 = 4, /* Arguments de fonction */ + MIPS_REG_ARG_1 = 5, /* Arguments de fonction */ + MIPS_REG_ARG_2 = 6, /* Arguments de fonction */ + MIPS_REG_ARG_3 = 7, /* Arguments de fonction */ + MIPS_REG_TMP_0 = 8, /* Stockage temporaire */ + MIPS_REG_TMP_1 = 9, /* Stockage temporaire */ + MIPS_REG_TMP_2 = 10, /* Stockage temporaire */ + MIPS_REG_TMP_3 = 11, /* Stockage temporaire */ + MIPS_REG_TMP_4 = 12, /* Stockage temporaire */ + MIPS_REG_TMP_5 = 13, /* Stockage temporaire */ + MIPS_REG_TMP_6 = 14, /* Stockage temporaire */ + MIPS_REG_TMP_7 = 15, /* Stockage temporaire */ + MIPS_REG_SAV_0 = 16, /* Sauvegarde des registres */ + MIPS_REG_SAV_1 = 17, /* Sauvegarde des registres */ + MIPS_REG_SAV_2 = 18, /* Sauvegarde des registres */ + MIPS_REG_SAV_3 = 19, /* Sauvegarde des registres */ + MIPS_REG_SAV_4 = 20, /* Sauvegarde des registres */ + MIPS_REG_SAV_5 = 21, /* Sauvegarde des registres */ + MIPS_REG_SAV_6 = 22, /* Sauvegarde des registres */ + MIPS_REG_SAV_7 = 23, /* Sauvegarde des registres */ + MIPS_REG_TMP_8 = 24, /* Stockage temporaire */ + MIPS_REG_TMP_9 = 25, /* Stockage temporaire */ + MIPS_REG_KERN_0 = 26, /* Réservé pour le noyau */ + MIPS_REG_KERN_1 = 27, /* Réservé pour le noyau */ + MIPS_REG_GLOBAL = 28, /* Pointeur global */ + MIPS_REG_STACK = 29, /* Pointeur de pile */ + MIPS_REG_FRAME = 30, /* Pointeur de frame */ + MIPS_REG_RET = 31 /* Adresse de retour */ + +}; + + + +/****************************************************************************** +* * +* Paramètres : value = valeur correspondant au registre. * +* * +* Description : Récupère l'indentifiant interne d'un registre. * +* * +* Retour : Registre définit ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +mips_register *get_mips_register(bin_t value) +{ + mips_register *result; /* Représentation à renvoyer */ + + if (value > 31) return NULL; + + result = (mips_register *)calloc(1, sizeof(mips_register)); + + *result = value; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à supprimer. * +* * +* Description : Efface de la mémoire l'indentifiant interne d'un registre. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void free_mips_register(mips_register *reg) +{ + free(reg); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à consulter. * +* * +* Description : Indique si le registre correspond à ra. * +* * +* Retour : true si la correspondance est avérée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool is_mips_register_return_address(const mips_register *reg) +{ + return (*reg == MIPS_REG_RET); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à imprimer. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un registre MIPS en texte. * +* * +* Retour : Traduction en chaîne à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *mips_register_as_text(const mips_register *reg, AsmSyntax syntax) +{ + char *result; /* Chaîne à renvoyer */ + + result = (char *)calloc(6, sizeof(char)); + + switch (syntax) + { + case ASX_INTEL: + switch (*reg) + { + case MIPS_REG_ZERO: + snprintf(result, 6, "zero"); + break; + case MIPS_REG_AT: + snprintf(result, 6, "at"); + break; + case MIPS_REG_V_0 ... MIPS_REG_V_1: + snprintf(result, 6, "v%c", '0' + *reg - MIPS_REG_V_0); + break; + case MIPS_REG_ARG_0 ... MIPS_REG_ARG_3: + snprintf(result, 6, "a%c", '0' + *reg - MIPS_REG_ARG_0); + break; + case MIPS_REG_TMP_0 ... MIPS_REG_TMP_7: + snprintf(result, 6, "t%c", '0' + *reg - MIPS_REG_TMP_0); + break; + case MIPS_REG_SAV_0 ... MIPS_REG_SAV_7: + snprintf(result, 6, "s%c", '0' + *reg - MIPS_REG_SAV_0); + break; + case MIPS_REG_TMP_8 ... MIPS_REG_TMP_9: + snprintf(result, 6, "t%c", '8' + *reg - MIPS_REG_TMP_8); + break; + case MIPS_REG_KERN_0 ... MIPS_REG_KERN_1: + snprintf(result, 6, "k%c", '0' + *reg - MIPS_REG_KERN_0); + break; + case MIPS_REG_GLOBAL: + snprintf(result, 6, "gp"); + break; + case MIPS_REG_STACK: + snprintf(result, 6, "sp"); + break; + case MIPS_REG_FRAME: + snprintf(result, 6, "fp"); + break; + case MIPS_REG_RET: + snprintf(result, 6, "ra"); + break; + } + break; + + case ASX_ATT: + switch (*reg) + { + case MIPS_REG_ZERO: + snprintf(result, 6, "%%zero"); + break; + case MIPS_REG_AT: + snprintf(result, 6, "%%at"); + break; + case MIPS_REG_V_0 ... MIPS_REG_V_1: + snprintf(result, 6, "%%v%c", '0' + *reg - MIPS_REG_V_0); + break; + case MIPS_REG_ARG_0 ... MIPS_REG_ARG_3: + snprintf(result, 6, "%%a%c", '0' + *reg - MIPS_REG_ARG_0); + break; + case MIPS_REG_TMP_0 ... MIPS_REG_TMP_7: + snprintf(result, 6, "%%t%c", '0' + *reg - MIPS_REG_TMP_0); + break; + case MIPS_REG_SAV_0 ... MIPS_REG_SAV_7: + snprintf(result, 6, "%%s%c", '0' + *reg - MIPS_REG_SAV_0); + break; + case MIPS_REG_TMP_8 ... MIPS_REG_TMP_9: + snprintf(result, 6, "%%t%c", '8' + *reg - MIPS_REG_TMP_8); + break; + case MIPS_REG_KERN_0 ... MIPS_REG_KERN_1: + snprintf(result, 6, "%%k%c", '0' + *reg - MIPS_REG_KERN_0); + break; + case MIPS_REG_GLOBAL: + snprintf(result, 6, "%%gp"); + break; + case MIPS_REG_STACK: + snprintf(result, 6, "%%sp"); + break; + case MIPS_REG_FRAME: + snprintf(result, 6, "%%fp"); + break; + case MIPS_REG_RET: + snprintf(result, 6, "%%ra"); + break; + } + break; + + default: + break; + + } + + return result; + +} diff --git a/src/arch/mips/registers.h b/src/arch/mips/registers.h new file mode 100644 index 0000000..a9aaaae --- /dev/null +++ b/src/arch/mips/registers.h @@ -0,0 +1,51 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * registers.h - prototypes pour les aides auxiliaires relatives aux registres MIPS + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#ifndef _ARCH_MIPS_REGISTERS_H +#define _ARCH_MIPS_REGISTERS_H + + +#include "../archbase.h" +#include "../operand.h" + + + +/* Registre MIPS */ +typedef enum _mips_register mips_register; + + +/* Récupère l'indentifiant interne d'un registre. */ +mips_register *get_mips_register(bin_t); + +/* Efface de la mémoire l'indentifiant interne d'un registre. */ +void free_mips_register(mips_register *); + +/* Indique si le registre correspond à ra. */ +bool is_mips_register_return_address(const mips_register *); + +/* Traduit un registre MIPS en texte. */ +char *mips_register_as_text(const mips_register *, AsmSyntax); + + + +#endif /* _ARCH_MIPS_REGISTERS_H */ diff --git a/src/arch/processor.c b/src/arch/processor.c index 191fa10..317e893 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -43,6 +43,7 @@ #include "artificial.h" #include "jvm/processor.h" +#include "mips/processor.h" #include "x86/processor.h" @@ -189,8 +190,9 @@ GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *proc bool init_all_processors(void) { - _processors_list[APT_386] = g_x86_processor_new(); _processors_list[APT_JVM] = g_jvm_processor_new(); + _processors_list[APT_MIPS] = g_mips_processor_new(); + _processors_list[APT_386] = g_x86_processor_new(); return true; diff --git a/src/arch/processor.h b/src/arch/processor.h index c37811f..5726197 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -84,8 +84,9 @@ GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *, co /* Type de processeurs disponibles */ typedef enum _ArchProcessorType { - APT_386, /* Intel 80386 */ APT_JVM, /* Java Virtual Machine */ + APT_MIPS, /* Mips 32 ou 64 bits */ + APT_386, /* Intel 80386 */ APT_COUNT diff --git a/src/arch/x86/instruction.c b/src/arch/x86/instruction.c new file mode 100644 index 0000000..f68ec59 --- /dev/null +++ b/src/arch/x86/instruction.c @@ -0,0 +1,507 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.c - gestion des instructions de l'architecture x86 + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "instruction.h" + + +#include "../instruction-int.h" +#include "../../common/extstr.h" + + + +/* Définition générique d'une instruction d'architecture x86 (instance) */ +struct _GX86Instruction +{ + GArchInstruction parent; /* A laisser en premier */ + + X86Opcodes type; /* Position dans la liste */ + + X86Prefix prefixes; /* Préfixes finalement trouvés */ + +}; + +/* Définition générique d'une instruction d'architecture x86 (classe) */ +struct _GX86InstructionClass +{ + GArchInstructionClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des instructions pour x86. */ +static void g_x86_instruction_class_init(GX86InstructionClass *); + +/* Initialise une instance d'opérande d'architecture x86. */ +static void g_x86_instruction_init(GX86Instruction *); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Répertoire de toutes les instructions x86 */ +typedef struct _x86_instruction +{ + bool care_of_data; /* Devinette = repas ? */ + bin_t opcode; /* Opcode de l'instruction */ + bin_t op_extension; /* Extension de l'opcode */ + + const char *keyword; /* Mot clef de la commande */ + + X86Prefix prefix; /* Eventuel(s) préfixe(s) */ + +} x86_instruction; + + +#define OPCODE_EXT(eop) ((eop) & 0x38) +#define IDX_TO_EXT(idx) (idx == -1 ? 0xff : idx << 3) + + +static x86_instruction _instructions[XOP_COUNT] = { + + [XOP_ADD_RM8_R8] = { false, 0x00, IDX_TO_EXT(-1), "add", XPX_NONE }, + [XOP_ADD_RM1632_R1632] = { false, 0x01, IDX_TO_EXT(-1), "add", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_ADD_R8_RM8] = { false, 0x02, IDX_TO_EXT(-1), "add", XPX_NONE }, + [XOP_ADD_R1632_RM1632] = { false, 0x03, IDX_TO_EXT(-1), "add", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_ADD_AL_IMM8] = { false, 0x04, IDX_TO_EXT(-1), "add", XPX_NONE }, + [XOP_ADD_E_AX_IMM1632] = { false, 0x05, IDX_TO_EXT(-1), "add", XPX_OPERAND_SIZE_OVERRIDE }, + + [XOP_OR_R8_RM8] = { false, 0x0a, IDX_TO_EXT(-1), "or", XPX_NONE }, + [XOP_OR_AL_IMM8] = { false, 0x0c, IDX_TO_EXT(-1), "or", XPX_NONE }, + + [XOP_ADC_RM8_R8] = { false, 0x10, IDX_TO_EXT(-1), "adc", XPX_NONE }, + + [XOP_AND_RM8_R8] = { false, 0x20, IDX_TO_EXT(-1), "and", XPX_NONE }, + + [XOP_SUB_RM1632_R1632] = { false, 0x29, IDX_TO_EXT(-1), "sub", XPX_OPERAND_SIZE_OVERRIDE }, + + [XOP_SUB_R8_RM8] = { false, 0x2a, IDX_TO_EXT(-1), "sub", XPX_NONE }, + [XOP_SUB_AL_IMM8] = { false, 0x2c, IDX_TO_EXT(-1), "sub", XPX_NONE }, + + [XOP_SUB_E_AX_IMM1632] = { false, 0x2d, IDX_TO_EXT(-1), "sub", XPX_OPERAND_SIZE_OVERRIDE }, + + + + [XOP_XOR_RM8_R8] = { false, 0x30, IDX_TO_EXT(-1), "xor", XPX_NONE}, + [XOP_XOR_RM1632_R1632] = { false, 0x31, IDX_TO_EXT(-1), "xor", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XOR_R8_RM8] = { false, 0x32, IDX_TO_EXT(-1), "xor", XPX_NONE}, + [XOP_XOR_R1632_RM1632] = { false, 0x33, IDX_TO_EXT(-1), "xor", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XOR_AL_IMM8] = { false, 0x34, IDX_TO_EXT(-1), "xor", XPX_NONE }, + [XOP_XOR_E_AX_IMM1632] = { false, 0x35, IDX_TO_EXT(-1), "xor", XPX_OPERAND_SIZE_OVERRIDE }, + + + + + + [XOP_CMP_RM1632_R1632] = { false, 0x39, IDX_TO_EXT(-1), "cmp", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_INC_E_AX] = { true, 0x40, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_INC_E_CX] = { true, 0x41, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_INC_E_DX] = { true, 0x42, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_INC_E_BX] = { true, 0x43, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_INC_E_SP] = { true, 0x44, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_INC_E_BP] = { true, 0x45, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_INC_E_SI] = { true, 0x46, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_INC_E_DI] = { true, 0x47, IDX_TO_EXT(-1), "inc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_DEC_E_AX] = { true, 0x48, IDX_TO_EXT(-1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_DEC_E_CX] = { true, 0x49, IDX_TO_EXT(-1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_DEC_E_DX] = { true, 0x4a, IDX_TO_EXT(-1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_DEC_E_BX] = { true, 0x4b, IDX_TO_EXT(-1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_DEC_E_SP] = { true, 0x4c, IDX_TO_EXT(-1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_DEC_E_BP] = { true, 0x4d, IDX_TO_EXT(-1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_DEC_E_SI] = { true, 0x4e, IDX_TO_EXT(-1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_DEC_E_DI] = { true, 0x4f, IDX_TO_EXT(-1), "dec", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_E_AX] = { true, 0x50, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_E_CX] = { true, 0x51, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_E_DX] = { true, 0x52, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_E_BX] = { true, 0x53, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_E_SP] = { true, 0x54, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_E_BP] = { true, 0x55, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_E_SI] = { true, 0x56, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_E_DI] = { true, 0x57, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_POP_E_AX] = { true, 0x58, IDX_TO_EXT(-1), "pop", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_POP_E_CX] = { true, 0x59, IDX_TO_EXT(-1), "pop", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_POP_E_DX] = { true, 0x5a, IDX_TO_EXT(-1), "pop", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_POP_E_BX] = { true, 0x5b, IDX_TO_EXT(-1), "pop", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_POP_E_SP] = { true, 0x5c, IDX_TO_EXT(-1), "pop", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_POP_E_BP] = { true, 0x5d, IDX_TO_EXT(-1), "pop", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_POP_E_SI] = { true, 0x5e, IDX_TO_EXT(-1), "pop", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_POP_E_DI] = { true, 0x5f, IDX_TO_EXT(-1), "pop", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_PUSH_IMM1632] = { false, 0x68, IDX_TO_EXT(-1), "push", XPX_OPERAND_SIZE_OVERRIDE }, + + + + [XOP_JO_REL8] = { false, 0x70, IDX_TO_EXT(-1), "jo", XPX_NONE }, + [XOP_JNO_REL8] = { false, 0x71, IDX_TO_EXT(-1), "jno", XPX_NONE }, + [XOP_JB_REL8] = { false, 0x72, IDX_TO_EXT(-1), "jb", XPX_NONE }, + [XOP_JNB_REL8] = { false, 0x73, IDX_TO_EXT(-1), "jnb", XPX_NONE }, + [XOP_JE_REL8] = { false, 0x74, IDX_TO_EXT(-1), "je", XPX_NONE }, + [XOP_JNE_REL8] = { false, 0x75, IDX_TO_EXT(-1), "jne", XPX_NONE }, + [XOP_JNA_REL8] = { false, 0x76, IDX_TO_EXT(-1), "jna", XPX_NONE }, + [XOP_JA_REL8] = { false, 0x77, IDX_TO_EXT(-1), "ja", XPX_NONE }, + [XOP_JS_REL8] = { false, 0x78, IDX_TO_EXT(-1), "js", XPX_NONE }, + [XOP_JNS_REL8] = { false, 0x79, IDX_TO_EXT(-1), "jns", XPX_NONE }, + [XOP_JP_REL8] = { false, 0x7a, IDX_TO_EXT(-1), "jp", XPX_NONE }, + [XOP_JNP_REL8] = { false, 0x7b, IDX_TO_EXT(-1), "jnp", XPX_NONE }, + [XOP_JL_REL8] = { false, 0x7c, IDX_TO_EXT(-1), "jl", XPX_NONE }, + [XOP_JNL_REL8] = { false, 0x7d, IDX_TO_EXT(-1), "jnl", XPX_NONE }, + [XOP_JNG_REL8] = { false, 0x7e, IDX_TO_EXT(-1), "jng", XPX_NONE }, + [XOP_JG_REL8] = { false, 0x7f, IDX_TO_EXT(-1), "jg", XPX_NONE }, + [XOP_ADD_RM8_IMM8] = { false, 0x80, IDX_TO_EXT(0), "add", XPX_NONE }, + [XOP_OR_RM8_IMM8] = { false, 0x80, IDX_TO_EXT(1), "or", XPX_NONE }, + [XOP_ADC_RM8_IMM8] = { false, 0x80, IDX_TO_EXT(2), "adc", XPX_NONE }, + [XOP_SBB_RM8_IMM8] = { false, 0x80, IDX_TO_EXT(3), "sbb", XPX_NONE }, + [XOP_AND_RM8_IMM8] = { false, 0x80, IDX_TO_EXT(4), "and", XPX_NONE }, + [XOP_SUB_RM8_IMM8] = { false, 0x80, IDX_TO_EXT(5), "sub", XPX_NONE }, + [XOP_XOR_RM8_IMM8] = { false, 0x80, IDX_TO_EXT(6), "xor", XPX_NONE }, + [XOP_CMP_RM8_IMM8] = { false, 0x80, IDX_TO_EXT(7), "cmp", XPX_NONE }, + [XOP_ADD_RM1632_IMM1632] = { false, 0x81, IDX_TO_EXT(0), "add", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_OR_RM1632_IMM1632] = { false, 0x81, IDX_TO_EXT(0), "add", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_ADC_RM1632_IMM1632] = { false, 0x81, IDX_TO_EXT(2), "adc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SBB_RM1632_IMM1632] = { false, 0x81, IDX_TO_EXT(3), "sbb", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_AND_RM1632_IMM1632] = { false, 0x81, IDX_TO_EXT(4), "and", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SUB_RM1632_IMM1632] = { false, 0x81, IDX_TO_EXT(5), "sub", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XOR_RM1632_IMM1632] = { false, 0x81, IDX_TO_EXT(6), "xor", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_CMP_RM1632_IMM1632] = { false, 0x81, IDX_TO_EXT(7), "cmp", XPX_OPERAND_SIZE_OVERRIDE }, + + + + [XOP_ADD_RM1632_IMM8] = { false, 0x83, IDX_TO_EXT(0), "add", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_OR_RM1632_IMM8] = { false, 0x83, IDX_TO_EXT(1), "or", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_ADC_RM1632_IMM8] = { false, 0x83, IDX_TO_EXT(2), "adc", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SBB_RM1632_IMM8] = { false, 0x83, IDX_TO_EXT(3), "sbb", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_AND_RM1632_IMM8] = { false, 0x83, IDX_TO_EXT(4), "and", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SUB_RM1632_IMM8] = { false, 0x83, IDX_TO_EXT(5), "sub", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XOR_RM1632_IMM8] = { false, 0x83, IDX_TO_EXT(6), "xor", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_CMP_RM1632_IMM8] = { false, 0x83, IDX_TO_EXT(7), "cmp", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_TEST_RM8_R8] = { false, 0x84, IDX_TO_EXT(-1), "test", XPX_NONE }, + [XOP_TEST_RM1632_R1632] = { false, 0x85, IDX_TO_EXT(-1), "test", XPX_OPERAND_SIZE_OVERRIDE }, + + [XOP_MOV_RM8_R8] = { false, 0x88, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_RM1632_R1632] = { false, 0x89, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_MOV_R1632_RM1632] = { false, 0x8b, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_LEA_R1632_M] = { false, 0x8d, IDX_TO_EXT(-1), "lea", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_NOP] = { false, 0x90, IDX_TO_EXT(-1), "nop", XPX_NONE }, + [XOP_XCHG_R1632_E_AX] = { true, 0x90, IDX_TO_EXT(-1), "xchg", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XCHG_R1632_E_CX] = { true, 0x91, IDX_TO_EXT(-1), "xchg", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XCHG_R1632_E_DX] = { true, 0x92, IDX_TO_EXT(-1), "xchg", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XCHG_R1632_E_BX] = { true, 0x93, IDX_TO_EXT(-1), "xchg", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XCHG_R1632_E_SP] = { true, 0x94, IDX_TO_EXT(-1), "xchg", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XCHG_R1632_E_BP] = { true, 0x95, IDX_TO_EXT(-1), "xchg", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XCHG_R1632_E_SI] = { true, 0x96, IDX_TO_EXT(-1), "xchg", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_XCHG_R1632_E_DI] = { true, 0x97, IDX_TO_EXT(-1), "xchg", XPX_OPERAND_SIZE_OVERRIDE }, + + + + [XOP_MOV_AL_MOFFS8] = { false, 0xa0, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_E_AX_MOFFS1632] = { false, 0xa1, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOV_MOFFS8_AL] = { false, 0xa2, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_MOFFS1632_E_AX] = { false, 0xa3, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_TEST_AL_IMM8] = { false, 0xa8, IDX_TO_EXT(-1), "test", XPX_NONE }, + [XOP_TEST_E_AX_IMM1632] = { false, 0xa9, IDX_TO_EXT(-1), "test", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_SCAS_AL_M8] = { false, 0xae, IDX_TO_EXT(-1), "scas", XPX_NONE }, + + + [XOP_MOV_AL_IMM8] = { true, 0xb0, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_CL_IMM8] = { true, 0xb1, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_DL_IMM8] = { true, 0xb2, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_BL_IMM8] = { true, 0xb3, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_AH_IMM8] = { true, 0xb4, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_CH_IMM8] = { true, 0xb5, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_DH_IMM8] = { true, 0xb6, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_BH_IMM8] = { true, 0xb7, IDX_TO_EXT(-1), "mov", XPX_NONE }, + [XOP_MOV_E_AX_IMM1632] = { true, 0xb8, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOV_E_CX_IMM1632] = { true, 0xb9, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOV_E_DX_IMM1632] = { true, 0xba, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOV_E_BX_IMM1632] = { true, 0xbb, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOV_E_SP_IMM1632] = { true, 0xbc, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOV_E_BP_IMM1632] = { true, 0xbd, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOV_E_SI_IMM1632] = { true, 0xbe, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_MOV_E_DI_IMM1632] = { true, 0xbf, IDX_TO_EXT(-1), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + + + + [XOP_ROL_RM1632_IMM8] = { false, 0xc1, IDX_TO_EXT(0), "rol", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_ROR_RM1632_IMM8] = { false, 0xc1, IDX_TO_EXT(1), "ror", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_RCL_RM1632_IMM8] = { false, 0xc1, IDX_TO_EXT(2), "rcl", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_RCR_RM1632_IMM8] = { false, 0xc1, IDX_TO_EXT(3), "rcr", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SHL_RM1632_IMM8] = { false, 0xc1, IDX_TO_EXT(4), "shl", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SHR_RM1632_IMM8] = { false, 0xc1, IDX_TO_EXT(5), "shr", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SAL_RM1632_IMM8] = { false, 0xc1, IDX_TO_EXT(6), "sal", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_SAR_RM1632_IMM8] = { false, 0xc1, IDX_TO_EXT(7), "sar", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_RET] = { false, 0xc3, IDX_TO_EXT(-1), "ret", XPX_NONE }, + + + [XOP_MOV_RM8_IMM8] = { false, 0xc6, IDX_TO_EXT(0), "mov", XPX_NONE }, + [XOP_MOV_RM1632_IMM1632] = { false, 0xc7, IDX_TO_EXT(0), "mov", XPX_OPERAND_SIZE_OVERRIDE }, + + + + [XOP_LEAVE] = { false, 0xc9, IDX_TO_EXT(-1), "leave", XPX_NONE }, + + + [XOP_INT_3] = { false, 0xcc, IDX_TO_EXT(-1), "int", XPX_NONE }, + [XOP_INT] = { false, 0xcd, IDX_TO_EXT(-1), "int", XPX_NONE }, + + + [XOP_SHL_RM1632_CL] = { false, 0xd3, IDX_TO_EXT(4), "shl", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_CALL_REL1632] = { false, 0xe8, IDX_TO_EXT(-1), "call", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JMP_REL1632] = { false, 0xe9, IDX_TO_EXT(-1), "jmp", XPX_OPERAND_SIZE_OVERRIDE }, + + [XOP_JMP_REL8] = { false, 0xeb, IDX_TO_EXT(-1), "jmp", XPX_NONE }, + + [XOP_HLT] = { false, 0xf4, IDX_TO_EXT(-1), "hlt", XPX_NONE }, + + [XOP_NOT_RM1632] = { false, 0xf7, IDX_TO_EXT(2), "not", XPX_OPERAND_SIZE_OVERRIDE }, + + + [XOP_CLD] = { false, 0xfc, IDX_TO_EXT(-1), "cld", XPX_NONE }, + + [XOP_CALL_RM1632] = { false, 0xff, IDX_TO_EXT(2), "call", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_JMP_RM1632] = { false, 0xff, IDX_TO_EXT(4), "jmp", XPX_OPERAND_SIZE_OVERRIDE }, + [XOP_PUSH_RM1632] = { false, 0xff, IDX_TO_EXT(6), "push", XPX_OPERAND_SIZE_OVERRIDE } + +}; + + + + + +/* Traduit une instruction en version humainement lisible. */ +static const char *x86_get_instruction_text(const GX86Instruction *, const exe_format *, AsmSyntax); + + + + + + +/* Indique le type défini pour une instruction d'architecture x86. */ +G_DEFINE_TYPE(GX86Instruction, g_x86_instruction, G_TYPE_ARCH_INSTRUCTION); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des instructions pour x86. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_x86_instruction_class_init(GX86InstructionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser. * +* * +* Description : Initialise une instance d'instruction d'architecture x86. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_x86_instruction_init(GX86Instruction *instr) +{ + GArchInstruction *parent; /* Instance parente */ + + parent = G_ARCH_INSTRUCTION(instr); + + parent->get_text = (get_instruction_text_fc)x86_get_instruction_text; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'instruction à représenter. * +* * +* Description : Crée une instruction pour l'architecture x86. * +* * +* Retour : Architecture mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_x86_instruction_new(X86Opcodes type) +{ + GArchInstruction *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_X86_INSTRUCTION, NULL); + + G_X86_INSTRUCTION(result)->type = type; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à venir compléter. * +* prefixes = listes des préfixes rencontrés. * +* * +* Description : Attache à une instructions ses préfixes associés. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_x86_instruction_set_prefixes(GX86Instruction *instr, X86Prefix prefixes) +{ + instr->prefixes = prefixes; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* AIDE A LA MISE EN PLACE D'INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. * +* len = taille totale des données à analyser. * +* prefix = éventuel(s) préfixe(s) remarqué(s). [OUT] * +* care = la lecture de l'instr. veut-elle les opcodes ? [OUT]* +* * +* Description : Recherche l'identifiant de la prochaine instruction. * +* * +* Retour : Identifiant de la prochaine instruction à tenter de charger. * +* * +* Remarques : - * +* * +******************************************************************************/ + +X86Opcodes x86_guess_next_instruction(const bin_t *data, off_t pos, off_t len, X86Prefix *prefix, bool *care) +{ + X86Opcodes result; /* Identifiant à retourner */ + X86Prefix extra; /* Préfixes n'intervenant pas */ + bin_t opcode; /* Opcode à trouver */ + + extra = XPX_NONE; + *prefix = XPX_NONE; + + while (pos < len) + switch (data[pos]) + { + case 0x66: + pos++; + *prefix |= XPX_OPERAND_SIZE_OVERRIDE; + break; + case 0xf2: + pos++; + extra |= XPX_REPEAT_STRING_OPERATION; + break; + default: + goto xgni_look_for; + break; + } + + xgni_look_for: + + if (pos == len) return XOP_COUNT; + + opcode = data[pos]; + + for (result = 0; result < XOP_COUNT; result++) + { + if ((_instructions[result].prefix & *prefix) != *prefix) continue; + + if (_instructions[result].opcode != opcode) continue; + + if (_instructions[result].op_extension != IDX_TO_EXT(-1)) + { + if ((pos + 1) == len) continue; + if (_instructions[result].op_extension != OPCODE_EXT(data[pos + 1])) continue; + } + + *prefix |= extra; + *care = _instructions[result].care_of_data; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit une instruction en version humainement lisible. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *x86_get_instruction_text(const GX86Instruction *instr, const exe_format *format, AsmSyntax syntax) +{ + const char *result; /* Chaîne à retourner */ + + result = strdup(_instructions[instr->type].keyword); + + if (instr->prefixes & XPX_REPEAT_STRING_OPERATION) + result = strprep(result, "repnz "); + + return result; + +} diff --git a/src/arch/x86/op_jump.c b/src/arch/x86/op_jump.c index 709ff24..be993f1 100644 --- a/src/arch/x86/op_jump.c +++ b/src/arch/x86/op_jump.c @@ -1,6 +1,6 @@ /* OpenIDA - Outil d'analyse de fichiers binaires - * op_jump.c - décodage des sauts conditionnels + * op_jump.c - décodage des sauts inconditionnels * * Copyright (C) 2008 Cyrille Bagard * diff --git a/src/arch/x86/op_scas.c b/src/arch/x86/op_scas.c new file mode 100644 index 0000000..2ec8230 --- /dev/null +++ b/src/arch/x86/op_scas.c @@ -0,0 +1,63 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * op_scas.c - décodage des recherches dans des chaînes ASCII + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include + + +#include "../instruction-int.h" +#include "opcodes.h" +#include "operand.h" + + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. [OUT] * +* len = taille totale des données à analyser. * +* addr = adresse virtuelle de l'instruction. * +* proc = architecture ciblée par le désassemblage. * +* * +* Description : Décode une instruction de type 'scas al, ...' (8 bits). * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *x86_read_instr_scas_al_m8(const bin_t *data, off_t *pos, off_t len, vmpa_t addr, X86Prefix prefix, const GX86Processor *proc) +{ + GArchInstruction *result; /* Instruction à retourner */ + + result = g_x86_instruction_new(XOP_SCAS_AL_M8); + + if (!x86_read_two_operands(result, data, pos, len, X86_OTP_AL, X86_OTP_AL/*FIXME*/)) + { + /* TODO free(result);*/ + return NULL; + } + + return result; + +} diff --git a/src/arch/x86/operand.c b/src/arch/x86/operand.c index e916541..5e01fd7 100644 --- a/src/arch/x86/operand.c +++ b/src/arch/x86/operand.c @@ -40,7 +40,7 @@ /* ---------------------- COQUILLE VIDE POUR LES OPERANDES X86 ---------------------- */ -/* Définition d'un opérande de la x86 (instance) */ +/* Définition d'un opérande de x86 (instance) */ struct _GX86Operand { GArchOperand parent; /* Instance parente */ @@ -48,7 +48,7 @@ struct _GX86Operand }; -/* Définition d'un opérande de la x86 (classe) */ +/* Définition d'un opérande de x86 (classe) */ struct _GX86OperandClass { GArchOperandClass parent; /* Classe parente */ @@ -59,7 +59,7 @@ struct _GX86OperandClass /* Initialise la classe des opérandes x86 de base. */ static void g_x86_operand_class_init(GX86OperandClass *); -/* Initialise une instance d'opérande de base pour la x86. */ +/* Initialise une instance d'opérande de base pour x86. */ static void g_x86_operand_init(GX86Operand *); @@ -224,7 +224,7 @@ static void g_x86_operand_class_init(GX86OperandClass *klass) * * * Paramètres : operand = instance à initialiser. * * * -* Description : Initialise une instance d'opérande de registre x86. * +* Description : Initialise une instance d'opérande de base pour x86. * * * * Retour : - * * * @@ -297,7 +297,7 @@ static void g_x86_register_operand_init(GX86RegisterOperand *operand) * size = taille de l'opérande, et donc du registre. * * base = indice du premier registre. * * * -* Description : Crée un opérande visant un registre X86. * +* Description : Crée un opérande visant un registre x86. * * * * Retour : Opérande mis en place. * * * @@ -336,7 +336,7 @@ GArchOperand *g_x86_register_operand_new_from_opcode(const bin_t *data, off_t *p * size = taille de l'opérande, et donc du registre. * * first = indique la partie du ModR/M à traiter. * * * -* Description : Crée un opérande visant un registre X86. * +* Description : Crée un opérande visant un registre x86. * * * * Retour : Opérande mis en place. * * * @@ -376,7 +376,7 @@ GArchOperand *g_x86_register_operand_new_from_mod_rm(const bin_t *data, off_t *p * Paramètres : index = indice du registre visé. * * size = taille de l'opérande, et donc du registre. * * * -* Description : Crée un opérande visant un registre X86 donnée. * +* Description : Crée un opérande visant un registre x86 donné. * * * * Retour : Opérande mis en place. * * * diff --git a/src/arch/x86/operand.h b/src/arch/x86/operand.h index ebab200..1139fe2 100644 --- a/src/arch/x86/operand.h +++ b/src/arch/x86/operand.h @@ -41,10 +41,10 @@ #define G_X86_OPERAND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_x86_operand_get_type(), GX86OperandIface)) -/* Définition d'un opérande de la x86 (instance) */ +/* Définition d'un opérande de x86 (instance) */ typedef struct _GX86Operand GX86Operand; -/* Définition d'un opérande de la x86 (classe) */ +/* Définition d'un opérande de x86 (classe) */ typedef struct _GX86OperandClass GX86OperandClass; @@ -72,13 +72,13 @@ typedef struct _GX86RegisterOperandClass GX86RegisterOperandClass; /* Indique le type défini par la GLib pour un opérande de registre x86. */ GType g_x86_register_operand_get_type(void); -/* Crée un opérande visant un registre X86. */ +/* Crée un opérande visant un registre x86. */ GArchOperand *g_x86_register_operand_new_from_opcode(const bin_t *, off_t *, off_t, AsmOperandSize, bin_t); -/* Crée un opérande visant un registre X86. */ +/* Crée un opérande visant un registre x86. */ GArchOperand *g_x86_register_operand_new_from_mod_rm(const bin_t *, off_t *, off_t, AsmOperandSize, bool); -/* Crée un opérande visant un registre X86 donnée. */ +/* Crée un opérande visant un registre x86 donné. */ GArchOperand *g_x86_register_operand_new_from_index(bin_t, AsmOperandSize); diff --git a/src/arch/x86/registers.c b/src/arch/x86/registers.c new file mode 100644 index 0000000..802e2f6 --- /dev/null +++ b/src/arch/x86/registers.c @@ -0,0 +1,530 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * registers.c - aides auxiliaires relatives aux registres x86 + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#include "registers.h" + + +#include +#include + + + +/* Liste des registres 8 bits */ +typedef enum _X868bRegister +{ + X86_REG8_AL = 0, /* Registre AL */ + X86_REG8_CL = 1, /* Registre AL */ + X86_REG8_DL = 2, /* Registre AL */ + X86_REG8_BL = 3, /* Registre AL */ + X86_REG8_AH = 4, /* Registre AH */ + X86_REG8_CH = 5, /* Registre AH */ + X86_REG8_DH = 6, /* Registre AH */ + X86_REG8_BH = 7, /* Registre AH */ + + X86_REG8_NONE /* Aucun registre */ + +} X868bRegister; + +/* Liste des registres 16 bits */ +typedef enum _X8616bRegister +{ + X86_REG16_AX = 0, /* Registre AX */ + X86_REG16_CX = 1, /* Registre AX */ + X86_REG16_DX = 2, /* Registre AX */ + X86_REG16_BX = 3, /* Registre AX */ + X86_REG16_SP = 4, /* Registre SP */ + X86_REG16_BP = 5, /* Registre BP */ + X86_REG16_SI = 6, /* Registre SI */ + X86_REG16_DI = 7, /* Registre DI */ + + X86_REG16_NONE /* Aucun registre */ + +} X8616bRegister; + +/* Liste des registres 32 bits */ +typedef enum _X8632bRegister +{ + X86_REG32_EAX = 0, /* Registre EAX */ + X86_REG32_ECX = 1, /* Registre EAX */ + X86_REG32_EDX = 2, /* Registre EAX */ + X86_REG32_EBX = 3, /* Registre EAX */ + X86_REG32_ESP = 4, /* Registre ESP */ + X86_REG32_EBP = 5, /* Registre EBP */ + X86_REG32_ESI = 6, /* Registre ESI */ + X86_REG32_EDI = 7, /* Registre EDI */ + + X86_REG32_NONE /* Aucun registre */ + +} X8632bRegister; + + +/* Registre x86 */ +struct _x86_register +{ + union + { + X868bRegister reg8; /* Registre 8 bits */ + X8616bRegister reg16; /* Registre 16 bits */ + X8632bRegister reg32; /* Registre 32 bits */ + + } reg; + + AsmOperandSize size; /* Taille de ce registre */ + +}; + + + +/****************************************************************************** +* * +* Paramètres : size = indique la taille du registre. * +* value = valeur correspondant au registre. * +* * +* Description : Récupère l'indentifiant interne d'un registre. * +* * +* Retour : Registre définit ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +x86_register *get_x86_register(AsmOperandSize size, bin_t value) +{ + x86_register *result; /* Représentation à renvoyer */ + + result = (x86_register *)calloc(1, sizeof(x86_register)); + + result->size = size; + + switch (size) + { + case AOS_8_BITS: + switch (value) + { + case 0 ... 7: + result->reg.reg8 = (X868bRegister)value; + break; + default: + goto gxr_error; + break; + } + break; + + case AOS_16_BITS: + switch (value) + { + case 0 ... 7: + result->reg.reg16 = (X8616bRegister)value; + break; + default: + goto gxr_error; + break; + } + break; + + case AOS_32_BITS: + switch (value) + { + case 0 ... 7: + result->reg.reg32 = (X8632bRegister)value; + break; + default: + goto gxr_error; + break; + } + break; + + default: + goto gxr_error; + break; + + } + + return result; + + gxr_error: + + free(result); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à supprimer. * +* * +* Description : Efface de la mémoire l'indentifiant interne d'un registre. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void free_x86_register(x86_register *reg) +{ + free(reg); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à consulter. * +* * +* Description : Indique si le registre correspond à ebp ou similaire. * +* * +* Retour : true si la correspondance est avérée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool is_x86_register_base_pointer(const x86_register *reg) +{ + bool result; /* Bilan à remonter */ + + switch (reg->size) + { + case AOS_8_BITS_UNSIGNED: + case AOS_8_BITS_SIGNED: + result = (reg->reg.reg8 == X86_REG8_CH); + break; + case AOS_16_BITS_UNSIGNED: + case AOS_16_BITS_SIGNED: + result = (reg->reg.reg16 == X86_REG16_BP); + break; + case AOS_32_BITS_UNSIGNED: + case AOS_32_BITS_SIGNED: + result = (reg->reg.reg32 == X86_REG32_EBP); + break; + /* + case AOS_64_BITS_UNSIGNED: + case AOS_64_BITS_SIGNED: + result = (reg->reg.reg8 == X86_REG8_CH); + break; + */ + default: + result = false; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à consulter. * +* * +* Description : Indique si le registre correspond à esp ou similaire. * +* * +* Retour : true si la correspondance est avérée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool is_x86_register_stack_pointer(const x86_register *reg) +{ + bool result; /* Bilan à remonter */ + + switch (reg->size) + { + case AOS_8_BITS_UNSIGNED: + case AOS_8_BITS_SIGNED: + result = (reg->reg.reg8 == X86_REG8_AH); + break; + case AOS_16_BITS_UNSIGNED: + case AOS_16_BITS_SIGNED: + result = (reg->reg.reg16 == X86_REG16_SP); + break; + case AOS_32_BITS_UNSIGNED: + case AOS_32_BITS_SIGNED: + result = (reg->reg.reg32 == X86_REG32_ESP); + break; + /* + case AOS_64_BITS_UNSIGNED: + case AOS_64_BITS_SIGNED: + result = (reg->reg.reg8 == X86_REG8_CH); + break; + */ + default: + result = false; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à imprimer. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un registre x86 en texte. * +* * +* Retour : Traduction en chaîne à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *x86_register_as_text(const x86_register *reg, AsmSyntax syntax) +{ + char *result; /* Chaîne à renvoyer */ + + result = (char *)calloc(5, sizeof(char)); + + switch (syntax) + { + case ASX_INTEL: + switch (reg->size) + { + case AOS_8_BITS: + switch (reg->reg.reg8) + { + case X86_REG8_AL: + snprintf(result, 5, "al"); + break; + case X86_REG8_CL: + snprintf(result, 5, "cl"); + break; + case X86_REG8_DL: + snprintf(result, 5, "dl"); + break; + case X86_REG8_BL: + snprintf(result, 5, "bl"); + break; + case X86_REG8_AH: + snprintf(result, 5, "ah"); + break; + case X86_REG8_CH: + snprintf(result, 5, "ch"); + break; + case X86_REG8_DH: + snprintf(result, 5, "dh"); + break; + case X86_REG8_BH: + snprintf(result, 5, "bh"); + break; + case X86_REG8_NONE: + /* Ne devrait jamais arriver */ + break; + } + break; + + case AOS_16_BITS: + switch (reg->reg.reg16) + { + case X86_REG16_AX: + snprintf(result, 5, "ax"); + break; + case X86_REG16_CX: + snprintf(result, 5, "cx"); + break; + case X86_REG16_DX: + snprintf(result, 5, "dx"); + break; + case X86_REG16_BX: + snprintf(result, 5, "bx"); + break; + case X86_REG16_SP: + snprintf(result, 5, "sp"); + break; + case X86_REG16_BP: + snprintf(result, 5, "bp"); + break; + case X86_REG16_SI: + snprintf(result, 5, "si"); + break; + case X86_REG16_DI: + snprintf(result, 5, "di"); + break; + case X86_REG16_NONE: + /* Ne devrait jamais arriver */ + break; + } + break; + + case AOS_32_BITS: + switch (reg->reg.reg32) + { + case X86_REG32_EAX: + snprintf(result, 5, "eax"); + break; + case X86_REG32_ECX: + snprintf(result, 5, "ecx"); + break; + case X86_REG32_EDX: + snprintf(result, 5, "edx"); + break; + case X86_REG32_EBX: + snprintf(result, 5, "ebx"); + break; + case X86_REG32_ESP: + snprintf(result, 5, "esp"); + break; + case X86_REG32_EBP: + snprintf(result, 5, "ebp"); + break; + case X86_REG32_ESI: + snprintf(result, 5, "esi"); + break; + case X86_REG32_EDI: + snprintf(result, 5, "edi"); + break; + case X86_REG32_NONE: + printf("null reg\n"); + /* Ne devrait jamais arriver */ + break; + } + break; + + default: + break; + + } + break; + + case ASX_ATT: + switch (reg->size) + { + case AOS_8_BITS: + switch (reg->reg.reg8) + { + case X86_REG8_AL: + snprintf(result, 5, "%%al"); + break; + case X86_REG8_CL: + snprintf(result, 5, "%%cl"); + break; + case X86_REG8_DL: + snprintf(result, 5, "%%dl"); + break; + case X86_REG8_BL: + snprintf(result, 5, "%%bl"); + break; + case X86_REG8_AH: + snprintf(result, 5, "%%ah"); + break; + case X86_REG8_CH: + snprintf(result, 5, "%%ch"); + break; + case X86_REG8_DH: + snprintf(result, 5, "%%dh"); + break; + case X86_REG8_BH: + snprintf(result, 5, "%%bh"); + break; + case X86_REG8_NONE: + /* Ne devrait jamais arriver */ + break; + } + break; + + case AOS_16_BITS: + switch (reg->reg.reg16) + { + case X86_REG16_AX: + snprintf(result, 5, "%%ax"); + break; + case X86_REG16_CX: + snprintf(result, 5, "%%cx"); + break; + case X86_REG16_DX: + snprintf(result, 5, "%%dx"); + break; + case X86_REG16_BX: + snprintf(result, 5, "%%bx"); + break; + case X86_REG16_SP: + snprintf(result, 5, "%%sp"); + break; + case X86_REG16_BP: + snprintf(result, 5, "%%bp"); + break; + case X86_REG16_SI: + snprintf(result, 5, "%%si"); + break; + case X86_REG16_DI: + snprintf(result, 5, "%%di"); + break; + case X86_REG16_NONE: + /* Ne devrait jamais arriver */ + break; + } + break; + + case AOS_32_BITS: + switch (reg->reg.reg32) + { + case X86_REG32_EAX: + snprintf(result, 5, "%%eax"); + break; + case X86_REG32_ECX: + snprintf(result, 5, "%%ecx"); + break; + case X86_REG32_EDX: + snprintf(result, 5, "%%edx"); + break; + case X86_REG32_EBX: + snprintf(result, 5, "%%ebx"); + break; + case X86_REG32_ESP: + snprintf(result, 5, "%%esp"); + break; + case X86_REG32_EBP: + snprintf(result, 5, "%%ebp"); + break; + case X86_REG32_ESI: + snprintf(result, 5, "%%esi"); + break; + case X86_REG32_EDI: + snprintf(result, 5, "%%edi"); + break; + case X86_REG32_NONE: + /* Ne devrait jamais arriver */ + break; + } + break; + + default: + break; + + } + break; + + default: + break; + + } + + return result; + +} diff --git a/src/arch/x86/registers.h b/src/arch/x86/registers.h new file mode 100644 index 0000000..491d5bc --- /dev/null +++ b/src/arch/x86/registers.h @@ -0,0 +1,54 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * registers.h - prototypes pour les aides auxiliaires relatives aux registres x86 + * + * Copyright (C) 2009 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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 3 of the License, or + * (at your option) any later version. + * + * OpenIDA 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 Foobar. If not, see . + */ + + +#ifndef _ARCH_X86_REGISTERS_H +#define _ARCH_X86_REGISTERS_H + + +#include "../archbase.h" +#include "../operand.h" + + + +/* Registre x86 */ +typedef struct _x86_register x86_register; + + +/* Récupère l'indentifiant interne d'un registre. */ +x86_register *get_x86_register(AsmOperandSize, bin_t); + +/* Efface de la mémoire l'indentifiant interne d'un registre. */ +void free_x86_register(x86_register *); + +/* Indique si le registre correspond à ebp ou similaire. */ +bool is_x86_register_base_pointer(const x86_register *); + +/* Indique si le registre correspond à esp ou similaire. */ +bool is_x86_register_stack_pointer(const x86_register *); + +/* Traduit un registre x86 en texte. */ +char *x86_register_as_text(const x86_register *, AsmSyntax); + + + +#endif /* _ARCH_X86_REGISTERS_H */ diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c index dac0cd7..b5e3406 100644 --- a/src/format/elf/e_elf.c +++ b/src/format/elf/e_elf.c @@ -242,7 +242,25 @@ elf_format *load_elf(const uint8_t *content, off_t length) FormatTargetMachine get_elf_target_machine(const elf_format *format) { - return FTM_386; + FormatTargetMachine result; /* Identifiant à retourner */ + + switch (format->header.e_machine) + { + case EM_MIPS: + result = FTM_MIPS; + break; + + case EM_386: + result = FTM_386; + break; + + default: + /* FIXME */ + break; + + } + + return result; } diff --git a/src/format/exe_format.c b/src/format/exe_format.c index aeeaea3..5ddb934 100644 --- a/src/format/exe_format.c +++ b/src/format/exe_format.c @@ -360,7 +360,25 @@ const uint8_t *get_exe_content(const exe_format *format, off_t *length) FormatTargetMachine get_exe_target_machine(const exe_format *format) { - return format->get_target_machine(format); + FormatTargetMachine result; /* Type à retourner */ + + result = format->get_target_machine(format); + + switch (result) + { + case FTM_JVM: + log_simple_message(LMT_INFO, _("Detected architecture: Java Virtual Machine")); + break; + case FTM_MIPS: + log_simple_message(LMT_INFO, _("Detected architecture: Microprocessor without Interlocked Pipeline Stages")); + break; + case FTM_386: + log_simple_message(LMT_INFO, _("Detected architecture: X386")); + break; + + } + + return result; } diff --git a/src/format/exe_format.h b/src/format/exe_format.h index 2c10d65..de9f025 100644 --- a/src/format/exe_format.h +++ b/src/format/exe_format.h @@ -92,8 +92,9 @@ exe_format *load_new_exe_format(const uint8_t *, off_t); /* Architectures de destination des formats */ typedef enum _FormatTargetMachine { - FTM_386, /* Intel 80386 */ FTM_JVM, /* Java Virtual Machine */ + FTM_MIPS, /* Mips 32 ou 64 bits */ + FTM_386, /* Intel 80386 */ FTM_COUNT -- cgit v0.11.2-87-g4458