From adb98feb93f09d8de343c504a0c8c72815d62dab Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 23 Jan 2016 18:48:50 +0100 Subject: Created storable items for user comments. --- plugins/pychrysa/analysis/db/items/comment.c | 3 +- src/analysis/db/collection.c | 39 ++- src/analysis/db/items/bookmark.c | 2 +- src/analysis/db/items/comment.c | 460 ++++++++++++++++++++++++++- src/analysis/db/items/comment.h | 6 +- src/analysis/db/items/switcher.c | 2 +- src/analysis/disass/output.c | 2 + src/common/sqlite.h | 5 +- src/format/symbol.h | 20 +- src/glibext/gbufferline.c | 59 ++++ src/glibext/gbufferline.h | 3 + src/glibext/gcodebuffer.c | 74 ++++- src/glibext/gcodebuffer.h | 7 +- 13 files changed, 634 insertions(+), 48 deletions(-) diff --git a/plugins/pychrysa/analysis/db/items/comment.c b/plugins/pychrysa/analysis/db/items/comment.c index 951f6ce..ead5179 100644 --- a/plugins/pychrysa/analysis/db/items/comment.c +++ b/plugins/pychrysa/analysis/db/items/comment.c @@ -81,7 +81,8 @@ static PyObject *py_db_comment_new(PyTypeObject *type, PyObject *args, PyObject addr = get_internal_vmpa(py_vmpa); if (py_vmpa == NULL) Py_RETURN_NONE; - comment = g_db_comment_new(addr, text, is_volatile); + return NULL;/* FIXME */ + //comment = g_db_comment_new(addr, text, is_volatile); result = pygobject_new(G_OBJECT(comment)); g_object_unref(comment); diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index d5518dd..aa7591e 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -992,15 +992,21 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db) /** * On réalise une petite conversion selon le champ. * - * Le filtre SQLITE_NATIVE est destiné à conserver un champ sur 32 bits - * quand il s'agit du format utilisé, même si toutes les valeurs sont - * enregistrées en 64 bits. + * Le filtre SQLITE_NATIVE est destiné à conserver le type choisi par + * SQLite. Typiquement, une chaîne peut être à SQLITE_NULL ou SQLITE_TEXT + * selon la valeur conservée dans la base. * - * C'est par exemple le cas dans les bascules d'affichage. - * - * D'autres éléments, comme les localisations en mémoire, peuvent + * D'autres éléments, comme les localisations en mémoire, peuvent aussi * avoir un champ éventuellement nul, donc la définition à partir des * indications de la base de données reste importante. + * + * En ce qui concerne les valeurs numériques, SQLite ne fait pas de + * distinction : tout passe par la fonction sqlite3VdbeIntValue(), + * qui effectue des transtypages au besoin pour tout ce qui n'est + * pas numérique. + * + * Pour les types internes SQLITE_INTEGER et SQLITE_BOOLEAN, + * il est donc nécessaire d'ajuster en interne. */ if (native_type == SQLITE_INTEGER) @@ -1010,13 +1016,18 @@ bool g_db_collection_load_all_items(GDbCollection *collec, sqlite3 *db) values[i].type = native_type; else - assert(values[i].type == native_type || values[i].type == SQLITE_INTEGER); - + assert(values[i].type == native_type + || values[i].type == SQLITE_INTEGER + || values[i].type == SQLITE_BOOLEAN); switch (values[i].type) { + case SQLITE_BOOLEAN: + values[i].boolean = (bool)sqlite3_column_int(stmt, i); + break; + case SQLITE_INTEGER: - values[i].integer = (int)sqlite3_column_int64(stmt, i); + values[i].integer = sqlite3_column_int(stmt, i); break; case SQLITE_INT64: @@ -1142,6 +1153,11 @@ static bool g_db_collection_store_item(const GDbCollection *collec, const GDbIte { switch (values[i].type) { + case SQLITE_BOOLEAN: + ret = sqlite3_bind_int(stmt, index, values[i].boolean); + index++; + break; + case SQLITE_INTEGER: ret = sqlite3_bind_int(stmt, index, values[i].integer); index++; @@ -1301,6 +1317,11 @@ static bool g_db_collection_store_updated_item(const GDbCollection *collec, cons switch (values[i].type) { + case SQLITE_BOOLEAN: + ret = sqlite3_bind_int(stmt, index, values[i].boolean); + index++; + break; + case SQLITE_INTEGER: ret = sqlite3_bind_int(stmt, index, values[i].integer); index++; diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index 6914bc3..4c93faf 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -393,7 +393,7 @@ static void g_db_bookmark_build_label(GDbBookmark *bookmark) * * * Paramètres : bookmark = signet à manipuler. * * binary = binaire chargé en mémoire à modifier. * -* prev = état précédent de la présence du drapeau. * +* prev = état précédent de la présence du drapeau. [OUT] * * set = précision quant au nouvel état du drapeau. * * * * Description : Exécute un signet sur un tampon de binaire chargé. * diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c index 9212cae..b4a1dc0 100644 --- a/src/analysis/db/items/comment.c +++ b/src/analysis/db/items/comment.c @@ -24,12 +24,18 @@ #include "comment.h" +#include +#include #include #include +#include + + #include "../collection-int.h" #include "../item-int.h" +#include "../../../common/io.h" @@ -42,8 +48,21 @@ struct _GDbComment GDbItem parent; /* A laisser en premier */ vmpa2t addr; /* Adresse du commentaire */ + BufferLineFlags flags; /* Identification de l'accroche*/ + rle_string text; /* Contenu du commentaire */ + bool inlined; /* Intégration dans une ligne ?*/ + + union + { + bool repeatable; /* Répétition aux lignes liées */ + bool before; /* Zone dédiée au dessus ? */ + }; + + GDbComment **oldies; /* Commentaires d'origine ? */ + size_t old_count; /* Nombre de places à restaurer*/ + }; /* Commentaire à placer dans du texte quelconque (classe) */ @@ -75,6 +94,18 @@ static bool g_db_comment_recv_from_fd(GDbComment *, int, int); /* Exporte la définition d'un commentaire dans un flux réseau. */ static bool g_db_comment_send_to_fd(const GDbComment *, int, int); +/* Construit la description humaine d'un commentaire. */ +static void g_db_comment_build_label(GDbComment *); + +/* Exécute l'impression de commentaire dans du code de binaire. */ +static bool g_db_comment_run(GDbComment *, GLoadedBinary *, bool); + +/* Réalise l'impression de commentaire dans du code de binaire. */ +static bool g_db_comment_apply(GDbComment *, GLoadedBinary *); + +/* Annule l'impression d'un commentaire dans du code de binaire. */ +static bool g_db_comment_cancel(GDbComment *, GLoadedBinary *); + /* Constitue les champs destinés à une insertion / modification. */ static bool g_db_comment_prepare_db_statement(const GDbComment *, bound_value **, size_t *); @@ -162,6 +193,10 @@ static void g_db_comment_class_init(GDbCommentClass *klass) item->recv = (recv_db_item_fc)g_db_comment_recv_from_fd; item->send = (send_db_item_fc)g_db_comment_send_to_fd; + item->build_label = (build_item_label_fc)g_db_comment_build_label; + item->apply = (run_item_fc)g_db_comment_apply; + item->cancel = (run_item_fc)g_db_comment_cancel; + item->prepare_stmt = (prepare_db_statement)g_db_comment_prepare_db_statement; item->load = (load_db_item_fc)g_db_comment_load; @@ -200,6 +235,14 @@ static void g_db_comment_init(GDbComment *comment) static void g_db_comment_dispose(GDbComment *comment) { + size_t i; /* Boucle de parcours */ + + for (i = 0; i < comment->old_count; i++) + g_object_unref(G_OBJECT(comment->oldies[i])); + + if (comment->oldies != NULL) + free(comment->oldies); + G_OBJECT_CLASS(g_db_comment_parent_class)->dispose(G_OBJECT(comment)); } @@ -228,9 +271,10 @@ static void g_db_comment_finalize(GDbComment *comment) /****************************************************************************** * * -* Paramètres : addr = adresse inamovible localisant une position. * -* text = commentaire construit ou NULL. * -* is_volatile = état du besoin en sauvegarde. * +* Paramètres : addr = adresse inamovible localisant une position. * +* flags = indentifiants supplémentaires de ligne visée. * +* text = commentaire construit ou NULL. * +* repeatable = repétition aux instructions liées ? * * * * Description : Crée une définition de commentaire dans une zone de texte. * * * @@ -240,7 +284,7 @@ static void g_db_comment_finalize(GDbComment *comment) * * ******************************************************************************/ -GDbComment *g_db_comment_new(const vmpa2t *addr, const char *text, bool is_volatile) +GDbComment *g_db_comment_new_inlined(const vmpa2t *addr, BufferLineFlags flags, const char *text, bool repeatable) { GDbComment *result; /* Instance à retourner */ @@ -248,9 +292,49 @@ GDbComment *g_db_comment_new(const vmpa2t *addr, const char *text, bool is_volat copy_vmpa(&result->addr, addr); + result->flags = flags; + g_db_comment_set_text(result, text); - g_db_item_set_volatile(G_DB_ITEM(result), is_volatile); + result->inlined = true; + + result->repeatable = repeatable; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : addr = adresse inamovible localisant une position. * +* flags = indentifiants supplémentaires de ligne visée. * +* text = commentaire construit ou NULL. * +* before = précision quant à la position de la zone à définir. * +* * +* Description : Crée une définition de commentaire dans une zone de texte. * +* * +* Retour : Commentaire mis en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDbComment *g_db_comment_new_area(const vmpa2t *addr, BufferLineFlags flags, const char *text, bool before) +{ + GDbComment *result; /* Instance à retourner */ + + result = g_object_new(G_TYPE_DB_COMMENT, NULL); + + copy_vmpa(&result->addr, addr); + + result->flags = flags; + + g_db_comment_set_text(result, text); + + result->inlined = false; + + result->before = before; return result; @@ -305,6 +389,8 @@ static gint g_db_comment_cmp(GDbComment *a, GDbComment *b, bool with) static bool g_db_comment_recv_from_fd(GDbComment *comment, int fd, int flags) { bool status; /* Bilan d'opération initiale */ + uint32_t val32; /* Valeur sur 32 bits */ + uint8_t val8; /* Valeur sur 8 bits */ status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->recv(G_DB_ITEM(comment), fd, flags); if (!status) return false; @@ -312,9 +398,24 @@ static bool g_db_comment_recv_from_fd(GDbComment *comment, int fd, int flags) if (!recv_vmpa(&comment->addr, fd, flags)) return false; + status = safe_recv(fd, &val32, sizeof(uint32_t), MSG_WAITALL | flags); + if (!status) return false; + + comment->flags = be32toh(val32); + if (!recv_rle_string(&comment->text, fd, flags)) return false; + status = safe_recv(fd, &val8, sizeof(uint8_t), MSG_WAITALL | flags); + if (!status) return false; + + comment->inlined = val8; + + status = safe_recv(fd, &val8, sizeof(uint8_t), MSG_WAITALL | flags); + if (!status) return false; + + comment->repeatable = val8; + return true; } @@ -344,9 +445,18 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags if (!send_vmpa(&comment->addr, fd, MSG_MORE | flags)) return false; - if (!send_rle_string(&comment->text, fd, flags)) + status = safe_send(fd, (uint32_t []) { htobe32(comment->flags) }, sizeof(uint32_t), MSG_MORE | flags); + if (!status) return false; + + if (!send_rle_string(&comment->text, fd, MSG_MORE | flags)) return false; + status = safe_send(fd, (uint8_t []) { (uint8_t)comment->inlined }, sizeof(uint8_t), MSG_MORE | flags); + if (!status) return false; + + status = safe_send(fd, (uint8_t []) { (uint8_t)comment->repeatable }, sizeof(uint8_t), flags); + if (!status) return false; + return true; } @@ -354,6 +464,250 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags /****************************************************************************** * * +* Paramètres : comment = définition de commentaire à manipuler. * +* * +* Description : Construit la description humaine d'un commentaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_db_comment_build_label(GDbComment *comment) +{ + VMPA_BUFFER(loc); /* Indication de position */ + + if (has_virt_addr(&comment->addr)) + vmpa2_virt_to_string(&comment->addr, MDS_UNDEFINED, loc, NULL); + else + vmpa2_phys_to_string(&comment->addr, MDS_UNDEFINED, loc, NULL); + + if (is_rle_string_empty(&comment->text)) + asprintf(&G_DB_ITEM(comment)->label, _("Delete comment at %s"), loc); + + else + { + if (comment->inlined) + asprintf(&G_DB_ITEM(comment)->label, _("Enter inlined comment at %s"), loc); + else + asprintf(&G_DB_ITEM(comment)->label, _("Enter comment area at %s"), loc); + } + +} + + +/****************************************************************************** +* * +* Paramètres : comment = définition de commentaire à manipuler. * +* binary = binaire chargé en mémoire à modifier. * +* apply = indique s'il faut appliquer la définition ou non. * +* * +* Description : Exécute l'impression de commentaire dans du code de binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_comment_run(GDbComment *comment, GLoadedBinary *binary, bool apply) +{ + bool result; /* Bilan à faire remonter */ + GCodeBuffer *buffer; /* Tampon de lignes à traiter */ + GBufferLine *line; /* Ligne de tampon à marquer */ + GArchProcessor *proc; /* Propriétaire d'instructions */ + GArchInstruction *instr; /* Instruction à traiter */ + GArchInstruction **sources; /* Instructions diverses liées */ + size_t scount; /* Nbre de sources affichées */ + size_t i; /* Boucle de parcours */ + const mrange_t *range; /* Emplacement d'instruction */ + GBufferLine *linked; /* Ligne liée à traiter */ + GDbComment *old; /* Ancien élément à restaurer */ + + result = true; + + /* Recherche de la ligne visée */ + + buffer = g_loaded_binary_get_disassembled_buffer(binary); + + line = g_code_buffer_find_line_by_addr(buffer, &comment->addr, comment->flags, NULL); + if (line == NULL) + { + result = false; + goto exit_gui; + } + + /* Détermination de l'imprimeur précédent */ + + if (apply) + { + assert(comment->old_count == 0); + + comment->old_count = 1; + comment->oldies = (GDbComment **)calloc(comment->old_count, sizeof(GDbComment *)); + + } + + /* Applications globales finales */ + +#define g_code_buffer_update_inlined_comment_dummy(b, l, c, d, o) \ + g_code_buffer_update_inlined_comment(b, l, c, o) + + /** + * Note : on part du principe qu'un commentaire intégré ne peut remplacer qu'un + * commentaire intégré. Et pareil pour les commentaires en blocs. + */ + +#define RUN_COMMENT_ON(ln, idx, func) \ + if (apply) \ + { \ + comment->oldies[idx] = (GDbComment *)g_code_buffer_get_comment_creator(buffer, ln); \ + assert(comment->oldies[idx] == NULL || G_IS_DB_COMMENT(comment->oldies[idx])); \ + assert(comment->oldies[idx] == NULL || comment->oldies[idx]->inlined == comment->inlined); \ + \ + if (is_rle_string_empty(&comment->text)) \ + result = g_code_buffer_delete_lines_comment(buffer, ln); \ + else \ + result = func(buffer, ln, get_rle_string(&comment->text), \ + comment->before, G_OBJECT(comment)); \ + } \ + else \ + { \ + old = comment->oldies[idx]; \ + \ + if (old == NULL) \ + { \ + if (!is_rle_string_empty(&comment->text)) \ + result = g_code_buffer_delete_lines_comment(buffer, ln); \ + else \ + result = true; \ + } \ + else \ + { \ + if (is_rle_string_empty(&old->text)) \ + result = g_code_buffer_delete_lines_comment(buffer, ln); \ + else \ + result = func(buffer, ln, get_rle_string(&old->text), \ + old->before, G_OBJECT(old)); \ + } \ + \ + } + + if (comment->inlined) + { + /* Traitement d'un commentaire inscrusté */ + + RUN_COMMENT_ON(line, 0, g_code_buffer_update_inlined_comment_dummy); + + /* Traitement des répétitions ? */ + + if (comment->repeatable/* && result*/) + { + proc = g_loaded_binary_get_processor(binary); + + range = g_buffer_line_get_range(line); + + instr = g_arch_processor_find_instr_by_address(proc, get_mrange_addr(range)); + assert(instr != NULL); + + scount = g_arch_instruction_get_sources(instr, &sources, NULL); + + if (apply) + { + comment->old_count += scount; + comment->oldies = (GDbComment **)realloc(comment->oldies, + comment->old_count * sizeof(GDbComment *)); + } + + for (i = 0; i < scount && result; i++) + { + range = g_arch_instruction_get_range(sources[i]); + + /** + * On recherche ici une ligne potentiellement BLF_HAS_CODE ou BLF_IS_LABEL. + * Comme on ne peut pas traiter les deux cas, on prend la première qui vient + * avec BLF_NONE. + */ + linked = g_code_buffer_find_line_by_addr(buffer, get_mrange_addr(range), BLF_NONE, NULL); + assert(linked != NULL); + + RUN_COMMENT_ON(linked, 1 + i, g_code_buffer_update_inlined_comment_dummy); + + } + + g_object_unref(G_OBJECT(proc)); + + } + + } + + else + { + RUN_COMMENT_ON(line, 0, g_code_buffer_update_comment_area); + } + + g_object_unref(G_OBJECT(line)); + + exit_gui: + + /* TODO g_object_unref(G_OBJECT(buffer));*/ + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = définition de commentaire à manipuler. * +* binary = binaire chargé en mémoire à modifier. * +* * +* Description : Réalise l'impression de commentaire dans du code de binaire. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_comment_apply(GDbComment *comment, GLoadedBinary *binary) +{ + bool result; /* Bilan à faire remonter */ + + result = g_db_comment_run(comment, binary, true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : comment = définition de commentaire à manipuler. * +* binary = binaire chargé en mémoire à modifier. * +* * +* Description : Annule l'impression d'un commentaire dans du code de binaire.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_db_comment_cancel(GDbComment *comment, GLoadedBinary *binary) +{ + bool result; /* Bilan à faire remonter */ + + result = g_db_comment_run(comment, binary, false); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : comment = base d'éléments sur laquelle s'appuyer. * * values = couples de champs et de valeurs à lier. [OUT] * * count = nombre de ces couples. [OUT] * @@ -369,6 +723,7 @@ static bool g_db_comment_send_to_fd(const GDbComment *comment, int fd, int flags static bool g_db_comment_prepare_db_statement(const GDbComment *comment, bound_value **values, size_t *count) { bool status; /* Bilan d'opération initiale */ + bound_value *value; /* Valeur à éditer / définir */ status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->prepare_stmt(G_DB_ITEM(comment), values, count); if (!status) return false; @@ -376,9 +731,36 @@ static bool g_db_comment_prepare_db_statement(const GDbComment *comment, bound_v status = prepare_vmpa_db_statement(&comment->addr, values, count); if (!status) return false; + *count += 1; + *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + + value = &(*values)[*count - 1]; + + value->name = "flags"; + value->type = SQLITE_INTEGER; + value->integer = comment->flags; + value->delete = NULL; + status &= prepare_db_statement_for_rle_string(&comment->text, "text", values, count); if (!status) return false; + *count += 2; + *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + + value = &(*values)[*count - 2]; + + value->name = "inlined"; + value->type = SQLITE_BOOLEAN; + value->boolean = comment->inlined; + value->delete = NULL; + + value = &(*values)[*count - 1]; + + value->name = "repeatable"; + value->type = SQLITE_BOOLEAN; + value->boolean = comment->repeatable; + value->delete = NULL; + return true; } @@ -401,13 +783,44 @@ static bool g_db_comment_prepare_db_statement(const GDbComment *comment, bound_v static bool g_db_comment_load(GDbComment *comment, const bound_value *values, size_t count) { bool result; /* Bilan à faire remonter */ + const bound_value *value; /* Valeur à éditer / définir */ result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->load(G_DB_ITEM(comment), values, count); result &= load_vmpa(&comment->addr, values, count); + if (result) + { + value = find_bound_value(values, count, "flags"); + result = (value != NULL && value->type == SQLITE_INTEGER); + + if (result) + comment->flags = value->integer; + + } + result &= load_rle_string(&comment->text, "text", values, count); + if (result) + { + value = find_bound_value(values, count, "inlined"); + result = (value != NULL && value->type == SQLITE_BOOLEAN); + + if (result) + comment->inlined = value->boolean; + + } + + if (result) + { + value = find_bound_value(values, count, "repeatable"); + result = (value != NULL && value->type == SQLITE_BOOLEAN); + + if (result) + comment->repeatable = value->boolean; + + } + return result; } @@ -526,7 +939,7 @@ static void g_comment_collection_class_init(GCommentCollectionClass *klass) static void g_comment_collection_init(GCommentCollection *collec) { - G_DB_COLLECTION(collec)->featuring = 0; + G_DB_COLLECTION(collec)->featuring = DBF_COMMENTS; G_DB_COLLECTION(collec)->type = G_TYPE_DB_COMMENT; G_DB_COLLECTION(collec)->name = "Comments"; @@ -613,10 +1026,13 @@ static bool g_comment_collection_create_db_table(const GCommentCollection *colle int ret; /* Bilan de la création */ char *msg; /* Message d'erreur */ - sql = "CREATE TABLE Comments (" \ - SQLITE_DB_ITEM_CREATE ", " \ - SQLITE_VMPA_CREATE ", " \ - SQLITE_RLESTR_CREATE("text") \ + sql = "CREATE TABLE Comments (" \ + SQLITE_DB_ITEM_CREATE ", " \ + SQLITE_VMPA_CREATE ", " \ + "flags INTEGER, " \ + SQLITE_RLESTR_CREATE("text") ", " \ + "inlined INTEGER, " \ + "repeatable INTEGER" \ ");"; ret = sqlite3_exec(db, sql, NULL, NULL, &msg); @@ -648,6 +1064,7 @@ static bool g_comment_collection_create_db_table(const GCommentCollection *colle static bool g_comment_collection_setup_load(GCommentCollection *collec, bound_value **values, size_t *count) { bool status; /* Bilan d'une préparation */ + bound_value *value; /* Valeur à éditer / définir */ status = G_DB_COLLECTION_CLASS(g_comment_collection_parent_class)->setup_load(G_DB_COLLECTION(collec), \ values, count); @@ -656,9 +1073,30 @@ static bool g_comment_collection_setup_load(GCommentCollection *collec, bound_va if (!setup_load_for_vmpa(NULL, values, count)) return false; + *count += 1; + *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + + value = &(*values)[*count - 1]; + + value->name = "flags"; + value->type = SQLITE_INTEGER; + if (!setup_load_of_rle_string(NULL, "text", values, count)) return false; + *count += 2; + *values = (bound_value *)realloc(*values, *count * sizeof(bound_value)); + + value = &(*values)[*count - 2]; + + value->name = "inlined"; + value->type = SQLITE_BOOLEAN; + + value = &(*values)[*count - 1]; + + value->name = "repeatable"; + value->type = SQLITE_BOOLEAN; + return true; } diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h index 316f4c5..dc9addc 100644 --- a/src/analysis/db/items/comment.h +++ b/src/analysis/db/items/comment.h @@ -32,6 +32,7 @@ #include "../../../arch/vmpa.h" +#include "../../../glibext/gbufferline.h" @@ -57,7 +58,10 @@ typedef struct _GDbCommentClass GDbCommentClass; GType g_db_comment_get_type(void); /* Crée une définition de commentaire dans une zone de texte. */ -GDbComment *g_db_comment_new(const vmpa2t *, const char *, bool); +GDbComment *g_db_comment_new_inlined(const vmpa2t *, BufferLineFlags, const char *, bool); + +/* Crée une définition de commentaire dans une zone de texte. */ +GDbComment *g_db_comment_new_area(const vmpa2t *, BufferLineFlags, const char *, bool); /* Fournit l'adresse associée à un commentaire. */ const vmpa2t *g_db_comment_get_address(GDbComment *); diff --git a/src/analysis/db/items/switcher.c b/src/analysis/db/items/switcher.c index 7b72cf2..6497e41 100644 --- a/src/analysis/db/items/switcher.c +++ b/src/analysis/db/items/switcher.c @@ -481,7 +481,7 @@ static void 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. * +* old = état précédent à conserver. [OUT] * * new = nouvel état à appliquer. * * * * Description : Exécute une bascule d'affichage d'opérande sur un binaire. * diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index 75444a5..07165c0 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -269,6 +269,8 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form if (comment != NULL) { + /* FIXME : appliquer ! */ + text = g_db_comment_get_text(comment); diff --git a/src/common/sqlite.h b/src/common/sqlite.h index 2036589..064972b 100644 --- a/src/common/sqlite.h +++ b/src/common/sqlite.h @@ -25,6 +25,7 @@ #define _COMMON_SQLITE_H +#include #include #include @@ -33,7 +34,8 @@ /* Type pour les insertions brutes */ #define SQLITE_RAW 0 /* En dur dans une requête */ #define SQLITE_INT64 10 /* Entier sur 64 bits */ -#define SQLITE_NATIVE 11 /* Déterminé par la base */ +#define SQLITE_BOOLEAN 11 /* Booléen sur 1 bit */ +#define SQLITE_NATIVE 12 /* Déterminé par la base */ /* Description des champs et de leur valeur associée */ @@ -44,6 +46,7 @@ typedef struct _bound_value union { + bool boolean; /* Etat sur 1 bit */ int32_t integer; /* Nombre sur 32 bits */ int64_t integer64; /* Nombre sur 64 bits */ char *string; /* Chaîne de caractères #1 */ diff --git a/src/format/symbol.h b/src/format/symbol.h index 94003bb..6f2078c 100644 --- a/src/format/symbol.h +++ b/src/format/symbol.h @@ -29,6 +29,7 @@ #include "../analysis/routine.h" +#include "../analysis/db/item.h" #include "../analysis/db/items/comment.h" #include "../arch/instruction.h" @@ -129,15 +130,16 @@ GDbComment *g_binary_symbol_get_comment(const GBinSymbol *); } \ while (0) -#define ADD_RAW_AS_SYM(_fmt, _sym, _pos, _ins, _cmt, _txt) \ - do \ - { \ - _cmt = g_db_comment_new(_pos, _txt, true); \ - _sym = g_binary_symbol_new(STP_DATA); \ - g_binary_symbol_attach_instruction(_sym, _ins); \ - g_binary_symbol_set_comment(_sym, _cmt); \ - g_binary_format_add_symbol(G_BIN_FORMAT(_fmt), _sym); \ - } \ +#define ADD_RAW_AS_SYM(_fmt, _sym, _pos, _ins, _cmt, _txt) \ + do \ + { \ + _cmt = g_db_comment_new_inlined(_pos, BLF_HAS_CODE, _txt, false); \ + g_db_item_set_volatile(G_DB_ITEM(_cmt), true); \ + _sym = g_binary_symbol_new(STP_DATA); \ + g_binary_symbol_attach_instruction(_sym, _ins); \ + g_binary_symbol_set_comment(_sym, _cmt); \ + g_binary_format_add_symbol(G_BIN_FORMAT(_fmt), _sym); \ + } \ while (0) #define ADD_STR_AS_SYM(_fmt, _sym, _ins) \ diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index 2f29ee4..b8838ae 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -78,6 +78,9 @@ static GBufferSegment *get_segment_at(const buffer_line_column *, gint *, GdkScr static GBufferSegment *find_near_segment(const buffer_line_column *, GBufferSegment *, GdkScrollDirection); /* Fournit le segment créé par un objet particulier. */ +static GObject *find_first_segment_creator(const buffer_line_column *); + +/* Fournit le segment créé par un objet particulier. */ static GBufferSegment *find_segment_from_creator(const buffer_line_column *, GObject *); /* Imprime le contenu d'une colonne de ligne de texte. */ @@ -410,6 +413,33 @@ static GBufferSegment *find_near_segment(const buffer_line_column *column, GBuff /****************************************************************************** * * +* Paramètres : column = colonne de ligne de texte à consulter. * +* * +* Description : Fournit le segment créé par un objet particulier. * +* * +* Retour : Créateur trouvé à déréférencer par la suite ou NULL si échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +static GObject *find_first_segment_creator(const buffer_line_column *column) +{ + GObject *result; /* Trouvaille à retourner */ + size_t i; /* Boucle de parcours */ + + result = NULL; + + for (i = 0; i < column->count && result == NULL; i++) + result = g_buffer_segment_get_creator(column->segments[i]); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : column = colonne de ligne de texte à consulter. * * creator = créateur à l'origine du segment recherché. * * * @@ -1165,6 +1195,35 @@ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *line, GBuffer /****************************************************************************** * * +* Paramètres : line = ligne à venir consulter. * +* column = indice de la colonne visée par les recherches. * +* * +* Description : Recherche le premier créateur enregistré dans des segments. * +* * +* Retour : Créateur trouvé à déréférencer par la suite ou NULL si échec.* +* * +* Remarques : - * +* * +******************************************************************************/ + +GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *line, BufferLineColumn column) +{ + GObject *result; /* Trouvaille à retourner */ + + assert(column < BLC_COUNT); + + result = find_first_segment_creator(&line->columns[column]); + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : line = ligne à venir consulter. * * creator = créateur à l'origine du segment recherché. * * * diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index 19652ab..89313be 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -120,6 +120,9 @@ GBufferSegment *g_buffer_line_get_segment_at(const GBufferLine *, const gint [BL /* Fournit le segment voisin d'un autre segment identifié. */ GBufferSegment *g_buffer_line_find_near_segment(const GBufferLine *, GBufferSegment *, const gint [BLC_COUNT], const bool *, GdkScrollDirection, gint *); +/* Recherche le premier créateur enregistré dans des segments. */ +GObject *g_buffer_line_find_first_segment_creator(const GBufferLine *, BufferLineColumn); + /* Fournit le segment créé par un objet particulier. */ GBufferSegment *g_buffer_line_find_segment_from_creator(const GBufferLine *, GObject *); diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index f96212c..be7fa37 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -158,10 +158,10 @@ static void g_code_buffer_insert_lines_at(GCodeBuffer *, GBufferLine **, size_t, /* Affiche un commentaire sur une ligne de tampon donnée. */ -static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *, GBufferLine *, const char *); +static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *, GBufferLine *, const char *, GObject *); /* Affiche un commentaire sur une ligne de tampon dédiée. */ -static bool _g_code_buffer_write_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool); +static bool _g_code_buffer_write_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool, GObject *); /* Retrouve la première ligne d'une zone de commentaire. */ static size_t g_code_buffer_find_first_line_comment(const GCodeBuffer *, size_t); @@ -453,6 +453,7 @@ static void g_buffer_scan_process(GBufferScan *scan, GtkExtStatusBar *statusbar) * Paramètres : buffer = tampon de lignes à consulter. * * line = ligne à l'intérieur d'un commentaire. * * comment = nouveau commentaire à inscrire à la ligne donnée. * +* creator = créateur à l'origine de la construction. * * * * Description : Affiche un commentaire sur une ligne de tampon donnée. * * * @@ -462,7 +463,7 @@ static void g_buffer_scan_process(GBufferScan *scan, GtkExtStatusBar *statusbar) * * ******************************************************************************/ -static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment) +static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator) { bool result; /* Bilan à retourner */ const mrange_t *range; /* Emplace de ligne à utiliser */ @@ -472,6 +473,7 @@ static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLin char *saveptr; /* Sauvegarde pour la sécurité */ char *token; /* Fragment à insérer */ size_t len; /* Taille dudit fragment */ + GBufferSegment *segment; /* Segment à marquer au fer */ GBufferLine *new; /* Nouvelle ligne créée */ size_t i; /* Boucle de parcours */ @@ -493,12 +495,17 @@ static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLin len = strlen(token); if (!result) - g_buffer_line_insert_text(line, BLC_COMMENTS, token, len, RTT_COMMENT); + { + segment = g_buffer_line_insert_text(line, BLC_COMMENTS, token, len, RTT_COMMENT); + g_buffer_segment_set_creator(segment, creator); + } else { new = g_code_buffer_prepare_new_line(buffer, range); - g_buffer_line_insert_text(new, BLC_COMMENTS, token, len, RTT_COMMENT); + + segment = g_buffer_line_insert_text(new, BLC_COMMENTS, token, len, RTT_COMMENT); + g_buffer_segment_set_creator(segment, creator); extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *)); @@ -534,6 +541,7 @@ static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLin * Paramètres : buffer = tampon de lignes à consulter. * * line = ligne à l'intérieur d'un commentaire. * * comment = nouveau commentaire à inscrire à la ligne donnée. * +* creator = créateur à l'origine de la construction. * * * * Description : Affiche un commentaire sur une ligne de tampon donnée. * * * @@ -543,7 +551,7 @@ static bool _g_code_buffer_write_inlined_comment(GCodeBuffer *buffer, GBufferLin * * ******************************************************************************/ -bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment) +bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line, const char *comment, GObject *creator) { bool result; /* Bilan à retourner */ @@ -553,7 +561,7 @@ bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line result = true; if (result) - result = _g_code_buffer_write_inlined_comment(buffer, line, comment); + result = _g_code_buffer_write_inlined_comment(buffer, line, comment, creator); /* TODO : emit() */ @@ -568,6 +576,7 @@ bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line * line = ligne à l'intérieur d'un commentaire. * * comment = nouveau commentaire à inscrire à la ligne donnée. * * before = précise la position du commentaire. * +* creator = créateur à l'origine de la construction. * * * * Description : Affiche un commentaire sur une ligne de tampon dédiée. * * * @@ -577,7 +586,7 @@ bool g_code_buffer_update_inlined_comment(GCodeBuffer *buffer, GBufferLine *line * * ******************************************************************************/ -static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before) +static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator) { bool result; /* Bilan à retourner */ const mrange_t *range; /* Emplace de ligne à utiliser */ @@ -588,6 +597,7 @@ static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine * char *token; /* Fragment à insérer */ size_t len; /* Taille dudit fragment */ GBufferLine *new; /* Nouvelle ligne créée */ + GBufferSegment *segment; /* Segment à marquer au fer */ size_t i; /* Boucle de parcours */ assert(!g_buffer_line_has_comment(line)); @@ -609,7 +619,9 @@ static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine * new = g_code_buffer_prepare_new_line(buffer, range); g_buffer_line_start_merge_at(new, BLC_DISPLAY); - g_buffer_line_insert_text(new, BLC_DISPLAY, token, len, RTT_COMMENT); + + segment = g_buffer_line_insert_text(new, BLC_DISPLAY, token, len, RTT_COMMENT); + g_buffer_segment_set_creator(segment, creator); extra = (GBufferLine **)realloc(extra, ++extra_count * sizeof(GBufferLine *)); @@ -644,6 +656,7 @@ static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine * * line = ligne à l'intérieur d'un commentaire. * * comment = nouveau commentaire à inscrire à la ligne donnée. * * before = précise la position du commentaire. * +* creator = créateur à l'origine de la construction. * * * * Description : Affiche un commentaire sur une ligne de tampon dédiée. * * * @@ -653,7 +666,7 @@ static bool _g_code_buffer_write_comment_area(GCodeBuffer *buffer, GBufferLine * * * ******************************************************************************/ -bool g_code_buffer_update_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before) +bool g_code_buffer_update_comment_area(GCodeBuffer *buffer, GBufferLine *line, const char *comment, bool before, GObject *creator) { bool result; /* Bilan à retourner */ @@ -663,7 +676,7 @@ bool g_code_buffer_update_comment_area(GCodeBuffer *buffer, GBufferLine *line, c result = true; if (result) - result = _g_code_buffer_write_comment_area(buffer, line, comment, before); + result = _g_code_buffer_write_comment_area(buffer, line, comment, before, creator); /* TODO : emit() */ @@ -873,6 +886,43 @@ static size_t g_code_buffer_find_last_line_comment(const GCodeBuffer *buffer, si * Paramètres : buffer = tampon de lignes à consulter. * * line = ligne à l'intérieur d'un commentaire. * * * +* Description : Retrouve le créateur d'un commentaire existant. * +* * +* Retour : Instance trouvée à déréférencer ensuite ou NULL si aucune. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *buffer, const GBufferLine *line) +{ + GObject *result; /* Instance à retourner */ + BufferLineColumn merge_col; /* Colonne de fusion */ + + if (g_buffer_line_has_comment(line)) + { + merge_col = g_buffer_line_get_merge_start(line); + + if (merge_col == BLC_DISPLAY) + result = g_buffer_line_find_first_segment_creator(line, BLC_DISPLAY); + else + result = g_buffer_line_find_first_segment_creator(line, BLC_COMMENTS); + + } + + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : buffer = tampon de lignes à consulter. * +* line = ligne à l'intérieur d'un commentaire. * +* * * Description : Récupère le contenu d'un commentaire existant. * * * * Retour : Commentaire retrouver à libérer ou NULL en cas d'échec. * @@ -1536,7 +1586,7 @@ GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, const vm result = buffer->lines[index]; if (flags != BLF_NONE) - while ((g_buffer_line_get_flags(result) & flags) == 0) + while ((g_buffer_line_get_flags(result) & flags) != flags) { if ((index + 1) == buffer->used) break; diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h index d04ed76..8bcbc4a 100644 --- a/src/glibext/gcodebuffer.h +++ b/src/glibext/gcodebuffer.h @@ -111,10 +111,13 @@ GDelayedWork *g_buffer_code_scan(GCodeBuffer *, const vmpa2t *, const vmpa2t *, /* Affiche un commentaire sur une ligne de tampon donnée. */ -bool g_code_buffer_update_inlined_comment(GCodeBuffer *, GBufferLine *, const char *); +bool g_code_buffer_update_inlined_comment(GCodeBuffer *, GBufferLine *, const char *, GObject *); /* Affiche un commentaire sur une ligne de tampon dédiée. */ -bool g_code_buffer_update_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool); +bool g_code_buffer_update_comment_area(GCodeBuffer *, GBufferLine *, const char *, bool, GObject *); + +/* Retrouve le créateur d'un commentaire existant. */ +GObject *g_code_buffer_get_comment_creator(const GCodeBuffer *, const GBufferLine *); /* Récupère le contenu d'un commentaire existant. */ char *g_code_buffer_get_lines_comment(const GCodeBuffer *, const GBufferLine *); -- cgit v0.11.2-87-g4458