/* Chrysalide - Outil d'analyse de fichiers binaires * operand.h - prototypes pour la gestion des operandes de l'architecture MIPS * * Copyright (C) 2009-2017 Cyrille Bagard * * This file is part of Chrysalide. * * Chrysalide 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. * * Chrysalide is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "operand.h" #include #include "../immediate.h" #include "../operand-int.h" #include "../../common/endianness.h" #include "../../common/extstr.h" /* ------------------------ COQUILLE VIDE POUR OPERANDE MIPS ------------------------ */ /* Définition d'un opérande de la MIPS (instance) */ struct _GMipsOperand { GArchOperand parent; /* Instance parente */ }; /* Définition d'un opérande de la MIPS (classe) */ struct _GMipsOperandClass { GArchOperandClass parent; /* Classe parente */ }; /* Initialise la classe des opérandes MIPS de base. */ static void g_mips_operand_class_init(GMipsOperandClass *); /* Initialise une instance d'opérande de base pour MIPS. */ static void g_mips_operand_init(GMipsOperand *); /* ----------------------- OPERANDES OFFRANT UN REGISTRE MIPS ----------------------- */ /* Définition d'un opérande visant un registre MIPS (instance) */ struct _GMipsRegisterOperand { GMipsOperand parent; /* Instance parente */ mips_register *reg; /* Registre représenté */ }; /* Définition d'un opérande visant un registre MIPS (classe) */ struct _GMipsRegisterOperandClass { GMipsOperandClass parent; /* Classe parente */ }; /* Initialise la classe des opérandes de registre MIPS. */ static void g_mips_register_operand_class_init(GMipsRegisterOperandClass *); /* Initialise une instance d'opérande de registre MIPS. */ static void g_mips_register_operand_init(GMipsRegisterOperand *); /* -------------------------- 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 *); /* ----------------------------- 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 *); /* ---------------------------------------------------------------------------------- */ /* 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) { } /****************************************************************************** * * * 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); } #if 0 /****************************************************************************** * * * 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 GExeFormat *format, AsmSyntax syntax) { char *result; /* Chaîne à retourner */ result = mips_register_as_text(operand->reg, syntax); return result; } #endif /****************************************************************************** * * * 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) { } /****************************************************************************** * * * 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(MDS_16_BITS_SIGNED, offset); } else result = NULL; return G_ARCH_OPERAND(result); } #if 0 /****************************************************************************** * * * 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 GExeFormat *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, "+"); /* FIXME ! tmp = g_arch_operand_get_text(G_ARCH_OPERAND(operand->offset), format, syntax); result = stradd(result, tmp); free(tmp); */ result = stradd(result, "]"); return result; } #endif /* ---------------------------------------------------------------------------------- */ /* 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) { } /****************************************************************************** * * * 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(MDS_16_BITS_SIGNED, offset); return G_ARCH_OPERAND(result); } #if 0 /****************************************************************************** * * * 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 GExeFormat *format, AsmSyntax syntax) { return strdup("");/* FIXME g_arch_operand_get_text(G_ARCH_OPERAND(operand->offset), format, syntax); */ } #endif /* ---------------------------------------------------------------------------------- */ /* 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(MDS_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(MDS_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; }