diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2021-08-21 15:07:38 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2021-08-21 15:07:38 (GMT) |
commit | bae8c01323703d467ed2cce07c8bf8fd70f7816a (patch) | |
tree | a4e180f9d82ed3f7312dcf52b4517cb7580b83e5 /src/arch | |
parent | 9ed9405f37244832570f48b42dced1c92704ba3d (diff) |
Define all architecture instructions as serializable.
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/instruction-int.h | 11 | ||||
-rw-r--r-- | src/arch/instruction.c | 387 | ||||
-rw-r--r-- | src/arch/instruction.h | 4 | ||||
-rw-r--r-- | src/arch/instructions/undefined.c | 104 | ||||
-rw-r--r-- | src/arch/processor.c | 4 | ||||
-rw-r--r-- | src/arch/storage.c | 4 |
6 files changed, 503 insertions, 11 deletions
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index 9a23bf2..f8998a1 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -26,6 +26,7 @@ #include "instruction.h" +#include "../analysis/storage/storage.h" #include "../common/array.h" #include "../glibext/objhole.h" @@ -58,6 +59,13 @@ typedef GBufferLine * (* print_instruction_fc) (const GArchInstruction *, GBuffe /* Liste les registres lus et écrits par l'instruction. */ typedef void (* get_instruction_rw_regs_fc) (const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *); +/* Charge un contenu depuis une mémoire tampon. */ +typedef bool (* load_instruction_fc) (GArchInstruction *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un contenu dans une mémoire tampon. */ +typedef bool (* store_instruction_fc) (GArchInstruction *, GObjectStorage *, packed_buffer_t *); + + /* Informations glissées dans la structure GObject de GArchOperand */ typedef struct _instr_extra_data_t @@ -142,6 +150,9 @@ struct _GArchInstructionClass print_instruction_fc print; /* Imprime l'ensemble */ + load_instruction_fc load; /* Chargement depuis un tampon */ + store_instruction_fc store; /* Conservation dans un tampon */ + //get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés */ }; diff --git a/src/arch/instruction.c b/src/arch/instruction.c index e0d1091..c4354d4 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -34,6 +34,7 @@ #include "instruction-int.h" #include "storage.h" +#include "../analysis/storage/serialize-int.h" #include "../core/logs.h" #include "../core/processors.h" #include "../glibext/gbinarycursor.h" @@ -49,7 +50,10 @@ static void g_arch_instruction_class_init(GArchInstructionClass *); static void g_arch_instruction_init(GArchInstruction *); /* Procède à l'initialisation de l'interface de génération. */ -static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface *); +static void g_arch_instruction_generator_init(GLineGeneratorInterface *); + +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_arch_instruction_serializable_init(GSerializableObjectInterface *); /* Supprime toutes les références externes. */ static void g_arch_instruction_dispose(GArchInstruction *); @@ -59,6 +63,18 @@ static void g_arch_instruction_finalize(GArchInstruction *); + + +/* Charge un contenu depuis une mémoire tampon. */ +static bool g_arch_instruction_load_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde toutes les destinations d'une instruction. */ +bool g_arch_instruction_store_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *); + + + + + /* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ @@ -92,10 +108,27 @@ static void _g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); +/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ + + +/* Charge un contenu depuis une mémoire tampon. */ +static bool _g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *); + +/* Charge un contenu depuis une mémoire tampon. */ +static bool g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un contenu dans une mémoire tampon. */ +static bool _g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un contenu dans une mémoire tampon. */ +static bool g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *); + + /* Indique le type défini pour une instruction d'architecture. */ G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_interface_init)); + G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_init)); /****************************************************************************** @@ -127,6 +160,9 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass) instr->print = (print_instruction_fc)_g_arch_instruction_print; + instr->load = (load_instruction_fc)_g_arch_instruction_load; + instr->store = (store_instruction_fc)_g_arch_instruction_store; + } @@ -170,7 +206,7 @@ static void g_arch_instruction_init(GArchInstruction *instr) * * ******************************************************************************/ -static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface *iface) +static void g_arch_instruction_generator_init(GLineGeneratorInterface *iface) { iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines; iface->compute = (linegen_compute_fc)g_arch_instruction_compute_cursor; @@ -183,6 +219,26 @@ static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface /****************************************************************************** * * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de sérialisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_instruction_serializable_init(GSerializableObjectInterface *iface) +{ + iface->load = (load_serializable_object_cb)g_arch_instruction_load; + iface->store = (store_serializable_object_cb)g_arch_instruction_store; + +} + + +/****************************************************************************** +* * * Paramètres : instr = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * @@ -1560,6 +1616,132 @@ instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_ } +/****************************************************************************** +* * +* Paramètres : instr = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un contenu depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + uleb128_t count; /* Nombre de liens à charger */ + uleb128_t i; /* Boucle de parcours */ + GArchInstruction *linked; /* Lien vers une instruction */ + uleb128_t type; /* Valeur ULEB128 à charger */ + + g_arch_instruction_lock_dest(instr); + + result = unpack_uleb128(&count, pbuf); + + for (i = 0; i < count && result; i++) + { + linked = G_ARCH_INSTRUCTION(g_object_storage_unpack_object(storage, "instructions", pbuf)); + if (linked == NULL) + { + result = false; + break; + } + + result = unpack_uleb128(&type, pbuf); + if (!result) + { + g_object_unref(G_OBJECT(linked)); + break; + } + + g_arch_instruction_link_with(instr, linked, type); + g_object_unref(G_OBJECT(linked)); + + } + + g_arch_instruction_unlock_dest(instr); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont les informations sont à consulter.* +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde toutes les destinations d'une instruction. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_instruction_store_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + size_t count; /* Nombre d'éléments à traiter */ + size_t kept; /* Nombre de liens conservés */ + size_t i; /* Boucle de parcours */ + const instr_link_t *link; /* Lien vers une instruction */ + + g_arch_instruction_lock_dest(instr); + + count = g_arch_instruction_count_destinations(instr); + + /** + * Le type de lien ILT_REF n'est mis en place que lors de la création + * d'opérandes de type G_TYPE_TARGET_OPERAND, et sera donc remis en place + * dynamiquement lors de la restauration de ces derniers. + */ + + kept = 0; + + for (i = 0; i < count; i++) + { + link = g_arch_instruction_get_destination(instr, i); + + if (link->type != ILT_REF) + kept++; + + unref_instr_link(link); + + } + + result = pack_uleb128((uleb128_t []){ kept }, pbuf); + + for (i = 0; i < count && result; i++) + { + link = g_arch_instruction_get_destination(instr, i); + + if (link->type != ILT_REF) + { + result = g_object_storage_pack_object(storage, "instructions", + G_SERIALIZABLE_OBJECT(link->linked), pbuf); + + if (result) + result = pack_uleb128((uleb128_t []){ link->type }, pbuf); + + } + + unref_instr_link(link); + + } + + g_arch_instruction_unlock_dest(instr); + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* CONVERSIONS DU FORMAT DES INSTRUCTIONS */ @@ -1787,7 +1969,7 @@ static bool g_arch_instruction_unserialize(GArchInstruction *instr, GAsmStorage * * ******************************************************************************/ -GArchInstruction *g_arch_instruction_load(GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) +GArchInstruction *g_arch_instruction_load__old(GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) { GArchInstruction *result; /* Instance à retourner */ bool status; /* Bilan du chargement */ @@ -1969,7 +2151,7 @@ static bool g_arch_instruction_serialize(GArchInstruction *instr, GAsmStorage *s * * ******************************************************************************/ -bool g_arch_instruction_store(GArchInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf) +bool g_arch_instruction_store__old(GArchInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf) { bool result; /* Bilan à retourner */ @@ -2175,3 +2357,198 @@ static void g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat, content); } + + + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION ET RECHARGEMENT DES DONNEES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un contenu depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool _g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + instr_extra_data_t *extra; /* Données insérées à consulter*/ + uleb128_t value; /* Valeur ULEB128 à charger */ + uleb128_t count; /* Nombre d'éléments à traiter */ + uleb128_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à traiter */ + + extra = GET_ARCH_INSTR_EXTRA(instr); + + LOCK_GOBJECT_EXTRA(extra); + + result = unpack_uleb128(&value, pbuf); + if (!result) goto exit; + + extra->uid = value; + + result = unpack_uleb128(&value, pbuf); + if (!result) goto exit; + + extra->flags = value; + + UNLOCK_GOBJECT_EXTRA(extra); + + result = unpack_mrange(&instr->range, pbuf); + + if (result) + { + result = unpack_uleb128(&count, pbuf); + + for (i = 0; i < count && result; i++) + { + op = G_ARCH_OPERAND(g_object_storage_unpack_object(storage, "operands", pbuf)); + result = (op != NULL); + + if (result) + g_arch_instruction_attach_extra_operand(instr, op); + + } + + } + + if (result) + result = g_arch_instruction_load_destinations(instr, storage, pbuf); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un contenu depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *class; /* Classe à activer */ + + class = G_ARCH_INSTRUCTION_GET_CLASS(instr); + + result = class->load(instr, storage, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un contenu dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool _g_arch_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + instr_extra_data_t *extra; /* Données insérées à consulter*/ + size_t count; /* Nombre d'éléments à traiter */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à traiter */ + + extra = GET_ARCH_INSTR_EXTRA(instr); + + LOCK_GOBJECT_EXTRA(extra); + + result = pack_uleb128((uleb128_t []){ extra->uid }, pbuf); + + if (result) + result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf); + + UNLOCK_GOBJECT_EXTRA(extra); + + if (result) + result = pack_mrange(&instr->range, pbuf); + + if (result) + { + g_arch_instruction_lock_operands(instr); + + count = _g_arch_instruction_count_operands(instr); + + result = pack_uleb128((uleb128_t []){ count }, pbuf); + + for (i = 0; i < count && result; i++) + { + op = _g_arch_instruction_get_operand(instr, i); + + result = g_object_storage_pack_object(storage, "operands", G_SERIALIZABLE_OBJECT(op), pbuf); + + g_object_unref(G_OBJECT(op)); + + } + + g_arch_instruction_unlock_operands(instr); + + } + + if (result) + result = g_arch_instruction_store_destinations(instr, storage, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un contenu dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *class; /* Classe à activer */ + + class = G_ARCH_INSTRUCTION_GET_CLASS(instr); + + result = class->store(instr, storage, pbuf); + + return result; + +} diff --git a/src/arch/instruction.h b/src/arch/instruction.h index a9d66be..683adfb 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -318,10 +318,10 @@ typedef struct _GAsmStorage GAsmStorage; /* Charge une instruction depuis une mémoire tampon. */ -GArchInstruction *g_arch_instruction_load(GAsmStorage *, GBinFormat *, packed_buffer_t *); +GArchInstruction *g_arch_instruction_load__old(GAsmStorage *, GBinFormat *, packed_buffer_t *); /* Sauvegarde une instruction dans une mémoire tampon. */ -bool g_arch_instruction_store(GArchInstruction *, GAsmStorage *, packed_buffer_t *); +bool g_arch_instruction_store__old(GArchInstruction *, GAsmStorage *, packed_buffer_t *); diff --git a/src/arch/instructions/undefined.c b/src/arch/instructions/undefined.c index 663a9eb..7ed5db9 100644 --- a/src/arch/instructions/undefined.c +++ b/src/arch/instructions/undefined.c @@ -74,6 +74,17 @@ static void g_undef_instruction_print(GUndefInstruction *, GBufferLine *, size_t +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Charge un contenu depuis une mémoire tampon. */ +static bool g_undef_instruction_load(GUndefInstruction *, GObjectStorage *, packed_buffer_t *); + +/* Sauvegarde un contenu dans une mémoire tampon. */ +static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, packed_buffer_t *); + + + /* ---------------------------------------------------------------------------------- */ /* INSTRUCTION INCONNUE / DONNEES */ /* ---------------------------------------------------------------------------------- */ @@ -115,6 +126,9 @@ static void g_undef_instruction_class_init(GUndefInstructionClass *klass) instr->print = (print_instruction_fc)g_undef_instruction_print; + instr->load = (load_instruction_fc)g_undef_instruction_load; + instr->store = (store_instruction_fc)g_undef_instruction_store; + } @@ -440,3 +454,93 @@ InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction * return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un contenu depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + undef_extra_data_t *extra; /* Données insérées à consulter*/ + uint8_t val; /* Champ de bits manipulé */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); + + result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf); + + if (result) + { + extra = GET_UNDEF_INSTR_EXTRA(instr); + + LOCK_GOBJECT_EXTRA(extra); + + result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); + extra->behavior = val; + + UNLOCK_GOBJECT_EXTRA(extra); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un contenu dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_undef_instruction_store(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + undef_extra_data_t *extra; /* Données insérées à consulter*/ + + parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); + + result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf); + + if (result) + { + extra = GET_UNDEF_INSTR_EXTRA(instr); + + LOCK_GOBJECT_EXTRA(extra); + + result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false); + + UNLOCK_GOBJECT_EXTRA(extra); + + } + + return result; + +} diff --git a/src/arch/processor.c b/src/arch/processor.c index 1fbc14b..56a45a4 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -1898,7 +1898,7 @@ instr_iter_t *_g_arch_processor_get_covered_iter_from_address(GArchProcessor *pr /****************************************************************************** * * -* Paramètres : content = élément GLib à constuire. * +* Paramètres : proc = élément GLib à constuire. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à lire. * * * @@ -1940,7 +1940,7 @@ static bool g_arch_processor_load(GArchProcessor *proc, GObjectStorage *storage, /****************************************************************************** * * -* Paramètres : content = élément GLib à consulter. * +* Paramètres : proc = élément GLib à consulter. * * storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à remplir. * * * diff --git a/src/arch/storage.c b/src/arch/storage.c index 41fa602..d552ae3 100644 --- a/src/arch/storage.c +++ b/src/arch/storage.c @@ -486,7 +486,7 @@ static void g_ins_caching_process_store(GInsCaching *caching, GtkStatusStack *st instr = g_arch_processor_get_instruction(proc, i); - caching->status = g_arch_instruction_store(instr, storage, &pbuf); + caching->status = g_arch_instruction_store__old(instr, storage, &pbuf); if (caching->status) caching->status = g_asm_storage_store_instruction_data(storage, &pbuf, &pos); @@ -1544,7 +1544,7 @@ GArchInstruction *g_asm_storage_get_instruction_at(GAsmStorage *storage, GBinFor status = g_asm_storage_load_instruction_data(storage, pbuf, target); if (status) - storage->collected[index] = g_arch_instruction_load(storage, format, pbuf); + storage->collected[index] = g_arch_instruction_load__old(storage, format, pbuf); if (storage->collected[index] != NULL) { |