From 8e5c8417e8ef79c1b475cb1b86a1754b24f9af78 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 20 Apr 2017 20:52:01 +0200 Subject: Shared immediate operands in order to avoid useless allocations. --- ChangeLog | 53 +++++ plugins/pychrysa/arch/immediate.c | 12 +- plugins/pychrysa/helpers.h | 8 + plugins/stackvars/stackvars.c | 2 +- src/analysis/db/items/switcher.c | 4 +- src/analysis/disass/links.c | 2 +- src/arch/arm/v7/fetch.c | 37 ++-- src/arch/arm/v7/post.c | 2 +- src/arch/dalvik/operands/args.c | 2 +- src/arch/dalvik/operands/pool.c | 2 +- src/arch/dalvik/operands/register.c | 2 +- src/arch/immediate.c | 431 ++++++++++++++++++++++++++++++++---- src/arch/immediate.h | 28 ++- src/arch/instruction.c | 85 ++++++- src/arch/instruction.h | 12 +- src/arch/operand-int.h | 9 +- src/arch/operand.c | 31 ++- src/arch/post.c | 2 +- src/arch/raw.c | 17 +- src/arch/sharing/container-int.h | 2 +- src/arch/sharing/container.c | 12 +- src/arch/sharing/container.h | 2 +- src/arch/sharing/instance-int.h | 4 + src/arch/sharing/instance.c | 24 ++ src/arch/sharing/instance.h | 3 + src/arch/sharing/manager.c | 101 ++++++++- src/arch/sharing/manager.h | 6 + src/core/processors.c | 7 +- src/format/symbol.h | 16 +- tools/d2c/syntax/manager.c | 20 +- 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 + + * 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 * 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 +#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"); -- cgit v0.11.2-87-g4458