From 8ce244d136b32b43d8553866747c68b503b2d10a Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 21 Feb 2022 07:51:14 +0100 Subject: Define the first steps towards format serialization. --- src/format/format.c | 372 +++++++++++++++++++++++++++++++++++++++++++++++++ src/format/known-int.h | 10 ++ src/format/known.c | 181 +++++++++++++++++++++++- src/format/symbol.c | 84 ++++++++++- 4 files changed, 644 insertions(+), 3 deletions(-) diff --git a/src/format/format.c b/src/format/format.c index f8fe13a..d126236 100644 --- a/src/format/format.c +++ b/src/format/format.c @@ -33,6 +33,7 @@ #include "preload.h" #include "../arch/processor.h" #include "../common/sort.h" +#include "../core/demanglers.h" #include "../plugins/pglist.h" @@ -49,6 +50,12 @@ static void g_binary_format_dispose(GBinFormat *); /* Procède à la libération totale de la mémoire. */ static void g_binary_format_finalize(GBinFormat *); +/* Charge les plages de couvertures depuis une mémoire tampon. */ +static bool g_binary_format_load_start_points(GBinFormat *, packed_buffer_t *); + +/* Sauvegarde les points de départ enregistrés pour un format. */ +static bool g_binary_format_store_start_points(GBinFormat *, packed_buffer_t *); + /* ---------------------- RASSEMBLEMENT ET GESTION DE SYMBOLES ---------------------- */ @@ -65,6 +72,30 @@ static bool __g_binary_format_find_symbol(const GBinFormat *, const void *, __co +/* ------------------ CONSERVATION DES SOUCIS DURANT LE CHARGEMENT ------------------ */ + + +/* Charge les erreurs de chargement depuis une mémoire tampon. */ +static bool g_binary_format_load_errors(GBinFormat *, packed_buffer_t *); + +/* Sauvegarde les erreurs de chargement dans une mémoire tampon. */ +static bool g_binary_format_store_errors(GBinFormat *, packed_buffer_t *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Charge un format depuis une mémoire tampon. */ +static bool g_binary_format_load(GBinFormat *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un format dans une mémoire tampon. */ +static bool g_binary_format_store(GBinFormat *, GObjectStorage *, packed_buffer_t *); + + + + + /* Indique le type défini pour un format binaire générique. */ G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_KNOWN_FORMAT); @@ -84,12 +115,18 @@ G_DEFINE_TYPE(GBinFormat, g_binary_format, G_TYPE_KNOWN_FORMAT); static void g_binary_format_class_init(GBinFormatClass *klass) { GObjectClass *object; /* Autre version de la classe */ + GKnownFormatClass *known; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_binary_format_dispose; object->finalize = (GObjectFinalizeFunc)g_binary_format_finalize; + known = G_KNOWN_FORMAT_CLASS(klass); + + known->load = (load_known_fc)g_binary_format_load; + known->store = (load_known_fc)g_binary_format_store; + g_signal_new("symbol-added", G_TYPE_BIN_FORMAT, G_SIGNAL_RUN_LAST, @@ -411,6 +448,101 @@ void g_binary_format_register_code_point(GBinFormat *format, virt_t pt, DisassPr /****************************************************************************** * * +* Paramètres : proc = architecture concernée par la procédure. * +* pbuf = zone tampon à vider. * +* * +* Description : Charge les plages de couvertures depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_format_load_start_points(GBinFormat *format, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + DisassPriorityLevel i; /* Boucle de parcours #1 */ + uleb128_t count; /* Quantité de points présents */ + size_t k; /* Boucle de parcours #2 */ + uleb128_t value; /* Valeur ULEB128 à charger */ + + result = true; + + g_rw_lock_writer_lock(&format->pt_lock); + + for (i = 0; i < DPL_COUNT && result; i++) + { + result = unpack_uleb128(&count, pbuf); + if (!result) break; + + format->pt_allocated[i] = count; + format->pt_count[i] = count; + + format->start_points[i] = calloc(format->pt_count[i], sizeof(virt_t)); + + for (k = 0; k < format->pt_count[i] && result; k++) + { + result = unpack_uleb128(&value, pbuf); + if (!result) break; + + format->start_points[i][k] = value; + + } + + } + + g_rw_lock_writer_unlock(&format->pt_lock); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde les points de départ enregistrés pour un format. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_format_store_start_points(GBinFormat *format, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + DisassPriorityLevel i; /* Boucle de parcours #1 */ + size_t count; /* Quantité de points présents */ + size_t k; /* Boucle de parcours #2 */ + + result = true; + + g_rw_lock_writer_lock(&format->pt_lock); + + for (i = 0; i < DPL_COUNT && result; i++) + { + count = format->pt_count[i]; + + result = pack_uleb128((uleb128_t []){ count }, pbuf); + + for (k = 0; k < count && result; k++) + result = pack_uleb128((uleb128_t []){ format->start_points[i][k] }, pbuf); + + } + + g_rw_lock_writer_unlock(&format->pt_lock); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : format = description de l'exécutable à consulter. * * ctx = contexte de désassemblage à préparer. * * status = barre de statut à tenir informée. * @@ -1546,3 +1678,243 @@ bool g_binary_format_get_error(GBinFormat *format, size_t index, BinaryFormatErr return result; } + + +/****************************************************************************** +* * +* Paramètres : format = format de binaire concerné par la procédure. * +* pbuf = zone tampon à vider. * +* * +* Description : Charge les erreurs de chargement depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_format_load_errors(GBinFormat *format, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + uleb128_t value; /* Valeur ULEB128 à charger */ + size_t i; /* Boucle de parcours */ + fmt_error *error; /* Raccourci de confort */ + rle_string str; /* Chaîne à charger */ + + g_binary_format_lock_errors(format); + + result = unpack_uleb128(&value, pbuf); + if (!result) goto exit; + + format->error_count = value; + + format->errors = calloc(format->error_count, sizeof(fmt_error)); + + for (i = 0; i < format->error_count && result; i++) + { + error = &format->errors[i]; + + result = unpack_uleb128(&value, pbuf); + if (!result) break; + + error->type = value; + + result = unpack_vmpa(&error->addr, pbuf); + if (!result) break; + + setup_empty_rle_string(&str); + + result = unpack_rle_string(&str, pbuf); + if (!result) break; + + if (get_rle_string(&str) != NULL) + error->desc = strdup(get_rle_string(&str)); + + exit_rle_string(&str); + + } + + exit: + + g_binary_format_unlock_errors(format); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = format de binaire concerné par la procédure. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde les erreurs de chargement dans une mémoire tampon.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_format_store_errors(GBinFormat *format, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours */ + fmt_error *error; /* Raccourci de confort */ + rle_string str; /* Chaîne à conserver */ + + g_binary_format_lock_errors(format); + + result = pack_uleb128((uleb128_t []){ format->error_count }, pbuf); + + for (i = 0; i < format->error_count && result; i++) + { + error = &format->errors[i]; + + result = pack_uleb128((uleb128_t []){ error->type }, pbuf); + if (!result) break; + + result = pack_vmpa(&error->addr, pbuf); + if (!result) break; + + init_static_rle_string(&str, error->desc); + + result = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + } + + g_binary_format_unlock_errors(format); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un format depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_format_load(GBinFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + fmt_extra_data_t *extra; /* Données insérées à consulter*/ + uleb128_t value; /* Valeur ULEB128 à charger */ + rle_string str; /* Chaîne à charger */ + + extra = GET_BIN_FORMAT_EXTRA(format); + + LOCK_GOBJECT_EXTRA(extra); + + result = unpack_uleb128(&value, pbuf); + + if (result) + extra->flags = value; + + UNLOCK_GOBJECT_EXTRA(extra); + + if (result) + result = g_binary_format_load_start_points(format, pbuf); + + if (result) + { + setup_empty_rle_string(&str); + + result = unpack_rle_string(&str, pbuf); + + if (result) + result = (get_rle_string(&str) != NULL); + + if (result) + format->demangler = get_compiler_demangler_for_key(get_rle_string(&str)); + + if (result) + result = (format->demangler != NULL); + + exit_rle_string(&str); + + } + + + + + + if (result) + result = g_binary_format_load_errors(format, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un format dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_binary_format_store(GBinFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + fmt_extra_data_t *extra; /* Données insérées à consulter*/ + char *key; /* Désignation du décodeur */ + rle_string str; /* Chaîne à conserver */ + + extra = GET_BIN_FORMAT_EXTRA(format); + + LOCK_GOBJECT_EXTRA(extra); + + result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf); + + UNLOCK_GOBJECT_EXTRA(extra); + + if (result) + result = g_binary_format_store_start_points(format, pbuf); + + if (result) + { + key = g_compiler_demangler_get_key(format->demangler); + init_dynamic_rle_string(&str, key); + + result = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + } + + + + + + + if (result) + result = g_binary_format_store_errors(format, pbuf); + + return result; + +} diff --git a/src/format/known-int.h b/src/format/known-int.h index 950c75f..3328a96 100644 --- a/src/format/known-int.h +++ b/src/format/known-int.h @@ -26,6 +26,7 @@ #include "known.h" +#include "../analysis/storage/storage.h" @@ -41,6 +42,12 @@ typedef bool (* known_analyze_fc) (GKnownFormat *, wgroup_id_t, GtkStatusStack * /* Réalise un traitement post-désassemblage. */ typedef void (* known_complete_analysis_fc) (GKnownFormat *, wgroup_id_t, GtkStatusStack *); +/* Charge un format depuis une mémoire tampon. */ +typedef bool (* load_known_fc) (GKnownFormat *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un format dans une mémoire tampon. */ +typedef bool (* store_known_fc) (GKnownFormat *, GObjectStorage *, packed_buffer_t *); + /* Format binaire générique (instance) */ struct _GKnownFormat @@ -62,6 +69,9 @@ struct _GKnownFormatClass known_analyze_fc analyze; /* Interprétation du format */ known_complete_analysis_fc complete; /* Terminaison d'analyse */ + load_known_fc load; /* Chargement depuis un tampon */ + store_known_fc store; /* Conservation dans un tampon */ + }; diff --git a/src/format/known.c b/src/format/known.c index 6865d0d..7512ae1 100644 --- a/src/format/known.c +++ b/src/format/known.c @@ -28,16 +28,23 @@ #include "known-int.h" +#include "../analysis/storage/serialize-int.h" #include "../plugins/pglist.h" +/* ---------------------- DEFINITION DE LA BASE DE TOUT FORMAT ---------------------- */ + + /* Initialise la classe des formats binaires génériques. */ static void g_known_format_class_init(GKnownFormatClass *); /* Initialise une instance de format binaire générique. */ static void g_known_format_init(GKnownFormat *); +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_known_format_serializable_init(GSerializableObjectInterface *); + /* Supprime toutes les références externes. */ static void g_known_format_dispose(GKnownFormat *); @@ -46,8 +53,31 @@ static void g_known_format_finalize(GKnownFormat *); +/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ + + +/* Charge un format depuis une mémoire tampon. */ +static bool _g_known_format_load(GKnownFormat *, GObjectStorage *, packed_buffer_t *); + +/* Charge un format depuis une mémoire tampon. */ +static bool g_known_format_load(GKnownFormat *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un format dans une mémoire tampon. */ +static bool _g_known_format_store(GKnownFormat *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un format dans une mémoire tampon. */ +static bool g_known_format_store(GKnownFormat *, GObjectStorage *, packed_buffer_t *); + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DE LA BASE DE TOUT FORMAT */ +/* ---------------------------------------------------------------------------------- */ + + /* Indique le type défini pour un format binaire générique. */ -G_DEFINE_TYPE(GKnownFormat, g_known_format, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE(GKnownFormat, g_known_format, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_known_format_serializable_init)); /****************************************************************************** @@ -71,6 +101,9 @@ static void g_known_format_class_init(GKnownFormatClass *klass) object->dispose = (GObjectFinalizeFunc/* ! */)g_known_format_dispose; object->finalize = (GObjectFinalizeFunc)g_known_format_finalize; + klass->load = (load_known_fc)_g_known_format_load; + klass->store = (store_known_fc)_g_known_format_store; + } @@ -95,6 +128,26 @@ static void g_known_format_init(GKnownFormat *format) /****************************************************************************** * * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de sérialisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_known_format_serializable_init(GSerializableObjectInterface *iface) +{ + iface->load = (load_serializable_object_cb)g_known_format_load; + iface->store = (store_serializable_object_cb)g_known_format_store; + +} + + +/****************************************************************************** +* * * Paramètres : format = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * @@ -289,3 +342,129 @@ void g_known_format_complete_analysis(GKnownFormat *format, wgroup_id_t gid, Gtk handle_known_format_analysis(PGA_FORMAT_POST_ANALYSIS_ENDED, format, gid, status); } + + + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION ET RECHARGEMENT DES DONNEES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un format depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool _g_known_format_load(GKnownFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GBinContent *content; /* Contenu binaire rechargé */ + + content = G_BIN_CONTENT(g_object_storage_unpack_object(storage, "contents", pbuf)); + result = (content != NULL); + + if (result) + { + g_known_format_set_content(format, content); + + g_object_unref(G_OBJECT(content)); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un format depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_known_format_load(GKnownFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GKnownFormatClass *class; /* Classe à activer */ + + class = G_KNOWN_FORMAT_GET_CLASS(format); + + result = class->load(format, storage, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un format dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool _g_known_format_store(GKnownFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + + if (format->content == NULL) + result = false; + + else + result = g_object_storage_pack_object(storage, "contents", G_SERIALIZABLE_OBJECT(format->content), pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un format dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_known_format_store(GKnownFormat *format, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GKnownFormatClass *class; /* Classe à activer */ + + class = G_KNOWN_FORMAT_GET_CLASS(format); + + result = class->store(format, storage, pbuf); + + return result; + +} diff --git a/src/format/symbol.c b/src/format/symbol.c index 2cd4f87..9b054e6 100644 --- a/src/format/symbol.c +++ b/src/format/symbol.c @@ -30,6 +30,7 @@ #include "symbol-int.h" +#include "../analysis/db/misc/rlestr.h" #include "../glibext/gbinarycursor.h" #include "../glibext/linegen-int.h" #include "../gtkext/gtkblockdisplay.h" @@ -940,8 +941,57 @@ static void g_binary_symbol_print(GBinSymbol *symbol, GBufferLine *line, size_t static bool _g_binary_symbol_load(GBinSymbol *symbol, GObjectStorage *storage, packed_buffer_t *pbuf) { bool result; /* Bilan à retourner */ + sym_extra_data_t *extra; /* Données insérées à consulter*/ + uleb128_t value; /* Valeur ULEB128 à charger */ + rle_string str; /* Chaîne à charger */ - result = true; + extra = GET_BIN_SYMBOL_EXTRA(symbol); + + LOCK_GOBJECT_EXTRA(extra); + + result = unpack_uleb128(&value, pbuf); + + if (result) + extra->stype = value; + + if (result) + { + result = unpack_uleb128(&value, pbuf); + + if (result) + extra->status = value; + + } + + if (result) + result = extract_packed_buffer(pbuf, &extra->nm_prefix, 1, false); + + if (result) + { + result = unpack_uleb128(&value, pbuf); + + if (result) + extra->flags = value; + + } + + UNLOCK_GOBJECT_EXTRA(extra); + + if (result) + result = unpack_mrange(&symbol->range, pbuf); + + if (result) + { + setup_empty_rle_string(&str); + + result = unpack_rle_string(&str, pbuf); + + if (result && get_rle_string(&str) != NULL) + symbol->alt = strdup(get_rle_string(&str)); + + exit_rle_string(&str); + + } return result; @@ -993,8 +1043,38 @@ static bool g_binary_symbol_load(GBinSymbol *symbol, GObjectStorage *storage, pa static bool _g_binary_symbol_store(GBinSymbol *symbol, GObjectStorage *storage, packed_buffer_t *pbuf) { bool result; /* Bilan à retourner */ + sym_extra_data_t *extra; /* Données insérées à consulter*/ + rle_string str; /* Chaîne à conserver */ + + extra = GET_BIN_SYMBOL_EXTRA(symbol); + + LOCK_GOBJECT_EXTRA(extra); + + result = pack_uleb128((uleb128_t []){ extra->stype }, pbuf); + + if (result) + result = pack_uleb128((uleb128_t []){ extra->status }, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &extra->nm_prefix, 1, false); + + if (result) + result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf); + + UNLOCK_GOBJECT_EXTRA(extra); + + if (result) + result = pack_mrange(&symbol->range, pbuf); - result = true; + if (result) + { + init_static_rle_string(&str, symbol->alt); + + result = pack_rle_string(&str, pbuf); + + exit_rle_string(&str); + + } return result; -- cgit v0.11.2-87-g4458