diff options
Diffstat (limited to 'src')
27 files changed, 1345 insertions, 76 deletions
diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 64d8fc4..61f775c 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -1642,6 +1642,14 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binar g_object_unref(G_OBJECT(disass)); +#ifdef DEBUG_DUMP_STATS + + display_share_stats(binary->proc); + +#endif + + + /* ... = *///g_loaded_binary_connect_internal(binary); diff --git a/src/arch/dalvik/context.c b/src/arch/dalvik/context.c index 3b79ffa..997d899 100644 --- a/src/arch/dalvik/context.c +++ b/src/arch/dalvik/context.c @@ -638,7 +638,7 @@ static GDecInstruction *g_dalvik_dcontext_convert_register(GDalvikDContext *ctx, GDexFormat *format; /* Recherche de méthode */ GBinRoutine *routine; /* Objet des recherches */ GDexMethod *method; /* Méthode décompilée */ - GDalvikRegister *reg; /* Registre Dalvik représenté */ + const GDalvikRegister *reg; /* Registre Dalvik représenté */ uint16_t index; /* Identifiant du registre */ DexVariableIndex info; /* Nature du registre */ GBinVariable *this; /* Définition de "this" */ diff --git a/src/arch/dalvik/core.c b/src/arch/dalvik/core.c index ba07c97..9438d17 100644 --- a/src/arch/dalvik/core.c +++ b/src/arch/dalvik/core.c @@ -25,6 +25,9 @@ #include "register.h" +#include "operands/args.h" +#include "operands/pool.h" +#include "operands/register.h" @@ -48,6 +51,10 @@ bool init_dalvik_core(void) result &= init_dalvik_register_sharing(); + result &= init_dalvik_args_operand_sharing(); + result &= init_dalvik_pool_operand_sharing(); + result &= init_dalvik_register_operand_sharing(); + return result; } @@ -57,6 +64,30 @@ bool init_dalvik_core(void) * * * Paramètres : - * * * +* Description : Imprime des statistiques quant aux partages dans l'archi. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_share_stats(void) +{ + dump_dalvik_register_share_stats(); + + dump_dalvik_args_operand_share_stats(); + dump_dalvik_pool_operand_share_stats(); + dump_dalvik_register_operand_share_stats(); + +} +#endif + + +/****************************************************************************** +* * +* Paramètres : - * +* * * Description : Supprime les mécanismes internes de l'architecture Dalvik. * * * * Retour : - * @@ -69,4 +100,8 @@ void exit_dalvik_core(void) { exit_dalvik_register_sharing(); + exit_dalvik_args_operand_sharing(); + exit_dalvik_pool_operand_sharing(); + exit_dalvik_register_operand_sharing(); + } diff --git a/src/arch/dalvik/core.h b/src/arch/dalvik/core.h index e7a5e1e..4d7577a 100644 --- a/src/arch/dalvik/core.h +++ b/src/arch/dalvik/core.h @@ -32,6 +32,11 @@ /* Met en place les mécanismes internes de l'architecture. */ bool init_dalvik_core(void); +/* Imprime des statistiques quant aux partages dans l'archi. */ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_share_stats(void); +#endif + /* Supprime les mécanismes internes de l'architecture Dalvik. */ void exit_dalvik_core(void); diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c index cc1cab2..77fdd11 100644 --- a/src/arch/dalvik/instruction.c +++ b/src/arch/dalvik/instruction.c @@ -525,7 +525,7 @@ static void g_dalvik_instruction_get_rw_registers(const GDalvikInstruction *inst GArchInstruction *base; /* Version basique à manipuler */ size_t i; /* Boucle de parcours */ GArchOperand *operand; /* Operande à analyser */ - GDalvikRegister *reg; /* Registre concerné */ + const GDalvikRegister *reg; /* Registre concerné */ base = G_ARCH_INSTRUCTION(instr); diff --git a/src/arch/dalvik/operand.c b/src/arch/dalvik/operand.c index 802ce1e..e1a910c 100644 --- a/src/arch/dalvik/operand.c +++ b/src/arch/dalvik/operand.c @@ -474,14 +474,13 @@ static bool dalvik_read_fixed_operands(GArchInstruction *instr, GDexFormat *form /* Mise en place des arguments */ args = g_dalvik_args_operand_new(); - g_arch_instruction_attach_extra_operand(instr, args); for (i = 0; i < MIN(a, 4); i++) { op = g_dalvik_register_operand_new(content, pos, low, MDS_4_BITS, endian); if (op == NULL) goto err_registers; - g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), op); + args = G_ARCH_OPERAND(g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), op, NULL)); } @@ -494,7 +493,7 @@ static bool dalvik_read_fixed_operands(GArchInstruction *instr, GDexFormat *form /* Rajout des éléments finaux déjà chargés */ if (a == 5) - g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), opg); + args = G_ARCH_OPERAND(g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), opg, NULL)); else { @@ -502,6 +501,10 @@ static bool dalvik_read_fixed_operands(GArchInstruction *instr, GDexFormat *form g_object_unref(G_OBJECT(opg)); } + g_arch_instruction_attach_extra_operand(instr, args); + + /* Rajout de la cible */ + g_arch_instruction_attach_extra_operand(instr, target); return true; @@ -564,17 +567,18 @@ static bool dalvik_read_variatic_operands(GArchInstruction *instr, GDexFormat *f /* Mise en place des arguments */ args = g_dalvik_args_operand_new(); - g_arch_instruction_attach_extra_operand(instr, args); for (i = 0; i < a; i++) { op = g_dalvik_register_operand_new_from_existing(g_dalvik_register_new(c + i)); if (op == NULL) goto drvo_registers; - g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), op); + args = G_ARCH_OPERAND(g_dalvik_args_operand_add(G_DALVIK_ARGS_OPERAND(args), op, NULL)); } + g_arch_instruction_attach_extra_operand(instr, args); + /* Rajout de la cible */ g_arch_instruction_attach_extra_operand(instr, target); diff --git a/src/arch/dalvik/operands/args.c b/src/arch/dalvik/operands/args.c index 6e1725c..9e75604 100644 --- a/src/arch/dalvik/operands/args.c +++ b/src/arch/dalvik/operands/args.c @@ -24,13 +24,18 @@ #include "args.h" +#include <assert.h> #include <malloc.h> #include "../../operand-int.h" +#include "../../sharing/manager.h" +/* --------------------- MANIPULATION D'OPERANDES INDIVIDUELLES --------------------- */ + + /* Définition d'un opérande visant une liste d'opérandes Dalvik (instance) */ struct _GDalvikArgsOperand { @@ -62,11 +67,33 @@ static void g_dalvik_args_operand_dispose(GDalvikArgsOperand *); /* Procède à la libération totale de la mémoire. */ static void g_dalvik_args_operand_finalize(GDalvikArgsOperand *); +/* Initialise un nouvel objet partagé avec des informations. */ +static bool g_dalvik_args_operand_do_init(GDalvikArgsOperand *, const GDalvikArgsOperand *); + +/* Indique l'objet partagé correspond à une description donnée. */ +static gboolean g_dalvik_args_operand_compare_info(const GDalvikArgsOperand *, const GDalvikArgsOperand *); + +/* Compare un opérande avec un autre. */ +static bool g_dalvik_args_operand_compare(const GDalvikArgsOperand *, const GDalvikArgsOperand *); + /* Traduit un opérande en version humainement lisible. */ static void g_dalvik_args_operand_print(const GDalvikArgsOperand *, GBufferLine *, AsmSyntax); +/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */ + + +/* Gestionnaire des partages d'instances */ +static GShareManager *_dalvik_args_operand_manager = NULL; + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION D'OPERANDES INDIVIDUELLES */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini par la GLib pour une liste d'arguments Dalvik. */ G_DEFINE_TYPE(GDalvikArgsOperand, g_dalvik_args_operand, G_TYPE_ARCH_OPERAND); @@ -94,6 +121,10 @@ 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->cmp_info = (compare_shared_info_fc)g_dalvik_args_operand_compare_info; + + operand->compare = (operand_compare_fc)g_dalvik_args_operand_compare; operand->print = (operand_print_fc)g_dalvik_args_operand_print; } @@ -174,11 +205,107 @@ static void g_dalvik_args_operand_finalize(GDalvikArgsOperand *operand) GArchOperand *g_dalvik_args_operand_new(void) { - GDalvikArgsOperand *result; /* Structure à retourner */ + GArchOperand *result; /* Structure à retourner */ + + result = G_ARCH_OPERAND(g_share_manager_get(_dalvik_args_operand_manager, NULL)); + + 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_dalvik_args_operand_do_init(GDalvikArgsOperand *operand, const GDalvikArgsOperand *fake) +{ + size_t i; /* Boucle de parcours */ + + if (fake == NULL) + { + operand->args = NULL; + operand->count = 0; + } + + else + { + operand->args = (GArchOperand **)calloc(fake->count, sizeof(GArchOperand *)); + + for (i = 0; i < fake->count; i++) + operand->args[i] = fake->args[i]; + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à consulter. * +* fake = coquille vide contenant les infos à comparer. * +* * +* Description : Indique l'objet partagé correspond à une description donnée. * +* * +* Retour : TRUE si les détails centraux sont partagés, FALSE sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean g_dalvik_args_operand_compare_info(const GDalvikArgsOperand *operand, const GDalvikArgsOperand *fake) +{ + gboolean result; /* Bilan à retourner */ + + result = g_dalvik_args_operand_compare(operand, fake); + + return result; + +} + + +/****************************************************************************** +* * +* 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 bool g_dalvik_args_operand_compare(const GDalvikArgsOperand *a, const GDalvikArgsOperand *b) +{ + bool result; /* Bilan à renvoyer */ + size_t i; /* Boucle de parcours */ + + if (b == NULL) + result = (a->count == 0); - result = g_object_new(G_TYPE_DALVIK_ARGS_OPERAND, NULL); + else + { + result = (a->count == b->count); + + for (i = 0; i < a->count && result; i++) + result = g_arch_operand_compare(a->args[i], b->args[i]); + + } - return G_ARCH_OPERAND(result); + return result; } @@ -236,12 +363,25 @@ static void g_dalvik_args_operand_print(const GDalvikArgsOperand *operand, GBuff * * ******************************************************************************/ -void g_dalvik_args_operand_add(GDalvikArgsOperand *operand, GArchOperand *arg) +GDalvikArgsOperand *g_dalvik_args_operand_add(GDalvikArgsOperand *operand, GArchOperand *arg, GShareContainer *container) { - operand->args = (GArchOperand **)realloc(operand->args, - ++operand->count * sizeof(GArchOperand *)); + GSharedInstance *result; /* Nouvelle version à renvoyer */ + GDalvikArgsOperand fake; /* Transport d'informations */ + size_t i; /* Boucle de parcours */ + + fake.count = operand->count + 1; + fake.args = (GArchOperand **)calloc(fake.count, sizeof(GArchOperand *)); + + for (i = 0; i < operand->count; i++) + fake.args[i] = operand->args[i]; - operand->args[operand->count - 1] = arg; + fake.args[i] = arg; + + result = g_share_manager_update(_dalvik_args_operand_manager, G_SHARED_INSTANCE(operand), &fake, container); + + free(fake.args); + + return G_DALVIK_ARGS_OPERAND(result); } @@ -280,8 +420,74 @@ size_t g_dalvik_args_count(const GDalvikArgsOperand *operand) GArchOperand *g_dalvik_args_operand_get(const GDalvikArgsOperand *operand, size_t index) { - /* BUG_ON(index >= operand->count) */ + assert(index < operand->count); return operand->args[index]; } + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTAGES DE CONTENUS UNIQUES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Met en place les mécanismes de partage des opérandes Dalvik. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_dalvik_args_operand_sharing(void) +{ + _dalvik_args_operand_manager = g_share_manager_new(G_TYPE_DALVIK_ARGS_OPERAND); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Imprime des statistiques quant aux partages dans l'archi. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_args_operand_share_stats(void) +{ + g_share_manager_dump_stats(_dalvik_args_operand_manager); + +} +#endif + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Supprime les mécanismes de partage des opérandes Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_dalvik_args_operand_sharing(void) +{ + g_object_unref(G_OBJECT(_dalvik_args_operand_manager)); + +} diff --git a/src/arch/dalvik/operands/args.h b/src/arch/dalvik/operands/args.h index 993e551..b4f5e69 100644 --- a/src/arch/dalvik/operands/args.h +++ b/src/arch/dalvik/operands/args.h @@ -29,9 +29,13 @@ #include "../../operand.h" +#include "../../sharing/container.h" +/* --------------------- MANIPULATION D'OPERANDES INDIVIDUELLES --------------------- */ + + #define G_TYPE_DALVIK_ARGS_OPERAND g_dalvik_args_operand_get_type() #define G_DALVIK_ARGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_args_operand_get_type(), GDalvikArgsOperand)) #define G_IS_DALVIK_ARGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_args_operand_get_type())) @@ -54,7 +58,7 @@ GType g_dalvik_args_operand_get_type(void); GArchOperand *g_dalvik_args_operand_new(void); /* Ajoute un élément à la liste d'arguments Dalvik. */ -void g_dalvik_args_operand_add(GDalvikArgsOperand *, GArchOperand *); +GDalvikArgsOperand *g_dalvik_args_operand_add(GDalvikArgsOperand *, GArchOperand *, GShareContainer *); /* Fournit le nombre d'arguments pris en charge. */ size_t g_dalvik_args_count(const GDalvikArgsOperand *); @@ -64,4 +68,20 @@ GArchOperand *g_dalvik_args_operand_get(const GDalvikArgsOperand *, size_t); +/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */ + + +/* Met en place les mécanismes de partage des opérandes Dalvik. */ +bool init_dalvik_args_operand_sharing(void); + +/* Imprime des statistiques quant aux partages dans l'archi. */ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_args_operand_share_stats(void); +#endif + +/* Supprime les mécanismes de partage des opérandes Dalvik. */ +void exit_dalvik_args_operand_sharing(void); + + + #endif /* _ARCH_DALVIK_OPERANDS_ARGS_H */ diff --git a/src/arch/dalvik/operands/pool.c b/src/arch/dalvik/operands/pool.c index e737a0b..4884867 100644 --- a/src/arch/dalvik/operands/pool.c +++ b/src/arch/dalvik/operands/pool.c @@ -32,10 +32,14 @@ #include "../../operand-int.h" +#include "../../sharing/manager.h" #include "../../../format/dex/pool.h" +/* --------------------- MANIPULATION D'OPERANDES INDIVIDUELLES --------------------- */ + + /* Définition d'un opérande visant un élément de table de constantes Dalvik (instance) */ struct _GDalvikPoolOperand { @@ -68,11 +72,33 @@ static void g_dalvik_pool_operand_dispose(GDalvikPoolOperand *); /* Procède à la libération totale de la mémoire. */ static void g_dalvik_pool_operand_finalize(GDalvikPoolOperand *); +/* Initialise un nouvel objet partagé avec des informations. */ +static bool g_dalvik_pool_operand_do_init(GDalvikPoolOperand *, const GDalvikPoolOperand *); + +/* Indique l'objet partagé correspond à une description donnée. */ +static gboolean g_dalvik_pool_operand_compare_info(const GDalvikPoolOperand *, const GDalvikPoolOperand *); + +/* Compare un opérande avec un autre. */ +static bool g_dalvik_pool_operand_compare(const GDalvikPoolOperand *, const GDalvikPoolOperand *); + /* Traduit un opérande en version humainement lisible. */ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *, GBufferLine *, AsmSyntax); +/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */ + + +/* Gestionnaire des partages d'instances */ +static GShareManager *_dalvik_pool_operand_manager = NULL; + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION D'OPERANDES INDIVIDUELLES */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini par la GLib pour un un élément de table de constantes Dalvik. */ G_DEFINE_TYPE(GDalvikPoolOperand, g_dalvik_pool_operand, G_TYPE_ARCH_OPERAND); @@ -95,11 +121,16 @@ static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *klass) GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_pool_operand_dispose; object->finalize = (GObjectFinalizeFunc)g_dalvik_pool_operand_finalize; + operand = G_ARCH_OPERAND_CLASS(klass); + + operand->init = (init_shared_fc)g_dalvik_pool_operand_do_init; + operand->cmp_info = (compare_shared_info_fc)g_dalvik_pool_operand_compare_info; + + operand->compare = (operand_compare_fc)g_dalvik_pool_operand_compare; operand->print = (operand_print_fc)g_dalvik_pool_operand_print; } @@ -182,10 +213,13 @@ static void g_dalvik_pool_operand_finalize(GDalvikPoolOperand *operand) GArchOperand *g_dalvik_pool_operand_new(GDexFormat *format, DalvikPoolType type, const GBinContent *content, vmpa2t *pos, MemoryDataSize size, SourceEndian endian) { - GDalvikPoolOperand *result; /* Structure à retourner */ + GArchOperand *result; /* Structure à retourner */ uint8_t index8; /* Indice sur 8 bits */ uint16_t index16; /* Indice sur 16 bits */ bool test; /* Bilan de lecture */ + GDalvikPoolOperand fake; /* Transport d'informations */ + + result = NULL; switch (size) { @@ -201,17 +235,93 @@ GArchOperand *g_dalvik_pool_operand_new(GDexFormat *format, DalvikPoolType type, } if (!test) - return NULL; + goto gdpon_exit; + + fake.format = format; + fake.type = type; + fake.index = (size == MDS_8_BITS ? index8 : index16); + + result = G_ARCH_OPERAND(g_share_manager_get(_dalvik_pool_operand_manager, &fake)); + + gdpon_exit: + + 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_dalvik_pool_operand_do_init(GDalvikPoolOperand *operand, const GDalvikPoolOperand *fake) +{ + operand->format = fake->format; + g_object_ref(G_OBJECT(fake->format)); + + operand->type = fake->type; + operand->index = fake->index; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à consulter. * +* fake = coquille vide contenant les infos à comparer. * +* * +* Description : Indique l'objet partagé correspond à une description donnée. * +* * +* Retour : TRUE si les détails centraux sont partagés, FALSE sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean g_dalvik_pool_operand_compare_info(const GDalvikPoolOperand *operand, const GDalvikPoolOperand *fake) +{ + gboolean result; /* Bilan à retourner */ + + result = g_dalvik_pool_operand_compare(operand, fake); + + return result; + +} + - result = g_object_new(G_TYPE_DALVIK_POOL_OPERAND, NULL); +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ - g_object_ref(G_OBJECT(format)); +static bool g_dalvik_pool_operand_compare(const GDalvikPoolOperand *a, const GDalvikPoolOperand *b) +{ + bool result; /* Bilan à renvoyer */ - result->format = format; - result->type = type; - result->index = (size == MDS_8_BITS ? index8 : index16); + result = (a->format == b->format); + result &= (a->type == b->type); + result &= (a->index == b->index); - return G_ARCH_OPERAND(result); + return result; } @@ -413,3 +523,69 @@ uint32_t g_dalvik_pool_operand_get_index(const GDalvikPoolOperand *operand) return operand->index; } + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTAGES DE CONTENUS UNIQUES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Met en place les mécanismes de partage des opérandes Dalvik. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_dalvik_pool_operand_sharing(void) +{ + _dalvik_pool_operand_manager = g_share_manager_new(G_TYPE_DALVIK_POOL_OPERAND); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Imprime des statistiques quant aux partages dans l'archi. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_pool_operand_share_stats(void) +{ + g_share_manager_dump_stats(_dalvik_pool_operand_manager); + +} +#endif + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Supprime les mécanismes de partage des opérandes Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_dalvik_pool_operand_sharing(void) +{ + g_object_unref(G_OBJECT(_dalvik_pool_operand_manager)); + +} diff --git a/src/arch/dalvik/operands/pool.h b/src/arch/dalvik/operands/pool.h index 8223d1c..98d2d41 100644 --- a/src/arch/dalvik/operands/pool.h +++ b/src/arch/dalvik/operands/pool.h @@ -35,12 +35,15 @@ -#define G_TYPE_DALVIK_POOL_OPERAND g_dalvik_pool_operand_get_type() -#define G_DALVIK_POOL_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_pool_operand_get_type(), GDalvikPoolOperand)) -#define G_IS_DALVIK_POOL_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_pool_operand_get_type())) -#define G_DALVIK_POOL_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_POOL_OPERAND, GDalvikPoolOperandClass)) -#define G_IS_DALVIK_POOL_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_POOL_OPERAND)) -#define G_DALVIK_POOL_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_POOL_OPERAND, GDalvikPoolOperandClass)) +/* --------------------- MANIPULATION D'OPERANDES INDIVIDUELLES --------------------- */ + + +#define G_TYPE_DALVIK_POOL_OPERAND g_dalvik_pool_operand_get_type() +#define G_DALVIK_POOL_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DALVIK_POOL_OPERAND, GDalvikPoolOperand)) +#define G_IS_DALVIK_POOL_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DALVIK_POOL_OPERAND)) +#define G_DALVIK_POOL_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_POOL_OPERAND, GDalvikPoolOperandClass)) +#define G_IS_DALVIK_POOL_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_POOL_OPERAND)) +#define G_DALVIK_POOL_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_POOL_OPERAND, GDalvikPoolOperandClass)) /* Définition d'un opérande visant un élément de table de constantes Dalvik (instance) */ @@ -77,4 +80,20 @@ uint32_t g_dalvik_pool_operand_get_index(const GDalvikPoolOperand *); +/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */ + + +/* Met en place les mécanismes de partage des opérandes Dalvik. */ +bool init_dalvik_pool_operand_sharing(void); + +/* Imprime des statistiques quant aux partages dans l'archi. */ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_pool_operand_share_stats(void); +#endif + +/* Supprime les mécanismes de partage des opérandes Dalvik. */ +void exit_dalvik_pool_operand_sharing(void); + + + #endif /* _ARCH_DALVIK_OPERANDS_POOL_H */ diff --git a/src/arch/dalvik/operands/register.c b/src/arch/dalvik/operands/register.c index 1fc5782..dcdcbac 100644 --- a/src/arch/dalvik/operands/register.c +++ b/src/arch/dalvik/operands/register.c @@ -26,15 +26,19 @@ #include "../../operand-int.h" #include "../../register.h" +#include "../../sharing/manager.h" +/* --------------------- MANIPULATION D'OPERANDES INDIVIDUELLES --------------------- */ + + /* Définition d'un opérande visant un registre Dalvik (instance) */ struct _GDalvikRegisterOperand { GArchOperand parent; /* Instance parente */ - GDalvikRegister *reg; /* Registre représenté */ + const GDalvikRegister *reg; /* Registre représenté */ bool is_written; /* Changement de contenu */ }; @@ -60,6 +64,12 @@ static void g_dalvik_register_operand_dispose(GDalvikRegisterOperand *); /* Procède à la libération totale de la mémoire. */ static void g_dalvik_register_operand_finalize(GDalvikRegisterOperand *); +/* Initialise un nouvel objet partagé avec des informations. */ +static bool g_dalvik_register_operand_do_init(GDalvikRegisterOperand *, const GDalvikRegister *); + +/* Indique l'objet partagé correspond à une description donnée. */ +static gboolean g_dalvik_register_operand_compare_info(const GDalvikRegisterOperand *, const GDalvikRegister *); + /* Compare un opérande avec un autre. */ static bool g_dalvik_register_operand_compare(const GDalvikRegisterOperand *, const GDalvikRegisterOperand *); @@ -68,6 +78,19 @@ static void g_dalvik_register_operand_print(const GDalvikRegisterOperand *, GBuf +/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */ + + +/* Gestionnaire des partages d'instances */ +static GShareManager *_dalvik_register_operand_manager = NULL; + + + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION D'OPERANDES INDIVIDUELLES */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ G_DEFINE_TYPE(GDalvikRegisterOperand, g_dalvik_register_operand, G_TYPE_ARCH_OPERAND); @@ -90,11 +113,15 @@ static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *kl GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_register_operand_dispose; object->finalize = (GObjectFinalizeFunc)g_dalvik_register_operand_finalize; + operand = G_ARCH_OPERAND_CLASS(klass); + + operand->init = (init_shared_fc)g_dalvik_register_operand_do_init; + operand->cmp_info = (compare_shared_info_fc)g_dalvik_register_operand_compare_info; + operand->compare = (operand_compare_fc)g_dalvik_register_operand_compare; operand->print = (operand_print_fc)g_dalvik_register_operand_print; @@ -122,7 +149,7 @@ static void g_dalvik_register_operand_init(GDalvikRegisterOperand *operand) /****************************************************************************** * * -* Paramètres : binary = instance d'objet GLib à traiter. * +* Paramètres : operand = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -141,7 +168,7 @@ static void g_dalvik_register_operand_dispose(GDalvikRegisterOperand *operand) /****************************************************************************** * * -* Paramètres : binary = instance d'objet GLib à traiter. * +* Paramètres : operand = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -176,10 +203,13 @@ static void g_dalvik_register_operand_finalize(GDalvikRegisterOperand *operand) GArchOperand *g_dalvik_register_operand_new(const GBinContent *content, vmpa2t *pos, bool *low, MemoryDataSize size, SourceEndian endian) { - GDalvikRegisterOperand *result; /* Structure à retourner */ + GArchOperand *result; /* Structure à retourner */ uint8_t index8; /* Indice sur 8 bits */ uint16_t index16; /* Indice sur 16 bits */ bool test; /* Bilan de lecture */ + GDalvikRegister *reg; /* Registre à représenter */ + + result = NULL; switch (size) { @@ -198,24 +228,34 @@ GArchOperand *g_dalvik_register_operand_new(const GBinContent *content, vmpa2t * } if (!test) - return NULL; - - result = g_object_new(G_TYPE_DALVIK_REGISTER_OPERAND, NULL); + goto gdron_exit; switch (size) { case MDS_4_BITS: case MDS_8_BITS: - result->reg = g_dalvik_register_new(index8); + reg = g_dalvik_register_new(index8); break; case MDS_16_BITS: - result->reg = g_dalvik_register_new(index16); + reg = g_dalvik_register_new(index16); break; default: + reg = NULL; break; } - return G_ARCH_OPERAND(result); + if (reg != NULL) + { + result = g_dalvik_register_operand_new_from_existing(reg); + + if (result == NULL) + g_object_unref(G_OBJECT(reg)); + + } + + gdron_exit: + + return result; } @@ -234,32 +274,57 @@ GArchOperand *g_dalvik_register_operand_new(const GBinContent *content, vmpa2t * GArchOperand *g_dalvik_register_operand_new_from_existing(GDalvikRegister *reg) { - GDalvikRegisterOperand *result; /* Structure à retourner */ + GArchOperand *result; /* Structure à retourner */ + + result = G_ARCH_OPERAND(g_share_manager_get(_dalvik_register_operand_manager, reg)); + + return result; + +} - result = g_object_new(G_TYPE_DALVIK_REGISTER_OPERAND, NULL); - result->reg = reg; +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à initialiser. * +* reg = registre Dalvik à associer à l'opérande. * +* * +* Description : Initialise un nouvel objet partagé avec des informations. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dalvik_register_operand_do_init(GDalvikRegisterOperand *operand, const GDalvikRegister *reg) +{ + operand->reg = reg; - return G_ARCH_OPERAND(result); + return true; } /****************************************************************************** * * -* Paramètres : operand = opérande représentant un registre. * +* Paramètres : operand = objet partagé à consulter. * +* reg = registre Dalvik utilisé comme description. * * * -* Description : Fournit le registre Dalvik associé à l'opérande. * +* Description : Indique l'objet partagé correspond à une description donnée. * * * -* Retour : Représentation interne du registre. * +* Retour : TRUE si les détails centraux sont partagés, FALSE sinon. * * * * Remarques : - * * * ******************************************************************************/ -GDalvikRegister *g_dalvik_register_operand_get(const GDalvikRegisterOperand *operand) +static gboolean g_dalvik_register_operand_compare_info(const GDalvikRegisterOperand *operand, const GDalvikRegister *reg) { - return operand->reg; + gboolean result; /* Bilan à retourner */ + + result = g_arch_register_equal(G_ARCH_REGISTER(operand->reg), G_ARCH_REGISTER(reg)); + + return result; } @@ -307,6 +372,25 @@ static void g_dalvik_register_operand_print(const GDalvikRegisterOperand *operan /****************************************************************************** * * +* Paramètres : operand = opérande représentant un registre. * +* * +* Description : Fournit le registre Dalvik associé à l'opérande. * +* * +* Retour : Représentation interne du registre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const GDalvikRegister *g_dalvik_register_operand_get(const GDalvikRegisterOperand *operand) +{ + return operand->reg; + +} + + +/****************************************************************************** +* * * Paramètres : operand = opérande représentant un registre à mettre à jour. * * * * Description : Marque l'opérande comme étant écrit plutôt que consulté. * @@ -341,3 +425,69 @@ bool g_dalvik_register_operand_is_written(const GDalvikRegisterOperand *operand) return operand->is_written; } + + + +/* ---------------------------------------------------------------------------------- */ +/* PARTAGES DE CONTENUS UNIQUES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Met en place les mécanismes de partage des opérandes Dalvik. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_dalvik_register_operand_sharing(void) +{ + _dalvik_register_operand_manager = g_share_manager_new(G_TYPE_DALVIK_REGISTER_OPERAND); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Imprime des statistiques quant aux partages dans l'archi. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_register_operand_share_stats(void) +{ + g_share_manager_dump_stats(_dalvik_register_operand_manager); + +} +#endif + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Supprime les mécanismes de partage des opérandes Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_dalvik_register_operand_sharing(void) +{ + g_object_unref(G_OBJECT(_dalvik_register_operand_manager)); + +} diff --git a/src/arch/dalvik/operands/register.h b/src/arch/dalvik/operands/register.h index e8f28d1..9c6c61b 100644 --- a/src/arch/dalvik/operands/register.h +++ b/src/arch/dalvik/operands/register.h @@ -26,6 +26,7 @@ #include <glib-object.h> +#include <stdbool.h> #include "../register.h" @@ -34,12 +35,15 @@ -#define G_TYPE_DALVIK_REGISTER_OPERAND g_dalvik_register_operand_get_type() -#define G_DALVIK_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_register_operand_get_type(), GDalvikRegisterOperand)) -#define G_IS_DALVIK_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_register_operand_get_type())) -#define G_DALVIK_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_REGISTER_OPERAND, GDalvikRegisterOperandClass)) -#define G_IS_DALVIK_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_REGISTER_OPERAND)) -#define G_DALVIK_REGISTER_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_REGISTER_OPERAND, GDalvikRegisterOperandClass)) +/* --------------------- MANIPULATION D'OPERANDES INDIVIDUELLES --------------------- */ + + +#define G_TYPE_DALVIK_REGISTER_OPERAND g_dalvik_register_operand_get_type() +#define G_DALVIK_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DALVIK_REGISTER_OPERAND, GDalvikRegisterOperand)) +#define G_IS_DALVIK_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DALVIK_REGISTER_OPERAND)) +#define G_DALVIK_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_REGISTER_OPERAND, GDalvikRegisterOperandClass)) +#define G_IS_DALVIK_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_REGISTER_OPERAND)) +#define G_DALVIK_REGISTER_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_REGISTER_OPERAND, GDalvikRegisterOperandClass)) /* Définition d'un opérande visant un registre Dalvik (instance) */ @@ -59,7 +63,7 @@ GArchOperand *g_dalvik_register_operand_new(const GBinContent *, vmpa2t *, bool GArchOperand *g_dalvik_register_operand_new_from_existing(GDalvikRegister *); /* Fournit le registre Dalvik associé à l'opérande. */ -GDalvikRegister *g_dalvik_register_operand_get(const GDalvikRegisterOperand *); +const GDalvikRegister *g_dalvik_register_operand_get(const GDalvikRegisterOperand *); /* Marque l'opérande comme étant écrit plutôt que consulté. */ void g_dalvik_register_operand_mark_as_written(GDalvikRegisterOperand *); @@ -69,4 +73,20 @@ bool g_dalvik_register_operand_is_written(const GDalvikRegisterOperand *); +/* -------------------------- PARTAGES DE CONTENUS UNIQUES -------------------------- */ + + +/* Met en place les mécanismes de partage des opérandes Dalvik. */ +bool init_dalvik_register_operand_sharing(void); + +/* Imprime des statistiques quant aux partages dans l'archi. */ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_register_operand_share_stats(void); +#endif + +/* Supprime les mécanismes de partage des opérandes Dalvik. */ +void exit_dalvik_register_operand_sharing(void); + + + #endif /* _ARCH_DALVIK_OPERANDS_REGISTER_H */ diff --git a/src/arch/dalvik/register.c b/src/arch/dalvik/register.c index d112a86..d455eb2 100644 --- a/src/arch/dalvik/register.c +++ b/src/arch/dalvik/register.c @@ -62,6 +62,12 @@ static void g_dalvik_register_class_init(GDalvikRegisterClass *); /* Initialise une instance de registre Dalvik. */ static void g_dalvik_register_init(GDalvikRegister *); +/* Supprime toutes les références externes. */ +static void g_dalvik_register_dispose(GDalvikRegister *); + +/* Procède à la libération totale de la mémoire. */ +static void g_dalvik_register_finalize(GDalvikRegister *); + /* Initialise un nouvel objet partagé avec des informations. */ static bool g_dalvik_register_do_init(GDalvikRegister *, const uint16_t *); @@ -110,8 +116,14 @@ G_DEFINE_TYPE(GDalvikRegister, g_dalvik_register, G_TYPE_ARCH_REGISTER); static void g_dalvik_register_class_init(GDalvikRegisterClass *klass) { + GObjectClass *object; /* Autre version de la classe */ GArchRegisterClass *register_class; /* Classe de haut niveau */ + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_dalvik_register_dispose; + object->finalize = (GObjectFinalizeFunc)g_dalvik_register_finalize; + register_class = G_ARCH_REGISTER_CLASS(klass); register_class->init = (init_shared_fc)g_dalvik_register_do_init; @@ -144,6 +156,44 @@ static void g_dalvik_register_init(GDalvikRegister *reg) /****************************************************************************** * * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_dispose(GDalvikRegister *reg) +{ + G_OBJECT_CLASS(g_dalvik_register_parent_class)->dispose(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_register_finalize(GDalvikRegister *reg) +{ + G_OBJECT_CLASS(g_dalvik_register_parent_class)->finalize(G_OBJECT(reg)); + +} + + +/****************************************************************************** +* * * Paramètres : index = indice du registre correspondant. * * * * Description : Crée une réprésentation de registre Dalvik. * @@ -160,10 +210,6 @@ GDalvikRegister *g_dalvik_register_new(uint16_t index) result = G_DALVIK_REGISTER(g_share_manager_get(_dalvik_register_manager, &index)); - //result = g_object_new(G_TYPE_DALVIK_REGISTER, NULL); - - //result->index = index; - return result; } @@ -198,7 +244,7 @@ static bool g_dalvik_register_do_init(GDalvikRegister *reg, const uint16_t *inde * * * Description : Indique l'objet partagé correspond à une description donnée. * * * -* Retour : true si les détails centraux sont partagés, false sinon. * +* Retour : TRUE si les détails centraux sont partagés, FALSE sinon. * * * * Remarques : - * * * @@ -206,7 +252,7 @@ static bool g_dalvik_register_do_init(GDalvikRegister *reg, const uint16_t *inde static gboolean g_dalvik_register_compare_info(const GDalvikRegister *reg, const uint16_t *index) { - bool result; /* Bilan à retourner */ + gboolean result; /* Bilan à retourner */ result = (reg->index == *index); @@ -355,18 +401,36 @@ bool init_dalvik_register_sharing(void) * * * Paramètres : - * * * -* Description : Supprime les mécanismes de partage des registres Dalvik. * +* Description : Imprime des statistiques quant aux partages dans l'archi. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ - -void exit_dalvik_register_sharing(void) +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_register_share_stats(void) { + g_share_manager_dump_stats(_dalvik_register_manager); +} +#endif +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Supprime les mécanismes de partage des registres Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_dalvik_register_sharing(void) +{ + g_object_unref(G_OBJECT(_dalvik_register_manager)); } diff --git a/src/arch/dalvik/register.h b/src/arch/dalvik/register.h index ab7368f..03faf76 100644 --- a/src/arch/dalvik/register.h +++ b/src/arch/dalvik/register.h @@ -69,6 +69,11 @@ uint16_t g_dalvik_register_get_index(const GDalvikRegister *); /* Met en place les mécanismes de partage des registres Dalvik. */ bool init_dalvik_register_sharing(void); +/* Imprime des statistiques quant aux partages dans l'archi. */ +#ifdef DEBUG_DUMP_STATS +void dump_dalvik_register_share_stats(void); +#endif + /* Supprime les mécanismes de partage des registres Dalvik. */ void exit_dalvik_register_sharing(void); diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h index 5cc645f..3d3ffc9 100644 --- a/src/arch/operand-int.h +++ b/src/arch/operand-int.h @@ -26,6 +26,7 @@ #include "operand.h" +#include "sharing/instance-int.h" @@ -41,6 +42,8 @@ struct _GArchOperand { GObject parent; /* A laisser en premier */ + unsigned int shared_count; /* Compteur de partages */ + char *alt_text; /* Eventuel texte alternatif */ size_t alt_len; /* Taille de ce texte */ RenderingTagType alt_tag; /* Type de rendu */ @@ -53,6 +56,9 @@ struct _GArchOperandClass { GObjectClass parent; /* A laisser en premier */ + init_shared_fc init; /* Mise en place via interface */ + compare_shared_info_fc cmp_info; /* Comparaison des détails */ + 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 b355afd..ec970ea 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -38,16 +38,34 @@ static void g_arch_operand_class_init(GArchOperandClass *); /* Initialise une instance d'opérande d'architecture. */ static void g_arch_operand_init(GArchOperand *); +/* Procède à l'initialisation de l'interface de partage. */ +static void g_arch_operand_interface_init(GSharedInstanceInterface *); + /* Supprime toutes les références externes. */ static void g_arch_operand_dispose(GArchOperand *); /* Procède à la libération totale de la mémoire. */ static void g_arch_operand_finalize(GArchOperand *); +/* Initialise un nouvel objet partagé avec des informations. */ +static bool g_arch_operand_do_init(GArchOperand *, const void *); + +/* Fournit la valeur du compteur de partage. */ +static unsigned int g_arch_operand_get_references(const GArchOperand *); + +/* Incrémente le compteur de partage. */ +static void g_arch_operand_inc_references(GArchOperand *); + +/* Décrémente le compteur de partage. */ +static void g_arch_operand_dec_references(GArchOperand *); + +/* Indique l'objet partagé correspond à une description donnée. */ +static gboolean g_arch_operand_compare_info(const GArchOperand *, const void *); /* Indique le type défini pour un opérande d'architecture. */ -G_DEFINE_TYPE(GArchOperand, g_arch_operand, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_SHARED_INSTANCE, g_arch_operand_interface_init)); @@ -95,6 +113,32 @@ static void g_arch_operand_init(GArchOperand *operand) /****************************************************************************** * * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de partage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_operand_interface_init(GSharedInstanceInterface *iface) +{ + iface->init = (init_shared_fc)g_arch_operand_do_init; + + iface->get_ref = (get_shared_ref_fc)g_arch_operand_get_references; + iface->inc_ref = (inc_shared_ref_fc)g_arch_operand_inc_references; + iface->dec_ref = (dec_shared_ref_fc)g_arch_operand_dec_references; + + iface->cmp_info = (compare_shared_info_fc)g_arch_operand_compare_info; + iface->is_equal = (is_shared_equal_fc)g_arch_operand_compare; + +} + + +/****************************************************************************** +* * * Paramètres : operand = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * @@ -135,6 +179,111 @@ static void g_arch_operand_finalize(GArchOperand *operand) /****************************************************************************** * * +* Paramètres : operand = objet partagé à initialiser. * +* info = information à utiliser pour la mise en place. * +* * +* Description : Initialise un nouvel objet partagé avec des informations. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_operand_do_init(GArchOperand *operand, const void *info) +{ + bool result; /* Bilan à retourner */ + + result = G_ARCH_OPERAND_GET_CLASS(operand)->init(G_SHARED_INSTANCE(operand), info); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à consulter. * +* * +* Description : Fournit la valeur du compteur de partage. * +* * +* Retour : Nombre de partages courant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static unsigned int g_arch_operand_get_references(const GArchOperand *operand) +{ + return operand->shared_count; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à modifier. * +* * +* Description : Incrémente le compteur de partage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_operand_inc_references(GArchOperand *operand) +{ + operand->shared_count++; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à modifier. * +* * +* Description : Décrémente le compteur de partage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_operand_dec_references(GArchOperand *operand) +{ + operand->shared_count--; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = objet partagé à consulter. * +* info = compilation de d'information à analyser. * +* * +* Description : Indique l'objet partagé correspond à une description donnée. * +* * +* Retour : true si les détails centraux sont partagés, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean g_arch_operand_compare_info(const GArchOperand *operand, const void *info) +{ + bool result; /* Bilan à retourner */ + + result = G_ARCH_OPERAND_GET_CLASS(operand)->cmp_info(G_SHARED_INSTANCE(operand), info); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : a = premier opérande à consulter. * * b = second opérande à consulter. * * * diff --git a/src/arch/sharing/Makefile.am b/src/arch/sharing/Makefile.am index 46496c2..48c6636 100644 --- a/src/arch/sharing/Makefile.am +++ b/src/arch/sharing/Makefile.am @@ -2,6 +2,8 @@ noinst_LTLIBRARIES = libarchsharing.la libarchsharing_la_SOURCES = \ + container-int.h \ + container.h container.c \ instance-int.h \ instance.h instance.c \ manager.h manager.c diff --git a/src/arch/sharing/container-int.h b/src/arch/sharing/container-int.h new file mode 100644 index 0000000..2bc5395 --- /dev/null +++ b/src/arch/sharing/container-int.h @@ -0,0 +1,51 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * container-int.h - définitions internes propres aux intégrateurs de contenu + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_SHARING_CONTAINER_INT_H +#define _ARCH_SHARING_CONTAINER_INT_H + + +#include "container.h" + + + +/* Assure la mise à jour du contenu d'un intégrateur. */ +typedef void (* replace_shared_fc) (GShareContainer *, GSharedInstance *, GSharedInstance *); + + +/* Règles de partage d'une instance GObject (interface) */ +struct _GShareContainerIface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + replace_shared_fc replace; /* Mise à jour du conteneur */ + +}; + + +/* Redéfinition */ +typedef GShareContainerIface GShareContainerInterface; + + + +#endif /* _ARCH_SHARING_CONTAINER_INT_H */ diff --git a/src/arch/sharing/container.c b/src/arch/sharing/container.c new file mode 100644 index 0000000..b968dad --- /dev/null +++ b/src/arch/sharing/container.c @@ -0,0 +1,87 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * content.c - intégration de données partagées + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "container.h" + + +#include <assert.h> + + +#include "container-int.h" + + + +/* Procède à l'initialisation de l'interface d'intégration. */ +static void g_share_container_default_init(GShareContainerInterface *); + + + +/* Détermine le type d'une interface pour l'intégration de contenu partagé. */ +G_DEFINE_INTERFACE(GShareContainer, g_share_container, G_TYPE_OBJECT) + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'intégration. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_share_container_default_init(GShareContainerInterface *iface) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : instance = intégrateur à éventuellement manipuler. * +* old = ancien contenu à remplacer si besoin est. * +* new = nouveau contenu, potentiellement original. * +* * +* Description : Assure la mise à jour du contenu d'un intégrateur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_share_container_replace(GShareContainer *container, GSharedInstance *old, GSharedInstance *new) +{ + GShareContainerIface *iface; /* Interface utilisée */ + + if (old != new) + { + iface = G_SHARE_CONTAINER_GET_IFACE(container); + + iface->replace(container, old, new); + + } + +} diff --git a/src/arch/sharing/container.h b/src/arch/sharing/container.h new file mode 100644 index 0000000..d1ac8b2 --- /dev/null +++ b/src/arch/sharing/container.h @@ -0,0 +1,59 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * content.h - prototypes pour l'intégration de données partagées + * + * Copyright (C) 2016 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_SHARING_CONTAINER_H +#define _ARCH_SHARING_CONTAINER_H + + +#include <stdbool.h> +#include <glib-object.h> + + +#include "instance.h" + + + +#define G_TYPE_SHARE_CONTAINER (g_share_container_get_type()) +#define G_SHARE_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SHARE_CONTAINER, GShareContainer)) +#define G_SHARE_CONTAINER_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_SHARE_CONTAINER, GShareContainerIface)) +#define GTK_IS_SHARE_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SHARE_CONTAINER)) +#define GTK_IS_SHARE_CONTAINER_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_SHARE_CONTAINER)) +#define G_SHARE_CONTAINER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_SHARE_CONTAINER, GShareContainerIface)) + + +/* Intégrateur de contenu partagé (coquille vide) */ +typedef struct _GShareContainer GShareContainer; + +/* Intégrateur de contenu partagé (interface) */ +typedef struct _GShareContainerIface GShareContainerIface; + + +/* Détermine le type d'une interface pour l'intégration de contenu partagé. */ +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 *); + + + +#endif /* _ARCH_SHARING_CONTAINER_H */ diff --git a/src/arch/sharing/instance.c b/src/arch/sharing/instance.c index b737206..956a4c7 100644 --- a/src/arch/sharing/instance.c +++ b/src/arch/sharing/instance.c @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * content.c - lecture de données binaires quelconques + * instance.c - partage de données d'architecture quelconques * * Copyright (C) 2016 Cyrille Bagard * @@ -42,7 +42,7 @@ G_DEFINE_INTERFACE(GSharedInstance, g_shared_instance, G_TYPE_OBJECT) /****************************************************************************** * * -* Paramètres : iface = interface GTK à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * * Description : Procède à l'initialisation de l'interface de partage. * * * diff --git a/src/arch/sharing/instance.h b/src/arch/sharing/instance.h index fc7fa30..8cf8385 100644 --- a/src/arch/sharing/instance.h +++ b/src/arch/sharing/instance.h @@ -1,6 +1,6 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * content.h - prototypes pour la lecture de données binaires quelconques + * instance.h - prototypes pour le partage de données d'architecture quelconques * * Copyright (C) 2016 Cyrille Bagard * diff --git a/src/arch/sharing/manager.c b/src/arch/sharing/manager.c index 9f6ec39..2e92766 100644 --- a/src/arch/sharing/manager.c +++ b/src/arch/sharing/manager.c @@ -25,6 +25,9 @@ #include <assert.h> +#ifdef DEBUG_DUMP_STATS +# include <stdio.h> +#endif @@ -34,6 +37,7 @@ struct _GShareManager GObject parent; /* A laisser en premier */ GHashTable *table; /* Collection de partages */ + GMutex access; /* Accès à la table */ GType managed; /* Type d'instances gérées */ @@ -103,6 +107,7 @@ static void g_share_manager_class_init(GShareManagerClass *class) static void g_share_manager_init(GShareManager *manager) { + g_mutex_init(&manager->access); } @@ -122,6 +127,7 @@ static void g_share_manager_init(GShareManager *manager) static void g_share_manager_dispose(GShareManager *manager) { g_hash_table_unref(manager->table); + g_mutex_clear(&manager->access); G_OBJECT_CLASS(g_share_manager_parent_class)->dispose(G_OBJECT(manager)); @@ -190,7 +196,7 @@ GShareManager *g_share_manager_new(GType type) * * ******************************************************************************/ -GSharedInstance *g_share_manager_get(const GShareManager *manager, const void *info) +GSharedInstance *g_share_manager_get(GShareManager *manager, const void *info) { GSharedInstance *result; /* Trouvaille à retourner */ gpointer found; /* Elément correspondant ? */ @@ -204,6 +210,8 @@ GSharedInstance *g_share_manager_get(const GShareManager *manager, const void *i return g_shared_instance_compare_info(key, nfo); } + g_mutex_lock(&manager->access); + found = g_hash_table_find(manager->table, (GHRFunc)find_shared_matching_info, (void *)info); if (found == NULL) @@ -220,6 +228,7 @@ GSharedInstance *g_share_manager_get(const GShareManager *manager, const void *i else { + g_shared_instance_inc_references(result); #ifndef NDEBUG new = g_hash_table_add(manager->table, result); @@ -241,6 +250,123 @@ GSharedInstance *g_share_manager_get(const GShareManager *manager, const void *i g_shared_instance_inc_references(result); } + g_mutex_unlock(&manager->access); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : manager = gestionnaire d'instance à consulter. * +* old = ancienne instance partagée à faire évoluer. * +* info = informations à retrouver intégralement. * +* container = propriétaire de l'ancienne version à contacter. * +* * +* Description : Met à jour une instance partagée. * +* * +* Retour : Instance existante déjà partagée ou nouvellement créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GSharedInstance *g_share_manager_update(GShareManager *manager, GSharedInstance *old, const void *info, GShareContainer *container) +{ + GSharedInstance *result; /* Nouvelle instance à renvoyer*/ + + result = g_share_manager_get(manager, info); + + if (container != NULL) + g_share_container_replace(container, old, result); + + g_share_manager_put(manager, old); + return result; } + + +/****************************************************************************** +* * +* Paramètres : manager = gestionnaire d'instance à consulter. * +* shared = instance partagée à libérer. * +* * +* Description : Abandonne un usage d'une instance partagée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_share_manager_put(GShareManager *manager, GSharedInstance *shared) +{ +#ifndef NDEBUG + gboolean found; /* Présence de partage existant*/ +#endif + + g_mutex_lock(&manager->access); + + g_shared_instance_dec_references(shared); + + if (g_shared_instance_get_references(shared) == 1) + { +#ifndef NDEBUG + found = g_hash_table_remove(manager->table, shared); + assert(found); +#else + g_hash_table_remove(manager->table, shared); +#endif + } + + g_mutex_unlock(&manager->access); + +} + + +/****************************************************************************** +* * +* Paramètres : manager = gestionnaire d'instance à consulter. * +* * +* Description : Imprime des statistiques d'utilisation du gestionnaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#ifdef DEBUG_DUMP_STATS +void g_share_manager_dump_stats(GShareManager *manager) +{ + unsigned int counter; /* Quantité nécessaire */ + GTypeQuery query; /* Informations sur un type */ + guint size; /* Taille de la table */ + + void count_shared_instances(const GSharedInstance *key, gpointer unused, unsigned int *c) + { + *c += g_shared_instance_get_references(key); + } + + counter = 0; + + g_mutex_lock(&manager->access); + + g_hash_table_foreach(manager->table, (GHFunc)count_shared_instances, &counter); + + size = g_hash_table_size(manager->table); + + g_mutex_unlock(&manager->access); + + g_type_query(manager->managed, &query); + + printf("%s: current = %u / %u - needed = %u / %u (size=%u, saved=%u)\n", + query.type_name, + size, size * query.instance_size, + counter, counter * query.instance_size, + query.instance_size, + (counter - size) * query.instance_size); + +} +#endif diff --git a/src/arch/sharing/manager.h b/src/arch/sharing/manager.h index 85f4b1f..0a44214 100644 --- a/src/arch/sharing/manager.h +++ b/src/arch/sharing/manager.h @@ -29,6 +29,7 @@ #include <stdbool.h> +#include "container.h" #include "instance.h" @@ -59,7 +60,18 @@ GType g_share_manager_get_type(void); GShareManager *g_share_manager_new(GType); /* Retrouve ou crée une instance partagée. */ -GSharedInstance *g_share_manager_get(const GShareManager *, const void *); +GSharedInstance *g_share_manager_get(GShareManager *, const void *); + +/* Met à jour une instance partagée. */ +GSharedInstance *g_share_manager_update(GShareManager *, GSharedInstance *, const void *, GShareContainer *); + +/* Abandonne un usage d'une instance partagée. */ +void g_share_manager_put(GShareManager *, GSharedInstance *); + +/* Imprime des statistiques d'utilisation du gestionnaire. */ +#ifdef DEBUG_DUMP_STATS +void g_share_manager_dump_stats(GShareManager *); +#endif diff --git a/src/common/extstr.c b/src/common/extstr.c index 2e69e3f..43a5ec9 100644 --- a/src/common/extstr.c +++ b/src/common/extstr.c @@ -196,13 +196,13 @@ char *strrpl(char *haystack, const char *needle1, const char *needle2) haystack = (char *)realloc(haystack, inlen * sizeof(char *)); found = haystack + index; - memmove(found + len1, found + len2, inlen - index + len2); + memmove(found + len2, found + len1, inlen + len2 - index); } else if (len2 < len1) { - memmove(found + len2, found + len1, inlen - index - len1); + memmove(found + len2, found + len1, inlen + len2 - index); inlen -= (len1 - len2); diff --git a/src/core/processors.c b/src/core/processors.c index 9c67a87..2b1e0ca 100644 --- a/src/core/processors.c +++ b/src/core/processors.c @@ -45,6 +45,9 @@ typedef struct _proc_t GType instance; /* Type à manipuler en interne */ init_arch_fc init; /* Phase d'intialisation */ +#ifdef DEBUG_DUMP_STATS + dump_arch_stats_fc dump; /* Affichage de statistiques */ +#endif exit_arch_fc exit; /* Phase de relâchement */ } proc_t; @@ -69,6 +72,7 @@ static proc_t *find_processor_by_key(const char *); * name = désignation humaine de l'architecture. * * instance = type GLib représentant le type à instancier. * * init = procédure d'initialisation de mécanismes internes.* +* dump = procédure d'affichage de statistiques. * * exit = procédure de suppression de mécanismes internes. * * * * Description : Enregistre un processeur pour une architecture donnée. * @@ -78,8 +82,11 @@ static proc_t *find_processor_by_key(const char *); * Remarques : - * * * ******************************************************************************/ - +#ifdef DEBUG_DUMP_STATS +bool register_processor_type(const char *key, const char *name, GType instance, init_arch_fc init, dump_arch_stats_fc dump, exit_arch_fc exit) +#else bool register_processor_type(const char *key, const char *name, GType instance, init_arch_fc init, exit_arch_fc exit) +#endif { bool result; /* Bilan à retourner */ proc_t *new; /* Nouvel élément à définir */ @@ -104,6 +111,9 @@ bool register_processor_type(const char *key, const char *name, GType instance, new->instance = instance; new->init = init; +#ifdef DEBUG_DUMP_STATS + new->dump = dump; +#endif new->exit = exit; } @@ -134,10 +144,18 @@ bool load_hard_coded_processors_definitions(void) result = true; result &= register_processor_type("armv7", "ARM v7", G_TYPE_ARMV7_PROCESSOR, +#ifdef DEBUG_DUMP_STATS + init_armv7_core, NULL, exit_armv7_core); +#else init_armv7_core, exit_armv7_core); +#endif result &= register_processor_type("dalvik", "Dalvik Virtual Machine", G_TYPE_DALVIK_PROCESSOR, +#ifdef DEBUG_DUMP_STATS + init_dalvik_core, dump_dalvik_share_stats, exit_dalvik_core); +#else init_dalvik_core, exit_dalvik_core); +#endif //result &= register_processor_type("jvm", "Java Virtual Machine", G_TYPE_JVM_PROCESSOR); @@ -278,3 +296,37 @@ GArchProcessor *get_arch_processor_for_type(const char *key) return result; } + + +/****************************************************************************** +* * +* Paramètres : proc = processeur associé à l'architecture à traiter. * +* * +* Description : Imprime des statistiques quant aux partages. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +#ifdef DEBUG_DUMP_STATS +void display_share_stats(GArchProcessor *proc) +{ + GType type; /* Type de processeur */ + size_t i; /* Boucle de parcours */ + + type = G_OBJECT_TYPE(proc); + + G_LOCK(_pdef_access); + + for (i = 0; i < _processors_definitions_count; i++) + if (_processors_definitions[i].instance == type) + { + _processors_definitions[i].dump(); + break; + } + + G_UNLOCK(_pdef_access); + +} +#endif diff --git a/src/core/processors.h b/src/core/processors.h index 4f82dc3..6104c97 100644 --- a/src/core/processors.h +++ b/src/core/processors.h @@ -36,12 +36,21 @@ /* Mise en place de mécanismes internes */ typedef bool (* init_arch_fc) (void); +/* Affichage de statistiques */ +#ifdef DEBUG_DUMP_STATS +typedef void (* dump_arch_stats_fc) (void); +#endif + /* Suppression de mécanismes internes */ typedef void (* exit_arch_fc) (void); /* Enregistre un processeur pour une architecture donnée. */ +#ifdef DEBUG_DUMP_STATS +bool register_processor_type(const char *, const char *, GType, init_arch_fc, dump_arch_stats_fc, exit_arch_fc); +#else bool register_processor_type(const char *, const char *, GType, init_arch_fc, exit_arch_fc); +#endif /* Charge les définitions de processeurs "natifs". */ bool load_hard_coded_processors_definitions(void); @@ -55,6 +64,10 @@ const char *get_arch_processor_name(const char *); /* Fournit le processeur d'architecture correspondant à un type. */ GArchProcessor *get_arch_processor_for_type(const char *); +/* Imprime des statistiques quant aux partages. */ +#ifdef DEBUG_DUMP_STATS +void display_share_stats(GArchProcessor *); +#endif #endif /* _ANALYSIS_DB_COLLECTION_H */ |