From 9b018cede5af54594c0a20847239233153b04ce1 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 8 Jul 2017 12:14:12 +0200
Subject: Scrolled to the main address at startup without using a nested
 function.

---
 ChangeLog                   | 11 ++++++++
 src/analysis/project.c      | 64 +++++++++++++++++++++++++--------------------
 src/format/elf/elf.c        | 55 ++++++++++++++++++++++++++++++++++++++
 src/format/executable-int.h |  4 +++
 src/format/executable.c     | 41 +++++++++++++++++++++++++++++
 src/format/executable.h     |  3 +++
 6 files changed, 150 insertions(+), 28 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4810880..895fe1d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+17-07-08  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/project.c:
+	Scroll to the main address at startup without using a nested function.
+
+	* src/format/elf/elf.c:
+	* src/format/executable-int.h:
+	* src/format/executable.c:
+	* src/format/executable.h:
+	Provide the main address of a given file format.
+
 17-07-07  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/glibext/gbinportion.c:
diff --git a/src/analysis/project.c b/src/analysis/project.c
index 88e90ea..5c5c653 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -107,6 +107,9 @@ static void g_study_project_init(GStudyProject *);
 /* Supprime de l'écran un projet en place. */
 static void g_study_project_hide(const GStudyProject *);
 
+/* Assure un positionnement initial idéal. */
+static gboolean scroll_for_the_first_time(GtkWidget *, GdkEvent *, GLoadedBinary *);
+
 
 
 /* ----------------------- VUES ET BASCULEMENT ENTRE LES VUES ----------------------- */
