diff options
46 files changed, 3611 insertions, 1443 deletions
diff --git a/configure.ac b/configure.ac index 5c3c0e8..f1ac211 100644 --- a/configure.ac +++ b/configure.ac @@ -328,6 +328,7 @@ AC_CONFIG_FILES([Makefile plugins/arm/v7/opdefs/Makefile plugins/arm/v7/opcodes/Makefile plugins/arm/v7/operands/Makefile + plugins/arm/v7/registers/Makefile plugins/dalvik/Makefile plugins/dalvik/operands/Makefile plugins/dalvik/pseudo/Makefile @@ -378,6 +379,7 @@ AC_CONFIG_FILES([Makefile src/analysis/human/asm/Makefile src/analysis/types/Makefile src/arch/Makefile + src/arch/operands/Makefile src/common/Makefile src/core/Makefile src/debug/Makefile diff --git a/plugins/arm/register-int.h b/plugins/arm/register-int.h index 616750f..e4b834a 100644 --- a/plugins/arm/register-int.h +++ b/plugins/arm/register-int.h @@ -25,7 +25,6 @@ #define _PLUGINS_ARM_REGISTER_INT_H - #include <arch/register-int.h> @@ -33,9 +32,6 @@ -#define MAX_REGNAME_LEN 8 - - /* Représentation d'un registre ARM (instance) */ struct _GArmRegister { diff --git a/plugins/arm/register.c b/plugins/arm/register.c index 0ae7072..3e1251b 100644 --- a/plugins/arm/register.c +++ b/plugins/arm/register.c @@ -31,6 +31,9 @@ +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + /* Initialise la classe des registres ARM. */ static void g_arm_register_class_init(GArmRegisterClass *); @@ -51,6 +54,22 @@ static int g_arm_register_compare(const GArmRegister *, const GArmRegister *); +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ + + +/* Charge un registre depuis une mémoire tampon. */ +static GArchRegister *g_arm_register_unserialize(GArmRegister *, GAsmStorage *, packed_buffer *); + +/* Sauvegarde un registre dans une mémoire tampon. */ +static bool g_arm_register_serialize(const GArmRegister *, GAsmStorage *, packed_buffer *); + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION UNITAIRE DES REGISTRES */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini pour une représentation d'un registre ARM. */ G_DEFINE_TYPE(GArmRegister, g_arm_register, G_TYPE_ARCH_REGISTER); @@ -70,16 +89,19 @@ G_DEFINE_TYPE(GArmRegister, g_arm_register, G_TYPE_ARCH_REGISTER); static void g_arm_register_class_init(GArmRegisterClass *klass) { GObjectClass *object_class; /* Autre version de la classe */ - GArchRegisterClass *register_class; /* Classe de haut niveau */ + GArchRegisterClass *reg_class; /* Classe de haut niveau */ object_class = G_OBJECT_CLASS(klass); - register_class = G_ARCH_REGISTER_CLASS(klass); object_class->dispose = (GObjectFinalizeFunc/* ! */)g_arm_register_dispose; object_class->finalize = (GObjectFinalizeFunc)g_arm_register_finalize; - register_class->hash = (reg_hash_fc)g_arm_register_hash; - register_class->compare = (reg_compare_fc)g_arm_register_compare; + reg_class = G_ARCH_REGISTER_CLASS(klass); + + reg_class->hash = (reg_hash_fc)g_arm_register_hash; + reg_class->compare = (reg_compare_fc)g_arm_register_compare; + reg_class->unserialize = (reg_unserialize_fc)g_arm_register_unserialize; + reg_class->serialize = (reg_serialize_fc)g_arm_register_serialize; } @@ -200,3 +222,81 @@ static int g_arm_register_compare(const GArmRegister *a, const GArmRegister *b) return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un registre depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *g_arm_register_unserialize(GArmRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + GArchRegister *result; /* Instance à retourner */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + /** + * L'indice de registre est utilisé par les sous-classes pour la regénération + * à partir du cache. + * + * Il est donc lu depuis le tempon avant l'appel à cette fonction, et est + * ainsi déjà pris en compte. + */ + + result = G_ARCH_REGISTER(reg); + + parent = G_ARCH_REGISTER_CLASS(g_arm_register_parent_class); + + result = parent->unserialize(result, storage, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un registre dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arm_register_serialize(const GArmRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + result = extend_packed_buffer(pbuf, ®->index, sizeof(uint8_t), false); + + if (result) + { + parent = G_ARCH_REGISTER_CLASS(g_arm_register_parent_class); + + result = parent->serialize(G_ARCH_REGISTER(reg), storage, pbuf); + + } + + return result; + +} diff --git a/plugins/arm/register.h b/plugins/arm/register.h index 0beb653..8def8fd 100644 --- a/plugins/arm/register.h +++ b/plugins/arm/register.h @@ -30,12 +30,15 @@ -#define G_TYPE_ARM_REGISTER g_arm_register_get_type() -#define G_ARM_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arm_register_get_type(), GArmRegister)) -#define G_IS_ARM_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arm_register_get_type())) -#define G_ARM_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARM_REGISTER, GArmRegisterClass)) -#define G_IS_ARM_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARM_REGISTER)) -#define G_ARM_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARM_REGISTER, GArmRegisterClass)) +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +#define G_TYPE_ARM_REGISTER g_arm_register_get_type() +#define G_ARM_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARM_REGISTER, GArmRegister)) +#define G_IS_ARM_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARM_REGISTER)) +#define G_ARM_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARM_REGISTER, GArmRegisterClass)) +#define G_IS_ARM_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARM_REGISTER)) +#define G_ARM_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARM_REGISTER, GArmRegisterClass)) /* Représentation d'un registre ARM (instance) */ diff --git a/plugins/arm/v7/Makefile.am b/plugins/arm/v7/Makefile.am index 1ce4b01..5c98f7c 100644 --- a/plugins/arm/v7/Makefile.am +++ b/plugins/arm/v7/Makefile.am @@ -5,7 +5,6 @@ libarmv7_la_SOURCES = \ arm.h arm.c \ context.h context.c \ core.h core.c \ - cregister.h cregister.c \ fetch.h fetch.c \ helpers.h \ instruction.h instruction.c \ @@ -13,6 +12,7 @@ libarmv7_la_SOURCES = \ post.h post.c \ processor.h processor.c \ pseudo.h pseudo.c \ + register-int.h \ register.h register.c \ simd.h simd.c \ thumb_16.h thumb_16.c \ @@ -20,7 +20,8 @@ libarmv7_la_SOURCES = \ libarmv7_la_LIBADD = \ opcodes/libarmv7opcodes.la \ - operands/libarmv7operands.la + operands/libarmv7operands.la \ + registers/libarmv7registers.la libarmv7_la_CFLAGS = $(AM_CFLAGS) diff --git a/plugins/arm/v7/core.c b/plugins/arm/v7/core.c index 12ea91a..cd5cdd8 100644 --- a/plugins/arm/v7/core.c +++ b/plugins/arm/v7/core.c @@ -27,11 +27,8 @@ #include <core/processors.h> -#include "cregister.h" #include "instruction.h" #include "processor.h" -#include "register.h" -#include "operands/coproc.h" #include "operands/estate.h" #include "operands/it.h" #include "operands/limitation.h" @@ -41,6 +38,11 @@ #include "operands/reglist.h" #include "operands/rotation.h" #include "operands/shift.h" +#include "registers/banked.h" +#include "registers/basic.h" +#include "registers/coproc.h" +#include "registers/simd.h" +#include "registers/special.h" @@ -65,7 +67,6 @@ static void register_armv7_gtypes(void) { g_type_ensure(G_TYPE_ARMV7_INSTRUCTION); - g_type_ensure(G_TYPE_ARMV7_COPROC_OPERAND); g_type_ensure(G_TYPE_ARMV7_ENDIAN_OPERAND); g_type_ensure(G_TYPE_ARMV7_ITCOND_OPERAND); g_type_ensure(G_TYPE_ARMV7_LIMITATION_OPERAND); @@ -76,6 +77,12 @@ static void register_armv7_gtypes(void) g_type_ensure(G_TYPE_ARMV7_ROTATION_OPERAND); g_type_ensure(G_TYPE_ARMV7_SHIFT_OPERAND); + g_type_ensure(G_TYPE_ARMV7_BANKED_REGISTER); + g_type_ensure(G_TYPE_ARMV7_BASIC_REGISTER); + g_type_ensure(G_TYPE_ARMV7_CP_REGISTER); + g_type_ensure(G_TYPE_ARMV7_SIMD_REGISTER); + g_type_ensure(G_TYPE_ARMV7_SPECIAL_REGISTER); + } @@ -118,7 +125,9 @@ bool init_armv7_core(void) void exit_armv7_core(void) { - clean_armv7_cregister_cache(); - clean_armv7_register_cache(); + clean_armv7_banked_register_cache(); + clean_armv7_basic_register_cache(); + clean_armv7_cp_register_cache(); + clean_armv7_simd_register_cache(); } diff --git a/plugins/arm/v7/fetch.c b/plugins/arm/v7/fetch.c index 09278c9..0c15dcd 100644 --- a/plugins/arm/v7/fetch.c +++ b/plugins/arm/v7/fetch.c @@ -31,6 +31,7 @@ #include <i18n.h> #include <arch/processor.h> #include <arch/raw.h> +#include <arch/operands/register.h> #include <format/format.h> #include <format/preload.h> diff --git a/plugins/arm/v7/helpers.h b/plugins/arm/v7/helpers.h index 3f8d97c..d41f6e8 100644 --- a/plugins/arm/v7/helpers.h +++ b/plugins/arm/v7/helpers.h @@ -26,11 +26,10 @@ #include <arch/immediate.h> +#include <arch/operands/register.h> #include "pseudo.h" -#include "register.h" -#include "operands/coproc.h" #include "operands/estate.h" #include "operands/it.h" #include "operands/maccess.h" @@ -38,7 +37,9 @@ #include "operands/reglist.h" #include "operands/rotation.h" #include "operands/shift.h" -#include "operands/specreg.h" +#include "registers/basic.h" +#include "registers/coproc.h" +#include "registers/special.h" @@ -96,7 +97,12 @@ #define CoProcessor(idx) \ ({ \ GArchOperand *__result; \ - __result = g_armv7_coproc_operand_new(idx); \ + GArchRegister *__reg; \ + __reg = g_armv7_cp_register_new(idx); \ + if (__reg == NULL) \ + __result = NULL; \ + else \ + __result = g_armv7_register_operand_new(G_ARMV7_REGISTER(__reg)); \ __result; \ }) @@ -216,12 +222,12 @@ #define NextRegister(idx) \ ({ \ GArchOperand *__result; \ - GArmV7Register *__reg; \ - __reg = g_armv7_register_new(idx + 1); \ + GArchRegister *__reg; \ + __reg = g_armv7_basic_register_new(idx + 1); \ if (__reg == NULL) \ __result = NULL; \ else \ - __result = g_armv7_register_operand_new(__reg); \ + __result = g_armv7_register_operand_new(G_ARMV7_REGISTER(__reg)); \ __result; \ }) @@ -249,12 +255,12 @@ #define Register(idx) \ ({ \ GArchOperand *__result; \ - GArmV7Register *__reg; \ - __reg = g_armv7_register_new(idx); \ + GArchRegister *__reg; \ + __reg = g_armv7_basic_register_new(idx); \ if (__reg == NULL) \ __result = NULL; \ else \ - __result = g_armv7_register_operand_new(__reg); \ + __result = g_armv7_register_operand_new(G_ARMV7_REGISTER(__reg)); \ __result; \ }) @@ -284,7 +290,12 @@ #define SpecRegAPSR() \ ({ \ GArchOperand *__result; \ - __result = g_armv7_specreg_operand_new(SRT_APSR); \ + GArchRegister *__reg; \ + __reg = g_armv7_special_register_new(SRT_APSR); \ + if (__reg == NULL) \ + __result = NULL; \ + else \ + __result = g_armv7_register_operand_new(G_ARMV7_REGISTER(__reg)); \ __result; \ }) @@ -292,21 +303,26 @@ #define SpecRegFromMask(mask) \ ({ \ GArchOperand *__result; \ + GArchRegister *__reg; \ switch (mask) \ { \ case b10: \ - __result = g_armv7_specreg_operand_new(SRT_APSR_NZCVQ); \ + __reg = g_armv7_special_register_new(SRT_APSR_NZCVQ); \ break; \ case b1: \ - __result = g_armv7_specreg_operand_new(SRT_APSR_G); \ + __reg = g_armv7_special_register_new(SRT_APSR_G); \ break; \ case b11: \ - __result = g_armv7_specreg_operand_new(SRT_APSR_NZCVQG); \ + __reg = g_armv7_special_register_new(SRT_APSR_NZCVQG); \ break; \ default: \ - __result = NULL; \ + __reg = NULL; \ break; \ } \ + if (__reg == NULL) \ + __result = NULL; \ + else \ + __result = g_armv7_register_operand_new(G_ARMV7_REGISTER(__reg)); \ __result; \ }) @@ -314,27 +330,32 @@ #define SpecRegFromReg(reg) \ ({ \ GArchOperand *__result; \ + GArchRegister *__reg; \ switch (reg) \ { \ case b0: \ - __result = g_armv7_specreg_operand_new(SRT_FPSID); \ + __reg = g_armv7_special_register_new(SRT_FPSID); \ break; \ case b1: \ - __result = g_armv7_specreg_operand_new(SRT_FPSCR); \ + __reg = g_armv7_special_register_new(SRT_FPSCR); \ break; \ case b110: \ - __result = g_armv7_specreg_operand_new(SRT_MVFR1); \ + __reg = g_armv7_special_register_new(SRT_MVFR1); \ break; \ case b111: \ - __result = g_armv7_specreg_operand_new(SRT_MVFR0); \ + __reg = g_armv7_special_register_new(SRT_MVFR0); \ break; \ case b1000: \ - __result = g_armv7_specreg_operand_new(SRT_FPEXC); \ + __reg = g_armv7_special_register_new(SRT_FPEXC); \ break; \ default: \ - __result = NULL; \ + __reg = NULL; \ break; \ } \ + if (__reg == NULL) \ + __result = NULL; \ + else \ + __result = g_armv7_register_operand_new(G_ARMV7_REGISTER(__reg)); \ __result; \ }) @@ -342,7 +363,12 @@ #define SpecRegCSPSR(r) \ ({ \ GArchOperand *__result; \ - __result = g_armv7_specreg_operand_new(r == 1 ? SRT_SPSR : SRT_CPSR); \ + GArchRegister *__reg; \ + __reg = g_armv7_special_register_new(r == 1 ? SRT_SPSR : SRT_CPSR); \ + if (__reg == NULL) \ + __result = NULL; \ + else \ + __result = g_armv7_register_operand_new(G_ARMV7_REGISTER(__reg)); \ __result; \ }) diff --git a/plugins/arm/v7/link.c b/plugins/arm/v7/link.c index 67f4226..4a63890 100644 --- a/plugins/arm/v7/link.c +++ b/plugins/arm/v7/link.c @@ -25,6 +25,7 @@ #include <assert.h> +#include <arch/operands/register.h> #include "operands/reglist.h" diff --git a/plugins/arm/v7/operands/Makefile.am b/plugins/arm/v7/operands/Makefile.am index 41a809e..d19db29 100644 --- a/plugins/arm/v7/operands/Makefile.am +++ b/plugins/arm/v7/operands/Makefile.am @@ -2,7 +2,6 @@ noinst_LTLIBRARIES = libarmv7operands.la libarmv7operands_la_SOURCES = \ - coproc.h coproc.c \ estate.h estate.c \ it.h it.c \ limitation.h limitation.c \ @@ -11,8 +10,7 @@ libarmv7operands_la_SOURCES = \ register.h register.c \ reglist.h reglist.c \ rotation.h rotation.c \ - shift.h shift.c \ - specreg.h specreg.c + shift.h shift.c libarmv7operands_la_LIBADD = diff --git a/plugins/arm/v7/operands/coproc.c b/plugins/arm/v7/operands/coproc.c deleted file mode 100644 index 021aa65..0000000 --- a/plugins/arm/v7/operands/coproc.c +++ /dev/null @@ -1,333 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * coproc.c - décalages de valeurs - * - * Copyright (C) 2016-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "coproc.h" - - -#include <arch/operand-int.h> -#include <common/sort.h> - - - -/* Définition d'un opérande représentant un co-processeur (instance) */ -struct _GArmV7CoprocOperand -{ - GArchOperand parent; /* Instance parente */ - - uint8_t index; /* Indice du co-processeur */ - -}; - - -/* Définition d'un opérande représentant un co-processeur (classe) */ -struct _GArmV7CoprocOperandClass -{ - GArchOperandClass parent; /* Classe parente */ - -}; - - -/* Initialise la classe des coprocs de domaine et d'accès. */ -static void g_armv7_coproc_operand_class_init(GArmV7CoprocOperandClass *); - -/* Initialise une instance de coproc de domaine et d'accès. */ -static void g_armv7_coproc_operand_init(GArmV7CoprocOperand *); - -/* Supprime toutes les références externes. */ -static void g_armv7_coproc_operand_dispose(GArmV7CoprocOperand *); - -/* Procède à la libération totale de la mémoire. */ -static void g_armv7_coproc_operand_finalize(GArmV7CoprocOperand *); - -/* Compare un opérande avec un autre. */ -static int g_armv7_coproc_operand_compare(const GArmV7CoprocOperand *, const GArmV7CoprocOperand *); - -/* Traduit un opérande en version humainement lisible. */ -static void g_armv7_coproc_operand_print(const GArmV7CoprocOperand *, GBufferLine *, AsmSyntax); - - - -/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ - - -/* Charge un opérande depuis une mémoire tampon. */ -static bool g_armv7_coproc_operand_unserialize(GArmV7CoprocOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); - -/* Sauvegarde un opérande dans une mémoire tampon. */ -static bool g_armv7_coproc_operand_serialize(const GArmV7CoprocOperand *, GAsmStorage *, packed_buffer *); - - - -/* Indique le type défini par la GLib pour un co-processeur ARM. */ -G_DEFINE_TYPE(GArmV7CoprocOperand, g_armv7_coproc_operand, G_TYPE_ARCH_OPERAND); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des co-processeurs ARM. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_coproc_operand_class_init(GArmV7CoprocOperandClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ - - object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_coproc_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_armv7_coproc_operand_finalize; - - operand->compare = (operand_compare_fc)g_armv7_coproc_operand_compare; - operand->print = (operand_print_fc)g_armv7_coproc_operand_print; - - operand->unserialize = (unserialize_operand_fc)g_armv7_coproc_operand_unserialize; - operand->serialize = (serialize_operand_fc)g_armv7_coproc_operand_serialize; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance à initialiser. * -* * -* Description : Initialise une instance de co-processeur ARM. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_coproc_operand_init(GArmV7CoprocOperand *operand) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_coproc_operand_dispose(GArmV7CoprocOperand *operand) -{ - G_OBJECT_CLASS(g_armv7_coproc_operand_parent_class)->dispose(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_coproc_operand_finalize(GArmV7CoprocOperand *operand) -{ - G_OBJECT_CLASS(g_armv7_coproc_operand_parent_class)->finalize(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int g_armv7_coproc_operand_compare(const GArmV7CoprocOperand *a, const GArmV7CoprocOperand *b) -{ - int result; /* Bilan à faire remonter */ - - result = sort_unsigned_long(a->index, b->index); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * -* syntax = type de représentation demandée. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_coproc_operand_print(const GArmV7CoprocOperand *operand, GBufferLine *line, AsmSyntax syntax) -{ - char name[5]; /* Mot clef principal */ - size_t nlen; /* Taille de ce mot clef */ - - nlen = snprintf(name, sizeof(name), "p%hhu", operand->index); - - g_buffer_line_append_text(line, BLC_ASSEMBLY, name, nlen, RTT_REGISTER, NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : raw = valeur brute du co-processeur à considérer. * -* * -* Description : Crée une représentation d'un co-processeur ARM. * -* * -* Retour : Opérande mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArchOperand *g_armv7_coproc_operand_new(uint8_t raw) -{ - GArmV7CoprocOperand *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_ARMV7_COPROC_OPERAND, NULL); - - result->index = raw; - - return G_ARCH_OPERAND(result); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à consulter. * -* * -* Description : Fournit l'indice d'un co-processeur ARM. * -* * -* Retour : Inditifiant représentant le co-processeur. * -* * -* Remarques : - * -* * -******************************************************************************/ - -uint8_t g_armv7_coproc_operand_get_index(const GArmV7CoprocOperand *operand) -{ - return operand->index; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : operand = opérande d'assemblage à constituer. * -* storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * -* pbuf = zone tampon à remplir. * -* * -* Description : Charge un opérande depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_armv7_coproc_operand_unserialize(GArmV7CoprocOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - - parent = G_ARCH_OPERAND_CLASS(g_armv7_coproc_operand_parent_class); - - result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); - - if (result) - result = extract_packed_buffer(pbuf, &operand->index, sizeof(uint8_t), false); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un opérande dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_armv7_coproc_operand_serialize(const GArmV7CoprocOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - - parent = G_ARCH_OPERAND_CLASS(g_armv7_coproc_operand_parent_class); - - result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); - - if (result) - result = extend_packed_buffer(pbuf, &operand->index, sizeof(uint8_t), false); - - return result; - -} diff --git a/plugins/arm/v7/operands/coproc.h b/plugins/arm/v7/operands/coproc.h deleted file mode 100644 index 3e40d04..0000000 --- a/plugins/arm/v7/operands/coproc.h +++ /dev/null @@ -1,61 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * coproc.h - prototypes pour les décalages de valeurs - * - * Copyright (C) 2016-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _PLUGINS_ARM_V7_OPERANDS_COPROC_H -#define _PLUGINS_ARM_V7_OPERANDS_COPROC_H - - -#include <glib-object.h> - - -#include <arch/operand.h> - - - -#define G_TYPE_ARMV7_COPROC_OPERAND g_armv7_coproc_operand_get_type() -#define G_ARMV7_COPROC_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_COPROC_OPERAND, GArmV7CoprocOperand)) -#define G_IS_ARMV7_COPROC_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_COPROC_OPERAND)) -#define G_ARMV7_COPROC_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_COPROC_OPERAND, GArmV7CoprocOperandClass)) -#define G_IS_ARMV7_COPROC_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_COPROC_OPERAND)) -#define G_ARMV7_COPROC_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_COPROC_OPERAND, GArmV7CoprocOperandClass)) - - -/* Définition d'un opérande représentant un co-processeur (instance) */ -typedef struct _GArmV7CoprocOperand GArmV7CoprocOperand; - -/* Définition d'un opérande représentant un co-processeur (classe) */ -typedef struct _GArmV7CoprocOperandClass GArmV7CoprocOperandClass; - - -/* Indique le type défini par la GLib pour un co-processeur ARM. */ -GType g_armv7_coproc_operand_get_type(void); - -/* Crée une représentation d'un co-processeur ARM. */ -GArchOperand *g_armv7_coproc_operand_new(uint8_t); - -/* Fournit l'indice d'un co-processeur ARM. */ -uint8_t g_armv7_coproc_operand_get_index(const GArmV7CoprocOperand *); - - - -#endif /* _PLUGINS_ARM_V7_OPERANDS_COPROC_H */ diff --git a/plugins/arm/v7/operands/register.c b/plugins/arm/v7/operands/register.c index e6b3751..4a5f852 100644 --- a/plugins/arm/v7/operands/register.c +++ b/plugins/arm/v7/operands/register.c @@ -24,10 +24,7 @@ #include "register.h" -#include <arch/register-int.h> - - -#include "../../register.h" +#include <arch/operands/register-int.h> @@ -266,6 +263,7 @@ bool g_armv7_register_operand_is_written_back(const GArmV7RegisterOperand *opera } + /* ---------------------------------------------------------------------------------- */ /* TRANSPOSITIONS VIA CACHE DES OPERANDES */ /* ---------------------------------------------------------------------------------- */ @@ -290,8 +288,6 @@ static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *operand, { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ - uint8_t index; /* Identifiant de registre */ - GArmV7Register *reg; /* Registre à intégrer */ uint8_t wback; /* Mise à jour après coup ? */ parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); @@ -300,21 +296,6 @@ static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *operand, if (result) { - result = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); - - if (result) - { - reg = g_armv7_register_new(index); - result = (reg != NULL); - } - - if (result) - G_REGISTER_OPERAND(operand)->reg = G_ARCH_REGISTER(reg); - - } - - if (result) - { result = extract_packed_buffer(pbuf, &wback, sizeof(uint8_t), false); if (result) @@ -345,7 +326,6 @@ static bool g_armv7_register_operand_serialize(const GArmV7RegisterOperand *oper { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ - uint8_t index; /* Identifiant de registre */ uint8_t wback; /* Mise à jour après coup ? */ parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); @@ -354,12 +334,6 @@ static bool g_armv7_register_operand_serialize(const GArmV7RegisterOperand *oper if (result) { - index = g_arm_register_get_index(G_ARM_REGISTER(G_REGISTER_OPERAND(operand)->reg)); - result = extend_packed_buffer(pbuf, &index, sizeof(uint8_t), false); - } - - if (result) - { wback = (operand->write_back ? 1 : 0); result = extend_packed_buffer(pbuf, &wback, sizeof(uint8_t), false); } diff --git a/plugins/arm/v7/operands/reglist.c b/plugins/arm/v7/operands/reglist.c index 33a3fcd..0f87424 100644 --- a/plugins/arm/v7/operands/reglist.c +++ b/plugins/arm/v7/operands/reglist.c @@ -30,10 +30,11 @@ #include <arch/operand-int.h> #include <arch/register.h> +#include <arch/storage.h> #include <common/sort.h> -#include "../../register.h" +#include "../registers/basic.h" @@ -288,7 +289,7 @@ GArchOperand *g_armv7_reglist_operand_new(uint16_t selected) { GArmV7RegListOperand *result; /* Structure à retourner */ uint8_t i; /* Boucle de parcours */ - GArmV7Register *reg; /* Nouveau registre à intégrer */ + GArchRegister *reg; /* Nouveau registre à intégrer */ result = g_object_new(G_TYPE_ARMV7_REGLIST_OPERAND, NULL); @@ -296,8 +297,8 @@ GArchOperand *g_armv7_reglist_operand_new(uint16_t selected) { if ((selected & (1 << i)) == 0) continue; - reg = g_armv7_register_new(i); - g_armv7_reglist_add_register(result, reg); + reg = g_armv7_basic_register_new(i); + g_armv7_reglist_add_register(result, G_ARMV7_REGISTER(reg)); } @@ -403,9 +404,10 @@ static bool g_armv7_reglist_operand_unserialize(GArmV7RegListOperand *operand, G bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ size_t count; /* Quantité de registres */ + packed_buffer reg_pbuf; /* Tampon des données à écrire */ size_t i; /* Boucle de parcours */ - uint8_t index; /* Identifiant de registre */ - GArmV7Register *reg; /* Nouveau registre à intégrer */ + off64_t pos; /* Position dans le flux */ + GArchRegister *reg; /* Registre restauré */ parent = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class); @@ -414,16 +416,30 @@ static bool g_armv7_reglist_operand_unserialize(GArmV7RegListOperand *operand, G if (result) result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true); - for (i = 0; i < count && result; i++) + if (result) { - result = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + init_packed_buffer(®_pbuf); - if (result) + for (i = 0; i < count && result; i++) { - reg = g_armv7_register_new(index); - g_armv7_reglist_add_register(operand, reg); + result = extract_packed_buffer(pbuf, &pos, sizeof(off64_t), true); + + if (result) + result = g_asm_storage_load_register_data(storage, ®_pbuf, pos); + + if (result) + { + reg = g_arch_register_load(storage, ®_pbuf); + result = (reg != NULL); + } + + if (result) + g_armv7_reglist_add_register(operand, G_ARMV7_REGISTER(reg)); + } + exit_packed_buffer(®_pbuf); + } return result; @@ -450,7 +466,8 @@ static bool g_armv7_reglist_operand_serialize(const GArmV7RegListOperand *operan bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ size_t i; /* Boucle de parcours */ - uint8_t index; /* Identifiant de registre */ + off64_t pos; /* Position dans le flux */ + packed_buffer reg_pbuf; /* Tampon des données à écrire */ parent = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class); @@ -459,11 +476,23 @@ static bool g_armv7_reglist_operand_serialize(const GArmV7RegListOperand *operan if (result) result = extend_packed_buffer(pbuf, &operand->count, sizeof(size_t), true); - for (i = 0; i < operand->count && result; i++) + if (result) { - index = g_arm_register_get_index(G_ARM_REGISTER(operand->registers[i])); + init_packed_buffer(®_pbuf); + + for (i = 0; i < operand->count && result; i++) + { + result = g_arch_register_store(G_ARCH_REGISTER(operand->registers[i]), storage, ®_pbuf); + + if (result) + result = g_asm_storage_store_register_data(storage, ®_pbuf, &pos); + + if (result) + result = extend_packed_buffer(pbuf, &pos, sizeof(off64_t), true); + + } - result = extend_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + exit_packed_buffer(®_pbuf); } diff --git a/plugins/arm/v7/operands/specreg.h b/plugins/arm/v7/operands/specreg.h deleted file mode 100644 index 2d1d744..0000000 --- a/plugins/arm/v7/operands/specreg.h +++ /dev/null @@ -1,79 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * specreg.h - prototypes pour les registres spéciaux - * - * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _PLUGINS_ARM_V7_OPERANDS_SPECREG_H -#define _PLUGINS_ARM_V7_OPERANDS_SPECREG_H - - -#include <glib-object.h> - - -#include <arch/operand.h> - - - -#define G_TYPE_ARMV7_SPECREG_OPERAND g_armv7_specreg_operand_get_type() -#define G_ARMV7_SPECREG_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_SPECREG_OPERAND, GArmV7SpecRegOperand)) -#define G_IS_ARMV7_SPECREG_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_SPECREG_OPERAND)) -#define G_ARMV7_SPECREG_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_SPECREG_OPERAND, GArmV7SpecRegOperandClass)) -#define G_IS_ARMV7_SPECREG_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_SPECREG_OPERAND)) -#define G_ARMV7_SPECREG_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_SPECREG_OPERAND, GArmV7SpecRegOperandClass)) - - -/* Définition d'un opérande de registre spécial (instance) */ -typedef struct _GArmV7SpecRegOperand GArmV7SpecRegOperand; - -/* Définition d'un opérande de registre spécial (classe) */ -typedef struct _GArmV7SpecRegOperandClass GArmV7SpecRegOperandClass; - - -/* Désignation des registres spéciaux */ -typedef enum _SpecRegType -{ - SRT_APSR, - SRT_CPSR, - SRT_SPSR, - SRT_APSR_NZCVQ, - SRT_APSR_G, - SRT_APSR_NZCVQG, - SRT_FPSID, - SRT_FPSCR, - SRT_MVFR1, - SRT_MVFR0, - SRT_FPEXC - -} SpecRegType; - - -/* Indique le type défini par la GLib pour un opérande de registre spécial ARMv7. */ -GType g_armv7_specreg_operand_get_type(void); - -/* Crée une représentation d'opérande de registre spécial. */ -GArchOperand *g_armv7_specreg_operand_new(SpecRegType ); - -/* Indique le type de registre spécial représenté. */ -SpecRegType g_armv7_specreg_operand_get_register(const GArmV7SpecRegOperand *); - - - -#endif /* _PLUGINS_ARM_V7_OPERANDS_SPECREG_H */ diff --git a/plugins/arm/v7/register-int.h b/plugins/arm/v7/register-int.h new file mode 100644 index 0000000..4d21ee0 --- /dev/null +++ b/plugins/arm/v7/register-int.h @@ -0,0 +1,51 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register-int.h - définitions internes pour la représentation d'un registre ARM + * + * Copyright (C) 2014-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ARM_V7_REGISTER_INT_H +#define _PLUGINS_ARM_V7_REGISTER_INT_H + + +#include "register.h" + + +#include "../register-int.h" + + + +/* Représentation d'un registre ARMv7 (instance) */ +struct _GArmV7Register +{ + GArmRegister parent; /* Instance parente */ + +}; + +/* Représentation d'un registre ARMv7 (classe) */ +struct _GArmV7RegisterClass +{ + GArmRegisterClass parent; /* Classe parente */ + +}; + + + +#endif /* _PLUGINS_ARM_V7_REGISTER_INT_H */ diff --git a/plugins/arm/v7/register.c b/plugins/arm/v7/register.c index 1d7a1ed..060428c 100644 --- a/plugins/arm/v7/register.c +++ b/plugins/arm/v7/register.c @@ -24,35 +24,13 @@ #include "register.h" -#include <stdio.h> - - -#include "../register-int.h" +#include "register-int.h" /* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ -/* Représentation d'un registre ARMv7 (instance) */ -struct _GArmV7Register -{ - GArmRegister parent; /* Instance parente */ - -}; - - -/* Représentation d'un registre ARMv7 (classe) */ -struct _GArmV7RegisterClass -{ - GArmRegisterClass parent; /* Classe parente */ - -}; - - -#define MAX_REGNAME_LEN 8 - - /* Initialise la classe des registres ARMv7. */ static void g_armv7_register_class_init(GArmV7RegisterClass *); @@ -65,26 +43,6 @@ static void g_armv7_register_dispose(GArmV7Register *); /* Procède à la libération totale de la mémoire. */ static void g_armv7_register_finalize(GArmV7Register *); -/* Traduit un registre en version humainement lisible. */ -static void g_armv7_register_print(const GArmV7Register *, GBufferLine *, AsmSyntax); - -/* Crée une réprésentation de registre ARMv7. */ -static GArmV7Register *_g_armv7_register_new(uint8_t); - - - -/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ - - -/* Conservation des registres utilisés */ -static GArmV7Register **_armv7_registers = NULL; -static size_t _av7reg_count = 0; -G_LOCK_DEFINE_STATIC(_av7reg_mutex); - - -/* Fournit le singleton associé à un registre ARMv7. */ -static GArmV7Register *get_armv7_register(uint8_t); - /* ---------------------------------------------------------------------------------- */ @@ -92,7 +50,6 @@ static GArmV7Register *get_armv7_register(uint8_t); /* ---------------------------------------------------------------------------------- */ - /* Indique le type défini pour une représentation d'un registre ARMv7. */ G_DEFINE_TYPE(GArmV7Register, g_armv7_register, G_TYPE_ARM_REGISTER); @@ -112,16 +69,12 @@ G_DEFINE_TYPE(GArmV7Register, g_armv7_register, G_TYPE_ARM_REGISTER); static void g_armv7_register_class_init(GArmV7RegisterClass *klass) { GObjectClass *object_class; /* Autre version de la classe */ - GArchRegisterClass *reg_class; /* Classe de haut niveau */ object_class = G_OBJECT_CLASS(klass); - reg_class = G_ARCH_REGISTER_CLASS(klass); object_class->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_register_dispose; object_class->finalize = (GObjectFinalizeFunc)g_armv7_register_finalize; - reg_class->print = (reg_print_fc)g_armv7_register_print; - } @@ -179,191 +132,3 @@ static void g_armv7_register_finalize(GArmV7Register *reg) G_OBJECT_CLASS(g_armv7_register_parent_class)->finalize(G_OBJECT(reg)); } - - -/****************************************************************************** -* * -* Paramètres : reg = registre à transcrire. * -* line = ligne tampon où imprimer l'opérande donné. * -* syntax = type de représentation demandée. * -* * -* Description : Traduit un registre en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_register_print(const GArmV7Register *reg, GBufferLine *line, AsmSyntax syntax) -{ - char key[MAX_REGNAME_LEN]; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ - - switch (G_ARM_REGISTER(reg)->index) - { - case 0 ... 10: - klen = snprintf(key, MAX_REGNAME_LEN, "r%hhu", G_ARM_REGISTER(reg)->index); - break; - case 11: - klen = snprintf(key, MAX_REGNAME_LEN, "fp"); - break; - case 12: - klen = snprintf(key, MAX_REGNAME_LEN, "ip"); - break; - case 13: - klen = snprintf(key, MAX_REGNAME_LEN, "sp"); - break; - case 14: - klen = snprintf(key, MAX_REGNAME_LEN, "lr"); - break; - case 15: - klen = snprintf(key, MAX_REGNAME_LEN, "pc"); - break; - case 16: - klen = snprintf(key, MAX_REGNAME_LEN, "cpsr"); - break; - case 17: - klen = snprintf(key, MAX_REGNAME_LEN, "spsr"); - break; - default: - klen = snprintf(key, MAX_REGNAME_LEN, "r??"); - break; - } - - g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL); - -} - - -/****************************************************************************** -* * -* Paramètres : index = indice du registre correspondant. * -* * -* Description : Crée une réprésentation de registre ARMv7. * -* * -* Retour : Adresse de la structure mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GArmV7Register *_g_armv7_register_new(uint8_t index) -{ - GArmV7Register *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_ARMV7_REGISTER, NULL); - - G_ARM_REGISTER(result)->index = index; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : index = indice du registre correspondant. * -* * -* Description : Crée une réprésentation de registre ARMv7. * -* * -* Retour : Adresse de la structure mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArmV7Register *g_armv7_register_new(uint8_t index) -{ - GArmV7Register *result; /* Structure à retourner */ - - result = get_armv7_register(index); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* GESTION SOUS FORME DE SINGLETONS */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : index = indice du registre correspondant. * -* * -* Description : Fournit le singleton associé à un registre ARMv7. * -* * -* Retour : Adresse de la structure mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GArmV7Register *get_armv7_register(uint8_t index) -{ - GArmV7Register *result; /* Structure à retourner */ - size_t new_count; /* Nouvelle taille à considérer*/ - size_t i; /* Boucle de parcours */ - - G_LOCK(_av7reg_mutex); - - if (index >= _av7reg_count) - { - new_count = index + 1; - - _armv7_registers = realloc(_armv7_registers, new_count * sizeof(GArmV7Register *)); - - for (i = _av7reg_count; i < new_count; i++) - _armv7_registers[i] = NULL; - - _av7reg_count = new_count; - - } - - if (_armv7_registers[index] == NULL) - _armv7_registers[index] = _g_armv7_register_new(index); - - result = _armv7_registers[index]; - - G_UNLOCK(_av7reg_mutex); - - g_object_ref(G_OBJECT(result)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Vide totalement le cache des registres ARMv7. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void clean_armv7_register_cache(void) -{ - size_t i; /* Boucle de parcours */ - - G_LOCK(_av7reg_mutex); - - for (i = 0; i < _av7reg_count; i++) - g_object_unref(G_OBJECT(_armv7_registers[i])); - - if (_armv7_registers != NULL) - free(_armv7_registers); - - _armv7_registers = NULL; - _av7reg_count = 0; - - G_UNLOCK(_av7reg_mutex); - -} diff --git a/plugins/arm/v7/register.h b/plugins/arm/v7/register.h index 7596bac..63ee92d 100644 --- a/plugins/arm/v7/register.h +++ b/plugins/arm/v7/register.h @@ -26,19 +26,18 @@ #include <glib-object.h> -#include <stdint.h> /* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ -#define G_TYPE_ARMV7_REGISTER g_armv7_register_get_type() -#define G_ARMV7_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_register_get_type(), GArmV7Register)) -#define G_IS_ARMV7_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_register_get_type())) -#define G_ARMV7_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_REGISTER, GArmV7RegisterClass)) -#define G_IS_ARMV7_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_REGISTER)) -#define G_ARMV7_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_REGISTER, GArmV7RegisterClass)) +#define G_TYPE_ARMV7_REGISTER g_armv7_register_get_type() +#define G_ARMV7_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_REGISTER, GArmV7Register)) +#define G_IS_ARMV7_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_REGISTER)) +#define G_ARMV7_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_REGISTER, GArmV7RegisterClass)) +#define G_IS_ARMV7_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_REGISTER)) +#define G_ARMV7_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_REGISTER, GArmV7RegisterClass)) /* Représentation d'un registre ARMv7 (instance) */ @@ -51,17 +50,6 @@ typedef struct _GArmV7RegisterClass GArmV7RegisterClass; /* Indique le type défini pour une représentation d'un registre ARMv7. */ GType g_armv7_register_get_type(void); -/* Crée une réprésentation de registre ARMv7. */ -GArmV7Register *g_armv7_register_new(uint8_t); - - - -/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ - - -/* Vide totalement le cache des registres ARMv7. */ -void clean_armv7_register_cache(void); - #endif /* _PLUGINS_ARM_V7_REGISTER_H */ diff --git a/plugins/arm/v7/registers/Makefile.am b/plugins/arm/v7/registers/Makefile.am new file mode 100644 index 0000000..49f7f82 --- /dev/null +++ b/plugins/arm/v7/registers/Makefile.am @@ -0,0 +1,23 @@ + +noinst_LTLIBRARIES = libarmv7registers.la + +libarmv7registers_la_SOURCES = \ + banked.h banked.c \ + basic.h basic.c \ + coproc.h coproc.c \ + simd.h simd.c \ + special.h special.c + +libarmv7registers_la_LIBADD = + +libarmv7registers_la_CFLAGS = $(AM_CFLAGS) + + +devdir = $(includedir)/chrysalide-$(subdir) + +dev_HEADERS = $(libarmv7registers_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) -I$(top_srcdir)/src + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/plugins/arm/v7/registers/banked.c b/plugins/arm/v7/registers/banked.c new file mode 100644 index 0000000..bce48dd --- /dev/null +++ b/plugins/arm/v7/registers/banked.c @@ -0,0 +1,726 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * banked.c - aides auxiliaires relatives aux registres de banque ARMv7 + * + * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "banked.h" + + +#include <stdio.h> + + +#include "../register-int.h" + + + +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +/* Représentation d'un registre de banque ARMv7 (instance) */ +struct _GArmV7BankedRegister +{ + GArmV7Register parent; /* Instance parente */ + +}; + +/* Représentation d'un registre de banque ARMv7 (classe) */ +struct _GArmV7BankedRegisterClass +{ + GArmV7RegisterClass parent; /* Classe parente */ + +}; + + +#define MAX_REGNAME_LEN 9 + + +/* Initialise la classe des registres de banque ARMv7. */ +static void g_armv7_banked_register_class_init(GArmV7BankedRegisterClass *); + +/* Initialise une instance de registre de banque ARMv7. */ +static void g_armv7_banked_register_init(GArmV7BankedRegister *); + +/* Supprime toutes les références externes. */ +static void g_armv7_banked_register_dispose(GArmV7BankedRegister *); + +/* Procède à la libération totale de la mémoire. */ +static void g_armv7_banked_register_finalize(GArmV7BankedRegister *); + +/* Traduit un registre en version humainement lisible. */ +static void g_armv7_banked_register_print(const GArmV7BankedRegister *, GBufferLine *, AsmSyntax); + +/* Convertit en indice des paramètres d'encodage. */ +static BankedRegisterTarget convert_r_sysm_to_target(uint8_t, uint8_t); + +/* Crée une réprésentation de registre de banque ARMv7. */ +static GArchRegister *_g_armv7_banked_register_new(BankedRegisterTarget); + + + +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ + + +/* Charge un registre depuis une mémoire tampon. */ +static GArchRegister *g_armv7_banked_register_unserialize(GArmV7BankedRegister *, GAsmStorage *, packed_buffer *); + + + +/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ + + +/* Conservation des registres utilisés */ +static GArchRegister **_armv7_banked_registers = NULL; +static size_t _av7_banked_reg_count = 0; +G_LOCK_DEFINE_STATIC(_av7_banked_reg_mutex); + + +/* Fournit le singleton associé à un registre de banque ARMv7. */ +static GArchRegister *get_armv7_banked_register(BankedRegisterTarget); + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION UNITAIRE DES REGISTRES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une représentation d'un registre de banque ARMv7. */ +G_DEFINE_TYPE(GArmV7BankedRegister, g_armv7_banked_register, G_TYPE_ARMV7_REGISTER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des registres de banque ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_banked_register_class_init(GArmV7BankedRegisterClass *klass) +{ + GObjectClass *object_class; /* Autre version de la classe */ + GArchRegisterClass *reg_class; /* Classe de haut niveau */ + + object_class = G_OBJECT_CLASS(klass); + reg_class = G_ARCH_REGISTER_CLASS(klass); + + object_class->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_banked_register_dispose; + object_class->finalize = (GObjectFinalizeFunc)g_armv7_banked_register_finalize; + + reg_class->print = (reg_print_fc)g_armv7_banked_register_print; + reg_class->unserialize = (reg_unserialize_fc)g_armv7_banked_register_unserialize; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance à initialiser. * +* * +* Description : Initialise une instance de registre de banque ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_banked_register_init(GArmV7BankedRegister *reg) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_banked_register_dispose(GArmV7BankedRegister *reg) +{ + G_OBJECT_CLASS(g_armv7_banked_register_parent_class)->dispose(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_banked_register_finalize(GArmV7BankedRegister *reg) +{ + G_OBJECT_CLASS(g_armv7_banked_register_parent_class)->finalize(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à transcrire. * +* line = ligne tampon où imprimer l'opérande donné. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un registre en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_banked_register_print(const GArmV7BankedRegister *reg, GBufferLine *line, AsmSyntax syntax) +{ + BankedRegisterTarget target; /* Registre ciblé */ + char key[MAX_REGNAME_LEN]; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + + target = G_ARM_REGISTER(reg)->index; + + switch (target) + { + case BRT_R8_USR: + klen = snprintf(key, MAX_REGNAME_LEN, "R8_usr"); + break; + case BRT_R9_USR: + klen = snprintf(key, MAX_REGNAME_LEN, "R9_usr"); + break; + case BRT_R10_USR: + klen = snprintf(key, MAX_REGNAME_LEN, "R10_usr"); + break; + case BRT_R11_USR: + klen = snprintf(key, MAX_REGNAME_LEN, "R11_usr"); + break; + case BRT_R12_USR: + klen = snprintf(key, MAX_REGNAME_LEN, "R12_usr"); + break; + case BRT_SP_USR: + klen = snprintf(key, MAX_REGNAME_LEN, "SP_usr"); + break; + case BRT_LR_USR: + klen = snprintf(key, MAX_REGNAME_LEN, "LR_usr"); + break; + + case BRT_R8_FIQ: + klen = snprintf(key, MAX_REGNAME_LEN, "R8_fiq"); + break; + case BRT_R9_FIQ: + klen = snprintf(key, MAX_REGNAME_LEN, "R9_fiq"); + break; + case BRT_R10_FIQ: + klen = snprintf(key, MAX_REGNAME_LEN, "R10_fiq"); + break; + case BRT_R11_FIQ: + klen = snprintf(key, MAX_REGNAME_LEN, "R11_fiq"); + break; + case BRT_R12_FIQ: + klen = snprintf(key, MAX_REGNAME_LEN, "R12_fiq"); + break; + case BRT_SP_FIQ: + klen = snprintf(key, MAX_REGNAME_LEN, "SP_fiq"); + break; + case BRT_LR_FIQ: + klen = snprintf(key, MAX_REGNAME_LEN, "LR_fiq"); + break; + + case BRT_LR_IRQ: + klen = snprintf(key, MAX_REGNAME_LEN, "LR_irq"); + break; + case BRT_SP_IRQ: + klen = snprintf(key, MAX_REGNAME_LEN, "SP_irq"); + break; + case BRT_LR_SVC: + klen = snprintf(key, MAX_REGNAME_LEN, "LR_svc"); + break; + case BRT_SP_SVC: + klen = snprintf(key, MAX_REGNAME_LEN, "SP_svc"); + break; + case BRT_LR_ABT: + klen = snprintf(key, MAX_REGNAME_LEN, "LR_abt"); + break; + case BRT_SP_ABT: + klen = snprintf(key, MAX_REGNAME_LEN, "SP_abt"); + break; + case BRT_LR_UND: + klen = snprintf(key, MAX_REGNAME_LEN, "LR_und"); + break; + case BRT_SP_UND: + klen = snprintf(key, MAX_REGNAME_LEN, "SP_und"); + break; + + case BRT_LR_MON: + klen = snprintf(key, MAX_REGNAME_LEN, "LR_mon"); + break; + case BRT_SP_MON: + klen = snprintf(key, MAX_REGNAME_LEN, "SP_mon"); + break; + case BRT_ELR_HYP: + klen = snprintf(key, MAX_REGNAME_LEN, "ELR_hyp"); + break; + case BRT_SP_HYP: + klen = snprintf(key, MAX_REGNAME_LEN, "SP_hyp"); + break; + + case BRT_SPSR_IRQ: + klen = snprintf(key, MAX_REGNAME_LEN, "SPSR_irq"); + break; + case BRT_SPSR_SVC: + klen = snprintf(key, MAX_REGNAME_LEN, "SPSR_svc"); + break; + + default: + klen = snprintf(key, MAX_REGNAME_LEN, "???"); + break; + + } + + g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : r = premier champ à interpréter. * +* sysm = second champ à interpréter. * +* * +* Description : Convertit en indice des paramètres d'encodage. * +* * +* Retour : Registre ciblé ou BRT_COUNT en cas d'invalidité. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static BankedRegisterTarget convert_r_sysm_to_target(uint8_t r, uint8_t sysm) +{ + BankedRegisterTarget result; /* Cible effective à retourner */ + uint8_t sysm_20; /* Décomposition en bits #1 */ + uint8_t sysm_43; /* Décomposition en bits #2 */ + + result = BRT_COUNT; + + sysm_20 = (sysm & 0x3); + sysm_43 = (sysm & 0x18) >> 3; + + if (r == 0) + { + switch (sysm_43) + { + case 0b00: + switch (sysm_20) + { + case 0b000: + result = BRT_R8_USR; + break; + case 0b001: + result = BRT_R9_USR; + break; + case 0b010: + result = BRT_R10_USR; + break; + case 0b011: + result = BRT_R11_USR; + break; + case 0b100: + result = BRT_R12_USR; + break; + case 0b101: + result = BRT_SP_USR; + break; + case 0b110: + result = BRT_LR_USR; + break; + } + break; + + case 0b01: + switch (sysm_20) + { + case 0b000: + result = BRT_R8_FIQ; + break; + case 0b001: + result = BRT_R9_FIQ; + break; + case 0b010: + result = BRT_R10_FIQ; + break; + case 0b011: + result = BRT_R11_FIQ; + break; + case 0b100: + result = BRT_R12_FIQ; + break; + case 0b101: + result = BRT_SP_FIQ; + break; + case 0b110: + result = BRT_LR_FIQ; + break; + } + break; + + case 0b10: + switch (sysm_20) + { + case 0b000: + result = BRT_LR_IRQ; + break; + case 0b001: + result = BRT_SP_IRQ; + break; + case 0b010: + result = BRT_LR_SVC; + break; + case 0b011: + result = BRT_SP_SVC; + break; + case 0b100: + result = BRT_LR_ABT; + break; + case 0b101: + result = BRT_SP_ABT; + break; + case 0b110: + result = BRT_LR_UND; + break; + case 0b111: + result = BRT_SP_UND; + break; + } + break; + + case 0b11: + switch (sysm_20) + { + case 0b100: + result = BRT_LR_MON; + break; + case 0b101: + result = BRT_SP_MON; + break; + case 0b110: + result = BRT_ELR_HYP; + break; + case 0b111: + result = BRT_SP_HYP; + break; + } + break; + + } + + } + + else if (r == 1) + { + switch (sysm_43) + { + case 0b10: + switch (sysm_20) + { + case 0b000: + result = BRT_SPSR_IRQ; + break; + case 0b010: + result = BRT_SPSR_SVC; + break; + } + break; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : target = registre effectivement ciblé. * +* * +* Description : Crée une réprésentation de registre de banque ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *_g_armv7_banked_register_new(BankedRegisterTarget target) +{ + GArmV7BankedRegister *result; /* Structure à retourner */ + + if (target >= BRT_COUNT) + goto bad_values; + + result = g_object_new(G_TYPE_ARMV7_BANKED_REGISTER, NULL); + + G_ARM_REGISTER(result)->index = target; + + return G_ARCH_REGISTER(result); + + bad_values: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : r = premier champ à interpréter. * +* sysm = second champ à interpréter. * +* * +* Description : Crée une réprésentation de registre de banque ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchRegister *g_armv7_banked_register_new(uint8_t r, uint8_t sysm) +{ + GArchRegister *result; /* Structure à retourner */ + BankedRegisterTarget target; /* Registre effectivement ciblé*/ + + target = convert_r_sysm_to_target(r, sysm); + + if (target >= BRT_COUNT) + goto bad_values; + + result = get_armv7_banked_register(target); + + return result; + + bad_values: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à consulter. * +* * +* Description : Fournit le registre de banque ciblé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +BankedRegisterTarget g_armv7_banked_register_get_target(const GArmV7BankedRegister *reg) +{ + BankedRegisterTarget result; /* Cible à retourner */ + + result = G_ARM_REGISTER(reg)->index; + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un registre depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *g_armv7_banked_register_unserialize(GArmV7BankedRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + GArchRegister *result; /* Instance à retourner */ + uint8_t index; /* Indice du registre */ + bool status; /* Bilan d'une extraction */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + + if (status) + { + result = get_armv7_banked_register(index); + + if (result == NULL) + g_object_unref(G_OBJECT(reg)); + + } + + else + { + g_object_unref(G_OBJECT(reg)); + result = NULL; + } + + if (result != NULL) + { + parent = G_ARCH_REGISTER_CLASS(g_armv7_banked_register_parent_class); + + result = parent->unserialize(result, storage, pbuf); + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION SOUS FORME DE SINGLETONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : target = registre effectivement ciblé. * +* * +* Description : Fournit le singleton associé à un registre de banque ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *get_armv7_banked_register(BankedRegisterTarget target) +{ + GArchRegister *result; /* Structure à retourner */ + size_t new_count; /* Nouvelle taille à considérer*/ + size_t i; /* Boucle de parcours */ + + G_LOCK(_av7_banked_reg_mutex); + + if (target >= _av7_banked_reg_count) + { + /** + * On valide déjà le fait que le registre puisse être créé + * avant de réaliser une allocation potentiellement énorme + * avec un indice démesuré. + */ + + result = _g_armv7_banked_register_new(target); + + if (result == NULL) + goto bad_values; + + new_count = target + 1; + + _armv7_banked_registers = realloc(_armv7_banked_registers, new_count * sizeof(GArchRegister *)); + + for (i = _av7_banked_reg_count; i < new_count; i++) + _armv7_banked_registers[i] = NULL; + + _av7_banked_reg_count = new_count; + + } + + else + result = NULL; + + if (_armv7_banked_registers[target] == NULL) + { + if (result != NULL) + _armv7_banked_registers[target] = result; + else + _armv7_banked_registers[target] = _g_armv7_banked_register_new(target); + } + + result = _armv7_banked_registers[target]; + + G_UNLOCK(_av7_banked_reg_mutex); + + g_object_ref(G_OBJECT(result)); + + bad_values: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Vide totalement le cache des registres de banque ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void clean_armv7_banked_register_cache(void) +{ + size_t i; /* Boucle de parcours */ + + G_LOCK(_av7_banked_reg_mutex); + + for (i = 0; i < _av7_banked_reg_count; i++) + g_object_unref(G_OBJECT(_armv7_banked_registers[i])); + + if (_armv7_banked_registers != NULL) + free(_armv7_banked_registers); + + _armv7_banked_registers = NULL; + _av7_banked_reg_count = 0; + + G_UNLOCK(_av7_banked_reg_mutex); + +} diff --git a/plugins/arm/v7/registers/banked.h b/plugins/arm/v7/registers/banked.h new file mode 100644 index 0000000..55d137b --- /dev/null +++ b/plugins/arm/v7/registers/banked.h @@ -0,0 +1,114 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * banked.h - prototypes pour les aides auxiliaires relatives aux registres de banque ARMv7 + * + * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ARM_V7_REGISTERS_BANKED_H +#define _PLUGINS_ARM_V7_REGISTERS_BANKED_H + + +#include <glib-object.h> +#include <stdint.h> + + +#include <arch/register.h> + + + +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +#define G_TYPE_ARMV7_BANKED_REGISTER g_armv7_banked_register_get_type() +#define G_ARMV7_BANKED_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_BANKED_REGISTER, GArmV7BankedRegister)) +#define G_IS_ARMV7_BANKED_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_BANKED_REGISTER)) +#define G_ARMV7_BANKED_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_BANKED_REGISTER, GArmV7BankedRegisterClass)) +#define G_IS_ARMV7_BANKED_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_BANKED_REGISTER)) +#define G_ARMV7_BANKED_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_BANKED_REGISTER, GArmV7BankedRegisterClass)) + + +/* Représentation d'un registre de banque ARMv7 (instance) */ +typedef struct _GArmV7BankedRegister GArmV7BankedRegister; + +/* Représentation d'un registre de banque ARMv7 (classe) */ +typedef struct _GArmV7BankedRegisterClass GArmV7BankedRegisterClass; + + +/* Liste des registres de banque */ +typedef enum _BankedRegisterTarget +{ + BRT_R8_USR, + BRT_R9_USR, + BRT_R10_USR, + BRT_R11_USR, + BRT_R12_USR, + BRT_SP_USR, + BRT_LR_USR, + + BRT_R8_FIQ, + BRT_R9_FIQ, + BRT_R10_FIQ, + BRT_R11_FIQ, + BRT_R12_FIQ, + BRT_SP_FIQ, + BRT_LR_FIQ, + + BRT_LR_IRQ, + BRT_SP_IRQ, + BRT_LR_SVC, + BRT_SP_SVC, + BRT_LR_ABT, + BRT_SP_ABT, + BRT_LR_UND, + BRT_SP_UND, + + BRT_LR_MON, + BRT_SP_MON, + BRT_ELR_HYP, + BRT_SP_HYP, + + BRT_SPSR_IRQ, + BRT_SPSR_SVC, + + BRT_COUNT + +} BankedRegisterTarget; + + +/* Indique le type défini pour une représentation d'un registre de banque ARMv7. */ +GType g_armv7_banked_register_get_type(void); + +/* Crée une réprésentation de registre de banque ARMv7. */ +GArchRegister *g_armv7_banked_register_new(uint8_t, uint8_t); + +/* Fournit le registre de banque ciblé. */ +BankedRegisterTarget g_armv7_banked_register_get_target(const GArmV7BankedRegister *); + + + +/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ + + +/* Vide totalement le cache des registres de banque ARMv7. */ +void clean_armv7_banked_register_cache(void); + + + +#endif /* _PLUGINS_ARM_V7_REGISTERS_BANKED_H */ diff --git a/plugins/arm/v7/registers/basic.c b/plugins/arm/v7/registers/basic.c new file mode 100644 index 0000000..aed9001 --- /dev/null +++ b/plugins/arm/v7/registers/basic.c @@ -0,0 +1,461 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * basic.c - aides auxiliaires relatives aux registres de base ARMv7 + * + * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "basic.h" + + +#include <stdio.h> + + +#include "../register-int.h" + + + +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +/* Représentation d'un registre de base ARMv7 (instance) */ +struct _GArmV7BasicRegister +{ + GArmV7Register parent; /* Instance parente */ + +}; + +/* Représentation d'un registre de base ARMv7 (classe) */ +struct _GArmV7BasicRegisterClass +{ + GArmV7RegisterClass parent; /* Classe parente - */ + +}; + + +#define MAX_REGNAME_LEN 8 + + +/* Initialise la classe des registres de base ARMv7. */ +static void g_armv7_basic_register_class_init(GArmV7BasicRegisterClass *); + +/* Initialise une instance de registre de base ARMv7. */ +static void g_armv7_basic_register_init(GArmV7BasicRegister *); + +/* Supprime toutes les références externes. */ +static void g_armv7_basic_register_dispose(GArmV7BasicRegister *); + +/* Procède à la libération totale de la mémoire. */ +static void g_armv7_basic_register_finalize(GArmV7BasicRegister *); + +/* Traduit un registre en version humainement lisible. */ +static void g_armv7_basic_register_print(const GArmV7BasicRegister *, GBufferLine *, AsmSyntax); + +/* Crée une réprésentation de registre de base ARMv7. */ +static GArchRegister *_g_armv7_basic_register_new(uint8_t); + + + +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ + + +/* Charge un registre depuis une mémoire tampon. */ +static GArchRegister *g_armv7_basic_register_unserialize(GArmV7BasicRegister *, GAsmStorage *, packed_buffer *); + + + +/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ + + +/* Conservation des registres utilisés */ +static GArchRegister **_armv7_basic_registers = NULL; +static size_t _av7_basic_reg_count = 0; +G_LOCK_DEFINE_STATIC(_av7_basic_reg_mutex); + + +/* Fournit le singleton associé à un registre de base ARMv7. */ +static GArchRegister *get_armv7_basic_register(uint8_t); + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION UNITAIRE DES REGISTRES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une représentation d'un registre de base ARMv7. */ +G_DEFINE_TYPE(GArmV7BasicRegister, g_armv7_basic_register, G_TYPE_ARMV7_REGISTER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des registres de base ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_basic_register_class_init(GArmV7BasicRegisterClass *klass) +{ + GObjectClass *object_class; /* Autre version de la classe */ + GArchRegisterClass *reg_class; /* Classe de haut niveau */ + + object_class = G_OBJECT_CLASS(klass); + reg_class = G_ARCH_REGISTER_CLASS(klass); + + object_class->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_basic_register_dispose; + object_class->finalize = (GObjectFinalizeFunc)g_armv7_basic_register_finalize; + + reg_class->print = (reg_print_fc)g_armv7_basic_register_print; + reg_class->unserialize = (reg_unserialize_fc)g_armv7_basic_register_unserialize; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance à initialiser. * +* * +* Description : Initialise une instance de registre de base ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_basic_register_init(GArmV7BasicRegister *reg) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_basic_register_dispose(GArmV7BasicRegister *reg) +{ + G_OBJECT_CLASS(g_armv7_basic_register_parent_class)->dispose(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_basic_register_finalize(GArmV7BasicRegister *reg) +{ + G_OBJECT_CLASS(g_armv7_basic_register_parent_class)->finalize(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à transcrire. * +* line = ligne tampon où imprimer l'opérande donné. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un registre en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_basic_register_print(const GArmV7BasicRegister *reg, GBufferLine *line, AsmSyntax syntax) +{ + char key[MAX_REGNAME_LEN]; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + + switch (G_ARM_REGISTER(reg)->index) + { + case 0 ... 10: + klen = snprintf(key, MAX_REGNAME_LEN, "r%hhu", G_ARM_REGISTER(reg)->index); + break; + case 11: + klen = snprintf(key, MAX_REGNAME_LEN, "fp"); + break; + case 12: + klen = snprintf(key, MAX_REGNAME_LEN, "ip"); + break; + case 13: + klen = snprintf(key, MAX_REGNAME_LEN, "sp"); + break; + case 14: + klen = snprintf(key, MAX_REGNAME_LEN, "lr"); + break; + case 15: + klen = snprintf(key, MAX_REGNAME_LEN, "pc"); + break; + case 16: + klen = snprintf(key, MAX_REGNAME_LEN, "cpsr"); + break; + case 17: + klen = snprintf(key, MAX_REGNAME_LEN, "spsr"); + break; + default: + klen = snprintf(key, MAX_REGNAME_LEN, "r??"); + break; + } + + g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : index = indice du registre correspondant. * +* * +* Description : Crée une réprésentation de registre de base ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *_g_armv7_basic_register_new(uint8_t index) +{ + GArmV7BasicRegister *result; /* Structure à retourner */ + + if (index > 17) + goto bad_index; + + result = g_object_new(G_TYPE_ARMV7_BASIC_REGISTER, NULL); + + G_ARM_REGISTER(result)->index = index; + + return G_ARCH_REGISTER(result); + + bad_index: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : index = indice du registre correspondant. * +* * +* Description : Crée une réprésentation de registre de base ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchRegister *g_armv7_basic_register_new(uint8_t index) +{ + GArchRegister *result; /* Structure à retourner */ + + result = get_armv7_basic_register(index); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un registre depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *g_armv7_basic_register_unserialize(GArmV7BasicRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + GArchRegister *result; /* Instance à retourner */ + uint8_t index; /* Indice du registre */ + bool status; /* Bilan d'une extraction */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + + if (status) + { + result = get_armv7_basic_register(index); + + if (result == NULL) + g_object_unref(G_OBJECT(reg)); + + } + + else + { + g_object_unref(G_OBJECT(reg)); + result = NULL; + } + + if (result != NULL) + { + parent = G_ARCH_REGISTER_CLASS(g_armv7_basic_register_parent_class); + + result = parent->unserialize(result, storage, pbuf); + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION SOUS FORME DE SINGLETONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : index = indice du registre correspondant. * +* * +* Description : Fournit le singleton associé à un registre de base ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *get_armv7_basic_register(uint8_t index) +{ + GArchRegister *result; /* Structure à retourner */ + size_t new_count; /* Nouvelle taille à considérer*/ + size_t i; /* Boucle de parcours */ + + G_LOCK(_av7_basic_reg_mutex); + + if (index >= _av7_basic_reg_count) + { + /** + * On valide déjà le fait que le registre puisse être créé + * avant de réaliser une allocation potentiellement énorme + * avec un indice démesuré. + */ + + result = _g_armv7_basic_register_new(index); + + if (result == NULL) + goto bad_index; + + new_count = index + 1; + + _armv7_basic_registers = realloc(_armv7_basic_registers, new_count * sizeof(GArchRegister *)); + + for (i = _av7_basic_reg_count; i < new_count; i++) + _armv7_basic_registers[i] = NULL; + + _av7_basic_reg_count = new_count; + + } + + else + result = NULL; + + if (_armv7_basic_registers[index] == NULL) + { + if (result != NULL) + _armv7_basic_registers[index] = result; + else + _armv7_basic_registers[index] = _g_armv7_basic_register_new(index); + } + + result = _armv7_basic_registers[index]; + + G_UNLOCK(_av7_basic_reg_mutex); + + g_object_ref(G_OBJECT(result)); + + bad_index: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Vide totalement le cache des registres de base ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void clean_armv7_basic_register_cache(void) +{ + size_t i; /* Boucle de parcours */ + + G_LOCK(_av7_basic_reg_mutex); + + for (i = 0; i < _av7_basic_reg_count; i++) + g_object_unref(G_OBJECT(_armv7_basic_registers[i])); + + if (_armv7_basic_registers != NULL) + free(_armv7_basic_registers); + + _armv7_basic_registers = NULL; + _av7_basic_reg_count = 0; + + G_UNLOCK(_av7_basic_reg_mutex); + +} diff --git a/plugins/arm/v7/registers/basic.h b/plugins/arm/v7/registers/basic.h new file mode 100644 index 0000000..bec4747 --- /dev/null +++ b/plugins/arm/v7/registers/basic.h @@ -0,0 +1,70 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * basic.h - prototypes pour les aides auxiliaires relatives aux registres de base ARMv7 + * + * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ARM_V7_REGISTERS_BASIC_H +#define _PLUGINS_ARM_V7_REGISTERS_BASIC_H + + +#include <glib-object.h> +#include <stdint.h> + + +#include <arch/register.h> + + + +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +#define G_TYPE_ARMV7_BASIC_REGISTER g_armv7_basic_register_get_type() +#define G_ARMV7_BASIC_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_BASIC_REGISTER, GArmV7BasicRegister)) +#define G_IS_ARMV7_BASIC_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_BASIC_REGISTER)) +#define G_ARMV7_BASIC_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_BASIC_REGISTER, GArmV7BasicRegisterClass)) +#define G_IS_ARMV7_BASIC_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_BASIC_REGISTER)) +#define G_ARMV7_BASIC_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_BASIC_REGISTER, GArmV7BasicRegisterClass)) + + +/* Représentation d'un registre de base ARMv7 (instance) */ +typedef struct _GArmV7BasicRegister GArmV7BasicRegister; + +/* Représentation d'un registre de base ARMv7 (classe) */ +typedef struct _GArmV7BasicRegisterClass GArmV7BasicRegisterClass; + + +/* Indique le type défini pour une représentation d'un registre de base ARMv7. */ +GType g_armv7_basic_register_get_type(void); + +/* Crée une réprésentation de registre de base ARMv7. */ +GArchRegister *g_armv7_basic_register_new(uint8_t); + + + +/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ + + +/* Vide totalement le cache des registres de base ARMv7. */ +void clean_armv7_basic_register_cache(void); + + + +#endif /* _PLUGINS_ARM_V7_REGISTERS_BASIC_H */ diff --git a/plugins/arm/v7/cregister.c b/plugins/arm/v7/registers/coproc.c index 7b39e02..f1dc3bc 100644 --- a/plugins/arm/v7/cregister.c +++ b/plugins/arm/v7/registers/coproc.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * cregisters.c - aides auxiliaires relatives aux registres de co-processeur ARMv7 + * coproc.c - aides auxiliaires relatives aux registres de co-processeur ARMv7 * * Copyright (C) 2016-2017 Cyrille Bagard * @@ -21,7 +21,7 @@ */ -#include "cregister.h" +#include "coproc.h" #include <stdio.h> @@ -35,39 +35,49 @@ /* Représentation d'un registre de co-processeur ARMv7 (instance) */ -struct _GArmV7CRegister +struct _GArmV7CpRegister { - GArmRegister parent; /* Instance parente */ + GArmV7Register parent; /* Instance parente */ }; /* Représentation d'un registre de co-processeur ARMv7 (classe) */ -struct _GArmV7CRegisterClass +struct _GArmV7CpRegisterClass { - GArmRegisterClass parent; /* Classe parente */ + GArmV7RegisterClass parent; /* Classe parente */ }; +#define MAX_REGNAME_LEN 5 + /* Initialise la classe des registres de co-processeur ARMv7. */ -static void g_armv7_cregister_class_init(GArmV7CRegisterClass *); +static void g_armv7_cp_register_class_init(GArmV7CpRegisterClass *); /* Initialise une instance de registre de co-processeur ARMv7. */ -static void g_armv7_cregister_init(GArmV7CRegister *); +static void g_armv7_cp_register_init(GArmV7CpRegister *); /* Supprime toutes les références externes. */ -static void g_armv7_cregister_dispose(GArmV7CRegister *); +static void g_armv7_cp_register_dispose(GArmV7CpRegister *); /* Procède à la libération totale de la mémoire. */ -static void g_armv7_cregister_finalize(GArmV7CRegister *); +static void g_armv7_cp_register_finalize(GArmV7CpRegister *); /* Traduit un registre en version humainement lisible. */ -static void g_armv7_cregister_print(const GArmV7CRegister *, GBufferLine *, AsmSyntax); +static void g_armv7_cp_register_print(const GArmV7CpRegister *, GBufferLine *, AsmSyntax); /* Crée une réprésentation de registre de co-processeur ARMv7. */ -static GArmV7CRegister *_g_armv7_cregister_new(uint8_t); +static GArchRegister *_g_armv7_cp_register_new(uint8_t); + + + +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ + + +/* Charge un registre depuis une mémoire tampon. */ +static GArchRegister *g_armv7_cp_register_unserialize(GArmV7CpRegister *, GAsmStorage *, packed_buffer *); @@ -75,18 +85,23 @@ static GArmV7CRegister *_g_armv7_cregister_new(uint8_t); /* Conservation des registres utilisés */ -static GArmV7CRegister **_armv7_cregisters = NULL; -static size_t _av7creg_count = 0; -G_LOCK_DEFINE_STATIC(_av7creg_mutex); +static GArchRegister **_armv7_cp_registers = NULL; +static size_t _av7_cp_reg_count = 0; +G_LOCK_DEFINE_STATIC(_av7_cp_reg_mutex); /* Fournit le singleton associé à un registre de co-proc. ARMv7. */ -static GArmV7CRegister *get_armv7_cregister(uint8_t); +static GArchRegister *get_armv7_cp_register(uint8_t); + +/* ---------------------------------------------------------------------------------- */ +/* GESTION UNITAIRE DES REGISTRES */ +/* ---------------------------------------------------------------------------------- */ + /* Indique le type défini pour une représentation d'un registre de co-processeur ARMv7. */ -G_DEFINE_TYPE(GArmV7CRegister, g_armv7_cregister, G_TYPE_ARM_REGISTER); +G_DEFINE_TYPE(GArmV7CpRegister, g_armv7_cp_register, G_TYPE_ARMV7_REGISTER); /****************************************************************************** @@ -101,7 +116,7 @@ G_DEFINE_TYPE(GArmV7CRegister, g_armv7_cregister, G_TYPE_ARM_REGISTER); * * ******************************************************************************/ -static void g_armv7_cregister_class_init(GArmV7CRegisterClass *klass) +static void g_armv7_cp_register_class_init(GArmV7CpRegisterClass *klass) { GObjectClass *object_class; /* Autre version de la classe */ GArchRegisterClass *reg_class; /* Classe de haut niveau */ @@ -109,10 +124,11 @@ static void g_armv7_cregister_class_init(GArmV7CRegisterClass *klass) object_class = G_OBJECT_CLASS(klass); reg_class = G_ARCH_REGISTER_CLASS(klass); - object_class->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_cregister_dispose; - object_class->finalize = (GObjectFinalizeFunc)g_armv7_cregister_finalize; + object_class->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_cp_register_dispose; + object_class->finalize = (GObjectFinalizeFunc)g_armv7_cp_register_finalize; - reg_class->print = (reg_print_fc)g_armv7_cregister_print; + reg_class->print = (reg_print_fc)g_armv7_cp_register_print; + reg_class->unserialize = (reg_unserialize_fc)g_armv7_cp_register_unserialize; } @@ -129,7 +145,7 @@ static void g_armv7_cregister_class_init(GArmV7CRegisterClass *klass) * * ******************************************************************************/ -static void g_armv7_cregister_init(GArmV7CRegister *reg) +static void g_armv7_cp_register_init(GArmV7CpRegister *reg) { } @@ -147,9 +163,9 @@ static void g_armv7_cregister_init(GArmV7CRegister *reg) * * ******************************************************************************/ -static void g_armv7_cregister_dispose(GArmV7CRegister *reg) +static void g_armv7_cp_register_dispose(GArmV7CpRegister *reg) { - G_OBJECT_CLASS(g_armv7_cregister_parent_class)->dispose(G_OBJECT(reg)); + G_OBJECT_CLASS(g_armv7_cp_register_parent_class)->dispose(G_OBJECT(reg)); } @@ -166,9 +182,9 @@ static void g_armv7_cregister_dispose(GArmV7CRegister *reg) * * ******************************************************************************/ -static void g_armv7_cregister_finalize(GArmV7CRegister *reg) +static void g_armv7_cp_register_finalize(GArmV7CpRegister *reg) { - G_OBJECT_CLASS(g_armv7_cregister_parent_class)->finalize(G_OBJECT(reg)); + G_OBJECT_CLASS(g_armv7_cp_register_parent_class)->finalize(G_OBJECT(reg)); } @@ -187,7 +203,7 @@ static void g_armv7_cregister_finalize(GArmV7CRegister *reg) * * ******************************************************************************/ -static void g_armv7_cregister_print(const GArmV7CRegister *reg, GBufferLine *line, AsmSyntax syntax) +static void g_armv7_cp_register_print(const GArmV7CpRegister *reg, GBufferLine *line, AsmSyntax syntax) { char key[MAX_REGNAME_LEN]; /* Mot clef principal */ size_t klen; /* Taille de ce mot clef */ @@ -195,10 +211,10 @@ static void g_armv7_cregister_print(const GArmV7CRegister *reg, GBufferLine *lin switch (G_ARM_REGISTER(reg)->index) { case 0 ... 15: - klen = snprintf(key, MAX_REGNAME_LEN, "c%hhu", G_ARM_REGISTER(reg)->index); + klen = snprintf(key, MAX_REGNAME_LEN, "cp%hhu", G_ARM_REGISTER(reg)->index); break; default: - klen = snprintf(key, MAX_REGNAME_LEN, "c??"); + klen = snprintf(key, MAX_REGNAME_LEN, "cp??"); break; } @@ -219,15 +235,22 @@ static void g_armv7_cregister_print(const GArmV7CRegister *reg, GBufferLine *lin * * ******************************************************************************/ -static GArmV7CRegister *_g_armv7_cregister_new(uint8_t index) +static GArchRegister *_g_armv7_cp_register_new(uint8_t index) { - GArmV7CRegister *result; /* Structure à retourner */ + GArmV7CpRegister *result; /* Structure à retourner */ + + if (index > 15) + goto bad_index; - result = g_object_new(G_TYPE_ARMV7_CREGISTER, NULL); + result = g_object_new(G_TYPE_ARMV7_CP_REGISTER, NULL); G_ARM_REGISTER(result)->index = index; - return result; + return G_ARCH_REGISTER(result); + + bad_index: + + return NULL; } @@ -244,11 +267,68 @@ static GArmV7CRegister *_g_armv7_cregister_new(uint8_t index) * * ******************************************************************************/ -GArmV7CRegister *g_armv7_cregister_new(uint8_t index) +GArchRegister *g_armv7_cp_register_new(uint8_t index) +{ + GArchRegister *result; /* Structure à retourner */ + + result = get_armv7_cp_register(index); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un registre depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *g_armv7_cp_register_unserialize(GArmV7CpRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) { - GArmV7CRegister *result; /* Structure à retourner */ + GArchRegister *result; /* Instance à retourner */ + uint8_t index; /* Indice du registre */ + bool status; /* Bilan d'une extraction */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + + if (status) + { + result = get_armv7_cp_register(index); + + if (result == NULL) + g_object_unref(G_OBJECT(reg)); + + } - result = get_armv7_cregister(index); + else + { + g_object_unref(G_OBJECT(reg)); + result = NULL; + } + + if (result != NULL) + { + parent = G_ARCH_REGISTER_CLASS(g_armv7_cp_register_parent_class); + + result = parent->unserialize(result, storage, pbuf); + + } return result; @@ -273,36 +353,57 @@ GArmV7CRegister *g_armv7_cregister_new(uint8_t index) * * ******************************************************************************/ -static GArmV7CRegister *get_armv7_cregister(uint8_t index) +static GArchRegister *get_armv7_cp_register(uint8_t index) { - GArmV7CRegister *result; /* Structure à retourner */ + GArchRegister *result; /* Structure à retourner */ size_t new_count; /* Nouvelle taille à considérer*/ size_t i; /* Boucle de parcours */ - G_LOCK(_av7creg_mutex); + G_LOCK(_av7_cp_reg_mutex); - if (index >= _av7creg_count) + if (index >= _av7_cp_reg_count) { + /** + * On valide déjà le fait que le registre puisse être créé + * avant de réaliser une allocation potentiellement énorme + * avec un indice démesuré. + */ + + result = _g_armv7_cp_register_new(index); + + if (result == NULL) + goto bad_index; + new_count = index + 1; - _armv7_cregisters = realloc(_armv7_cregisters, new_count * sizeof(GArmV7CRegister *)); + _armv7_cp_registers = realloc(_armv7_cp_registers, new_count * sizeof(GArchRegister *)); - for (i = _av7creg_count; i < new_count; i++) - _armv7_cregisters[i] = NULL; + for (i = _av7_cp_reg_count; i < new_count; i++) + _armv7_cp_registers[i] = NULL; - _av7creg_count = new_count; + _av7_cp_reg_count = new_count; } - if (_armv7_cregisters[index] == NULL) - _armv7_cregisters[index] = _g_armv7_cregister_new(index); + else + result = NULL; - result = _armv7_cregisters[index]; + if (_armv7_cp_registers[index] == NULL) + { + if (result != NULL) + _armv7_cp_registers[index] = result; + else + _armv7_cp_registers[index] = _g_armv7_cp_register_new(index); + } + + result = _armv7_cp_registers[index]; - G_UNLOCK(_av7creg_mutex); + G_UNLOCK(_av7_cp_reg_mutex); g_object_ref(G_OBJECT(result)); + bad_index: + return result; } @@ -320,21 +421,21 @@ static GArmV7CRegister *get_armv7_cregister(uint8_t index) * * ******************************************************************************/ -void clean_armv7_cregister_cache(void) +void clean_armv7_cp_register_cache(void) { size_t i; /* Boucle de parcours */ - G_LOCK(_av7creg_mutex); + G_LOCK(_av7_cp_reg_mutex); - for (i = 0; i < _av7creg_count; i++) - g_object_unref(G_OBJECT(_armv7_cregisters[i])); + for (i = 0; i < _av7_cp_reg_count; i++) + g_object_unref(G_OBJECT(_armv7_cp_registers[i])); - if (_armv7_cregisters != NULL) - free(_armv7_cregisters); + if (_armv7_cp_registers != NULL) + free(_armv7_cp_registers); - _armv7_cregisters = NULL; - _av7creg_count = 0; + _armv7_cp_registers = NULL; + _av7_cp_reg_count = 0; - G_UNLOCK(_av7creg_mutex); + G_UNLOCK(_av7_cp_reg_mutex); } diff --git a/plugins/arm/v7/cregister.h b/plugins/arm/v7/registers/coproc.h index 857c11d..200b721 100644 --- a/plugins/arm/v7/cregister.h +++ b/plugins/arm/v7/registers/coproc.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * cregisters.h - prototypes pour les aides auxiliaires relatives aux registres de co-processeur ARMv7 + * coproc.h - prototypes pour les aides auxiliaires relatives aux registres de co-processeur ARMv7 * * Copyright (C) 2016-2017 Cyrille Bagard * @@ -21,47 +21,50 @@ */ -#ifndef _PLUGINS_ARM_V7_CREGISTER_H -#define _PLUGINS_ARM_V7_CREGISTER_H +#ifndef _PLUGINS_ARM_V7_REGISTERS_COPROC_H +#define _PLUGINS_ARM_V7_REGISTERS_COPROC_H #include <glib-object.h> #include <stdint.h> +#include <arch/register.h> + + /* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ -#define G_TYPE_ARMV7_CREGISTER g_armv7_cregister_get_type() -#define G_ARMV7_CREGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_cregister_get_type(), GArmV7CRegister)) -#define G_IS_ARMV7_CREGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_cregister_get_type())) -#define G_ARMV7_CREGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_CREGISTER, GArmV7CRegisterClass)) -#define G_IS_ARMV7_CREGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_CREGISTER)) -#define G_ARMV7_CREGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_CREGISTER, GArmV7CRegisterClass)) +#define G_TYPE_ARMV7_CP_REGISTER g_armv7_cp_register_get_type() +#define G_ARMV7_CP_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_CP_REGISTER, GArmV7CpRegister)) +#define G_IS_ARMV7_CP_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_CP_REGISTER)) +#define G_ARMV7_CP_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_CP_REGISTER, GArmV7CpRegisterClass)) +#define G_IS_ARMV7_CP_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_CP_REGISTER)) +#define G_ARMV7_CP_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_CP_REGISTER, GArmV7CpRegisterClass)) /* Représentation d'un registre de co-processeur ARMv7 (instance) */ -typedef struct _GArmV7CRegister GArmV7CRegister; +typedef struct _GArmV7CpRegister GArmV7CpRegister; /* Représentation d'un registre de co-processeur ARMv7 (classe) */ -typedef struct _GArmV7CRegisterClass GArmV7CRegisterClass; +typedef struct _GArmV7CpRegisterClass GArmV7CpRegisterClass; /* Indique le type défini pour une représentation d'un registre de co-processeur ARMv7. */ -GType g_armv7_cregister_get_type(void); +GType g_armv7_cp_register_get_type(void); /* Crée une réprésentation de registre de co-processeur ARMv7. */ -GArmV7CRegister *g_armv7_cregister_new(uint8_t); +GArchRegister *g_armv7_cp_register_new(uint8_t); /* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ -/* Vide totalement le cache des registres ARMv7. */ -void clean_armv7_cregister_cache(void); +/* Vide totalement le cache des registres de co-processeur ARMv7. */ +void clean_armv7_cp_register_cache(void); -#endif /* _PLUGINS_ARM_V7_CREGISTER_H */ +#endif /* _PLUGINS_ARM_V7_REGISTERS_COPROC_H */ diff --git a/plugins/arm/v7/registers/simd.c b/plugins/arm/v7/registers/simd.c new file mode 100644 index 0000000..1a71fc7 --- /dev/null +++ b/plugins/arm/v7/registers/simd.c @@ -0,0 +1,534 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * simd.c - aides auxiliaires relatives aux registres SIMD ARMv7 + * + * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "simd.h" + + +#include <assert.h> +#include <stdio.h> + + +#include "../register-int.h" + + + +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +/* Représentation d'un registre ARMv7 (instance) */ +struct _GArmV7SIMDRegister +{ + GArmV7Register parent; /* Instance parente */ + + SIMDRegisterMapping mapping; /* Type de registre */ + +}; + +/* Représentation d'un registre ARMv7 (classe) */ +struct _GArmV7SIMDRegisterClass +{ + GArmV7RegisterClass parent; /* Classe parente */ + +}; + + +#define MAX_REGNAME_LEN 4 + + +/* Initialise la classe des registres SIMD ARMv7. */ +static void g_armv7_simd_register_class_init(GArmV7SIMDRegisterClass *); + +/* Initialise une instance de registre SIMD ARMv7. */ +static void g_armv7_simd_register_init(GArmV7SIMDRegister *); + +/* Supprime toutes les références externes. */ +static void g_armv7_simd_register_dispose(GArmV7SIMDRegister *); + +/* Procède à la libération totale de la mémoire. */ +static void g_armv7_simd_register_finalize(GArmV7SIMDRegister *); + +/* Traduit un registre en version humainement lisible. */ +static void g_armv7_simd_register_print(const GArmV7SIMDRegister *, GBufferLine *, AsmSyntax); + +/* Crée une réprésentation de registre SIMD ARMv7. */ +static GArchRegister *_g_armv7_simd_register_new(SIMDRegisterMapping, uint8_t); + + + +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ + + +/* Charge un registre depuis une mémoire tampon. */ +static GArchRegister *g_armv7_simd_register_unserialize(GArmV7SIMDRegister *, GAsmStorage *, packed_buffer *); + +/* Sauvegarde un registre dans une mémoire tampon. */ +static bool g_armv7_simd_register_serialize(const GArmV7SIMDRegister *, GAsmStorage *, packed_buffer *); + + + +/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ + + +/* Conservation des registres utilisés */ +static GArchRegister **_armv7_simd_registers[SRM_COUNT] = { NULL, NULL, NULL }; +static size_t _av7_simd_reg_count[SRM_COUNT] = { 0, 0, 0 }; +G_LOCK_DEFINE_STATIC(_av7_simd_reg_mutex); + + +/* Fournit le singleton associé à un registre SIMD ARMv7. */ +static GArchRegister *get_armv7_simd_register(SIMDRegisterMapping, uint8_t); + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION UNITAIRE DES REGISTRES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une représentation d'un registre SIMD ARMv7. */ +G_DEFINE_TYPE(GArmV7SIMDRegister, g_armv7_simd_register, G_TYPE_ARMV7_REGISTER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des registres SIMD ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_simd_register_class_init(GArmV7SIMDRegisterClass *klass) +{ + GObjectClass *object_class; /* Autre version de la classe */ + GArchRegisterClass *reg_class; /* Classe de haut niveau */ + + object_class = G_OBJECT_CLASS(klass); + + object_class->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_simd_register_dispose; + object_class->finalize = (GObjectFinalizeFunc)g_armv7_simd_register_finalize; + + reg_class = G_ARCH_REGISTER_CLASS(klass); + + reg_class->print = (reg_print_fc)g_armv7_simd_register_print; + reg_class->unserialize = (reg_unserialize_fc)g_armv7_simd_register_unserialize; + reg_class->serialize = (reg_serialize_fc)g_armv7_simd_register_serialize; + + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance à initialiser. * +* * +* Description : Initialise une instance de registre SIMD ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_simd_register_init(GArmV7SIMDRegister *reg) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_simd_register_dispose(GArmV7SIMDRegister *reg) +{ + G_OBJECT_CLASS(g_armv7_simd_register_parent_class)->dispose(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_simd_register_finalize(GArmV7SIMDRegister *reg) +{ + G_OBJECT_CLASS(g_armv7_simd_register_parent_class)->finalize(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à transcrire. * +* line = ligne tampon où imprimer l'opérande donné. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un registre en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_simd_register_print(const GArmV7SIMDRegister *reg, GBufferLine *line, AsmSyntax syntax) +{ + char key[MAX_REGNAME_LEN]; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + + switch (reg->mapping) + { + case SRM_SINGLE_WORD: + klen = snprintf(key, MAX_REGNAME_LEN, "s%hhu", G_ARM_REGISTER(reg)->index); + break; + + case SRM_DOUBLE_WORD: + klen = snprintf(key, MAX_REGNAME_LEN, "d%hhu", G_ARM_REGISTER(reg)->index); + break; + + case SRM_QUAD_WORD: + klen = snprintf(key, MAX_REGNAME_LEN, "q%hhu", G_ARM_REGISTER(reg)->index); + break; + + default: + assert(false); + klen = snprintf(key, MAX_REGNAME_LEN, "x??"); + break; + + } + + g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : mapping = type de registre demandé. * +* index = indice du registre correspondant. * +* * +* Description : Crée une réprésentation de registre SIMD ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *_g_armv7_simd_register_new(SIMDRegisterMapping mapping, uint8_t index) +{ + GArmV7SIMDRegister *result; /* Structure à retourner */ + uint8_t max; /* Borne supérieure de limite */ + + switch (mapping) + { + case SRM_SINGLE_WORD: + max = 31; + break; + + case SRM_DOUBLE_WORD: + max = 31; + break; + + case SRM_QUAD_WORD: + max = 15; + break; + + default: + assert(false); + goto bad_mapping; + break; + + } + + if (index > max) + goto bad_index; + + result = g_object_new(G_TYPE_ARMV7_SIMD_REGISTER, NULL); + + G_ARM_REGISTER(result)->index = index; + + result->mapping = mapping; + + return G_ARCH_REGISTER(result); + + bad_mapping: + bad_index: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : mapping = type de registre demandé. * +* index = indice du registre correspondant. * +* * +* Description : Crée une réprésentation de registre SIMD ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchRegister *g_armv7_simd_register_new(SIMDRegisterMapping mapping, uint8_t index) +{ + GArchRegister *result; /* Structure à retourner */ + + result = get_armv7_simd_register(mapping, index); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un registre depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *g_armv7_simd_register_unserialize(GArmV7SIMDRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + GArchRegister *result; /* Instance à retourner */ + SIMDRegisterMapping mapping; /* Type de registre */ + bool status; /* Bilan d'une extraction */ + uint8_t index; /* Indice du registre */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + status = extract_packed_buffer(pbuf, &mapping, sizeof(SIMDRegisterMapping), true); + + if (status) + status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + + if (status) + { + result = get_armv7_simd_register(mapping, index); + + if (result == NULL) + g_object_unref(G_OBJECT(reg)); + + } + + else + { + g_object_unref(G_OBJECT(reg)); + result = NULL; + } + + if (result != NULL) + { + parent = G_ARCH_REGISTER_CLASS(g_armv7_simd_register_parent_class); + + result = parent->unserialize(G_ARCH_REGISTER(reg), storage, pbuf); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un registre dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_simd_register_serialize(const GArmV7SIMDRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + result = extend_packed_buffer(pbuf, ®->mapping, sizeof(SIMDRegisterMapping), true); + + if (result) + { + parent = G_ARCH_REGISTER_CLASS(g_armv7_simd_register_parent_class); + + result = parent->serialize(G_ARCH_REGISTER(reg), storage, pbuf); + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION SOUS FORME DE SINGLETONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : mapping = type de registre demandé. * +* index = indice du registre correspondant. * +* * +* Description : Fournit le singleton associé à un registre SIMD ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *get_armv7_simd_register(SIMDRegisterMapping mapping, uint8_t index) +{ + GArchRegister *result; /* Structure à retourner */ + size_t new_count; /* Nouvelle taille à considérer*/ + size_t i; /* Boucle de parcours */ + + assert(mapping < SRM_COUNT); + + G_LOCK(_av7_simd_reg_mutex); + + if (index >= _av7_simd_reg_count[mapping]) + { + /** + * On valide déjà le fait que le registre puisse être créé + * avant de réaliser une allocation potentiellement énorme + * avec un indice démesuré. + */ + + result = _g_armv7_simd_register_new(mapping, index); + + if (result == NULL) + goto bad_index; + + new_count = index + 1; + + _armv7_simd_registers[mapping] = realloc(_armv7_simd_registers[mapping], + new_count * sizeof(GArchRegister *)); + + for (i = _av7_simd_reg_count[mapping]; i < new_count; i++) + _armv7_simd_registers[mapping][i] = NULL; + + _av7_simd_reg_count[mapping] = new_count; + + } + + else + result = NULL; + + if (_armv7_simd_registers[mapping][index] == NULL) + { + if (result != NULL) + _armv7_simd_registers[mapping][index] = result; + else + _armv7_simd_registers[mapping][index] = _g_armv7_simd_register_new(mapping, index); + } + + result = _armv7_simd_registers[mapping][index]; + + G_UNLOCK(_av7_simd_reg_mutex); + + g_object_ref(G_OBJECT(result)); + + bad_index: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Vide totalement le cache des registres SIMD ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void clean_armv7_simd_register_cache(void) +{ + SIMDRegisterMapping i; /* Boucle de parcours #1 */ + size_t k; /* Boucle de parcours #2 */ + + G_LOCK(_av7_simd_reg_mutex); + + for (i = 0; i < SRM_COUNT; i++) + { + for (k = 0; k < _av7_simd_reg_count[i]; k++) + g_object_unref(G_OBJECT(_armv7_simd_registers[i][k])); + + if (_armv7_simd_registers[i] != NULL) + free(_armv7_simd_registers[i]); + + _armv7_simd_registers[i] = NULL; + _av7_simd_reg_count[i] = 0; + + } + + G_UNLOCK(_av7_simd_reg_mutex); + +} diff --git a/plugins/arm/v7/registers/simd.h b/plugins/arm/v7/registers/simd.h new file mode 100644 index 0000000..9d731ac --- /dev/null +++ b/plugins/arm/v7/registers/simd.h @@ -0,0 +1,82 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * simd.h - prototypes pour les aides auxiliaires relatives aux registres SIMD ARMv7 + * + * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ARM_V7_REGISTERS_SIMD_H +#define _PLUGINS_ARM_V7_REGISTERS_SIMD_H + + +#include <glib-object.h> +#include <stdint.h> + + +#include <arch/register.h> + + + +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +#define G_TYPE_ARMV7_SIMD_REGISTER g_armv7_simd_register_get_type() +#define G_ARMV7_SIMD_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_SIMD_REGISTER, GArmV7SIMDRegister)) +#define G_IS_ARMV7_SIMD_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_SIMD_REGISTER)) +#define G_ARMV7_SIMD_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_SIMD_REGISTER, GArmV7SIMDRegisterClass)) +#define G_IS_ARMV7_SIMD_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_SIMD_REGISTER)) +#define G_ARMV7_SIMD_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_SIMD_REGISTER, GArmV7SIMDRegisterClass)) + + +/* Représentation d'un registre SIMD ARMv7 (instance) */ +typedef struct _GArmV7SIMDRegister GArmV7SIMDRegister; + +/* Représentation d'un registre SIMD ARMv7 (classe) */ +typedef struct _GArmV7SIMDRegisterClass GArmV7SIMDRegisterClass; + + +/* Types de registre */ +typedef enum _SIMDRegisterMapping +{ + SRM_SINGLE_WORD, /* Simple mot */ + SRM_DOUBLE_WORD, /* Double mot */ + SRM_QUAD_WORD, /* Quadruple mot */ + + SRM_COUNT + +} SIMDRegisterMapping; + + +/* Indique le type défini pour une représentation d'un registre SIMD ARMv7. */ +GType g_armv7_simd_register_get_type(void); + +/* Crée une réprésentation de registre SIMD ARMv7. */ +GArchRegister *g_armv7_simd_register_new(SIMDRegisterMapping, uint8_t); + + + +/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ + + +/* Vide totalement le cache des registres SIMD ARMv7. */ +void clean_armv7_simd_register_cache(void); + + + +#endif /* _PLUGINS_ARM_V7_REGISTERS_SIMD_H */ diff --git a/plugins/arm/v7/registers/special.c b/plugins/arm/v7/registers/special.c new file mode 100644 index 0000000..ce3d859 --- /dev/null +++ b/plugins/arm/v7/registers/special.c @@ -0,0 +1,485 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * special.c - aides auxiliaires relatives aux registres spéciaux ARMv7 + * + * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "special.h" + + +#include <stdio.h> + + +#include "../register-int.h" + + + +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +/* Représentation d'un registre spécial ARMv7 (instance) */ +struct _GArmV7SpecialRegister +{ + GArmV7Register parent; /* Instance parente */ + +}; + +/* Représentation d'un registre spécial ARMv7 (classe) */ +struct _GArmV7SpecialRegisterClass +{ + GArmV7RegisterClass parent; /* Classe parente - */ + +}; + + +#define MAX_REGNAME_LEN 12 + + +/* Initialise la classe des registres spéciaux ARMv7. */ +static void g_armv7_special_register_class_init(GArmV7SpecialRegisterClass *); + +/* Initialise une instance de registre spécial ARMv7. */ +static void g_armv7_special_register_init(GArmV7SpecialRegister *); + +/* Supprime toutes les références externes. */ +static void g_armv7_special_register_dispose(GArmV7SpecialRegister *); + +/* Procède à la libération totale de la mémoire. */ +static void g_armv7_special_register_finalize(GArmV7SpecialRegister *); + +/* Traduit un registre en version humainement lisible. */ +static void g_armv7_special_register_print(const GArmV7SpecialRegister *, GBufferLine *, AsmSyntax); + +/* Crée une réprésentation de registre spécial ARMv7. */ +static GArchRegister *_g_armv7_special_register_new(SpecRegTarget); + + + +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ + + +/* Charge un registre depuis une mémoire tampon. */ +static GArchRegister *g_armv7_special_register_unserialize(GArmV7SpecialRegister *, GAsmStorage *, packed_buffer *); + + + +/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ + + +/* Conservation des registres utilisés */ +static GArchRegister **_armv7_special_registers = NULL; +static size_t _av7_special_reg_count = 0; +G_LOCK_DEFINE_STATIC(_av7_special_reg_mutex); + + +/* Fournit le singleton associé à un registre spécial ARMv7. */ +static GArchRegister *get_armv7_special_register(SpecRegTarget); + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION UNITAIRE DES REGISTRES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une représentation d'un registre spécial ARMv7. */ +G_DEFINE_TYPE(GArmV7SpecialRegister, g_armv7_special_register, G_TYPE_ARMV7_REGISTER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des registres spéciaux ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_special_register_class_init(GArmV7SpecialRegisterClass *klass) +{ + GObjectClass *object_class; /* Autre version de la classe */ + GArchRegisterClass *reg_class; /* Classe de haut niveau */ + + object_class = G_OBJECT_CLASS(klass); + reg_class = G_ARCH_REGISTER_CLASS(klass); + + object_class->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_special_register_dispose; + object_class->finalize = (GObjectFinalizeFunc)g_armv7_special_register_finalize; + + reg_class->print = (reg_print_fc)g_armv7_special_register_print; + reg_class->unserialize = (reg_unserialize_fc)g_armv7_special_register_unserialize; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance à initialiser. * +* * +* Description : Initialise une instance de registre spécial ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_special_register_init(GArmV7SpecialRegister *reg) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_special_register_dispose(GArmV7SpecialRegister *reg) +{ + G_OBJECT_CLASS(g_armv7_special_register_parent_class)->dispose(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_special_register_finalize(GArmV7SpecialRegister *reg) +{ + G_OBJECT_CLASS(g_armv7_special_register_parent_class)->finalize(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à transcrire. * +* line = ligne tampon où imprimer l'opérande donné. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un registre en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_special_register_print(const GArmV7SpecialRegister *reg, GBufferLine *line, AsmSyntax syntax) +{ + SpecRegTarget target; /* Registre ciblé */ + char key[MAX_REGNAME_LEN]; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + + target = G_ARM_REGISTER(reg)->index; + + switch (target) + { + case SRT_APSR: + klen = snprintf(key, MAX_REGNAME_LEN, "APSR"); + break; + + case SRT_CPSR: + klen = snprintf(key, MAX_REGNAME_LEN, "CPSR"); + break; + + case SRT_SPSR: + klen = snprintf(key, MAX_REGNAME_LEN, "SPSR"); + break; + + case SRT_APSR_NZCVQ: + klen = snprintf(key, MAX_REGNAME_LEN, "APSR_nzcvq"); + break; + + case SRT_APSR_G: + klen = snprintf(key, MAX_REGNAME_LEN, "APSR_g"); + break; + + case SRT_APSR_NZCVQG: + klen = snprintf(key, MAX_REGNAME_LEN, "APSR_nzcvqg"); + break; + + case SRT_FPSID: + klen = snprintf(key, MAX_REGNAME_LEN, "FPSID"); + break; + + case SRT_FPSCR: + klen = snprintf(key, MAX_REGNAME_LEN, "FPSCR"); + break; + + case SRT_MVFR1: + klen = snprintf(key, MAX_REGNAME_LEN, "MVFR1"); + break; + + case SRT_MVFR0: + klen = snprintf(key, MAX_REGNAME_LEN, "MVFR0"); + break; + + case SRT_FPEXC: + klen = snprintf(key, MAX_REGNAME_LEN, "FPEXC"); + break; + + default: + klen = snprintf(key, MAX_REGNAME_LEN, "???"); + break; + + } + + g_buffer_line_append_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER, NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : target = registre effectivement ciblé. * +* * +* Description : Crée une réprésentation de registre spécial ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *_g_armv7_special_register_new(SpecRegTarget target) +{ + GArmV7SpecialRegister *result; /* Structure à retourner */ + + if (target >= SRT_CPSR) + goto bad_index; + + result = g_object_new(G_TYPE_ARMV7_SPECIAL_REGISTER, NULL); + + G_ARM_REGISTER(result)->index = target; + + return G_ARCH_REGISTER(result); + + bad_index: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : target = registre effectivement ciblé. * +* * +* Description : Crée une réprésentation de registre spécial ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchRegister *g_armv7_special_register_new(SpecRegTarget target) +{ + GArchRegister *result; /* Structure à retourner */ + + result = get_armv7_special_register(target); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un registre depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *g_armv7_special_register_unserialize(GArmV7SpecialRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + GArchRegister *result; /* Instance à retourner */ + uint8_t index; /* Indice du registre */ + bool status; /* Bilan d'une extraction */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + status = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + + if (status) + { + result = get_armv7_special_register(index); + + if (result == NULL) + g_object_unref(G_OBJECT(reg)); + + } + + else + { + g_object_unref(G_OBJECT(reg)); + result = NULL; + } + + if (result != NULL) + { + parent = G_ARCH_REGISTER_CLASS(g_armv7_special_register_parent_class); + + result = parent->unserialize(result, storage, pbuf); + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION SOUS FORME DE SINGLETONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : target = registre effectivement ciblé. * +* * +* Description : Fournit le singleton associé à un registre spécial ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *get_armv7_special_register(SpecRegTarget target) +{ + GArchRegister *result; /* Structure à retourner */ + size_t new_count; /* Nouvelle taille à considérer*/ + size_t i; /* Boucle de parcours */ + + G_LOCK(_av7_special_reg_mutex); + + if (target >= _av7_special_reg_count) + { + /** + * On valide déjà le fait que le registre puisse être créé + * avant de réaliser une allocation potentiellement énorme + * avec un indice démesuré. + */ + + result = _g_armv7_special_register_new(target); + + if (result == NULL) + goto bad_index; + + new_count = target + 1; + + _armv7_special_registers = realloc(_armv7_special_registers, new_count * sizeof(GArchRegister *)); + + for (i = _av7_special_reg_count; i < new_count; i++) + _armv7_special_registers[i] = NULL; + + _av7_special_reg_count = new_count; + + } + + else + result = NULL; + + if (_armv7_special_registers[target] == NULL) + { + if (result != NULL) + _armv7_special_registers[target] = result; + else + _armv7_special_registers[target] = _g_armv7_special_register_new(target); + } + + result = _armv7_special_registers[target]; + + G_UNLOCK(_av7_special_reg_mutex); + + g_object_ref(G_OBJECT(result)); + + bad_index: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Vide totalement le cache des registres spéciaux ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void clean_armv7_special_register_cache(void) +{ + size_t i; /* Boucle de parcours */ + + G_LOCK(_av7_special_reg_mutex); + + for (i = 0; i < _av7_special_reg_count; i++) + g_object_unref(G_OBJECT(_armv7_special_registers[i])); + + if (_armv7_special_registers != NULL) + free(_armv7_special_registers); + + _armv7_special_registers = NULL; + _av7_special_reg_count = 0; + + G_UNLOCK(_av7_special_reg_mutex); + +} diff --git a/plugins/arm/v7/registers/special.h b/plugins/arm/v7/registers/special.h new file mode 100644 index 0000000..ef23a9a --- /dev/null +++ b/plugins/arm/v7/registers/special.h @@ -0,0 +1,90 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * special.h - prototypes pour les aides auxiliaires relatives aux registres spéciaux ARMv7 + * + * Copyright (C) 2018 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_ARM_V7_REGISTERS_SPECIAL_H +#define _PLUGINS_ARM_V7_REGISTERS_SPECIAL_H + + +#include <glib-object.h> +#include <stdint.h> + + +#include <arch/register.h> + + + +/* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ + + +#define G_TYPE_ARMV7_SPECIAL_REGISTER g_armv7_special_register_get_type() +#define G_ARMV7_SPECIAL_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_SPECIAL_REGISTER, GArmV7SpecialRegister)) +#define G_IS_ARMV7_SPECIAL_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_SPECIAL_REGISTER)) +#define G_ARMV7_SPECIAL_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_SPECIAL_REGISTER, GArmV7SpecialRegisterClass)) +#define G_IS_ARMV7_SPECIAL_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_SPECIAL_REGISTER)) +#define G_ARMV7_SPECIAL_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_SPECIAL_REGISTER, GArmV7SpecialRegisterClass)) + + +/* Représentation d'un registre spécial ARMv7 (instance) */ +typedef struct _GArmV7SpecialRegister GArmV7SpecialRegister; + +/* Représentation d'un registre spécial ARMv7 (classe) */ +typedef struct _GArmV7SpecialRegisterClass GArmV7SpecialRegisterClass; + + +/* Désignation des registres spéciaux */ +typedef enum _SpecRegTarget +{ + SRT_APSR, + SRT_CPSR, + SRT_SPSR, + SRT_APSR_NZCVQ, + SRT_APSR_G, + SRT_APSR_NZCVQG, + SRT_FPSID, + SRT_FPSCR, + SRT_MVFR1, + SRT_MVFR0, + SRT_FPEXC, + + SRT_COUNT + +} SpecRegTarget; + + +/* Indique le type défini pour une représentation d'un registre spécial ARMv7. */ +GType g_armv7_special_register_get_type(void); + +/* Crée une réprésentation de registre spécial ARMv7. */ +GArchRegister *g_armv7_special_register_new(SpecRegTarget); + + + +/* ------------------------ GESTION SOUS FORME DE SINGLETONS ------------------------ */ + + +/* Vide totalement le cache des registres spéciaux ARMv7. */ +void clean_armv7_special_register_cache(void); + + + +#endif /* _PLUGINS_ARM_V7_REGISTERS_SPECIAL_H */ diff --git a/plugins/dalvik/core.c b/plugins/dalvik/core.c index cc96843..524e3c9 100644 --- a/plugins/dalvik/core.c +++ b/plugins/dalvik/core.c @@ -63,6 +63,8 @@ static void register_dalvik_gtypes(void) g_type_ensure(G_TYPE_DALVIK_POOL_OPERAND); g_type_ensure(G_TYPE_DALVIK_REGISTER_OPERAND); + g_type_ensure(G_TYPE_DALVIK_REGISTER); + } diff --git a/plugins/dalvik/operand.c b/plugins/dalvik/operand.c index 4d8fc73..e89bcab 100644 --- a/plugins/dalvik/operand.c +++ b/plugins/dalvik/operand.c @@ -29,6 +29,9 @@ #include <stdarg.h> +#include <arch/operands/register.h> + + /* Liste de tous les types d'opérandes */ typedef enum _DalvikOperandID diff --git a/plugins/dalvik/operands/register.c b/plugins/dalvik/operands/register.c index 7d011a0..ede3eb6 100644 --- a/plugins/dalvik/operands/register.c +++ b/plugins/dalvik/operands/register.c @@ -24,7 +24,7 @@ #include "register.h" -#include <arch/register-int.h> +#include <arch/operands/register-int.h> @@ -58,17 +58,6 @@ static void g_dalvik_register_operand_finalize(GDalvikRegisterOperand *); -/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ - - -/* Charge un opérande depuis une mémoire tampon. */ -static bool g_dalvik_register_operand_unserialize(GDalvikRegisterOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); - -/* Sauvegarde un opérande dans une mémoire tampon. */ -static bool g_dalvik_register_operand_serialize(const GDalvikRegisterOperand *, GAsmStorage *, packed_buffer *); - - - /* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ G_DEFINE_TYPE(GDalvikRegisterOperand, g_dalvik_register_operand, G_TYPE_REGISTER_OPERAND); @@ -88,18 +77,12 @@ G_DEFINE_TYPE(GDalvikRegisterOperand, g_dalvik_register_operand, G_TYPE_REGISTER static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_register_operand_dispose; object->finalize = (GObjectFinalizeFunc)g_dalvik_register_operand_finalize; - operand = G_ARCH_OPERAND_CLASS(klass); - - operand->unserialize = (unserialize_operand_fc)g_dalvik_register_operand_unserialize; - operand->serialize = (serialize_operand_fc)g_dalvik_register_operand_serialize; - } @@ -181,7 +164,7 @@ GArchOperand *g_dalvik_register_operand_new(const GBinContent *content, vmpa2t * uint8_t index8; /* Indice sur 8 bits */ uint16_t index16; /* Indice sur 16 bits */ bool test; /* Bilan de lecture */ - GDalvikRegister *reg; /* Registre à représenter */ + GArchRegister *reg; /* Registre à représenter */ result = NULL; @@ -248,13 +231,13 @@ GArchOperand *g_dalvik_register_operand_new(const GBinContent *content, vmpa2t * * * ******************************************************************************/ -GArchOperand *g_dalvik_register_operand_new_from_existing(GDalvikRegister *reg) +GArchOperand *g_dalvik_register_operand_new_from_existing(GArchRegister *reg) { GDalvikRegisterOperand *result; /* Structure à retourner */ result = g_object_new(G_TYPE_DALVIK_REGISTER_OPERAND, NULL); - G_REGISTER_OPERAND(result)->reg = G_ARCH_REGISTER(reg); + G_REGISTER_OPERAND(result)->reg = reg; return G_ARCH_OPERAND(result); @@ -282,90 +265,3 @@ const GDalvikRegister *g_dalvik_register_operand_get(const GDalvikRegisterOperan return result; } - - - -/* ---------------------------------------------------------------------------------- */ -/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : operand = opérande d'assemblage à constituer. * -* storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * -* pbuf = zone tampon à remplir. * -* * -* Description : Charge un opérande depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_dalvik_register_operand_unserialize(GDalvikRegisterOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - uint16_t index; /* Identifiant de registre */ - GDalvikRegister *reg; /* Registre à intégrer */ - - parent = G_ARCH_OPERAND_CLASS(g_dalvik_register_operand_parent_class); - - result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); - - if (result) - { - result = extract_packed_buffer(pbuf, &index, sizeof(uint16_t), true); - - if (result) - { - reg = g_dalvik_register_new(index); - result = (reg != NULL); - } - - if (result) - G_REGISTER_OPERAND(operand)->reg = G_ARCH_REGISTER(reg); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un opérande dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_dalvik_register_operand_serialize(const GDalvikRegisterOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - uint16_t index; /* Identifiant de registre */ - - parent = G_ARCH_OPERAND_CLASS(g_dalvik_register_operand_parent_class); - - result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); - - if (result) - { - index = g_dalvik_register_get_index(G_DALVIK_REGISTER(G_REGISTER_OPERAND(operand)->reg)); - result = extend_packed_buffer(pbuf, &index, sizeof(uint16_t), true); - } - - return result; - -} diff --git a/plugins/dalvik/operands/register.h b/plugins/dalvik/operands/register.h index 29b14c8..cca1ff4 100644 --- a/plugins/dalvik/operands/register.h +++ b/plugins/dalvik/operands/register.h @@ -59,7 +59,7 @@ GType g_dalvik_register_operand_get_type(void); GArchOperand *g_dalvik_register_operand_new(const GBinContent *, vmpa2t *, bool *, MemoryDataSize, SourceEndian); /* Crée un opérande visant un registre Dalvik. */ -GArchOperand *g_dalvik_register_operand_new_from_existing(GDalvikRegister *); +GArchOperand *g_dalvik_register_operand_new_from_existing(GArchRegister *); /* Fournit le registre Dalvik associé à l'opérande. */ const GDalvikRegister *g_dalvik_register_operand_get(const GDalvikRegisterOperand *); diff --git a/plugins/dalvik/register.c b/plugins/dalvik/register.c index 1e59421..458d219 100644 --- a/plugins/dalvik/register.c +++ b/plugins/dalvik/register.c @@ -76,7 +76,18 @@ static guint g_dalvik_register_hash(const GDalvikRegister *); static void g_dalvik_register_print(const GDalvikRegister *, GBufferLine *, AsmSyntax); /* Crée une réprésentation de registre Dalvik. */ -static GDalvikRegister *_g_dalvik_register_new(uint16_t); +static GArchRegister *_g_dalvik_register_new(uint16_t); + + + +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ + + +/* Charge un registre depuis une mémoire tampon. */ +static GArchRegister *g_dalvik_register_unserialize(GDalvikRegister *, GAsmStorage *, packed_buffer *); + +/* Sauvegarde un registre dans une mémoire tampon. */ +static bool g_dalvik_register_serialize(const GDalvikRegister *, GAsmStorage *, packed_buffer *); @@ -84,13 +95,13 @@ static GDalvikRegister *_g_dalvik_register_new(uint16_t); /* Conservation des registres utilisés */ -static GDalvikRegister **_dalvik_registers = NULL; +static GArchRegister **_dalvik_registers = NULL; static size_t _dreg_count = 0; G_LOCK_DEFINE_STATIC(_dreg_mutex); /* Fournit le singleton associé à un registre Dalvik. */ -static GDalvikRegister *get_dalvik_register(uint16_t); +static GArchRegister *get_dalvik_register(uint16_t); @@ -118,18 +129,20 @@ G_DEFINE_TYPE(GDalvikRegister, g_dalvik_register, G_TYPE_ARCH_REGISTER); static void g_dalvik_register_class_init(GDalvikRegisterClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchRegisterClass *register_class; /* Classe de haut niveau */ + GArchRegisterClass *reg_class; /* Classe de haut niveau */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_register_dispose; object->finalize = (GObjectFinalizeFunc)g_dalvik_register_finalize; - register_class = G_ARCH_REGISTER_CLASS(klass); + reg_class = G_ARCH_REGISTER_CLASS(klass); - register_class->hash = (reg_hash_fc)g_dalvik_register_hash; - register_class->compare = (reg_compare_fc)g_dalvik_register_compare; - register_class->print = (reg_print_fc)g_dalvik_register_print; + reg_class->hash = (reg_hash_fc)g_dalvik_register_hash; + reg_class->compare = (reg_compare_fc)g_dalvik_register_compare; + reg_class->print = (reg_print_fc)g_dalvik_register_print; + reg_class->unserialize = (reg_unserialize_fc)g_dalvik_register_unserialize; + reg_class->serialize = (reg_serialize_fc)g_dalvik_register_serialize; } @@ -261,7 +274,7 @@ static void g_dalvik_register_print(const GDalvikRegister *reg, GBufferLine *lin * * ******************************************************************************/ -static GDalvikRegister *_g_dalvik_register_new(uint16_t index) +static GArchRegister *_g_dalvik_register_new(uint16_t index) { GDalvikRegister *result; /* Structure à retourner */ @@ -269,7 +282,7 @@ static GDalvikRegister *_g_dalvik_register_new(uint16_t index) result->index = index; - return result; + return G_ARCH_REGISTER(result); } @@ -286,9 +299,9 @@ static GDalvikRegister *_g_dalvik_register_new(uint16_t index) * * ******************************************************************************/ -GDalvikRegister *g_dalvik_register_new(uint16_t index) +GArchRegister *g_dalvik_register_new(uint16_t index) { - GDalvikRegister *result; /* Structure à retourner */ + GArchRegister *result; /* Structure à retourner */ result = get_dalvik_register(index); @@ -342,6 +355,97 @@ int g_dalvik_register_compare(const GDalvikRegister *a, const GDalvikRegister *b /* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un registre depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchRegister *g_dalvik_register_unserialize(GDalvikRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + GArchRegister *result; /* Instance à retourner */ + uint16_t index; /* Indice du registre */ + bool status; /* Bilan d'une extraction */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + status = extract_packed_buffer(pbuf, &index, sizeof(uint16_t), true); + + if (status) + { + result = get_dalvik_register(index); + + if (result == NULL) + g_object_unref(G_OBJECT(reg)); + + } + + else + { + g_object_unref(G_OBJECT(reg)); + result = NULL; + } + + if (result != NULL) + { + parent = G_ARCH_REGISTER_CLASS(g_dalvik_register_parent_class); + + result = parent->unserialize(result, storage, pbuf); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre d'architecture à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un registre dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dalvik_register_serialize(const GDalvikRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchRegisterClass *parent; /* Classe parente à consulter */ + + result = extend_packed_buffer(pbuf, ®->index, sizeof(uint16_t), true); + + if (result) + { + parent = G_ARCH_REGISTER_CLASS(g_dalvik_register_parent_class); + + result = parent->serialize(G_ARCH_REGISTER(reg), storage, pbuf); + + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ /* GESTION SOUS FORME DE SINGLETONS */ /* ---------------------------------------------------------------------------------- */ @@ -358,9 +462,9 @@ int g_dalvik_register_compare(const GDalvikRegister *a, const GDalvikRegister *b * * ******************************************************************************/ -static GDalvikRegister *get_dalvik_register(uint16_t index) +static GArchRegister *get_dalvik_register(uint16_t index) { - GDalvikRegister *result; /* Structure à retourner */ + GArchRegister *result; /* Structure à retourner */ size_t new_count; /* Nouvelle taille à considérer*/ size_t i; /* Boucle de parcours */ @@ -370,7 +474,7 @@ static GDalvikRegister *get_dalvik_register(uint16_t index) { new_count = index + 1; - _dalvik_registers = realloc(_dalvik_registers, new_count * sizeof(GDalvikRegister *)); + _dalvik_registers = realloc(_dalvik_registers, new_count * sizeof(GArchRegister *)); for (i = _dreg_count; i < new_count; i++) _dalvik_registers[i] = NULL; diff --git a/plugins/dalvik/register.h b/plugins/dalvik/register.h index 42206c8..fa3f2ab 100644 --- a/plugins/dalvik/register.h +++ b/plugins/dalvik/register.h @@ -29,6 +29,9 @@ #include <stdint.h> +#include <arch/register.h> + + /* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ @@ -52,7 +55,7 @@ typedef struct _GDalvikRegisterClass GDalvikRegisterClass; GType g_dalvik_register_get_type(void); /* Crée une réprésentation de registre Dalvik. */ -GDalvikRegister *g_dalvik_register_new(uint16_t); +GArchRegister *g_dalvik_register_new(uint16_t); /* Fournit l'indice d'un registre Dalvik. */ uint16_t g_dalvik_register_get_index(const GDalvikRegister *); diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index c9cc63b..8710b13 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -30,7 +30,8 @@ libarch_la_SOURCES = \ # mips/libarchmips.la \ # x86/libarchx86.la -libarch_la_LIBADD = +libarch_la_LIBADD = \ + operands/libarchoperands.la libarch_la_LDFLAGS = @@ -46,4 +47,4 @@ AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) #SUBDIRS = arm dalvik jvm mips x86 -SUBDIRS = +SUBDIRS = operands diff --git a/src/arch/operands/Makefile.am b/src/arch/operands/Makefile.am new file mode 100644 index 0000000..fb43a22 --- /dev/null +++ b/src/arch/operands/Makefile.am @@ -0,0 +1,23 @@ + +noinst_LTLIBRARIES = libarchoperands.la + +libarchoperands_la_SOURCES = \ + register-int.h \ + register.h register.c + +libarchoperands_la_LIBADD = + +libarchoperands_la_LDFLAGS = + + +devdir = $(includedir)/chrysalide/$(subdir:src/%=%) + +dev_HEADERS = $(libarchoperands_la_SOURCES:%c=) + + +AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +SUBDIRS = diff --git a/src/arch/operands/register-int.h b/src/arch/operands/register-int.h new file mode 100644 index 0000000..348e2a3 --- /dev/null +++ b/src/arch/operands/register-int.h @@ -0,0 +1,54 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register-int.h - définitions internes pour la représentation générique d'un registre + * + * Copyright (C) 2012-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERANDS_REGISTER_INT_H +#define _ARCH_OPERANDS_REGISTER_INT_H + + +#include "register.h" + + +#include "../operand-int.h" + + + +/* Définition d'un opérande visant un registre (instance) */ +struct _GRegisterOperand +{ + GArchOperand parent; /* Instance parente */ + + GArchRegister *reg; /* Registre représenté */ + bool is_written; /* Changement de contenu */ + +}; + +/* Définition d'un opérande visant un registre (classe) */ +struct _GRegisterOperandClass +{ + GArchOperandClass parent; /* Classe parente */ + +}; + + + +#endif /* _ARCH_OPERANDS_REGISTER_INT_H */ diff --git a/plugins/arm/v7/operands/specreg.c b/src/arch/operands/register.c index 233e6fd..e890fd6 100644 --- a/plugins/arm/v7/operands/specreg.c +++ b/src/arch/operands/register.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * specreg.c - registres spéciaux + * registers.c - aides auxiliaires relatives aux registres Dalvik * - * Copyright (C) 2018 Cyrille Bagard + * Copyright (C) 2012-2017 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,49 +21,34 @@ */ -#include "specreg.h" +#include "register.h" -#include <arch/operand-int.h> -#include <common/sort.h> +#include "register-int.h" +#include "../storage.h" -/* Définition d'un opérande de registre spécial (instance) */ -struct _GArmV7SpecRegOperand -{ - GArchOperand parent; /* Instance parente */ - - SpecRegType reg; /* Identifiant de registre */ - -}; - +/* ------------------------- REGISTRE SOUS FORME D'OPERANDE ------------------------- */ -/* Définition d'un opérande de registre spécial (classe) */ -struct _GArmV7SpecRegOperandClass -{ - GArchOperandClass parent; /* Classe parente */ - -}; +/* Initialise la classe des opérandes de registre. */ +static void g_register_operand_class_init(GRegisterOperandClass *); -/* Initialise la classe des opérandes de registre spécial. */ -static void g_armv7_specreg_operand_class_init(GArmV7SpecRegOperandClass *); - -/* Initialise une instance d'opérande de registre spécial. */ -static void g_armv7_specreg_operand_init(GArmV7SpecRegOperand *); +/* Initialise une instance d'opérande de registre. */ +static void g_register_operand_init(GRegisterOperand *); /* Supprime toutes les références externes. */ -static void g_armv7_specreg_operand_dispose(GArmV7SpecRegOperand *); +static void g_register_operand_dispose(GRegisterOperand *); /* Procède à la libération totale de la mémoire. */ -static void g_armv7_specreg_operand_finalize(GArmV7SpecRegOperand *); +static void g_register_operand_finalize(GRegisterOperand *); /* Compare un opérande avec un autre. */ -static int g_armv7_specreg_operand_compare(const GArmV7SpecRegOperand *, const GArmV7SpecRegOperand *); +static int g_register_operand_compare(const GRegisterOperand *, const GRegisterOperand *); /* Traduit un opérande en version humainement lisible. */ -static void g_armv7_specreg_operand_print(const GArmV7SpecRegOperand *, GBufferLine *, AsmSyntax); +static void g_register_operand_print(const GRegisterOperand *, GBufferLine *, AsmSyntax); @@ -71,22 +56,27 @@ static void g_armv7_specreg_operand_print(const GArmV7SpecRegOperand *, GBufferL /* Charge un opérande depuis une mémoire tampon. */ -static bool g_armv7_specreg_operand_unserialize(GArmV7SpecRegOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); +static bool g_register_operand_unserialize(GRegisterOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); /* Sauvegarde un opérande dans une mémoire tampon. */ -static bool g_armv7_specreg_operand_serialize(const GArmV7SpecRegOperand *, GAsmStorage *, packed_buffer *); +static bool g_register_operand_serialize(const GRegisterOperand *, GAsmStorage *, packed_buffer *); -/* Indique le type défini par la GLib pour un opérande de registre spécial ARMv7. */ -G_DEFINE_TYPE(GArmV7SpecRegOperand, g_armv7_specreg_operand, G_TYPE_ARCH_OPERAND); +/* ---------------------------------------------------------------------------------- */ +/* REGISTRE SOUS FORME D'OPERANDE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ +G_DEFINE_TYPE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * -* Description : Initialise la classe des opérandes de registre spécial. * +* Description : Initialise la classe des opérandes de registre Dalvik. * * * * Retour : - * * * @@ -94,7 +84,7 @@ G_DEFINE_TYPE(GArmV7SpecRegOperand, g_armv7_specreg_operand, G_TYPE_ARCH_OPERAND * * ******************************************************************************/ -static void g_armv7_specreg_operand_class_init(GArmV7SpecRegOperandClass *klass) +static void g_register_operand_class_init(GRegisterOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ GArchOperandClass *operand; /* Version de classe parente */ @@ -102,14 +92,16 @@ static void g_armv7_specreg_operand_class_init(GArmV7SpecRegOperandClass *klass) object = G_OBJECT_CLASS(klass); operand = G_ARCH_OPERAND_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_specreg_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_armv7_specreg_operand_finalize; + object->dispose = (GObjectFinalizeFunc/* ! */)g_register_operand_dispose; + object->finalize = (GObjectFinalizeFunc)g_register_operand_finalize; - operand->compare = (operand_compare_fc)g_armv7_specreg_operand_compare; - operand->print = (operand_print_fc)g_armv7_specreg_operand_print; + operand = G_ARCH_OPERAND_CLASS(klass); - operand->unserialize = (unserialize_operand_fc)g_armv7_specreg_operand_unserialize; - operand->serialize = (serialize_operand_fc)g_armv7_specreg_operand_serialize; + operand->compare = (operand_compare_fc)g_register_operand_compare; + operand->print = (operand_print_fc)g_register_operand_print; + + operand->unserialize = (unserialize_operand_fc)g_register_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_register_operand_serialize; } @@ -118,7 +110,7 @@ static void g_armv7_specreg_operand_class_init(GArmV7SpecRegOperandClass *klass) * * * Paramètres : operand = instance à initialiser. * * * -* Description : Initialise une instance d'opérande de registre spécial. * +* Description : Initialise une instance d'opérande de registre Dalvik. * * * * Retour : - * * * @@ -126,15 +118,17 @@ static void g_armv7_specreg_operand_class_init(GArmV7SpecRegOperandClass *klass) * * ******************************************************************************/ -static void g_armv7_specreg_operand_init(GArmV7SpecRegOperand *operand) +static void g_register_operand_init(GRegisterOperand *operand) { + operand->reg = NULL; + operand->is_written = false; } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : binary = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -144,16 +138,19 @@ static void g_armv7_specreg_operand_init(GArmV7SpecRegOperand *operand) * * ******************************************************************************/ -static void g_armv7_specreg_operand_dispose(GArmV7SpecRegOperand *operand) +static void g_register_operand_dispose(GRegisterOperand *operand) { - G_OBJECT_CLASS(g_armv7_specreg_operand_parent_class)->dispose(G_OBJECT(operand)); + if (operand->reg != NULL) + g_object_unref(G_OBJECT(operand->reg)); + + G_OBJECT_CLASS(g_register_operand_parent_class)->dispose(G_OBJECT(operand)); } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : binary = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -163,9 +160,9 @@ static void g_armv7_specreg_operand_dispose(GArmV7SpecRegOperand *operand) * * ******************************************************************************/ -static void g_armv7_specreg_operand_finalize(GArmV7SpecRegOperand *operand) +static void g_register_operand_finalize(GRegisterOperand *operand) { - G_OBJECT_CLASS(g_armv7_specreg_operand_parent_class)->finalize(G_OBJECT(operand)); + G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(G_OBJECT(operand)); } @@ -183,11 +180,11 @@ static void g_armv7_specreg_operand_finalize(GArmV7SpecRegOperand *operand) * * ******************************************************************************/ -static int g_armv7_specreg_operand_compare(const GArmV7SpecRegOperand *a, const GArmV7SpecRegOperand *b) +static int g_register_operand_compare(const GRegisterOperand *a, const GRegisterOperand *b) { - int result; /* Bilan à faire remonter */ + int result; /* Bilan à retourner */ - result = sort_unsigned_long(a->reg, b->reg); + result = g_arch_register_compare(a->reg, b->reg); return result; @@ -208,103 +205,73 @@ static int g_armv7_specreg_operand_compare(const GArmV7SpecRegOperand *a, const * * ******************************************************************************/ -static void g_armv7_specreg_operand_print(const GArmV7SpecRegOperand *operand, GBufferLine *line, AsmSyntax syntax) +static void g_register_operand_print(const GRegisterOperand *operand, GBufferLine *line, AsmSyntax syntax) { - switch (operand->reg) - { - case SRT_APSR: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "APSR", 4, RTT_REGISTER, NULL); - break; + g_arch_register_print(operand->reg, line, syntax); - case SRT_CPSR: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "CPSR", 4, RTT_REGISTER, NULL); - break; - - case SRT_SPSR: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "SPSR", 4, RTT_REGISTER, NULL); - break; - - case SRT_APSR_NZCVQ: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "APSR_nzcvq", 10, RTT_REGISTER, NULL); - break; - - case SRT_APSR_G: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "APSR_g", 6, RTT_REGISTER, NULL); - break; - - case SRT_APSR_NZCVQG: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "APSR_nzcvqg", 11, RTT_REGISTER, NULL); - break; +} - case SRT_FPSID: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "FPSID", 5, RTT_REGISTER, NULL); - break; - case SRT_FPSCR: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "FPSCR", 5, RTT_REGISTER, NULL); - break; +/****************************************************************************** +* * +* Paramètres : operand = opérande représentant un registre. * +* * +* Description : Fournit le registre Dalvik associé à l'opérande. * +* * +* Retour : Représentation interne du registre. * +* * +* Remarques : - * +* * +******************************************************************************/ - case SRT_MVFR1: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "MVFR1", 5, RTT_REGISTER, NULL); - break; +GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand) +{ + GArchRegister *result; /* Instance à retourner */ - case SRT_MVFR0: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "MVFR0", 5, RTT_REGISTER, NULL); - break; + result = operand->reg; - case SRT_FPEXC: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "FPEXC", 5, RTT_REGISTER, NULL); - break; + if (result != NULL) + g_object_ref(G_OBJECT(result)); - } + return result; } /****************************************************************************** * * -* Paramètres : big = indication sur le boutisme à représenter. * +* Paramètres : operand = opérande représentant un registre à mettre à jour. * * * -* Description : Crée une représentation d'opérande de registre spécial. * +* Description : Marque l'opérande comme étant écrit plutôt que consulté. * * * -* Retour : Opérande mis en place. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *g_armv7_specreg_operand_new(SpecRegType reg) +void g_register_operand_mark_as_written(GRegisterOperand *operand) { - GArmV7SpecRegOperand *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_ARMV7_SPECREG_OPERAND, NULL); - - result->reg = reg; - - return G_ARCH_OPERAND(result); + operand->is_written = true; } /****************************************************************************** * * -* Paramètres : operand = opérande à consulter. * +* Paramètres : operand = opérande représentant un registre à consulter. * * * -* Description : Indique le type de registre spécial représenté. * +* Description : Indique le type d'accès réalisé sur l'opérande. * * * -* Retour : Identifiant de registre spécial. * +* Retour : Type d'accès : true en cas d'écriture, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -SpecRegType g_armv7_specreg_operand_get_register(const GArmV7SpecRegOperand *operand) +bool g_register_operand_is_written(const GRegisterOperand *operand) { - SpecRegType result; /* Désignation à retourner */ - - result = operand->reg; - - return result; + return operand->is_written; } @@ -330,17 +297,39 @@ SpecRegType g_armv7_specreg_operand_get_register(const GArmV7SpecRegOperand *ope * * ******************************************************************************/ -static bool g_armv7_specreg_operand_unserialize(GArmV7SpecRegOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +static bool g_register_operand_unserialize(GRegisterOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ + off64_t pos; /* Position dans le flux */ + packed_buffer reg_pbuf; /* Tampon des données à écrire */ + GArchRegister *reg; /* Registre restauré */ - parent = G_ARCH_OPERAND_CLASS(g_armv7_specreg_operand_parent_class); + parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); if (result) - result = extract_packed_buffer(pbuf, &operand->reg, sizeof(SpecRegType), true); + result = extract_packed_buffer(pbuf, &pos, sizeof(off64_t), true); + + if (result) + { + init_packed_buffer(®_pbuf); + + result = g_asm_storage_load_register_data(storage, ®_pbuf, pos); + + if (result) + { + reg = g_arch_register_load(storage, ®_pbuf); + result = (reg != NULL); + } + + if (result) + operand->reg = reg; + + exit_packed_buffer(®_pbuf); + + } return result; @@ -361,18 +350,33 @@ static bool g_armv7_specreg_operand_unserialize(GArmV7SpecRegOperand *operand, G * * ******************************************************************************/ -static bool g_armv7_specreg_operand_serialize(const GArmV7SpecRegOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +static bool g_register_operand_serialize(const GRegisterOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ + off64_t pos; /* Position dans le flux */ + packed_buffer reg_pbuf; /* Tampon des données à écrire */ - parent = G_ARCH_OPERAND_CLASS(g_armv7_specreg_operand_parent_class); + parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); if (result) - result = extend_packed_buffer(pbuf, &operand->reg, sizeof(SpecRegType), true); - + { + init_packed_buffer(®_pbuf); + + result = g_arch_register_store(operand->reg, storage, ®_pbuf); + + if (result) + result = g_asm_storage_store_register_data(storage, ®_pbuf, &pos); + + if (result) + result = extend_packed_buffer(pbuf, &pos, sizeof(off64_t), true); + + exit_packed_buffer(®_pbuf); + + } + return result; } diff --git a/src/arch/operands/register.h b/src/arch/operands/register.h new file mode 100644 index 0000000..e4693b1 --- /dev/null +++ b/src/arch/operands/register.h @@ -0,0 +1,69 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register.h - prototypes pour les aides auxiliaires relatives aux registres Dalvik + * + * Copyright (C) 2012-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERANDS_REGISTER_H +#define _ARCH_OPERANDS_REGISTER_H + + +#include <glib-object.h> +#include <stdbool.h> + + +#include "../operand.h" +#include "../register.h" + + + +/* ------------------------- REGISTRE SOUS FORME D'OPERANDE ------------------------- */ + + +#define G_TYPE_REGISTER_OPERAND g_register_operand_get_type() +#define G_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_REGISTER_OPERAND, GRegisterOperand)) +#define G_IS_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_REGISTER_OPERAND)) +#define G_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_REGISTER_OPERAND, GRegisterOperandClass)) +#define G_IS_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_REGISTER_OPERAND)) +#define G_REGISTER_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_REGISTER_OPERAND, GRegisterOperandClass)) + + +/* Définition d'un opérande visant un registre (instance) */ +typedef struct _GRegisterOperand GRegisterOperand; + +/* Définition d'un opérande visant un registre (classe) */ +typedef struct _GRegisterOperandClass GRegisterOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de registre. */ +GType g_register_operand_get_type(void); + +/* Fournit le registre associé à l'opérande. */ +GArchRegister *g_register_operand_get_register(const GRegisterOperand *); + +/* Marque l'opérande comme étant écrit plutôt que consulté. */ +void g_register_operand_mark_as_written(GRegisterOperand *); + +/* Indique le type d'accès réalisé sur l'opérande. */ +bool g_register_operand_is_written(const GRegisterOperand *); + + + +#endif /* _ARCH_OPERANDS_REGISTER_H */ diff --git a/src/arch/register-int.h b/src/arch/register-int.h index 173e6e0..fb9534b 100644 --- a/src/arch/register-int.h +++ b/src/arch/register-int.h @@ -47,6 +47,11 @@ typedef bool (* reg_is_base_pointer_fc) (const GArchRegister *); /* Indique si le registre correspond à esp ou similaire. */ typedef bool (* reg_is_stack_pointer_fc) (const GArchRegister *); +/* Charge un registre depuis une mémoire tampon. */ +typedef GArchRegister * (* reg_unserialize_fc) (GArchRegister *, GAsmStorage *, packed_buffer *); + +/* Sauvegarde un registre dans une mémoire tampon. */ +typedef bool (* reg_serialize_fc) (const GArchRegister *, GAsmStorage *, packed_buffer *); /* Représentation d'un registre (instance) */ @@ -56,7 +61,6 @@ struct _GArchRegister }; - /* Représentation d'un registre (classe) */ struct _GArchRegisterClass { @@ -68,28 +72,8 @@ struct _GArchRegisterClass reg_is_base_pointer_fc is_bp; /* Correspondance avec ebp */ reg_is_stack_pointer_fc is_sp; /* Correspondance avec esp */ -}; - - - -/* ------------------------- REGISTRE SOUS FORME D'OPERANDE ------------------------- */ - - -/* Définition d'un opérande visant un registre (instance) */ -struct _GRegisterOperand -{ - GArchOperand parent; /* Instance parente */ - - GArchRegister *reg; /* Registre représenté */ - bool is_written; /* Changement de contenu */ - -}; - - -/* Définition d'un opérande visant un registre (classe) */ -struct _GRegisterOperandClass -{ - GArchOperandClass parent; /* Classe parente */ + reg_unserialize_fc unserialize; /* Chargement depuis un tampon */ + reg_serialize_fc serialize; /* Conservation dans un tampon */ }; diff --git a/src/arch/register.c b/src/arch/register.c index 7e1bcc2..f678327 100644 --- a/src/arch/register.c +++ b/src/arch/register.c @@ -25,6 +25,7 @@ #include "register-int.h" +#include "storage.h" @@ -44,37 +45,15 @@ static void g_arch_register_dispose(GArchRegister *); static void g_arch_register_finalize(GArchRegister *); -/* ------------------------- REGISTRE SOUS FORME D'OPERANDE ------------------------- */ +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ -/* Initialise la classe des opérandes de registre. */ -static void g_register_operand_class_init(GRegisterOperandClass *); -/* Initialise une instance d'opérande de registre. */ -static void g_register_operand_init(GRegisterOperand *); +/* Charge un registre depuis une mémoire tampon. */ +static GArchRegister *g_arch_register_unserialize(GArchRegister *, GAsmStorage *, packed_buffer *); -/* Supprime toutes les références externes. */ -static void g_register_operand_dispose(GRegisterOperand *); - -/* Procède à la libération totale de la mémoire. */ -static void g_register_operand_finalize(GRegisterOperand *); - -/* Compare un opérande avec un autre. */ -static int g_register_operand_compare(const GRegisterOperand *, const GRegisterOperand *); - -/* Traduit un opérande en version humainement lisible. */ -static void g_register_operand_print(const GRegisterOperand *, GBufferLine *, AsmSyntax); - - - -/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ - - -/* Charge un opérande depuis une mémoire tampon. */ -static bool g_register_operand_unserialize(GRegisterOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); - -/* Sauvegarde un opérande dans une mémoire tampon. */ -static bool g_register_operand_serialize(const GRegisterOperand *, GAsmStorage *, packed_buffer *); +/* Sauvegarde un registre dans une mémoire tampon. */ +static bool g_arch_register_serialize(const GArchRegister *, GAsmStorage *, packed_buffer *); @@ -108,6 +87,9 @@ static void g_arch_register_class_init(GArchRegisterClass *klass) object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_register_dispose; object->finalize = (GObjectFinalizeFunc)g_arch_register_finalize; + klass->unserialize = (reg_unserialize_fc)g_arch_register_unserialize; + klass->serialize = (reg_serialize_fc)g_arch_register_serialize; + } @@ -281,127 +263,29 @@ bool g_arch_register_is_stack_pointer(const GArchRegister *reg) /* ---------------------------------------------------------------------------------- */ -/* REGISTRE SOUS FORME D'OPERANDE */ +/* TRANSPOSITIONS VIA CACHE DES REGISTRES */ /* ---------------------------------------------------------------------------------- */ -/* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ -G_DEFINE_TYPE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des opérandes de registre Dalvik. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_register_operand_class_init(GRegisterOperandClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ - - object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_register_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_register_operand_finalize; - - operand = G_ARCH_OPERAND_CLASS(klass); - - operand->compare = (operand_compare_fc)g_register_operand_compare; - operand->print = (operand_print_fc)g_register_operand_print; - - operand->unserialize = (unserialize_operand_fc)g_register_operand_unserialize; - operand->serialize = (serialize_operand_fc)g_register_operand_serialize; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance à initialiser. * -* * -* Description : Initialise une instance d'opérande de registre Dalvik. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_register_operand_init(GRegisterOperand *operand) -{ - operand->reg = NULL; - operand->is_written = false; - -} - - -/****************************************************************************** -* * -* Paramètres : binary = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_register_operand_dispose(GRegisterOperand *operand) -{ - if (operand->reg != NULL) - g_object_unref(G_OBJECT(operand->reg)); - - G_OBJECT_CLASS(g_register_operand_parent_class)->dispose(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : binary = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_register_operand_finalize(GRegisterOperand *operand) -{ - G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(G_OBJECT(operand)); - -} - - /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * +* Paramètres : reg = registre d'architecture à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * * * -* Description : Compare un opérande avec un autre. * +* Description : Charge un registre depuis une mémoire tampon. * * * -* Retour : Bilan de la comparaison. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static int g_register_operand_compare(const GRegisterOperand *a, const GRegisterOperand *b) +static GArchRegister *g_arch_register_unserialize(GArchRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) { - int result; /* Bilan à retourner */ + GArchRegister *result; /* Instance à retourner */ - result = g_arch_register_compare(a->reg, b->reg); + result = reg; return result; @@ -410,123 +294,49 @@ static int g_register_operand_compare(const GRegisterOperand *a, const GRegister /****************************************************************************** * * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * -* syntax = type de représentation demandée. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_register_operand_print(const GRegisterOperand *operand, GBufferLine *line, AsmSyntax syntax) -{ - g_arch_register_print(operand->reg, line, syntax); - -} - - -/****************************************************************************** -* * -* Paramètres : reg = registre déjà en place. * -* * -* Description : Crée un opérande visant un registre. * -* * -* Retour : Opérande mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArchOperand *g_register_operand_new(GArchRegister *reg) -{ - GRegisterOperand *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_REGISTER_OPERAND, NULL); - - result->reg = reg; - - return G_ARCH_OPERAND(result); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande représentant un registre. * +* Paramètres : storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * * * -* Description : Fournit le registre Dalvik associé à l'opérande. * +* Description : Charge un registre depuis une mémoire tampon. * * * -* Retour : Représentation interne du registre. * +* Retour : Registre d'architecture constitué ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand) +GArchRegister *g_arch_register_load(GAsmStorage *storage, packed_buffer *pbuf) { - g_object_ref(G_OBJECT(operand->reg)); + GArchRegister *result; /* Instance à retourner */ + GArchRegister *dummy; /* Patron du type de registre */ - return operand->reg; + dummy = G_ARCH_REGISTER(g_asm_storage_create_object(storage, pbuf)); -} + if (dummy != NULL) + { + result = G_ARCH_REGISTER_GET_CLASS(dummy)->unserialize(dummy, storage, pbuf); + /* Si personne ne l'a fait avant... */ + if (result != NULL) + g_object_unref(G_OBJECT(dummy)); -/****************************************************************************** -* * -* Paramètres : operand = opérande représentant un registre à mettre à jour. * -* * -* Description : Marque l'opérande comme étant écrit plutôt que consulté. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_register_operand_mark_as_written(GRegisterOperand *operand) -{ - operand->is_written = true; + } -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande représentant un registre à consulter. * -* * -* Description : Indique le type d'accès réalisé sur l'opérande. * -* * -* Retour : Type d'accès : true en cas d'écriture, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ + else + result = NULL; -bool g_register_operand_is_written(const GRegisterOperand *operand) -{ - return operand->is_written; + return result; } - -/* ---------------------------------------------------------------------------------- */ -/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : operand = opérande d'assemblage à constituer. * +* Paramètres : reg = registre d'architecture à consulter. * * storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * * pbuf = zone tampon à remplir. * * * -* Description : Charge un opérande depuis une mémoire tampon. * +* Description : Sauvegarde un registre dans une mémoire tampon. * * * * Retour : Bilan de l'opération. * * * @@ -534,14 +344,11 @@ bool g_register_operand_is_written(const GRegisterOperand *operand) * * ******************************************************************************/ -static bool g_register_operand_unserialize(GRegisterOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +static bool g_arch_register_serialize(const GArchRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - - parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); - result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + result = true; return result; @@ -550,11 +357,11 @@ static bool g_register_operand_unserialize(GRegisterOperand *operand, GAsmStorag /****************************************************************************** * * -* Paramètres : operand = opérande d'assemblage à consulter. * +* Paramètres : reg = registre d'architecture à consulter. * * storage = mécanisme de sauvegarde à manipuler. * * pbuf = zone tampon à remplir. * * * -* Description : Sauvegarde un opérande dans une mémoire tampon. * +* Description : Sauvegarde un registre dans une mémoire tampon. * * * * Retour : Bilan de l'opération. * * * @@ -562,14 +369,14 @@ static bool g_register_operand_unserialize(GRegisterOperand *operand, GAsmStorag * * ******************************************************************************/ -static bool g_register_operand_serialize(const GRegisterOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +bool g_arch_register_store(const GArchRegister *reg, GAsmStorage *storage, packed_buffer *pbuf) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); + result = g_asm_storage_store_object_gtype(storage, G_OBJECT(reg), pbuf); - result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + if (result) + result = G_ARCH_REGISTER_GET_CLASS(reg)->serialize(reg, storage, pbuf); return result; diff --git a/src/arch/register.h b/src/arch/register.h index fb3741e..5a97682 100644 --- a/src/arch/register.h +++ b/src/arch/register.h @@ -21,8 +21,8 @@ */ -#ifndef _ARCH_ARCH_REGISTER_H -#define _ARCH_ARCH_REGISTER_H +#ifndef _ARCH_REGISTER_H +#define _ARCH_REGISTER_H #include <glib-object.h> @@ -30,7 +30,6 @@ #include "archbase.h" -#include "operand.h" #include "../glibext/gbufferline.h" @@ -73,39 +72,19 @@ bool g_arch_register_is_stack_pointer(const GArchRegister *); -/* ------------------------- REGISTRE SOUS FORME D'OPERANDE ------------------------- */ +/* --------------------- TRANSPOSITIONS VIA CACHE DES REGISTRES --------------------- */ -#define G_TYPE_REGISTER_OPERAND g_register_operand_get_type() -#define G_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_REGISTER_OPERAND, GRegisterOperand)) -#define G_IS_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_REGISTER_OPERAND)) -#define G_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_REGISTER_OPERAND, GRegisterOperandClass)) -#define G_IS_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_REGISTER_OPERAND)) -#define G_REGISTER_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_REGISTER_OPERAND, GRegisterOperandClass)) +/* Depuis "storage.h" : définition d'une conservation d'instructions d'assemblage (instance) */ +typedef struct _GAsmStorage GAsmStorage; -/* Définition d'un opérande visant un registre (instance) */ -typedef struct _GRegisterOperand GRegisterOperand; +/* Charge un registre depuis une mémoire tampon. */ +GArchRegister *g_arch_register_load(GAsmStorage *, packed_buffer *); -/* Définition d'un opérande visant un registre (classe) */ -typedef struct _GRegisterOperandClass GRegisterOperandClass; +/* Sauvegarde un registre dans une mémoire tampon. */ +bool g_arch_register_store(const GArchRegister *, GAsmStorage *, packed_buffer *); -/* Indique le type défini par la GLib pour un opérande de registre. */ -GType g_register_operand_get_type(void); -/* Crée un opérande visant un registre. */ -GArchOperand *g_register_operand_new(GArchRegister *); - -/* Fournit le registre associé à l'opérande. */ -GArchRegister *g_register_operand_get_register(const GRegisterOperand *); - -/* Marque l'opérande comme étant écrit plutôt que consulté. */ -void g_register_operand_mark_as_written(GRegisterOperand *); - -/* Indique le type d'accès réalisé sur l'opérande. */ -bool g_register_operand_is_written(const GRegisterOperand *); - - - -#endif /* _ARCH_ARCH_REGISTER_H */ +#endif /* _ARCH_REGISTER_H */ diff --git a/src/arch/storage.c b/src/arch/storage.c index ac1c878..217d327 100644 --- a/src/arch/storage.c +++ b/src/arch/storage.c @@ -131,11 +131,13 @@ struct _GAsmStorage char *idx_filename; /* Fichier pour l'indexage */ char *ins_filename; /* Fichier pour instructions */ char *op_filename; /* Fichier pour les opérandes */ + char *reg_filename; /* Fichier pour les registres */ char *tp_filename; /* Fichier pour les types */ int idx_fd; /* Flux pour l'indexage */ int ins_fd; /* Flux pour les instructions */ int op_fd; /* Flux pour les opérandes */ + int reg_fd; /* Flux pour les registres */ int tp_fd; /* Flux pour les types */ /** @@ -602,11 +604,13 @@ static void g_asm_storage_init(GAsmStorage *storage) storage->idx_filename = NULL; storage->ins_filename = NULL; storage->op_filename = NULL; + storage->reg_filename = NULL; storage->tp_filename = NULL; storage->idx_fd = -1; storage->ins_fd = -1; storage->op_fd = -1; + storage->reg_fd = -1; storage->tp_fd = -1; storage->gtypes = NULL; @@ -693,6 +697,7 @@ static void g_asm_storage_finalize(GAsmStorage *storage) finalize_storage_file(storage->idx_filename); finalize_storage_file(storage->ins_filename); finalize_storage_file(storage->op_filename); + finalize_storage_file(storage->reg_filename); finalize_storage_file(storage->tp_filename); if (storage->idx_fd != -1) @@ -704,6 +709,9 @@ static void g_asm_storage_finalize(GAsmStorage *storage) if (storage->op_fd != -1) close(storage->op_fd); + if (storage->reg_fd != -1) + close(storage->reg_fd); + if (storage->gtypes != NULL) free(storage->gtypes); @@ -757,6 +765,7 @@ GAsmStorage *g_asm_storage_new_compressed(GArchProcessor *proc, const gchar *id) asprintf(&result->idx_filename, "%s.%s-%s", basedir, id, "index.bin"); asprintf(&result->ins_filename, "%s.%s-%s", basedir, id, "instructions.bin"); asprintf(&result->op_filename, "%s.%s-%s", basedir, id, "operands.bin"); + asprintf(&result->reg_filename, "%s.%s-%s", basedir, id, "registers.bin"); asprintf(&result->tp_filename, "%s.%s-%s", basedir, id, "types.bin"); free(basedir); @@ -891,6 +900,11 @@ static bool g_asm_storage_decompress(const GAsmStorage *storage) if (!dump_archive_entry_into_file(in, entry, storage->op_filename)) goto gasd_exit; } + else if (strcmp(path, "registers.bin") == 0) + { + if (!dump_archive_entry_into_file(in, entry, storage->reg_filename)) + goto gasd_exit; + } else if (strcmp(path, "types.bin") == 0) { if (!dump_archive_entry_into_file(in, entry, storage->tp_filename)) @@ -958,6 +972,9 @@ static bool g_asm_storage_compress(const GAsmStorage *storage) status = add_file_into_archive(out, storage->op_filename, "operands.bin"); if (status != CPE_NO_ERROR) goto gasc_exit; + status = add_file_into_archive(out, storage->reg_filename, "registers.bin"); + if (status != CPE_NO_ERROR) goto gasc_exit; + status = add_file_into_archive(out, storage->tp_filename, "types.bin"); if (status != CPE_NO_ERROR) goto gasc_exit; @@ -1212,7 +1229,7 @@ static bool g_asm_storage_write_types(GAsmStorage *storage) /****************************************************************************** * * * Paramètres : storage = gestionnaire à manipuler. * -* ins = true si les données viennent d'une instruction. * +* type = type du fichier de destination. * * pbuf = zone tampon à remplir. * * pos = tête de lecture avant écriture. * * * @@ -1224,13 +1241,33 @@ static bool g_asm_storage_write_types(GAsmStorage *storage) * * ******************************************************************************/ -bool _g_asm_storage_load_data(const GAsmStorage *storage, bool ins, packed_buffer *pbuf, off64_t pos) +bool _g_asm_storage_load_data(const GAsmStorage *storage, StorageFileType type, packed_buffer *pbuf, off64_t pos) { bool result; /* Bilan à retourner */ int fd; /* Flux ciblé */ off64_t new; /* Nouvelle position de lecture*/ - fd = ins ? storage->ins_fd : storage->op_fd; + switch (type) + { + case SFT_INSTRUCTION: + fd = storage->ins_fd; + break; + case SFT_OPERAND: + fd = storage->op_fd; + break; + case SFT_REGISTER: + fd = storage->reg_fd; + break; + default: + fd = -1; + break; + } + + if (fd == -1) + { + result = false; + goto type_error; + } new = lseek64(fd, pos, SEEK_SET); @@ -1243,6 +1280,8 @@ bool _g_asm_storage_load_data(const GAsmStorage *storage, bool ins, packed_buffe result = read_packed_buffer(pbuf, fd); } + type_error: + return result; } @@ -1251,7 +1290,7 @@ bool _g_asm_storage_load_data(const GAsmStorage *storage, bool ins, packed_buffe /****************************************************************************** * * * Paramètres : storage = gestionnaire à manipuler. * -* ins = true si les données viennent d'une instruction. * +* type = type du fichier de destination. * * pbuf = zone tampon à lire. * * pos = tête de lecture avant écriture. [OUT] * * * @@ -1263,12 +1302,32 @@ bool _g_asm_storage_load_data(const GAsmStorage *storage, bool ins, packed_buffe * * ******************************************************************************/ -bool _g_asm_storage_store_data(const GAsmStorage *storage, bool ins, packed_buffer *pbuf, off64_t *pos) +bool _g_asm_storage_store_data(const GAsmStorage *storage, StorageFileType type, packed_buffer *pbuf, off64_t *pos) { bool result; /* Bilan à retourner */ int fd; /* Flux ciblé */ - fd = ins ? storage->ins_fd : storage->op_fd; + switch (type) + { + case SFT_INSTRUCTION: + fd = storage->ins_fd; + break; + case SFT_OPERAND: + fd = storage->op_fd; + break; + case SFT_REGISTER: + fd = storage->reg_fd; + break; + default: + fd = -1; + break; + } + + if (fd == -1) + { + result = false; + goto type_error; + } *pos = lseek64(fd, 0, SEEK_CUR); @@ -1281,6 +1340,8 @@ bool _g_asm_storage_store_data(const GAsmStorage *storage, bool ins, packed_buff reset_packed_buffer(pbuf); } + type_error: + return result; } @@ -1326,6 +1387,9 @@ static bool g_asm_storage_open_files(GAsmStorage *storage, int flags) result = open_file(storage->op_filename, storage->op_fd); if (result) + result = open_file(storage->reg_filename, storage->reg_fd); + + if (result) result = open_file(storage->tp_filename, storage->tp_fd); return result; diff --git a/src/arch/storage.h b/src/arch/storage.h index 002897a..35e3a7d 100644 --- a/src/arch/storage.h +++ b/src/arch/storage.h @@ -72,23 +72,38 @@ GObject *g_asm_storage_create_object(GAsmStorage *, packed_buffer *); /* Sauvegarde le type d'un objet instancié. */ bool g_asm_storage_store_object_gtype(GAsmStorage *, GObject *, packed_buffer *); +/* Type de fichier intermédiaire */ +typedef enum _StorageFileType +{ + SFT_INSTRUCTION, /* Pour instructions */ + SFT_OPERAND, /* Pour opérandes */ + SFT_REGISTER /* Pour registres */ + +} StorageFileType; + /* Charge des données rassemblées. */ -bool _g_asm_storage_load_data(const GAsmStorage *, bool, packed_buffer *, off64_t); +bool _g_asm_storage_load_data(const GAsmStorage *, StorageFileType, packed_buffer *, off64_t); #define g_asm_storage_load_instruction_data(s, b, p) \ - _g_asm_storage_load_data(s, true, b, p) + _g_asm_storage_load_data(s, SFT_INSTRUCTION, b, p) #define g_asm_storage_load_operand_data(s, b, p) \ - _g_asm_storage_load_data(s, false, b, p) + _g_asm_storage_load_data(s, SFT_OPERAND, b, p) + +#define g_asm_storage_load_register_data(s, b, p) \ + _g_asm_storage_load_data(s, SFT_REGISTER, b, p) /* Sauvegarde des données rassemblées. */ -bool _g_asm_storage_store_data(const GAsmStorage *, bool, packed_buffer *, off64_t *); +bool _g_asm_storage_store_data(const GAsmStorage *, StorageFileType, packed_buffer *, off64_t *); #define g_asm_storage_store_instruction_data(s, b, p) \ - _g_asm_storage_store_data(s, true, b, p) + _g_asm_storage_store_data(s, SFT_INSTRUCTION, b, p) #define g_asm_storage_store_operand_data(s, b, p) \ - _g_asm_storage_store_data(s, false, b, p) + _g_asm_storage_store_data(s, SFT_OPERAND, b, p) + +#define g_asm_storage_store_register_data(s, b, p) \ + _g_asm_storage_store_data(s, SFT_REGISTER, b, p) /* Lance une restauration complète d'unsauvegarde compressée. */ bool g_asm_storage_open(GAsmStorage *, GBinFormat *, wgroup_id_t); diff --git a/src/core/processors.c b/src/core/processors.c index 12c63cf..68fd0f6 100644 --- a/src/core/processors.c +++ b/src/core/processors.c @@ -31,9 +31,9 @@ #include "../arch/immediate.h" #include "../arch/raw.h" -#include "../arch/register.h" #include "../arch/target.h" #include "../arch/undefined.h" +#include "../arch/operands/register.h" //#include "../arch/jvm/processor.h" |