summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-12-14 23:30:12 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-12-14 23:30:12 (GMT)
commitdb1a6171007a6641a4659392c9bcc05670396643 (patch)
treed011651b8b73b2a28d01e416d613d63bf5b0b4e6 /src
parentba6ca32c37c5db2582a015ed15d6ba128c36968e (diff)
Provided an iterator for instructions.
Diffstat (limited to 'src')
-rw-r--r--src/arch/Makefile.am1
-rw-r--r--src/arch/instriter.c135
-rw-r--r--src/arch/instriter.h50
-rw-r--r--src/arch/instruction.h2
-rw-r--r--src/arch/processor-int.h5
-rw-r--r--src/arch/processor.c196
-rw-r--r--src/arch/processor.h18
7 files changed, 362 insertions, 45 deletions
diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am
index 030ee87..a7ff3a2 100644
--- a/src/arch/Makefile.am
+++ b/src/arch/Makefile.am
@@ -6,6 +6,7 @@ libarch_la_SOURCES = \
context-int.h \
context.h context.c \
immediate.h immediate.c \
+ instriter.h instriter.c \
instruction-int.h \
instruction.h instruction.c \
link.h link.c \
diff --git a/src/arch/instriter.c b/src/arch/instriter.c
new file mode 100644
index 0000000..0f33998
--- /dev/null
+++ b/src/arch/instriter.c
@@ -0,0 +1,135 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instriter.h - prototypes pour le parcours simplifié d'un ensemble d'instructions
+ *
+ * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "instriter.h"
+
+
+#include <malloc.h>
+
+
+#include "processor.h"
+
+
+
+/* Suivi d'un parcours d'instructions */
+typedef struct _instr_iter_t
+{
+ GArchProcessor *proc; /* Conteneur associé */
+ unsigned int stamp; /* Suivi d'évolutions externes */
+
+ size_t index; /* Instruction courante */
+
+} instr_iter_t;
+
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = processeur recensant diverses instructions. *
+* index = indice de la première instruction à fournir. *
+* *
+* Description : Construit un itérateur pour parcourir des instructions. *
+* *
+* Retour : Itérateur prêt à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+instr_iter_t *create_instruction_iterator(GArchProcessor *proc, size_t index)
+{
+ instr_iter_t *result; /* Structure à retourner */
+
+ result = (instr_iter_t *)malloc(sizeof(instr_iter_t));
+
+ g_object_ref(G_OBJECT(proc));
+
+ result->proc = proc;
+ result->stamp = g_arch_processor_get_stamp(proc);
+
+ result->index = index;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iter = itérateur à traiter. *
+* *
+* Description : Détruit un itérateur mis en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_instruction_iterator(instr_iter_t *iter)
+{
+ g_object_unref(G_OBJECT(iter->proc));
+
+ free(iter);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iter = itérateur à manipuler. *
+* *
+* Description : Fournit l'instruction qui en suit une autre. *
+* *
+* Retour : Instruction suivante trouvée, ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchInstruction *get_instruction_iterator_next(instr_iter_t *iter)
+{
+ GArchInstruction *result; /* Résultat à retourner */
+
+ g_arch_processor_lock(iter->proc);
+
+ if (iter->stamp != g_arch_processor_get_stamp(iter->proc))
+ result = NULL;
+
+ else
+ {
+ if (iter->index < g_arch_processor_count_disassembled_instructions(iter->proc))
+ result = g_arch_processor_get_disassembled_instruction(iter->proc, iter->index);
+ else
+ result = NULL;
+
+ if (result != NULL)
+ iter->index++;
+
+ }
+
+ g_arch_processor_unlock(iter->proc);
+
+ return result;
+
+}
diff --git a/src/arch/instriter.h b/src/arch/instriter.h
new file mode 100644
index 0000000..b9c7621
--- /dev/null
+++ b/src/arch/instriter.h
@@ -0,0 +1,50 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * instriter.h - prototypes pour le parcours simplifié d'un ensemble d'instructions
+ *
+ * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_INSTRITER_H
+#define _ARCH_INSTRITER_H
+
+
+#include "instruction.h"
+
+
+
+/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */
+typedef struct _GArchProcessor GArchProcessor;
+
+/* Suivi d'un parcours d'instructions */
+typedef struct _instr_iter_t instr_iter_t;
+
+
+/* Construit un itérateur pour parcourir des instructions. */
+instr_iter_t *create_instruction_iterator(GArchProcessor *, size_t);
+
+/* Détruit un itérateur mis en place. */
+void delete_instruction_iterator(instr_iter_t *);
+
+/* Fournit l'instruction qui en suit une autre. */
+GArchInstruction *get_instruction_iterator_next(instr_iter_t *);
+
+
+
+#endif /* _ARCH_INSTRITER_H */
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index d625e77..bddc2bf 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -84,7 +84,7 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *);
* On procède donc à une seconde déclaration, en attendant éventuellement mieux.
*/
-/* Ligne de représentation générique (instance) */
+/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */
typedef struct _GArchProcessor GArchProcessor;
diff --git a/src/arch/processor-int.h b/src/arch/processor-int.h
index 8631731..b170cad 100644
--- a/src/arch/processor-int.h
+++ b/src/arch/processor-int.h
@@ -87,6 +87,11 @@ struct _GArchProcessor
GArchInstruction **instructions; /* Instructions désassemblées */
size_t instr_allocated; /* Taille de la liste allouée */
size_t instr_count; /* Taille de la liste aplatie */
+ unsigned int stamp; /* Marque de suivi des modifs */
+ GMutex mutex; /* Verrou pour l'accès */
+#ifndef NDEBUG
+ gint locked; /* Statut d'accès à la liste */
+#endif
instr_coverage *coverages; /* Liste de couvertures */
size_t cov_allocated; /* Taille de la liste allouée */
diff --git a/src/arch/processor.c b/src/arch/processor.c
index 615aa86..26c7170 100644
--- a/src/arch/processor.c
+++ b/src/arch/processor.c
@@ -59,6 +59,12 @@ static void g_arch_processor_class_init(GArchProcessorClass *);
/* Initialise une instance de processeur d'architecture. */
static void g_arch_processor_init(GArchProcessor *);
+/* Supprime toutes les références externes. */
+static void g_arch_processor_dispose(GArchProcessor *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_arch_processor_finalize(GArchProcessor *);
+
@@ -76,6 +82,9 @@ static void g_arch_processor_finish_last_coverage(GArchProcessor *, GArchInstruc
+
+
+
/* Indique le type défini pour un processeur d'architecture. */
G_DEFINE_TYPE(GArchProcessor, g_arch_processor, G_TYPE_OBJECT);
@@ -94,6 +103,12 @@ G_DEFINE_TYPE(GArchProcessor, g_arch_processor, G_TYPE_OBJECT);
static void g_arch_processor_class_init(GArchProcessorClass *klass)
{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_processor_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_arch_processor_finalize;
}
@@ -112,6 +127,11 @@ static void g_arch_processor_class_init(GArchProcessorClass *klass)
static void g_arch_processor_init(GArchProcessor *proc)
{
+#ifndef DEBUG
+ g_atomic_int_set(&proc->loacked, 0);
+#endif
+ g_mutex_init(&proc->mutex);
+
proc->coverages = NULL;
proc->cov_allocated = 0;
proc->cov_count = 0;
@@ -121,6 +141,46 @@ static void g_arch_processor_init(GArchProcessor *proc)
/******************************************************************************
* *
+* Paramètres : proc = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arch_processor_dispose(GArchProcessor *proc)
+{
+ g_mutex_clear(&proc->mutex);
+
+ G_OBJECT_CLASS(g_arch_processor_parent_class)->dispose(G_OBJECT(proc));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_arch_processor_finalize(GArchProcessor *proc)
+{
+ G_OBJECT_CLASS(g_arch_processor_parent_class)->finalize(G_OBJECT(proc));
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : proc = architecture visée par la procédure. *
* *
* Description : Fournit un contexte propre au processeur d'une architecture. *
@@ -268,6 +328,62 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *proc, GProc
/* ---------------------------------------------------------------------------------- */
+/* RASSEMBLEMENT DES INSTRUCTIONS DESASSEMBLEES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = architecture à manipuler. *
+* state = nouvel état de l'accès aux instructions. *
+* *
+* Description : Protège ou lève la protection de l'accès aux instructions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_arch_processor_lock_unlock(GArchProcessor *proc, bool state)
+{
+ if (state)
+ {
+ g_mutex_lock(&proc->mutex);
+ g_atomic_int_set(&proc->locked, 1);
+ }
+ else
+ {
+ g_atomic_int_set(&proc->locked, 0);
+ g_mutex_unlock(&proc->mutex);
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : proc = architecture à consulter via la procédure. *
+* *
+* Description : Fournit la marque de dernière modification des instructions. *
+* *
+* Retour : Marque de la dernière modification de la liste d'instruct°. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+unsigned int g_arch_processor_get_stamp(const GArchProcessor *proc)
+{
+ //assert(g_atomic_int_get(&proc->locked) == 1);
+
+ return proc->stamp;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
/* MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES */
/* ---------------------------------------------------------------------------------- */
@@ -348,48 +464,6 @@ static void g_arch_processor_finish_last_coverage(GArchProcessor *proc, GArchIns
/******************************************************************************
* *
-* Paramètres : proc = processeur recensant diverses instructions. *
-* addr = position en mémoire ou physique à chercher. *
-* *
-* Description : Recherche un groupe d'instruction d'après son adresse. *
-* *
-* Retour : Couverture trouvée ou NULL si aucune. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProcessor *proc, const vmpa2t *addr)
-{
- instr_coverage *result; /* Trouvaille à retourner */
- void *ptr; /* Résultat des recherches */
-
- int search_for_coverage_by_addr(const vmpa2t *a, const instr_coverage *c)
- {
- int status; /* Bilan d'une comparaison */
-
- status = cmp_mrange_with_vmpa(&c->range, a);
-
- return status;
-
- }
-
- ptr = bsearch(addr, proc->coverages, proc->cov_count,
- sizeof(instr_coverage), (__compar_fn_t)search_for_coverage_by_addr);
-
- result = ((instr_coverage *)ptr);
-
- return result;
-
-}
-
-
-
-
-
-
-/******************************************************************************
-* *
* Paramètres : proc = architecture visée par la procédure. *
* list = liste des instructions désassemblées. *
* *
@@ -519,6 +593,44 @@ size_t g_arch_processor_count_disassembled_instructions(const GArchProcessor *pr
/******************************************************************************
* *
+* Paramètres : proc = processeur recensant diverses instructions. *
+* addr = position en mémoire ou physique à chercher. *
+* *
+* Description : Recherche un groupe d'instruction d'après son adresse. *
+* *
+* Retour : Couverture trouvée ou NULL si aucune. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const instr_coverage *g_arch_processor_find_coverage_by_address(const GArchProcessor *proc, const vmpa2t *addr)
+{
+ instr_coverage *result; /* Trouvaille à retourner */
+ void *ptr; /* Résultat des recherches */
+
+ int search_for_coverage_by_addr(const vmpa2t *a, const instr_coverage *c)
+ {
+ int status; /* Bilan d'une comparaison */
+
+ status = cmp_mrange_with_vmpa(&c->range, a);
+
+ return status;
+
+ }
+
+ ptr = bsearch(addr, proc->coverages, proc->cov_count,
+ sizeof(instr_coverage), (__compar_fn_t)search_for_coverage_by_addr);
+
+ result = ((instr_coverage *)ptr);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : proc = processeur recensant diverses instructions. *
* addr = position en mémoire ou physique à chercher. *
* nearby = la recherche s'effectue-t-elle de façon stricte ? *
diff --git a/src/arch/processor.h b/src/arch/processor.h
index f0f9b55..02b3533 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -44,10 +44,10 @@
-/* Ligne de représentation générique (instance) */
+/* Définition générique d'un processeur d'architecture (instance) */
typedef struct _GArchProcessor GArchProcessor;
-/* Ligne de représentation générique (classe) */
+/* Définition générique d'un processeur d'architecture (classe) */
typedef struct _GArchProcessorClass GArchProcessorClass;
@@ -74,6 +74,20 @@ GArchInstruction *g_arch_processor_disassemble(const GArchProcessor *, GProcCont
+/* ------------------ RASSEMBLEMENT DES INSTRUCTIONS DESASSEMBLEES ------------------ */
+
+
+/* Protège ou lève la protection de l'accès aux instructions. */
+void g_arch_processor_lock_unlock(GArchProcessor *, bool);
+
+#define g_arch_processor_lock(p) g_arch_processor_lock_unlock(p, true)
+#define g_arch_processor_unlock(p) g_arch_processor_lock_unlock(p, false)
+
+/* Fournit la marque de dernière modification des instructions. */
+unsigned int g_arch_processor_get_stamp(const GArchProcessor *);
+
+
+
/* ------------------ MANIPULATIONS DES INSTRUCTIONS DESASSEMBLEES ------------------ */