From ed763539951307353042c04af5c2278db0d05298 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 16 Aug 2017 23:52:02 +0200
Subject: Ensured all registered binary portions are fully included in the
 file.

---
 ChangeLog                 | 14 +++++++++++++
 plugins/mobicore/mclf.c   | 40 ++++++++++++++++++++++++++++--------
 src/format/dex/dex-int.c  |  2 ++
 src/format/dex/dex_def.h  |  2 ++
 src/format/dex/method.c   |  2 +-
 src/format/elf/elf.c      | 12 +++++++++--
 src/format/executable.c   | 52 ++++++++++++++++++++++++++++++++++++++---------
 src/format/executable.h   |  2 +-
 src/glibext/gbinportion.c | 15 +++++---------
 9 files changed, 109 insertions(+), 32 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index dad8776..f4fddab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+17-08-16  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/mobicore/mclf.c:
+	* src/format/dex/dex-int.c:
+	* src/format/dex/dex_def.h:
+	* src/format/dex/method.c:
+	* src/format/elf/elf.c:
+	Update code.
+
+	* src/format/executable.c:
+	* src/format/executable.h:
+	* src/glibext/gbinportion.c:
+	Ensure all registered binary portions are fully included in the file.
+
 17-08-15  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/contents/file.c:
diff --git a/plugins/mobicore/mclf.c b/plugins/mobicore/mclf.c
index 740e7b1..7697d15 100644
--- a/plugins/mobicore/mclf.c
+++ b/plugins/mobicore/mclf.c
@@ -270,6 +270,8 @@ static const char *g_mclf_format_get_target_machine(const GMCLFFormat *format)
 static void g_mclf_format_refine_portions(GMCLFFormat *format)
 {
     GExeFormat *exe_format;                 /* Autre version du format     */
+    phys_t offset;                          /* Position physique           */
+    vmpa2t origin;                          /* Origine d'une définition    */
     vmpa2t addr;                            /* Emplacement dans le binaire */
     GBinPortion *new;                       /* Nouvelle portion définie    */
     char desc[MAX_PORTION_DESC];            /* Description d'une portion   */
@@ -279,6 +281,18 @@ static void g_mclf_format_refine_portions(GMCLFFormat *format)
 
     /* Segment de code */
 
+    offset = sizeof(uint32_t)   /* magic */             \
+           + sizeof(uint32_t)   /* version */           \
+           + sizeof(uint32_t)   /* flags */             \
+           + sizeof(uint32_t)   /* mem_type */          \
+           + sizeof(uint32_t)   /* service_type */      \
+           + sizeof(uint32_t)   /* num_instances */     \
+           + 16                 /* uuid */              \
+           + sizeof(uint32_t)   /* driver_id */         \
+           + sizeof(uint32_t);  /* num_threads */
+
+    init_vmpa(&origin, offset, VMPA_NO_VIRTUAL);
+
     init_vmpa(&addr, 0, format->header.v1.text.start);
 
     new = g_binary_portion_new(BPC_CODE, &addr, format->header.v1.text.len);
@@ -288,10 +302,15 @@ static void g_mclf_format_refine_portions(GMCLFFormat *format)
 
     g_binary_portion_set_rights(new, PAC_WRITE | PAC_EXEC);
 
-    g_exe_format_include_portion(exe_format, new);
+    g_exe_format_include_portion(exe_format, new, &origin);
 
     /* Segment de données */
 
+    offset += sizeof(uint32_t)  /* start */             \
+            + sizeof(uint32_t); /* len */
+
+    init_vmpa(&origin, offset, VMPA_NO_VIRTUAL);
+
     init_vmpa(&addr, format->header.v1.text.len, format->header.v1.data.start);
 
     new = g_binary_portion_new(BPC_DATA, &addr, format->header.v1.data.len);
@@ -301,20 +320,25 @@ static void g_mclf_format_refine_portions(GMCLFFormat *format)
 
     g_binary_portion_set_rights(new, PAC_READ | PAC_WRITE);
 
-    g_exe_format_include_portion(exe_format, new);
+    g_exe_format_include_portion(exe_format, new, &origin);
 
     /* Signature finale */
 
     length = g_binary_content_compute_size(G_BIN_FORMAT(format)->content);
-    init_vmpa(&addr, length - 521, VMPA_NO_VIRTUAL);  /* FIXME */
 
-    new = g_binary_portion_new(BPC_DATA, &addr, 521);
+    if (length > 521)
+    {
+        init_vmpa(&addr, length - 521, VMPA_NO_VIRTUAL);
+
+        new = g_binary_portion_new(BPC_DATA, &addr, 521);
 
-    sprintf(desc, "%s \"%s\"", _("Segment"), "sig");
-    g_binary_portion_set_desc(new, desc);
+        sprintf(desc, "%s \"%s\"", _("Segment"), "sig");
+        g_binary_portion_set_desc(new, desc);
 
-    g_binary_portion_set_rights(new, PAC_READ | PAC_WRITE);
+        g_binary_portion_set_rights(new, PAC_READ | PAC_WRITE);
 
-    g_exe_format_include_portion(exe_format, new);
+        g_exe_format_include_portion(exe_format, new, NULL);
+
+    }
 
 }
diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c
index 1626dde..c49445d 100644
--- a/src/format/dex/dex-int.c
+++ b/src/format/dex/dex-int.c
@@ -376,6 +376,8 @@ bool read_dex_encoded_method(const GDexFormat *format, vmpa2t *pos, encoded_meth
 
     content = G_BIN_FORMAT(format)->content;
 
+    copy_vmpa(&method->origin, pos);
+
     result &= g_binary_content_read_uleb128(content, pos, &method->method_idx_diff);
     result &= g_binary_content_read_uleb128(content, pos, &method->access_flags);
     result &= g_binary_content_read_uleb128(content, pos, &method->code_off);
diff --git a/src/format/dex/dex_def.h b/src/format/dex/dex_def.h
index 8ddcf30..e1521e8 100755
--- a/src/format/dex/dex_def.h
+++ b/src/format/dex/dex_def.h
@@ -191,6 +191,8 @@ typedef struct _encoded_method
     uleb128_t access_flags;                 /* Conditions d'accès          */
     uleb128_t code_off;                     /* Position du code associé    */
 
+    vmpa2t origin;                          /* Rajout pour suivi interne   */
+
 } encoded_method;
 
 /* Type quelconque */
diff --git a/src/format/dex/method.c b/src/format/dex/method.c
index f487c0a..ec12119 100644
--- a/src/format/dex/method.c
+++ b/src/format/dex/method.c
@@ -387,7 +387,7 @@ void g_dex_method_include_as_portion(const GDexMethod *method, GExeFormat *forma
 
     g_binary_portion_set_rights(new, PAC_READ | PAC_EXEC);
 
-    g_exe_format_include_portion(format, new);
+    g_exe_format_include_portion(format, new, &method->info.origin);
 
 }
 
diff --git a/src/format/elf/elf.c b/src/format/elf/elf.c
index 1ca81be..2ca3b8c 100644
--- a/src/format/elf/elf.c
+++ b/src/format/elf/elf.c
@@ -468,6 +468,7 @@ static void g_elf_format_refine_portions(GElfFormat *format)
     uint16_t max;                           /* Décompte d'éléments traités */
     uint16_t i;                             /* Boucle de parcours          */
     off_t offset;                           /* Début de part de programme  */
+    vmpa2t origin;                          /* Origine d'une définition    */
     elf_phdr phdr;                          /* En-tête de programme ELF    */
     uint32_t p_flags;                       /* Droits associés à une partie*/
     const char *background;                 /* Fond signigicatif           */
@@ -506,6 +507,8 @@ static void g_elf_format_refine_portions(GElfFormat *format)
         offset = ELF_HDR(format, format->header, e_phoff)
             + ELF_HDR(format, format->header, e_phentsize) * i;
 
+        init_vmpa(&origin, offset, VMPA_NO_VIRTUAL);
+
         if (!read_elf_program_header(format, offset, &phdr))
             continue;
 
@@ -535,7 +538,7 @@ static void g_elf_format_refine_portions(GElfFormat *format)
 
         g_binary_portion_set_rights(new, rights);
 
-        g_exe_format_include_portion(exe_format, new);
+        g_exe_format_include_portion(exe_format, new, &origin);
 
     }
 
@@ -586,7 +589,12 @@ static void g_elf_format_refine_portions(GElfFormat *format)
 
         g_binary_portion_set_rights(new, rights);
 
-        g_exe_format_include_portion(exe_format, new);
+        offset = ELF_HDR(format, format->header, e_shoff)
+            + ELF_HDR(format, format->header, e_shentsize) * i;
+
+        init_vmpa(&origin, offset, VMPA_NO_VIRTUAL);
+
+        g_exe_format_include_portion(exe_format, new, &origin);
 
     }
 
diff --git a/src/format/executable.c b/src/format/executable.c
index f121f5b..ac67d62 100644
--- a/src/format/executable.c
+++ b/src/format/executable.c
@@ -24,7 +24,9 @@
 #include "executable.h"
 
 
