From 98570719ff25a4dcde917056e55490bf2a6b1453 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 26 Dec 2021 01:26:28 +0100 Subject: Provide a method to hash all ARMv7 operands. --- plugins/arm/v7/Makefile.am | 2 + plugins/arm/v7/operand-int.h | 51 +++++++++ plugins/arm/v7/operand.c | 188 +++++++++++++++++++++++++++++++++ plugins/arm/v7/operand.h | 55 ++++++++++ plugins/arm/v7/operands/estate.c | 11 +- plugins/arm/v7/operands/iflags.c | 10 +- plugins/arm/v7/operands/it.c | 153 +++++++++++++++++++++++---- plugins/arm/v7/operands/limitation.c | 52 +++++++++- plugins/arm/v7/operands/maccess.c | 194 ++++++++++++++++++++++++++++++++++- plugins/arm/v7/operands/offset.c | 10 +- plugins/arm/v7/operands/register.c | 155 ++++++++++++++++++++++++++-- plugins/arm/v7/operands/reglist.c | 54 +++++++++- plugins/arm/v7/operands/rotation.c | 73 ++++++++++++- plugins/arm/v7/operands/shift.c | 117 ++++++++++++++++++++- src/arch/operand-int.h | 7 ++ src/arch/operand.c | 60 ++++++++++- 16 files changed, 1132 insertions(+), 60 deletions(-) create mode 100644 plugins/arm/v7/operand-int.h create mode 100644 plugins/arm/v7/operand.c create mode 100644 plugins/arm/v7/operand.h diff --git a/plugins/arm/v7/Makefile.am b/plugins/arm/v7/Makefile.am index 5d30876..f75e9b3 100644 --- a/plugins/arm/v7/Makefile.am +++ b/plugins/arm/v7/Makefile.am @@ -9,6 +9,8 @@ libarmv7_la_SOURCES = \ helpers.h \ instruction.h instruction.c \ link.h link.c \ + operand-int.h \ + operand.h operand.c \ post.h post.c \ processor.h processor.c \ pseudo.h pseudo.c \ diff --git a/plugins/arm/v7/operand-int.h b/plugins/arm/v7/operand-int.h new file mode 100644 index 0000000..1832c32 --- /dev/null +++ b/plugins/arm/v7/operand-int.h @@ -0,0 +1,51 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-int.h - prototypes pour la définition interne des opérandes ARMv7 + * + * Copyright (C) 2021 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 . + */ + + +#ifndef _PLUGINS_ARM_V7_OPERAND_INT_H +#define _PLUGINS_ARM_V7_OPERAND_INT_H + + +#include "operand.h" + + +#include + + + +/* Définition générique d'un opérande ARMv7 (instance) */ +struct _GArmV7Operand +{ + GArchOperand parent; /* A laisser en premier */ + +}; + +/* Définition générique d'un opérande ARMv7 (classe) */ +struct _GArmV7OperandClass +{ + GArchOperandClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _PLUGINS_ARM_V7_OPERAND_INT_H */ diff --git a/plugins/arm/v7/operand.c b/plugins/arm/v7/operand.c new file mode 100644 index 0000000..8f93e78 --- /dev/null +++ b/plugins/arm/v7/operand.c @@ -0,0 +1,188 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand.c - opérandes ARMv7 + * + * Copyright (C) 2021 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 . + */ + + +#include "operand.h" + + +#include "operand-int.h" + + + +/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ + + +/* Initialise la classe des affichages de boutisme. */ +static void g_armv7_operand_class_init(GArmV7OperandClass *); + +/* Initialise une instance d'affichage de boutisme. */ +static void g_armv7_operand_init(GArmV7Operand *); + +/* Supprime toutes les références externes. */ +static void g_armv7_operand_dispose(GArmV7Operand *); + +/* Procède à la libération totale de la mémoire. */ +static void g_armv7_operand_finalize(GArmV7Operand *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_armv7_operand_hash(const GArmV7Operand *, bool); + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UN NOUVEAU TYPE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour une de domaine et d'accès. */ +G_DEFINE_TYPE(GArmV7Operand, g_armv7_operand, G_TYPE_ARCH_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des affichages de boutisme. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_operand_class_init(GArmV7OperandClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GArchOperandClass *operand; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_operand_dispose; + object->finalize = (GObjectFinalizeFunc)g_armv7_operand_finalize; + + operand = G_ARCH_OPERAND_CLASS(klass); + + operand->hash = (operand_hash_fc)g_armv7_operand_hash; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'affichage de boutisme. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_operand_init(GArmV7Operand *operand) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_operand_dispose(GArmV7Operand *operand) +{ + G_OBJECT_CLASS(g_armv7_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_operand_finalize(GArmV7Operand *operand) +{ + G_OBJECT_CLASS(g_armv7_operand_parent_class)->finalize(G_OBJECT(operand)); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_armv7_operand_hash(const GArmV7Operand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + lockable_obj_extra_t *extra; /* Données insérées à consulter*/ + GArchOperandClass *class; /* Classe parente normalisée */ + + extra = GET_GOBJECT_EXTRA(G_OBJECT(operand), lockable_obj_extra_t); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + class = G_ARCH_OPERAND_CLASS(g_armv7_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} diff --git a/plugins/arm/v7/operand.h b/plugins/arm/v7/operand.h new file mode 100644 index 0000000..8c80365 --- /dev/null +++ b/plugins/arm/v7/operand.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand.h - prototypes pour les opérandes ARMv7 + * + * Copyright (C) 2017-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 . + */ + + +#ifndef _PLUGINS_ARM_V7_OPERAND_H +#define _PLUGINS_ARM_V7_OPERAND_H + + +#include + + +#include + + + +#define G_TYPE_ARMV7_OPERAND g_armv7_operand_get_type() +#define G_ARMV7_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_OPERAND, GArmV7Operand)) +#define G_IS_ARMV7_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_OPERAND)) +#define G_ARMV7_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_OPERAND, GArmV7OperandClass)) +#define G_IS_ARMV7_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_OPERAND)) +#define G_ARMV7_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_OPERAND, GArmV7OperandClass)) + + +/* Définition générique d'un opérande ARMv7 (instance) */ +typedef struct _GArmV7Operand GArmV7Operand; + +/* Définition générique d'un opérande ARMv7 (classe) */ +typedef struct _GArmV7OperandClass GArmV7OperandClass; + + +/* Indique le type défini par la GLib pour un opérande ARMv7. */ +GType g_armv7_operand_get_type(void); + + + +#endif /* _PLUGINS_ARM_V7_OPERAND_H */ diff --git a/plugins/arm/v7/operands/estate.c b/plugins/arm/v7/operands/estate.c index bf142af..d82ffa1 100644 --- a/plugins/arm/v7/operands/estate.c +++ b/plugins/arm/v7/operands/estate.c @@ -24,10 +24,12 @@ #include "estate.h" -#include #include +#include "../operand-int.h" + + /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ @@ -35,7 +37,7 @@ /* Définition d'un opérande affichant le choix d'un boutisme (instance) */ struct _GArmV7EndianOperand { - GArchOperand parent; /* Instance parente */ + GArmV7Operand parent; /* Instance parente */ }; @@ -43,7 +45,7 @@ struct _GArmV7EndianOperand /* Définition d'un opérande affichant le choix d'un boutisme (classe) */ struct _GArmV7EndianOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -61,6 +63,7 @@ static void g_armv7_endian_operand_dispose(GArmV7EndianOperand *); static void g_armv7_endian_operand_finalize(GArmV7EndianOperand *); + /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ @@ -75,7 +78,7 @@ static void g_armv7_endian_operand_print(const GArmV7EndianOperand *, GBufferLin /* Indique le type défini par la GLib pour une endian de domaine et d'accès. */ -G_DEFINE_TYPE(GArmV7EndianOperand, g_armv7_endian_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7EndianOperand, g_armv7_endian_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** diff --git a/plugins/arm/v7/operands/iflags.c b/plugins/arm/v7/operands/iflags.c index f24f2f4..2e26810 100644 --- a/plugins/arm/v7/operands/iflags.c +++ b/plugins/arm/v7/operands/iflags.c @@ -24,10 +24,12 @@ #include "iflags.h" -#include #include +#include "../operand-int.h" + + /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ @@ -35,7 +37,7 @@ /* Définition d'un opérande précisant un masque d'interruption ARMv7 (instance) */ struct _GArmV7IFlagsOperand { - GArchOperand parent; /* Instance parente */ + GArmV7Operand parent; /* Instance parente */ }; @@ -43,7 +45,7 @@ struct _GArmV7IFlagsOperand /* Définition d'un opérande précisant un masque d'interruption ARMv7 (classe) */ struct _GArmV7IFlagsOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -75,7 +77,7 @@ static void g_armv7_iflags_operand_print(const GArmV7IFlagsOperand *, GBufferLin /* Indique le type défini par la GLib pour un opérande de masque d'interruption ARMv7. */ -G_DEFINE_TYPE(GArmV7IFlagsOperand, g_armv7_iflags_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7IFlagsOperand, g_armv7_iflags_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** diff --git a/plugins/arm/v7/operands/it.c b/plugins/arm/v7/operands/it.c index 54e15ed..b2fb2f6 100644 --- a/plugins/arm/v7/operands/it.c +++ b/plugins/arm/v7/operands/it.c @@ -27,30 +27,55 @@ #include -#include #include #include +#include "../operand-int.h" + + /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ -/* Définition d'un opérande organisant l'application d'une instruction IT (instance) */ -struct _GArmV7ITCondOperand +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _a7itcop_extra_data_t { - GArchOperand parent; /* Instance parente */ + operand_extra_data_t parent; /* A laisser en premier */ ArmCondCode firstcond; /* Condition première */ uint8_t mask; /* Masque de l'interprétation */ +} a7itcop_extra_data_t; + + +/* Définition d'un opérande organisant l'application d'une instruction IT (instance) */ +struct _GArmV7ITCondOperand +{ + GArmV7Operand parent; /* Instance parente */ + }; +/** + * Accès aux informations éventuellement déportées. + */ + +#if __SIZEOF_INT__ == __SIZEOF_LONG__ + +# define GET_ARMV7_ITCOND_OP_EXTRA(op) (a7itcop_extra_data_t *)&op->extra + +#else + +# define GET_ARMV7_ITCOND_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), a7itcop_extra_data_t) + +#endif + + /* Définition d'un opérande organisant l'application d'une instruction IT (classe) */ struct _GArmV7ITCondOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -78,6 +103,9 @@ static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *, const GAr /* Traduit un opérande en version humainement lisible. */ static void g_armv7_itcond_operand_print(const GArmV7ITCondOperand *, GBufferLine *); +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_armv7_itcond_operand_hash(const GArmV7ITCondOperand *, bool); + /* Charge un contenu depuis une mémoire tampon. */ static bool g_armv7_itcond_operand_load(GArmV7ITCondOperand *, GObjectStorage *, packed_buffer_t *); @@ -92,7 +120,7 @@ static bool g_armv7_itcond_operand_store(GArmV7ITCondOperand *, GObjectStorage * /* Indique le type défini par la GLib pour l'application d'une instruction IT. */ -G_DEFINE_TYPE(GArmV7ITCondOperand, g_armv7_itcond_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7ITCondOperand, g_armv7_itcond_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** @@ -120,8 +148,11 @@ static void g_armv7_itcond_operand_class_init(GArmV7ITCondOperandClass *klass) operand = G_ARCH_OPERAND_CLASS(klass); operand->compare = (operand_compare_fc)g_armv7_itcond_operand_compare; + operand->print = (operand_print_fc)g_armv7_itcond_operand_print; + operand->hash = (operand_hash_fc)g_armv7_itcond_operand_hash; + operand->load = (load_operand_fc)g_armv7_itcond_operand_load; operand->store = (store_operand_fc)g_armv7_itcond_operand_store; @@ -200,14 +231,17 @@ static void g_armv7_itcond_operand_finalize(GArmV7ITCondOperand *operand) GArchOperand *g_armv7_itcond_operand_new(uint8_t firstcond, uint8_t mask) { GArmV7ITCondOperand *result; /* Structure à retourner */ + a7itcop_extra_data_t *extra; /* Données insérées à modifier */ if (firstcond > ACC_NV) return NULL; result = g_object_new(G_TYPE_ARMV7_ITCOND_OPERAND, NULL); - result->firstcond = firstcond; - result->mask = mask; + extra = GET_ARMV7_ITCOND_OP_EXTRA(result); + + extra->firstcond = firstcond; + extra->mask = mask; return G_ARCH_OPERAND(result); @@ -229,8 +263,11 @@ GArchOperand *g_armv7_itcond_operand_new(uint8_t firstcond, uint8_t mask) ArmCondCode g_armv7_itcond_operand_get_firstcond(const GArmV7ITCondOperand *operand) { ArmCondCode result; /* Condition à renvoyer */ + a7itcop_extra_data_t *extra; /* Données insérées à modifier */ + + extra = GET_ARMV7_ITCOND_OP_EXTRA(operand); - result = operand->firstcond; + result = extra->firstcond; return result; @@ -252,8 +289,11 @@ ArmCondCode g_armv7_itcond_operand_get_firstcond(const GArmV7ITCondOperand *oper uint8_t g_armv7_itcond_operand_get_mask(const GArmV7ITCondOperand *operand) { uint8_t result; /* Valeur à retourner */ + a7itcop_extra_data_t *extra; /* Données insérées à modifier */ - result = operand->mask; + extra = GET_ARMV7_ITCOND_OP_EXTRA(operand); + + result = extra->mask; return result; @@ -283,12 +323,23 @@ uint8_t g_armv7_itcond_operand_get_mask(const GArmV7ITCondOperand *operand) static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *a, const GArmV7ITCondOperand *b, bool lock) { int result; /* Bilan à faire remonter */ + a7itcop_extra_data_t *ea; /* Données insérées à consulter*/ + a7itcop_extra_data_t *eb; /* Données insérées à consulter*/ GArchOperandClass *class; /* Classe parente normalisée */ - result = sort_boolean(a->firstcond, b->firstcond); + ea = GET_ARMV7_ITCOND_OP_EXTRA(a); + eb = GET_ARMV7_ITCOND_OP_EXTRA(b); + + if (lock) + { + LOCK_GOBJECT_EXTRA(ea); + LOCK_GOBJECT_EXTRA(eb); + } + + result = sort_boolean(ea->firstcond, eb->firstcond); if (result == 0) - result = sort_unsigned_long(a->mask, b->mask); + result = sort_unsigned_long(ea->mask, eb->mask); if (result == 0) { @@ -296,6 +347,12 @@ static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *a, const GA result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); } + if (lock) + { + UNLOCK_GOBJECT_EXTRA(eb); + UNLOCK_GOBJECT_EXTRA(ea); + } + return result; } @@ -316,9 +373,12 @@ static int g_armv7_itcond_operand_compare(const GArmV7ITCondOperand *a, const GA static void g_armv7_itcond_operand_print(const GArmV7ITCondOperand *operand, GBufferLine *line) { + a7itcop_extra_data_t *extra; /* Données insérées à consulter*/ const char *kw; /* Mot clef à imprimer */ - switch (operand->firstcond) + extra = GET_ARMV7_ITCOND_OP_EXTRA(operand); + + switch (extra->firstcond) { case ACC_EQ: kw = "EQ"; break; case ACC_NE: kw = "NE"; break; @@ -352,6 +412,45 @@ static void g_armv7_itcond_operand_print(const GArmV7ITCondOperand *operand, GBu /****************************************************************************** * * +* Paramètres : operand = objet dont l'instance se veut unique. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_armv7_itcond_operand_hash(const GArmV7ITCondOperand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + a7itcop_extra_data_t *extra; /* Données internes à manipuler*/ + GArchOperandClass *class; /* Classe parente normalisée */ + + extra = GET_ARMV7_ITCOND_OP_EXTRA(operand); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + class = G_ARCH_OPERAND_CLASS(g_armv7_itcond_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); + + result ^= extra->firstcond; + + result ^= extra->mask; + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à lire. * @@ -368,16 +467,26 @@ static bool g_armv7_itcond_operand_load(GArmV7ITCondOperand *operand, GObjectSto { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ + uleb128_t value; /* Valeur ULEB128 à charger */ + a7itcop_extra_data_t *extra; /* Données insérées à modifier */ parent = G_ARCH_OPERAND_CLASS(g_armv7_itcond_operand_parent_class); result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); if (result) - result = extract_packed_buffer(pbuf, &operand->firstcond, sizeof(ArmCondCode), true); + { + extra = GET_ARMV7_ITCOND_OP_EXTRA(operand); - if (result) - result = extract_packed_buffer(pbuf, &operand->mask, sizeof(uint8_t), false); + result = unpack_uleb128(&value, pbuf); + + if (result) + extra->firstcond = value; + + if (result) + result = extract_packed_buffer(pbuf, &extra->mask, sizeof(uint8_t), false); + + } return result; @@ -402,16 +511,22 @@ static bool g_armv7_itcond_operand_store(GArmV7ITCondOperand *operand, GObjectSt { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ + a7itcop_extra_data_t *extra; /* Données insérées à modifier */ parent = G_ARCH_OPERAND_CLASS(g_armv7_itcond_operand_parent_class); result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); if (result) - result = extend_packed_buffer(pbuf, &operand->firstcond, sizeof(ArmCondCode), true); + { + extra = GET_ARMV7_ITCOND_OP_EXTRA(operand); - if (result) - result = extend_packed_buffer(pbuf, &operand->mask, sizeof(uint8_t), false); + result = pack_uleb128((uleb128_t []){ extra->firstcond }, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &extra->mask, sizeof(uint8_t), false); + + } return result; diff --git a/plugins/arm/v7/operands/limitation.c b/plugins/arm/v7/operands/limitation.c index 5d22681..b3c6d07 100644 --- a/plugins/arm/v7/operands/limitation.c +++ b/plugins/arm/v7/operands/limitation.c @@ -29,6 +29,9 @@ #include +#include "../operand-int.h" + + /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ @@ -46,7 +49,7 @@ typedef struct _a7limop_extra_data_t /* Définition d'un opérande déterminant une limitation de domaine et d'accès (instance) */ struct _GArmV7LimitationOperand { - GArchOperand parent; /* Instance parente */ + GArmV7Operand parent; /* Instance parente */ }; @@ -54,7 +57,7 @@ struct _GArmV7LimitationOperand /* Définition d'un opérande déterminant une limitation de domaine et d'accès (classe) */ struct _GArmV7LimitationOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -97,6 +100,9 @@ static int g_armv7_limitation_operand_compare(const GArmV7LimitationOperand *, c /* Traduit un opérande en version humainement lisible. */ static void g_armv7_limitation_operand_print(const GArmV7LimitationOperand *, GBufferLine *); +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_armv7_limitation_operand_hash(const GArmV7LimitationOperand *, bool); + /* Charge un contenu depuis une mémoire tampon. */ static bool g_armv7_limitation_operand_load(GArmV7LimitationOperand *, GObjectStorage *, packed_buffer_t *); @@ -111,7 +117,7 @@ static bool g_armv7_limitation_operand_store(GArmV7LimitationOperand *, GObjectS /* Indique le type défini par la GLib pour une limitation de domaine et d'accès. */ -G_DEFINE_TYPE(GArmV7LimitationOperand, g_armv7_limitation_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7LimitationOperand, g_armv7_limitation_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** @@ -138,8 +144,11 @@ static void g_armv7_limitation_operand_class_init(GArmV7LimitationOperandClass * object->finalize = (GObjectFinalizeFunc)g_armv7_limitation_operand_finalize; operand->compare = (operand_compare_fc)g_armv7_limitation_operand_compare; + operand->print = (operand_print_fc)g_armv7_limitation_operand_print; + operand->hash = (operand_hash_fc)g_armv7_limitation_operand_hash; + operand->load = (load_operand_fc)g_armv7_limitation_operand_load; operand->store = (store_operand_fc)g_armv7_limitation_operand_store; @@ -383,6 +392,43 @@ static void g_armv7_limitation_operand_print(const GArmV7LimitationOperand *oper /****************************************************************************** * * +* Paramètres : operand = objet dont l'instance se veut unique. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_armv7_limitation_operand_hash(const GArmV7LimitationOperand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + a7limop_extra_data_t *extra; /* Données internes à manipuler*/ + GArchOperandClass *class; /* Classe parente normalisée */ + + extra = GET_ARMV7_LIMITATION_OP_EXTRA(operand); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + class = G_ARCH_OPERAND_CLASS(g_armv7_limitation_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); + + result ^= extra->type; + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à lire. * diff --git a/plugins/arm/v7/operands/maccess.c b/plugins/arm/v7/operands/maccess.c index 0b0d0b4..3eb3116 100644 --- a/plugins/arm/v7/operands/maccess.c +++ b/plugins/arm/v7/operands/maccess.c @@ -29,12 +29,14 @@ #include -#include #include #include #include +#include "../operand-int.h" + + /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ @@ -42,7 +44,7 @@ /* Définition d'un opérande offrant un accès à la mémoire depuis une base (instance) */ struct _GArmV7MAccessOperand { - GArchOperand parent; /* Instance parente */ + GArmV7Operand parent; /* Instance parente */ GArchOperand *base; /* Base de l'accès en mémoire */ GArchOperand *offset; /* Décalage pour l'adresse */ @@ -54,7 +56,7 @@ struct _GArmV7MAccessOperand /* Définition d'un opérande offrant un accès à la mémoire depuis une base (classe) */ struct _GArmV7MAccessOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -88,6 +90,15 @@ static GArchOperand *g_armv7_maccess_operand_get_inner_operand_from_path(const G /* Traduit un opérande en version humainement lisible. */ static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *, GBufferLine *); +/* Fournit une liste de candidats embarqués par un candidat. */ +static GArchOperand **g_armv7_maccess_operand_list_inner_instances(const GArmV7MAccessOperand *, size_t *); + +/* Met à jour une liste de candidats embarqués par un candidat. */ +static void g_armv7_maccess_operand_update_inner_instances(GArmV7MAccessOperand *, GArchOperand **, size_t); + +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_armv7_maccess_operand_hash(const GArmV7MAccessOperand *, bool); + /* Charge un contenu depuis une mémoire tampon. */ static bool g_armv7_maccess_operand_load(GArmV7MAccessOperand *, GObjectStorage *, packed_buffer_t *); @@ -102,7 +113,7 @@ static bool g_armv7_maccess_operand_store(GArmV7MAccessOperand *, GObjectStorage /* Indique le type défini par la GLib pour un accès à la mémoire depuis une base. */ -G_DEFINE_TYPE(GArmV7MAccessOperand, g_armv7_maccess_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7MAccessOperand, g_armv7_maccess_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** @@ -135,6 +146,10 @@ static void g_armv7_maccess_operand_class_init(GArmV7MAccessOperandClass *klass) operand->print = (operand_print_fc)g_armv7_maccess_operand_print; + operand->list_inner = (operand_list_inners_fc)g_armv7_maccess_operand_list_inner_instances; + operand->update_inner = (operand_update_inners_fc)g_armv7_maccess_operand_update_inner_instances; + operand->hash = (operand_hash_fc)g_armv7_maccess_operand_hash; + operand->load = (load_operand_fc)g_armv7_maccess_operand_load; operand->store = (store_operand_fc)g_armv7_maccess_operand_store; @@ -534,6 +549,177 @@ static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, G /****************************************************************************** * * +* Paramètres : operand = objet dont l'instance se veut unique. * +* count = quantité d'instances à l'unicité internes. * +* * +* Description : Fournit une liste de candidats embarqués par un candidat. * +* * +* Retour : Liste de candidats internes ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchOperand **g_armv7_maccess_operand_list_inner_instances(const GArmV7MAccessOperand *operand, size_t *count) +{ + GArchOperand **result; /* Instances à retourner */ + size_t idx; /* Indice de traitement */ + + *count = 1; + + if (operand->offset != NULL) + (*count)++; + + if (operand->shift != NULL) + (*count)++; + + result = malloc(*count * sizeof(GArchOperand *)); + + result[0] = operand->base; + g_object_ref(G_OBJECT(result[0])); + + if (operand->offset != NULL) + { + result[1] = operand->offset; + g_object_ref(G_OBJECT(result[1])); + + idx = 2; + + } + else + idx = 1; + + if (operand->shift != NULL) + { + result[idx] = operand->shift; + g_object_ref(G_OBJECT(result[idx])); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* instances = liste de candidats internes devenus singletons. * +* count = quantité d'instances à l'unicité internes. * +* * +* Description : Met à jour une liste de candidats embarqués par un candidat. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_maccess_operand_update_inner_instances(GArmV7MAccessOperand *operand, GArchOperand **instances, size_t count) +{ +#ifndef NDEBUG + size_t idx_check; /* Décompte des éléments utiles*/ +#endif + size_t i; /* Boucle de parcours */ + +#ifndef NDEBUG + idx_check = 1; + + if (operand->offset != NULL) + (idx_check)++; + + if (operand->shift != NULL) + (idx_check)++; + + assert(count == idx_check); +#endif + + for (i = 0; i < count; i++) + { + switch (i) + { + case 0: + g_object_unref(G_OBJECT(operand->base)); + operand->base = instances[i]; + break; + + case 1: + if (operand->offset != NULL) + { + g_object_unref(G_OBJECT(operand->offset)); + operand->offset = instances[i]; + } + else + { + assert(count == 2); + + g_object_unref(G_OBJECT(operand->shift)); + operand->shift = instances[i]; + + } + break; + + case 2: + g_object_unref(G_OBJECT(operand->shift)); + operand->shift = instances[i]; + break; + + } + + g_object_ref(G_OBJECT(instances[i])); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_armv7_maccess_operand_hash(const GArmV7MAccessOperand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + lockable_obj_extra_t *extra; /* Données insérées à consulter*/ + GArchOperandClass *class; /* Classe parente normalisée */ + size_t count; /* Quantité d'éléments utiles */ + + extra = GET_GOBJECT_EXTRA(G_OBJECT(operand), lockable_obj_extra_t); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + class = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); + + count = 1; + + if (operand->offset != NULL) + (count)++; + + if (operand->shift != NULL) + (count)++; + + result ^= count; + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à lire. * diff --git a/plugins/arm/v7/operands/offset.c b/plugins/arm/v7/operands/offset.c index fc68638..1634230 100644 --- a/plugins/arm/v7/operands/offset.c +++ b/plugins/arm/v7/operands/offset.c @@ -28,10 +28,12 @@ #include -#include #include +#include "../operand-int.h" + + /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ @@ -39,7 +41,7 @@ /* Définition d'un opérande visant à constituer un décalage relatif ARMv7 (instance) */ struct _GArmV7OffsetOperand { - GArchOperand parent; /* Instance parente */ + GArmV7Operand parent; /* Instance parente */ GArchOperand *value; /* Valeur du décalage */ @@ -49,7 +51,7 @@ struct _GArmV7OffsetOperand /* Définition d'un opérande visant à constituer un décalage relatif ARMv7 (classe) */ struct _GArmV7OffsetOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -97,7 +99,7 @@ static bool g_armv7_offset_operand_store(GArmV7OffsetOperand *, GObjectStorage * /* Indique le type défini par la GLib pour un décalage relatif ARMv7. */ -G_DEFINE_TYPE(GArmV7OffsetOperand, g_armv7_offset_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7OffsetOperand, g_armv7_offset_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** diff --git a/plugins/arm/v7/operands/register.c b/plugins/arm/v7/operands/register.c index dce8fef..026d0d5 100644 --- a/plugins/arm/v7/operands/register.c +++ b/plugins/arm/v7/operands/register.c @@ -25,6 +25,7 @@ #include +#include #include @@ -32,13 +33,21 @@ /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _a7regop_extra_data_t +{ + operand_extra_data_t parent; /* A laisser en premier */ + + uint8_t alignment; /* Eventuel alignement */ + +} a7regop_extra_data_t; + + /* Définition d'un opérande visant un registre ARMv7 (instance) */ struct _GArmV7RegisterOperand { GRegisterOperand parent; /* Instance parente */ - unsigned int alignment; /* Eventuel alignement */ - }; @@ -50,6 +59,21 @@ struct _GArmV7RegisterOperandClass }; +/** + * Accès aux informations éventuellement déportées. + */ + +#if __SIZEOF_INT__ == __SIZEOF_LONG__ + +# define GET_ARMV7_REGISTER_OP_EXTRA(op) (a7regop_extra_data_t *)&op->extra + +#else + +# define GET_ARMV7_REGISTER_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), a7regop_extra_data_t) + +#endif + + /* Initialise la classe des opérandes de registre ARMv7. */ static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *); @@ -67,9 +91,15 @@ static void g_armv7_register_operand_finalize(GArmV7RegisterOperand *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Compare un opérande avec un autre. */ +static int g_armv7_register_operand_compare(const GArmV7RegisterOperand *, const GArmV7RegisterOperand *, bool); + /* Traduit un opérande en version humainement lisible. */ static void g_armv7_register_operand_print(const GArmV7RegisterOperand *, GBufferLine *); +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_armv7_register_operand_hash(const GArmV7RegisterOperand *, bool); + /* Charge un contenu depuis une mémoire tampon. */ static bool g_armv7_register_operand_load(GArmV7RegisterOperand *, GObjectStorage *, packed_buffer_t *); @@ -111,8 +141,12 @@ static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *klas operand = G_ARCH_OPERAND_CLASS(klass); + operand->compare = (operand_compare_fc)g_armv7_register_operand_compare; + operand->print = (operand_print_fc)g_armv7_register_operand_print; + operand->hash = (operand_hash_fc)g_armv7_register_operand_hash; + operand->load = (load_operand_fc)g_armv7_register_operand_load; operand->store = (store_operand_fc)g_armv7_register_operand_store; @@ -215,9 +249,20 @@ GArchOperand *g_armv7_register_operand_new(GArmV7Register *reg) void g_armv7_register_operand_define_alignement(GArmV7RegisterOperand *operand, unsigned int align) { - operand->alignment = align; + a7regop_extra_data_t *extra; /* Données internes à manipuler*/ + + extra = GET_ARMV7_REGISTER_OP_EXTRA(operand); + + LOCK_GOBJECT_EXTRA(extra); - g_arch_operand_set_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT); + extra->alignment = align; + + if (align > 0) + _g_arch_operand_set_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT, false); + else + _g_arch_operand_unset_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT, false); + + UNLOCK_GOBJECT_EXTRA(extra); } @@ -250,6 +295,55 @@ void g_armv7_register_operand_write_back(GArmV7RegisterOperand *operand, bool wb /****************************************************************************** * * +* Paramètres : a = premier opérande à consulter. * +* b = second opérande à consulter. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Compare un opérande avec un autre. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int g_armv7_register_operand_compare(const GArmV7RegisterOperand *a, const GArmV7RegisterOperand *b, bool lock) +{ + int result; /* Bilan à faire remonter */ + a7regop_extra_data_t *ea; /* Données insérées à consulter*/ + a7regop_extra_data_t *eb; /* Données insérées à consulter*/ + GArchOperandClass *class; /* Classe parente normalisée */ + + ea = GET_ARMV7_REGISTER_OP_EXTRA(a); + eb = GET_ARMV7_REGISTER_OP_EXTRA(b); + + if (lock) + { + LOCK_GOBJECT_EXTRA(ea); + LOCK_GOBJECT_EXTRA(eb); + } + + result = sort_unsigned_long(ea->alignment, eb->alignment); + + if (result == 0) + { + class = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); + } + + if (lock) + { + UNLOCK_GOBJECT_EXTRA(eb); + UNLOCK_GOBJECT_EXTRA(ea); + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = opérande à traiter. * * line = ligne tampon où imprimer l'opérande donné. * * * @@ -277,6 +371,43 @@ static void g_armv7_register_operand_print(const GArmV7RegisterOperand *operand, /****************************************************************************** * * +* Paramètres : operand = objet dont l'instance se veut unique. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_armv7_register_operand_hash(const GArmV7RegisterOperand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + a7regop_extra_data_t *extra; /* Données internes à manipuler*/ + GArchOperandClass *class; /* Classe parente normalisée */ + + extra = GET_ARMV7_REGISTER_OP_EXTRA(operand); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + class = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); + + result ^= extra->alignment; + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à lire. * @@ -293,13 +424,19 @@ static bool g_armv7_register_operand_load(GArmV7RegisterOperand *operand, GObjec { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ + a7regop_extra_data_t *extra; /* Données internes à manipuler*/ parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); if (result && g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT)) - result = extract_packed_buffer(pbuf, &operand->alignment, sizeof(unsigned int), true); + { + extra = GET_ARMV7_REGISTER_OP_EXTRA(operand); + + result = extract_packed_buffer(pbuf, &extra->alignment, sizeof(uint8_t), false); + + } return result; @@ -324,13 +461,19 @@ static bool g_armv7_register_operand_store(GArmV7RegisterOperand *operand, GObje { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ + a7regop_extra_data_t *extra; /* Données internes à manipuler*/ parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); if (result && g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT)) - result = extend_packed_buffer(pbuf, &operand->alignment, sizeof(unsigned int), true); + { + extra = GET_ARMV7_REGISTER_OP_EXTRA(operand); + + result = extend_packed_buffer(pbuf, &extra->alignment, sizeof(uint8_t), false); + + } return result; diff --git a/plugins/arm/v7/operands/reglist.c b/plugins/arm/v7/operands/reglist.c index 21407a4..d53a7e1 100644 --- a/plugins/arm/v7/operands/reglist.c +++ b/plugins/arm/v7/operands/reglist.c @@ -28,13 +28,13 @@ #include -#include #include #include #include #include +#include "../operand-int.h" #include "../registers/basic.h" @@ -45,7 +45,7 @@ /* Définition d'un opérande listant une série de registres ARM (instance) */ struct _GArmV7RegListOperand { - GArchOperand parent; /* Instance parente */ + GArmV7Operand parent; /* Instance parente */ GArmV7Register **registers; /* Liste de registres intégrés */ size_t count; /* Taille de cette liste */ @@ -56,7 +56,7 @@ struct _GArmV7RegListOperand /* Définition d'un opérande listant une série de registres ARM (classe) */ struct _GArmV7RegListOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -84,6 +84,9 @@ static int g_armv7_reglist_operand_compare(const GArmV7RegListOperand *, const G /* Traduit un opérande en version humainement lisible. */ static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *, GBufferLine *); +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_armv7_reglist_operand_hash(const GArmV7RegListOperand *, bool); + /* Charge un contenu depuis une mémoire tampon. */ static bool g_armv7_reglist_operand_load(GArmV7RegListOperand *, GObjectStorage *, packed_buffer_t *); @@ -98,7 +101,7 @@ static bool g_armv7_reglist_operand_store(GArmV7RegListOperand *, GObjectStorage /* Indique le type défini par la GLib pour une liste de registres ARM. */ -G_DEFINE_TYPE(GArmV7RegListOperand, g_armv7_reglist_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7RegListOperand, g_armv7_reglist_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** @@ -127,6 +130,8 @@ static void g_armv7_reglist_operand_class_init(GArmV7RegListOperandClass *klass) operand->compare = (operand_compare_fc)g_armv7_reglist_operand_compare; operand->print = (operand_print_fc)g_armv7_reglist_operand_print; + operand->hash = (operand_hash_fc)g_armv7_reglist_operand_hash; + operand->load = (load_operand_fc)g_armv7_reglist_operand_load; operand->store = (store_operand_fc)g_armv7_reglist_operand_store; @@ -428,6 +433,47 @@ static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *operand, G /****************************************************************************** * * +* Paramètres : operand = objet dont l'instance se veut unique. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_armv7_reglist_operand_hash(const GArmV7RegListOperand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + lockable_obj_extra_t *extra; /* Données insérées à consulter*/ + GArchOperandClass *class; /* Classe parente normalisée */ + size_t i; /* Boucle de parcours */ + + extra = GET_GOBJECT_EXTRA(G_OBJECT(operand), lockable_obj_extra_t); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + class = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); + + result ^= operand->count; + + for (i = 0; i < operand->count; i++) + result ^= g_arch_register_hash(G_ARCH_REGISTER(operand->registers[i])); + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à lire. * diff --git a/plugins/arm/v7/operands/rotation.c b/plugins/arm/v7/operands/rotation.c index 85f7290..f90c76b 100644 --- a/plugins/arm/v7/operands/rotation.c +++ b/plugins/arm/v7/operands/rotation.c @@ -24,15 +24,18 @@ #include "rotation.h" +#include #include #include -#include #include #include +#include "../operand-int.h" + + /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ @@ -40,7 +43,7 @@ /* Définition d'un opérande visant une opérande de rotation ARMv7 (instance) */ struct _GArmV7RotationOperand { - GArchOperand parent; /* Instance parente */ + GArmV7Operand parent; /* Instance parente */ GArchOperand *value; /* Valeur du décalage */ @@ -50,7 +53,7 @@ struct _GArmV7RotationOperand /* Définition d'un opérande visant une opérande de rotation ARMv7 (classe) */ struct _GArmV7RotationOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -84,6 +87,12 @@ static GArchOperand *g_armv7_rotation_operand_get_inner_operand_from_path(const /* Traduit un opérande en version humainement lisible. */ static void g_armv7_rotation_operand_print(const GArmV7RotationOperand *, GBufferLine *); +/* Fournit une liste de candidats embarqués par un candidat. */ +static GArchOperand **g_armv7_rotation_operand_list_inner_instances(const GArmV7RotationOperand *, size_t *); + +/* Met à jour une liste de candidats embarqués par un candidat. */ +static void g_armv7_rotation_operand_update_inner_instances(GArmV7RotationOperand *, GArchOperand **, size_t); + /* Charge un contenu depuis une mémoire tampon. */ static bool g_armv7_rotation_operand_load(GArmV7RotationOperand *, GObjectStorage *, packed_buffer_t *); @@ -98,7 +107,7 @@ static bool g_armv7_rotation_operand_store(GArmV7RotationOperand *, GObjectStora /* Indique le type défini par la GLib pour une opérande de rotation ARMv7. */ -G_DEFINE_TYPE(GArmV7RotationOperand, g_armv7_rotation_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7RotationOperand, g_armv7_rotation_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** @@ -131,6 +140,9 @@ static void g_armv7_rotation_operand_class_init(GArmV7RotationOperandClass *klas operand->print = (operand_print_fc)g_armv7_rotation_operand_print; + operand->list_inner = (operand_list_inners_fc)g_armv7_rotation_operand_list_inner_instances; + operand->update_inner = (operand_update_inners_fc)g_armv7_rotation_operand_update_inner_instances; + operand->load = (load_operand_fc)g_armv7_rotation_operand_load; operand->store = (store_operand_fc)g_armv7_rotation_operand_store; @@ -397,6 +409,59 @@ static void g_armv7_rotation_operand_print(const GArmV7RotationOperand *operand, /****************************************************************************** * * +* Paramètres : operand = objet dont l'instance se veut unique. * +* count = quantité d'instances à l'unicité internes. * +* * +* Description : Fournit une liste de candidats embarqués par un candidat. * +* * +* Retour : Liste de candidats internes ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchOperand **g_armv7_rotation_operand_list_inner_instances(const GArmV7RotationOperand *operand, size_t *count) +{ + GArchOperand **result; /* Instances à retourner */ + + *count = 1; + + result = malloc(*count * sizeof(GArchOperand *)); + + result[0] = operand->value; + g_object_ref(G_OBJECT(result[0])); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* instances = liste de candidats internes devenus singletons. * +* count = quantité d'instances à l'unicité internes. * +* * +* Description : Met à jour une liste de candidats embarqués par un candidat. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_rotation_operand_update_inner_instances(GArmV7RotationOperand *operand, GArchOperand **instances, size_t count) +{ + assert(count == 1); + + g_object_unref(G_OBJECT(operand->value)); + operand->value = instances[0]; + +} + + +/****************************************************************************** +* * * Paramètres : operand = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à lire. * diff --git a/plugins/arm/v7/operands/shift.c b/plugins/arm/v7/operands/shift.c index 8c00753..55f2a22 100644 --- a/plugins/arm/v7/operands/shift.c +++ b/plugins/arm/v7/operands/shift.c @@ -24,15 +24,18 @@ #include "shift.h" +#include #include #include -#include #include #include +#include "../operand-int.h" + + /* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ @@ -50,7 +53,7 @@ typedef struct _a7shiftop_extra_data_t /* Définition d'un opérande visant une opérande de décalage ARMv7 (instance) */ struct _GArmV7ShiftOperand { - GArchOperand parent; /* Instance parente */ + GArmV7Operand parent; /* Instance parente */ GArchOperand *shift_value; /* Valeur du décalage */ @@ -60,7 +63,7 @@ struct _GArmV7ShiftOperand /* Définition d'un opérande visant une opérande de décalage ARMv7 (classe) */ struct _GArmV7ShiftOperandClass { - GArchOperandClass parent; /* Classe parente */ + GArmV7OperandClass parent; /* Classe parente */ }; @@ -109,6 +112,15 @@ static GArchOperand *g_armv7_shift_operand_get_inner_operand_from_path(const GAr /* Traduit un opérande en version humainement lisible. */ static void g_armv7_shift_operand_print(const GArmV7ShiftOperand *, GBufferLine *); +/* Fournit une liste de candidats embarqués par un candidat. */ +static GArchOperand **g_armv7_shift_operand_list_inner_instances(const GArmV7ShiftOperand *, size_t *); + +/* Met à jour une liste de candidats embarqués par un candidat. */ +static void g_armv7_shift_operand_update_inner_instances(GArmV7ShiftOperand *, GArchOperand **, size_t); + +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_armv7_shift_operand_hash(const GArmV7ShiftOperand *, bool); + /* Charge un contenu depuis une mémoire tampon. */ static bool g_armv7_shift_operand_load(GArmV7ShiftOperand *, GObjectStorage *, packed_buffer_t *); @@ -123,7 +135,7 @@ static bool g_armv7_shift_operand_store(GArmV7ShiftOperand *, GObjectStorage *, /* Indique le type défini par la GLib pour une opérande de décalage ARMv7. */ -G_DEFINE_TYPE(GArmV7ShiftOperand, g_armv7_shift_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GArmV7ShiftOperand, g_armv7_shift_operand, G_TYPE_ARMV7_OPERAND); /****************************************************************************** @@ -156,6 +168,10 @@ static void g_armv7_shift_operand_class_init(GArmV7ShiftOperandClass *klass) operand->print = (operand_print_fc)g_armv7_shift_operand_print; + operand->list_inner = (operand_list_inners_fc)g_armv7_shift_operand_list_inner_instances; + operand->update_inner = (operand_update_inners_fc)g_armv7_shift_operand_update_inner_instances; + operand->hash = (operand_hash_fc)g_armv7_shift_operand_hash; + operand->load = (load_operand_fc)g_armv7_shift_operand_load; operand->store = (store_operand_fc)g_armv7_shift_operand_store; @@ -476,6 +492,99 @@ static void g_armv7_shift_operand_print(const GArmV7ShiftOperand *operand, GBuff /****************************************************************************** * * +* Paramètres : operand = objet dont l'instance se veut unique. * +* count = quantité d'instances à l'unicité internes. * +* * +* Description : Fournit une liste de candidats embarqués par un candidat. * +* * +* Retour : Liste de candidats internes ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GArchOperand **g_armv7_shift_operand_list_inner_instances(const GArmV7ShiftOperand *operand, size_t *count) +{ + GArchOperand **result; /* Instances à retourner */ + + *count = 1; + + result = malloc(*count * sizeof(GArchOperand *)); + + result[0] = operand->shift_value; + g_object_ref(G_OBJECT(result[0])); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* instances = liste de candidats internes devenus singletons. * +* count = quantité d'instances à l'unicité internes. * +* * +* Description : Met à jour une liste de candidats embarqués par un candidat. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_shift_operand_update_inner_instances(GArmV7ShiftOperand *operand, GArchOperand **instances, size_t count) +{ + assert(count == 1); + + g_object_unref(G_OBJECT(operand->shift_value)); + operand->shift_value = instances[0]; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_armv7_shift_operand_hash(const GArmV7ShiftOperand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + lockable_obj_extra_t *extra; /* Données insérées à consulter*/ + GArchOperandClass *class; /* Classe parente normalisée */ + a7shiftop_extra_data_t *op_extra; /* Données internes à manipuler*/ + + extra = GET_GOBJECT_EXTRA(G_OBJECT(operand), lockable_obj_extra_t); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + class = G_ARCH_OPERAND_CLASS(g_armv7_shift_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); + + op_extra = GET_ARMV7_SHIFT_OP_EXTRA(operand); + + result ^= op_extra->shift_type; + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à lire. * diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h index d2f43f1..dc505b6 100644 --- a/src/arch/operand-int.h +++ b/src/arch/operand-int.h @@ -135,5 +135,12 @@ struct _GArchOperandClass #endif +/* Ajoute une information complémentaire à un opérande. */ +bool _g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag, bool); + +/* Retire une information complémentaire à un opérande. */ +bool _g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag, bool); + + #endif /* _ARCH_OPERAND_INT_H */ diff --git a/src/arch/operand.c b/src/arch/operand.c index e95f24e..81aa633 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -442,6 +442,7 @@ char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBin * * * Paramètres : operand = opérande à venir modifier. * * flag = drapeau d'information complémentaire à planter. * +* lock = indique un besoin de verrouillage des données. * * * * Description : Ajoute une information complémentaire à un opérande. * * * @@ -451,7 +452,7 @@ char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBin * * ******************************************************************************/ -bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) +bool _g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag, bool lock) { bool result; /* Bilan à retourner */ operand_extra_data_t *extra; /* Données insérées à modifier */ @@ -460,13 +461,39 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) extra = GET_ARCH_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); + if (lock) + LOCK_GOBJECT_EXTRA(extra); result = !(extra->flags & flag); extra->flags |= flag; - UNLOCK_GOBJECT_EXTRA(extra); + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à venir modifier. * +* flag = drapeau d'information complémentaire à planter. * +* * +* Description : Ajoute une information complémentaire à un opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) +{ + bool result; /* Bilan à retourner */ + + result = _g_arch_operand_set_flag(operand, flag, true); return result; @@ -477,6 +504,7 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) * * * Paramètres : operand = opérande à venir modifier. * * flag = drapeau d'information complémentaire à planter. * +* lock = indique un besoin de verrouillage des données. * * * * Description : Retire une information complémentaire à un opérande. * * * @@ -486,7 +514,7 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) * * ******************************************************************************/ -bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) +bool _g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag, bool lock) { bool result; /* Bilan à retourner */ operand_extra_data_t *extra; /* Données insérées à modifier */ @@ -510,6 +538,30 @@ bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) /****************************************************************************** * * +* Paramètres : operand = opérande à venir modifier. * +* flag = drapeau d'information complémentaire à planter. * +* * +* Description : Retire une information complémentaire à un opérande. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) +{ + bool result; /* Bilan à retourner */ + + result = _g_arch_operand_unset_flag(operand, flag, true); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = opérande à venir consulter. * * flag = drapeau d'information à rechercher. * * * -- cgit v0.11.2-87-g4458