diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2009-05-31 20:58:20 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2009-05-31 20:58:20 (GMT) | 
| commit | 8724afdc73e0ddad86f46de1a3fbe0254575a76e (patch) | |
| tree | de666b66e154c6c6453807d3fa4272efb6877a91 /src/arch | |
| parent | 0b7d7f26c745ff0f52e9e483a0980351368ca824 (diff) | |
Supported a new architecture (MIPS).
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@67 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/arch')
32 files changed, 4061 insertions, 23 deletions
| 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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include "operand.h" + + +#include <stdarg.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_MIPS_OPERAND_H +#define _ARCH_MIPS_OPERAND_H + + +#include <stdbool.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include "registers.h" + + +#include <malloc.h> +#include <stdio.h> + + + +/* 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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include <malloc.h> + + +#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 <http://www.gnu.org/licenses/>. + */ + + +#include "registers.h" + + +#include <malloc.h> +#include <stdio.h> + + + +/* 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 <http://www.gnu.org/licenses/>. + */ + + +#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 */ | 
