summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2021-12-30 18:28:18 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2021-12-30 18:44:35 (GMT)
commit945e0c9ecce02155555387aad672e272f5646362 (patch)
tree3d35bdb25012a9ef710a13c9e733b5a80f6641b1 /src
parent98570719ff25a4dcde917056e55490bf2a6b1453 (diff)
Create generic functions to load and store operands.
Diffstat (limited to 'src')
-rw-r--r--src/analysis/storage/storage.c75
-rw-r--r--src/analysis/storage/storage.h3
-rw-r--r--src/arch/Makefile.am2
-rw-r--r--src/arch/operand-int.c308
-rw-r--r--src/arch/operand-int.h42
-rw-r--r--src/arch/operand.c8
6 files changed, 430 insertions, 8 deletions
diff --git a/src/analysis/storage/storage.c b/src/analysis/storage/storage.c
index e286641..c641a52 100644
--- a/src/analysis/storage/storage.c
+++ b/src/analysis/storage/storage.c
@@ -28,6 +28,7 @@
#include <malloc.h>
#include <string.h>
#include <unistd.h>
+#include <stdarg.h>
#include "storage-int.h"
@@ -702,6 +703,67 @@ GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, con
/******************************************************************************
* *
+* Paramètres : storage = gestionnaire à manipuler. *
+* name = désignation d'un nouveau groupe d'objets. *
+* pbuf = zone tampon à parcourir. *
+* expected = type d'objet attendu. *
+* ... = élément restauré ou NULL en cas d'échec. [OUT] *
+* *
+* Description : Charge un objet interne à partir de données rassemblées. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf, GType expected, ...)
+{
+ bool result; /* Bilan d'une opération */
+ uint64_t pos; /* Localisation des données */
+ GSerializableObject *instance; /* Objet rechargé à valider */
+ va_list ap; /* Liste d'arguments variables */
+ void **object; /* Lieu d'enregistrement final */
+
+ result = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true);
+
+ if (result)
+ {
+ if (pos == 0)
+ *object = NULL;
+
+ else
+ {
+ instance = g_object_storage_load_object(storage, name, pos);
+
+ result = G_TYPE_CHECK_INSTANCE_TYPE(instance, expected);
+
+ if (result)
+ {
+ va_start(ap, expected);
+
+ object = va_arg(ap, void **);
+
+ *object = instance;
+
+ va_end(ap);
+
+ }
+
+ else
+ g_clear_object(&instance);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : storage = gestionnaire à manipuler. *
* name = désignation d'un nouveau groupe d'objets. *
* object = objet sérialisable à traiter. *
@@ -787,10 +849,17 @@ bool g_object_storage_pack_object(GObjectStorage *storage, const char *name, con
bool result; /* Bilan à retourner */
off64_t pos; /* Localisation des données */
- result = g_object_storage_store_object(storage, name, object, &pos);
+ if (object == NULL)
+ result = extend_packed_buffer(pbuf, (uint64_t []){ 0 }, sizeof(uint64_t), true);
- if (result)
- result = extend_packed_buffer(pbuf, (uint64_t []){ pos }, sizeof(uint64_t), true);
+ else
+ {
+ result = g_object_storage_store_object(storage, name, object, &pos);
+
+ if (result)
+ result = extend_packed_buffer(pbuf, (uint64_t []){ pos }, sizeof(uint64_t), true);
+
+ }
return result;
diff --git a/src/analysis/storage/storage.h b/src/analysis/storage/storage.h
index 0d35d78..cc0caad 100644
--- a/src/analysis/storage/storage.h
+++ b/src/analysis/storage/storage.h
@@ -78,6 +78,9 @@ GSerializableObject *g_object_storage_unpack_object(GObjectStorage *, const char
/* Sauvegarde un object sous forme de données rassemblées. */
bool g_object_storage_store_object(GObjectStorage *, const char *, const GSerializableObject *, off64_t *);
+/* Charge un objet interne à partir de données rassemblées. */
+bool g_object_storage_unpack_object_2(GObjectStorage *, const char *, packed_buffer_t *, GType, ...);
+
/* Sauvegarde un object interne sous forme de données. */
bool g_object_storage_pack_object(GObjectStorage *, const char *, const GSerializableObject *, packed_buffer_t *);
diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am
index 3ea5713..8a2eea3 100644
--- a/src/arch/Makefile.am
+++ b/src/arch/Makefile.am
@@ -9,7 +9,7 @@ libarch_la_SOURCES = \
instruction-int.h \
instruction.h instruction.c \
link.h link.c \
- operand-int.h \
+ operand-int.h operand-int.c \
operand.h operand.c \
post.h post.c \
processor-int.h \
diff --git a/src/arch/operand-int.c b/src/arch/operand-int.c
new file mode 100644
index 0000000..51e8d44
--- /dev/null
+++ b/src/arch/operand-int.c
@@ -0,0 +1,308 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * operand-int.c - définition générique interne des opérandes
+ *
+ * Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "operand-int.h"
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONSERVATION ET RECHARGEMENT DES DONNEES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à consulter. *
+* count = quantité d'opérandes à extraire du tampon. *
+* *
+* Description : Charge une série d'opérandes internes depuis un tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool _g_arch_operand_load_inner_instances(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf, size_t count)
+{
+ bool result; /* Bilan à retourner */
+ GArchOperand **instances; /* Liste d'opérandes à charger */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ instances = calloc(count, sizeof(GArchOperand *));
+
+ for (i = 0; i < count && result; i++)
+ result = g_object_storage_unpack_object_2(storage, "operands", pbuf, G_TYPE_ARCH_OPERAND, &instances[i]);
+
+ if (result)
+ g_arch_operand_update_inner_instances(operand, instances, count);
+
+ for (i = 0; i < count; i++)
+ g_clear_object(&instances[i]);
+
+ free(instances);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à consulter. *
+* *
+* Description : Charge une série d'opérandes internes depuis un tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_arch_operand_load_generic_fixed_1(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GType type; /* Type d'opérande manipulé */
+ GArchOperandClass *parent; /* Classe parente à consulter */
+
+ type = G_TYPE_FROM_INSTANCE(operand);
+
+ parent = g_type_class_peek_parent(g_type_class_peek(type));
+
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
+
+ if (result)
+ result = _g_arch_operand_load_inner_instances(operand, storage, pbuf, 1);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à consulter. *
+* *
+* Description : Charge une série d'opérandes internes depuis un tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_arch_operand_load_generic_fixed_3(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GType type; /* Type d'opérande manipulé */
+ GArchOperandClass *parent; /* Classe parente à consulter */
+
+ type = G_TYPE_FROM_INSTANCE(operand);
+
+ parent = g_type_class_peek_parent(g_type_class_peek(type));
+
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
+
+ if (result)
+ result = _g_arch_operand_load_inner_instances(operand, storage, pbuf, 3);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à consulter. *
+* *
+* Description : Charge une série d'opérandes internes depuis un tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_arch_operand_load_generic_variadic(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GType type; /* Type d'opérande manipulé */
+ GArchOperandClass *parent; /* Classe parente à consulter */
+ uleb128_t value; /* Valeur ULEB128 à charger */
+
+ type = G_TYPE_FROM_INSTANCE(operand);
+
+ parent = g_type_class_peek_parent(g_type_class_peek(type));
+
+ result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf);
+
+ if (result)
+ result = unpack_uleb128(&value, pbuf);
+
+ if (result)
+ result = _g_arch_operand_load_inner_instances(operand, storage, pbuf, value);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à remplir. *
+* fixed = précise si le nombre d'opérande est fixe ou non. *
+* *
+* Description : Sauvegarde une série d'opérandes internes dans un tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool _g_arch_operand_store_inner_instances(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf, bool fixed)
+{
+ bool result; /* Bilan à retourner */
+ size_t count; /* Nombre d'opérandes listées */
+ GArchOperand **instances; /* Liste d'opérandes à traiter */
+ size_t i; /* Boucle de parcours */
+ GSerializableObject *obj; /* Objet à conserver */
+
+ result = true;
+
+ instances = g_arch_operand_list_inner_instances(operand, &count);
+
+ if (!fixed)
+ result = pack_uleb128((uleb128_t []){ count }, pbuf);
+
+ if (instances != NULL)
+ {
+ for (i = 0; i < count && result; i++)
+ {
+ if (instances[i] == NULL)
+ result = g_object_storage_pack_object(storage, "operands", NULL, pbuf);
+
+ else
+ {
+ obj = G_SERIALIZABLE_OBJECT(instances[i]);
+
+ result = g_object_storage_pack_object(storage, "operands", obj, pbuf);
+
+ g_object_unref(G_OBJECT(instances[i]));
+
+ }
+
+ }
+
+ for (; i < count && result; i++)
+ g_clear_object(&instances[i]);
+
+ free(instances);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à remplir. *
+* fixed = précise si le nombre d'opérande est fixe ou non. *
+* *
+* Description : Sauvegarde un opérande dans un tampon de façon générique. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_arch_operand_store_generic_fixed(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GType type; /* Type d'opérande manipulé */
+ GArchOperandClass *parent; /* Classe parente à consulter */
+
+ type = G_TYPE_FROM_INSTANCE(operand);
+
+ parent = g_type_class_peek_parent(g_type_class_peek(type));
+
+ result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
+
+ if (result)
+ result = _g_arch_operand_store_inner_instances(operand, storage, pbuf, true);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = élément GLib à consulter. *
+* storage = conservateur de données à manipuler ou NULL. *
+* pbuf = zone tampon à remplir. *
+* fixed = précise si le nombre d'opérande est fixe ou non. *
+* *
+* Description : Sauvegarde un opérande dans un tampon de façon générique. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_arch_operand_store_generic_variadic(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf)
+{
+ bool result; /* Bilan à retourner */
+ GType type; /* Type d'opérande manipulé */
+ GArchOperandClass *parent; /* Classe parente à consulter */
+
+ type = G_TYPE_FROM_INSTANCE(operand);
+
+ parent = g_type_class_peek_parent(g_type_class_peek(type));
+
+ result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf);
+
+ if (result)
+ result = _g_arch_operand_store_inner_instances(operand, storage, pbuf, false);
+
+ return result;
+
+}
diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h
index dc505b6..d424e94 100644
--- a/src/arch/operand-int.h
+++ b/src/arch/operand-int.h
@@ -26,6 +26,11 @@
#include "operand.h"
+
+
+#include <stdbool.h>
+
+
#include "../analysis/storage/storage.h"
#include "../glibext/objhole.h"
@@ -143,4 +148,41 @@ bool _g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag, bool);
+/* ------------------------ CONTROLE DU VOLUME DES INSTANCES ------------------------ */
+
+
+/* Fournit une liste de candidats embarqués par un candidat. */
+GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *, size_t *);
+
+/* Met à jour une liste de candidats embarqués par un candidat. */
+void g_arch_operand_update_inner_instances(GArchOperand *, GArchOperand **, size_t);
+
+
+
+/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */
+
+
+/* Charge une série d'opérandes internes depuis un tampon. */
+bool _g_arch_operand_load_inner_instances(GArchOperand *, GObjectStorage *, packed_buffer_t *, size_t);
+
+/* Charge une série d'opérandes internes depuis un tampon. */
+bool g_arch_operand_load_generic_fixed_1(GArchOperand *, GObjectStorage *, packed_buffer_t *);
+
+/* Charge une série d'opérandes internes depuis un tampon. */
+bool g_arch_operand_load_generic_fixed_3(GArchOperand *, GObjectStorage *, packed_buffer_t *);
+
+/* Charge une série d'opérandes internes depuis un tampon. */
+bool g_arch_operand_load_generic_variadic(GArchOperand *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde une série d'opérandes internes dans un tampon. */
+bool _g_arch_operand_store_inner_instances(GArchOperand *, GObjectStorage *, packed_buffer_t *, bool);
+
+/* Sauvegarde un opérande dans un tampon de façon générique. */
+bool g_arch_operand_store_generic_fixed(GArchOperand *, GObjectStorage *, packed_buffer_t *);
+
+/* Sauvegarde un opérande dans un tampon de façon générique. */
+bool g_arch_operand_store_generic_variadic(GArchOperand *, GObjectStorage *, packed_buffer_t *);
+
+
+
#endif /* _ARCH_OPERAND_INT_H */
diff --git a/src/arch/operand.c b/src/arch/operand.c
index 81aa633..f262373 100644
--- a/src/arch/operand.c
+++ b/src/arch/operand.c
@@ -69,10 +69,10 @@ static int _g_arch_operand_compare(const GArchOperand *, const GArchOperand *, b
/* Fournit une liste de candidats embarqués par un candidat. */
-static GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *, size_t *);
+GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *, size_t *);
/* Met à jour une liste de candidats embarqués par un candidat. */
-static void g_arch_operand_update_inner_instances(GArchOperand *, GArchOperand **, size_t);
+void g_arch_operand_update_inner_instances(GArchOperand *, GArchOperand **, size_t);
/* Fournit l'empreinte d'un candidat à une centralisation. */
static guint _g_arch_operand_hash(const GArchOperand *, bool);
@@ -642,7 +642,7 @@ ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *operand)
* *
******************************************************************************/
-static GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand, size_t *count)
+GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand, size_t *count)
{
GArchOperand **result; /* Instances à retourner */
GArchOperandClass *class; /* Classe associée à l'objet */
@@ -677,7 +677,7 @@ static GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *op
* *
******************************************************************************/
-static void g_arch_operand_update_inner_instances(GArchOperand *operand, GArchOperand **instances, size_t count)
+void g_arch_operand_update_inner_instances(GArchOperand *operand, GArchOperand **instances, size_t count)
{
GArchOperandClass *class; /* Classe associée à l'objet */