/* Chrysalide - Outil d'analyse de fichiers binaires * instruction.c - gestion des instructions 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 "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 GExeFormat *, 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 GExeFormat *format, AsmSyntax syntax) { const char *result; /* Chaîne à retourner */ result = strdup(_instructions[instr->type].keyword); return result; }