From 0f0cb560006c0ef5eb690f89c4ce720936c9d6f6 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 28 Oct 2016 21:40:19 +0200
Subject: Stored instruction hooks in the data section rather than in the heap.

---
 ChangeLog                  | 10 ++++++
 src/arch/instruction-int.h |  2 +-
 src/arch/instruction.c     |  8 ++---
 src/arch/instruction.h     |  2 +-
 tools/d2c/hooks/manager.c  | 90 +++++++++++++++++++++++++++++++++++++++++-----
 tools/d2c/hooks/manager.h  |  3 ++
 tools/d2c/spec.c           |  4 +++
 7 files changed, 103 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 52e0a39..169362f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+16-10-28  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/instruction-int.h:
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	* tools/d2c/hooks/manager.c:
+	* tools/d2c/hooks/manager.h:
+	* tools/d2c/spec.c:
+	Store instruction hooks in the data section rather than in the heap.
+
 16-10-26  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/loop.c:
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index dca63e7..8eb6b68 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -63,7 +63,7 @@ struct _GArchInstruction
     phys_t max_displayed_len;               /* Quantité de code affichée   */
 
     ArchInstrFlag flags;                    /* Informations complémentaires*/
-    instr_hook_fc hooks[IPH_COUNT];         /* Traitements complémentaires */
+    const instr_hook_fc *hooks;             /* Traitements complémentaires */
 
     mrange_t range;                         /* Emplacement en mémoire      */
 
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 8264f5b..4c0fdb9 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -281,11 +281,9 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
 *                                                                             *
 ******************************************************************************/
 
-void g_arch_instruction_set_hook(GArchInstruction *instr, InstrProcessHook type, instr_hook_fc hook)
+void g_arch_instruction_set_hooks(GArchInstruction *instr, const instr_hook_fc hooks[IPH_COUNT])
 {
-    assert(type < IPH_COUNT);
-
-    instr->hooks[type] = hook;
+    instr->hooks = hooks;
 
 }
 
@@ -310,7 +308,7 @@ void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type
 {
     assert(type < IPH_COUNT);
 
-    if (instr->hooks[type] != NULL)
+    if (instr->hooks != NULL && instr->hooks[type] != NULL)
         instr->hooks[type](instr, proc, context, format);
 
 }
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index e902849..93dfa52 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -117,7 +117,7 @@ typedef enum _InstrProcessHook
 typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GBinFormat *);
 
 /* Définit un traitement complémentare au désassemblage. */
-void g_arch_instruction_set_hook(GArchInstruction *, InstrProcessHook, instr_hook_fc);
+void g_arch_instruction_set_hooks(GArchInstruction *, const instr_hook_fc [IPH_COUNT]);
 
 /* Complète un désassemblage accompli pour une instruction. */
 void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GBinFormat *);
diff --git a/tools/d2c/hooks/manager.c b/tools/d2c/hooks/manager.c
index 67c09f8..2db4bbc 100644
--- a/tools/d2c/hooks/manager.c
+++ b/tools/d2c/hooks/manager.c
@@ -137,7 +137,7 @@ void register_hook_function(instr_hooks *hooks, char *type, char *name)
 *                top   = indique si l'écriture se réalise au plus haut niveau.*
 *                fd    = descripteur d'un flux ouvert en écriture.            *
 *                                                                             *
-*  Description : Associe dans le code des fonctions à une instruction.        *
+*  Description : Déclare des opérations complémentaires pour une instruction. *
 *                                                                             *
 *  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
@@ -145,29 +145,101 @@ void register_hook_function(instr_hooks *hooks, char *type, char *name)
 *                                                                             *
 ******************************************************************************/
 
