summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog53
-rw-r--r--plugins/pychrysa/arch/immediate.c12
-rw-r--r--plugins/pychrysa/helpers.h8
-rw-r--r--plugins/stackvars/stackvars.c2
-rw-r--r--src/analysis/db/items/switcher.c4
-rw-r--r--src/analysis/disass/links.c2
-rw-r--r--src/arch/arm/v7/fetch.c37
-rw-r--r--src/arch/arm/v7/post.c2
-rw-r--r--src/arch/dalvik/operands/args.c2
-rw-r--r--src/arch/dalvik/operands/pool.c2
-rw-r--r--src/arch/dalvik/operands/register.c2
-rw-r--r--src/arch/immediate.c431
-rw-r--r--src/arch/immediate.h28
-rw-r--r--src/arch/instruction.c85
-rw-r--r--src/arch/instruction.h12
-rw-r--r--src/arch/operand-int.h9
-rw-r--r--src/arch/operand.c31
-rw-r--r--src/arch/post.c2
-rw-r--r--src/arch/raw.c17
-rw-r--r--src/arch/sharing/container-int.h2
-rw-r--r--src/arch/sharing/container.c12
-rw-r--r--src/arch/sharing/container.h2
-rw-r--r--src/arch/sharing/instance-int.h4
-rw-r--r--src/arch/sharing/instance.c24
-rw-r--r--src/arch/sharing/instance.h3
-rw-r--r--src/arch/sharing/manager.c101
-rw-r--r--src/arch/sharing/manager.h6
-rw-r--r--src/core/processors.c7
-rw-r--r--src/format/symbol.h16
-rw-r--r--tools/d2c/syntax/manager.c20
30 files changed, 808 insertions, 130 deletions
diff --git a/ChangeLog b/ChangeLog
index 448352b..f163828 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+17-04-20 Cyrille Bagard <nocbos@gmail.com>
+
+ * plugins/pychrysa/arch/immediate.c:
+ Update code.
+
+ * plugins/pychrysa/helpers.h:
+ Provide a way to update the GLib instance linked to a Python object.
+
+ * plugins/stackvars/stackvars.c:
+ * src/analysis/db/items/switcher.c:
+ * src/analysis/disass/links.c:
+ * src/arch/arm/v7/fetch.c:
+ * src/arch/arm/v7/post.c:
+ Update code.
+
+ * src/arch/dalvik/operands/args.c:
+ * src/arch/dalvik/operands/pool.c:
+ * src/arch/dalvik/operands/register.c:
+ Update class callbacks.
+
+ * src/arch/immediate.c:
+ * src/arch/immediate.h:
+ Share immediate operands in order to avoid useless allocations.
+
+ * src/arch/instruction.c:
+ * src/arch/instruction.h:
+ Make instructions become share containers.
+
+ * src/arch/operand-int.h:
+ * src/arch/operand.c:
+ Update class callbacks.
+
+ * src/arch/post.c:
+ * src/arch/raw.c:
+ Update code.
+
+ * src/arch/sharing/container-int.h:
+ * src/arch/sharing/container.c:
+ * src/arch/sharing/container.h:
+ * src/arch/sharing/instance-int.h:
+ * src/arch/sharing/instance.c:
+ * src/arch/sharing/instance.h:
+ * src/arch/sharing/manager.c:
+ * src/arch/sharing/manager.h:
+ Extend the features of the share system.
+
+ * src/core/processors.c:
+ Register the share manager for immediate operands.
+
+ * src/format/symbol.h:
+ * tools/d2c/syntax/manager.c:
+ Update code.
+
17-04-19 Cyrille Bagard <nocbos@gmail.com>
* plugins/pychrysa/analysis/db/items/comment.c:
diff --git a/plugins/pychrysa/arch/immediate.c b/plugins/pychrysa/arch/immediate.c
index e600a9a..363c3cc 100644
--- a/plugins/pychrysa/arch/immediate.c
+++ b/plugins/pychrysa/arch/immediate.c
@@ -243,7 +243,9 @@ static int py_imm_operand_set_padding(PyObject *self, PyObject *value, void *clo
operand = G_IMM_OPERAND(pygobject_get(self));
assert(operand != NULL);
- g_imm_operand_pad(operand, padding);
+ g_imm_operand_pad(&operand, padding, NULL);
+
+ pygobject_set(self, operand);
return 0;
@@ -316,7 +318,9 @@ static int py_imm_operand_set_default_display(PyObject *self, PyObject *value, v
operand = G_IMM_OPERAND(pygobject_get(self));
assert(operand != NULL);
- g_imm_operand_set_default_display(operand, display);
+ g_imm_operand_set_default_display(&operand, display, NULL);
+
+ pygobject_set(self, operand);
return 0;
@@ -390,7 +394,9 @@ static int py_imm_operand_set_display(PyObject *self, PyObject *value, void *clo
operand = G_IMM_OPERAND(pygobject_get(self));
assert(operand != NULL);
- g_imm_operand_set_display(operand, display);
+ g_imm_operand_set_display(&operand, display, NULL);
+
+ pygobject_set(self, operand);
return 0;
diff --git a/plugins/pychrysa/helpers.h b/plugins/pychrysa/helpers.h
index 22f3702..3e079b7 100644
--- a/plugins/pychrysa/helpers.h
+++ b/plugins/pychrysa/helpers.h
@@ -65,5 +65,13 @@ bool PyDict_AddStringConstant(PyTypeObject *, const char *, const char *);
bool register_class_for_pygobject(PyObject *, GType, PyTypeObject *, PyTypeObject *);
+/**
+ * Quand on remplace un objet GLib dans le dos de Python, il faut
+ * le remplacer de la même manière qu'on l'a obtenu !
+ */
+
+#define pygobject_set(p, v) ((PyGObject *)(p))->obj = (GObject *)v
+
+
#endif /* _PLUGINS_HELPERS_H */
diff --git a/plugins/stackvars/stackvars.c b/plugins/stackvars/stackvars.c
index f3baeef..4e07035 100644
--- a/plugins/stackvars/stackvars.c
+++ b/plugins/stackvars/stackvars.c
@@ -216,7 +216,7 @@ static bool replace_stack_vars_in_instruction(GArchInstruction *instr, GBinRouti
if (!dryrun && result)
{
- _g_arch_instruction_replace_operand(instr, new, operand);
+ _g_arch_instruction_replace_operand(instr, operand, new);
result = true;
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c
index b7957ff..35acf5f 100644
--- a/src/analysis/db/items/switcher.c
+++ b/src/analysis/db/items/switcher.c
@@ -547,7 +547,7 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO
if (new == IOD_COUNT)
new = g_imm_operand_get_default_display(operand);
- g_imm_operand_set_display(operand, new);
+ g_imm_operand_set_display(&operand, new, G_SHARE_CONTAINER(instr));
len = g_imm_operand_to_string(operand, ASX_INTEL, value);
@@ -561,7 +561,7 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO
exit_operand:
- g_object_unref(G_OBJECT(proc));
+ g_object_unref(G_OBJECT(instr));
exit_instr:
diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c
index e1bc58c..036a621 100644
--- a/src/analysis/disass/links.c
+++ b/src/analysis/disass/links.c
@@ -229,7 +229,7 @@ static void convert_immediate_into_target(GArchInstruction *instr, size_t index,
if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format, false))
g_object_unref(G_OBJECT(new));
else
- _g_arch_instruction_replace_operand(instr, new, op);
+ _g_arch_instruction_replace_operand(instr, op, new);
}
diff --git a/src/arch/arm/v7/fetch.c b/src/arch/arm/v7/fetch.c
index 84319cc..11864f6 100644
--- a/src/arch/arm/v7/fetch.c
+++ b/src/arch/arm/v7/fetch.c
@@ -34,6 +34,7 @@
#include "operands/offset.h"
#include "../register.h"
#include "../../raw.h"
+#include "../../sharing/container.h"
#include "../../../format/format.h"
@@ -58,7 +59,7 @@ void help_fetching_with_instruction_b_with_orig(GArchInstruction *instr, GArchPr
{
const mrange_t *range; /* Emplacementt d'instruction */
virt_t pc; /* Position dans l'exécution */
- GArchOperand *op; /* Opérande numérique en place */
+ GImmOperand *op; /* Opérande numérique en place */
int32_t offset; /* Décallage encodé en dur */
virt_t target; /* Adresse virtuelle visée */
@@ -86,10 +87,10 @@ void help_fetching_with_instruction_b_with_orig(GArchInstruction *instr, GArchPr
//pc += get_mrange_length(range);
- op = g_arch_instruction_get_operand(instr, 0);
+ op = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 0));
- if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset))
- g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
+ if (g_imm_operand_get_value(op, MDS_32_BITS_SIGNED, &offset))
+ g_imm_operand_set_value(&op, MDS_32_BITS_UNSIGNED, pc + offset, G_SHARE_CONTAINER(instr));
else assert(0);
@@ -121,7 +122,7 @@ void help_fetching_with_instruction_bl_with_orig(GArchInstruction *instr, GArchP
{
const mrange_t *range; /* Emplacementt d'instruction */
virt_t pc; /* Position dans l'exécution */
- GArchOperand *op; /* Opérande numérique en place */
+ GImmOperand *op; /* Opérande numérique en place */
int32_t offset; /* Décallage encodé en dur */
virt_t target; /* Adresse virtuelle visée */
@@ -149,10 +150,10 @@ void help_fetching_with_instruction_bl_with_orig(GArchInstruction *instr, GArchP
break;
}
- op = g_arch_instruction_get_operand(instr, 0);
+ op = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 0));
- if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset))
- g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
+ if (g_imm_operand_get_value(op, MDS_32_BITS_SIGNED, &offset))
+ g_imm_operand_set_value(&op, MDS_32_BITS_UNSIGNED, pc + offset, G_SHARE_CONTAINER(instr));
else assert(0);
@@ -184,7 +185,7 @@ void help_fetching_with_instruction_blx_with_dest(GArchInstruction *instr, GArch
{
const mrange_t *range; /* Emplacementt d'instruction */
virt_t pc; /* Position dans l'exécution */
- GArchOperand *op; /* Opérande numérique en place */
+ GImmOperand *op; /* Opérande numérique en place */
int32_t offset; /* Décallage encodé en dur */
virt_t target; /* Adresse virtuelle visée */
@@ -202,10 +203,10 @@ void help_fetching_with_instruction_blx_with_dest(GArchInstruction *instr, GArch
pc += 4;
pc -= pc % 4;
- op = g_arch_instruction_get_operand(instr, 0);
+ op = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 0));
- if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_SIGNED, &offset))
- g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
+ if (g_imm_operand_get_value(op, MDS_32_BITS_SIGNED, &offset))
+ g_imm_operand_set_value(&op, MDS_32_BITS_UNSIGNED, pc + offset, G_SHARE_CONTAINER(instr));
else assert(0);
@@ -307,7 +308,7 @@ void help_fetching_with_instruction_cb_n_z(GArchInstruction *instr, GArchProcess
{
const mrange_t *range; /* Emplacementt d'instruction */
virt_t pc; /* Position dans l'exécution */
- GArchOperand *op; /* Opérande numérique en place */
+ GImmOperand *op; /* Opérande numérique en place */
uint32_t offset; /* Décallage encodé en dur */
virt_t target; /* Adresse virtuelle visée */
@@ -321,10 +322,10 @@ void help_fetching_with_instruction_cb_n_z(GArchInstruction *instr, GArchProcess
pc += 4;
- op = g_arch_instruction_get_operand(instr, 1);
+ op = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 1));
- if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &offset))
- g_imm_operand_set_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, pc + offset);
+ if (g_imm_operand_get_value(op, MDS_32_BITS_UNSIGNED, &offset))
+ g_imm_operand_set_value(&op, MDS_32_BITS_UNSIGNED, pc + offset, G_SHARE_CONTAINER(instr));
else assert(0);
@@ -486,7 +487,7 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst
- //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target);
+ //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target, G_SHARE_CONTAINER(instr));
/// FIXME ?!
@@ -496,7 +497,7 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst
new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target);
- _g_arch_instruction_replace_operand(instr, new, op);
+ _g_arch_instruction_replace_operand(instr, op, new);
g_arch_instruction_unlock_operands(instr);
diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c
index 6c63832..cfdc3be 100644
--- a/src/arch/arm/v7/post.c
+++ b/src/arch/arm/v7/post.c
@@ -93,7 +93,7 @@ void post_process_ldr_instructions(GArchInstruction *instr, GArchProcessor *proc
}
- _g_arch_instruction_replace_operand(instr, new, op);
+ _g_arch_instruction_replace_operand(instr, op, new);
}
diff --git a/src/arch/dalvik/operands/args.c b/src/arch/dalvik/operands/args.c
index 1eccf3a..8a687db 100644
--- a/src/arch/dalvik/operands/args.c
+++ b/src/arch/dalvik/operands/args.c
@@ -119,7 +119,7 @@ static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *klass)
object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_args_operand_dispose;
object->finalize = (GObjectFinalizeFunc)g_dalvik_args_operand_finalize;
- operand->init = (init_shared_fc)g_dalvik_args_operand_do_init;
+ operand->init = (operand_do_init_fc)g_dalvik_args_operand_do_init;
operand->compare = (operand_compare_fc)g_dalvik_args_operand_compare;
operand->print = (operand_print_fc)g_dalvik_args_operand_print;
diff --git a/src/arch/dalvik/operands/pool.c b/src/arch/dalvik/operands/pool.c
index f40c839..a450ffe 100644
--- a/src/arch/dalvik/operands/pool.c
+++ b/src/arch/dalvik/operands/pool.c
@@ -125,7 +125,7 @@ static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *klass)
operand = G_ARCH_OPERAND_CLASS(klass);
- operand->init = (init_shared_fc)g_dalvik_pool_operand_do_init;
+ operand->init = (operand_do_init_fc)g_dalvik_pool_operand_do_init;
operand->compare = (operand_compare_fc)g_dalvik_pool_operand_compare;
operand->print = (operand_print_fc)g_dalvik_pool_operand_print;
diff --git a/src/arch/dalvik/operands/register.c b/src/arch/dalvik/operands/register.c
index b90f02b..b415d3f 100644
--- a/src/arch/dalvik/operands/register.c
+++ b/src/arch/dalvik/operands/register.c
@@ -116,7 +116,7 @@ static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *kl
operand = G_ARCH_OPERAND_CLASS(klass);
- operand->init = (init_shared_fc)g_dalvik_register_operand_do_init;
+ operand->init = (operand_do_init_fc)g_dalvik_register_operand_do_init;
operand->compare = (operand_compare_fc)g_dalvik_register_operand_compare;
operand->print = (operand_print_fc)g_dalvik_register_operand_print;
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));
+
+}
diff --git a/src/arch/immediate.h b/src/arch/immediate.h
index fa30fe0..b4d1f84 100644
--- a/src/arch/immediate.h
+++ b/src/arch/immediate.h
@@ -32,10 +32,14 @@
#include "archbase.h"
#include "operand.h"
+#include "sharing/container.h"
#include "../analysis/content.h"
+/* ------------------ MANIPULATION D'OPERANDES DE VALEUR IMMEDIATE ------------------ */
+
+
/* Grande ligne d'un format d'affichage */
typedef enum _ImmOperandDisplay
{
@@ -87,22 +91,22 @@ bool g_imm_operand_get_value(const GImmOperand *, MemoryDataSize, ...);
uint64_t g_imm_operand_get_raw_value(const GImmOperand *);
/* Définit la nouvelle valeur de l'opérande à une valeur. */
-bool g_imm_operand_set_value(GImmOperand *, MemoryDataSize, uint64_t);
+void g_imm_operand_set_value(GImmOperand **, MemoryDataSize, uint64_t, GShareContainer *);
/* Précise si des zéro doivent compléter l'affichage ou non. */
-void g_imm_operand_pad(GImmOperand *, bool);
+void g_imm_operand_pad(GImmOperand **, bool, GShareContainer *);
/* Indique le signe d'une valeur immédiate. */
bool g_imm_operand_does_padding(const GImmOperand *);
/* Définit le format textuel par défaut de la valeur. */
-void g_imm_operand_set_default_display(GImmOperand *, ImmOperandDisplay);
+void g_imm_operand_set_default_display(GImmOperand **, ImmOperandDisplay, GShareContainer *);
/* Indique le format textuel par défaut de la valeur. */
ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *);
/* Définit la grande ligne du format textuel de la valeur. */
-void g_imm_operand_set_display(GImmOperand *, ImmOperandDisplay);
+void g_imm_operand_set_display(GImmOperand **, ImmOperandDisplay, GShareContainer *);
/* Indique la grande ligne du format textuel de la valeur. */
ImmOperandDisplay g_imm_operand_get_display(const GImmOperand *);
@@ -145,4 +149,20 @@ bool g_imm_operand_to_off_t(const GImmOperand *, off_t *, bool *) __attribute__
+/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */
+
+
+/* Initialise les mécanismes de partage des opérandes immédiates. */
+bool init_imm_operand_sharing(void);
+
+/* Imprime des statistiques quant aux partages dans l'archi. */
+#ifdef DEBUG_DUMP_STATS
+void dump_imm_operand_share_stats(void);
+#endif
+
+/* Supprime les mécanismes de partage des opérandes immédiates. */
+void exit_imm_operand_sharing(void);
+
+
+
#endif /* _ARCH_IMMEDIATE_H */
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 14e78dc..a2ba138 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -30,6 +30,7 @@
#include "instruction-int.h"
+#include "sharing/container-int.h"
#include "../glibext/linegen-int.h"
@@ -40,8 +41,11 @@ static void g_arch_instruction_class_init(GArchInstructionClass *);
/* Initialise une instance d'opérande d'architecture. */
static void g_arch_instruction_init(GArchInstruction *);
+/* Procède à l'initialisation de l'interface de partage. */
+static void g_arch_instruction_share_interface_init(GShareContainerInterface *);
+
/* Procède à l'initialisation de l'interface de génération. */
-static void g_arch_instruction_interface_init(GLineGeneratorInterface *);
+static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface *);
/* Supprime toutes les références externes. */
static void g_arch_instruction_dispose(GArchInstruction *);
@@ -76,7 +80,8 @@ static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t,
/* Indique le type défini pour une instruction d'architecture. */
G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_interface_init));
+ G_IMPLEMENT_INTERFACE(G_TYPE_SHARE_CONTAINER, g_arch_instruction_share_interface_init)
+ G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_interface_init));
/******************************************************************************
@@ -134,6 +139,25 @@ static void g_arch_instruction_init(GArchInstruction *instr)
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
+* Description : Procède à l'initialisation de l'interface de partage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arch_instruction_share_interface_init(GShareContainerInterface *iface)
+{
+ iface->replace = (replace_shared_fc)g_arch_instruction_replace_operand;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
* Description : Procède à l'initialisation de l'interface de génération. *
* *
* Retour : - *
@@ -142,7 +166,7 @@ static void g_arch_instruction_init(GArchInstruction *instr)
* *
******************************************************************************/
-static void g_arch_instruction_interface_init(GLineGeneratorInterface *iface)
+static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface *iface)
{
iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines;
iface->compute = (linegen_compute_fc)g_arch_instruction_compute_addr;
@@ -475,8 +499,8 @@ void g_arch_instruction_unlock_operands(GArchInstruction *instr)
/******************************************************************************
* *
-* Paramètres : instr = instance à mettre à jour. *
-* opererand = instruction à venir associer. *
+* Paramètres : instr = instance à mettre à jour. *
+* operand = instruction à venir associer. *
* *
* Description : Attache un opérande supplémentaire à une instruction. *
* *
@@ -552,23 +576,55 @@ GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, siz
/******************************************************************************
* *
* Paramètres : instr = instance à mettre à jour. *
-* new = nouvelle opérande à attacher. *
+* old = ancien opérande à remplacer. *
+* new = nouvel opérande à intégrer. *
+* *
+* Description : Remplace un opérande d'une instruction par un autre. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
+{
+ bool result; /* Bilan à retourner */
+
+ g_arch_instruction_lock_operands(instr);
+
+ result = _g_arch_instruction_replace_operand(instr, old, new);
+
+ g_arch_instruction_unlock_operands(instr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instance à mettre à jour. *
* old = ancienne opérande à détacher. *
+* new = nouvelle opérande à attacher. *
* *
* Description : Remplace un opérande d'une instruction par un autre. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-void _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *new, GArchOperand *old)
+bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
{
+ bool result; /* Bilan à retourner */
size_t count; /* Nombre d'opérandes en place */
size_t i; /* Boucle de parcours */
GArchOperand *op; /* Opérande à manipuler */
+ result = false;
+
count = _g_arch_instruction_count_operands(instr);
for (i = 0; i < count; i++)
@@ -576,13 +632,22 @@ void _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *
op = _g_arch_instruction_get_operand(instr, i);
if (op == old)
+ {
+ result = true;
break;
+ }
}
- rpl_item_in_flat_array(instr->operands, i, &new, sizeof(GArchOperand *));
+ if (result)
+ {
+ rpl_item_in_flat_array(instr->operands, i, &new, sizeof(GArchOperand *));
+
+ g_object_unref(G_OBJECT(old));
- g_object_unref(G_OBJECT(old));
+ }
+
+ return result;
}
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index bb2dc94..55c845e 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -147,7 +147,10 @@ size_t _g_arch_instruction_count_operands(const GArchInstruction *);
GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *, size_t);
/* Remplace un opérande d'une instruction par un autre. */
-void _g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
+bool g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
+
+/* Remplace un opérande d'une instruction par un autre. */
+bool _g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *);
/* Détache un opérande liée d'une instruction. */
void _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
@@ -171,13 +174,6 @@ void _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *);
__result; \
})
-#define g_arch_instruction_replace_operand(ins, n, o) \
- ({ \
- g_arch_instruction_lock_operands(ins); \
- _g_arch_instruction_replace_operand(ins, n, o); \
- g_arch_instruction_unlock_operands(ins); \
- })
-
#define g_arch_instruction_detach_operand(ins, o) \
({ \
g_arch_instruction_lock_operands(ins); \
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h
index 8335614..535df1b 100644
--- a/src/arch/operand-int.h
+++ b/src/arch/operand-int.h
@@ -30,6 +30,12 @@
+/* Initialise un nouvel objet partagé avec des informations. */
+typedef bool (* operand_do_init_fc) (GArchOperand *, const GArchOperand *);
+
+/* Réalise une copie minimale d'un contenu partagé. */
+typedef void (* operand_qck_copy_fc) (const GArchOperand *, GArchOperand *);
+
/* Compare un opérande avec un autre. */
typedef int (* operand_compare_fc) (const GArchOperand * const *, const GArchOperand * const *);
@@ -66,7 +72,8 @@ struct _GArchOperandClass
{
GObjectClass parent; /* A laisser en premier */
- init_shared_fc init; /* Mise en place via interface */
+ operand_do_init_fc init; /* Mise en place via interface */
+ operand_qck_copy_fc qck_copy; /* Copie minimale via interface*/
operand_compare_fc compare; /* Comparaison d'opérandes */
operand_print_fc print; /* Texte humain équivalent */
diff --git a/src/arch/operand.c b/src/arch/operand.c
index dd28238..584e3c0 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -50,7 +50,10 @@ static void g_arch_operand_dispose(GArchOperand *);
static void g_arch_operand_finalize(GArchOperand *);
/* Initialise un nouvel objet partagé avec des informations. */
-static bool g_arch_operand_do_init(GArchOperand *, const void *);
+static bool g_arch_operand_do_init(GArchOperand *, const GArchOperand *);
+
+/* Réalise une copie minimale d'un contenu partagé. */
+static void g_arch_operand_quickly_copy(const GArchOperand *, GArchOperand *);
/* Fournit la valeur du compteur de partage. */
static unsigned int g_arch_operand_get_references(const GArchOperand *);
@@ -65,6 +68,7 @@ static void g_arch_operand_dec_references(GArchOperand *);
static int g_arch_operand_quickly_compare(const GArchOperand **, const GArchOperand **);
+
/* 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_SHARED_INSTANCE, g_arch_operand_interface_init));
@@ -128,6 +132,7 @@ static void g_arch_operand_init(GArchOperand *operand)
static void g_arch_operand_interface_init(GSharedInstanceInterface *iface)
{
iface->init = (init_shared_fc)g_arch_operand_do_init;
+ iface->qck_copy = (qck_copy_shared_fc)g_arch_operand_quickly_copy;
iface->get_ref = (get_shared_ref_fc)g_arch_operand_get_references;
iface->inc_ref = (inc_shared_ref_fc)g_arch_operand_inc_references;
@@ -191,11 +196,11 @@ static void g_arch_operand_finalize(GArchOperand *operand)
* *
******************************************************************************/
-static bool g_arch_operand_do_init(GArchOperand *operand, const void *info)
+static bool g_arch_operand_do_init(GArchOperand *operand, const GArchOperand *info)
{
bool result; /* Bilan à retourner */
- result = G_ARCH_OPERAND_GET_CLASS(operand)->init(G_SHARED_INSTANCE(operand), info);
+ result = G_ARCH_OPERAND_GET_CLASS(operand)->init(operand, info);
return result;
@@ -204,6 +209,26 @@ static bool g_arch_operand_do_init(GArchOperand *operand, const void *info)
/******************************************************************************
* *
+* 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_arch_operand_quickly_copy(const GArchOperand *operand, GArchOperand *template)
+{
+ G_ARCH_OPERAND_GET_CLASS(operand)->qck_copy(operand, template);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : operand = objet partagé à consulter. *
* *
* Description : Fournit la valeur du compteur de partage. *
diff --git a/src/arch/post.c b/src/arch/post.c
index 5c7ed13..184430d 100644
--- a/src/arch/post.c
+++ b/src/arch/post.c
@@ -111,7 +111,7 @@ void post_process_target_resolution(GArchInstruction *instr, GArchProcessor *pro
}
- _g_arch_instruction_replace_operand(instr, new, op);
+ _g_arch_instruction_replace_operand(instr, op, new);
}
diff --git a/src/arch/raw.c b/src/arch/raw.c
index 9d9b8de..b84d9f7 100644
--- a/src/arch/raw.c
+++ b/src/arch/raw.c
@@ -195,17 +195,17 @@ static void g_raw_instruction_finalize(GRawInstruction *instr)
GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *addr, MemoryDataSize size, uint64_t value)
{
GArchInstruction *result; /* Instruction à retourner */
- GArchOperand *operand; /* Octet non décodé à afficher */
+ GImmOperand *operand; /* Octet non décodé à afficher */
mrange_t range; /* Couverture de l'instruction */
result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
- operand = g_imm_operand_new_from_value(size, value);
+ operand = G_IMM_OPERAND(g_imm_operand_new_from_value(size, value));
if (operand == NULL) goto grinfv_error;
- g_imm_operand_pad(G_IMM_OPERAND(operand), true);
+ g_imm_operand_pad(&operand, true, NULL);
- g_arch_instruction_attach_extra_operand(result, operand);
+ g_arch_instruction_attach_extra_operand(result, G_ARCH_OPERAND(operand));
switch (size)
{
@@ -348,7 +348,7 @@ GArchInstruction *g_raw_instruction_new_array(const GBinContent *content, Memory
GArchInstruction *result; /* Instruction à retourner */
vmpa2t old; /* Sauvegarde de la position */
size_t i; /* Boucle de parcours */
- GArchOperand *operand; /* Octet non décodé à afficher */
+ GImmOperand *operand; /* Octet non décodé à afficher */
mrange_t range; /* Couverture de l'instruction */
/* Par soucis de cohérence */
@@ -360,12 +360,13 @@ GArchInstruction *g_raw_instruction_new_array(const GBinContent *content, Memory
for (i = 0; i < count; i++)
{
- operand = g_imm_operand_new_from_data(size, content, addr, endian);
+ operand = G_IMM_OPERAND(g_imm_operand_new_from_data(size, content, addr, endian));
if (operand == NULL) goto grina_error;
- g_imm_operand_pad(G_IMM_OPERAND(operand), true);
+ g_imm_operand_pad(&operand, true, NULL);
+
+ g_arch_instruction_attach_extra_operand(result, G_ARCH_OPERAND(operand));
- g_arch_instruction_attach_extra_operand(result, operand);
}
init_mrange(&range, &old, compute_vmpa_diff(addr, &old));
diff --git a/src/arch/sharing/container-int.h b/src/arch/sharing/container-int.h
index 8e4ccbd..bc67bf6 100644
--- a/src/arch/sharing/container-int.h
+++ b/src/arch/sharing/container-int.h
@@ -30,7 +30,7 @@
/* Assure la mise à jour du contenu d'un intégrateur. */
-typedef void (* replace_shared_fc) (GShareContainer *, GSharedInstance *, GSharedInstance *);
+typedef bool (* replace_shared_fc) (GShareContainer *, GSharedInstance *, GSharedInstance *);
/* Règles de partage d'une instance GObject (interface) */
diff --git a/src/arch/sharing/container.c b/src/arch/sharing/container.c
index f027673..5ff62b7 100644
--- a/src/arch/sharing/container.c
+++ b/src/arch/sharing/container.c
@@ -66,22 +66,28 @@ static void g_share_container_default_init(GShareContainerInterface *iface)
* *
* Description : Assure la mise à jour du contenu d'un intégrateur. *
* *
-* Retour : - *
+* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
-void g_share_container_replace(GShareContainer *container, GSharedInstance *old, GSharedInstance *new)
+bool g_share_container_replace(GShareContainer *container, GSharedInstance *old, GSharedInstance *new)
{
+ bool result; /* Bilan à retourner */
GShareContainerIface *iface; /* Interface utilisée */
if (old != new)
{
iface = G_SHARE_CONTAINER_GET_IFACE(container);
- iface->replace(container, old, new);
+ result = iface->replace(container, old, new);
}
+ else
+ result = false;
+
+ return result;
+
}
diff --git a/src/arch/sharing/container.h b/src/arch/sharing/container.h
index 06d55a1..3312f9d 100644
--- a/src/arch/sharing/container.h
+++ b/src/arch/sharing/container.h
@@ -52,7 +52,7 @@ typedef struct _GShareContainerIface GShareContainerIface;
GType g_share_container_get_type(void) G_GNUC_CONST;
/* Assure la mise à jour du contenu d'un intégrateur. */
-void g_share_container_replace(GShareContainer *, GSharedInstance *, GSharedInstance *);
+bool g_share_container_replace(GShareContainer *, GSharedInstance *, GSharedInstance *);
diff --git a/src/arch/sharing/instance-int.h b/src/arch/sharing/instance-int.h
index c3ebae5..f9a91ba 100644
--- a/src/arch/sharing/instance-int.h
+++ b/src/arch/sharing/instance-int.h
@@ -32,6 +32,9 @@
/* Initialise un nouvel objet partagé avec des informations. */
typedef bool (* init_shared_fc) (GSharedInstance *, const GSharedInstance *);
+/* Procède à l'initialisation de l'interface de partage. */
+typedef void (* qck_copy_shared_fc) (const GSharedInstance *, GSharedInstance *);
+
/* Fournit la valeur du compteur de partage. */
typedef unsigned int (* get_shared_ref_fc) (const GSharedInstance *);
@@ -51,6 +54,7 @@ struct _GSharedInstanceIface
GTypeInterface base_iface; /* A laisser en premier */
init_shared_fc init; /* Initialisation de l'objet */
+ qck_copy_shared_fc qck_copy; /* Copie minimale des détails */
get_shared_ref_fc get_ref; /* Obtention du compteur */
inc_shared_ref_fc inc_ref; /* Incrémentation du compteur */
diff --git a/src/arch/sharing/instance.c b/src/arch/sharing/instance.c
index abcb653..c0038aa 100644
--- a/src/arch/sharing/instance.c
+++ b/src/arch/sharing/instance.c
@@ -88,6 +88,30 @@ bool g_shared_instance_init(GSharedInstance *instance, const GSharedInstance *te
/******************************************************************************
* *
* Paramètres : instance = objet partagé à consulter. *
+* template = informations à retrouver intégralement. *
+* *
+* Description : Réalise une copie minimale d'un contenu partagé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_shared_instance_quickly_copy(const GSharedInstance *instance, GSharedInstance *template)
+{
+ GSharedInstanceIface *iface; /* Interface utilisée */
+
+ iface = G_SHARED_INSTANCE_GET_IFACE(instance);
+
+ iface->qck_copy(instance, template);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instance = objet partagé à consulter. *
* *
* Description : Fournit la valeur du compteur de partage. *
* *
diff --git a/src/arch/sharing/instance.h b/src/arch/sharing/instance.h
index b79fa33..fdc94d7 100644
--- a/src/arch/sharing/instance.h
+++ b/src/arch/sharing/instance.h
@@ -51,6 +51,9 @@ GType g_shared_instance_get_type(void) G_GNUC_CONST;
/* Initialise un nouvel objet partagé avec des informations. */
bool g_shared_instance_init(GSharedInstance *, const GSharedInstance *);
+/* Réalise une copie minimale d'un contenu partagé. */
+void g_shared_instance_quickly_copy(const GSharedInstance *, GSharedInstance *);
+
/* Fournit la valeur du compteur de partage. */
unsigned int g_shared_instance_get_references(const GSharedInstance *);
diff --git a/src/arch/sharing/manager.c b/src/arch/sharing/manager.c
index 43e7e25..952fc33 100644
--- a/src/arch/sharing/manager.c
+++ b/src/arch/sharing/manager.c
@@ -235,8 +235,8 @@ GSharedInstance *g_share_manager_get(GShareManager *manager, GSharedInstance *te
{
g_shared_instance_inc_references(result);
- manager->instances = (GSharedInstance **)_qinsert(manager->instances, &manager->count,
- sizeof(GSharedInstance *), &result, index);
+ manager->instances = _qinsert(manager->instances, &manager->count,
+ sizeof(GSharedInstance *), &result, index);
}
@@ -276,13 +276,96 @@ GSharedInstance *g_share_manager_get(GShareManager *manager, GSharedInstance *te
GSharedInstance *g_share_manager_update(GShareManager *manager, GSharedInstance *old, GSharedInstance *template, GShareContainer *container)
{
GSharedInstance *result; /* Nouvelle instance à renvoyer*/
+ bool replaced; /* Remplacement effectué ? */
result = g_share_manager_get(manager, template);
if (container != NULL)
- g_share_container_replace(container, old, result);
+ replaced = g_share_container_replace(container, old, result);
+ else
+ replaced = false;
+
+ if (replaced)
+ g_share_manager_put(manager, old);
- g_share_manager_put(manager, old);
+ else
+ {
+ g_share_manager_put(manager, result);
+ result = old;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = gestionnaire d'instance à consulter. *
+* instance = instance partagée vouée à évoluer. *
+* *
+* Description : Prépare une modification légère et locale d'un élément. *
+* *
+* Retour : Indice de l'élément prêt à être modifié. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_share_manager_prepare_light_update(GShareManager *manager, GSharedInstance *instance)
+{
+ size_t result; /* Indice courant à retourner */
+#ifndef NDEBUG
+ bool found; /* Validation de présence */
+#endif
+
+ g_mutex_lock(&manager->access);
+
+#ifndef NDEBUG
+
+ found = bsearch_index(&instance, manager->instances, manager->count,sizeof(GSharedInstance *),
+ (__compar_fn_t)g_shared_instance_quickly_compare, &result);
+
+ assert(found);
+
+#else
+
+ bsearch_index(&instance, manager->instances, manager->count,sizeof(GSharedInstance *),
+ (__compar_fn_t)g_shared_instance_quickly_compare, &result);
+
+#endif
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : manager = gestionnaire d'instance à consulter. *
+* instance = instance partagée vouée à évoluer. *
+* index = indice de la place de l'élément avant modifcation.*
+* *
+* Description : Conclut une modification légère et locale d'un élément. *
+* *
+* Retour : Indice de l'élément prêt à être modifié. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSharedInstance *g_share_manager_complete_light_update(GShareManager *manager, GSharedInstance *instance, size_t index)
+{
+ GSharedInstance *result; /* Nouvelle instance à renvoyer*/
+
+ manager->instances = _qdelete(manager->instances, &manager->count,
+ sizeof(GSharedInstance *), index);
+
+ g_mutex_unlock(&manager->access);
+
+ result = g_share_manager_get(manager, instance);
+
+ g_object_unref(G_OBJECT(instance));
return result;
@@ -310,12 +393,12 @@ void g_share_manager_put(GShareManager *manager, GSharedInstance *shared)
if (g_shared_instance_get_references(shared) == 1)
{
- g_object_unref(G_OBJECT(shared));
+ manager->instances = qdelete(manager->instances, &manager->count,
+ sizeof(GSharedInstance *),
+ (__compar_fn_t)g_shared_instance_quickly_compare,
+ &shared);
- manager->instances = (GSharedInstance **)qdelete(manager->instances, &manager->count,
- sizeof(GSharedInstance *),
- (__compar_fn_t)g_shared_instance_quickly_compare,
- &shared);
+ g_object_unref(G_OBJECT(shared));
}
diff --git a/src/arch/sharing/manager.h b/src/arch/sharing/manager.h
index 959087d..f2fcea6 100644
--- a/src/arch/sharing/manager.h
+++ b/src/arch/sharing/manager.h
@@ -65,6 +65,12 @@ GSharedInstance *g_share_manager_get(GShareManager *, GSharedInstance *);
/* Met à jour une instance partagée. */
GSharedInstance *g_share_manager_update(GShareManager *, GSharedInstance *, GSharedInstance *, GShareContainer *);
+/* Prépare une modification légère et locale d'un élément. */
+size_t g_share_manager_prepare_light_update(GShareManager *, GSharedInstance *);
+
+/* Conclut une modification légère et locale d'un élément. */
+GSharedInstance *g_share_manager_complete_light_update(GShareManager *, GSharedInstance *, size_t);
+
/* Abandonne un usage d'une instance partagée. */
void g_share_manager_put(GShareManager *, GSharedInstance *);
diff --git a/src/core/processors.c b/src/core/processors.c
index 864b066..193cd25 100644
--- a/src/core/processors.c
+++ b/src/core/processors.c
@@ -29,6 +29,7 @@
#include <string.h>
+#include "../arch/immediate.h"
#include "../arch/arm/v7/core.h"
#include "../arch/arm/v7/processor.h"
#include "../arch/dalvik/core.h"
@@ -141,7 +142,7 @@ bool load_hard_coded_processors_definitions(void)
{
bool result; /* Bilan à retourner */
- result = true;
+ result = init_imm_operand_sharing();
result &= register_processor_type("armv7", "ARM v7", G_TYPE_ARMV7_PROCESSOR,
#ifdef DEBUG_DUMP_STATS
@@ -194,6 +195,8 @@ void unload_processors_definitions(void)
_processors_definitions = NULL;
_processors_definitions_count = 0;
+ exit_imm_operand_sharing();
+
G_UNLOCK(_pdef_access);
}
@@ -319,6 +322,8 @@ void display_share_stats(GArchProcessor *proc)
G_LOCK(_pdef_access);
+ dump_imm_operand_share_stats();
+
for (i = 0; i < _processors_definitions_count; i++)
if (_processors_definitions[i].instance == type)
{
diff --git a/src/format/symbol.h b/src/format/symbol.h
index 7389195..d5c9a79 100644
--- a/src/format/symbol.h
+++ b/src/format/symbol.h
@@ -133,13 +133,15 @@ GDbComment *g_binary_symbol_get_comment(const GBinSymbol *);
* Confort pour l'ajout de symboles basés sur des formats.
*/
-#define SET_IMM_DISPLAY(_ins, _op, _idx, _dsp) \
- do \
- { \
- _op = g_arch_instruction_get_operand(_ins, _idx); \
- g_imm_operand_set_default_display(G_IMM_OPERAND(_op), _dsp); \
- g_imm_operand_set_display(G_IMM_OPERAND(_op), _dsp); \
- } \
+#define SET_IMM_DISPLAY(_ins, _op, _idx, _dsp) \
+ do \
+ { \
+ GImmOperand *_imm; \
+ _imm = G_IMM_OPERAND(g_arch_instruction_get_operand(_ins, _idx)); \
+ g_imm_operand_set_default_display(&_imm, _dsp, G_SHARE_CONTAINER(_ins)); \
+ g_imm_operand_set_display(&_imm, _dsp, G_SHARE_CONTAINER(_ins)); \
+ _op = G_ARCH_OPERAND(_imm); \
+ } \
while (0)
#define ADD_RAW_AS_SYM(_fmt, _sym, _ins, _cmt, _txt) \
diff --git a/tools/d2c/syntax/manager.c b/tools/d2c/syntax/manager.c
index cfbf826..6857e9a 100644
--- a/tools/d2c/syntax/manager.c
+++ b/tools/d2c/syntax/manager.c
@@ -230,12 +230,14 @@ bool declare_syntax_items(const asm_syntax *syntax, int fd, const coding_bits *b
{
bool result; /* Bilan à retourner */
bool has_operand; /* Présence d'un opérande */
+ bool has_immediate; /* Présence d'une conversion */
size_t i; /* Boucle de parcours */
syntax_item *item; /* Lien vers un opérande */
result = true;
has_operand = false;
+ has_immediate = false;
for (i = 0; i < syntax->items_count && result; i++)
{
@@ -244,11 +246,17 @@ bool declare_syntax_items(const asm_syntax *syntax, int fd, const coding_bits *b
has_operand |= (item->impact == SIT_EXT_OPERAND);
+ if (has_operand)
+ has_immediate = (item->flags & SIF_DECIMAL);
+
}
if (has_operand)
dprintf(fd, "\t\tGArchOperand *op;\n");
+ if (has_immediate)
+ dprintf(fd, "\t\tGImmOperand *imm;\n");
+
return result;
}
@@ -355,7 +363,11 @@ bool define_syntax_items(const asm_syntax *syntax, int fd, const char *arch, con
dprintf(fd, "\n");
if (item->flags & SIF_DECIMAL)
- dprintf(fd, "\t\tg_imm_operand_set_default_display(G_IMM_OPERAND(op), IOD_DEC);\n");
+ {
+ dprintf(fd, "\t\timm = G_IMM_OPERAND(op)\n");
+ dprintf(fd, "\t\tg_imm_operand_set_default_display(&imm, IOD_DEC, NULL);\n");
+ dprintf(fd, "\t\timm = G_IMM_OPERAND(op)\n");
+ }
dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n");
@@ -382,7 +394,11 @@ bool define_syntax_items(const asm_syntax *syntax, int fd, const char *arch, con
dprintf(fd, "\n");
if (item->flags & SIF_DECIMAL)
- dprintf(fd, "\t\tg_imm_operand_set_default_display(G_IMM_OPERAND(op), IOD_DEC);\n");
+ {
+ dprintf(fd, "\t\timm = G_IMM_OPERAND(op)\n");
+ dprintf(fd, "\t\tg_imm_operand_set_default_display(&imm, IOD_DEC, NULL);\n");
+ dprintf(fd, "\t\timm = G_IMM_OPERAND(op)\n");
+ }
dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n");