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/mips/operand.c | |
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/mips/operand.c')
-rw-r--r-- | src/arch/mips/operand.c | 649 |
1 files changed, 649 insertions, 0 deletions
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; + +} |