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