/* Chrysalide - Outil d'analyse de fichiers binaires * processor.c - gestion 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 "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 *); /* Supprime toutes les références externes. */ static void g_mips_processor_dispose(GMipsProcessor *); /* Procède à la libération totale de la mémoire. */ static void g_mips_processor_finalize(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) { GObjectClass *object; /* Autre version de la classe */ GArchProcessorClass *proc; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_mips_processor_dispose; object->finalize = (GObjectFinalizeFunc)g_mips_processor_finalize; proc = G_ARCH_PROCESSOR_CLASS(klass); proc->decode = (decode_instruction_fc)g_mips_processor_decode_instruction; } /****************************************************************************** * * * 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->memsize = MDS_32_BITS; } /****************************************************************************** * * * Paramètres : proc = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_mips_processor_dispose(GMipsProcessor *proc) { G_OBJECT_CLASS(g_mips_processor_parent_class)->dispose(G_OBJECT(proc)); } /****************************************************************************** * * * Paramètres : bookmark = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_mips_processor_finalize(GMipsProcessor *proc) { G_OBJECT_CLASS(g_mips_processor_parent_class)->finalize(G_OBJECT(proc)); } /****************************************************************************** * * * 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; }