@@ -562,6 +565,39 @@ void g_study_project_add_loaded_binary(GLoadedBinary *binary, GStudyProject *pro
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : widget = composant d'affichage nouvellement porté à l'écran. *
+*                event  = informations liées à l'événement.                   *
+*                binary = fichier binaire à associer au projet actuel.        *
+*                                                                             *
+*  Description : Assure un positionnement initial idéal.                      *
+*                                                                             *
+*  Retour      : FALSE.                                                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static gboolean scroll_for_the_first_time(GtkWidget *widget, GdkEvent *event, GLoadedBinary *binary)
+{
+    GExeFormat *format;                 /* Format associé au binaire       */
+    vmpa2t target;                      /* Position initiale à viser       */
+
+    g_signal_handlers_disconnect_by_func(widget, G_CALLBACK(scroll_for_the_first_time), binary);
+
+    format = g_loaded_binary_get_format(binary);
+
+    if (g_exe_format_get_main_address(format, &target))
+        gtk_display_panel_request_move(GTK_DISPLAY_PANEL(widget), &target);
+
+    g_object_unref(G_OBJECT(format));
+
+    return FALSE;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : project = project à effacer de la mémoire.                   *
 *                binary  = fichier binaire à associer au projet actuel.       *
 *                                                                             *
@@ -596,34 +632,6 @@ void g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *binary
 
     /* Premier affichage */
 
-    gboolean scroll_for_the_first_time(GtkWidget *widget, GdkEvent *event, GLoadedBinary *binary)
-    {
-        GBinFormat *format;                 /* Format associé au binaire   */
-        GBinSymbol *symbol;                 /* Point d'entrée trouvé       */
-        const mrange_t *range;              /* Emplacement de ce point     */
-
-        g_signal_handlers_disconnect_by_func(widget, G_CALLBACK(scroll_for_the_first_time), binary);
-
-        format = G_BIN_FORMAT(g_loaded_binary_get_format(binary));
-
-        /* TODO : se rabattre sur des symboles identifiés comme point d'entrée si on ne trouve pas les principaux ci dessous */
-
-        if (g_binary_format_find_symbol_by_label(format, "main", &symbol)
-            || g_binary_format_find_symbol_by_label(format, "_start", &symbol)
-            || g_binary_format_find_symbol_by_label(format, "entry_point", &symbol))
-        {
-            range = g_binary_symbol_get_range(symbol);
-
-            gtk_display_panel_request_move(GTK_DISPLAY_PANEL(widget), get_mrange_addr(range));
-
-        }
-
-        g_object_unref(G_OBJECT(format));
-
-        return FALSE;
-
-    }
-
     panel = _setup_new_panel_item_for_binary(project, binary, BVW_BLOCK, &display);
 
     g_mutex_unlock(&project->bin_mutex);
diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c
index 0336ba3..1254e52 100644
--- a/src/format/elf/elf.c
+++ b/src/format/elf/elf.c
@@ -69,6 +69,9 @@ static SourceEndian g_elf_format_get_endianness(const GElfFormat *);
 /* Indique le type d'architecture visée par le format. */
 static const char *g_elf_format_get_target_machine(const GElfFormat *);
 
+/* Fournit l'adresse principale associée à un format Elf. */
+static bool g_elf_format_get_main_address(GElfFormat *, vmpa2t *);
+
 /* Etend la définition des portions au sein d'un binaire. */
 static void g_elf_format_refine_portions(GElfFormat *);
 
@@ -161,6 +164,7 @@ static void g_elf_format_class_init(GElfFormatClass *klass)
     exe = G_EXE_FORMAT_CLASS(klass);
 
     exe->get_machine = (get_target_machine_fc)g_elf_format_get_target_machine;
+    exe->get_main_addr = (get_main_addr_fc)g_elf_format_get_main_address;
     exe->refine_portions = (refine_portions_fc)g_elf_format_refine_portions;
 
     exe->translate_phys = (translate_phys_fc)g_elf_format_translate_offset_into_vmpa;
@@ -397,6 +401,57 @@ static const char *g_elf_format_get_target_machine(const GElfFormat *format)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                addr   = adresse principale trouvée si possible. [OUT]       *
+*                                                                             *
+*  Description : Fournit l'adresse principale associée à un format Elf.       *
+*                                                                             *
+*  Retour      : Bilan des recherches.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_elf_format_get_main_address(GElfFormat *format, vmpa2t *addr)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinSymbol *symbol;                     /* Point d'entrée trouvé       */
+    GBinFormat *base;                       /* Version d'instance parente  */
+    const mrange_t *range;                  /* Emplacement de ce point     */
+
+    result = false;
+    symbol = NULL;
+
+    base = G_BIN_FORMAT(format);
+
+    if (g_binary_format_find_symbol_by_label(base, "main", &symbol))
+        goto done;
+
+    if (g_binary_format_find_symbol_by_label(base, "_start", &symbol))
+        goto done;
+
+    if (g_binary_format_find_symbol_by_label(base, "entry_point", &symbol))
+        goto done;
+
+ done:
+
+    if (symbol != NULL)
+    {
+        result = true;
+
+        range = g_binary_symbol_get_range(symbol);
+
+        copy_vmpa(addr, get_mrange_addr(range));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                                                                             *
 *  Description : Etend la définition des portions au sein d'un binaire.       *
diff --git a/src/format/executable-int.h b/src/format/executable-int.h
index 8a5f197..64050e3 100644
--- a/src/format/executable-int.h
+++ b/src/format/executable-int.h
@@ -35,6 +35,9 @@
 /* Indique le type d'architecture visée par le format. */
 typedef const char * (* get_target_machine_fc) (const GExeFormat *);
 
+/* Fournit l'adresse principale associée à un format. */
+typedef bool (* get_main_addr_fc) (GExeFormat *, vmpa2t *);
+
 /* Etend la définition des portions au sein d'un binaire. */
 typedef void (* refine_portions_fc) (GExeFormat *);
 
@@ -68,6 +71,7 @@ struct _GExeFormatClass
     GBinFormatClass parent;                 /* A laisser en premier        */
 
     get_target_machine_fc get_machine;      /* Architecture ciblée         */
+    get_main_addr_fc get_main_addr;         /* Obtention d'adresse première*/
     refine_portions_fc refine_portions;     /* Décrit les portions binaires*/
 
     translate_phys_fc translate_phys;       /* Correspondance phys -> vmpa */
diff --git a/src/format/executable.c b/src/format/executable.c
index 3d3847c..fe3448d 100644
--- a/src/format/executable.c
+++ b/src/format/executable.c
@@ -242,6 +242,47 @@ const char *g_exe_format_get_target_machine(const GExeFormat *format)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                addr   = adresse principale trouvée si possible. [OUT]       *
+*                                                                             *
+*  Description : Fournit l'adresse principale associée à un format.           *
+*                                                                             *
+*  Retour      : Bilan des recherches.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_exe_format_get_main_address(GExeFormat *format, vmpa2t *addr)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinFormat *base;                       /* Version d'instance parente  */
+
+    result = false;
+
+    if (G_EXE_FORMAT_GET_CLASS(format)->get_main_addr != NULL)
+        result = G_EXE_FORMAT_GET_CLASS(format)->get_main_addr(format, addr);
+
+    if (!result)
+    {
+        base = G_BIN_FORMAT(format);
+
+        g_rw_lock_reader_lock(&base->pt_lock);
+
+        if (base->ep_count > 0)
+            result = g_exe_format_translate_address_into_vmpa(format, base->entry_points[0], addr);
+
+        g_rw_lock_reader_unlock(&base->pt_lock);
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : format = instance à traiter.                                 *
 *                status = barre de statut à tenir informée.                   *
 *                                                                             *
diff --git a/src/format/executable.h b/src/format/executable.h
index e6d9abf..985efb2 100644
--- a/src/format/executable.h
+++ b/src/format/executable.h
@@ -64,6 +64,9 @@ GDbgFormat *g_exe_format_get_debug_info(const GExeFormat *, size_t);
 /* Indique le type d'architecture visée par le format. */
 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 *);
+
 /* Procède à l'enregistrement d'une portion dans un format. */
 void g_exe_format_include_portion(GExeFormat *, GBinPortion *);
 
-- 
cgit v0.11.2-87-g4458