summaryrefslogtreecommitdiff
path: root/src/arch/immediate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/immediate.c')
-rw-r--r--src/arch/immediate.c431
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));
+
+}