+#include <assert.h>
 #include <malloc.h>
+#include <stdio.h>
 #include <stdlib.h>
 
 
@@ -330,6 +332,7 @@ bool g_executable_format_complete_loading(GExeFormat *format, GtkStatusStack *st
 *                                                                             *
 *  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.     *
 *                                                                             *
@@ -339,24 +342,53 @@ bool g_executable_format_complete_loading(GExeFormat *format, GtkStatusStack *st
 *                                                                             *
 ******************************************************************************/
 
-void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion)
+void g_exe_format_include_portion(GExeFormat *format, GBinPortion *portion, const vmpa2t *origin)
 {
-    phys_t max;                             /* Position hors limite        */
+    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 */
+    char *msg;                              /* Description d'une erreur    */
+    phys_t remaining;                       /* Taille maximale envisageable*/
     bool truncated;                         /* Modification faite ?        */
 
-    max = g_binary_content_compute_size(G_BIN_FORMAT(format)->content);
+    available = g_binary_content_compute_size(G_BIN_FORMAT(format)->content);
 
-    truncated = g_binary_portion_limit_range(portion, max);
+    range = g_binary_portion_get_range(portion);
 
-    if (truncated)
-        log_variadic_message(LMT_BAD_BINARY, _("Truncated binary portion '%s' to fit the binary content size!"),
-                             g_binary_portion_get_desc(portion));
+    start = get_phy_addr(get_mrange_addr(range));
 
-    g_mutex_lock(&format->mutex);
+    if (start >= available)
+    {
+        assert(origin != NULL);
 
-    g_binary_portion_include(format->portions, portion);
+        asprintf(&msg, _("Defined binary portion '%s' is out of the file scope... Discarding!"),
+                 g_binary_portion_get_desc(portion));
 
-    g_mutex_unlock(&format->mutex);
+        g_binary_format_add_error(G_BIN_FORMAT(format), BFE_STRUCTURE, origin, msg);
+
+        free(msg);
+
+        g_object_unref(G_OBJECT(portion));
+
+    }
+
+    else
+    {
+        remaining = available - start;
+
+        truncated = g_binary_portion_limit_range(portion, remaining);
+
+        if (truncated)
+            log_variadic_message(LMT_BAD_BINARY, _("Truncated binary portion '%s' to fit the binary content size!"),
+                                 g_binary_portion_get_desc(portion));
+
+        g_mutex_lock(&format->mutex);
+
+        g_binary_portion_include(format->portions, portion);
+
+        g_mutex_unlock(&format->mutex);
+
+    }
 
 }
 
diff --git a/src/format/executable.h b/src/format/executable.h
index 985efb2..81e5e6c 100644
--- a/src/format/executable.h
+++ b/src/format/executable.h
@@ -68,7 +68,7 @@ const char *g_exe_format_get_target_machine(const GExeFormat *);
 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 *);
+void g_exe_format_include_portion(GExeFormat *, GBinPortion *, const vmpa2t *);
 
 /* Fournit la première couche des portions composent le binaire. */
 GBinPortion *g_exe_format_get_portions(GExeFormat *);
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index 731cd08..c0e14fa 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -488,7 +488,7 @@ const mrange_t *g_binary_portion_get_range(const GBinPortion *portion)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : portion = description de partie à mettre à jour.             *
-*                max     = première position physique hors limite.            *
+*                max     = taille maximale accordée à la portion.             *
 *                                                                             *
 *  Description : Assure qu'une portion ne dépasse pas une position donnée.    *
 *                                                                             *
@@ -501,19 +501,14 @@ const mrange_t *g_binary_portion_get_range(const GBinPortion *portion)
 bool g_binary_portion_limit_range(GBinPortion *portion, phys_t max)
 {
     bool result;                            /* Bilan à retourner           */
-    vmpa2t end;                             /* Limite actuelle de portion  */
-    const vmpa2t *start;                    /* Position de départ          */
+    phys_t current;                         /* Taille courante             */
 
-    compute_mrange_end_addr(&portion->range, &end);
+    current = get_mrange_length(&portion->range);
 
-    result = get_phy_addr(&end) > max;
+    result = (current > max);
 
     if (result)
-    {
-        start = get_mrange_addr(&portion->range);
-        set_mrange_length(&portion->range, max - get_phy_addr(start));
-
-    }
+        set_mrange_length(&portion->range, max);
 
     return result;
 
-- 
cgit v0.11.2-87-g4458