From 83faef9c8f78b20cb031af686f763cfb215cf9d7 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Wed, 11 Sep 2019 23:25:13 +0200 Subject: Reactivated bookmarks for disassembled code. --- plugins/pychrysalide/analysis/db/constants.c | 38 ++++++ plugins/pychrysalide/analysis/db/constants.h | 3 + plugins/pychrysalide/analysis/db/item.c | 137 +++++++++++++++++++++- plugins/pychrysalide/analysis/db/items/bookmark.c | 7 +- src/analysis/db/collection.c | 10 +- src/analysis/db/item-int.h | 9 ++ src/analysis/db/item.c | 68 +++++++++++ src/analysis/db/item.h | 18 +++ src/analysis/db/items/bookmark.c | 71 ++++++++--- src/analysis/db/misc/rlestr.c | 13 ++ src/arch/vmpa.c | 24 +--- src/glibext/gbuffercache.h | 5 + 12 files changed, 356 insertions(+), 47 deletions(-) diff --git a/plugins/pychrysalide/analysis/db/constants.c b/plugins/pychrysalide/analysis/db/constants.c index 9685ba6..fb30c7e 100644 --- a/plugins/pychrysalide/analysis/db/constants.c +++ b/plugins/pychrysalide/analysis/db/constants.c @@ -25,6 +25,7 @@ #include "constants.h" +#include #include @@ -36,6 +37,43 @@ * * * Paramètres : type = type dont le dictionnaire est à compléter. * * * +* Description : Définit les constantes pour les éléments de base de données. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_db_item_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + values = PyDict_New(); + + result = add_const_to_group(values, "NONE", DIF_NONE); + if (result) result = add_const_to_group(values, "ERASER", DIF_ERASER); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group(type, true, "DbItemFlags", values, "Properties of a database item."); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * * Description : Définit les constantes pour les serveurs de données. * * * * Retour : true en cas de succès de l'opération, false sinon. * diff --git a/plugins/pychrysalide/analysis/db/constants.h b/plugins/pychrysalide/analysis/db/constants.h index a2fc49e..cb7edf4 100644 --- a/plugins/pychrysalide/analysis/db/constants.h +++ b/plugins/pychrysalide/analysis/db/constants.h @@ -31,6 +31,9 @@ +/* Définit les constantes pour les éléments de base de données. */ +bool define_db_item_constants(PyTypeObject *); + /* Définit les constantes pour les serveurs de données. */ bool define_hub_server_constants(PyTypeObject *); diff --git a/plugins/pychrysalide/analysis/db/item.c b/plugins/pychrysalide/analysis/db/item.c index 981e0c0..bbaa21b 100644 --- a/plugins/pychrysalide/analysis/db/item.c +++ b/plugins/pychrysalide/analysis/db/item.c @@ -32,17 +32,109 @@ #include +#include "constants.h" #include "../../access.h" #include "../../helpers.h" +/* Ajoute une propriété à un élément de base de données. */ +static PyObject *py_db_item_add_flag(PyObject *, PyObject *); + +/* Retire une propriété à un élément de base de données. */ +static PyObject *py_db_item_remove_flag(PyObject *, PyObject *); + /* Indique si l'élément contient des données à oublier ou non. */ static PyObject *py_db_item_get_volatile(PyObject *, void *); /* Définit si l'élément contient des données à oublier ou non. */ static int py_db_item_set_volatile(PyObject *, PyObject *, void *); +/* Indique les propriétés particulières appliquées à l'élément. */ +static PyObject *py_db_item_get_flags(PyObject *, void *); + + + +/****************************************************************************** +* * +* Paramètres : self = serveur à manipuler. * +* args = arguments d'appel non utilisés ici. * +* * +* Description : Ajoute une propriété à un élément de base de données. * +* * +* Retour : None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_db_item_add_flag(PyObject *self, PyObject *args) +{ + unsigned int flag; /* Propriété à traiter */ + int ret; /* Bilan de lecture des args. */ + GDbItem *item; /* Elément à manipuler */ + +#define DB_ITEM_ADD_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + add_flag, "$self, flag, /", \ + METH_VARARGS, py_db_item, \ + "Add a property to a database item." \ + "\n" \ + "This property is one of the values listed in the" \ + " of pychrysalide.analysis.db.DbItem.DbItemFlags enumeration." \ +) + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + item = G_DB_ITEM(pygobject_get(self)); + + g_db_item_add_flag(item, flag); + + Py_RETURN_NONE; + +} + + +/****************************************************************************** +* * +* Paramètres : self = serveur à manipuler. * +* args = arguments d'appel non utilisés ici. * +* * +* Description : Retire une propriété à un élément de base de données. * +* * +* Retour : None. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_db_item_remove_flag(PyObject *self, PyObject *args) +{ + unsigned int flag; /* Propriété à traiter */ + int ret; /* Bilan de lecture des args. */ + GDbItem *item; /* Elément à manipuler */ + +#define DB_ITEM_REMOVE_FLAG_METHOD PYTHON_METHOD_DEF \ +( \ + remove_flag, "$self, flag, /", \ + METH_VARARGS, py_db_item, \ + "Remove a property from a database item." \ + "\n" \ + "This property is one of the values listed in the" \ + " of pychrysalide.analysis.db.DbItem.DbItemFlags enumeration." \ +) + + ret = PyArg_ParseTuple(args, "I", &flag); + if (!ret) return NULL; + + item = G_DB_ITEM(pygobject_get(self)); + + g_db_item_remove_flag(item, flag); + + Py_RETURN_NONE; + +} /****************************************************************************** @@ -107,6 +199,43 @@ static int py_db_item_set_volatile(PyObject *self, PyObject *value, void *closur /****************************************************************************** * * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Indique les propriétés particulières appliquées à l'élément. * +* * +* Retour : Propriétés actives de l'élément. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_db_item_get_flags(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GDbItem *item; /* Elément à consulter */ + DbItemFlags flags; /* Propriétés de l'élément */ + +#define DB_ITEM_FLAGS_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + flags, py_db_item, \ + "Properties of the database item, provided as a mask" \ + " of pychrysalide.analysis.db.DbItem.DbItemFlags values." \ +) + + item = G_DB_ITEM(pygobject_get(self)); + + flags = g_db_item_get_flags(item); + + result = cast_with_constants_group(get_python_db_item_type(), "DbItemFlags", flags); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -120,17 +249,18 @@ static int py_db_item_set_volatile(PyObject *self, PyObject *value, void *closur PyTypeObject *get_python_db_item_type(void) { static PyMethodDef py_db_item_methods[] = { + DB_ITEM_ADD_FLAG_METHOD, + DB_ITEM_REMOVE_FLAG_METHOD, { NULL } }; static PyGetSetDef py_db_item_getseters[] = { - { "volatile", py_db_item_get_volatile, py_db_item_set_volatile, "Define if a Database item can be forgotten.", NULL }, + DB_ITEM_FLAGS_ATTRIB, { NULL } - }; static PyTypeObject py_db_item_type = { @@ -183,6 +313,9 @@ bool ensure_python_db_item_is_registered(void) if (!register_class_for_pygobject(dict, G_TYPE_DB_ITEM, type, &PyGObject_Type)) return false; + if (!define_db_item_constants(type)) + return false; + } return true; diff --git a/plugins/pychrysalide/analysis/db/items/bookmark.c b/plugins/pychrysalide/analysis/db/items/bookmark.c index 8a33357..783efa6 100644 --- a/plugins/pychrysalide/analysis/db/items/bookmark.c +++ b/plugins/pychrysalide/analysis/db/items/bookmark.c @@ -147,7 +147,12 @@ static int py_db_bookmark_init(PyObject *self, PyObject *args, PyObject *kwds) " DbBookmark(addr, comment=None)" \ "\n" \ "Where addr is a location of type pychrysalide.arch.vmpa and" \ - " comment is a string or None." + " comment is a string or None.\n" \ + "\n" \ + "An empty comment is not enough to delete a bookmark for a given address;" \ + " the *ERASER* flag from the pychrysalide.analysis.db.DbItem.DbItemFlags" \ + " enumeration must be explicitly add to the item by a call to the" \ + " pychrysalide.analysis.db.DbItem.add_flag() function." result = -1; diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c index cdc91aa..0f4e771 100644 --- a/src/analysis/db/collection.c +++ b/src/analysis/db/collection.c @@ -375,14 +375,10 @@ bool g_db_collection_unpack(GDbCollection *collec, packed_buffer *pbuf, sqlite3 if (result) { if (collec->binary != NULL && g_db_item_is_active(item)) - result = g_db_item_apply(item, collec->binary); + g_db_item_apply(item, collec->binary); - if (result && db != NULL) - result = g_db_collection_store_item(collec, item, db); - - /* En cas d'erreur, il faut retirer l'élément */ - if (!result) - _g_db_collection_remove_item(collec, item, true, false); + if (db != NULL) + g_db_collection_store_item(collec, item, db); } diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h index 3a5f47d..923ea3a 100644 --- a/src/analysis/db/item-int.h +++ b/src/analysis/db/item-int.h @@ -71,8 +71,17 @@ struct _GDbItem char *label; /* Représentation humaine */ + union + { + DbItemFlags flags; /* Propriétés de l'élément */ + gint atomic_flags; /* Accès atomique */ + + }; + bool is_volatile; /* Pas besoin de sauvegarde ? */ + bool broken; /* Changement applicable ? */ + }; /* Base d'un élément pour collection générique (classe) */ diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c index 2bbc683..c59ef64 100644 --- a/src/analysis/db/item.c +++ b/src/analysis/db/item.c @@ -596,6 +596,74 @@ bool g_db_item_is_volatile(const GDbItem *item) } +/****************************************************************************** +* * +* Paramètres : item = base d'éléments à mettre à jour. * +* flag = type de propriété à traiter. * +* * +* Description : Ajoute une propriété à un élément de base de données. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_item_add_flag(GDbItem *item, DbItemFlags flag) +{ + g_atomic_int_add(&item->atomic_flags, flag); + +} + + +/****************************************************************************** +* * +* Paramètres : item = base d'éléments à mettre à jour. * +* flag = type de propriété à traiter. * +* * +* Description : Retire une propriété à un élément de base de données. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_db_item_remove_flag(GDbItem *item, DbItemFlags flag) +{ + gint mask; /* Masque à appliquer */ + + mask = flag; + mask = ~mask; + + g_atomic_int_and(&item->atomic_flags, mask); + +} + + +/****************************************************************************** +* * +* Paramètres : item = base d'éléments à consulter. * +* * +* Description : Indique les propriétés particulières appliquées à l'élément. * +* * +* Retour : Propriétés actives de l'élément. * +* * +* Remarques : - * +* * +******************************************************************************/ + +DbItemFlags g_db_item_get_flags(const GDbItem *item) +{ + DbItemFlags result; /* Fanions à retourner */ + + result = g_atomic_int_get(&item->atomic_flags); + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* MANIPULATIONS AVEC UNE BASE DE DONNEES */ diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h index 6644507..3444b73 100644 --- a/src/analysis/db/item.h +++ b/src/analysis/db/item.h @@ -40,6 +40,15 @@ typedef struct _GLoadedBinary GLoadedBinary; +/* Propriétés particulières pour un élément */ +typedef enum _DbItemFlags +{ + DIF_NONE = (0 << 0), /* Propriétés par défaut */ + DIF_ERASER = (1 << 0), /* Suppression de l'effet */ + +} DbItemFlags; + + #define G_TYPE_DB_ITEM g_db_item_get_type() #define G_DB_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_item_get_type(), GDbItem)) #define G_IS_DB_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_db_item_get_type())) @@ -103,6 +112,15 @@ void g_db_item_set_volatile(GDbItem *, bool); /* Indique si l'élément contient des données à oublier ou non. */ bool g_db_item_is_volatile(const GDbItem *); +/* Ajoute une propriété à un élément de base de données. */ +void g_db_item_add_flag(GDbItem *, DbItemFlags); + +/* Retire une propriété à un élément de base de données. */ +void g_db_item_remove_flag(GDbItem *, DbItemFlags); + +/* Indique les propriétés particulières appliquées à l'élément. */ +DbItemFlags g_db_item_get_flags(const GDbItem *); + /* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */ diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c index 266b04c..819528d 100644 --- a/src/analysis/db/items/bookmark.c +++ b/src/analysis/db/items/bookmark.c @@ -34,6 +34,7 @@ #include "../collection-int.h" #include "../item-int.h" +#include "../../../glibext/gbinarycursor.h" @@ -206,6 +207,9 @@ static void g_db_bookmark_class_init(GDbBookmarkClass *klass) static void g_db_bookmark_init(GDbBookmark *bookmark) { + init_vmpa(&bookmark->addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + + init_dynamic_rle_string(&bookmark->comment, NULL); } @@ -440,37 +444,60 @@ static void g_db_bookmark_build_label(GDbBookmark *bookmark) static bool g_db_bookmark_run(GDbBookmark *bookmark, GLoadedBinary *binary, bool *prev, bool set) { - return false; -#if 0 bool result; /* Bilan à faire remonter */ - GCodeBuffer *buffer; /* Tampon de lignes à traiter */ + GBufferCache *cache; /* Tampon d'impression colorée */ + GLineCursor *cursor; /* Emplacement dans un tampon */ + size_t index; /* Indice de ligne à traiter */ GBufferLine *line; /* Ligne de tampon à marquer */ - result = true; + result = false; + + cache = g_loaded_binary_get_disassembled_cache(binary); + if (cache == NULL) goto exit; + + g_buffer_cache_lock(cache); + + /* Recherche de la ligne concernée */ + + cursor = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(cursor), &bookmark->addr); - buffer = g_loaded_binary_get_disassembled_buffer(binary); + index = g_buffer_cache_find_index_by_cursor(cache, cursor, true); - line = g_code_buffer_find_line_by_addr(buffer, &bookmark->addr, BLF_HAS_CODE, NULL); - if (line == NULL) + g_object_unref(G_OBJECT(cursor)); + + line = g_buffer_cache_find_line_by_index(cache, index); + + /* Application du changement */ + + result = (line != NULL); + + if (result) { - result = false; - goto exit; - } + *prev = g_buffer_line_get_flags(line) & BLF_BOOKMARK; - *prev = g_buffer_line_get_flags(line) & BLF_BOOKMARK; + if (set) + g_buffer_line_add_flag(line, BLF_BOOKMARK); - if (set) - g_buffer_line_add_flag(line, BLF_BOOKMARK); + else + g_buffer_line_remove_flag(line, BLF_BOOKMARK); - else - g_buffer_line_remove_flag(line, BLF_BOOKMARK); + g_object_unref(G_OBJECT(line)); + + g_buffer_cache_throw_update_at_index(cache, index); + + } - g_object_unref(G_OBJECT(line)); + /* Sortie */ + + g_buffer_cache_unlock(cache); + + g_object_unref(G_OBJECT(cache)); exit: return result; -#endif + } @@ -490,8 +517,11 @@ static bool g_db_bookmark_run(GDbBookmark *bookmark, GLoadedBinary *binary, bool static bool g_db_bookmark_apply(GDbBookmark *bookmark, GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ + DbItemFlags flags; /* Propriétés de l'élément */ - result = g_db_bookmark_run(bookmark, binary, &bookmark->prev_state, true); + flags = g_db_item_get_flags(G_DB_ITEM(bookmark)); + + result = g_db_bookmark_run(bookmark, binary, &bookmark->prev_state, (flags & DIF_ERASER) == 0); return result; @@ -514,9 +544,12 @@ static bool g_db_bookmark_apply(GDbBookmark *bookmark, GLoadedBinary *binary) static bool g_db_bookmark_cancel(GDbBookmark *bookmark, GLoadedBinary *binary) { bool result; /* Bilan à faire remonter */ + DbItemFlags flags; /* Propriétés de l'élément */ + + flags = g_db_item_get_flags(G_DB_ITEM(bookmark)); if (!bookmark->prev_state) - result = g_db_bookmark_run(bookmark, binary, (bool []) { 0 }, false); + result = g_db_bookmark_run(bookmark, binary, (bool []) { 0 }, (flags & DIF_ERASER) != 0); else result = true; diff --git a/src/analysis/db/misc/rlestr.c b/src/analysis/db/misc/rlestr.c index f26c146..0fe182b 100644 --- a/src/analysis/db/misc/rlestr.c +++ b/src/analysis/db/misc/rlestr.c @@ -105,6 +105,9 @@ void init_static_rle_string(rle_string *str, const char *data) void dup_into_rle_string(rle_string *str, const char *data) { + if (str->data != NULL) + unset_rle_string(str); + if (data != NULL) { str->data = strdup(data); @@ -144,6 +147,11 @@ void set_dynamic_rle_string(rle_string *str, char *data) str->length = strlen(data); str->dynamic = true; } + else + { + str->data = NULL; + str->length = 0; + } } @@ -172,6 +180,11 @@ void set_static_rle_string(rle_string *str, const char *data) str->length = strlen(data); str->dynamic = false; } + else + { + str->data = NULL; + str->length = 0; + } } diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c index a2a3ba5..70ea52b 100644 --- a/src/arch/vmpa.c +++ b/src/arch/vmpa.c @@ -813,36 +813,24 @@ bool store_vmpa(const vmpa2t *addr, const char *base, bound_value **values, size asprintf(&value->name, "%s%sphys", base != NULL ? base : "", base != NULL ? "_" : ""); value->built_name = true; + value->type = SQLITE_INT64; + value->has_value = (addr != NULL); if (value->has_value) - { - if (addr->physical != VMPA_NO_PHYSICAL) - { - value->type = SQLITE_INT64; - value->integer64 = addr->physical; - } - else - value->type = SQLITE_NULL; - } + value->integer64 = addr->physical; value = &(*values)[*count - 1]; asprintf(&value->name, "%s%svirt", base != NULL ? base : "", base != NULL ? "_" : ""); value->built_name = true; + value->type = SQLITE_INT64; + value->has_value = (addr != NULL); if (value->has_value) - { - if (addr->virtual != VMPA_NO_VIRTUAL) - { - value->type = SQLITE_INT64; - value->integer64 = addr->virtual; - } - else - value->type = SQLITE_NULL; - } + value->integer64 = addr->virtual; return true; diff --git a/src/glibext/gbuffercache.h b/src/glibext/gbuffercache.h index 8059357..0086b38 100644 --- a/src/glibext/gbuffercache.h +++ b/src/glibext/gbuffercache.h @@ -99,6 +99,11 @@ void g_buffer_cache_get_line_cursor(const GBufferCache *, size_t, gint, GLineCur /* Détermine l'ensemble des propriétés attachées à une ligne. */ BufferLineFlags g_buffer_cache_get_line_flags(const GBufferCache *, size_t); +#define g_buffer_cache_lock(c) +#define g_buffer_cache_unlock(c) + +#define g_buffer_cache_throw_update_at_index(c, i) // check locked + /* Retrouve une ligne au sein d'un tampon avec un indice. */ GBufferLine *g_buffer_cache_find_line_by_index(const GBufferCache *, size_t); -- cgit v0.11.2-87-g4458