From e873101ef61b19ddf7bf1ef9230143d0735c0fd8 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 30 Jan 2019 14:41:51 +0100
Subject: Extended the APIs available for formats (both native and Python).

---
 plugins/pychrysalide/format/executable.c | 41 ++++++++++++++++++++++++
 plugins/pychrysalide/format/format.c     | 36 +++++++++++++++++++++
 src/format/executable-int.h              |  2 ++
 src/format/executable.c                  | 54 +++++++++++++++++++++++++++++---
 src/format/executable.h                  |  5 ++-
 src/format/flat.c                        | 14 +++++----
 6 files changed, 141 insertions(+), 11 deletions(-)

diff --git a/plugins/pychrysalide/format/executable.c b/plugins/pychrysalide/format/executable.c
index 906fae5..5621d26 100644
--- a/plugins/pychrysalide/format/executable.c
+++ b/plugins/pychrysalide/format/executable.c
@@ -38,12 +38,16 @@
 #include "../helpers.h"
 #include "../arch/processor.h"
 #include "../arch/vmpa.h"
+#include "../glibext/binportion.h"
 
 
 
 /* ------------------------ DECLARATION DE FORMAT EXECUTABLE ------------------------ */
 
 
+/* Enregistre une portion artificielle pour le format. */
+static PyObject *py_exe_format_register_user_portion(PyObject *, PyObject *);
+
 /* Fournit l'emplacement correspondant à une position physique. */
 static PyObject *py_exe_format_translate_offset_into_vmpa(PyObject *, PyObject *);
 
