diff options
Diffstat (limited to 'src/arch/operands/target.c')
-rw-r--r-- | src/arch/operands/target.c | 162 |
1 files changed, 116 insertions, 46 deletions
diff --git a/src/arch/operands/target.c b/src/arch/operands/target.c index 5edc805..6450834 100644 --- a/src/arch/operands/target.c +++ b/src/arch/operands/target.c @@ -37,6 +37,7 @@ #include "targetable-int.h" #include "../../analysis/routine.h" #include "../../common/extstr.h" +#include "../../common/sort.h" #include "../../format/format.h" #include "../../format/strsym.h" #include "../../glibext/gbinarycursor.h" @@ -60,7 +61,7 @@ static void g_target_operand_dispose(GTargetOperand *); static void g_target_operand_finalize(GTargetOperand *); /* Compare un opérande avec un autre. */ -static int g_target_operand_compare(const GTargetOperand *, const GTargetOperand *); +static int g_target_operand_compare(const GTargetOperand *, const GTargetOperand *, bool); /* Traduit un opérande en version humainement lisible. */ static void g_target_operand_print(const GTargetOperand *, GBufferLine *); @@ -68,6 +69,9 @@ static void g_target_operand_print(const GTargetOperand *, GBufferLine *); /* Construit un petit résumé concis de l'opérande. */ static char *g_target_operand_build_tooltip(const GTargetOperand *, const GLoadedBinary *); +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_target_operand_hash(const GTargetOperand *, bool); + /* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ @@ -122,6 +126,8 @@ static void g_target_operand_class_init(GTargetOperandClass *klass) operand->print = (operand_print_fc)g_target_operand_print; operand->build_tooltip = (operand_build_tooltip_fc)g_target_operand_build_tooltip; + operand->hash = (operand_hash_fc)g_target_operand_hash; + operand->unserialize = (unserialize_operand_fc)g_target_operand_unserialize; operand->serialize = (serialize_operand_fc)g_target_operand_serialize; @@ -142,10 +148,10 @@ static void g_target_operand_class_init(GTargetOperandClass *klass) static void g_target_operand_init(GTargetOperand *operand) { - operand->size = MDS_UNDEFINED; + GET_TARGET_OP_EXTRA(operand)->size = MDS_UNDEFINED; + init_vmpa(&operand->addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); - operand->strict = true; operand->symbol = NULL; operand->diff = 0; @@ -211,8 +217,9 @@ static void g_target_operand_finalize(GTargetOperand *operand) /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * +* Paramètres : a = premier opérande à consulter. * +* b = second opérande à consulter. * +* lock = précise le besoin en verrouillage. * * * * Description : Compare un opérande avec un autre. * * * @@ -222,56 +229,56 @@ static void g_target_operand_finalize(GTargetOperand *operand) * * ******************************************************************************/ -static int g_target_operand_compare(const GTargetOperand *a, const GTargetOperand *b) +static int g_target_operand_compare(const GTargetOperand *a, const GTargetOperand *b, bool lock) { int result; /* Bilan à retourner */ + tarop_extra_data_t *ea; /* Données insérées à modifier */ + tarop_extra_data_t *eb; /* Données insérées à modifier */ + GArchOperandClass *class; /* Classe parente normalisée */ - result = cmp_vmpa(&a->addr, &b->addr); - if (result != 0) goto gtoc_done; + ea = GET_TARGET_OP_EXTRA(a); + eb = GET_TARGET_OP_EXTRA(b); - if (a->size < b->size) + if (lock) { - result = -1; - goto gtoc_done; - } - else if (a->size > b->size) - { - result = 1; - goto gtoc_done; + LOCK_GOBJECT_EXTRA(ea); + LOCK_GOBJECT_EXTRA(eb); } - if (a->symbol == NULL && b->symbol != NULL) - { - result = -1; - goto gtoc_done; - } - else if (a->symbol != NULL && b->symbol == NULL) - { - result = 1; - goto gtoc_done; - } - else if (a->symbol != NULL && b->symbol != NULL) + result = sort_unsigned_long(ea->size, eb->size); + + if (result == 0) + result = cmp_vmpa(&a->addr, &b->addr); + + if (result == 0) { - result = g_binary_symbol_cmp((const GBinSymbol *[]) { a->symbol }, - (const GBinSymbol *[]) { b->symbol }); - if (result != 0) goto gtoc_done; + if (a->symbol == NULL && b->symbol != NULL) + result = -1; + + else if (a->symbol != NULL && b->symbol == NULL) + result = 1; + + else if (a->symbol != NULL && b->symbol != NULL) + result = g_binary_symbol_cmp((const GBinSymbol *[]) { a->symbol }, + (const GBinSymbol *[]) { b->symbol }); + } - if (a->diff < b->diff) + if (result == 0) + result = sort_uint64_t(a->diff, b->diff); + + if (result == 0) { - result = -1; - goto gtoc_done; + class = G_ARCH_OPERAND_CLASS(g_target_operand_parent_class); + result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); } - else if (a->diff > b->diff) + + if (lock) { - result = 1; - goto gtoc_done; + UNLOCK_GOBJECT_EXTRA(eb); + UNLOCK_GOBJECT_EXTRA(ea); } - result = 0; - - gtoc_done: - return result; } @@ -296,6 +303,7 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l vmpa2t tmp; /* Coquille vide pour argument */ VMPA_BUFFER(value); /* Adresse brute à imprimer */ size_t len; /* Taille de l'élément inséré */ + MemoryDataSize size; /* Taille retenue */ label = g_binary_symbol_get_label(operand->symbol); @@ -322,7 +330,9 @@ static void g_target_operand_print(const GTargetOperand *operand, GBufferLine *l } else { - vmpa2_to_string(&operand->addr, operand->size, value, &len); + size = g_target_operand_get_size(operand); + + vmpa2_to_string(&operand->addr, size, value, &len); g_buffer_line_append_text(line, DLC_ASSEMBLY, value, len, RTT_LABEL, G_OBJECT(operand)); @@ -355,7 +365,8 @@ GArchOperand *g_target_operand_new(MemoryDataSize size, const vmpa2t *addr) assert(size != MDS_UNDEFINED); - result->size = size; + GET_TARGET_OP_EXTRA(result)->size = size; + copy_vmpa(&result->addr, addr); return G_ARCH_OPERAND(result); @@ -457,7 +468,18 @@ static char *g_target_operand_build_tooltip(const GTargetOperand *operand, const MemoryDataSize g_target_operand_get_size(const GTargetOperand *operand) { - return operand->size; + MemoryDataSize result; /* Taille à retourner */ + tarop_extra_data_t *extra; /* Données insérées à consulter*/ + + extra = GET_TARGET_OP_EXTRA(operand); + + LOCK_GOBJECT_EXTRA(extra); + + result = extra->size; + + UNLOCK_GOBJECT_EXTRA(extra); + + return result; } @@ -485,7 +507,10 @@ bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool const mrange_t *range; /* Couverture du symbole */ #endif - operand->strict = strict; + if (strict) + g_arch_operand_set_flag(G_ARCH_OPERAND(operand), TOF_STRICT); + else + g_arch_operand_unset_flag(G_ARCH_OPERAND(operand), TOF_STRICT); result = g_binary_format_resolve_symbol(format, &operand->addr, strict, &operand->symbol, &operand->diff); @@ -569,6 +594,48 @@ GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *operand, phys_t *d } +/****************************************************************************** +* * +* Paramètres : operand = objet dont l'instance se veut unique. * +* lock = précise le besoin en verrouillage. * +* * +* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* * +* Retour : Empreinte de l'élément représenté. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_target_operand_hash(const GTargetOperand *operand, bool lock) +{ + guint result; /* Valeur à retourner */ + tarop_extra_data_t *extra; /* Données insérées à modifier */ + GArchOperandClass *class; /* Classe parente normalisée */ + + extra = GET_TARGET_OP_EXTRA(operand); + + if (lock) + LOCK_GOBJECT_EXTRA(extra); + + class = G_ARCH_OPERAND_CLASS(g_target_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); + + result ^= extra->size; + + result ^= g_direct_hash(operand->symbol); + + result ^= (operand->diff & 0xffffffff); + result ^= (operand->diff >> 32); + + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* TRANSPOSITIONS VIA CACHE DES OPERANDES */ @@ -632,6 +699,7 @@ static bool g_target_operand_unserialize(GTargetOperand *operand, GAsmStorage *s static bool g_target_operand_serialize(const GTargetOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf) { bool result; /* Bilan à retourner */ + MemoryDataSize size; /* Taille retenue */ GArchOperand *original; /* Opérande d'origine */ /** @@ -639,10 +707,12 @@ static bool g_target_operand_serialize(const GTargetOperand *operand, GAsmStorag * par la position physique. */ + size = g_target_operand_get_size(operand); + if (has_virt_addr(&operand->addr)) - original = g_imm_operand_new_from_value(operand->size, get_virt_addr(&operand->addr)); + original = g_imm_operand_new_from_value(size, get_virt_addr(&operand->addr)); else - original = g_imm_operand_new_from_value(operand->size, get_phy_addr(&operand->addr)); + original = g_imm_operand_new_from_value(size, get_phy_addr(&operand->addr)); result = g_arch_operand_store(original, storage, pbuf); |