diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-05-28 17:37:46 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-05-28 17:37:46 (GMT) |
commit | 9f5ed46de568d3db882c939c8ca9d0117bff3369 (patch) | |
tree | 9d2090cd640e54379dc1b982e03dc284b2d23ae7 /plugins/arm | |
parent | 2fd186a84cba4f39f6f1bb8bd34d52b4e1d4f814 (diff) |
Relied on register objects as often as possible.
Diffstat (limited to 'plugins/arm')
29 files changed, 3048 insertions, 1268 deletions
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.c b/plugins/arm/v7/operands/specreg.c deleted file mode 100644 index 233e6fd..0000000 --- a/plugins/arm/v7/operands/specreg.c +++ /dev/null @@ -1,378 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * specreg.c - 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/>. - */ - - -#include "specreg.h" - - -#include <arch/operand-int.h> -#include <common/sort.h> - - - -/* Définition d'un opérande de registre spécial (instance) */ -struct _GArmV7SpecRegOperand -{ - GArchOperand parent; /* Instance parente */ - - SpecRegType reg; /* Identifiant de registre */ - -}; - - -/* 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 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 *); - -/* Supprime toutes les références externes. */ -static void g_armv7_specreg_operand_dispose(GArmV7SpecRegOperand *); - -/* Procède à la libération totale de la mémoire. */ -static void g_armv7_specreg_operand_finalize(GArmV7SpecRegOperand *); - -/* Compare un opérande avec un autre. */ -static int g_armv7_specreg_operand_compare(const GArmV7SpecRegOperand *, const GArmV7SpecRegOperand *); - -/* Traduit un opérande en version humainement lisible. */ -static void g_armv7_specreg_operand_print(const GArmV7SpecRegOperand *, GBufferLine *, AsmSyntax); - - - -/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ - - -/* Charge un opérande depuis une mémoire tampon. */ -static bool g_armv7_specreg_operand_unserialize(GArmV7SpecRegOperand *, 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 *); - - - -/* 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); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des opérandes de registre spécial. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_specreg_operand_class_init(GArmV7SpecRegOperandClass *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_specreg_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_armv7_specreg_operand_finalize; - - operand->compare = (operand_compare_fc)g_armv7_specreg_operand_compare; - operand->print = (operand_print_fc)g_armv7_specreg_operand_print; - - operand->unserialize = (unserialize_operand_fc)g_armv7_specreg_operand_unserialize; - operand->serialize = (serialize_operand_fc)g_armv7_specreg_operand_serialize; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance à initialiser. * -* * -* Description : Initialise une instance d'opérande de registre spécial. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_specreg_operand_init(GArmV7SpecRegOperand *operand) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_specreg_operand_dispose(GArmV7SpecRegOperand *operand) -{ - G_OBJECT_CLASS(g_armv7_specreg_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_specreg_operand_finalize(GArmV7SpecRegOperand *operand) -{ - G_OBJECT_CLASS(g_armv7_specreg_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_specreg_operand_compare(const GArmV7SpecRegOperand *a, const GArmV7SpecRegOperand *b) -{ - int result; /* Bilan à faire remonter */ - - result = sort_unsigned_long(a->reg, b->reg); - - 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_specreg_operand_print(const GArmV7SpecRegOperand *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; - - 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; - - case SRT_MVFR1: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "MVFR1", 5, RTT_REGISTER, NULL); - break; - - case SRT_MVFR0: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "MVFR0", 5, RTT_REGISTER, NULL); - break; - - case SRT_FPEXC: - g_buffer_line_append_text(line, BLC_ASSEMBLY, "FPEXC", 5, RTT_REGISTER, NULL); - break; - - } - -} - - -/****************************************************************************** -* * -* Paramètres : big = indication sur le boutisme à représenter. * -* * -* Description : Crée une représentation d'opérande de registre spécial. * -* * -* Retour : Opérande mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArchOperand *g_armv7_specreg_operand_new(SpecRegType reg) -{ - GArmV7SpecRegOperand *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_ARMV7_SPECREG_OPERAND, NULL); - - result->reg = reg; - - return G_ARCH_OPERAND(result); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à consulter. * -* * -* Description : Indique le type de registre spécial représenté. * -* * -* Retour : Identifiant de registre spécial. * -* * -* Remarques : - * -* * -******************************************************************************/ - -SpecRegType g_armv7_specreg_operand_get_register(const GArmV7SpecRegOperand *operand) -{ - SpecRegType result; /* Désignation à retourner */ - - result = operand->reg; - - 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_armv7_specreg_operand_unserialize(GArmV7SpecRegOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - - parent = G_ARCH_OPERAND_CLASS(g_armv7_specreg_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); - - 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_specreg_operand_serialize(const GArmV7SpecRegOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - - parent = G_ARCH_OPERAND_CLASS(g_armv7_specreg_operand_parent_class); - - result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); - - if (result) - result = extend_packed_buffer(pbuf, &operand->reg, sizeof(SpecRegType), true); - - return result; - -} 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 */ |