-bool write_hook_functions(const instr_hooks *hooks, bool top, int fd)
+bool declare_hook_functions(const instr_hooks *hooks, bool top, int fd)
 {
     bool result;                            /* Bilan à retourner           */
-    size_t i;                               /* Boucle de parcours          */
-    instr_func *func;                       /* Nouvelle prise en compte    */
+    size_t i;                               /* Boucle de parcours #1       */
+    const instr_func *func;                 /* Nouvelle prise en compte    */
+
+    static const char *hook_types[] = {
+        "FETCH",
+        "LINK",
+        "POST"
+    };
+
+    const instr_func *find_hook_by_name(const instr_hooks *list, const char *type)
+    {
+        const instr_func *hook;             /* Trouvaille à retourner      */
+        size_t k;                           /* Boucle de parcours #2       */
+
+        hook = NULL;
+
+        for (k = 0; k < list->func_count && hook == NULL; k++)
+            if (strcmp(list->funcs[k].type, type) == 0)
+                hook = &list->funcs[k];
+
+        return hook;
+
+    }
 
     result = true;
 
-    for (i = 0; i < hooks->func_count && result; i++)
+    if (hooks->func_count > 0)
     {
-        func = &hooks->funcs[i];
+        if (!top)
+            dprintf(fd, "\t");
+
+        dprintf(fd, "\tstatic const instr_hook_fc hooks[IPH_COUNT] = {\n\n");
+
+        for (i = 0; i < (sizeof(hook_types) / sizeof(hook_types[0])); i++)
+        {
+            func = find_hook_by_name(hooks, hook_types[i]);
+
+            if (!top)
+                dprintf(fd, "\t");
+
+            dprintf(fd, "\t\t[IPH_%s] = (instr_hook_fc)%s,\n", hook_types[i], func != NULL ? func->name : "NULL");
+
+        }
+
+        dprintf(fd, "\n");
 
         if (!top)
             dprintf(fd, "\t");
 
-        dprintf(fd, "\tg_arch_instruction_set_hook(%s, IPH_%s, (instr_hook_fc)%s);\n",
-                top ? "result" : "instr", func->type, func->name);
+        dprintf(fd, "\t};\n");
+
+        dprintf(fd, "\n");
 
     }
 
-    if (hooks->func_count > 0 && result)
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : hooks = gestionnaire d'un ensemble de fonctions associées.   *
+*                top   = indique si l'écriture se réalise au plus haut niveau.*
+*                fd    = descripteur d'un flux ouvert en écriture.            *
+*                                                                             *
+*  Description : Associe dans le code des fonctions à une instruction.        *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool write_hook_functions(const instr_hooks *hooks, bool top, int fd)
+{
+    bool result;                            /* Bilan à retourner           */
+
+    result = true;
+
+    if (hooks->func_count > 0)
+    {
+        if (!top)
+            dprintf(fd, "\t");
+
+        dprintf(fd, "\tg_arch_instruction_set_hooks(%s, hooks);\n",
+                top ? "result" : "instr");
+
         dprintf(fd, "\n");
 
+    }
+
     return result;
 
 }
diff --git a/tools/d2c/hooks/manager.h b/tools/d2c/hooks/manager.h
index 97bd388..1a50d0a 100644
--- a/tools/d2c/hooks/manager.h
+++ b/tools/d2c/hooks/manager.h
@@ -43,6 +43,9 @@ void delete_instr_hooks(instr_hooks *);
 /* Enregistre l'utilité d'une fonction pour une instruction. */
 void register_hook_function(instr_hooks *, char *, char *);
 
+/* Déclare des opérations complémentaires pour une instruction. */
+bool declare_hook_functions(const instr_hooks *, bool, int);
+
 /* Associe dans le code des fonctions à une instruction. */
 bool write_hook_functions(const instr_hooks *, bool, int);
 
diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c
index 1d91fed..5aa7066 100644
--- a/tools/d2c/spec.c
+++ b/tools/d2c/spec.c
@@ -332,6 +332,8 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a
 
     dprintf(fd, "\n");
 
+    result &= declare_hook_functions(spec->hooks, false, fd);
+
     /* Vérification que le décodage est possible */
 
     result &= check_bits_correctness(spec->bits, fd);
@@ -457,6 +459,8 @@ bool write_encoding_spec_format_disass(const encoding_spec *spec, int fd, const
 
     dprintf(fd, "\n");
 
+    result &= declare_hook_functions(spec->hooks, true, fd);
+
     /* Création de l'instruction en elle-même */
 
     new_ins = get_new_keyword_from_syntax_items(spec->syntax);
-- 
cgit v0.11.2-87-g4458