From 0286b53bad21abf91cbe17c4772ca9cde6a89cbc Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 14 May 2018 21:40:07 +0200 Subject: Created an instruction database for Chrysalide. --- configure.ac | 2 +- plugins/arm/core.c | 1 + plugins/arm/instruction-int.h | 1 - plugins/arm/instruction.c | 139 +++ plugins/arm/v7/core.c | 48 + plugins/arm/v7/helpers.h | 8 +- plugins/arm/v7/instruction.c | 106 +++ plugins/arm/v7/instruction.h | 12 +- plugins/arm/v7/operands/Makefile.am | 1 + plugins/arm/v7/operands/coproc.c | 83 ++ plugins/arm/v7/operands/coproc.h | 12 +- plugins/arm/v7/operands/estate.c | 94 ++ plugins/arm/v7/operands/estate.h | 12 +- plugins/arm/v7/operands/limitation.c | 83 ++ plugins/arm/v7/operands/limitation.h | 12 +- plugins/arm/v7/operands/maccess.c | 199 ++++- plugins/arm/v7/operands/maccess.h | 12 +- plugins/arm/v7/operands/offset.c | 114 ++- plugins/arm/v7/operands/offset.h | 12 +- plugins/arm/v7/operands/register.c | 297 +++++++ plugins/arm/v7/operands/register.h | 65 ++ plugins/arm/v7/operands/reglist.c | 112 +++ plugins/arm/v7/operands/reglist.h | 12 +- plugins/arm/v7/operands/rotation.c | 97 ++- plugins/arm/v7/operands/rotation.h | 12 +- plugins/arm/v7/operands/shift.c | 103 ++- plugins/arm/v7/operands/shift.h | 12 +- plugins/arm/v7/post.c | 4 +- plugins/arm/v7/post.h | 1 - plugins/dalvik/core.c | 39 +- plugins/dalvik/operand.c | 2 +- plugins/dalvik/operands/args.c | 108 ++- plugins/dalvik/operands/args.h | 12 +- plugins/dalvik/operands/pool.c | 99 ++- plugins/dalvik/operands/register.c | 156 ++-- plugins/dalvik/operands/register.h | 6 - plugins/dalvik/register.h | 12 +- plugins/dalvik/v35/Makefile.am | 1 + plugins/dalvik/v35/core.c | 99 +++ plugins/dalvik/v35/core.h | 40 + src/analysis/binary.c | 55 +- src/analysis/binary.h | 3 + src/analysis/disass/disassembler.c | 60 +- src/analysis/disass/fetch.c | 5 +- src/arch/Makefile.am | 1 + src/arch/immediate.c | 107 +++ src/arch/immediate.h | 12 +- src/arch/instruction-int.h | 9 + src/arch/instruction.c | 335 ++++++- src/arch/instruction.h | 17 +- src/arch/operand-int.h | 9 + src/arch/operand.c | 200 ++++- src/arch/operand.h | 29 +- src/arch/post.c | 2 +- src/arch/raw.c | 121 +++ src/arch/register.c | 79 ++ src/arch/register.h | 24 +- src/arch/storage.c | 1593 ++++++++++++++++++++++++++++++++++ src/arch/storage.h | 104 +++ src/arch/target.c | 104 +++ src/arch/target.h | 13 +- src/arch/undefined.c | 95 ++ src/arch/undefined.h | 12 +- src/arch/vmpa.c | 58 +- src/arch/vmpa.h | 10 +- src/common/packed.c | 19 + src/common/packed.h | 3 + src/core/core.c | 2 + src/core/processors.c | 28 + src/core/processors.h | 2 + src/core/queue.c | 12 +- src/core/queue.h | 3 +- src/main.c | 73 +- 73 files changed, 5205 insertions(+), 234 deletions(-) create mode 100644 plugins/arm/v7/operands/register.c create mode 100644 plugins/arm/v7/operands/register.h create mode 100644 plugins/dalvik/v35/core.c create mode 100644 plugins/dalvik/v35/core.h create mode 100644 src/arch/storage.c create mode 100644 src/arch/storage.h diff --git a/configure.ac b/configure.ac index b919cb4..5c3c0e8 100644 --- a/configure.ac +++ b/configure.ac @@ -158,7 +158,7 @@ AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [compile with debugging su #--- Small enumerations -CFLAGS="$CFLAGS -fshort-enums" +CFLAGS="$CFLAGS -fshort-enums -D_LARGEFILE64_SOURCE" AC_SUBST(CFLAGS) diff --git a/plugins/arm/core.c b/plugins/arm/core.c index 43e82e4..6a512b2 100644 --- a/plugins/arm/core.c +++ b/plugins/arm/core.c @@ -62,6 +62,7 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) } + /****************************************************************************** * * * Paramètres : plugin = greffon à manipuler. * diff --git a/plugins/arm/instruction-int.h b/plugins/arm/instruction-int.h index 2b559a9..ffa10ee 100644 --- a/plugins/arm/instruction-int.h +++ b/plugins/arm/instruction-int.h @@ -37,7 +37,6 @@ struct _GArmInstruction { GArchInstruction parent; /* A laisser en premier */ - const char *keyword; /* Nom clef de l'instruction */ char *suffix; /* Complément au nom affiché */ char *cached_keyword; /* Désignation complète */ diff --git a/plugins/arm/instruction.c b/plugins/arm/instruction.c index 9af8045..a717055 100644 --- a/plugins/arm/instruction.c +++ b/plugins/arm/instruction.c @@ -30,6 +30,7 @@ #include +#include #include "instruction-int.h" @@ -50,6 +51,17 @@ static void g_arm_instruction_finalize(GArmInstruction *); +/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ + + +/* Charge une instruction depuis une mémoire tampon. */ +static bool g_arm_instruction_unserialize(GArmInstruction *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde une instruction dans une mémoire tampon. */ +static bool g_arm_instruction_serialize(GArmInstruction *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini pour une représentation d'une instruction ARM. */ G_DEFINE_TYPE(GArmInstruction, g_arm_instruction, G_TYPE_ARCH_INSTRUCTION); @@ -69,12 +81,18 @@ G_DEFINE_TYPE(GArmInstruction, g_arm_instruction, G_TYPE_ARCH_INSTRUCTION); static void g_arm_instruction_class_init(GArmInstructionClass *klass) { GObjectClass *object_class; /* Autre version de la classe */ + GArchInstructionClass *instr; /* Encore une autre vision... */ object_class = G_OBJECT_CLASS(klass); object_class->dispose = (GObjectFinalizeFunc/* ! */)g_arm_instruction_dispose; object_class->finalize = (GObjectFinalizeFunc)g_arm_instruction_finalize; + instr = G_ARCH_INSTRUCTION_CLASS(klass); + + instr->unserialize = (unserialize_instruction_fc)g_arm_instruction_unserialize; + instr->serialize = (serialize_instruction_fc)g_arm_instruction_serialize; + } @@ -92,6 +110,9 @@ static void g_arm_instruction_class_init(GArmInstructionClass *klass) static void g_arm_instruction_init(GArmInstruction *instr) { + instr->suffix = NULL; + instr->cached_keyword = NULL; + instr->cond = ACC_AL; } @@ -243,3 +264,121 @@ ArmCondCode g_arm_instruction_get_cond(const GArmInstruction *instr) return instr->cond; } + + + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge une instruction depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arm_instruction_unserialize(GArmInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + unsigned char len; /* Taille de textes */ + char *text; /* Texte reconstitué */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_arm_instruction_parent_class); + + result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf); + + if (result) + { + result = extract_packed_buffer(pbuf, &len, sizeof(unsigned char), false); + + if (result && len > 0) + { + text = (char *)malloc(len); + + if (result) + result = extract_packed_buffer(pbuf, text, len, false); + + if (result) + result = g_arm_instruction_extend_keyword(instr, text); + + free(text); + + } + + } + + if (result) + result = extract_packed_buffer(pbuf, &instr->cond, sizeof(ArmCondCode), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde une instruction dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arm_instruction_serialize(GArmInstruction *instr, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + size_t len; /* Taille de textes */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_arm_instruction_parent_class); + + result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf); + + if (result) + { + if (instr->suffix == NULL) + result = extend_packed_buffer(pbuf, (unsigned char []) { 0 }, sizeof(unsigned char), false); + + else + { + len = strlen(instr->suffix) + 1; + assert(len > 1); + + if (len > (2 << (sizeof(unsigned char) * 8 - 1))) + { + log_variadic_message(LMT_ERROR, "ARM suffix too long: '%s' (%zu bytes)", instr->suffix, len); + result = false; + } + + else + result = extend_packed_buffer(pbuf, (unsigned char []) { len }, sizeof(unsigned char), false); + + if (result) + result = extend_packed_buffer(pbuf, instr->suffix, len, false); + + } + + } + + if (result) + result = extend_packed_buffer(pbuf, &instr->cond, sizeof(ArmCondCode), true); + + return result; + +} diff --git a/plugins/arm/v7/core.c b/plugins/arm/v7/core.c index 4de61a2..9b4d3f3 100644 --- a/plugins/arm/v7/core.c +++ b/plugins/arm/v7/core.c @@ -25,10 +25,56 @@ #include + + #include "cregister.h" +#include "instruction.h" #include "processor.h" #include "register.h" +#include "operands/coproc.h" +#include "operands/estate.h" +#include "operands/limitation.h" +#include "operands/maccess.h" +#include "operands/offset.h" +#include "operands/register.h" +#include "operands/reglist.h" +#include "operands/rotation.h" +#include "operands/shift.h" + + + +/* Assure l'enregistrement de types pour les caches à charger. */ +static void register_armv7_gtypes(void); + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Assure l'enregistrement de types pour les caches à charger. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ +static void register_armv7_gtypes(void) +{ + g_type_ensure(G_TYPE_ARMV7_INSTRUCTION); + + g_type_ensure(G_TYPE_ARMV7_COPROC_OPERAND); + g_type_ensure(G_TYPE_ARMV7_ENDIAN_OPERAND); + g_type_ensure(G_TYPE_ARMV7_LIMITATION_OPERAND); + g_type_ensure(G_TYPE_ARMV7_MACCESS_OPERAND); + g_type_ensure(G_TYPE_ARMV7_OFFSET_OPERAND); + g_type_ensure(G_TYPE_ARMV7_REGISTER_OPERAND); + g_type_ensure(G_TYPE_ARMV7_REGLIST_OPERAND); + g_type_ensure(G_TYPE_ARMV7_ROTATION_OPERAND); + g_type_ensure(G_TYPE_ARMV7_SHIFT_OPERAND); + +} /****************************************************************************** @@ -47,6 +93,8 @@ bool init_armv7_core(void) { bool result; /* Bilan à renvoyer */ + register_armv7_gtypes(); + result = register_processor_type("armv7", "ARM v7", G_TYPE_ARMV7_PROCESSOR); return result; diff --git a/plugins/arm/v7/helpers.h b/plugins/arm/v7/helpers.h index cb32785..ae759b8 100644 --- a/plugins/arm/v7/helpers.h +++ b/plugins/arm/v7/helpers.h @@ -26,7 +26,6 @@ #include -#include #include "pseudo.h" @@ -34,6 +33,7 @@ #include "operands/coproc.h" #include "operands/estate.h" #include "operands/maccess.h" +#include "operands/register.h" #include "operands/reglist.h" #include "operands/rotation.h" #include "operands/shift.h" @@ -212,7 +212,7 @@ if (__reg == NULL) \ __result = NULL; \ else \ - __result = g_register_operand_new(G_ARCH_REGISTER(__reg)); \ + __result = g_armv7_register_operand_new(__reg); \ __result; \ }) @@ -245,7 +245,7 @@ if (__reg == NULL) \ __result = NULL; \ else \ - __result = g_register_operand_new(G_ARCH_REGISTER(__reg)); \ + __result = g_armv7_register_operand_new(__reg); \ __result; \ }) @@ -383,7 +383,7 @@ if (__reg == NULL) \ __result = NULL; \ else \ - __result = g_register_operand_new(G_ARCH_REGISTER(__reg)); \ + __result = g_armv7_register_operand_new(__reg); \ __result; \ #endif diff --git a/plugins/arm/v7/instruction.c b/plugins/arm/v7/instruction.c index d45979b..9eb43ac 100644 --- a/plugins/arm/v7/instruction.c +++ b/plugins/arm/v7/instruction.c @@ -86,6 +86,17 @@ static char *g_armv7_instruction_build_tooltip(const GArmV7Instruction *); +/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ + + +/* Charge une instruction depuis une mémoire tampon. */ +static bool g_armv7_instruction_unserialize(GArmV7Instruction *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde une instruction dans une mémoire tampon. */ +static bool g_armv7_instruction_serialize(GArmV7Instruction *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini pour une représentation d'une instruction ARMv7. */ G_DEFINE_TYPE(GArmV7Instruction, g_armv7_instruction, G_TYPE_ARM_INSTRUCTION); @@ -118,6 +129,9 @@ static void g_armv7_instruction_class_init(GArmV7InstructionClass *klass) instr->call_hook = (call_instruction_hook_fc)g_armv7_instruction_call_hook; instr->build_tooltip = (build_instruction_tooltip_fc)g_armv7_instruction_build_tooltip; + instr->unserialize = (unserialize_instruction_fc)g_armv7_instruction_unserialize; + instr->serialize = (serialize_instruction_fc)g_armv7_instruction_serialize; + } @@ -397,3 +411,95 @@ bool g_armv7_instruction_get_setflags(const GArmV7Instruction *instr) return instr->setflags; } + + + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge une instruction depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_instruction_unserialize(GArmV7Instruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + uint8_t boolean; /* Valeur booléenne */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_armv7_instruction_parent_class); + + result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, &instr->sid, sizeof(ARMv7Syntax), true); + + if (result) + result = extract_packed_buffer(pbuf, &instr->encoding, sizeof(char), false); + + if (result) + { + result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + + if (result) + instr->setflags = (boolean == 1 ? true : false); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde une instruction dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_instruction_serialize(GArmV7Instruction *instr, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + uint8_t boolean; /* Valeur booléenne */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_armv7_instruction_parent_class); + + result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &instr->sid, sizeof(ARMv7Syntax), true); + + if (result) + result = extend_packed_buffer(pbuf, &instr->encoding, sizeof(char), false); + + if (result) + { + boolean = (instr->setflags ? 1 : 0); + result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + } + + return result; + +} diff --git a/plugins/arm/v7/instruction.h b/plugins/arm/v7/instruction.h index c75b71d..4315d9f 100644 --- a/plugins/arm/v7/instruction.h +++ b/plugins/arm/v7/instruction.h @@ -37,12 +37,12 @@ -#define G_TYPE_ARMV7_INSTRUCTION g_armv7_instruction_get_type() -#define G_ARMV7_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_instruction_get_type(), GArmV7Instruction)) -#define G_IS_ARMV7_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_instruction_get_type())) -#define G_ARMV7_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_INSTRUCTION, GArmV7InstructionClass)) -#define G_IS_ARMV7_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_INSTRUCTION)) -#define G_ARMV7_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_INSTRUCTION, GArmV7InstructionClass)) +#define G_TYPE_ARMV7_INSTRUCTION g_armv7_instruction_get_type() +#define G_ARMV7_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_INSTRUCTION, GArmV7Instruction)) +#define G_IS_ARMV7_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_INSTRUCTION)) +#define G_ARMV7_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_INSTRUCTION, GArmV7InstructionClass)) +#define G_IS_ARMV7_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_INSTRUCTION)) +#define G_ARMV7_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_INSTRUCTION, GArmV7InstructionClass)) /* Définition d'une instruction d'architecture ARMv7 (instance) */ diff --git a/plugins/arm/v7/operands/Makefile.am b/plugins/arm/v7/operands/Makefile.am index eca891c..7ba6d0a 100644 --- a/plugins/arm/v7/operands/Makefile.am +++ b/plugins/arm/v7/operands/Makefile.am @@ -7,6 +7,7 @@ libarmv7operands_la_SOURCES = \ limitation.h limitation.c \ maccess.h maccess.c \ offset.h offset.c \ + register.h register.c \ reglist.h reglist.c \ rotation.h rotation.c \ shift.h shift.c diff --git a/plugins/arm/v7/operands/coproc.c b/plugins/arm/v7/operands/coproc.c index 26c76d0..021aa65 100644 --- a/plugins/arm/v7/operands/coproc.c +++ b/plugins/arm/v7/operands/coproc.c @@ -67,6 +67,17 @@ static void g_armv7_coproc_operand_print(const GArmV7CoprocOperand *, GBufferLin +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_coproc_operand_unserialize(GArmV7CoprocOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_coproc_operand_serialize(const GArmV7CoprocOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour un co-processeur ARM. */ G_DEFINE_TYPE(GArmV7CoprocOperand, g_armv7_coproc_operand, G_TYPE_ARCH_OPERAND); @@ -97,6 +108,9 @@ static void g_armv7_coproc_operand_class_init(GArmV7CoprocOperandClass *klass) operand->compare = (operand_compare_fc)g_armv7_coproc_operand_compare; operand->print = (operand_print_fc)g_armv7_coproc_operand_print; + operand->unserialize = (unserialize_operand_fc)g_armv7_coproc_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_coproc_operand_serialize; + } @@ -248,3 +262,72 @@ uint8_t g_armv7_coproc_operand_get_index(const GArmV7CoprocOperand *operand) return operand->index; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_coproc_operand_unserialize(GArmV7CoprocOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_coproc_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, &operand->index, sizeof(uint8_t), false); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_coproc_operand_serialize(const GArmV7CoprocOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_coproc_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &operand->index, sizeof(uint8_t), false); + + return result; + +} diff --git a/plugins/arm/v7/operands/coproc.h b/plugins/arm/v7/operands/coproc.h index e203f2c..3e40d04 100644 --- a/plugins/arm/v7/operands/coproc.h +++ b/plugins/arm/v7/operands/coproc.h @@ -32,12 +32,12 @@ -#define G_TYPE_ARMV7_COPROC_OPERAND g_armv7_coproc_operand_get_type() -#define G_ARMV7_COPROC_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_coproc_operand_get_type(), GArmV7CoprocOperand)) -#define G_IS_ARMV7_COPROC_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_coproc_operand_get_type())) -#define G_ARMV7_COPROC_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_COPROC_OPERAND, GArmV7CoprocOperandClass)) -#define G_IS_ARMV7_COPROC_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_COPROC_OPERAND)) -#define G_ARMV7_COPROC_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_COPROC_OPERAND, GArmV7CoprocOperandClass)) +#define G_TYPE_ARMV7_COPROC_OPERAND g_armv7_coproc_operand_get_type() +#define G_ARMV7_COPROC_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_COPROC_OPERAND, GArmV7CoprocOperand)) +#define G_IS_ARMV7_COPROC_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_COPROC_OPERAND)) +#define G_ARMV7_COPROC_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_COPROC_OPERAND, GArmV7CoprocOperandClass)) +#define G_IS_ARMV7_COPROC_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_COPROC_OPERAND)) +#define G_ARMV7_COPROC_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_COPROC_OPERAND, GArmV7CoprocOperandClass)) /* Définition d'un opérande représentant un co-processeur (instance) */ diff --git a/plugins/arm/v7/operands/estate.c b/plugins/arm/v7/operands/estate.c index 3302f30..472ac2b 100644 --- a/plugins/arm/v7/operands/estate.c +++ b/plugins/arm/v7/operands/estate.c @@ -67,6 +67,17 @@ static void g_armv7_endian_operand_print(const GArmV7EndianOperand *, GBufferLin +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_endian_operand_unserialize(GArmV7EndianOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_endian_operand_serialize(const GArmV7EndianOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour une endian de domaine et d'accès. */ G_DEFINE_TYPE(GArmV7EndianOperand, g_armv7_endian_operand, G_TYPE_ARCH_OPERAND); @@ -97,6 +108,9 @@ static void g_armv7_endian_operand_class_init(GArmV7EndianOperandClass *klass) operand->compare = (operand_compare_fc)g_armv7_endian_operand_compare; operand->print = (operand_print_fc)g_armv7_endian_operand_print; + operand->unserialize = (unserialize_operand_fc)g_armv7_endian_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_endian_operand_serialize; + } @@ -246,3 +260,83 @@ bool g_armv7_endian_operand_is_big_endian(const GArmV7EndianOperand *operand) return operand->big; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_endian_operand_unserialize(GArmV7EndianOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + uint8_t big; /* Grand boutisme à afficher ? */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_endian_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + { + result = extract_packed_buffer(pbuf, &big, sizeof(uint8_t), false); + + if (result) + operand->big = (big == 1 ? true : false); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_endian_operand_serialize(const GArmV7EndianOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + uint8_t big; /* Grand boutisme à afficher ? */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_endian_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + { + big = (operand->big ? 1 : 0); + result = extend_packed_buffer(pbuf, &big, sizeof(uint8_t), false); + } + + return result; + +} diff --git a/plugins/arm/v7/operands/estate.h b/plugins/arm/v7/operands/estate.h index fae3188..6a1e371 100644 --- a/plugins/arm/v7/operands/estate.h +++ b/plugins/arm/v7/operands/estate.h @@ -32,12 +32,12 @@ -#define G_TYPE_ARMV7_ENDIAN_OPERAND g_armv7_endian_operand_get_type() -#define G_ARMV7_ENDIAN_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_endian_operand_get_type(), GArmV7EndianOperand)) -#define G_IS_ARMV7_ENDIAN_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_endian_operand_get_type())) -#define G_ARMV7_ENDIAN_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_ENDIAN_OPERAND, GArmV7EndianOperandClass)) -#define G_IS_ARMV7_ENDIAN_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_ENDIAN_OPERAND)) -#define G_ARMV7_ENDIAN_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_ENDIAN_OPERAND, GArmV7EndianOperandClass)) +#define G_TYPE_ARMV7_ENDIAN_OPERAND g_armv7_endian_operand_get_type() +#define G_ARMV7_ENDIAN_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_ENDIAN_OPERAND, GArmV7EndianOperand)) +#define G_IS_ARMV7_ENDIAN_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_ENDIAN_OPERAND)) +#define G_ARMV7_ENDIAN_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_ENDIAN_OPERAND, GArmV7EndianOperandClass)) +#define G_IS_ARMV7_ENDIAN_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_ENDIAN_OPERAND)) +#define G_ARMV7_ENDIAN_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_ENDIAN_OPERAND, GArmV7EndianOperandClass)) /* Définition d'un opérande affichant le choix d'un boutisme (instance) */ diff --git a/plugins/arm/v7/operands/limitation.c b/plugins/arm/v7/operands/limitation.c index 22ca1c0..6ed32fb 100644 --- a/plugins/arm/v7/operands/limitation.c +++ b/plugins/arm/v7/operands/limitation.c @@ -67,6 +67,17 @@ static void g_armv7_limitation_operand_print(const GArmV7LimitationOperand *, GB +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_limitation_operand_unserialize(GArmV7LimitationOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_limitation_operand_serialize(const GArmV7LimitationOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour une limitation de domaine et d'accès. */ G_DEFINE_TYPE(GArmV7LimitationOperand, g_armv7_limitation_operand, G_TYPE_ARCH_OPERAND); @@ -97,6 +108,9 @@ static void g_armv7_limitation_operand_class_init(GArmV7LimitationOperandClass * operand->compare = (operand_compare_fc)g_armv7_limitation_operand_compare; operand->print = (operand_print_fc)g_armv7_limitation_operand_print; + operand->unserialize = (unserialize_operand_fc)g_armv7_limitation_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_limitation_operand_serialize; + } @@ -285,3 +299,72 @@ BarrierLimitationType g_armv7_limitation_operand_get_value(const GArmV7Limitatio return operand->type; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_limitation_operand_unserialize(GArmV7LimitationOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_limitation_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, &operand->type, sizeof(BarrierLimitationType), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_limitation_operand_serialize(const GArmV7LimitationOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_limitation_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &operand->type, sizeof(BarrierLimitationType), true); + + return result; + +} diff --git a/plugins/arm/v7/operands/limitation.h b/plugins/arm/v7/operands/limitation.h index 47f38ff..e9c1617 100644 --- a/plugins/arm/v7/operands/limitation.h +++ b/plugins/arm/v7/operands/limitation.h @@ -32,12 +32,12 @@ -#define G_TYPE_ARMV7_LIMITATION_OPERAND g_armv7_limitation_operand_get_type() -#define G_ARMV7_LIMITATION_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_limitation_operand_get_type(), GArmV7LimitationOperand)) -#define G_IS_ARMV7_LIMITATION_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_limitation_operand_get_type())) -#define G_ARMV7_LIMITATION_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_LIMITATION_OPERAND, GArmV7LimitationOperandClass)) -#define G_IS_ARMV7_LIMITATION_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_LIMITATION_OPERAND)) -#define G_ARMV7_LIMITATION_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_LIMITATION_OPERAND, GArmV7LimitationOperandClass)) +#define G_TYPE_ARMV7_LIMITATION_OPERAND g_armv7_limitation_operand_get_type() +#define G_ARMV7_LIMITATION_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_LIMITATION_OPERAND, GArmV7LimitationOperand)) +#define G_IS_ARMV7_LIMITATION_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_LIMITATION_OPERAND)) +#define G_ARMV7_LIMITATION_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_LIMITATION_OPERAND, GArmV7LimitationOperandClass)) +#define G_IS_ARMV7_LIMITATION_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_LIMITATION_OPERAND)) +#define G_ARMV7_LIMITATION_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_LIMITATION_OPERAND, GArmV7LimitationOperandClass)) /* Définition d'un opérande déterminant une limitation de domaine et d'accès (instance) */ diff --git a/plugins/arm/v7/operands/maccess.c b/plugins/arm/v7/operands/maccess.c index a21921f..5359527 100644 --- a/plugins/arm/v7/operands/maccess.c +++ b/plugins/arm/v7/operands/maccess.c @@ -71,6 +71,17 @@ static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *, GBufferL +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_maccess_operand_unserialize(GArmV7MAccessOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_maccess_operand_serialize(const GArmV7MAccessOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour un accès à la mémoire depuis une base. */ G_DEFINE_TYPE(GArmV7MAccessOperand, g_armv7_maccess_operand, G_TYPE_ARCH_OPERAND); @@ -101,6 +112,9 @@ static void g_armv7_maccess_operand_class_init(GArmV7MAccessOperandClass *klass) operand->compare = (operand_compare_fc)g_armv7_maccess_operand_compare; operand->print = (operand_print_fc)g_armv7_maccess_operand_print; + operand->unserialize = (unserialize_operand_fc)g_armv7_maccess_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_maccess_operand_serialize; + } @@ -118,6 +132,9 @@ static void g_armv7_maccess_operand_class_init(GArmV7MAccessOperandClass *klass) static void g_armv7_maccess_operand_init(GArmV7MAccessOperand *operand) { + operand->base = NULL; + operand->offset = NULL; + operand->shift = NULL; } @@ -136,7 +153,8 @@ static void g_armv7_maccess_operand_init(GArmV7MAccessOperand *operand) static void g_armv7_maccess_operand_dispose(GArmV7MAccessOperand *operand) { - g_object_unref(G_OBJECT(operand->base)); + if (operand->base != NULL) + g_object_unref(G_OBJECT(operand->base)); if (operand->offset != NULL) g_object_unref(G_OBJECT(operand->offset)); @@ -383,3 +401,182 @@ bool g_armv7_maccess_operand_has_to_write_back(const GArmV7MAccessOperand *opera return operand->write_back; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_maccess_operand_unserialize(GArmV7MAccessOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + GArchOperand *subop; /* Sous-opérande à intégrer */ + uint8_t boolean; /* Valeur booléenne */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + { + subop = g_arch_operand_load(storage, format, pbuf); + + if (subop == NULL) + result = false; + + else + operand->base = subop; + + } + + if (result) + { + result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + + if (result && boolean == 1) + { + subop = g_arch_operand_load(storage, format, pbuf); + + if (subop == NULL) + result = false; + + else + operand->offset = subop; + + } + + } + + if (result) + { + result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + + if (result && boolean == 1) + { + subop = g_arch_operand_load(storage, format, pbuf); + + if (subop == NULL) + result = false; + + else + operand->shift = subop; + + } + + } + + if (result) + { + result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + + if (result) + operand->post_indexed = (boolean == 1 ? true : false); + + } + + if (result) + { + result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + + if (result) + operand->write_back = (boolean == 1 ? true : false); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_maccess_operand_serialize(const GArmV7MAccessOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + uint8_t boolean; /* Valeur booléenne */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = g_arch_operand_store(operand->base, storage, pbuf); + + if (result) + { + if (operand->offset == NULL) + result = extend_packed_buffer(pbuf, (uint8_t []) { 0 }, sizeof(uint8_t), false); + + else + { + result = extend_packed_buffer(pbuf, (uint8_t []) { 1 }, sizeof(uint8_t), false); + + if (result) + result = g_arch_operand_store(operand->offset, storage, pbuf); + + } + + } + + if (result) + { + if (operand->shift == NULL) + result = extend_packed_buffer(pbuf, (uint8_t []) { 0 }, sizeof(uint8_t), false); + + else + { + result = extend_packed_buffer(pbuf, (uint8_t []) { 1 }, sizeof(uint8_t), false); + + if (result) + result = g_arch_operand_store(operand->shift, storage, pbuf); + + } + + } + + if (result) + { + boolean = (operand->post_indexed ? 1 : 0); + result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + } + + if (result) + { + boolean = (operand->write_back ? 1 : 0); + result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + } + + return result; + +} diff --git a/plugins/arm/v7/operands/maccess.h b/plugins/arm/v7/operands/maccess.h index c2b11da..f9668c2 100644 --- a/plugins/arm/v7/operands/maccess.h +++ b/plugins/arm/v7/operands/maccess.h @@ -36,12 +36,12 @@ -#define G_TYPE_ARMV7_MACCESS_OPERAND g_armv7_maccess_operand_get_type() -#define G_ARMV7_MACCESS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_maccess_operand_get_type(), GArmV7MAccessOperand)) -#define G_IS_ARMV7_MACCESS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_maccess_operand_get_type())) -#define G_ARMV7_MACCESS_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_MACCESS_OPERAND, GArmV7MAccessOperandClass)) -#define G_IS_ARMV7_MACCESS_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_MACCESS_OPERAND)) -#define G_ARMV7_MACCESS_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_MACCESS_OPERAND, GArmV7MAccessOperandClass)) +#define G_TYPE_ARMV7_MACCESS_OPERAND g_armv7_maccess_operand_get_type() +#define G_ARMV7_MACCESS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_MACCESS_OPERAND, GArmV7MAccessOperand)) +#define G_IS_ARMV7_MACCESS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_MACCESS_OPERAND)) +#define G_ARMV7_MACCESS_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_MACCESS_OPERAND, GArmV7MAccessOperandClass)) +#define G_IS_ARMV7_MACCESS_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_MACCESS_OPERAND)) +#define G_ARMV7_MACCESS_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_MACCESS_OPERAND, GArmV7MAccessOperandClass)) /* Définition d'un opérande offrant un accès à la mémoire depuis une base (instance) */ diff --git a/plugins/arm/v7/operands/offset.c b/plugins/arm/v7/operands/offset.c index 10c7cb5..ffa3fac 100644 --- a/plugins/arm/v7/operands/offset.c +++ b/plugins/arm/v7/operands/offset.c @@ -68,6 +68,17 @@ static void g_armv7_offset_operand_print(const GArmV7OffsetOperand *, GBufferLin +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_offset_operand_unserialize(GArmV7OffsetOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_offset_operand_serialize(const GArmV7OffsetOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour un décalage relatif ARMv7. */ G_DEFINE_TYPE(GArmV7OffsetOperand, g_armv7_offset_operand, G_TYPE_ARCH_OPERAND); @@ -98,6 +109,9 @@ static void g_armv7_offset_operand_class_init(GArmV7OffsetOperandClass *klass) operand->compare = (operand_compare_fc)g_armv7_offset_operand_compare; operand->print = (operand_print_fc)g_armv7_offset_operand_print; + operand->unserialize = (unserialize_operand_fc)g_armv7_offset_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_offset_operand_serialize; + } @@ -115,6 +129,7 @@ static void g_armv7_offset_operand_class_init(GArmV7OffsetOperandClass *klass) static void g_armv7_offset_operand_init(GArmV7OffsetOperand *operand) { + operand->value = NULL; } @@ -133,7 +148,8 @@ static void g_armv7_offset_operand_init(GArmV7OffsetOperand *operand) static void g_armv7_offset_operand_dispose(GArmV7OffsetOperand *operand) { - g_object_unref(G_OBJECT(operand->value)); + if (operand->value != NULL) + g_object_unref(G_OBJECT(operand->value)); G_OBJECT_CLASS(g_armv7_offset_operand_parent_class)->dispose(G_OBJECT(operand)); @@ -281,3 +297,99 @@ GArchOperand *g_armv7_offset_operand_get_value(const GArmV7OffsetOperand *operan return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_offset_operand_unserialize(GArmV7OffsetOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + GArchOperand *value; /* Valeur à intégrer */ + uint8_t positive; /* Sens du décalage */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_offset_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + { + value = g_arch_operand_load(storage, format, pbuf); + + if (value == NULL) + result = false; + + else + operand->value = value; + + } + + if (result) + { + result = extract_packed_buffer(pbuf, &positive, sizeof(uint8_t), false); + + if (result) + operand->positive = (positive == 1 ? true : false); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_offset_operand_serialize(const GArmV7OffsetOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + uint8_t positive; /* Sens du décalage */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_offset_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + { + positive = (operand->positive ? 1 : 0); + result = extend_packed_buffer(pbuf, &positive, sizeof(uint8_t), false); + } + + if (result) + result = g_arch_operand_store(operand->value, storage, pbuf); + + return result; + +} diff --git a/plugins/arm/v7/operands/offset.h b/plugins/arm/v7/operands/offset.h index 18b626d..88c80a9 100644 --- a/plugins/arm/v7/operands/offset.h +++ b/plugins/arm/v7/operands/offset.h @@ -36,12 +36,12 @@ -#define G_TYPE_ARMV7_OFFSET_OPERAND g_armv7_offset_operand_get_type() -#define G_ARMV7_OFFSET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_offset_operand_get_type(), GArmV7OffsetOperand)) -#define G_IS_ARMV7_OFFSET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_offset_operand_get_type())) -#define G_ARMV7_OFFSET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_OFFSET_OPERAND, GArmV7OffsetOperandClass)) -#define G_IS_ARMV7_OFFSET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_OFFSET_OPERAND)) -#define G_ARMV7_OFFSET_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_OFFSET_OPERAND, GArmV7OffsetOperandClass)) +#define G_TYPE_ARMV7_OFFSET_OPERAND g_armv7_offset_operand_get_type() +#define G_ARMV7_OFFSET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_OFFSET_OPERAND, GArmV7OffsetOperand)) +#define G_IS_ARMV7_OFFSET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_OFFSET_OPERAND)) +#define G_ARMV7_OFFSET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_OFFSET_OPERAND, GArmV7OffsetOperandClass)) +#define G_IS_ARMV7_OFFSET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_OFFSET_OPERAND)) +#define G_ARMV7_OFFSET_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_OFFSET_OPERAND, GArmV7OffsetOperandClass)) /* Définition d'un opérande visant à constituer un décalage relatif ARMv7 (instance) */ diff --git a/plugins/arm/v7/operands/register.c b/plugins/arm/v7/operands/register.c new file mode 100644 index 0000000..33a14f6 --- /dev/null +++ b/plugins/arm/v7/operands/register.c @@ -0,0 +1,297 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register.c - opérandes visant un registre ARMv7 + * + * Copyright (C) 2010-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#include "register.h" + + +#include + + +#include "../../register.h" + + + +/* Définition d'un opérande visant un registre ARMv7 (instance) */ +struct _GArmV7RegisterOperand +{ + GRegisterOperand parent; /* Instance parente */ + +}; + + +/* Définition d'un opérande visant un registre ARMv7 (classe) */ +struct _GArmV7RegisterOperandClass +{ + GRegisterOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes de registre ARMv7. */ +static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *); + +/* Initialise une instance d'opérande de registre ARMv7. */ +static void g_armv7_register_operand_init(GArmV7RegisterOperand *); + +/* Supprime toutes les références externes. */ +static void g_armv7_register_operand_dispose(GArmV7RegisterOperand *); + +/* Procède à la libération totale de la mémoire. */ +static void g_armv7_register_operand_finalize(GArmV7RegisterOperand *); + + + +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_register_operand_serialize(const GArmV7RegisterOperand *, GAsmStorage *, packed_buffer *); + + + +/* Indique le type défini par la GLib pour un opérande de registre ARMv7. */ +G_DEFINE_TYPE(GArmV7RegisterOperand, g_armv7_register_operand, G_TYPE_REGISTER_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes de registre ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GArchOperandClass *operand; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_register_operand_dispose; + object->finalize = (GObjectFinalizeFunc)g_armv7_register_operand_finalize; + + operand = G_ARCH_OPERAND_CLASS(klass); + + operand->unserialize = (unserialize_operand_fc)g_armv7_register_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_register_operand_serialize; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande de registre ARMv7. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_register_operand_init(GArmV7RegisterOperand *operand) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_register_operand_dispose(GArmV7RegisterOperand *operand) +{ + G_OBJECT_CLASS(g_armv7_register_operand_parent_class)->dispose(G_OBJECT(operand)); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_register_operand_finalize(GArmV7RegisterOperand *operand) +{ + G_OBJECT_CLASS(g_armv7_register_operand_parent_class)->finalize(G_OBJECT(operand)); + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre déjà en place. * +* * +* Description : Crée un opérande visant un registre ARMv7. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_armv7_register_operand_new(GArmV7Register *reg) +{ + GArmV7RegisterOperand *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ARMV7_REGISTER_OPERAND, NULL); + + G_REGISTER_OPERAND(result)->reg = G_ARCH_REGISTER(reg); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande représentant un registre. * +* * +* Description : Fournit le registre ARMv7 associé à l'opérande. * +* * +* Retour : Représentation interne du registre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const GArmV7Register *g_armv7_register_operand_get(const GArmV7RegisterOperand *operand) +{ + GArmV7Register *result; /* Instance à retourner */ + + result = G_ARMV7_REGISTER(G_REGISTER_OPERAND(operand)->reg); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + uint8_t index; /* Identifiant de registre */ + GArmV7Register *reg; /* Registre à intégrer */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + { + result = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + + if (result) + { + reg = g_armv7_register_new(index); + result = (reg != NULL); + } + + if (result) + G_REGISTER_OPERAND(operand)->reg = G_ARCH_REGISTER(reg); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_register_operand_serialize(const GArmV7RegisterOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + uint8_t index; /* Identifiant de registre */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + { + index = g_arm_register_get_index(G_ARM_REGISTER(G_REGISTER_OPERAND(operand)->reg)); + result = extend_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + } + + return result; + +} diff --git a/plugins/arm/v7/operands/register.h b/plugins/arm/v7/operands/register.h new file mode 100644 index 0000000..61f5d6e --- /dev/null +++ b/plugins/arm/v7/operands/register.h @@ -0,0 +1,65 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register.h - prototypes pour les opérandes visant un registre ARMv7 + * + * Copyright (C) 2010-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#ifndef _PLUGINS_ARM_V7_OPERANDS_REGISTER_H +#define _PLUGINS_ARM_V7_OPERANDS_REGISTER_H + + +#include +#include + + +#include + + +#include "../register.h" + + + +#define G_TYPE_ARMV7_REGISTER_OPERAND g_armv7_register_operand_get_type() +#define G_ARMV7_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_REGISTER_OPERAND, GArmV7RegisterOperand)) +#define G_IS_ARMV7_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_REGISTER_OPERAND)) +#define G_ARMV7_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_REGISTER_OPERAND, GArmV7RegisterOperandClass)) +#define G_IS_ARMV7_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_REGISTER_OPERAND)) +#define G_ARMV7_REGISTER_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_REGISTER_OPERAND, GArmV7RegisterOperandClass)) + + +/* Définition d'un opérande visant un registre ARMv7 (instance) */ +typedef struct _GArmV7RegisterOperand GArmV7RegisterOperand; + +/* Définition d'un opérande visant un registre ARMv7 (classe) */ +typedef struct _GArmV7RegisterOperandClass GArmV7RegisterOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de registre ARMv7. */ +GType g_armv7_register_operand_get_type(void); + +/* Crée un opérande visant un registre ARMv7. */ +GArchOperand *g_armv7_register_operand_new(GArmV7Register *); + +/* Fournit le registre ARMv7 associé à l'opérande. */ +const GArmV7Register *g_armv7_register_operand_get(const GArmV7RegisterOperand *); + + + +#endif /* _PLUGINS_ARM_V7_OPERANDS_REGISTER_H */ diff --git a/plugins/arm/v7/operands/reglist.c b/plugins/arm/v7/operands/reglist.c index 5fc1f08..005aff7 100644 --- a/plugins/arm/v7/operands/reglist.c +++ b/plugins/arm/v7/operands/reglist.c @@ -33,6 +33,9 @@ #include +#include "../../register.h" + + /* Définition d'un opérande listant une série de registres ARM (instance) */ struct _GArmV7RegListOperand @@ -73,6 +76,17 @@ static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *, GBufferL +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_reglist_operand_unserialize(GArmV7RegListOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_reglist_operand_serialize(const GArmV7RegListOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour une liste de registres ARM. */ G_DEFINE_TYPE(GArmV7RegListOperand, g_armv7_reglist_operand, G_TYPE_ARCH_OPERAND); @@ -103,6 +117,9 @@ static void g_armv7_reglist_operand_class_init(GArmV7RegListOperandClass *klass) operand->compare = (operand_compare_fc)g_armv7_reglist_operand_compare; operand->print = (operand_print_fc)g_armv7_reglist_operand_print; + operand->unserialize = (unserialize_operand_fc)g_armv7_reglist_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_reglist_operand_serialize; + } @@ -352,3 +369,98 @@ GArmV7Register *g_armv7_reglist_operand_get_register(const GArmV7RegListOperand return operand->registers[index]; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_reglist_operand_unserialize(GArmV7RegListOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + size_t count; /* Quantité de registres */ + size_t i; /* Boucle de parcours */ + uint8_t index; /* Identifiant de registre */ + GArmV7Register *reg; /* Nouveau registre à intégrer */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + result = extract_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + + if (result) + { + reg = g_armv7_register_new(index); + g_armv7_reglist_add_register(operand, reg); + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_reglist_operand_serialize(const GArmV7RegListOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + size_t i; /* Boucle de parcours */ + uint8_t index; /* Identifiant de registre */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_reglist_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &operand->count, sizeof(size_t), true); + + for (i = 0; i < operand->count && result; i++) + { + index = g_arm_register_get_index(G_ARM_REGISTER(operand->registers[i])); + + result = extend_packed_buffer(pbuf, &index, sizeof(uint8_t), false); + + } + + return result; + +} diff --git a/plugins/arm/v7/operands/reglist.h b/plugins/arm/v7/operands/reglist.h index cb5d462..a8adc47 100644 --- a/plugins/arm/v7/operands/reglist.h +++ b/plugins/arm/v7/operands/reglist.h @@ -36,12 +36,12 @@ -#define G_TYPE_ARMV7_REGLIST_OPERAND g_armv7_reglist_operand_get_type() -#define G_ARMV7_REGLIST_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_reglist_operand_get_type(), GArmV7RegListOperand)) -#define G_IS_ARMV7_REGLIST_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_reglist_operand_get_type())) -#define G_ARMV7_REGLIST_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperandClass)) -#define G_IS_ARMV7_REGLIST_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_REGLIST_OPERAND)) -#define G_ARMV7_REGLIST_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperandClass)) +#define G_TYPE_ARMV7_REGLIST_OPERAND g_armv7_reglist_operand_get_type() +#define G_ARMV7_REGLIST_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperand)) +#define G_IS_ARMV7_REGLIST_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_REGLIST_OPERAND)) +#define G_ARMV7_REGLIST_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperandClass)) +#define G_IS_ARMV7_REGLIST_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_REGLIST_OPERAND)) +#define G_ARMV7_REGLIST_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperandClass)) /* Définition d'un opérande listant une série de registres ARM (instance) */ diff --git a/plugins/arm/v7/operands/rotation.c b/plugins/arm/v7/operands/rotation.c index 2b47d73..c091044 100644 --- a/plugins/arm/v7/operands/rotation.c +++ b/plugins/arm/v7/operands/rotation.c @@ -66,6 +66,17 @@ static void g_armv7_rotation_operand_print(const GArmV7RotationOperand *, GBuffe +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_rotation_operand_unserialize(GArmV7RotationOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_rotation_operand_serialize(const GArmV7RotationOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour une opérande de rotation ARMv7. */ G_DEFINE_TYPE(GArmV7RotationOperand, g_armv7_rotation_operand, G_TYPE_ARCH_OPERAND); @@ -96,6 +107,9 @@ static void g_armv7_rotation_operand_class_init(GArmV7RotationOperandClass *klas operand->compare = (operand_compare_fc)g_armv7_rotation_operand_compare; operand->print = (operand_print_fc)g_armv7_rotation_operand_print; + operand->unserialize = (unserialize_operand_fc)g_armv7_rotation_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_rotation_operand_serialize; + } @@ -113,6 +127,7 @@ static void g_armv7_rotation_operand_class_init(GArmV7RotationOperandClass *klas static void g_armv7_rotation_operand_init(GArmV7RotationOperand *operand) { + operand->value = NULL; } @@ -131,7 +146,8 @@ static void g_armv7_rotation_operand_init(GArmV7RotationOperand *operand) static void g_armv7_rotation_operand_dispose(GArmV7RotationOperand *operand) { - g_object_unref(G_OBJECT(operand->value)); + if (operand->value != NULL) + g_object_unref(G_OBJECT(operand->value)); G_OBJECT_CLASS(g_armv7_rotation_operand_parent_class)->dispose(G_OBJECT(operand)); @@ -254,3 +270,82 @@ GArchOperand *g_armv7_rotation_operand_get_value(const GArmV7RotationOperand *op return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_rotation_operand_unserialize(GArmV7RotationOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + GArchOperand *value; /* Valeur à intégrer */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_rotation_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + { + value = g_arch_operand_load(storage, format, pbuf); + + if (value == NULL) + result = false; + + else + operand->value = value; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_rotation_operand_serialize(const GArmV7RotationOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_rotation_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = g_arch_operand_store(operand->value, storage, pbuf); + + return result; + +} diff --git a/plugins/arm/v7/operands/rotation.h b/plugins/arm/v7/operands/rotation.h index 33dbfe7..8fd569f 100644 --- a/plugins/arm/v7/operands/rotation.h +++ b/plugins/arm/v7/operands/rotation.h @@ -32,12 +32,12 @@ -#define G_TYPE_ARMV7_ROTATION_OPERAND g_armv7_rotation_operand_get_type() -#define G_ARMV7_ROTATION_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_rotation_operand_get_type(), GArmV7RotationOperand)) -#define G_IS_ARMV7_ROTATION_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_rotation_operand_get_type())) -#define G_ARMV7_ROTATION_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_ROTATION_OPERAND, GArmV7RotationOperandClass)) -#define G_IS_ARMV7_ROTATION_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_ROTATION_OPERAND)) -#define G_ARMV7_ROTATION_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_ROTATION_OPERAND, GArmV7RotationOperandClass)) +#define G_TYPE_ARMV7_ROTATION_OPERAND g_armv7_rotation_operand_get_type() +#define G_ARMV7_ROTATION_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_ROTATION_OPERAND, GArmV7RotationOperand)) +#define G_IS_ARMV7_ROTATION_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_ROTATION_OPERAND)) +#define G_ARMV7_ROTATION_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_ROTATION_OPERAND, GArmV7RotationOperandClass)) +#define G_IS_ARMV7_ROTATION_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_ROTATION_OPERAND)) +#define G_ARMV7_ROTATION_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_ROTATION_OPERAND, GArmV7RotationOperandClass)) /* Définition d'un opérande visant une opérande de rotation ARMv7 (instance) */ diff --git a/plugins/arm/v7/operands/shift.c b/plugins/arm/v7/operands/shift.c index 3e8b8b7..e0637ee 100644 --- a/plugins/arm/v7/operands/shift.c +++ b/plugins/arm/v7/operands/shift.c @@ -68,6 +68,17 @@ static void g_armv7_shift_operand_print(const GArmV7ShiftOperand *, GBufferLine +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_armv7_shift_operand_unserialize(GArmV7ShiftOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_armv7_shift_operand_serialize(const GArmV7ShiftOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour une opérande de décalage ARMv7. */ G_DEFINE_TYPE(GArmV7ShiftOperand, g_armv7_shift_operand, G_TYPE_ARCH_OPERAND); @@ -98,6 +109,9 @@ static void g_armv7_shift_operand_class_init(GArmV7ShiftOperandClass *klass) operand->compare = (operand_compare_fc)g_armv7_shift_operand_compare; operand->print = (operand_print_fc)g_armv7_shift_operand_print; + operand->unserialize = (unserialize_operand_fc)g_armv7_shift_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_armv7_shift_operand_serialize; + } @@ -115,6 +129,7 @@ static void g_armv7_shift_operand_class_init(GArmV7ShiftOperandClass *klass) static void g_armv7_shift_operand_init(GArmV7ShiftOperand *operand) { + operand->shift_value = NULL; } @@ -133,7 +148,8 @@ static void g_armv7_shift_operand_init(GArmV7ShiftOperand *operand) static void g_armv7_shift_operand_dispose(GArmV7ShiftOperand *operand) { - g_object_unref(G_OBJECT(operand->shift_value)); + if (operand->shift_value != NULL) + g_object_unref(G_OBJECT(operand->shift_value)); G_OBJECT_CLASS(g_armv7_shift_operand_parent_class)->dispose(G_OBJECT(operand)); @@ -298,3 +314,88 @@ GArchOperand *g_armv7_shift_operand_get_shift_value(const GArmV7ShiftOperand *op return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_shift_operand_unserialize(GArmV7ShiftOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + GArchOperand *value; /* Valeur à intégrer */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_shift_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, &operand->shift_type, sizeof(SRType), true); + + if (result) + { + value = g_arch_operand_load(storage, format, pbuf); + + if (value == NULL) + result = false; + + else + operand->shift_value = value; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv7_shift_operand_serialize(const GArmV7ShiftOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_shift_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &operand->shift_type, sizeof(SRType), true); + + if (result) + result = g_arch_operand_store(operand->shift_value, storage, pbuf); + + return result; + +} diff --git a/plugins/arm/v7/operands/shift.h b/plugins/arm/v7/operands/shift.h index b5a2905..44a1a32 100644 --- a/plugins/arm/v7/operands/shift.h +++ b/plugins/arm/v7/operands/shift.h @@ -35,12 +35,12 @@ -#define G_TYPE_ARMV7_SHIFT_OPERAND g_armv7_shift_operand_get_type() -#define G_ARMV7_SHIFT_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_shift_operand_get_type(), GArmV7ShiftOperand)) -#define G_IS_ARMV7_SHIFT_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_shift_operand_get_type())) -#define G_ARMV7_SHIFT_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_SHIFT_OPERAND, GArmV7ShiftOperandClass)) -#define G_IS_ARMV7_SHIFT_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_SHIFT_OPERAND)) -#define G_ARMV7_SHIFT_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_SHIFT_OPERAND, GArmV7ShiftOperandClass)) +#define G_TYPE_ARMV7_SHIFT_OPERAND g_armv7_shift_operand_get_type() +#define G_ARMV7_SHIFT_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARMV7_SHIFT_OPERAND, GArmV7ShiftOperand)) +#define G_IS_ARMV7_SHIFT_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARMV7_SHIFT_OPERAND)) +#define G_ARMV7_SHIFT_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_SHIFT_OPERAND, GArmV7ShiftOperandClass)) +#define G_IS_ARMV7_SHIFT_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_SHIFT_OPERAND)) +#define G_ARMV7_SHIFT_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_SHIFT_OPERAND, GArmV7ShiftOperandClass)) /* Définition d'un opérande visant une opérande de décalage ARMv7 (instance) */ diff --git a/plugins/arm/v7/post.c b/plugins/arm/v7/post.c index fccd835..ad839cf 100644 --- a/plugins/arm/v7/post.c +++ b/plugins/arm/v7/post.c @@ -46,7 +46,7 @@ void post_process_ldr_instructions(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GExeFormat *format) { GArchOperand *op; /* Opérande numérique en place */ - uint32_t addr; /* Adresse visée par le saut */ + virt_t addr; /* Adresse visée par le saut */ GBinFormat *bfmt; /* Version basique du format */ GTargetOperand *new; /* Instruction de ciblage */ vmpa2t target; /* Défination finale précise */ @@ -62,7 +62,7 @@ void post_process_ldr_instructions(GArchInstruction *instr, GArchProcessor *proc if (!G_IS_IMM_OPERAND(op)) goto ppli_release; - if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr) + if (g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &addr) && g_exe_format_translate_address_into_vmpa(format, addr, &target)) { bfmt = G_BIN_FORMAT(format); diff --git a/plugins/arm/v7/post.h b/plugins/arm/v7/post.h index 7d6e0a8..e808efd 100644 --- a/plugins/arm/v7/post.h +++ b/plugins/arm/v7/post.h @@ -25,7 +25,6 @@ #define _PLUGINS_ARM_V7_POST_H -#include #include diff --git a/plugins/dalvik/core.c b/plugins/dalvik/core.c index f945c18..cc96843 100644 --- a/plugins/dalvik/core.c +++ b/plugins/dalvik/core.c @@ -24,12 +24,14 @@ #include "core.h" -#include #include #include "register.h" -#include "v35/processor.h" +#include "operands/args.h" +#include "operands/pool.h" +#include "operands/register.h" +#include "v35/core.h" @@ -38,6 +40,32 @@ DEFINE_CHRYSALIDE_PLUGIN("dalvik", "Add support for the Dalvik architecture", "0 +/* Assure l'enregistrement de types pour les caches à charger. */ +static void register_dalvik_gtypes(void); + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Assure l'enregistrement de types pour les caches à charger. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void register_dalvik_gtypes(void) +{ + g_type_ensure(G_TYPE_DALVIK_ARGS_OPERAND); + g_type_ensure(G_TYPE_DALVIK_POOL_OPERAND); + g_type_ensure(G_TYPE_DALVIK_REGISTER_OPERAND); + +} + + /****************************************************************************** * * * Paramètres : plugin = greffon à manipuler. * @@ -54,12 +82,15 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) { bool result; /* Bilan à retourner */ - result = register_processor_type("dalvik35", "Dalvik Virtual Machine v35", G_TYPE_DALVIK35_PROCESSOR); + register_dalvik_gtypes(); + + result = init_dalvik35_core(); return result; } + /****************************************************************************** * * * Paramètres : plugin = greffon à manipuler. * @@ -74,6 +105,8 @@ G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin) G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin) { + exit_dalvik35_core(); + clean_dalvik_register_cache(); } diff --git a/plugins/dalvik/operand.c b/plugins/dalvik/operand.c index ae57498..4d8fc73 100644 --- a/plugins/dalvik/operand.c +++ b/plugins/dalvik/operand.c @@ -747,7 +747,7 @@ void dalvik_mark_first_operand_as_written(GArchInstruction *instr) operand = g_arch_instruction_get_operand(instr, 0); - g_dalvik_register_operand_mark_as_written(G_DALVIK_REGISTER_OPERAND(operand)); + g_register_operand_mark_as_written(G_REGISTER_OPERAND(operand)); g_object_unref(G_OBJECT(operand)); diff --git a/plugins/dalvik/operands/args.c b/plugins/dalvik/operands/args.c index f35a11f..5224567 100644 --- a/plugins/dalvik/operands/args.c +++ b/plugins/dalvik/operands/args.c @@ -72,6 +72,17 @@ static void g_dalvik_args_operand_print(const GDalvikArgsOperand *, GBufferLine +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_dalvik_args_operand_unserialize(GDalvikArgsOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_dalvik_args_operand_serialize(const GDalvikArgsOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour une liste d'arguments Dalvik. */ G_DEFINE_TYPE(GDalvikArgsOperand, g_dalvik_args_operand, G_TYPE_ARCH_OPERAND); @@ -102,6 +113,9 @@ static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *klass) operand->compare = (operand_compare_fc)g_dalvik_args_operand_compare; operand->print = (operand_print_fc)g_dalvik_args_operand_print; + operand->unserialize = (unserialize_operand_fc)g_dalvik_args_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_dalvik_args_operand_serialize; + } @@ -119,6 +133,8 @@ static void g_dalvik_args_operand_class_init(GDalvikArgsOperandClass *klass) static void g_dalvik_args_operand_init(GDalvikArgsOperand *operand) { + operand->args = NULL; + operand->count = 0; } @@ -161,6 +177,9 @@ static void g_dalvik_args_operand_dispose(GDalvikArgsOperand *operand) static void g_dalvik_args_operand_finalize(GDalvikArgsOperand *operand) { + if (operand->args != NULL) + free(operand->args); + G_OBJECT_CLASS(g_dalvik_args_operand_parent_class)->finalize(G_OBJECT(operand)); } @@ -280,7 +299,6 @@ GArchOperand *g_dalvik_args_operand_new(void) void g_dalvik_args_operand_add(GDalvikArgsOperand *operand, GArchOperand *arg) { - operand->count++; operand->args = (GArchOperand **)realloc(operand->args, operand->count * sizeof(GArchOperand *)); @@ -328,3 +346,91 @@ GArchOperand *g_dalvik_args_operand_get(const GDalvikArgsOperand *operand, size_ return operand->args[index]; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dalvik_args_operand_unserialize(GDalvikArgsOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + size_t count; /* Nombre d'opérandes à charger*/ + size_t i; /* Boucle de parcours */ + GArchOperand *arg; /* Nouvel argument à intégrer */ + + parent = G_ARCH_OPERAND_CLASS(g_dalvik_args_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + arg = g_arch_operand_load(storage, format, pbuf); + + if (arg == NULL) + result = false; + + else + g_dalvik_args_operand_add(operand, arg); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dalvik_args_operand_serialize(const GDalvikArgsOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + size_t i; /* Boucle de parcours */ + + parent = G_ARCH_OPERAND_CLASS(g_dalvik_args_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &operand->count, sizeof(size_t), true); + + for (i = 0; i < operand->count && result; i++) + result = g_arch_operand_store(operand->args[i], storage, pbuf); + + return result; + +} diff --git a/plugins/dalvik/operands/args.h b/plugins/dalvik/operands/args.h index bf2fac4..3852e6d 100644 --- a/plugins/dalvik/operands/args.h +++ b/plugins/dalvik/operands/args.h @@ -32,12 +32,12 @@ -#define G_TYPE_DALVIK_ARGS_OPERAND g_dalvik_args_operand_get_type() -#define G_DALVIK_ARGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_args_operand_get_type(), GDalvikArgsOperand)) -#define G_IS_DALVIK_ARGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_args_operand_get_type())) -#define G_DALVIK_ARGS_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_ARGS_OPERAND, GDalvikArgsOperandClass)) -#define G_IS_DALVIK_ARGS_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_ARGS_OPERAND)) -#define G_DALVIK_ARGS_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_ARGS_OPERAND, GDalvikArgsOperandClass)) +#define G_TYPE_DALVIK_ARGS_OPERAND g_dalvik_args_operand_get_type() +#define G_DALVIK_ARGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DALVIK_ARGS_OPERAND, GDalvikArgsOperand)) +#define G_IS_DALVIK_ARGS_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DALVIK_ARGS_OPERAND)) +#define G_DALVIK_ARGS_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_ARGS_OPERAND, GDalvikArgsOperandClass)) +#define G_IS_DALVIK_ARGS_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_ARGS_OPERAND)) +#define G_DALVIK_ARGS_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_ARGS_OPERAND, GDalvikArgsOperandClass)) /* Définition d'un opérande visant une liste d'opérandes Dalvik (instance) */ diff --git a/plugins/dalvik/operands/pool.c b/plugins/dalvik/operands/pool.c index 9acfdb6..6bb1323 100644 --- a/plugins/dalvik/operands/pool.c +++ b/plugins/dalvik/operands/pool.c @@ -77,6 +77,17 @@ static void g_dalvik_pool_operand_print(const GDalvikPoolOperand *, GBufferLine +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_dalvik_pool_operand_unserialize(GDalvikPoolOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_dalvik_pool_operand_serialize(const GDalvikPoolOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini par la GLib pour un un élément de table de constantes Dalvik. */ G_DEFINE_TYPE(GDalvikPoolOperand, g_dalvik_pool_operand, G_TYPE_ARCH_OPERAND); @@ -108,6 +119,9 @@ static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *klass) operand->compare = (operand_compare_fc)g_dalvik_pool_operand_compare; operand->print = (operand_print_fc)g_dalvik_pool_operand_print; + operand->unserialize = (unserialize_operand_fc)g_dalvik_pool_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_dalvik_pool_operand_serialize; + } @@ -125,6 +139,7 @@ static void g_dalvik_pool_operand_class_init(GDalvikPoolOperandClass *klass) static void g_dalvik_pool_operand_init(GDalvikPoolOperand *operand) { + operand->format = NULL; } @@ -143,7 +158,8 @@ static void g_dalvik_pool_operand_init(GDalvikPoolOperand *operand) static void g_dalvik_pool_operand_dispose(GDalvikPoolOperand *operand) { - g_object_unref(G_OBJECT(operand->format)); + if (operand->format != NULL) + g_object_unref(G_OBJECT(operand->format)); G_OBJECT_CLASS(g_dalvik_pool_operand_parent_class)->dispose(G_OBJECT(operand)); @@ -453,3 +469,84 @@ uint32_t g_dalvik_pool_operand_get_index(const GDalvikPoolOperand *operand) return operand->index; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dalvik_pool_operand_unserialize(GDalvikPoolOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_dalvik_pool_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + { + operand->format = G_DEX_FORMAT(format); + g_object_ref(G_OBJECT(format)); + } + + if (result) + result = extract_packed_buffer(pbuf, &operand->type, sizeof(DalvikPoolType), true); + + if (result) + result = extract_packed_buffer(pbuf, &operand->index, sizeof(uint32_t), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_dalvik_pool_operand_serialize(const GDalvikPoolOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_dalvik_pool_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &operand->type, sizeof(DalvikPoolType), true); + + if (result) + result = extend_packed_buffer(pbuf, &operand->index, sizeof(uint32_t), true); + + return result; + +} diff --git a/plugins/dalvik/operands/register.c b/plugins/dalvik/operands/register.c index d2dd174..7d011a0 100644 --- a/plugins/dalvik/operands/register.c +++ b/plugins/dalvik/operands/register.c @@ -24,18 +24,14 @@ #include "register.h" -#include -#include +#include /* Définition d'un opérande visant un registre Dalvik (instance) */ struct _GDalvikRegisterOperand { - GArchOperand parent; /* Instance parente */ - - GDalvikRegister *reg; /* Registre représenté */ - bool is_written; /* Changement de contenu */ + GRegisterOperand parent; /* Instance parente */ }; @@ -43,7 +39,7 @@ struct _GDalvikRegisterOperand /* Définition d'un opérande visant un registre Dalvik (classe) */ struct _GDalvikRegisterOperandClass { - GArchOperandClass parent; /* Classe parente */ + GRegisterOperandClass parent; /* Classe parente */ }; @@ -60,16 +56,21 @@ static void g_dalvik_register_operand_dispose(GDalvikRegisterOperand *); /* Procède à la libération totale de la mémoire. */ static void g_dalvik_register_operand_finalize(GDalvikRegisterOperand *); -/* Compare un opérande avec un autre. */ -static int g_dalvik_register_operand_compare(const GDalvikRegisterOperand *, const GDalvikRegisterOperand *); -/* Traduit un opérande en version humainement lisible. */ -static void g_dalvik_register_operand_print(const GDalvikRegisterOperand *, GBufferLine *, AsmSyntax); + +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_dalvik_register_operand_unserialize(GDalvikRegisterOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_dalvik_register_operand_serialize(const GDalvikRegisterOperand *, GAsmStorage *, packed_buffer *); /* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ -G_DEFINE_TYPE(GDalvikRegisterOperand, g_dalvik_register_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE(GDalvikRegisterOperand, g_dalvik_register_operand, G_TYPE_REGISTER_OPERAND); /****************************************************************************** @@ -96,8 +97,8 @@ static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *kl operand = G_ARCH_OPERAND_CLASS(klass); - operand->compare = (operand_compare_fc)g_dalvik_register_operand_compare; - operand->print = (operand_print_fc)g_dalvik_register_operand_print; + operand->unserialize = (unserialize_operand_fc)g_dalvik_register_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_dalvik_register_operand_serialize; } @@ -116,8 +117,6 @@ static void g_dalvik_register_operand_class_init(GDalvikRegisterOperandClass *kl static void g_dalvik_register_operand_init(GDalvikRegisterOperand *operand) { - operand->reg = NULL; - operand->is_written = false; } @@ -136,9 +135,6 @@ static void g_dalvik_register_operand_init(GDalvikRegisterOperand *operand) static void g_dalvik_register_operand_dispose(GDalvikRegisterOperand *operand) { - if (operand->reg != NULL) - g_object_unref(G_OBJECT(operand->reg)); - G_OBJECT_CLASS(g_dalvik_register_operand_parent_class)->dispose(G_OBJECT(operand)); } @@ -165,51 +161,6 @@ static void g_dalvik_register_operand_finalize(GDalvikRegisterOperand *operand) /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int g_dalvik_register_operand_compare(const GDalvikRegisterOperand *a, const GDalvikRegisterOperand *b) -{ - int result; /* Bilan à retourner */ - - result = g_dalvik_register_compare(a->reg, b->reg); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * -* syntax = type de représentation demandée. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_dalvik_register_operand_print(const GDalvikRegisterOperand *operand, GBufferLine *line, AsmSyntax syntax) -{ - g_arch_register_print(G_ARCH_REGISTER(operand->reg), line, syntax); - -} - - -/****************************************************************************** -* * * Paramètres : content = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * low = position éventuelle des 4 bits visés. [OUT] * @@ -303,7 +254,7 @@ GArchOperand *g_dalvik_register_operand_new_from_existing(GDalvikRegister *reg) result = g_object_new(G_TYPE_DALVIK_REGISTER_OPERAND, NULL); - result->reg = reg; + G_REGISTER_OPERAND(result)->reg = G_ARCH_REGISTER(reg); return G_ARCH_OPERAND(result); @@ -324,44 +275,97 @@ GArchOperand *g_dalvik_register_operand_new_from_existing(GDalvikRegister *reg) const GDalvikRegister *g_dalvik_register_operand_get(const GDalvikRegisterOperand *operand) { - return operand->reg; + GDalvikRegister *result; /* Instance à retourner */ + + result = G_DALVIK_REGISTER(G_REGISTER_OPERAND(operand)->reg); + + return result; } + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = opérande représentant un registre à mettre à jour. * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * * * -* Description : Marque l'opérande comme étant écrit plutôt que consulté. * +* Description : Charge un opérande depuis une mémoire tampon. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -void g_dalvik_register_operand_mark_as_written(GDalvikRegisterOperand *operand) +static bool g_dalvik_register_operand_unserialize(GDalvikRegisterOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) { - operand->is_written = true; + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + uint16_t index; /* Identifiant de registre */ + GDalvikRegister *reg; /* Registre à intégrer */ + + parent = G_ARCH_OPERAND_CLASS(g_dalvik_register_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + { + result = extract_packed_buffer(pbuf, &index, sizeof(uint16_t), true); + + if (result) + { + reg = g_dalvik_register_new(index); + result = (reg != NULL); + } + + if (result) + G_REGISTER_OPERAND(operand)->reg = G_ARCH_REGISTER(reg); + + } + + return result; } /****************************************************************************** * * -* Paramètres : operand = opérande représentant un registre à consulter. * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * * * -* Description : Indique le type d'accès réalisé sur l'opérande. * +* Description : Sauvegarde un opérande dans une mémoire tampon. * * * -* Retour : Type d'accès : true en cas d'écriture, false sinon. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -bool g_dalvik_register_operand_is_written(const GDalvikRegisterOperand *operand) +static bool g_dalvik_register_operand_serialize(const GDalvikRegisterOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) { - return operand->is_written; + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + uint16_t index; /* Identifiant de registre */ + + parent = G_ARCH_OPERAND_CLASS(g_dalvik_register_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + { + index = g_dalvik_register_get_index(G_DALVIK_REGISTER(G_REGISTER_OPERAND(operand)->reg)); + result = extend_packed_buffer(pbuf, &index, sizeof(uint16_t), true); + } + + return result; } diff --git a/plugins/dalvik/operands/register.h b/plugins/dalvik/operands/register.h index efc3651..29b14c8 100644 --- a/plugins/dalvik/operands/register.h +++ b/plugins/dalvik/operands/register.h @@ -64,12 +64,6 @@ GArchOperand *g_dalvik_register_operand_new_from_existing(GDalvikRegister *); /* Fournit le registre Dalvik associé à l'opérande. */ const GDalvikRegister *g_dalvik_register_operand_get(const GDalvikRegisterOperand *); -/* Marque l'opérande comme étant écrit plutôt que consulté. */ -void g_dalvik_register_operand_mark_as_written(GDalvikRegisterOperand *); - -/* Indique le type d'accès réalisé sur l'opérande. */ -bool g_dalvik_register_operand_is_written(const GDalvikRegisterOperand *); - #endif /* _PLUGINS_DALVIK_OPERANDS_REGISTER_H */ diff --git a/plugins/dalvik/register.h b/plugins/dalvik/register.h index ffa44e4..42206c8 100644 --- a/plugins/dalvik/register.h +++ b/plugins/dalvik/register.h @@ -33,12 +33,12 @@ /* ------------------------- GESTION UNITAIRE DES REGISTRES ------------------------- */ -#define G_TYPE_DALVIK_REGISTER g_dalvik_register_get_type() -#define G_DALVIK_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_register_get_type(), GDalvikRegister)) -#define G_IS_DALVIK_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_register_get_type())) -#define G_DALVIK_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_REGISTER, GDalvikRegisterClass)) -#define G_IS_DALVIK_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_REGISTER)) -#define G_DALVIK_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_REGISTER, GDalvikRegisterClass)) +#define G_TYPE_DALVIK_REGISTER g_dalvik_register_get_type() +#define G_DALVIK_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_DALVIK_REGISTER, GDalvikRegister)) +#define G_IS_DALVIK_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_DALVIK_REGISTER)) +#define G_DALVIK_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_REGISTER, GDalvikRegisterClass)) +#define G_IS_DALVIK_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_REGISTER)) +#define G_DALVIK_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_REGISTER, GDalvikRegisterClass)) /* Représentation d'un registre Dalvik (instance) */ diff --git a/plugins/dalvik/v35/Makefile.am b/plugins/dalvik/v35/Makefile.am index ad179c0..eecdeba 100644 --- a/plugins/dalvik/v35/Makefile.am +++ b/plugins/dalvik/v35/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libdalvik35.la libdalvik35_la_SOURCES = \ + core.h core.c \ instruction.h instruction.c \ operand.h \ processor.h processor.c diff --git a/plugins/dalvik/v35/core.c b/plugins/dalvik/v35/core.c new file mode 100644 index 0000000..7e36691 --- /dev/null +++ b/plugins/dalvik/v35/core.c @@ -0,0 +1,99 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.c - chargement et déchargement des mécanismes internes de l'architecture Dalvik v35 + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#include "core.h" + + +#include + + +#include "instruction.h" +#include "processor.h" + + + +/* Assure l'enregistrement de types pour les caches à charger. */ +static void register_dalvik35_gtypes(void); + + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Assure l'enregistrement de types pour les caches à charger. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void register_dalvik35_gtypes(void) +{ + g_type_ensure(G_TYPE_DALVIK35_INSTRUCTION); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Met en place les mécanismes internes de l'archi. Dalvik v35. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool init_dalvik35_core(void) +{ + bool result; /* Bilan à renvoyer */ + + register_dalvik35_gtypes(); + + result = register_processor_type("dalvik35", "Dalvik Virtual Machine v35", G_TYPE_DALVIK35_PROCESSOR); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Supprime les mécanismes internes de l'archi. Dalvik v35. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void exit_dalvik35_core(void) +{ + +} diff --git a/plugins/dalvik/v35/core.h b/plugins/dalvik/v35/core.h new file mode 100644 index 0000000..1ee4bf6 --- /dev/null +++ b/plugins/dalvik/v35/core.h @@ -0,0 +1,40 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * core.h - prototypes pour le chargement et le déchargement des mécanismes internes de l'architecture Dalvik v35 + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see . + */ + + +#ifndef _PLUGINS_DALVIK_V35_CORE_H +#define _PLUGINS_DALVIK_V35_CORE_H + + +#include + + + +/* Met en place les mécanismes internes de l'architecture Dalvik v35. */ +bool init_dalvik35_core(void); + +/* Supprime les mécanismes internes de l'architecture Dalvik v35. */ +void exit_dalvik35_core(void); + + + +#endif /* _PLUGINS_DALVIK_V35_CORE_H */ diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 4bb9e43..f028cd6 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -40,6 +40,7 @@ #include "db/client.h" //#include "decomp/decompiler.h" #include "disass/disassembler.h" +#include "../arch/storage.h" #include "../common/extstr.h" #include "../common/cpp.h" #include "../common/xdg.h" @@ -1025,6 +1026,53 @@ static bool g_loaded_binary_connect_remote(GLoadedBinary *binary) } +/****************************************************************************** +* * +* Paramètres : binary = élément binaire à manipuler. * +* * +* Description : Sauvegarde le cache des instructions désassemblées. * +* * +* Retour : Bilan préliminaire de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_loaded_binary_save_cache(const GLoadedBinary *binary) +{ + bool result; /* Bilan à faire remonter */ + GArchProcessor *proc; /* Processeur concerné */ + GBinContent *content; /* Contenu brut représenté */ + const gchar *id; /* Identifiant court et unique */ + GAsmStorage *storage; /* Cache propre à constituer */ + + proc = g_loaded_binary_get_processor(binary); + content = g_loaded_binary_get_content(binary); + + id = g_binary_content_get_checksum(content); + + storage = g_asm_storage_new_compressed(proc, id); + + g_object_unref(G_OBJECT(content)); + g_object_unref(G_OBJECT(proc)); + + if (storage != NULL) + { + g_signal_connect(G_OBJECT(storage), "saved", G_CALLBACK(g_object_unref), NULL); + + g_asm_storage_save(storage); + + result = true; + + } + else + result = false; + + return result; + +} + + /* ---------------------------------------------------------------------------------- */ /* MANIPULATION DES COLLECTIONS */ @@ -1491,9 +1539,14 @@ static bool g_loaded_binary_save(const GLoadedBinary *binary, xmlDoc *xdoc, xmlX { bool result; /* Bilan à faire remonter */ + /* Mise en cache des instructions */ + + result = g_loaded_binary_save_cache(binary); + /* Elément divers associés au binaire */ - result = g_loaded_binary_save_storage(binary, xdoc, context, path); + if (result) + result = g_loaded_binary_save_storage(binary, xdoc, context, path); /* Sauvegarde côté serveur */ diff --git a/src/analysis/binary.h b/src/analysis/binary.h index b57e072..fd25210 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -111,6 +111,9 @@ DBStorage g_loaded_binary_get_storage(const GLoadedBinary *, DBFeatures); /* Définit la forme d'enregistrement d'une fonctionnalité. */ void g_loaded_binary_set_storage(GLoadedBinary *, DBFeatures, DBStorage); +/* Sauvegarde le cache des instructions désassemblées. */ +bool g_loaded_binary_save_cache(const GLoadedBinary *); + /* -------------------------- MANIPULATION DES COLLECTIONS -------------------------- */ diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index ca5e565..efe50e1 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -36,6 +36,7 @@ #include "instructions.h" #include "output.h" #include "routines.h" +#include "../../arch/storage.h" #include "../../core/global.h" #include "../../glibext/generators/prologue.h" #include "../../plugins/pglist.h" @@ -216,6 +217,10 @@ static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wg { GArchProcessor *proc; /* Architecture du binaire */ GExeFormat *format; /* Format du binaire représenté*/ + GBinContent *content; /* Contenu brut représenté */ + const gchar *id; /* Identifiant court et unique */ + GAsmStorage *storage; /* Cache propre à constituer */ + bool cached; /* Instructions en cache */ GArchInstruction **instrs; /* Instructions résultantes */ size_t count; /* Quantité de ces instructions*/ @@ -227,25 +232,54 @@ static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wg format = g_loaded_binary_get_format(binary); + g_binary_format_preload_disassembling_context(G_BIN_FORMAT(format), context, status); + + /** + * Etape zéro : récupération des instructions depuis un cache, si ce dernier exitste. + */ + + content = g_loaded_content_get_content(G_LOADED_CONTENT(binary)); + + id = g_binary_content_get_checksum(content); + + storage = g_asm_storage_new_compressed(proc, id); + + g_object_unref(G_OBJECT(content)); + + cached = g_asm_storage_has_cache(storage); + + if (cached) + cached = g_asm_storage_open(storage, G_BIN_FORMAT(format), gid); + + g_object_unref(G_OBJECT(storage)); + /** * Première étape : collecte des instructions. */ - instrs = disassemble_binary_content(binary, context, gid, status, &count); + if (!cached) + { + instrs = disassemble_binary_content(binary, context, gid, status, &count); + + g_arch_processor_set_instructions(proc, instrs, count); - g_arch_processor_set_instructions(proc, instrs, count); + process_disassembly_event(PGA_DISASSEMBLY_RAW, binary); - process_disassembly_event(PGA_DISASSEMBLY_RAW, binary); + } /** * Seconde étape : liaisons des instructions. */ - process_all_instructions(gid, status, _("Calling 'link' hook on all instructions..."), - g_instructions_study_do_link_operation, - proc, context, format); + if (!cached) + { + process_all_instructions(gid, status, _("Calling 'link' hook on all instructions..."), + g_instructions_study_do_link_operation, + proc, context, format); - process_disassembly_event(PGA_DISASSEMBLY_HOOKED_LINK, binary); + process_disassembly_event(PGA_DISASSEMBLY_HOOKED_LINK, binary); + + } /** * Troisième étape : exécution d'éventuels post-traitements. @@ -271,11 +305,15 @@ static void compute_disassembly(GLoadedBinary *binary, GProcContext *context, wg * Cinquième étape : liaisons entre instructions. */ - process_all_instructions(gid, status, _("Establishing links betweek all instructions..."), - g_instructions_study_establish_links, - proc, context, format); + if (!cached) + { + process_all_instructions(gid, status, _("Establishing links betweek all instructions..."), + g_instructions_study_establish_links, + proc, context, format); - process_disassembly_event(PGA_DISASSEMBLY_LINKED, binary); + process_disassembly_event(PGA_DISASSEMBLY_LINKED, binary); + + } /** * Sixième étape : regroupement en blocs basiques. diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c index 934c755..03b3ff0 100644 --- a/src/analysis/disass/fetch.c +++ b/src/analysis/disass/fetch.c @@ -431,11 +431,10 @@ GArchInstruction **disassemble_binary_content(GLoadedBinary *binary, GProcContex g_proc_context_attach_counter(template.ctx, &remaining_counter); /** - * Première phase de désassemblage : intégration des infos du format. + * Première phase de désassemblage : intégration des infos du format, + * récupérées dans le contexte via un appel à g_binary_format_preload_disassembling_context(). */ - g_binary_format_preload_disassembling_context(format, template.ctx, status); - populate_fresh_memory_areas(gid, status, template.areas, template.count, G_PRELOAD_INFO(ctx)); g_work_queue_wait_for_completion(queue, gid); diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index a5cde8f..c9cc63b 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -18,6 +18,7 @@ libarch_la_SOURCES = \ raw.h raw.c \ register-int.h \ register.h register.c \ + storage.h storage.c \ target.h target.c \ undefined.h undefined.c \ vmpa.h vmpa.c diff --git a/src/arch/immediate.c b/src/arch/immediate.c index bf4a36a..1c084ea 100644 --- a/src/arch/immediate.c +++ b/src/arch/immediate.c @@ -109,6 +109,17 @@ static char *g_imm_operand_build_tooltip(const GImmOperand *, const GLoadedBinar +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_imm_operand_unserialize(GImmOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_imm_operand_serialize(const GImmOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini pour un opérande de valeur numérique. */ G_DEFINE_TYPE(GImmOperand, g_imm_operand, G_TYPE_ARCH_OPERAND); @@ -141,6 +152,9 @@ static void g_imm_operand_class_init(GImmOperandClass *klass) operand->print = (operand_print_fc)g_imm_operand_print; operand->build_tooltip = (operand_build_tooltip_fc)g_imm_operand_build_tooltip; + operand->unserialize = (unserialize_operand_fc)g_imm_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_imm_operand_serialize; + } @@ -1357,3 +1371,96 @@ bool g_imm_operand_to_off_t(const GImmOperand *operand, off_t *value, bool *nega return false; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_imm_operand_unserialize(GImmOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, &operand->raw, sizeof(uint64_t), true); + + if (result) + result = extract_packed_buffer(pbuf, &operand->size, sizeof(MemoryDataSize), true); + + if (result) + result = extract_packed_buffer(pbuf, &operand->def_display, sizeof(ImmOperandDisplay), true); + + if (result) + result = extract_packed_buffer(pbuf, &operand->display, sizeof(ImmOperandDisplay), true); + + if (result) + result = extract_packed_buffer(pbuf, &operand->misc, sizeof(uint8_t), false); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_imm_operand_serialize(const GImmOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &operand->raw, sizeof(uint64_t), true); + + if (result) + result = extend_packed_buffer(pbuf, &operand->size, sizeof(MemoryDataSize), true); + + if (result) + result = extend_packed_buffer(pbuf, &operand->def_display, sizeof(ImmOperandDisplay), true); + + if (result) + result = extend_packed_buffer(pbuf, &operand->display, sizeof(ImmOperandDisplay), true); + + if (result) + result = extend_packed_buffer(pbuf, &operand->misc, sizeof(uint8_t), false); + + return result; + +} diff --git a/src/arch/immediate.h b/src/arch/immediate.h index 2a7f015..8f8f097 100644 --- a/src/arch/immediate.h +++ b/src/arch/immediate.h @@ -53,12 +53,12 @@ typedef enum _ImmOperandDisplay #define IOD_LAST_VALID IOD_CHAR -#define G_TYPE_IMM_OPERAND g_imm_operand_get_type() -#define G_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_imm_operand_get_type(), GImmOperand)) -#define G_IS_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_imm_operand_get_type())) -#define G_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_IMM_OPERAND, GImmOperandClass)) -#define G_IS_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_IMM_OPERAND)) -#define G_IMM_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_IMM_OPERAND, GImmOperandClass)) +#define G_TYPE_IMM_OPERAND g_imm_operand_get_type() +#define G_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_IMM_OPERAND, GImmOperand)) +#define G_IS_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_IMM_OPERAND)) +#define G_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_IMM_OPERAND, GImmOperandClass)) +#define G_IS_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_IMM_OPERAND)) +#define G_IMM_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_IMM_OPERAND, GImmOperandClass)) /* Définition d'un opérande de valeur numérique (instance) */ diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index 2adeed0..365c7e9 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -46,6 +46,12 @@ typedef char * (* build_instruction_tooltip_fc) (const GArchInstruction *); /* Fournit une description pour l'instruction manipulée. */ typedef const char * (* get_instruction_desc_fc) (const GArchInstruction *); +/* Charge une instruction depuis une mémoire tampon. */ +typedef bool (* unserialize_instruction_fc) (GArchInstruction *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde une instruction dans une mémoire tampon. */ +typedef bool (* serialize_instruction_fc) (GArchInstruction *, GAsmStorage *, packed_buffer *); + /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ typedef GBufferLine * (* print_instruction_fc) (const GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); @@ -106,6 +112,9 @@ struct _GArchInstructionClass build_instruction_tooltip_fc build_tooltip; /* Construction d'une bulle*/ get_instruction_desc_fc get_desc; /* Description assez complète */ + unserialize_instruction_fc unserialize; /* Chargement depuis un tampon */ + serialize_instruction_fc serialize; /* Conservation dans un tampon */ + print_instruction_fc print; /* Imprime l'ensemble */ //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 be7ff37..e2d8d2a 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -30,6 +30,7 @@ #include "instruction-int.h" +#include "storage.h" #include "../glibext/linegen-int.h" @@ -51,6 +52,17 @@ static void g_arch_instruction_finalize(GArchInstruction *); +/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ + + +/* Charge une instruction depuis une mémoire tampon. */ +static bool g_arch_instruction_unserialize(GArchInstruction *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde une instruction dans une mémoire tampon. */ +static bool g_arch_instruction_serialize(GArchInstruction *, GAsmStorage *, packed_buffer *); + + + /* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ @@ -103,6 +115,9 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass) instr = G_ARCH_INSTRUCTION_CLASS(klass); + instr->unserialize = (unserialize_instruction_fc)g_arch_instruction_unserialize; + instr->serialize = (serialize_instruction_fc)g_arch_instruction_serialize; + instr->print = (print_instruction_fc)_g_arch_instruction_print; } @@ -1055,7 +1070,7 @@ char *g_arch_instruction_build_tooltip(const GArchInstruction *instr) * Remarques : - * * * ******************************************************************************/ - + const char *g_arch_instruction_get_description(const GArchInstruction *instr) { const char *result; /* Description à retourner */ @@ -1069,6 +1084,324 @@ const char *g_arch_instruction_get_description(const GArchInstruction *instr) /* ---------------------------------------------------------------------------------- */ +/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge une instruction depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_instruction_unserialize(GArchInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + packed_buffer op_pbuf; /* Tampon des données à écrire */ + size_t count; /* Nombre d'éléments à traiter */ + size_t i; /* Boucle de parcours */ + off64_t pos; /* Position dans le flux */ + GArchOperand *op; /* Opérande à traiter */ + instr_link_t link; /* Lien vers une instruction */ + packed_buffer ins_pbuf; /* Tampon des données à écrire */ + + result = unpack_mrange(&instr->range, pbuf); + + if (result) + { + init_packed_buffer(&op_pbuf); + + result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + result = extract_packed_buffer(pbuf, &pos, sizeof(off64_t), true); + + if (result) + result = g_asm_storage_load_operand_data(storage, &op_pbuf, pos); + + if (result) + { + op = g_arch_operand_load(storage, format, &op_pbuf); + result = (op != NULL); + } + + if (result) + g_arch_instruction_attach_extra_operand(instr, op); + + } + + exit_packed_buffer(&op_pbuf); + + } + + bool unserialize_link(instr_link_t *lk) + { + bool status; /* Bilan d'une conservation */ + phys_t lk_phys; /* Position physique courante */ + + status = extract_packed_buffer(pbuf, &lk_phys, sizeof(phys_t), true); + + if (status) + { + lk->linked = g_asm_storage_get_instruction_at(storage, format, lk_phys, &ins_pbuf); + status = (lk->linked != NULL); + } + + if (status) + { + status = extract_packed_buffer(pbuf, &lk->type, sizeof(InstructionLinkType), true); + + if (!status) + g_object_unref(G_OBJECT(lk->linked)); + + } + + return status; + + } + + if (result) + { + init_packed_buffer(&ins_pbuf); + + result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + result = unserialize_link(&link); + + if (result) + { + g_arch_instruction_link_with(instr, link.linked, link.type); + g_object_unref(G_OBJECT(link.linked)); + } + + } + + exit_packed_buffer(&ins_pbuf); + + } + + if (result) + result = extract_packed_buffer(pbuf, &instr->uid, sizeof(itid_t), true); + + if (result) + result = extract_packed_buffer(pbuf, &instr->flags, sizeof(ArchInstrFlag), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge une instruction depuis une mémoire tampon. * +* * +* Retour : Instruction d'assemblage constitué ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_arch_instruction_load(GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + GArchInstruction *result; /* Instance à retourner */ + bool status; /* Bilan du chargement */ + + result = G_ARCH_INSTRUCTION(g_asm_storage_create_object(storage, pbuf)); + + if (result != NULL) + { + status = G_ARCH_INSTRUCTION_GET_CLASS(result)->unserialize(result, storage, format, pbuf); + + if (!status) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde une instruction dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_instruction_serialize(GArchInstruction *instr, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + packed_buffer op_pbuf; /* Tampon des données à écrire */ + size_t count; /* Nombre d'éléments à traiter */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à traiter */ + off64_t pos; /* Position dans le flux */ + size_t kept; /* Nombre de liens conservés */ + instr_link_t *link; /* Lien vers une instruction */ + + result = pack_mrange(&instr->range, pbuf); + + if (result) + { + init_packed_buffer(&op_pbuf); + + g_arch_instruction_lock_operands(instr); + + count = _g_arch_instruction_count_operands(instr); + + result = extend_packed_buffer(pbuf, &count, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + op = _g_arch_instruction_get_operand(instr, i); + + result = g_arch_operand_store(op, storage, &op_pbuf); + + if (result) + result = g_asm_storage_store_operand_data(storage, &op_pbuf, &pos); + + if (result) + result = extend_packed_buffer(pbuf, &pos, sizeof(off64_t), true); + + g_object_unref(G_OBJECT(op)); + + } + + g_arch_instruction_unlock_operands(instr); + + exit_packed_buffer(&op_pbuf); + + } + + bool serialize_link(const instr_link_t *lk) + { + bool status; /* Bilan d'une conservation */ + const mrange_t *range; /* Emplacement d'une instruct° */ + phys_t lk_phys; /* Position physique courante */ + + if (lk->type == ILT_REF) + status = true; + + else + { + range = g_arch_instruction_get_range(lk->linked); + + lk_phys = get_phy_addr(get_mrange_addr(range)); + + status = extend_packed_buffer(pbuf, &lk_phys, sizeof(phys_t), true); + + if (status) + status = extend_packed_buffer(pbuf, &lk->type, sizeof(InstructionLinkType), true); + + } + + return status; + + } + + if (result) + { + 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 && result; i++) + { + link = g_arch_instruction_get_destination(instr, i); + + if (link->type != ILT_REF) + kept++; + + } + + result = extend_packed_buffer(pbuf, &kept, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + link = g_arch_instruction_get_destination(instr, i); + result = serialize_link(link); + } + + g_arch_instruction_unlock_dest(instr); + + } + + if (result) + result = extend_packed_buffer(pbuf, &instr->uid, sizeof(itid_t), true); + + if (result) + result = extend_packed_buffer(pbuf, &instr->flags, sizeof(ArchInstrFlag), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde une instruction dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_instruction_store(GArchInstruction *instr, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + result = g_asm_storage_store_object_gtype(storage, G_OBJECT(instr), pbuf); + + if (result) + result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->serialize(instr, storage, pbuf); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ /* OFFRE DE CAPACITES DE GENERATION */ /* ---------------------------------------------------------------------------------- */ diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 497b7f6..2201dd5 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -32,8 +32,8 @@ #include "immediate.h" #include "register.h" #include "vmpa.h" -#include "../analysis/content.h" #include "../analysis/type.h" +#include "../common/packed.h" #include "../format/executable.h" @@ -260,4 +260,19 @@ const char *g_arch_instruction_get_description(const GArchInstruction *); +/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ + + +/* Depuis "storage.h" : définition d'une conservation d'instructions d'assemblage (instance) */ +typedef struct _GAsmStorage GAsmStorage; + + +/* Charge une instruction depuis une mémoire tampon. */ +GArchInstruction *g_arch_instruction_load(GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde une instruction dans une mémoire tampon. */ +bool g_arch_instruction_store(GArchInstruction *, GAsmStorage *, packed_buffer *); + + + #endif /* _ARCH_INSTRUCTION_H */ diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h index ac8d07c..c052e0a 100644 --- a/src/arch/operand-int.h +++ b/src/arch/operand-int.h @@ -38,6 +38,12 @@ typedef void (* operand_print_fc) (const GArchOperand *, GBufferLine *, AsmSynta /* Construit un petit résumé concis de l'opérande. */ typedef char * (* operand_build_tooltip_fc) (const GArchOperand *, const GLoadedBinary *); +/* Charge un opérande depuis une mémoire tampon. */ +typedef bool (* unserialize_operand_fc) (GArchOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +typedef bool (* serialize_operand_fc) (const GArchOperand *, GAsmStorage *, packed_buffer *); + /* Adjonction de rendu alternatif */ typedef struct _alt_rendering @@ -67,6 +73,9 @@ struct _GArchOperandClass operand_print_fc print; /* Texte humain équivalent */ operand_build_tooltip_fc build_tooltip; /* Construction de description */ + unserialize_operand_fc unserialize; /* Chargement depuis un tampon */ + serialize_operand_fc serialize; /* Conservation dans un tampon */ + }; diff --git a/src/arch/operand.c b/src/arch/operand.c index 930a588..1d4b468 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -30,7 +30,9 @@ #include "operand-int.h" +#include "storage.h" #include "../common/sort.h" +#include "../core/logs.h" @@ -48,6 +50,17 @@ static void g_arch_operand_finalize(GArchOperand *); +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_arch_operand_unserialize(GArchOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_arch_operand_serialize(const GArchOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini pour un opérande d'architecture. */ G_DEFINE_TYPE(GArchOperand, g_arch_operand, G_TYPE_OBJECT); @@ -68,12 +81,18 @@ G_DEFINE_TYPE(GArchOperand, g_arch_operand, G_TYPE_OBJECT); static void g_arch_operand_class_init(GArchOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ + GArchOperandClass *operand; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_operand_dispose; object->finalize = (GObjectFinalizeFunc)g_arch_operand_finalize; + operand = G_ARCH_OPERAND_CLASS(klass); + + operand->unserialize = (unserialize_operand_fc)g_arch_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_arch_operand_serialize; + } @@ -197,10 +216,17 @@ void g_arch_operand_set_alt_text(GArchOperand *operand, const char *text, Render { alt_len = strlen(text); - operand->alt_info = (alt_rendering *)malloc(sizeof(RenderingTagType) + alt_len + 1); + if (alt_len == 0) + operand->alt_info = NULL; + + else + { + operand->alt_info = (alt_rendering *)malloc(sizeof(RenderingTagType) + alt_len + 1); + + operand->alt_info->tag = tag; + strcpy(operand->alt_info->text, text); - operand->alt_info->tag = tag; - strcpy(operand->alt_info->text, text); + } } @@ -270,3 +296,171 @@ char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBin return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_operand_unserialize(GArchOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + unsigned char len; /* Taille du contenu alternatif*/ + char *text; /* Texte alternatif */ + RenderingTagType tag; /* Type de rendu */ + + result = extract_packed_buffer(pbuf, &len, sizeof(unsigned char), false); + + if (result && len > 0) + { + text = (char *)malloc(len); + + if (result) + result = extract_packed_buffer(pbuf, text, len, false); + + if (result) + result = extract_packed_buffer(pbuf, &tag, sizeof(RenderingTagType), true); + + if (result) + g_arch_operand_set_alt_text(operand, text, tag); + + free(text); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Opérande d'assemblage constitué ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_arch_operand_load(GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + GArchOperand *result; /* Instance à retourner */ + bool status; /* Bilan du chargement */ + + result = G_ARCH_OPERAND(g_asm_storage_create_object(storage, pbuf)); + + if (result != NULL) + { + status = G_ARCH_OPERAND_GET_CLASS(result)->unserialize(result, storage, format, pbuf); + + if (!status) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_operand_serialize(const GArchOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + size_t len; /* Taille du contenu alternatif*/ + + if (operand->alt_info == NULL) + result = extend_packed_buffer(pbuf, (unsigned char []) { 0 }, sizeof(unsigned char), false); + + else + { + len = strlen(operand->alt_info->text) + 1; + assert(len > 1); + + if (len > (2 << (sizeof(unsigned char) * 8 - 1))) + { + log_variadic_message(LMT_ERROR, "Alternative text too long: '%s' (%zu bytes)", + operand->alt_info->text, len); + result = false; + } + + else + result = extend_packed_buffer(pbuf, (unsigned char []) { len }, sizeof(unsigned char), false); + + if (result) + result = extend_packed_buffer(pbuf, operand->alt_info->text, len, false); + + if (result) + result = extend_packed_buffer(pbuf, &operand->alt_info->tag, sizeof(RenderingTagType), true); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_operand_store(const GArchOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + result = g_asm_storage_store_object_gtype(storage, G_OBJECT(operand), pbuf); + + if (result) + result = G_ARCH_OPERAND_GET_CLASS(operand)->serialize(operand, storage, pbuf); + + return result; + +} diff --git a/src/arch/operand.h b/src/arch/operand.h index cd140ba..bb7388d 100644 --- a/src/arch/operand.h +++ b/src/arch/operand.h @@ -28,6 +28,8 @@ #include +#include "../common/packed.h" +#include "../format/format.h" #include "../glibext/gbufferline.h" @@ -36,12 +38,12 @@ typedef struct _GLoadedBinary GLoadedBinary; -#define G_TYPE_ARCH_OPERAND g_arch_operand_get_type() -#define G_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_operand_get_type(), GArchOperand)) -#define G_IS_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_operand_get_type())) -#define G_ARCH_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_OPERAND, GArchOperandClass)) -#define G_IS_ARCH_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_OPERAND)) -#define G_ARCH_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_OPERAND, GArchOperandClass)) +#define G_TYPE_ARCH_OPERAND g_arch_operand_get_type() +#define G_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_OPERAND, GArchOperand)) +#define G_IS_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_OPERAND)) +#define G_ARCH_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_OPERAND, GArchOperandClass)) +#define G_IS_ARCH_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_OPERAND)) +#define G_ARCH_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_OPERAND, GArchOperandClass)) /* Définition générique d'un opérande d'architecture (instance) */ @@ -68,4 +70,19 @@ char *g_arch_operand_build_tooltip(const GArchOperand *, const GLoadedBinary *); +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Depuis "storage.h" : définition d'une conservation d'instructions d'assemblage (instance) */ +typedef struct _GAsmStorage GAsmStorage; + + +/* Charge un opérande depuis une mémoire tampon. */ +GArchOperand *g_arch_operand_load(GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +bool g_arch_operand_store(const GArchOperand *, GAsmStorage *, packed_buffer *); + + + #endif /* _ARCH_OPERAND_H */ diff --git a/src/arch/post.c b/src/arch/post.c index 5687556..de07499 100644 --- a/src/arch/post.c +++ b/src/arch/post.c @@ -54,10 +54,10 @@ void post_process_target_resolution(GArchInstruction *instr, GArchProcessor *pro { GArchOperand *op; /* Opérande numérique en place */ virt_t addr; /* Adresse visée par le saut */ + vmpa2t target; /* Emplacement de la cible */ GBinFormat *bfmt; /* Version basique du format */ MemoryDataSize ptr_size; /* Taille de l'espace mémoire */ GTargetOperand *new; /* Instruction de ciblage */ - vmpa2t target; /* Emplacement de la cible */ mrange_t trange; /* Etendue du symbole à créer */ VMPA_BUFFER(loc); /* Conversion en chaîne */ char name[5 + VMPA_MAX_LEN]; /* Etiquette de la destination */ diff --git a/src/arch/raw.c b/src/arch/raw.c index 36bb4b3..4ae1e11 100644 --- a/src/arch/raw.c +++ b/src/arch/raw.c @@ -77,6 +77,22 @@ static const char *g_raw_instruction_get_encoding(const GRawInstruction *); /* Fournit le nom humain de l'instruction manipulée. */ static const char *g_raw_instruction_get_keyword(const GRawInstruction *, AsmSyntax); + + +/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ + + +/* Charge une instruction depuis une mémoire tampon. */ +static bool g_raw_instruction_unserialize(GRawInstruction *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde une instruction dans une mémoire tampon. */ +static bool g_raw_instruction_serialize(GRawInstruction *, GAsmStorage *, packed_buffer *); + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ static void g_raw_instruction_print(GRawInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); @@ -117,6 +133,10 @@ static void g_raw_instruction_class_init(GRawInstructionClass *klass) instr->get_encoding = (get_instruction_encoding_fc)g_raw_instruction_get_encoding; instr->get_keyword = (get_instruction_keyword_fc)g_raw_instruction_get_keyword; + + instr->unserialize = (unserialize_instruction_fc)g_raw_instruction_unserialize; + instr->serialize = (serialize_instruction_fc)g_raw_instruction_serialize; + instr->print = (print_instruction_fc)g_raw_instruction_print; } @@ -475,6 +495,107 @@ static const char *g_raw_instruction_get_keyword(const GRawInstruction *instr, A } + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge une instruction depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_raw_instruction_unserialize(GRawInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + uint8_t boolean; /* Valeur booléenne */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class); + + result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf); + + if (result) + { + result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + + if (result) + instr->is_padding = (boolean == 1 ? true : false); + + } + + if (result) + { + result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + + if (result) + instr->is_string = (boolean == 1 ? true : false); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde une instruction dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + uint8_t boolean; /* Valeur booléenne */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class); + + result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf); + + if (result) + { + boolean = (instr->is_padding ? 1 : 0); + result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + } + + if (result) + { + boolean = (instr->is_string ? 1 : 0); + result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + } + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : instr = instruction d'assemblage à représenter. * diff --git a/src/arch/register.c b/src/arch/register.c index 0033071..7e1bcc2 100644 --- a/src/arch/register.c +++ b/src/arch/register.c @@ -67,6 +67,17 @@ static void g_register_operand_print(const GRegisterOperand *, GBufferLine *, As +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_register_operand_unserialize(GRegisterOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_register_operand_serialize(const GRegisterOperand *, GAsmStorage *, packed_buffer *); + + + /* ---------------------------------------------------------------------------------- */ /* PUR REGISTRE DU MATERIEL */ /* ---------------------------------------------------------------------------------- */ @@ -301,9 +312,14 @@ static void g_register_operand_class_init(GRegisterOperandClass *klass) object->dispose = (GObjectFinalizeFunc/* ! */)g_register_operand_dispose; object->finalize = (GObjectFinalizeFunc)g_register_operand_finalize; + operand = G_ARCH_OPERAND_CLASS(klass); + operand->compare = (operand_compare_fc)g_register_operand_compare; operand->print = (operand_print_fc)g_register_operand_print; + operand->unserialize = (unserialize_operand_fc)g_register_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_register_operand_serialize; + } @@ -495,3 +511,66 @@ bool g_register_operand_is_written(const GRegisterOperand *operand) return operand->is_written; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_register_operand_unserialize(GRegisterOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); + + result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_register_operand_serialize(const GRegisterOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); + + result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + + return result; + +} diff --git a/src/arch/register.h b/src/arch/register.h index f38698a..fb3741e 100644 --- a/src/arch/register.h +++ b/src/arch/register.h @@ -38,12 +38,12 @@ /* ---------------------------- PUR REGISTRE DU MATERIEL ---------------------------- */ -#define G_TYPE_ARCH_REGISTER g_arch_register_get_type() -#define G_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_register_get_type(), GArchRegister)) -#define G_IS_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_register_get_type())) -#define G_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_REGISTER, GArchRegisterClass)) -#define G_IS_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_REGISTER)) -#define G_ARCH_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_REGISTER, GArchRegisterClass)) +#define G_TYPE_ARCH_REGISTER g_arch_register_get_type() +#define G_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_REGISTER, GArchRegister)) +#define G_IS_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_REGISTER)) +#define G_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_REGISTER, GArchRegisterClass)) +#define G_IS_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_REGISTER)) +#define G_ARCH_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_REGISTER, GArchRegisterClass)) /* Représentation d'un registre (instance) */ @@ -76,12 +76,12 @@ bool g_arch_register_is_stack_pointer(const GArchRegister *); /* ------------------------- REGISTRE SOUS FORME D'OPERANDE ------------------------- */ -#define G_TYPE_REGISTER_OPERAND g_register_operand_get_type() -#define G_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_register_operand_get_type(), GRegisterOperand)) -#define G_IS_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_register_operand_get_type())) -#define G_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_REGISTER_OPERAND, GRegisterOperandClass)) -#define G_IS_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_REGISTER_OPERAND)) -#define G_REGISTER_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_REGISTER_OPERAND, GRegisterOperandClass)) +#define G_TYPE_REGISTER_OPERAND g_register_operand_get_type() +#define G_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_REGISTER_OPERAND, GRegisterOperand)) +#define G_IS_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_REGISTER_OPERAND)) +#define G_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_REGISTER_OPERAND, GRegisterOperandClass)) +#define G_IS_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_REGISTER_OPERAND)) +#define G_REGISTER_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_REGISTER_OPERAND, GRegisterOperandClass)) /* Définition d'un opérande visant un registre (instance) */ diff --git a/src/arch/storage.c b/src/arch/storage.c new file mode 100644 index 0000000..ac1c878 --- /dev/null +++ b/src/arch/storage.c @@ -0,0 +1,1593 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.c - conservation hors mémoire vive des instructions désassemblées + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#include "storage.h" + + +#include +#include +#include +#include +#include +#include + + +#include "instruction.h" +#include "target.h" +#include "../common/compression.h" +#include "../common/extstr.h" +#include "../common/pathname.h" +#include "../common/xdg.h" +#include "../core/global.h" +#include "../core/logs.h" +#include "../core/queue.h" +#include "../glibext/delayed-int.h" + + + +/* ----------------- CONSERVATION EXTERNE DES INSTRUCTIONS CHARGEES ----------------- */ + + +#define G_TYPE_INS_CACHING g_ins_caching_get_type() +#define G_INS_CACHING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_INS_CACHING, GInsCaching)) +#define G_IS_INS_CACHING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_INS_CACHING)) +#define G_INS_CACHING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_INS_CACHING, GInsCachingClass)) +#define G_IS_INS_CACHING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_INS_CACHING)) +#define G_INS_CACHING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_INS_CACHING, GInsCachingClass)) + + +/* Ensembles binaires à désassembler (instance) */ +typedef struct _GInsCaching +{ + GDelayedWork parent; /* A laisser en premier */ + + GArchProcessor *proc; /* Ensemble à traiter */ + GAsmStorage *storage; /* Cache de destinartion */ + + GBinFormat *format; /* Nature de l'opération */ + + bool status; /* Bilan de l'opération */ + +} GInsCaching; + +/* Ensembles binaires à désassembler (classe) */ +typedef struct _GInsCachingClass +{ + GDelayedWorkClass parent; /* A laisser en premier */ + +} GInsCachingClass; + + +/* Indique le type défini pour les tâches d'enregistrement des instructions. */ +GType g_ins_caching_get_type(void); + +/* initialise la classe des tâches de cache d'instructions. */ +static void g_ins_caching_class_init(GInsCachingClass *); + +/* Initialise une tâche de cache d'instructions. */ +static void g_ins_caching_init(GInsCaching *); + +/* Supprime toutes les références externes. */ +static void g_ins_caching_dispose(GInsCaching *); + +/* Procède à la libération totale de la mémoire. */ +static void g_ins_caching_finalize(GInsCaching *); + +/* Crée une tâche de mise en cache de toutes les instructions. */ +static GInsCaching *g_ins_caching_new(GArchProcessor *, GAsmStorage *, GBinFormat *); + +/* Assure la conservation ou le chargement d'instructions. */ +static void g_ins_caching_process(GInsCaching *, GtkStatusStack *); + +/* Assure le chargement d'instructions en différé. */ +static void g_ins_caching_process_load(GInsCaching *, GtkStatusStack *); + +/* Assure la conservation d'instructions en différé. */ +static void g_ins_caching_process_store(GInsCaching *, GtkStatusStack *); + +/* Fournit le bilan des traitements d'instructions en différé. */ +static bool g_ins_caching_get_status(const GInsCaching *); + + + +/* ------------------- MECANISME DE SAUVEGARDE ET DE RESTAURATION ------------------- */ + + +/* Conservation d'une référence sur un type */ +typedef struct _gtype_ref_info_t +{ + GType gtype; /* Type pour la GLib */ + gpointer gclass; /* Lien vers sa classe */ + +} gtype_ref_info_t; + +/* Définition d'une conservation d'instructions d'assemblage (instance) */ +struct _GAsmStorage +{ + GObject parent; /* A laisser en premier */ + + char *id; /* Identifiant de contenu */ + + char *idx_filename; /* Fichier pour l'indexage */ + char *ins_filename; /* Fichier pour instructions */ + char *op_filename; /* Fichier pour les opérandes */ + char *tp_filename; /* Fichier pour les types */ + + int idx_fd; /* Flux pour l'indexage */ + int ins_fd; /* Flux pour les instructions */ + int op_fd; /* Flux pour les opérandes */ + int tp_fd; /* Flux pour les types */ + + /** + * La GLib n'est pas très claire sur la taille de GType : + * + * #if GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG || !defined __cplusplus + * typedef gsize GType; + * #else // for historic reasons, C++ links against gulong GTypes + * typedef gulong GType; + * #endif + * + * Et : + * + * typedef unsigned $glib_size_type_define gsize; + * + * On prend le parti de réduire à 65536 types possibles dans l'enregistrement + * des objets instanciés, et on conserve ces types en tant qu'unsigned short. + */ + + gtype_ref_info_t *gtypes; /* Types des objets reconnus */ + size_t gtp_count; /* Quantité de ces objets */ + GMutex gtp_mutex; /* Contrôle d'accès à la liste */ + + GArchProcessor *proc; /* Ensemble à traiter */ + + GArchInstruction **collected; /* Liste d'instructions */ + off64_t length; /* Taille de cette liste */ + size_t count; /* Nombre de présences */ + +}; + +/* Définition d'une conservation d'instructions d'assemblage (classe) */ +struct _GAsmStorageClass +{ + GObjectClass parent; /* A laisser en premier */ + + /* Signaux */ + + void (* saved) (GAsmStorage *); + +}; + + +/* Initialise la classe des conservations d'instructions. */ +static void g_asm_storage_class_init(GAsmStorageClass *); + +/* Initialise une instance de conservation d'instructions. */ +static void g_asm_storage_init(GAsmStorage *); + +/* Supprime toutes les références externes. */ +static void g_asm_storage_dispose(GAsmStorage *); + +/* Procède à la libération totale de la mémoire. */ +static void g_asm_storage_finalize(GAsmStorage *); + +/* Indique le chemin d'accès à l'archive finale. */ +static char *g_asm_storage_get_archive_filename(const GAsmStorage *); + +/* Décompresse les fichiers de cache d'instructions. */ +static bool g_asm_storage_decompress(const GAsmStorage *); + +/* Compresse les fichiers de cache d'instructions. */ +static bool g_asm_storage_compress(const GAsmStorage *); + +/* Apprend tous les types mémorisés dans un fichier. */ +static bool g_asm_storage_read_types(GAsmStorage *); + +/* Enregistre tous les types mémorisés dans un fichier. */ +static bool g_asm_storage_write_types(GAsmStorage *); + +/* Ouvre tous les fichiers nécessaires à une opération. */ +static bool g_asm_storage_open_files(GAsmStorage *, int ); + +/* Acquitte la fin d'une tâche de sauvegarde complète. */ +static void on_cache_saving_completed(GInsCaching *, GAsmStorage *); + + + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION EXTERNE DES INSTRUCTIONS CHARGEES */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour les tâches d'enregistrement des instructions. */ +G_DEFINE_TYPE(GInsCaching, g_ins_caching, G_TYPE_DELAYED_WORK); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des tâches de cache d'instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_ins_caching_class_init(GInsCachingClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GDelayedWorkClass *work; /* Version en classe parente */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_ins_caching_dispose; + object->finalize = (GObjectFinalizeFunc)g_ins_caching_finalize; + + work = G_DELAYED_WORK_CLASS(klass); + + work->run = (run_task_fc)g_ins_caching_process; + +} + + +/****************************************************************************** +* * +* Paramètres : caching = instance à initialiser. * +* * +* Description : Initialise une tâche de cache d'instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_ins_caching_init(GInsCaching *caching) +{ + caching->status = true; + +} + + +/****************************************************************************** +* * +* Paramètres : caching = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_ins_caching_dispose(GInsCaching *caching) +{ + g_object_unref(G_OBJECT(caching->proc)); + + g_object_unref(G_OBJECT(caching->storage)); + + if (caching->format != NULL) + g_object_unref(G_OBJECT(caching->format)); + + G_OBJECT_CLASS(g_ins_caching_parent_class)->dispose(G_OBJECT(caching)); + +} + + +/****************************************************************************** +* * +* Paramètres : caching = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_ins_caching_finalize(GInsCaching *caching) +{ + G_OBJECT_CLASS(g_ins_caching_parent_class)->finalize(G_OBJECT(caching)); + +} + + +/****************************************************************************** +* * +* Paramètres : proc = gestionnaire de l'ensemble d'instructions visées. * +* storage = gestionnaire de la conservation à venir. * +* format = format binaire chargé associé à l'architecture. * +* * +* Description : Crée une tâche de mise en cache de toutes les instructions. * +* * +* Retour : Tâche créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GInsCaching *g_ins_caching_new(GArchProcessor *proc, GAsmStorage *storage, GBinFormat *format) +{ + GInsCaching *result; /* Tâche à retourner */ + + result = g_object_new(G_TYPE_INS_CACHING, NULL); + + result->proc = proc; + g_object_ref(G_OBJECT(result->proc)); + + result->storage = storage; + g_object_ref(G_OBJECT(result->storage)); + + result->format = format; + + if (format != NULL) + g_object_ref(G_OBJECT(format)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : caching = opération d'enregistrement à mener. * +* status = barre de statut à tenir informée. * +* * +* Description : Assure la conservation ou le chargement d'instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_ins_caching_process(GInsCaching *caching, GtkStatusStack *status) +{ + if (caching->format != NULL) + g_ins_caching_process_load(caching, status); + + else + g_ins_caching_process_store(caching, status); + +} + + +/****************************************************************************** +* * +* Paramètres : caching = opération d'enregistrement à mener. * +* status = barre de statut à tenir informée. * +* * +* Description : Assure le chargement d'instructions en différé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_ins_caching_process_load(GInsCaching *caching, GtkStatusStack *status) +{ + GAsmStorage *storage; /* Cache de destinartion */ + packed_buffer pbuf; /* Tampon des données à écrire */ + off64_t i; /* Boucle de parcours */ + off64_t pos; /* Position courante */ + GArchInstruction *instr; /* Instruction à traiter */ + off64_t target; /* Position dans le flux */ + + storage = caching->storage; + + init_packed_buffer(&pbuf); + + for (i = 0; i < storage->length && caching->status; i++) + { + /* Des données sont-elles présentes à cette position ? */ + + pos = lseek64(storage->idx_fd, i * sizeof(off64_t), SEEK_SET); + + if (pos != (i * sizeof(off64_t))) + { + perror("lseek64"); + caching->status = false; + break; + } + + caching->status = safe_read(storage->idx_fd, &target, sizeof(off64_t)); + + if (!caching->status) + break; + + if (target == (off64_t)-1) + continue; + + /* Chargement de l'instruction */ + + instr = g_asm_storage_get_instruction_at(storage, caching->format, i, &pbuf); + + if (instr == NULL) + caching->status = false; + + else + g_object_unref(G_OBJECT(instr)); + + } + + exit_packed_buffer(&pbuf); + +} + + +/****************************************************************************** +* * +* Paramètres : caching = opération d'enregistrement à mener. * +* status = barre de statut à tenir informée. * +* * +* Description : Assure la conservation d'instructions en différé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_ins_caching_process_store(GInsCaching *caching, GtkStatusStack *status) +{ + GArchProcessor *proc; /* Ensemble à traiter */ + GAsmStorage *storage; /* Cache de destinartion */ + packed_buffer pbuf; /* Tampon des données à écrire */ + size_t count; /* Quantité d'instructions */ + phys_t last_phys; /* Dernière position physique */ + size_t i; /* Boucle de parcours #1 */ + GArchInstruction *instr; /* Instruction à traiter */ + off64_t pos; /* Position dans le flux */ + const mrange_t *irange; /* Emplacement de l'instruction*/ + phys_t cur_phys; /* Position physique courante */ + phys_t k; /* Boucle de parcours #2 */ + + proc = caching->proc; + storage = caching->storage; + + init_packed_buffer(&pbuf); + + g_arch_processor_lock(proc); + + count = g_arch_processor_count_instructions(proc); + + last_phys = VMPA_NO_PHYSICAL; + + for (i = 0; i < count && caching->status; i++) + { + /* Enregistrement de l'instruction */ + + instr = g_arch_processor_get_instruction(proc, i); + + caching->status = g_arch_instruction_store(instr, storage, &pbuf); + + if (caching->status) + caching->status = g_asm_storage_store_instruction_data(storage, &pbuf, &pos); + + /* Enregistrement de la position */ + + if (caching->status) + { + irange = g_arch_instruction_get_range(instr); + + cur_phys = get_phy_addr(get_mrange_addr(irange)); + + assert((last_phys == VMPA_NO_PHYSICAL && cur_phys == 0) || (cur_phys > 0 && last_phys < cur_phys)); + + if (last_phys != VMPA_NO_PHYSICAL) + for (k = last_phys; k < (cur_phys - 1) && caching->status; k++) + caching->status = safe_write(storage->idx_fd, (off64_t []) { -1 }, sizeof(off64_t)); + + caching->status = safe_write(storage->idx_fd, &pos, sizeof(off64_t)); + + last_phys = cur_phys; + + } + + g_object_unref(G_OBJECT(instr)); + + } + + g_arch_processor_unlock(proc); + + exit_packed_buffer(&pbuf); + +} + + +/****************************************************************************** +* * +* Paramètres : caching = opération d'enregistrement à mener. * +* * +* Description : Fournit le bilan des traitements d'instructions en différé. * +* * +* Retour : Bilan des opérations. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_ins_caching_get_status(const GInsCaching *caching) +{ + bool result; /* Bilan à retourner */ + + result = caching->status; + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* MECANISME DE SAUVEGARDE ET DE RESTAURATION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une conservation d'instructions d'assemblage. */ +G_DEFINE_TYPE(GAsmStorage, g_asm_storage, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des conservations d'instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_storage_class_init(GAsmStorageClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_asm_storage_dispose; + object->finalize = (GObjectFinalizeFunc)g_asm_storage_finalize; + + g_signal_new("saved", + G_TYPE_ASM_STORAGE, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GAsmStorageClass, saved), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + +} + + +/****************************************************************************** +* * +* Paramètres : storage = instance à initialiser. * +* * +* Description : Initialise une instance de conservation d'instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_storage_init(GAsmStorage *storage) +{ + storage->idx_filename = NULL; + storage->ins_filename = NULL; + storage->op_filename = NULL; + storage->tp_filename = NULL; + + storage->idx_fd = -1; + storage->ins_fd = -1; + storage->op_fd = -1; + storage->tp_fd = -1; + + storage->gtypes = NULL; + storage->gtp_count = 0; + g_mutex_init(&storage->gtp_mutex); + + storage->proc = NULL; + + storage->collected = NULL; + storage->length = 0; + storage->count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_storage_dispose(GAsmStorage *storage) +{ + size_t i; /* Boucle de parcours */ + + g_mutex_lock(&storage->gtp_mutex); + + for (i = 0; i < storage->gtp_count; i++) + if (storage->gtypes[i].gclass != NULL) + g_type_class_unref(storage->gtypes[i].gclass); + + g_mutex_unlock(&storage->gtp_mutex); + + g_mutex_clear(&storage->gtp_mutex); + + if (storage->proc != NULL) + g_object_unref(G_OBJECT(storage->proc)); + + for (i = 0; i < storage->length; i++) + if (storage->collected[i] != NULL) + g_object_unref(G_OBJECT(storage->collected[i])); + + G_OBJECT_CLASS(g_asm_storage_parent_class)->dispose(G_OBJECT(storage)); + +} + + +/****************************************************************************** +* * +* Paramètres : storage = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_storage_finalize(GAsmStorage *storage) +{ + int ret; /* Bilan d'un appel */ + + free(storage->id); + +#define finalize_storage_file(f) \ + if (f != NULL) \ + { \ + ret = access(f, W_OK); \ + if (ret == 0) \ + { \ + ret = unlink(f); \ + if (ret != 0) perror("unlink"); \ + } \ + free(f); \ + } + + finalize_storage_file(storage->idx_filename); + finalize_storage_file(storage->ins_filename); + finalize_storage_file(storage->op_filename); + finalize_storage_file(storage->tp_filename); + + if (storage->idx_fd != -1) + close(storage->idx_fd); + + if (storage->ins_fd != -1) + close(storage->ins_fd); + + if (storage->op_fd != -1) + close(storage->op_fd); + + if (storage->gtypes != NULL) + free(storage->gtypes); + + if (storage->collected != NULL) + free(storage->collected); + + G_OBJECT_CLASS(g_asm_storage_parent_class)->finalize(G_OBJECT(storage)); + +} + + +/****************************************************************************** +* * +* Paramètres : proc = gestionnaire de l'ensemble d'instructions visées. * +* id = identifiant pour la zone d'enregistrements. * +* * +* Description : Crée le support d'une conservation d'instructions. * +* * +* Retour : Mécanismes mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GAsmStorage *g_asm_storage_new_compressed(GArchProcessor *proc, const gchar *id) +{ + GAsmStorage *result; /* Structure à retourner */ + char *suffix; /* Fin du nom de fichier */ + char *basedir; /* Chemin d'accès */ + bool status; /* Assurance de validité */ + + result = g_object_new(G_TYPE_ASM_STORAGE, NULL); + + result->id = strdup(id); + + result->proc = proc; + g_object_ref(G_OBJECT(proc)); + + suffix = strdup("chrysalide"); + suffix = stradd(suffix, G_DIR_SEPARATOR_S); + suffix = stradd(suffix, "cache"); + suffix = stradd(suffix, G_DIR_SEPARATOR_S); + + basedir = get_xdg_config_dir(suffix); + + free(suffix); + + status = mkpath(basedir); + if (!status) goto gasn_base_error; + + asprintf(&result->idx_filename, "%s.%s-%s", basedir, id, "index.bin"); + asprintf(&result->ins_filename, "%s.%s-%s", basedir, id, "instructions.bin"); + asprintf(&result->op_filename, "%s.%s-%s", basedir, id, "operands.bin"); + asprintf(&result->tp_filename, "%s.%s-%s", basedir, id, "types.bin"); + + free(basedir); + + return result; + + gasn_base_error: + + g_object_unref(G_OBJECT(result)); + + free(basedir); + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à consulter. * +* * +* Description : Indique le chemin d'accès à l'archive finale. * +* * +* Retour : Nom de fichier à libérer, ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_asm_storage_get_archive_filename(const GAsmStorage *storage) +{ + char *result; /* Chemin d'accès à retourner */ + char *suffix; /* Fin du nom de fichier */ + + suffix = strdup("chrysalide"); + suffix = stradd(suffix, G_DIR_SEPARATOR_S); + suffix = stradd(suffix, "cache"); + suffix = stradd(suffix, G_DIR_SEPARATOR_S); + suffix = stradd(suffix, storage->id); + suffix = stradd(suffix, ".idb.tar.xz"); + + result = get_xdg_config_dir(suffix); + + free(suffix); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à consulter. * +* * +* Description : Détermine si un cache d'instructions complet existe. * +* * +* Retour : Bilan de la détermination. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_asm_storage_has_cache(const GAsmStorage *storage) +{ + bool result; /* Bilan à faire remonter */ + char *filename; /* Chemin d'accès à l'archive */ + int ret; /* Résultat d'un test d'accès */ + + filename = g_asm_storage_get_archive_filename(storage); + + ret = access(filename, R_OK); + + result = (ret == 0); + + free(filename); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* * +* Description : Décompresse les fichiers de cache d'instructions. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_asm_storage_decompress(const GAsmStorage *storage) +{ + bool result; /* Bilan à retourner */ + char *filename; /* Chemin d'accès à l'archive */ + struct archive *in; /* Archive à consulter */ + int ret; /* Bilan d'un appel */ + struct archive_entry *entry; /* Elément de l'archive */ + const char *path; /* Désignation d'un fichier */ + + result = false; + + filename = g_asm_storage_get_archive_filename(storage); + + in = archive_read_new(); + archive_read_support_filter_all(in); + archive_read_support_format_all(in); + + ret = archive_read_open_filename(in, filename, 10240 /* ?! */); + if (ret != ARCHIVE_OK) goto gasd_bad_archive; + + for (ret = archive_read_next_header(in, &entry); + ret == ARCHIVE_OK; + ret = archive_read_next_header(in, &entry)) + { + path = archive_entry_pathname(entry); + + if (strcmp(path, "index.bin") == 0) + { + if (!dump_archive_entry_into_file(in, entry, storage->idx_filename)) + goto gasd_exit; + } + else if (strcmp(path, "instructions.bin") == 0) + { + if (!dump_archive_entry_into_file(in, entry, storage->ins_filename)) + goto gasd_exit; + } + else if (strcmp(path, "operands.bin") == 0) + { + if (!dump_archive_entry_into_file(in, entry, storage->op_filename)) + goto gasd_exit; + } + else if (strcmp(path, "types.bin") == 0) + { + if (!dump_archive_entry_into_file(in, entry, storage->tp_filename)) + goto gasd_exit; + } + + } + + if (ret != ARCHIVE_EOF) + goto gasd_exit; + + result = true; + + gasd_exit: + + gasd_bad_archive: + + archive_read_close(in); + archive_read_free(in); + + free(filename); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* * +* Description : Compresse les fichiers de cache d'instructions. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_asm_storage_compress(const GAsmStorage *storage) +{ + bool result; /* Bilan à retourner */ + char *filename; /* Chemin d'accès à l'archive */ + struct archive *out; /* Archive à constituer */ + int ret; /* Bilan d'une création */ + CPError status; /* Bilan d'une compression */ + + result = false; + + filename = g_asm_storage_get_archive_filename(storage); + + out = archive_write_new(); + archive_write_add_filter_xz(out); + archive_write_set_format_gnutar(out); + + ret = archive_write_open_filename(out, filename); + if (ret != ARCHIVE_OK) goto gasc_exit; + + status = add_file_into_archive(out, storage->idx_filename, "index.bin"); + if (status != CPE_NO_ERROR) goto gasc_exit; + + status = add_file_into_archive(out, storage->ins_filename, "instructions.bin"); + if (status != CPE_NO_ERROR) goto gasc_exit; + + status = add_file_into_archive(out, storage->op_filename, "operands.bin"); + if (status != CPE_NO_ERROR) goto gasc_exit; + + status = add_file_into_archive(out, storage->tp_filename, "types.bin"); + if (status != CPE_NO_ERROR) goto gasc_exit; + + result = true; + + gasc_exit: + + archive_write_close(out); + archive_write_free(out); + + free(filename); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à compléter. * +* * +* Description : Apprend tous les types mémorisés dans un fichier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_asm_storage_read_types(GAsmStorage *storage) +{ + bool result; /* Bilan à enregistrer */ + packed_buffer pbuf; /* Tampon des données à écrire */ + size_t i; /* Boucle de parcours */ + unsigned char len; /* Taille d'un nom de type */ + char *name; /* Désignation d'un type */ + + init_packed_buffer(&pbuf); + + result = read_packed_buffer(&pbuf, storage->tp_fd); + + if (result) + { + g_mutex_lock(&storage->gtp_mutex); + + result = extract_packed_buffer(&pbuf, &storage->gtp_count, sizeof(size_t), true); + + if (result) + storage->gtypes = (gtype_ref_info_t *)calloc(storage->gtp_count, sizeof(gtype_ref_info_t)); + + for (i = 0; i < storage->gtp_count && result; i++) + { + result = extract_packed_buffer(&pbuf, &len, sizeof(unsigned char), false); + + if (result) + { + name = (char *)malloc(len); + + result = extract_packed_buffer(&pbuf, name, len, false); + + if (result) + { + storage->gtypes[i].gtype = g_type_from_name(name); + result = (storage->gtypes[i].gtype != 0); + + if (!result) + log_variadic_message(LMT_ERROR, "Unknown type: '%s'", name); + + } + + if (result) + storage->gtypes[i].gclass = g_type_class_ref(storage->gtypes[i].gtype); + + free(name); + + } + + } + + g_mutex_unlock(&storage->gtp_mutex); + + } + + exit_packed_buffer(&pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* pbuf = zone tampon à venir lire. * +* * +* Description : Crée une nouvelle instance d'objet à partir de son type. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObject *g_asm_storage_create_object(GAsmStorage *storage, packed_buffer *pbuf) +{ + GObject *result; /* Nouvelle instance à renvoyer*/ + size_t index; /* Indice du point d'insertion */ + bool status; /* Bilan d'une récupération */ + + result = NULL; + + status = extract_packed_buffer(pbuf, &index, sizeof(size_t), true); + + if (status) + { + g_mutex_lock(&storage->gtp_mutex); + + if (index < storage->gtp_count) + result = g_object_new(storage->gtypes[index].gtype, NULL); + + g_mutex_unlock(&storage->gtp_mutex); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* obj = instance dont le type est à mémoriser. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde le type d'un objet instancié. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_asm_storage_store_object_gtype(GAsmStorage *storage, GObject *obj, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GType gtype; /* Type à enregistrer */ + size_t index; /* Indice du point d'insertion */ + + gtype = G_TYPE_FROM_INSTANCE(obj); + + /** + * Pour quelques explications sur l'esquive suivante, se rapporter aux + * commentaires de g_target_operand_unserialize(). + * + * Dans la situation présente, on ne doit pas enregistrer le type dans le tampon, + * car l'opérande va relancer l'opération entière (avec un opérande temporaire), + * ce qui conduirait à l'enregistrement de deux types successifs dans les données. + */ + + if (gtype == G_TYPE_TARGET_OPERAND) + result = true; + + else + { + g_mutex_lock(&storage->gtp_mutex); + + for (index = 0; index < storage->gtp_count; index++) + if (storage->gtypes[index].gtype == gtype) + break; + + if (index == storage->gtp_count) + { + storage->gtypes = (gtype_ref_info_t *)realloc(storage->gtypes, + ++storage->gtp_count * sizeof(gtype_ref_info_t)); + + assert(storage->gtp_count > 0); + + storage->gtypes[index].gtype = gtype; + storage->gtypes[index].gclass = g_type_class_ref(gtype); + + } + + g_mutex_unlock(&storage->gtp_mutex); + + result = extend_packed_buffer(pbuf, &index, sizeof(size_t), true); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à consulter. * +* * +* Description : Enregistre tous les types mémorisés dans un fichier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_asm_storage_write_types(GAsmStorage *storage) +{ + bool result; /* Bilan à enregistrer */ + packed_buffer pbuf; /* Tampon des données à écrire */ + size_t i; /* Boucle de parcours */ + const gchar *name; /* Désignation d'un type */ + size_t len; /* Taille de ce nom */ + + init_packed_buffer(&pbuf); + + g_mutex_lock(&storage->gtp_mutex); + + result = extend_packed_buffer(&pbuf, &storage->gtp_count, sizeof(size_t), true); + + for (i = 0; i < storage->gtp_count && result; i++) + { + name = g_type_name(storage->gtypes[i].gtype); + len = strlen(name) + 1; + + if (len > (2 << (sizeof(unsigned char) * 8 - 1))) + { + log_variadic_message(LMT_ERROR, "Type name too long: '%s' (%zu bytes)", name, len); + result = false; + break; + } + + result = extend_packed_buffer(&pbuf, (unsigned char []) { len }, sizeof(unsigned char), false); + + if (result) + result = extend_packed_buffer(&pbuf, name, len, false); + + } + + if (result) + result = write_packed_buffer(&pbuf, storage->tp_fd); + + g_mutex_unlock(&storage->gtp_mutex); + + exit_packed_buffer(&pbuf); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* ins = true si les données viennent d'une instruction. * +* pbuf = zone tampon à remplir. * +* pos = tête de lecture avant écriture. * +* * +* Description : Charge des données rassemblées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _g_asm_storage_load_data(const GAsmStorage *storage, bool ins, packed_buffer *pbuf, off64_t pos) +{ + bool result; /* Bilan à retourner */ + int fd; /* Flux ciblé */ + off64_t new; /* Nouvelle position de lecture*/ + + fd = ins ? storage->ins_fd : storage->op_fd; + + new = lseek64(fd, pos, SEEK_SET); + + if (new != pos) + result = false; + + else + { + reset_packed_buffer(pbuf); + result = read_packed_buffer(pbuf, fd); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* ins = true si les données viennent d'une instruction. * +* pbuf = zone tampon à lire. * +* pos = tête de lecture avant écriture. [OUT] * +* * +* Description : Sauvegarde des données rassemblées. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool _g_asm_storage_store_data(const GAsmStorage *storage, bool ins, packed_buffer *pbuf, off64_t *pos) +{ + bool result; /* Bilan à retourner */ + int fd; /* Flux ciblé */ + + fd = ins ? storage->ins_fd : storage->op_fd; + + *pos = lseek64(fd, 0, SEEK_CUR); + + if (*pos == (off64_t)-1) + result = false; + + else + { + result = write_packed_buffer(pbuf, fd); + reset_packed_buffer(pbuf); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* flags = options d'ouverture supplémentaires. * +* * +* Description : Ouvre tous les fichiers nécessaires à une opération. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_asm_storage_open_files(GAsmStorage *storage, int flags) +{ + bool result; /* Bilan à retourner */ + +#define open_file(filename, fd) \ + ({ \ + bool __status; \ + fd = open(filename, flags | O_LARGEFILE, 0600); \ + if (fd == -1) \ + { \ + perror("open"); \ + __status = false; \ + } \ + else \ + __status = true; \ + __status; \ + }) + + result = open_file(storage->idx_filename, storage->idx_fd); + + if (result) + result = open_file(storage->ins_filename, storage->ins_fd); + + if (result) + result = open_file(storage->op_filename, storage->op_fd); + + if (result) + result = open_file(storage->tp_filename, storage->tp_fd); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* gid = groupe de travail dédié. * +* * +* Description : Lance une restauration complète d'unsauvegarde compressée. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_asm_storage_open(GAsmStorage *storage, GBinFormat *format, wgroup_id_t gid) +{ + bool result; /* Bilan à retourner */ + GInsCaching *caching; /* Tâche à faire exécuter */ + GWorkQueue *queue; /* Gestionnaire des tâches */ + GArchInstruction **list; /* Instructions rechargées */ + size_t i; /* Boucle de parcours #1 */ + size_t k; /* Boucle de parcours #2 */ + + result = g_asm_storage_decompress(storage); + + if (result) + result = g_asm_storage_open_files(storage, O_RDONLY); + + if (result) + result = g_asm_storage_read_types(storage); + + if (result) + { + storage->length = lseek64(storage->idx_fd, 0, SEEK_END); + + if (storage->length == (off64_t)-1) + { + perror("lseek64"); + result = false; + goto gaso_exit; + } + + result = (storage->length % sizeof(off64_t) == 0); + + storage->length /= sizeof(off64_t); + + } + + if (!result) + { + log_simple_message(LMT_ERROR, "Instruction cache seems corrupted..."); + goto gaso_exit; + } + + storage->collected = (GArchInstruction **)calloc(storage->length, sizeof(GArchInstruction *)); + + /** + * Cette méthode ne peut être appelée que pour un objet construit + * à partir du constructeur g_asm_storage_new_compressed(). + */ + assert(storage->proc != NULL); + + caching = g_ins_caching_new(storage->proc, storage, format); + g_object_ref(G_OBJECT(caching)); + + queue = get_work_queue(); + + g_work_queue_schedule_work(queue, G_DELAYED_WORK(caching), gid); + + g_work_queue_wait_for_completion(queue, gid); + + result = g_ins_caching_get_status(caching); + + g_object_unref(G_OBJECT(caching)); + + + if (result) + { + log_simple_message(LMT_INFO, "Successfully restored all instructions from cache!"); + + list = (GArchInstruction **)malloc(storage->count * sizeof(GArchInstruction *)); + + for (i = 0, k = 0; i < storage->length; i++) + if (storage->collected[i] != NULL) + { + list[k] = storage->collected[i]; + g_object_ref(G_OBJECT(list[k++])); + } + + assert(k == storage->count); + + g_arch_processor_set_instructions(storage->proc, list, storage->count); + + } + + else + log_simple_message(LMT_ERROR, "Failed to restore all instructions from cache!"); + + gaso_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* index = position physique de l'instruction recherchée. * +* pbuf = tampon de lecture à disposition pour l'opération. * +* * +* Description : Fournit l'instruction correspondant à une position indicée. * +* * +* Retour : Instruction rechargée ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_asm_storage_get_instruction_at(GAsmStorage *storage, GBinFormat *format, off64_t index, packed_buffer *pbuf) +{ + GArchInstruction *result; /* Instruction à renvoyer */ + off64_t pos; /* Position dans le cache */ + off64_t new; /* Nouvelle position de lecture*/ + off64_t target; /* Emplacement du cache ciblé */ + bool status; /* Bilan d'une lecture */ +#ifndef NDEBUG + const mrange_t *irange; /* Emplacement de l'instruction*/ +#endif + + assert(index < storage->length); + + pos = index * sizeof(off64_t); + + if (storage->collected[index] == NULL) + { + new = lseek64(storage->idx_fd, pos, SEEK_SET); + + if (new == pos) + { + status = safe_read(storage->idx_fd, &target, sizeof(off64_t)); + + if (status) + status = g_asm_storage_load_instruction_data(storage, pbuf, target); + + if (status) + storage->collected[index] = g_arch_instruction_load(storage, format, pbuf); + + if (storage->collected[index] != NULL) + { + storage->count++; + +#ifndef NDEBUG + irange = g_arch_instruction_get_range(storage->collected[index]); + + assert(index == get_phy_addr(get_mrange_addr(irange))); +#endif + + } + + } + + } + + result = storage->collected[index]; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire à manipuler. * +* * +* Description : Programme une sauvegarde complète et compressée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_asm_storage_save(GAsmStorage *storage) +{ + bool status; /* Statut des préparatifs */ + GInsCaching *caching; /* Tâche à faire exécuter */ + GWorkQueue *queue; /* Gestionnaire des tâches */ + + status = g_asm_storage_open_files(storage, O_WRONLY | O_CREAT | O_TRUNC); + + if (!status) + log_simple_message(LMT_ERROR, "Unable to setup files for instructions caching!"); + + else + { + /** + * Cette méthode ne peut être appelée que pour un objet construit + * à partir du constructeur g_asm_storage_new_compressed(). + */ + assert(storage->proc != NULL); + + caching = g_ins_caching_new(storage->proc, storage, NULL); + + g_signal_connect(caching, "work-completed", G_CALLBACK(on_cache_saving_completed), storage); + + queue = get_work_queue(); + + g_work_queue_schedule_work(queue, G_DELAYED_WORK(caching), STORAGE_WORK_GROUP); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : caching = tâche de sauvegarde menée à son terme. * +* storage = gestionnaire de conservation à la réception. * +* * +* Description : Acquitte la fin d'une tâche de sauvegarde complète. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_cache_saving_completed(GInsCaching *caching, GAsmStorage *storage) +{ + bool status; /* Bilan des enregistrements */ + + status = g_ins_caching_get_status(caching); + + if (status) + log_simple_message(LMT_INFO, "Successfully cached all instructions!"); + else + log_simple_message(LMT_ERROR, "Failed to cache all instructions!"); + + if (status) + status = g_asm_storage_write_types(storage); + + if (status) + { + status = g_asm_storage_compress(storage); + + if (!status) + log_simple_message(LMT_ERROR, "Failed to compress instruction cache!"); + + } + + g_signal_emit_by_name(storage, "saved"); + +} diff --git a/src/arch/storage.h b/src/arch/storage.h new file mode 100644 index 0000000..002897a --- /dev/null +++ b/src/arch/storage.h @@ -0,0 +1,104 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * storage.h - prototypes pour la conservation hors mémoire vive des instructions désassemblées + * + * Copyright (C) 2018 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see . + */ + + +#ifndef _ARCH_STORAGE_H +#define _ARCH_STORAGE_H + + +#include + + +#include + + +#include "processor.h" + + + +/* ------------------- MECANISME DE SAUVEGARDE ET DE RESTAURATION ------------------- */ + + +/* Définition générique d'une instruction d'architecture (instance) */ +typedef struct _GArchInstruction GArchInstruction; + + +#define G_TYPE_ASM_STORAGE g_asm_storage_get_type() +#define G_ASM_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ASM_STORAGE, GAsmStorage)) +#define G_IS_ASM_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ASM_STORAGE)) +#define G_ASM_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ASM_STORAGE, GAsmStorageClass)) +#define G_IS_ASM_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ASM_STORAGE)) +#define G_ASM_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ASM_STORAGE, GAsmStorageClass)) + + +/* Définition d'une conservation d'instructions d'assemblage (instance) */ +typedef struct _GAsmStorage GAsmStorage; + +/* Définition d'une conservation d'instructions d'assemblage (classe) */ +typedef struct _GAsmStorageClass GAsmStorageClass; + + +/* Indique le type défini pour une conservation d'instructions d'assemblage. */ +GType g_asm_storage_get_type(void); + +/* Crée le support d'une conservation d'instructions. */ +GAsmStorage *g_asm_storage_new_compressed(GArchProcessor *, const gchar *); + +/* Détermine si un cache d'instructions complet existe. */ +bool g_asm_storage_has_cache(const GAsmStorage *); + +/* Crée une nouvelle instance d'objet à partir de son type. */ +GObject *g_asm_storage_create_object(GAsmStorage *, packed_buffer *); + +/* Sauvegarde le type d'un objet instancié. */ +bool g_asm_storage_store_object_gtype(GAsmStorage *, GObject *, packed_buffer *); + +/* Charge des données rassemblées. */ +bool _g_asm_storage_load_data(const GAsmStorage *, bool, packed_buffer *, off64_t); + +#define g_asm_storage_load_instruction_data(s, b, p) \ + _g_asm_storage_load_data(s, true, b, p) + +#define g_asm_storage_load_operand_data(s, b, p) \ + _g_asm_storage_load_data(s, false, b, p) + +/* Sauvegarde des données rassemblées. */ +bool _g_asm_storage_store_data(const GAsmStorage *, bool, packed_buffer *, off64_t *); + +#define g_asm_storage_store_instruction_data(s, b, p) \ + _g_asm_storage_store_data(s, true, b, p) + +#define g_asm_storage_store_operand_data(s, b, p) \ + _g_asm_storage_store_data(s, false, b, p) + +/* Lance une restauration complète d'unsauvegarde compressée. */ +bool g_asm_storage_open(GAsmStorage *, GBinFormat *, wgroup_id_t); + +/* Fournit l'instruction correspondant à une position indicée. */ +GArchInstruction *g_asm_storage_get_instruction_at(GAsmStorage *, GBinFormat *, off64_t, packed_buffer *); + +/* Programme une sauvegarde complète et compressée. */ +void g_asm_storage_save(GAsmStorage *); + + + +#endif /* _ARCH_STORAGE_H */ diff --git a/src/arch/target.c b/src/arch/target.c index 3b5655e..a297a3c 100644 --- a/src/arch/target.c +++ b/src/arch/target.c @@ -47,6 +47,7 @@ struct _GTargetOperand MemoryDataSize size; /* Taille de l'opérande */ vmpa2t addr; /* Adresse de l'élément visé */ + bool strict; /* Résolution stricte */ GBinSymbol *symbol; /* Eventuel symbole associé */ phys_t diff; /* Position dans le symbole */ @@ -84,6 +85,17 @@ static char *g_target_operand_build_tooltip(const GTargetOperand *, const GLoade +/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ + + +/* Charge un opérande depuis une mémoire tampon. */ +static bool g_target_operand_unserialize(GTargetOperand *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde un opérande dans une mémoire tampon. */ +static bool g_target_operand_serialize(const GTargetOperand *, GAsmStorage *, packed_buffer *); + + + /* Indique le type défini pour un opérande de valeur numérique. */ G_DEFINE_TYPE(GTargetOperand, g_target_operand, G_TYPE_ARCH_OPERAND); @@ -116,6 +128,9 @@ static void g_target_operand_class_init(GTargetOperandClass *klass) operand->print = (operand_print_fc)g_target_operand_print; operand->build_tooltip = (operand_build_tooltip_fc)g_target_operand_build_tooltip; + operand->unserialize = (unserialize_operand_fc)g_target_operand_unserialize; + operand->serialize = (serialize_operand_fc)g_target_operand_serialize; + } @@ -136,6 +151,7 @@ static void g_target_operand_init(GTargetOperand *operand) operand->size = MDS_UNDEFINED; init_vmpa(&operand->addr, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL); + operand->strict = true; operand->symbol = NULL; operand->diff = 0; @@ -324,6 +340,8 @@ GArchOperand *g_target_operand_new(MemoryDataSize size, const vmpa2t *addr) result = g_object_new(G_TYPE_TARGET_OPERAND, NULL); + assert(size != MDS_UNDEFINED); + result->size = size; copy_vmpa(&result->addr, addr); @@ -466,8 +484,12 @@ bool g_target_operand_resolve(GTargetOperand *operand, GBinFormat *format, bool if (operand->symbol != NULL) g_object_unref(G_OBJECT(operand->symbol)); + operand->strict = strict; + result = g_binary_format_resolve_symbol(format, &operand->addr, strict, &operand->symbol, &operand->diff); + assert(!result || !strict || (strict && operand->diff == 0)); + /** * Si plusieurs chaînes se suivent, la seconde et les suivantes bénéficient * d'une étiquette si et seulement si elles sont détachées des précédentes @@ -539,3 +561,85 @@ GBinSymbol *g_target_operand_get_symbol(const GTargetOperand *operand, phys_t *d return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à constituer. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge un opérande depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_target_operand_unserialize(GTargetOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + assert(false); + + /** + * Comme ce type d'opérande peut générer de nouveaux symboles lorsque + * sa résolution échoue, il faut appeler ces résolutions dans les contextes + * d'origine. + * + * Ces contextes sont généralement le lieu de conversions de valeurs immédiates + * en valeurs de cibles, donc la sérialisation de l'opérande conduit à + * la sauvegarde d'un opérande de valeur immédiate de subsitution. + * + * La désérialisation est donc prise en compte par ce dernier type d'opérande. + */ + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde un opérande dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_target_operand_serialize(const GTargetOperand *operand, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperand *original; /* Opérande d'origine */ + + /** + * Pour les architectures sans mémoire virtuelle, la valeur est portée + * par la position physique. + */ + + if (has_virt_addr(&operand->addr)) + original = g_imm_operand_new_from_value(operand->size, get_virt_addr(&operand->addr)); + else + original = g_imm_operand_new_from_value(operand->size, get_phy_addr(&operand->addr)); + + result = g_arch_operand_store(original, storage, pbuf); + + g_object_unref(G_OBJECT(original)); + + return result; + +} diff --git a/src/arch/target.h b/src/arch/target.h index 45c1cb0..3c68fda 100644 --- a/src/arch/target.h +++ b/src/arch/target.h @@ -32,16 +32,15 @@ #include "archbase.h" #include "operand.h" #include "vmpa.h" -#include "../format/format.h" -#define G_TYPE_TARGET_OPERAND g_target_operand_get_type() -#define G_TARGET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_target_operand_get_type(), GTargetOperand)) -#define G_IS_TARGET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_target_operand_get_type())) -#define G_TARGET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TARGET_OPERAND, GTargetOperandClass)) -#define G_IS_TARGET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TARGET_OPERAND)) -#define G_TARGET_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TARGET_OPERAND, GTargetOperandClass)) +#define G_TYPE_TARGET_OPERAND g_target_operand_get_type() +#define G_TARGET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_TARGET_OPERAND, GTargetOperand)) +#define G_IS_TARGET_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_TARGET_OPERAND)) +#define G_TARGET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TARGET_OPERAND, GTargetOperandClass)) +#define G_IS_TARGET_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TARGET_OPERAND)) +#define G_TARGET_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TARGET_OPERAND, GTargetOperandClass)) /* Définition d'un opérande ciblant idéalement un symbole connu (instance) */ diff --git a/src/arch/undefined.c b/src/arch/undefined.c index 656e3f5..5542ac2 100644 --- a/src/arch/undefined.c +++ b/src/arch/undefined.c @@ -69,6 +69,22 @@ static const char *g_undef_instruction_get_encoding(const GUndefInstruction *); /* Fournit le nom humain de l'instruction manipulée. */ static const char *g_undef_instruction_get_keyword(const GUndefInstruction *, AsmSyntax); + + +/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ + + +/* Charge une instruction depuis une mémoire tampon. */ +static bool g_undef_instruction_unserialize(GUndefInstruction *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde une instruction dans une mémoire tampon. */ +static bool g_undef_instruction_serialize(GUndefInstruction *, GAsmStorage *, packed_buffer *); + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + /* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ static void g_undef_instruction_print(GUndefInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); @@ -109,6 +125,10 @@ static void g_undef_instruction_class_init(GUndefInstructionClass *klass) instr->get_encoding = (get_instruction_encoding_fc)g_undef_instruction_get_encoding; instr->get_keyword = (get_instruction_keyword_fc)g_undef_instruction_get_keyword; + + instr->unserialize = (unserialize_instruction_fc)g_undef_instruction_unserialize; + instr->serialize = (serialize_instruction_fc)g_undef_instruction_serialize; + instr->print = (print_instruction_fc)g_undef_instruction_print; } @@ -261,6 +281,81 @@ const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr, AsmS } + +/* ---------------------------------------------------------------------------------- */ +/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge une instruction depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_undef_instruction_unserialize(GUndefInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); + + result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, &instr->status, sizeof(InstrBehaviorStatus), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde une instruction dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_undef_instruction_serialize(GUndefInstruction *instr, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchInstructionClass *parent; /* Classe parente à consulter */ + + parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); + + result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, &instr->status, sizeof(InstrBehaviorStatus), true); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : instr = instruction d'assemblage à représenter. * diff --git a/src/arch/undefined.h b/src/arch/undefined.h index 9992ce7..74db9fa 100644 --- a/src/arch/undefined.h +++ b/src/arch/undefined.h @@ -33,12 +33,12 @@ -#define G_TYPE_UNDEF_INSTRUCTION g_undef_instruction_get_type() -#define G_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_undef_instruction_get_type(), GUndefInstruction)) -#define G_IS_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_undef_instruction_get_type())) -#define G_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) -#define G_IS_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UNDEF_INSTRUCTION)) -#define G_UNDEF_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) +#define G_TYPE_UNDEF_INSTRUCTION g_undef_instruction_get_type() +#define G_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstruction)) +#define G_IS_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UNDEF_INSTRUCTION)) +#define G_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) +#define G_IS_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UNDEF_INSTRUCTION)) +#define G_UNDEF_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) /* Définition générique d'une instruction au comportement non défini (instance) */ diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c index b29bb72..7abb5de 100644 --- a/src/arch/vmpa.c +++ b/src/arch/vmpa.c @@ -415,7 +415,7 @@ phys_t compute_vmpa_diff(const vmpa2t *a, const vmpa2t *b) * Paramètres : addr = élément à venir lire. [OUT] * * pbuf = paquet de données où venir puiser les infos. * * * -* Description : Lit la définition d'une adresse depuis un flux réseau. * +* Description : Lit la définition d'une adresse depuis un tampon. * * * * Retour : Bilan de l'opération. * * * @@ -442,7 +442,7 @@ bool unpack_vmpa(vmpa2t *addr, packed_buffer *pbuf) * Paramètres : addr = élément à venir écrire. * * pbuf = paquet de données où venir inscrire les infos. * * * -* Description : Ecrit la définition d'une adresse dans un flux réseau. * +* Description : Ecrit la définition d'une adresse dans un tampon. * * * * Retour : Bilan de l'opération. * * * @@ -1283,6 +1283,60 @@ void compute_mrange_end_addr(const mrange_t *range, vmpa2t *addr) /****************************************************************************** * * +* Paramètres : range = élément à venir lire. [OUT] * +* pbuf = paquet de données où venir puiser les infos. * +* * +* Description : Lit la définition d'une couverture depuis un tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool unpack_mrange(mrange_t *range, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + result = unpack_vmpa(&range->addr, pbuf); + + if (result) + result = extract_packed_buffer(pbuf, (uint64_t *)&range->length, sizeof(uint64_t), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : range = élément à venir écrire. * +* pbuf = paquet de données où venir inscrire les infos. * +* * +* Description : Ecrit la définition d'une couverture dans un tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool pack_mrange(const mrange_t *range, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + result = pack_vmpa(&range->addr, pbuf); + + if (result) + result = extend_packed_buffer(pbuf, (uint64_t *)&range->length, sizeof(uint64_t), true); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : rane = emplacement virtuel ou physique à traiter. * * msize = taille de cette adresse, réelle ou désirée. * * start = indique si le début ou la fin est à imprimer. * diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 96fb52b..a1c60dd 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -121,10 +121,10 @@ void align_vmpa(vmpa2t *, phys_t); /* Calcule au mieux la distance entre deux coordonnées. */ phys_t compute_vmpa_diff(const vmpa2t *, const vmpa2t *); -/* Lit la définition d'une adresse depuis un flux réseau. */ +/* Lit la définition d'une adresse depuis un tampon. */ bool unpack_vmpa(vmpa2t *, packed_buffer *); -/* Ecrit la définition d'une adresse dans un flux réseau. */ +/* Ecrit la définition d'une adresse dans un tampon. */ bool pack_vmpa(const vmpa2t *, packed_buffer *); /* Transforme une adresse physique en chaîne de caractères. */ @@ -227,6 +227,12 @@ bool mrange_intersects_mrange(const mrange_t *, const mrange_t *); /* Calcule la position extérieure finale d'une couverture. */ void compute_mrange_end_addr(const mrange_t *, vmpa2t *); +/* Lit la définition d'une couverture depuis un tampon. */ +bool unpack_mrange(mrange_t *, packed_buffer *); + +/* Ecrit la définition d'une couverture dans un tampon. */ +bool pack_mrange(const mrange_t *, packed_buffer *); + /* Transforme un emplacement physique en chaîne de caractères. */ char *mrange_phys_to_string(const mrange_t *, MemoryDataSize, bool, char [VMPA_MAX_LEN], size_t *); diff --git a/src/common/packed.c b/src/common/packed.c index 1abfa98..ca6e816 100644 --- a/src/common/packed.c +++ b/src/common/packed.c @@ -53,6 +53,25 @@ void init_packed_buffer(packed_buffer *pbuf) pbuf->allocated = PACKET_BLOCK_SIZE; pbuf->data = malloc(pbuf->allocated * sizeof(uint8_t)); + reset_packed_buffer(pbuf); + +} + + +/****************************************************************************** +* * +* Paramètres : pbuf = paquet de données à réinitialiser. [OUT] * +* * +* Description : Réinitialise un paquet réseau pour une constitution. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void reset_packed_buffer(packed_buffer *pbuf) +{ pbuf->used = 0; pbuf->pos = sizeof(uint32_t); diff --git a/src/common/packed.h b/src/common/packed.h index 64d5d20..d25c947 100644 --- a/src/common/packed.h +++ b/src/common/packed.h @@ -49,6 +49,9 @@ typedef struct _packed_buffer /* Initialise un paquet réseau pour une constitution. */ void init_packed_buffer(packed_buffer *); +/* Réinitialise un paquet réseau pour une constitution. */ +void reset_packed_buffer(packed_buffer *); + /* Efface les données contenues par un paquet réseau. */ void exit_packed_buffer(packed_buffer *); diff --git a/src/core/core.c b/src/core/core.c index 5e3a4d0..bc1a9dc 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -106,6 +106,8 @@ bool load_all_basic_components(void) result &= init_segment_content_hash_table(); + register_arch_gtypes(); + result &= load_hard_coded_processors_definitions(); result &= load_hard_coded_formats_definitions(); diff --git a/src/core/processors.c b/src/core/processors.c index 0251f6f..12c63cf 100644 --- a/src/core/processors.c +++ b/src/core/processors.c @@ -29,6 +29,11 @@ #include +#include "../arch/immediate.h" +#include "../arch/raw.h" +#include "../arch/register.h" +#include "../arch/target.h" +#include "../arch/undefined.h" //#include "../arch/jvm/processor.h" @@ -58,6 +63,29 @@ static proc_t *find_processor_by_key(const char *); /****************************************************************************** * * +* Paramètres : - * +* * +* Description : Assure l'enregistrement de types pour les caches à charger. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void register_arch_gtypes(void) +{ + g_type_ensure(G_TYPE_RAW_INSTRUCTION); + g_type_ensure(G_TYPE_UNDEF_INSTRUCTION); + + g_type_ensure(G_TYPE_IMM_OPERAND); + g_type_ensure(G_TYPE_REGISTER_OPERAND); + +} + + +/****************************************************************************** +* * * Paramètres : key = désignation rapide et interne d'un processeur. * * name = désignation humaine de l'architecture. * * instance = type GLib représentant le type à instancier. * diff --git a/src/core/processors.h b/src/core/processors.h index 10bbcf3..f202114 100644 --- a/src/core/processors.h +++ b/src/core/processors.h @@ -32,6 +32,8 @@ #include "../arch/processor.h" +/* Assure l'enregistrement de types pour les caches à charger. */ +void register_arch_gtypes(void); /* Enregistre un processeur pour une architecture donnée. */ bool register_processor_type(const char *, const char *, GType); diff --git a/src/core/queue.c b/src/core/queue.c index 79a87b2..4439e61 100644 --- a/src/core/queue.c +++ b/src/core/queue.c @@ -67,6 +67,13 @@ bool init_global_works(void) g_work_queue_define_work_group(queue); #endif +#ifndef NDEBUG + expected = g_work_queue_define_work_group(queue); + assert(expected == STORAGE_WORK_GROUP); +#else + g_work_queue_define_work_group(queue); +#endif + return true; } @@ -111,9 +118,10 @@ void wait_for_all_global_works(void) { GWorkQueue *queue; /* Singleton pour tâches */ - static const wgroup_id_t group_ids[] = { + static const wgroup_id_t group_ids[GLOBAL_WORK_GROUPS_COUNT] = { DEFAULT_WORK_GROUP, - LOADING_WORK_GROUP + LOADING_WORK_GROUP, + STORAGE_WORK_GROUP }; queue = get_work_queue(); diff --git a/src/core/queue.h b/src/core/queue.h index bee16a4..a1b82f2 100644 --- a/src/core/queue.h +++ b/src/core/queue.h @@ -35,8 +35,9 @@ #define DEFAULT_WORK_GROUP 0 #define LOADING_WORK_GROUP 1 +#define STORAGE_WORK_GROUP 2 -#define GLOBAL_WORK_GROUPS_COUNT 2 +#define GLOBAL_WORK_GROUPS_COUNT 3 /* Met en place les mécanismes de traitements parallèles. */ diff --git a/src/main.c b/src/main.c index 583e00c..d9f356f 100644 --- a/src/main.c +++ b/src/main.c @@ -31,6 +31,7 @@ #include #include +#include "analysis/binary.h" #include "analysis/loading.h" #include "analysis/contents/file.h" #include "analysis/db/server.h" @@ -60,6 +61,9 @@ static gboolean load_last_project(GGenConfig *); /* Ouvre les éventuels fichiers fournis au démarrage. */ static int open_binaries(char **, int); +/* Sauvegarde le cache des binaires analysés. */ +static int save_binary_caches(void); + /****************************************************************************** @@ -94,6 +98,7 @@ static void show_chrysalide_help(const char *name) printf("\t-V --verbosity=level\tSet the log level (0 for all messages, %u for none).\n", LMT_COUNT); printf("\t-b --batch\t\tExit after processing files.\n"); + printf("\t-s --save\t\tSave disassembly cache after analysis in batch mode (ignored in normal mode).\n"); printf("\t-p --project=filename\tOpen an existing project or create a new one.\n"); printf("\n"); @@ -152,6 +157,7 @@ int main(int argc, char **argv) bool show_version; /* Affichage de la version ? */ LogMessageType verbosity; /* Niveau de filtre de message */ bool batch_mode; /* Exécution sans GUI ? */ + bool save; /* Sauvegarde du cache ? */ char *prj_filename; /* Chemin vers un projet */ int index; /* Indice d'argument */ int ret; /* Bilan d'un appel */ @@ -172,6 +178,7 @@ int main(int argc, char **argv) { "version", no_argument, NULL, 'v' }, { "verbosity", required_argument, NULL, 'V' }, { "batch", no_argument, NULL, 'b' }, + { "save", no_argument, NULL, 's' }, { "project", required_argument, NULL, 'p' }, { NULL, 0, NULL, 0 } }; @@ -192,11 +199,12 @@ int main(int argc, char **argv) verbosity = LMT_INFO; batch_mode = false; + save = false; prj_filename = NULL; while (true) { - ret = getopt_long(argc, argv, "hvV:bp:", long_options, &index); + ret = getopt_long(argc, argv, "hvV:bsp:", long_options, &index); if (ret == -1) break; switch (ret) @@ -217,6 +225,10 @@ int main(int argc, char **argv) batch_mode = true; break; + case 's': + save = true; + break; + case 'p': prj_filename = optarg; break; @@ -344,8 +356,17 @@ int main(int argc, char **argv) result = open_binaries(argv + optind, argc - optind); if (batch_mode) + { wait_for_all_global_works(); + if (save && result == EXIT_SUCCESS) + { + result = save_binary_caches(); + wait_for_all_global_works(); + } + + } + else gtk_main(); @@ -378,7 +399,6 @@ int main(int argc, char **argv) /****************************************************************************** * * * Paramètres : cfg = configuration globale sur laquelle s'appuyer. * -* ref = espace de référencement global. * * * * Description : Recharge le dernier projet ouvert s'il existe. * * * @@ -450,3 +470,52 @@ static int open_binaries(char **files, int count) return result; } + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Sauvegarde le cache des binaires analysés. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int save_binary_caches(void) +{ + int result; /* Bilan à retourner */ + GStudyProject *project; /* Projet courant à compléter */ + GLoadedContent **loaded; /* Contenus chargés et analysés*/ + size_t count; /* Quantité de ces contenus */ + size_t i; /* Boucle de parcours */ + bool status; /* Bilan de lancement */ + + result = EXIT_SUCCESS; + + project = get_current_project(); + + loaded = g_study_project_get_contents(project, &count); + + for (i = 0; i < count; i++) + { + if (G_IS_LOADED_BINARY(loaded[i])) + { + status = g_loaded_binary_save_cache(G_LOADED_BINARY(loaded[i])); + if (!status) result = EXIT_FAILURE; + } + + g_object_unref(G_OBJECT(loaded[i])); + + } + + if (loaded != NULL) + free(loaded); + + g_object_unref(G_OBJECT(project)); + + return result; + +} -- cgit v0.11.2-87-g4458