diff options
Diffstat (limited to 'src/arch/operand.c')
-rw-r--r-- | src/arch/operand.c | 639 |
1 files changed, 588 insertions, 51 deletions
diff --git a/src/arch/operand.c b/src/arch/operand.c index 3758d7f..0f5ffd5 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -31,14 +31,15 @@ #include "operand-int.h" #include "storage.h" +#include "../analysis/storage/serialize-int.h" +#include "../common/fnv1a.h" #include "../common/sort.h" #include "../core/logs.h" +#include "../glibext/singleton-int.h" -/* ---------------------------------------------------------------------------------- */ -/* DEFINITION D'OPERANDE QUELCONQUE */ -/* ---------------------------------------------------------------------------------- */ +/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */ /* Initialise la classe générique des opérandes. */ @@ -47,29 +48,76 @@ static void g_arch_operand_class_init(GArchOperandClass *); /* Initialise une instance d'opérande d'architecture. */ static void g_arch_operand_init(GArchOperand *); +/* Procède à l'initialisation de l'interface de singleton. */ +static void g_arch_operand_singleton_init(GSingletonCandidateInterface *); + +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_arch_operand_serializable_init(GSerializableObjectInterface *); + /* Supprime toutes les références externes. */ static void g_arch_operand_dispose(GArchOperand *); /* Procède à la libération totale de la mémoire. */ static void g_arch_operand_finalize(GArchOperand *); +/* Compare un opérande avec un autre. */ +static int _g_arch_operand_compare(const GArchOperand *, const GArchOperand *, bool); -/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ +/* ------------------------ CONTROLE DU VOLUME DES INSTANCES ------------------------ */ -/* Charge un opérande depuis une mémoire tampon. */ -static bool g_arch_operand_unserialize(GArchOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *); -/* Sauvegarde un opérande dans une mémoire tampon. */ -static bool g_arch_operand_serialize(const GArchOperand *, GAsmStorage *, packed_buffer_t *); +/* Fournit une liste de candidats embarqués par un candidat. */ +GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *, size_t *); +/* Met à jour une liste de candidats embarqués par un candidat. */ +void g_arch_operand_update_inner_instances(GArchOperand *, GArchOperand **, size_t); +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint _g_arch_operand_hash(const GArchOperand *, bool); -/* Indique le type défini pour un opérande d'architecture. */ -G_DEFINE_TYPE(GArchOperand, g_arch_operand, G_TYPE_OBJECT); +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_arch_operand_hash(const GArchOperand *); + +/* Détermine si deux candidats à l'unicité sont identiques. */ +static gboolean g_arch_operand_is_equal(const GArchOperand *, const GArchOperand *); + +/* Marque un candidat comme figé. */ +static void g_arch_operand_set_read_only(GArchOperand *); + +/* Indique si le candidat est figé. */ +static bool g_arch_operand_is_read_only(GArchOperand *); + + + +/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ +/* Charge un contenu depuis une mémoire tampon. */ +static bool _g_arch_operand_load(GArchOperand *, GObjectStorage *, packed_buffer_t *); + +/* Charge un contenu depuis une mémoire tampon. */ +static bool g_arch_operand_load(GArchOperand *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un contenu dans une mémoire tampon. */ +static bool _g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un contenu dans une mémoire tampon. */ +static bool g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'OPERANDE QUELCONQUE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un opérande d'architecture. */ +G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_SINGLETON_CANDIDATE, g_arch_operand_singleton_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_operand_serializable_init)); + /****************************************************************************** * * @@ -95,8 +143,12 @@ static void g_arch_operand_class_init(GArchOperandClass *klass) operand = G_ARCH_OPERAND_CLASS(klass); - operand->unserialize = (unserialize_operand_fc)g_arch_operand_unserialize; - operand->serialize = (serialize_operand_fc)g_arch_operand_serialize; + operand->compare = (operand_compare_fc)_g_arch_operand_compare; + + operand->hash = _g_arch_operand_hash; + + operand->load = (load_operand_fc)_g_arch_operand_load; + operand->store = (store_operand_fc)_g_arch_operand_store; } @@ -115,6 +167,57 @@ static void g_arch_operand_class_init(GArchOperandClass *klass) static void g_arch_operand_init(GArchOperand *operand) { + operand_extra_data_t *extra; /* Données insérées à modifier */ + + extra = GET_ARCH_OP_EXTRA(operand); + + INIT_GOBJECT_EXTRA_LOCK(extra); + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de singleton. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_operand_singleton_init(GSingletonCandidateInterface *iface) +{ + iface->list_inner = (list_inner_instances_fc)g_arch_operand_list_inner_instances; + iface->update_inner = (update_inner_instances_fc)g_arch_operand_update_inner_instances; + + iface->hash = (hash_candidate_fc)g_arch_operand_hash; + iface->is_equal = (is_candidate_equal_fc)g_arch_operand_is_equal; + + iface->set_ro = (set_candidate_ro_fc)g_arch_operand_set_read_only; + iface->is_ro = (is_candidate_ro_fc)g_arch_operand_is_read_only; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de sérialisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_operand_serializable_init(GSerializableObjectInterface *iface) +{ + iface->load = (load_serializable_object_cb)g_arch_operand_load; + iface->store = (store_serializable_object_cb)g_arch_operand_store; } @@ -159,6 +262,38 @@ static void g_arch_operand_finalize(GArchOperand *operand) /****************************************************************************** * * +* 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_arch_operand_compare(const GArchOperand *a, const GArchOperand *b, bool lock) +{ + int result; /* Bilan à faire remonter */ + operand_extra_data_t *ea; /* Données insérées à consulter*/ + operand_extra_data_t *eb; /* Données insérées à consulter*/ + + assert(!lock); + + ea = GET_ARCH_OP_EXTRA(a); + eb = GET_ARCH_OP_EXTRA(b); + + result = sort_unsigned_long(ea->flags, eb->flags); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : a = premier opérande à consulter. * * b = second opérande à consulter. * * * @@ -184,7 +319,7 @@ int g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b) result = sort_unsigned_long(type_a, type_b); if (result == 0) - result = G_ARCH_OPERAND_GET_CLASS(a)->compare(a, b); + result = G_ARCH_OPERAND_GET_CLASS(a)->compare(a, b, true); return result; @@ -273,6 +408,9 @@ void g_arch_operand_print(const GArchOperand *operand, GBufferLine *line) } +#ifdef INCLUDE_GTK_SUPPORT + + /****************************************************************************** * * * Paramètres : operand = opérande à consulter. * @@ -303,20 +441,53 @@ char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBin } +#endif -/* ---------------------------------------------------------------------------------- */ -/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ -/* ---------------------------------------------------------------------------------- */ + +/****************************************************************************** +* * +* 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. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +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 */ + + assert(flag <= AOF_HIGH_USER); + + extra = GET_ARCH_OP_EXTRA(operand); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + result = !(extra->flags & flag); + + extra->flags |= flag; + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} /****************************************************************************** * * -* 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. * +* Paramètres : operand = opérande à venir modifier. * +* flag = drapeau d'information complémentaire à planter. * * * -* Description : Charge un opérande depuis une mémoire tampon. * +* Description : Ajoute une information complémentaire à un opérande. * * * * Retour : Bilan de l'opération. * * * @@ -324,11 +495,11 @@ char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBin * * ******************************************************************************/ -static bool g_arch_operand_unserialize(GArchOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) +bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) { bool result; /* Bilan à retourner */ - result = true; + result = _g_arch_operand_set_flag(operand, flag, true); return result; @@ -337,37 +508,231 @@ static bool g_arch_operand_unserialize(GArchOperand *operand, GAsmStorage *stora /****************************************************************************** * * -* Paramètres : storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * -* pbuf = zone tampon à remplir. * +* 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. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +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 */ + + assert(flag <= AOF_HIGH_USER); + + extra = GET_ARCH_OP_EXTRA(operand); + + LOCK_GOBJECT_EXTRA(extra); + + result = (extra->flags & flag); + + extra->flags &= ~flag; + + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * +* 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 : - * * * -* Description : Charge un opérande depuis une mémoire tampon. * +******************************************************************************/ + +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; + +} + + +/****************************************************************************** * * -* Retour : Opérande d'assemblage constitué ou NULL en cas d'échec. * +* Paramètres : operand = opérande à venir consulter. * +* flag = drapeau d'information à rechercher. * +* * +* Description : Détermine si un opérande possède un fanion particulier. * +* * +* Retour : Bilan de la détection. * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *g_arch_operand_load(GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) +bool g_arch_operand_has_flag(const GArchOperand *operand, ArchOperandFlag flag) { - GArchOperand *result; /* Instance à retourner */ - bool status; /* Bilan du chargement */ + bool result; /* Bilan à retourner */ + operand_extra_data_t *extra; /* Données insérées à modifier */ + + assert(flag <= AOF_HIGH_USER); + + extra = GET_ARCH_OP_EXTRA(operand); + + LOCK_GOBJECT_EXTRA(extra); + + result = (extra->flags & flag); + + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} - result = G_ARCH_OPERAND(g_asm_storage_create_object(storage, pbuf)); - if (result != NULL) +/****************************************************************************** +* * +* Paramètres : operand = opérande à venir consulter. * +* * +* Description : Fournit les particularités de l'opérande. * +* * +* Retour : Somme de tous les fanions associés à l'opérande. * +* * +* Remarques : - * +* * +******************************************************************************/ + +ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *operand) +{ + ArchOperandFlag result; /* Fanions à retourner */ + operand_extra_data_t *extra; /* Données insérées à modifier */ + + extra = GET_ARCH_OP_EXTRA(operand); + + LOCK_GOBJECT_EXTRA(extra); + + result = extra->flags; + + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CONTROLE DU VOLUME DES INSTANCES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand, size_t *count) +{ + GArchOperand **result; /* Instances à retourner */ + GArchOperandClass *class; /* Classe associée à l'objet */ + + class = G_ARCH_OPERAND_GET_CLASS(operand); + + if (class->list_inner == NULL) { - status = G_ARCH_OPERAND_GET_CLASS(result)->unserialize(result, storage, format, pbuf); + *count = 0; + result = NULL; + } + + else + result = class->list_inner(operand, count); + + return result; + +} - if (!status) - { - g_object_unref(G_OBJECT(result)); - result = NULL; - } +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +void g_arch_operand_update_inner_instances(GArchOperand *operand, GArchOperand **instances, size_t count) +{ + GArchOperandClass *class; /* Classe associée à l'objet */ + + class = G_ARCH_OPERAND_GET_CLASS(operand); + + if (class->update_inner == NULL) + assert(class->list_inner == NULL); + + else + { + assert(class->list_inner != NULL); + class->update_inner(operand, instances, count); } +} + + +/****************************************************************************** +* * +* 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_arch_operand_hash(const GArchOperand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + const char *name; /* Désignation du type d'object*/ + fnv64_t name_hash; /* Empreinte du nom */ + operand_extra_data_t *extra; /* Données insérées à modifier */ + + assert(!lock); + + name = G_OBJECT_TYPE_NAME(G_OBJECT(operand)); + name_hash = fnv_64a_hash(name); + + result = (name_hash & 0xffffffff); + result ^= (name_hash >> 32); + + extra = GET_ARCH_OP_EXTRA(operand); + + result ^= extra->flags; + return result; } @@ -375,11 +740,176 @@ GArchOperand *g_arch_operand_load(GAsmStorage *storage, GBinFormat *format, pack /****************************************************************************** * * -* Paramètres : operand = opérande d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * +* Paramètres : operand = objet dont l'instance se veut unique. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_arch_operand_hash(const GArchOperand *operand) +{ + guint result; /* Valeur à retourner */ + GArchOperandClass *class; /* Classe associée à l'objet */ + + class = G_ARCH_OPERAND_GET_CLASS(operand); + + result = class->hash(operand, true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* other = second élément à analyser. * +* * +* Description : Détermine si deux candidats à l'unicité sont identiques. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean g_arch_operand_is_equal(const GArchOperand *operand, const GArchOperand *other) +{ + gboolean result; /* Bilan à renvoyer */ + int ret; /* Bilan d'une comparaison */ + + ret = g_arch_operand_compare(operand, other); + + result = (ret == 0); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* * +* Description : Marque un candidat comme figé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_operand_set_read_only(GArchOperand *operand) +{ + g_arch_operand_set_flag(operand, AOF_READ_ONLY); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* * +* Description : Indique si le candidat est figé. * +* * +* Retour : true si le contenu du candidat ne peut plus être modifié. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_operand_is_read_only(GArchOperand *operand) +{ + bool result; /* Etat à retourner */ + + result = g_arch_operand_has_flag(operand, AOF_READ_ONLY); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION ET RECHARGEMENT DES DONNEES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un contenu depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + operand_extra_data_t *extra; /* Données insérées à consulter*/ + uleb128_t value; /* Valeur ULEB128 à charger */ + + extra = GET_ARCH_OP_EXTRA(operand); + + LOCK_GOBJECT_EXTRA(extra); + + result = unpack_uleb128(&value, pbuf); + + if (result) + extra->flags = value; + + 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. * +* * +* Description : Charge un contenu depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *class; /* Classe à activer */ + + class = G_ARCH_OPERAND_GET_CLASS(operand); + + result = class->load(operand, storage, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à remplir. * * * -* Description : Sauvegarde un opérande dans une mémoire tampon. * +* Description : Sauvegarde un contenu dans une mémoire tampon. * * * * Retour : Bilan de l'opération. * * * @@ -387,11 +917,18 @@ GArchOperand *g_arch_operand_load(GAsmStorage *storage, GBinFormat *format, pack * * ******************************************************************************/ -static bool g_arch_operand_serialize(const GArchOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf) +static bool _g_arch_operand_store(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) { bool result; /* Bilan à retourner */ + operand_extra_data_t *extra; /* Données insérées à consulter*/ - result = true; + extra = GET_ARCH_OP_EXTRA(operand); + + LOCK_GOBJECT_EXTRA(extra); + + result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf); + + UNLOCK_GOBJECT_EXTRA(extra); return result; @@ -400,11 +937,11 @@ static bool g_arch_operand_serialize(const GArchOperand *operand, GAsmStorage *s /****************************************************************************** * * -* Paramètres : operand = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * +* Paramètres : operand = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à remplir. * * * -* Description : Sauvegarde un opérande dans une mémoire tampon. * +* Description : Sauvegarde un contenu dans une mémoire tampon. * * * * Retour : Bilan de l'opération. * * * @@ -412,14 +949,14 @@ static bool g_arch_operand_serialize(const GArchOperand *operand, GAsmStorage *s * * ******************************************************************************/ -bool g_arch_operand_store(const GArchOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf) +static bool g_arch_operand_store(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) { bool result; /* Bilan à retourner */ + GArchOperandClass *class; /* Classe à activer */ - result = g_asm_storage_store_object_gtype(storage, G_OBJECT(operand), pbuf); + class = G_ARCH_OPERAND_GET_CLASS(operand); - if (result) - result = G_ARCH_OPERAND_GET_CLASS(operand)->serialize(operand, storage, pbuf); + result = class->store(operand, storage, pbuf); return result; |