@@ -62,6 +66,38 @@ static PyObject *py_exe_format_translate_address_into_vmpa(PyObject *, PyObject
 *  Paramètres  : self = description de l'exécutable à consulter.              *
 *                args = arguments accompagnant l'appel.                       *
 *                                                                             *
+*  Description : Enregistre une portion artificielle pour le format.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_exe_format_register_user_portion(PyObject *self, PyObject *args)
+{
+    GBinPortion *portion;                   /* Portion binaire à conserver */
+    int ret;                                /* Bilan de lecture des args.  */
+    GExeFormat *format;                     /* Version GLib du format      */
+
+    ret = PyArg_ParseTuple(args, "O&", convert_to_binary_portion, &portion);
+    if (!ret) return NULL;
+
+    format = G_EXE_FORMAT(pygobject_get(self));
+
+    g_object_ref(G_OBJECT(portion));
+    g_exe_format_register_user_portion(format, portion);
+
+    Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = description de l'exécutable à consulter.              *
+*                args = arguments accompagnant l'appel.                       *
+*                                                                             *
 *  Description : Fournit l'emplacement correspondant à une position physique. *
 *                                                                             *
 *  Retour      : Position correspondante ou None.                             *
@@ -161,6 +197,11 @@ PyTypeObject *get_python_executable_format_type(void)
 {
     static PyMethodDef py_exe_format_methods[] = {
         {
+            "register_user_portion", py_exe_format_register_user_portion,
+            METH_VARARGS,
+            "register_user_portion($self, portion, /)\n--\n\nRemember a given user-defined binary portion as part of the executable format content."
+        },
+        {
             "translate_offset_into_vmpa", py_exe_format_translate_offset_into_vmpa,
             METH_VARARGS,
             "translate_offset_into_vmpa($self, off, /)\n--\n\nTranslate a physical offset to a full location."
diff --git a/plugins/pychrysalide/format/format.c b/plugins/pychrysalide/format/format.c
index 2affeba..e285116 100644
--- a/plugins/pychrysalide/format/format.c
+++ b/plugins/pychrysalide/format/format.c
@@ -43,6 +43,8 @@
 /* ---------------------------- FORMAT BINAIRE GENERIQUE ---------------------------- */
 
 
+/* Enregistre une adresse comme début d'une zone de code. */
+static PyObject *py_binary_format_register_code_point(PyObject *, PyObject *);
 
 /* Ajoute un symbole à la collection du format binaire. */
 static PyObject *py_binary_format_add_symbol(PyObject *, PyObject *);
@@ -100,7 +102,36 @@ static bool define_python_binary_format_constants(PyTypeObject *);
 /* ---------------------------------------------------------------------------------- */
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = classe représentant un format.                        *
+*                args = arguments fournis à l'appel.                          *
+*                                                                             *
+*  Description : Enregistre une adresse comme début d'une zone de code.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static PyObject *py_binary_format_register_code_point(PyObject *self, PyObject *args)
+{
+    unsigned long long pt;                  /* Adresse virtuelle du point  */
+    int entry;                              /* Nature du point fourni      */
+    int ret;                                /* Bilan de lecture des args.  */
+    GBinFormat *format;                     /* Format de binaire manipulé  */
 
+    ret = PyArg_ParseTuple(args, "Kp", &pt, &entry);
+    if (!ret) return NULL;
+
+    format = G_BIN_FORMAT(pygobject_get(self));
+
+    g_binary_format_register_code_point(format, pt, entry);
+
+    Py_RETURN_NONE;
+
+}
 
 
 /******************************************************************************
@@ -638,6 +669,11 @@ PyTypeObject *get_python_binary_format_type(void)
 {
     static PyMethodDef py_bin_format_methods[] = {
         {
+            "register_code_point", py_binary_format_register_code_point,
+            METH_VARARGS,
+            "register_code_point($self, pt, entry, /)\n--\n\nRegister a virtual address as entry point or basic point."
+        },
+        {
             "add_symbol", py_binary_format_add_symbol,
             METH_VARARGS,
             "add_symbol($self, symbol, /)\n--\n\nRegister a new symbol for the format."
diff --git a/src/format/executable-int.h b/src/format/executable-int.h
index 2f3ea73..9ad8568 100644
--- a/src/format/executable-int.h
+++ b/src/format/executable-int.h
@@ -60,6 +60,8 @@ struct _GExeFormat
     GDbgFormat **debugs;                    /* Informations de débogage    */
     size_t debugs_count;                    /* Nombre de ces informations  */
 
+    GBinPortion **user_portions;            /* Couches de morceaux binaires*/
+    size_t user_count;                      /* Nombre de ces portions      */
     GBinPortion *portions;                  /* Couches de morceaux binaires*/
     GMutex mutex;                           /* Accès à l'arborescence      */
 
diff --git a/src/format/executable.c b/src/format/executable.c
index 1f21ca3..cda2e3a 100644
--- a/src/format/executable.c
+++ b/src/format/executable.c
@@ -118,10 +118,12 @@ static void g_executable_format_dispose(GExeFormat *format)
     size_t i;                               /* Boucle de parcours          */
 
     for (i = 0; i < format->debugs_count; i++)
-        g_object_unref(G_OBJECT(format->debugs[i]));
+        g_clear_object(&format->debugs[i]);
 
-    if (format->portions != NULL)
-        g_object_unref(G_OBJECT(format->portions));
+    for (i = 0; i < format->user_count; i++)
+        g_clear_object(&format->user_portions[i]);
+
+    g_clear_object(&format->portions);
 
     g_mutex_clear(&format->mutex);
 
@@ -144,6 +146,12 @@ static void g_executable_format_dispose(GExeFormat *format)
 
 static void g_executable_format_finalize(GExeFormat *format)
 {
+    if (format->debugs != NULL)
+        free(format->debugs);
+
+    if (format->user_portions != NULL)
+        free(format->user_portions);
+
     G_OBJECT_CLASS(g_executable_format_parent_class)->finalize(G_OBJECT(format));
 
 }
@@ -310,6 +318,7 @@ void g_executable_format_setup_portions(GExeFormat *format, GtkStatusStack *stat
     vmpa2t addr;                            /* Emplacement vide de sens    */
     phys_t length;                          /* Taille de portion globale   */
     GExeFormatClass *class;                 /* Classe de l'instance        */
+    size_t i;                               /* Boucle de parcours          */
 
     base = G_BIN_FORMAT(format);
 
@@ -327,6 +336,12 @@ void g_executable_format_setup_portions(GExeFormat *format, GtkStatusStack *stat
     if (class->refine_portions != NULL)
         class->refine_portions(format);
 
+    for (i = 0; i < format->user_count; i++)
+    {
+        g_object_ref(G_OBJECT(format->user_portions[i]));
+        g_exe_format_include_portion(format, format->user_portions[i], NULL);
+    }
+
 }
 
 
@@ -385,6 +400,32 @@ bool g_executable_format_complete_loading(GExeFormat *format, wgroup_id_t gid, G
 *                                                                             *
 *  Paramètres  : format  = description de l'exécutable à modifier.            *
 *                portion = portion à inclure dans les définitions du format.  *
+*                                                                             *
+*  Description : Enregistre une portion artificielle pour le format.          *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_exe_format_register_user_portion(GExeFormat *format, GBinPortion *portion)
+{
+    g_mutex_lock(&format->mutex);
+
+    format->user_portions = realloc(format->user_portions, ++format->user_count * sizeof(GBinPortion *));
+
+    format->user_portions[format->user_count - 1] = portion;
+
+    g_mutex_unlock(&format->mutex);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format  = description de l'exécutable à modifier.            *
+*                portion = portion à inclure dans les définitions du format.  *
 *                origin  = source de définition de la portion fournie.        *
 *                                                                             *
 *  Description : Procède à l'enregistrement d'une portion dans un format.     *
@@ -400,6 +441,7 @@ void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion, cons
     phys_t available;                       /* Taille totale du bianire    */
     const mrange_t *range;                  /* Emplacement de la portion   */
     phys_t start;                           /* Début de zone de la portion */
+    vmpa2t no_origin;                       /* Emplacement inconnu         */
     char *msg;                              /* Description d'une erreur    */
     phys_t remaining;                       /* Taille maximale envisageable*/
     bool truncated;                         /* Modification faite ?        */
@@ -421,7 +463,11 @@ void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion, cons
 
     else if (start >= available)
     {
-        assert(origin != NULL);
+        if (origin == NULL)
+        {
+            init_vmpa(&no_origin, VMPA_NO_PHYSICAL, VMPA_NO_VIRTUAL);
+            origin = &no_origin;
+        }
 
         asprintf(&msg, _("Defined binary portion '%s' is out of the file scope... Discarding!"),
                  g_binary_portion_get_desc(portion));
diff --git a/src/format/executable.h b/src/format/executable.h
index 293a0c0..916269b 100644
--- a/src/format/executable.h
+++ b/src/format/executable.h
@@ -66,6 +66,9 @@ const char *g_exe_format_get_target_machine(const GExeFormat *);
 /* Fournit l'adresse principale associée à un format. */
 bool g_exe_format_get_main_address(GExeFormat *, vmpa2t *);
 
+/* Enregistre une portion artificielle pour le format. */
+void g_exe_format_register_user_portion(GExeFormat *, GBinPortion *);
+
 /* Procède à l'enregistrement d'une portion dans un format. */
 void g_exe_format_include_portion(GExeFormat *, GBinPortion *, const vmpa2t *);
 
@@ -73,7 +76,7 @@ void g_exe_format_include_portion(GExeFormat *, GBinPortion *, const vmpa2t *);
 GBinPortion *g_exe_format_get_portions(GExeFormat *);
 
 /* Fournit les espaces mémoires des portions exécutables. */
-mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count);
+mrange_t *g_exe_format_get_x_ranges(GExeFormat *, size_t *);
 
 /* Fournit l'emplacement correspondant à une position physique. */
 bool g_exe_format_translate_offset_into_vmpa(GExeFormat *, phys_t, vmpa2t *);
diff --git a/src/format/flat.c b/src/format/flat.c
index b165c18..b94988f 100644
--- a/src/format/flat.c
+++ b/src/format/flat.c
@@ -106,8 +106,8 @@ static void g_flat_format_class_init(GFlatFormatClass *klass)
     exe->get_machine = (get_target_machine_fc)g_flat_format_get_target_machine;
     exe->get_main_addr = (get_main_addr_fc)g_flat_format_get_main_address;
 
-    exe->translate_phys = (translate_phys_fc)g_exe_format_without_virt_translate_offset_into_vmpa;
-    exe->translate_virt = (translate_virt_fc)g_exe_format_without_virt_translate_address_into_vmpa;
+    exe->translate_phys = (translate_phys_fc)g_exe_format_translate_offset_into_vmpa_using_portions;
+    exe->translate_virt = (translate_virt_fc)g_exe_format_translate_address_into_vmpa_using_portions;
 
 }
 
@@ -263,8 +263,6 @@ static bool g_flat_format_analyze(GFlatFormat *format, wgroup_id_t gid, GtkStatu
 
     g_executable_format_setup_portions(G_EXE_FORMAT(format), status);
 
-    g_binary_format_register_code_point(G_BIN_FORMAT(format), 0, true);
-
     return result;
 
 }
@@ -375,10 +373,14 @@ static const char *g_flat_format_get_target_machine(const GFlatFormat *format)
 static bool g_flat_format_get_main_address(GFlatFormat *format, vmpa2t *addr)
 {
     bool result;                            /* Bilan à retourner           */
+    GBinFormat *base;                       /* Format de base du format    */
 
-    result = true;
+    base = G_BIN_FORMAT(format);
+
+    result = (base->ep_count > 0);
 
-    init_vmpa(addr, 0, VMPA_NO_VIRTUAL);
+    if (result)
+        init_vmpa(addr, 0, base->entry_points[0]);
 
     return result;
 
-- 
cgit v0.11.2-87-g4458