/* OpenIDA - Outil d'analyse de fichiers binaires * processor.c - gestion générique des architectures * * Copyright (C) 2008-2012 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 . */ #include "processor.h" #include "instruction-int.h" #include "processor-int.h" #include "artificial.h" #include "arm/processor.h" #include "dalvik/processor.h" #include "jvm/processor.h" #include "mips/processor.h" #include "x86/processor.h" /* Initialise la classe générique des processeurs. */ static void g_arch_processor_class_init(GArchProcessorClass *); /* Initialise une instance de processeur d'architecture. */ static void g_arch_processor_init(GArchProcessor *); /* ------------------------ ARCHITECTURES DANS LEUR ENSEMBLE ------------------------ */ static GArchProcessor *_processors_list[APT_COUNT]; /* Indique le type défini pour un processeur d'architecture. */ G_DEFINE_TYPE(GArchProcessor, g_arch_processor, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe générique des processeurs. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_arch_processor_class_init(GArchProcessorClass *klass) { } /****************************************************************************** * * * Paramètres : proc = instance à initialiser. * * * * Description : Initialise une instance de processeur d'architecture. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_arch_processor_init(GArchProcessor *proc) { } /****************************************************************************** * * * Paramètres : proc = architecture visée par la procédure. * * * * Description : Fournit un contexte propre au processeur d'une architecture. * * * * Retour : Nouveau contexte mis à disposition. * * * * Remarques : - * * * ******************************************************************************/ GProcContext *g_arch_processor_get_context(const GArchProcessor *proc) { GProcContext *result; /* Contexte à retourner */ if (proc->get_ctx != NULL) result = proc->get_ctx(proc); else result = NULL; return result; } /****************************************************************************** * * * Paramètres : proc = architecture visée par la procédure. * * * * Description : Fournit un contexte lié au processeur pour une décompilation.* * * * Retour : Nouveau contexte mis à disposition. * * * * Remarques : - * * * ******************************************************************************/ GDecContext *g_arch_processor_get_decomp_context(const GArchProcessor *proc) { GDecContext *result; /* Contexte à retourner */ if (proc->get_dec_ctx != NULL) result = proc->get_dec_ctx(proc); else result = NULL; return result; } /****************************************************************************** * * * Paramètres : proc = processeur d'architecture à consulter. * * * * Description : Fournit le boustime du processeur d'une architecture. * * * * Retour : Boutisme associé au processeur. * * * * Remarques : - * * * ******************************************************************************/ SourceEndian g_arch_processor_get_endianness(const GArchProcessor *proc) { return proc->endianness; } /****************************************************************************** * * * Paramètres : proc = processeur d'architecture à consulter. * * * * Description : Fournit la taille de l'espace mémoire d'une architecture. * * * * Retour : Taille de l'espace mémoire. * * * * Remarques : - * * * ******************************************************************************/ MemoryDataSize g_arch_processor_get_memory_size(const GArchProcessor *proc) { return proc->memsize; } /****************************************************************************** * * * Paramètres : proc = processeur d'architecture à consulter. * * * * Description : Fournit la taille min. des instructions d'une architecture. * * * * Retour : Taille d'encodage des instructions * * * * Remarques : - * * * ******************************************************************************/ MemoryDataSize g_arch_processor_get_instruction_size(const GArchProcessor *proc) { return proc->inssize; } /****************************************************************************** * * * Paramètres : proc = architecture visée par la procédure. * * ctx = contexte lié à l'exécution du processeur. * * data = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * len = taille totale des données à analyser. * * base = position physique du bloc de code courant. * * addr = adresse virtuelle de l'instruction. * * format = format du fichier contenant le code. * * * * Description : Décode une instruction dans un flux de données. * * * * Retour : Instruction mise en place. * * * * Remarques : - * * * ******************************************************************************/ GArchInstruction *g_arch_processor_decode_instruction(const GArchProcessor *proc, GProcContext *ctx, const bin_t *data, off_t *pos, off_t len, off_t base, vmpa_t addr, GBinFormat *format) { GArchInstruction *result; /* Instruction à renvoyer */ off_t old_pos; /* Sauvegarde de la position */ bool skipped; /* Données prise en compte ? */ old_pos = *pos; result = proc->decode(proc, ctx, data, pos, len, addr, format); if (result == NULL || result == SKIPPED_INSTR) { //printf("BAD CODE :: 0x%02hhx @0x%08lx\n", data[*pos], addr); skipped = (result == SKIPPED_INSTR); *pos = old_pos; result = g_db_instruction_new_from_data(data, pos, len, base, proc); #ifdef DEBUG /* FIXME */ if (skipped) g_db_instruction_mark_as_skipped(G_DB_INSTRUCTION(result)); #endif } g_arch_instruction_set_location(result, base + old_pos, *pos - old_pos, addr); return result; } /* ---------------------------------------------------------------------------------- */ /* ARCHITECTURES DANS LEUR ENSEMBLE */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : - * * * * Description : Procède au chargement des différentes architectures. * * * * Retour : Toujours true. * * * * Remarques : - * * * ******************************************************************************/ bool init_all_processors(void) { _processors_list[APT_ARM] = g_arm_processor_new(); _processors_list[APT_DALVIK] = g_dalvik_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; } /****************************************************************************** * * * Paramètres : type = sorte de processeur recherché. * * * * Description : Fournit le processeur d'architecture correspondant à un type.* * * * Retour : Processeur d'architecture trouvé. * * * * Remarques : - * * * ******************************************************************************/ GArchProcessor *get_arch_processor_for_type(ArchProcessorType type) { return _processors_list[type]; } /****************************************************************************** * * * Paramètres : format = exécutable d'origine. * * * * Description : Fournit le processeur d'architecture lié à un format. * * * * Retour : Processeur d'architecture trouvé. * * * * Remarques : - * * * ******************************************************************************/ GArchProcessor *get_arch_processor_from_format(const GExeFormat *format) { GArchProcessor *result; /* Conversion à retourner */ switch (g_exe_format_get_target_machine(format)) { case FTM_ARM: result = get_arch_processor_for_type(APT_ARM); break; case FTM_DALVIK: result = get_arch_processor_for_type(APT_DALVIK); break; case FTM_JVM: result = get_arch_processor_for_type(APT_JVM); break; case FTM_MIPS: result = get_arch_processor_for_type(APT_MIPS); break; case FTM_386: result = get_arch_processor_for_type(APT_386); break; default: result = NULL; break; } return result; }