diff options
Diffstat (limited to 'src/analysis')
-rw-r--r-- | src/analysis/db/items/switcher.c | 373 | ||||
-rw-r--r-- | src/analysis/db/items/switcher.h | 20 |
2 files changed, 259 insertions, 134 deletions
diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c index 9c6a2a3..3ae9358 100644 --- a/src/analysis/db/items/switcher.c +++ b/src/analysis/db/items/switcher.c @@ -34,6 +34,7 @@ #include "../collection-int.h" #include "../item-int.h" +#include "../../../glibext/gbinarycursor.h" @@ -46,10 +47,9 @@ struct _GDbSwitcher GDbItem parent; /* A laisser en premier */ vmpa2t addr; /* Adresse de l'instruction */ - size_t index; /* Indice de l'opérande visé */ + rle_string path; /* Chemin vers l'opérande visé */ ImmOperandDisplay display; /* Type de bascule */ - ImmOperandDisplay old; /* Type de bascule précédente */ }; @@ -74,6 +74,12 @@ static void g_db_switcher_dispose(GDbSwitcher *); /* Procède à la libération totale de la mémoire. */ static void g_db_switcher_finalize(GDbSwitcher *); +/* Calcule le condensat associé à l'élément vu comme clef. */ +static guint g_db_switcher_hash_key(const GDbSwitcher *); + +/* Compare deux éléments en tant que clefs. */ +static gboolean g_db_switcher_cmp_key(const GDbSwitcher *, const GDbSwitcher *); + /* Effectue la comparaison entre deux signets de collection. */ static gint g_db_switcher_cmp(const GDbSwitcher *, const GDbSwitcher *); @@ -87,7 +93,7 @@ static bool g_db_switcher_pack(const GDbSwitcher *, packed_buffer *); static char *g_db_switcher_build_label(GDbSwitcher *); /* Exécute une bascule d'affichage d'opérande sur un binaire. */ -static bool g_db_switcher_run(GDbSwitcher *, GLoadedBinary *, ImmOperandDisplay *, ImmOperandDisplay); +static bool g_db_switcher_run(GDbSwitcher *, GLoadedBinary *, ImmOperandDisplay); /* Applique une bascule d'affichage d'opérande sur un binaire. */ static bool g_db_switcher_apply(GDbSwitcher *, GLoadedBinary *); @@ -173,6 +179,8 @@ static void g_db_switcher_class_init(GDbSwitcherClass *klass) item->feature = DBF_DISPLAY_SWITCHERS; + item->hash_key = (hash_db_item_key_fc)g_db_switcher_hash_key; + item->cmp_key = (cmp_db_item_key_fc)g_db_switcher_cmp_key; item->cmp = (cmp_db_item_fc)g_db_switcher_cmp; item->unpack = (unpack_db_item_fc)g_db_switcher_unpack; @@ -202,6 +210,11 @@ static void g_db_switcher_class_init(GDbSwitcherClass *klass) static void g_db_switcher_init(GDbSwitcher *switcher) { + init_vmpa(&switcher->addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + + setup_empty_rle_string(&switcher->path); + + switcher->display = IOD_COUNT; } @@ -239,6 +252,8 @@ static void g_db_switcher_dispose(GDbSwitcher *switcher) static void g_db_switcher_finalize(GDbSwitcher *switcher) { + exit_rle_string(&switcher->path); + G_OBJECT_CLASS(g_db_switcher_parent_class)->finalize(G_OBJECT(switcher)); } @@ -246,12 +261,13 @@ static void g_db_switcher_finalize(GDbSwitcher *switcher) /****************************************************************************** * * -* Paramètres : addr = adresse inamovible localisant une position donnée. * -* comment = commentaire construit ou NULL. * +* Paramètres : instr = instruction contenant l'opérande à traiter. * +* imm = opérande de valeur immédiate concernée. * +* display = forme d'affichage à établir pour l'opérande. * * * -* Description : Crée une définition d'un signet dans une zone de texte. * +* Description : Crée une définition de bascule d'affichage pour un immédiat. * * * -* Retour : Signet mis en place ou NULL en cas d'erreur. * +* Retour : Bascule mise en place ou NULL en cas d'erreur. * * * * Remarques : - * * * @@ -260,53 +276,122 @@ static void g_db_switcher_finalize(GDbSwitcher *switcher) GDbSwitcher *g_db_switcher_new(GArchInstruction *instr, const GImmOperand *imm, ImmOperandDisplay display) { GDbSwitcher *result; /* Instance à retourner */ - size_t count; /* Nombre d'opérandes à visiter*/ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande manipulé */ + bool status; /* Bilan de l'initialisation */ + + result = g_object_new(G_TYPE_DB_SWITCHER, NULL); + + status = g_db_switcher_fill(result, instr, imm, display); + if (!status) goto error; + + return result; + + error: + + g_object_unref(G_OBJECT(result)); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = bascule à initialiser. * +* instr = instruction contenant l'opérande à traiter. * +* imm = opérande de valeur immédiate concerné. * +* display = forme d'affichage à établir pour l'opérande. * +* * +* Description : Initialise la définition de bascule d'affichage. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_db_switcher_fill(GDbSwitcher *switcher, GArchInstruction *instr, const GImmOperand *imm, ImmOperandDisplay display) +{ + bool result; /* Bilan à retourner */ + char *path; /* Chemin vers l'opérande visé */ const mrange_t *range; /* Localisation de l'instruct° */ + /** + * Cette fonction est principalement destinée aux initialisations + * depuis l'extension Python. + */ + + result = false; + /* Recherche de la position de l'opérande */ - g_arch_instruction_lock_operands(instr); + path = g_arch_instruction_find_operand_path(instr, G_ARCH_OPERAND(imm)); - count = _g_arch_instruction_count_operands(instr); + if (path == NULL) + goto failure; - for (i = 0; i < count; i++) - { - op = _g_arch_instruction_get_operand(instr, i); + /* Sauvegarde des propriétés */ - if (G_ARCH_OPERAND(imm) == op) - { - g_object_unref(G_OBJECT(op)); - break; - } + range = g_arch_instruction_get_range(instr); + copy_vmpa(&switcher->addr, get_mrange_addr(range)); - else - g_object_unref(G_OBJECT(op)); + dup_into_rle_string(&switcher->path, path); + free(path); - } + switcher->display = display; - g_arch_instruction_unlock_operands(instr); + result = true; - if (i == count) - return NULL; + failure: - /* Sauvegarde des propriétés */ + return result; - result = g_object_new(G_TYPE_DB_SWITCHER, NULL); +} - range = g_arch_instruction_get_range(instr); - copy_vmpa(&result->addr, get_mrange_addr(range)); - result->index = i; +/****************************************************************************** +* * +* Paramètres : switcher = élément de collection à consulter. * +* * +* Description : Calcule le condensat associé à l'élément vu comme clef. * +* * +* Retour : Condensat associé à l'élément. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_db_switcher_hash_key(const GDbSwitcher *switcher) +{ + guint result; /* Valeur "unique" à renvoyer */ + + result = hash_vmpa(&switcher->addr); + + return result; - result->display = display; +} - /* Création d'un intitulé adapté */ +/****************************************************************************** +* * +* Paramètres : a = premier élément de collection à consulter. * +* b = second élément de collection à consulter. * +* * +* Description : Compare deux éléments en tant que clefs. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ +static gboolean g_db_switcher_cmp_key(const GDbSwitcher *a, const GDbSwitcher *b) +{ + gboolean result; /* Bilan à retourner */ + int ret; /* Bilan intermédiaire */ - //g_db_switcher_set_comment(result, comment); + ret = cmp_vmpa(&a->addr, &b->addr); + + result = (ret == 0); return result; @@ -333,14 +418,7 @@ static gint g_db_switcher_cmp(const GDbSwitcher *a, const GDbSwitcher *b) result = cmp_vmpa(&a->addr, &b->addr); if (result == 0) - { - if (a->index < b->index) - result = -1; - - else if (a->index > b->index) - result = 1; - - } + result = cmp_rle_string(&a->path, &b->path); if (result == 0) { @@ -381,10 +459,7 @@ static bool g_db_switcher_unpack(GDbSwitcher *switcher, packed_buffer *pbuf) result = unpack_vmpa(&switcher->addr, pbuf); if (result) - { - result = extract_packed_buffer(pbuf, &tmp32, sizeof(uint32_t), true); - switcher->index = tmp32; - } + result = unpack_rle_string(&switcher->path, pbuf); if (result) { @@ -424,7 +499,7 @@ static bool g_db_switcher_pack(const GDbSwitcher *switcher, packed_buffer *pbuf) result = pack_vmpa(&switcher->addr, pbuf); if (result) - result = extend_packed_buffer(pbuf, (uint32_t []) { switcher->index }, sizeof(uint32_t), true); + result = pack_rle_string(&switcher->path, pbuf); if (result) result = extend_packed_buffer(pbuf, (uint32_t []) { switcher->display }, sizeof(uint32_t), true); @@ -448,7 +523,7 @@ static bool g_db_switcher_pack(const GDbSwitcher *switcher, packed_buffer *pbuf) static char *g_db_switcher_build_label(GDbSwitcher *switcher) { -#if 0 + char *result; /* Description à retourner */ VMPA_BUFFER(loc); /* Indication de position */ vmpa2_to_string(&switcher->addr, MDS_UNDEFINED, loc, NULL); @@ -456,26 +531,27 @@ static char *g_db_switcher_build_label(GDbSwitcher *switcher) switch (switcher->display) { case IOD_BIN: - asprintf(&G_DB_ITEM(switcher)->label, _("Switch to binary display at %s"), loc); + asprintf(&result, _("Switch to binary display at %s"), loc); break; case IOD_OCT: - asprintf(&G_DB_ITEM(switcher)->label, _("Switch to octal display at %s"), loc); + asprintf(&result, _("Switch to octal display at %s"), loc); break; case IOD_DEC: - asprintf(&G_DB_ITEM(switcher)->label, _("Switch to octal display at %s"), loc); + asprintf(&result, _("Switch to octal display at %s"), loc); break; case IOD_HEX: - asprintf(&G_DB_ITEM(switcher)->label, _("Switch to octal display at %s"), loc); + asprintf(&result, _("Switch to octal display at %s"), loc); break; case IOD_COUNT: - asprintf(&G_DB_ITEM(switcher)->label, _("Reset to default display at %s"), loc); + asprintf(&result, _("Reset to default display at %s"), loc); break; default: assert(false); + result = NULL; break; } -#endif - return NULL; + + return result; } @@ -484,7 +560,6 @@ static char *g_db_switcher_build_label(GDbSwitcher *switcher) * * * Paramètres : switcher = bascule d'affichage à manipuler. * * binary = binaire chargé en mémoire à modifier. * -* old = état précédent à conserver. [OUT] * * new = nouvel état à appliquer. * * * * Description : Exécute une bascule d'affichage d'opérande sur un binaire. * @@ -495,73 +570,69 @@ static char *g_db_switcher_build_label(GDbSwitcher *switcher) * * ******************************************************************************/ -static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmOperandDisplay *old, ImmOperandDisplay new) +static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmOperandDisplay new) { - return false; - -#if 0 bool result; /* Bilan à faire remonter */ GArchProcessor *proc; /* Propriétaire d'instructions */ GArchInstruction *instr; /* Instruction à traiter */ GArchOperand *op; /* Opérande à modifier */ - GCodeBuffer *buffer; /* Tampon de lignes à traiter */ - GBufferLine *line; /* Ligne de tampon à marquer */ GImmOperand *operand; /* Opérande de valeur immédiate*/ - char value[IMM_MAX_SIZE]; /* Chaîne à imprimer */ - size_t len; /* Taille de l'élément inséré */ + GBufferCache *cache; /* Tampon de lignes à traiter */ + GLineCursor *cursor; /* Emplacement dans un tampon */ + size_t index; /* Indice de ligne à traiter */ - result = true; + result = false; /* Traitement au niveau des instructions */ proc = g_loaded_binary_get_processor(binary); instr = g_arch_processor_find_instr_by_address(proc, &switcher->addr); - if (instr == NULL) - { - result = false; - goto exit_instr; - } + if (instr == NULL) goto exit_instr; - op = g_arch_instruction_get_operand(instr, switcher->index); - if (op == NULL) - { - result = false; - goto exit_without_operand; - } + op = g_arch_instruction_get_operand_from_path(instr, get_rle_string(&switcher->path)); + if (op == NULL) goto exit_without_operand; result = G_IS_IMM_OPERAND(op); if (!result) goto exit_operand; + operand = G_IMM_OPERAND(op); + + if (new == IOD_COUNT) + new = g_imm_operand_get_default_display(operand); + + g_imm_operand_set_display(operand, new); + /* Traitement au niveau du rendu graphique */ - buffer = g_loaded_binary_get_disassembled_buffer(binary); + cache = g_loaded_binary_get_disassembly_cache(binary); + if (cache == NULL) goto exit_operand; - line = g_code_buffer_find_line_by_addr(buffer, &switcher->addr, BLF_HAS_CODE, NULL); - if (line == NULL) - { - result = false; - goto exit_gui; - } + cursor = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(cursor), &switcher->addr); - operand = G_IMM_OPERAND(op); + g_buffer_cache_lock(cache); - *old = g_imm_operand_get_display(operand); + index = g_buffer_cache_find_index_by_cursor(cache, cursor, true); - if (new == IOD_COUNT) - new = g_imm_operand_get_default_display(operand); + g_object_unref(G_OBJECT(cursor)); + + index = g_buffer_cache_look_for_flag(cache, index, BLF_HAS_CODE); - g_imm_operand_set_display(&operand, new, G_SHARE_CONTAINER(instr)); + if (index == g_buffer_cache_count_lines(cache)) + goto exit_gui; - len = g_imm_operand_to_string(operand, value); + g_buffer_cache_refresh_line(cache, index); - result = g_buffer_line_replace_text(line, G_OBJECT(op), value, len); + result = true; - g_object_unref(G_OBJECT(line)); + /* Phase de sortie propre */ exit_gui: - /* TODO g_object_unref(G_OBJECT(buffer));*/ + g_buffer_cache_unlock(cache); + + g_object_unref(G_OBJECT(cache)); exit_operand: @@ -576,7 +647,7 @@ static bool g_db_switcher_run(GDbSwitcher *switcher, GLoadedBinary *binary, ImmO g_object_unref(G_OBJECT(proc)); return result; -#endif + } @@ -597,7 +668,7 @@ static bool g_db_switcher_apply(GDbSwitcher *switcher, GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ - result = g_db_switcher_run(switcher, binary, &switcher->old, switcher->display); + result = g_db_switcher_run(switcher, binary, switcher->display); return result; @@ -621,7 +692,7 @@ static bool g_db_switcher_cancel(GDbSwitcher *switcher, GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ - result = g_db_switcher_run(switcher, binary, (ImmOperandDisplay []) { 0 }, switcher->old); + result = g_db_switcher_run(switcher, binary, IOD_COUNT); return result; @@ -649,17 +720,9 @@ static bool g_db_switcher_load(GDbSwitcher *switcher, const bound_value *values, result = G_DB_ITEM_CLASS(g_db_switcher_parent_class)->load(G_DB_ITEM(switcher), values, count); - result &= load_vmpa(&switcher->addr, NULL, values, count); + if (result) result = load_vmpa(&switcher->addr, NULL, values, count); - if (result) - { - value = find_bound_value(values, count, "op_index"); - result = (value != NULL && value->type == SQLITE_INTEGER); - - if (result) - switcher->index = value->integer; - - } + if (result) result = load_rle_string(&switcher->path, "path", values, count); if (result) { @@ -709,22 +772,13 @@ static bool g_db_switcher_store(const GDbSwitcher *switcher, bound_value **value if (!status) return false; - *count += 2; - *values = realloc(*values, *count * sizeof(bound_value)); - - value = &(*values)[*count - 2]; - - value->cname = "op_index"; - value->built_name = false; - value->type = SQLITE_INTEGER; - - value->has_value = (switcher != NULL); + if (switcher == NULL) + status &= store_rle_string(NULL, "path", values, count); + else + status &= store_rle_string(&switcher->path, "path", values, count); - if (value->has_value) - { - value->integer = switcher->index; - value->delete = NULL; - } + *count += 1; + *values = realloc(*values, *count * sizeof(bound_value)); value = &(*values)[*count - 1]; @@ -745,6 +799,75 @@ static bool g_db_switcher_store(const GDbSwitcher *switcher, bound_value **value } +/****************************************************************************** +* * +* Paramètres : switcher = informations à consulter. * +* * +* Description : Fournit l'adresse associée à une bascule. * +* * +* Retour : Adresse mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const vmpa2t *g_db_switcher_get_address(const GDbSwitcher *switcher) +{ + const vmpa2t *result; /* Localisation à retourner */ + + result = &switcher->addr; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = informations à consulter. * +* * +* Description : Fournit le chemin menant vers l'opérande basculé. * +* * +* Retour : Chemin de type "n[:n:n:n]". * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_db_switcher_get_path(const GDbSwitcher *switcher) +{ + const char *result; /* Chemin à renvoyer */ + + result = get_rle_string(&switcher->path); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : switcher = informations à consulter. * +* * +* Description : Indique l'affichage vers lequel un opérande a basculé. * +* * +* Retour : Type d'affichage forcé pour un opérande. * +* * +* Remarques : - * +* * +******************************************************************************/ + +ImmOperandDisplay g_db_switcher_get_display(const GDbSwitcher *switcher) +{ + ImmOperandDisplay result; /* Type d'affichage à retourner*/ + + result = switcher->display; + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* DEFINITION DE LA COLLECTION ASSOCIEE */ @@ -887,11 +1010,11 @@ static bool g_switcher_collection_create_db_table(const GSwitcherCollection *col char *msg; /* Message d'erreur */ int ret; /* Bilan de la création */ - sql = "CREATE TABLE Switchers (" \ - SQLITE_DB_ITEM_CREATE ", " \ - "%s, " \ - "op_index INTEGER, " \ - "type INTEGER" \ + sql = "CREATE TABLE Switchers (" \ + SQLITE_DB_ITEM_CREATE ", " \ + "%s, " \ + SQLITE_RLESTR_CREATE("path") "," \ + "type INTEGER" \ ");"; addr_fields = create_vmpa_db_table(NULL); diff --git a/src/analysis/db/items/switcher.h b/src/analysis/db/items/switcher.h index ecc6fd4..daf6154 100644 --- a/src/analysis/db/items/switcher.h +++ b/src/analysis/db/items/switcher.h @@ -54,19 +54,21 @@ typedef struct _GDbSwitcherClass GDbSwitcherClass; /* Indique le type défini pour un signet à l'intérieur d'une zone de texte. */ GType g_db_switcher_get_type(void); -/* Crée une définition d'un signet dans une zone de texte. */ +/* Crée une définition de bascule d'affichage pour un immédiat. */ GDbSwitcher *g_db_switcher_new(GArchInstruction *, const GImmOperand *, ImmOperandDisplay); -#if 0 -/* Fournit l'adresse associée à un signet. */ -const vmpa2t *g_db_switcher_get_address(GDbSwitcher *); +/* Initialise la définition de bascule d'affichage. */ +bool g_db_switcher_fill(GDbSwitcher *, GArchInstruction *, const GImmOperand *, ImmOperandDisplay); -/* Fournit le commentaire associé à un signet. */ -const char *g_db_switcher_get_comment(const GDbSwitcher *); +/* Fournit l'adresse associée à une bascule. */ +const vmpa2t *g_db_switcher_get_address(const GDbSwitcher *); + +/* Fournit le chemin menant vers l'opérande basculé. */ +const char *g_db_switcher_get_path(const GDbSwitcher *); + +/* Indique l'affichage vers lequel un opérande a basculé. */ +ImmOperandDisplay g_db_switcher_get_display(const GDbSwitcher *); -/* Définit le commentaire associé à un signet. */ -void g_db_switcher_set_comment(GDbSwitcher *, const char *); -#endif /* ---------------------- DEFINITION DE LA COLLECTION ASSOCIEE ---------------------- */ |