diff options
Diffstat (limited to 'src/arch/immediate.c')
-rw-r--r-- | src/arch/immediate.c | 431 |
1 files changed, 389 insertions, 42 deletions
diff --git a/src/arch/immediate.c b/src/arch/immediate.c index 6c8be5c..6c52892 100644 --- a/src/arch/immediate.c +++ b/src/arch/immediate.c @@ -37,6 +37,7 @@ #include "operand-int.h" +#include "sharing/manager.h" #include "../common/asm.h" #include "../common/extstr.h" #include "../format/format.h" @@ -78,6 +79,15 @@ static void g_imm_operand_dispose(GImmOperand *); /* Procède à la libération totale de la mémoire. */ static void g_imm_operand_finalize(GImmOperand *); +/* Initialise un nouvel objet partagé avec des informations. */ +static bool g_imm_operand_do_init(GImmOperand *, const GImmOperand *); + +/* Réalise une copie minimale d'un contenu partagé. */ +static void g_imm_operand_quickly_copy(const GImmOperand *, GImmOperand *); + +/* Compare un opérande avec un autre. */ +static int g_imm_operand_compare(const GImmOperand * const *, const GImmOperand * const *); + /* Construit la chaîne de caractères correspondant à l'opérande. */ static size_t _g_imm_operand_to_string(const GImmOperand *, AsmSyntax, ImmOperandDisplay, char [IMM_MAX_SIZE]); @@ -89,6 +99,19 @@ static char *g_imm_operand_build_tooltip(const GImmOperand *, const GLoadedBinar +/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */ + + +/* Gestionnaire des partages d'instances */ +static GShareManager *_imm_operand_manager = NULL; + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION D'OPERANDES DE VALEUR IMMEDIATE */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini pour un opérande de valeur numérique. */ G_DEFINE_TYPE(GImmOperand, g_imm_operand, G_TYPE_ARCH_OPERAND); @@ -117,6 +140,10 @@ static void g_imm_operand_class_init(GImmOperandClass *klass) object->dispose = (GObjectFinalizeFunc/* ! */)g_imm_operand_dispose; object->finalize = (GObjectFinalizeFunc)g_imm_operand_finalize; + operand->init = (operand_do_init_fc)g_imm_operand_do_init; + operand->qck_copy = (operand_qck_copy_fc)g_imm_operand_quickly_copy; + + operand->compare = (operand_compare_fc)g_imm_operand_compare; operand->print = (operand_print_fc)g_imm_operand_print; operand->build_tooltip = (operand_build_tooltip_fc)g_imm_operand_build_tooltip; @@ -201,7 +228,8 @@ static void g_imm_operand_finalize(GImmOperand *operand) GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian) { - GImmOperand *result; /* Opérande à retourner */ + GArchOperand *result; /* Opérande à retourner */ + GImmOperand fake; /* Transport d'informations */ uint8_t uval8; /* Valeur sur 8 bits */ uint16_t uval16; /* Valeur sur 16 bits */ uint32_t uval32; /* Valeur sur 32 bits */ @@ -211,70 +239,70 @@ GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinConten int32_t sval32; /* Valeur sur 32 bits */ int64_t sval64; /* Valeur sur 64 bits */ - result = g_object_new(G_TYPE_IMM_OPERAND, NULL); + g_imm_operand_init(&fake); - result->size = size; + fake.size = size; switch (size) { case MDS_4_BITS_UNSIGNED: if (!g_binary_content_read_u4(content, addr, low, &uval8)) goto gionfd_error; - result->raw = uval8; + fake.raw = uval8; break; case MDS_8_BITS_UNSIGNED: if (!g_binary_content_read_u8(content, addr, &uval8)) goto gionfd_error; - result->raw = uval8; + fake.raw = uval8; break; case MDS_16_BITS_UNSIGNED: if (!g_binary_content_read_u16(content, addr, endian, &uval16)) goto gionfd_error; - result->raw = uval16; + fake.raw = uval16; break; case MDS_32_BITS_UNSIGNED: if (!g_binary_content_read_u32(content, addr, endian, &uval32)) goto gionfd_error; - result->raw = uval32; + fake.raw = uval32; break; case MDS_64_BITS_UNSIGNED: if (!g_binary_content_read_u64(content, addr, endian, &uval64)) goto gionfd_error; - result->raw = uval64; + fake.raw = uval64; break; case MDS_4_BITS_SIGNED: if (!g_binary_content_read_s4(content, addr, low, &sval8)) goto gionfd_error; - result->raw = sval8; + fake.raw = sval8; break; case MDS_8_BITS_SIGNED: if (!g_binary_content_read_s8(content, addr, &sval8)) goto gionfd_error; - result->raw = sval8; + fake.raw = sval8; break; case MDS_16_BITS_SIGNED: if (!g_binary_content_read_s16(content, addr, endian, &sval16)) goto gionfd_error; - result->raw = sval16; + fake.raw = sval16; break; case MDS_32_BITS_SIGNED: if (!g_binary_content_read_s32(content, addr, endian, &sval32)) goto gionfd_error; - result->raw = sval32; + fake.raw = sval32; break; case MDS_64_BITS_SIGNED: if (!g_binary_content_read_s64(content, addr, endian, &sval64)) goto gionfd_error; - result->raw = sval64; + fake.raw = sval64; break; case MDS_UNDEFINED: @@ -283,11 +311,11 @@ GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinConten } - return G_ARCH_OPERAND(result); + result = G_ARCH_OPERAND(g_share_manager_get(_imm_operand_manager, (GSharedInstance *)&fake)); - gionfd_error: + return result; - g_object_unref(G_OBJECT(result)); + gionfd_error: return NULL; @@ -309,15 +337,157 @@ GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinConten GArchOperand *g_imm_operand_new_from_value(MemoryDataSize size, uint64_t value) { - GImmOperand *result; /* Opérande à retourner */ + GArchOperand *result; /* Opérande à retourner */ + GImmOperand fake; /* Transport d'informations */ - if (size == MDS_UNDEFINED) return NULL; + if (size == MDS_UNDEFINED) + result = NULL; - result = g_object_new(G_TYPE_IMM_OPERAND, NULL); + else + { + g_imm_operand_init(&fake); - g_imm_operand_set_value(result, size, value); + fake.size = size; + fake.raw = value; - return G_ARCH_OPERAND(result); + result = G_ARCH_OPERAND(g_share_manager_get(_imm_operand_manager, (GSharedInstance *)&fake)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à initialiser. * +* fake = coquille vide contenant les infos à enregistrer. * +* * +* Description : Initialise un nouvel objet partagé avec des informations. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_imm_operand_do_init(GImmOperand *operand, const GImmOperand *fake) +{ + operand->raw = fake->raw; + operand->size = fake->size; + + operand->zpad = fake->zpad; + operand->def_display = fake->def_display; + operand->display = fake->display; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à consulter. * +* template = informations à retrouver intégralement. * +* * +* Description : Réalise une copie minimale d'un contenu partagé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_imm_operand_quickly_copy(const GImmOperand *operand, GImmOperand *template) +{ + template->raw = operand->raw; + template->size = operand->size; + + template->zpad = operand->zpad; + template->def_display = operand->def_display; + template->display = operand->display; + +} + + +/****************************************************************************** +* * +* 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_imm_operand_compare(const GImmOperand * const *a, const GImmOperand * const *b) +{ + int result; /* Bilan à retourner */ + const GImmOperand *imm_a; /* Accès simplifié à A */ + const GImmOperand *imm_b; /* Accès simplifié à B */ + + imm_a = *a; + imm_b = *b; + + if (imm_a->size < imm_b->size) + { + result = -1; + goto gioc_done; + } + else if (imm_a->size > imm_b->size) + { + result = 1; + goto gioc_done; + } + + if (imm_a->raw < imm_b->raw) + { + result = -1; + goto gioc_done; + } + else if (imm_a->raw > imm_b->raw) + { + result = 1; + goto gioc_done; + } + + if (imm_a->zpad != imm_b->zpad) + { + result = (imm_a->zpad ? 1 : -1); + goto gioc_done; + } + + if (imm_a->def_display < imm_b->def_display) + { + result = -1; + goto gioc_done; + } + else if (imm_a->def_display > imm_b->def_display) + { + result = 1; + goto gioc_done; + } + + if (imm_a->display < imm_b->display) + { + result = -1; + goto gioc_done; + } + else if (imm_a->display > imm_b->display) + { + result = 1; + goto gioc_done; + } + + result = 0; + + gioc_done: + + return result; } @@ -443,34 +613,62 @@ uint64_t g_imm_operand_get_raw_value(const GImmOperand *operand) /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à mettre à jour. * -* size = taille de l'opérande souhaitée. * -* value = valeur sur x bits à venir récupérer. * +* Paramètres : operand = structure dont le contenu est à actualiser. [OUT]* +* size = taille de l'opérande souhaitée. * +* value = valeur sur x bits à venir récupérer. * +* container = propriétaire d'origine à tenir au courant. * * * * Description : Définit la nouvelle valeur de l'opérande à une valeur. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t value) +void g_imm_operand_set_value(GImmOperand **operand, MemoryDataSize size, uint64_t value, GShareContainer *container) { - if (size == MDS_UNDEFINED) return false; + GSharedInstance *shared; /* Instace de travail partagée */ + size_t index; /* Indice du déménagement */ + GImmOperand fake; /* Transport d'informations */ - operand->size = size; - operand->raw = value; + assert(size != MDS_UNDEFINED); - return true; + shared = G_SHARED_INSTANCE(*operand); + + if (container == NULL) + { + index = g_share_manager_prepare_light_update(_imm_operand_manager, shared); + + (*operand)->size = size; + (*operand)->raw = value; + + shared = g_share_manager_complete_light_update(_imm_operand_manager, shared, index); + + } + + else + { + g_shared_instance_quickly_copy(shared, (GSharedInstance *)&fake); + + fake.size = size; + fake.raw = value; + + shared = g_share_manager_update(_imm_operand_manager, shared, + (GSharedInstance *)&fake, container); + + } + + *operand = G_IMM_OPERAND(shared); } /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à définir. * -* state = true si des zéro sont à ajouter, false sinon. * +* Paramètres : operand = structure dont le contenu est à actualiser. [OUT]* +* state = true si des zéro sont à ajouter, false sinon. * +* container = propriétaire d'origine à tenir au courant. * * * * Description : Précise si des zéro doivent compléter l'affichage ou non. * * * @@ -480,9 +678,36 @@ bool g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t * * ******************************************************************************/ -void g_imm_operand_pad(GImmOperand *operand, bool state) +void g_imm_operand_pad(GImmOperand **operand, bool state, GShareContainer *container) { - operand->zpad = state; + GSharedInstance *shared; /* Instace de travail partagée */ + size_t index; /* Indice du déménagement */ + GImmOperand fake; /* Transport d'informations */ + + shared = G_SHARED_INSTANCE(*operand); + + if (container == NULL) + { + index = g_share_manager_prepare_light_update(_imm_operand_manager, shared); + + (*operand)->zpad = state; + + shared = g_share_manager_complete_light_update(_imm_operand_manager, shared, index); + + } + + else + { + g_shared_instance_quickly_copy(shared, (GSharedInstance *)&fake); + + fake.zpad = state; + + shared = g_share_manager_update(_imm_operand_manager, shared, + (GSharedInstance *)&fake, container); + + } + + *operand = G_IMM_OPERAND(shared); } @@ -508,8 +733,9 @@ bool g_imm_operand_does_padding(const GImmOperand *operand) /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu par défaut est à définir.* -* display = format global d'un affichage de valeur. * +* Paramètres : operand = structure dont le contenu est à actualiser. [OUT]* +* display = format global d'un affichage de valeur. * +* container = propriétaire d'origine à tenir au courant. * * * * Description : Définit le format textuel par défaut de la valeur. * * * @@ -519,9 +745,36 @@ bool g_imm_operand_does_padding(const GImmOperand *operand) * * ******************************************************************************/ -void g_imm_operand_set_default_display(GImmOperand *operand, ImmOperandDisplay display) +void g_imm_operand_set_default_display(GImmOperand **operand, ImmOperandDisplay display, GShareContainer *container) { - operand->def_display = display; + GSharedInstance *shared; /* Instace de travail partagée */ + size_t index; /* Indice du déménagement */ + GImmOperand fake; /* Transport d'informations */ + + shared = G_SHARED_INSTANCE(*operand); + + if (container == NULL) + { + index = g_share_manager_prepare_light_update(_imm_operand_manager, shared); + + (*operand)->def_display = display; + + shared = g_share_manager_complete_light_update(_imm_operand_manager, shared, index); + + } + + else + { + g_shared_instance_quickly_copy(shared, (GSharedInstance *)&fake); + + fake.def_display = display; + + shared = g_share_manager_update(_imm_operand_manager, shared, + (GSharedInstance *)&fake, container); + + } + + *operand = G_IMM_OPERAND(shared); } @@ -547,8 +800,9 @@ ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand) /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à définir. * -* display = format global d'un affichage de valeur. * +* Paramètres : operand = structure dont le contenu est à actualiser. [OUT]* +* display = format global d'un affichage de valeur. * +* container = propriétaire d'origine à tenir au courant. * * * * Description : Définit la grande ligne du format textuel de la valeur. * * * @@ -558,9 +812,36 @@ ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand) * * ******************************************************************************/ -void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display) +void g_imm_operand_set_display(GImmOperand **operand, ImmOperandDisplay display, GShareContainer *container) { - operand->display = display; + GSharedInstance *shared; /* Instace de travail partagée */ + size_t index; /* Indice du déménagement */ + GImmOperand fake; /* Transport d'informations */ + + shared = G_SHARED_INSTANCE(*operand); + + if (container == NULL) + { + index = g_share_manager_prepare_light_update(_imm_operand_manager, shared); + + (*operand)->display = display; + + shared = g_share_manager_complete_light_update(_imm_operand_manager, shared, index); + + } + + else + { + g_shared_instance_quickly_copy(shared, (GSharedInstance *)&fake); + + fake.display = display; + + shared = g_share_manager_update(_imm_operand_manager, shared, + (GSharedInstance *)&fake, container); + + } + + *operand = G_IMM_OPERAND(shared); } @@ -1116,3 +1397,69 @@ bool g_imm_operand_to_off_t(const GImmOperand *operand, off_t *value, bool *nega return false; } + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTAGES DE CONTENUS UNIQUES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Initialise les mécanismes de partage d'opérandes immédiates. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_imm_operand_sharing(void) +{ + _imm_operand_manager = g_share_manager_new(G_TYPE_IMM_OPERAND); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Imprime des statistiques quant aux partages dans l'archi. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#ifdef DEBUG_DUMP_STATS +void dump_imm_operand_share_stats(void) +{ + g_share_manager_dump_stats(_imm_operand_manager); + +} +#endif + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Supprime les mécanismes de partage des opérandes immédiates. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_imm_operand_sharing(void) +{ + g_object_unref(G_OBJECT(_imm_operand_manager)); + +} |