From 08c45a8c7970403c3d658b1b0af9ac09f66b4a7e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 24 May 2018 09:43:32 +0200
Subject: Translated offsets and addresses with more accuracy.

---
 plugins/dex/format.c        |   2 +
 plugins/elf/format.c        |  68 +--------------
 plugins/elf/program.c       |  84 -------------------
 plugins/elf/program.h       |   6 --
 plugins/elf/section.c       |  84 -------------------
 plugins/elf/section.h       |   6 --
 plugins/mobicore/mclf.c     |   2 +
 src/format/executable-int.c |  74 ++++++++++++++++
 src/format/executable-int.h |  13 ++-
 src/format/executable.c     |  52 ++++++++----
 src/format/executable.h     |   4 +-
 src/glibext/gbinportion.c   | 200 +++++++++++++++++++++++++++++++++++++++++++-
 src/glibext/gbinportion.h   |   6 ++
 13 files changed, 333 insertions(+), 268 deletions(-)

diff --git a/plugins/dex/format.c b/plugins/dex/format.c
index b9b6ca9..f185cc3 100644
--- a/plugins/dex/format.c
+++ b/plugins/dex/format.c
@@ -407,6 +407,8 @@ static bool g_dex_format_analyze(GDexFormat *format, wgroup_id_t gid, GtkStatusS
 
     preload_binary_format(PGA_FORMAT_PRELOAD, base, base->info, status);
 
+    g_executable_format_setup_portions(exe, status);
+
     if (!g_executable_format_complete_loading(exe, status))
         goto gdfa_error;
 
diff --git a/plugins/elf/format.c b/plugins/elf/format.c
index 9e29a11..3394ba2 100644
--- a/plugins/elf/format.c
+++ b/plugins/elf/format.c
@@ -84,12 +84,6 @@ 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 *);
 
-/* Fournit l'emplacement correspondant à une position physique. */
-static bool g_elf_format_translate_offset_into_vmpa(const GElfFormat *, phys_t, vmpa2t *);
-
-/* Fournit l'emplacement correspondant à une position physique. */
-static bool g_elf_format_translate_address_into_vmpa(const GElfFormat *, virt_t, vmpa2t *);
-
 /* Fournit l'emplacement d'une section donnée. */
 static bool g_elf_format_get_section_range_by_name(const GElfFormat *, const char *, mrange_t *);
 
@@ -167,8 +161,8 @@ static void g_elf_format_class_init(GElfFormatClass *klass)
     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;
-    exe->translate_virt = (translate_virt_fc)g_elf_format_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;
 
     exe->get_range_by_name = (get_range_by_name_fc)g_elf_format_get_section_range_by_name;
 
@@ -382,6 +376,8 @@ static bool g_elf_format_analyze(GElfFormat *format, wgroup_id_t gid, GtkStatusS
 
     /* Chargements des informations utiles */
 
+    g_executable_format_setup_portions(exe, status);
+
     /**
      * On inscrit les éléments préchargés avant tout !
      *
@@ -698,62 +694,6 @@ static void g_elf_format_refine_portions(GElfFormat *format)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = description de l'exécutable à consulter.            *
-*                off    = position physique à retrouver.                      *
-*                pos    = position correspondante. [OUT]                      *
-*                                                                             *
-*  Description : Fournit l'emplacement correspondant à une position physique. *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_elf_format_translate_offset_into_vmpa(const GElfFormat *format, phys_t off, vmpa2t *pos)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = translate_offset_into_vmpa_using_elf_sections(format, off, pos);
-
-    if (!result)
-        result = translate_offset_into_vmpa_using_elf_programs(format, off, pos);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                addr   = adresse virtuelle à retrouver.                      *
-*                pos    = position correspondante. [OUT]                      *
-*                                                                             *
-*  Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool g_elf_format_translate_address_into_vmpa(const GElfFormat *format, virt_t addr, vmpa2t *pos)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = translate_address_into_vmpa_using_elf_sections(format, addr, pos);
-
-    if (!result)
-        result = translate_address_into_vmpa_using_elf_programs(format, addr, pos);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
 *                name   = nom de la section recherchée.                       *
 *                range  = emplacement en mémoire à renseigner. [OUT]          *
 *                                                                             *
diff --git a/plugins/elf/program.c b/plugins/elf/program.c
index 7fb63df..f4924f5 100644
--- a/plugins/elf/program.c
+++ b/plugins/elf/program.c
@@ -152,87 +152,3 @@ bool find_elf_program_by_type(const GElfFormat *format, uint32_t type, elf_phdr
     return result;
 
 }
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                off    = position physique à retrouver.                      *
-*                pos    = position correspondante. [OUT]                      *
-*                                                                             *
-*  Description : Fournit l'emplacement correspondant à une position physique. *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool translate_offset_into_vmpa_using_elf_programs(const GElfFormat *format, phys_t off, vmpa2t *pos)
-{
-    bool result;                            /* Bilan à retourner           */
-    uint16_t i;                             /* Boucle de parcours          */
-    elf_phdr program;                       /* Programme à analyser        */
-    virt_t addr;                            /* Adresse virtuelle calculée  */
-
-    result = false;
-
-    for (i = 0; i < ELF_HDR(format, format->header, e_phnum) && !result; i++)
-    {
-        find_elf_program_by_index(format, i, &program);
-
-        if (ELF_PHDR(format, program, p_offset) <= off
-            && off < (ELF_PHDR(format, program, p_offset) + ELF_PHDR(format, program, p_filesz)))
-        {
-            addr = ELF_PHDR(format, program, p_vaddr) + ELF_PHDR(format, program, p_offset) - off;
-            init_vmpa(pos, off, addr);
-            result = true;
-        }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                addr   = adresse virtuelle à retrouver.                      *
-*                pos    = position correspondante. [OUT]                      *
-*                                                                             *
-*  Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool translate_address_into_vmpa_using_elf_programs(const GElfFormat *format, virt_t addr, vmpa2t *pos)
-{
-    bool result;                            /* Bilan à retourner           */
-    uint16_t i;                             /* Boucle de parcours          */
-    elf_phdr program;                       /* Programme à analyser        */
-    phys_t off;                             /* Position physique calculée  */
-
-    result = false;
-
-    for (i = 0; i < ELF_HDR(format, format->header, e_phnum) && !result; i++)
-    {
-        find_elf_program_by_index(format, i, &program);
-
-        if (ELF_PHDR(format, program, p_vaddr) <= addr
-            && addr < (ELF_PHDR(format, program, p_vaddr) + ELF_PHDR(format, program, p_filesz)))
-        {
-            off = ELF_PHDR(format, program, p_offset) + addr - ELF_PHDR(format, program, p_vaddr);
-            init_vmpa(pos, off, addr);
-            result = true;
-        }
-
-    }
-
-    return result;
-
-}
diff --git a/plugins/elf/program.h b/plugins/elf/program.h
index 7c73340..34969cb 100644
--- a/plugins/elf/program.h
+++ b/plugins/elf/program.h
@@ -39,12 +39,6 @@ bool find_elf_program_by_index(const GElfFormat *, uint16_t, elf_phdr *);
 /* Recherche un programme donné au sein de binaire par type. */
 bool find_elf_program_by_type(const GElfFormat *, uint32_t, elf_phdr *);
 
-/* Fournit l'emplacement correspondant à une position physique. */
-bool translate_offset_into_vmpa_using_elf_programs(const GElfFormat *, phys_t, vmpa2t *);
-
-/* Fournit l'emplacement correspondant à une adresse virtuelle. */
-bool translate_address_into_vmpa_using_elf_programs(const GElfFormat *, virt_t, vmpa2t *);
-
 
 
 #endif  /* _PLUGINS_ELF_PROGRAM_H */
diff --git a/plugins/elf/section.c b/plugins/elf/section.c
index cc47f9d..0e2fd3e 100644
--- a/plugins/elf/section.c
+++ b/plugins/elf/section.c
@@ -342,87 +342,3 @@ const char *extract_name_from_elf_string_section(const GElfFormat *format, const
     return result;
 
 }
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                off    = position physique à retrouver.                      *
-*                pos    = position correspondante. [OUT]                      *
-*                                                                             *
-*  Description : Fournit l'emplacement correspondant à une position physique. *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool translate_offset_into_vmpa_using_elf_sections(const GElfFormat *format, phys_t off, vmpa2t *pos)
-{
-    bool result;                            /* Bilan à retourner           */
-    uint16_t i;                             /* Boucle de parcours          */
-    elf_shdr section;                       /* Section à analyser          */
-    virt_t addr;                            /* Adresse virtuelle calculée  */
-
-    result = false;
-
-    for (i = 0; i < ELF_HDR(format, format->header, e_shnum) && !result; i++)
-    {
-        find_elf_section_by_index(format, i, &section);
-
-        if (ELF_SHDR(format, section, sh_offset) <= off
-            && off < (ELF_SHDR(format, section, sh_offset) + ELF_SHDR(format, section, sh_size)))
-        {
-            addr = ELF_SHDR(format, section, sh_addr) + off - ELF_SHDR(format, section, sh_offset);
-            init_vmpa(pos, off, addr);
-            result = true;
-        }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = description de l'exécutable à consulter.            *
-*                addr   = adresse virtuelle à retrouver.                      *
-*                pos    = position correspondante. [OUT]                      *
-*                                                                             *
-*  Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-bool translate_address_into_vmpa_using_elf_sections(const GElfFormat *format, virt_t addr, vmpa2t *pos)
-{
-    bool result;                            /* Bilan à retourner           */
-    uint16_t i;                             /* Boucle de parcours          */
-    elf_shdr section;                       /* Section à analyser          */
-    phys_t off;                             /* Position physique calculée  */
-
-    result = false;
-
-    for (i = 0; i < ELF_HDR(format, format->header, e_shnum) && !result; i++)
-    {
-        find_elf_section_by_index(format, i, &section);
-
-        if (ELF_SHDR(format, section, sh_addr) <= addr
-            && addr < (ELF_SHDR(format, section, sh_addr) + ELF_SHDR(format, section, sh_size)))
-        {
-            off = ELF_SHDR(format, section, sh_offset) + addr - ELF_SHDR(format, section, sh_addr);
-            init_vmpa(pos, off, addr);
-            result = true;
-        }
-
-    }
-
-    return result;
-
-}
diff --git a/plugins/elf/section.h b/plugins/elf/section.h
index 021caf0..ac74ab1 100644
--- a/plugins/elf/section.h
+++ b/plugins/elf/section.h
@@ -57,12 +57,6 @@ bool find_elf_section_range_by_name(const GElfFormat *, const char *, mrange_t *
 /* Identifie une chaîne de caractères dans une section adéquate. */
 const char *extract_name_from_elf_string_section(const GElfFormat *, const elf_shdr *, off_t);
 
-/* Fournit l'emplacement correspondant à une position physique. */
-bool translate_offset_into_vmpa_using_elf_sections(const GElfFormat *, phys_t, vmpa2t *);
-
-/* Fournit l'emplacement correspondant à une adresse virtuelle. */
-bool translate_address_into_vmpa_using_elf_sections(const GElfFormat *, virt_t, vmpa2t *);
-
 
 
 #endif  /* _PLUGINS_ELF_SECTION_H */
diff --git a/plugins/mobicore/mclf.c b/plugins/mobicore/mclf.c
index 0c4de64..37939f7 100644
--- a/plugins/mobicore/mclf.c
+++ b/plugins/mobicore/mclf.c
@@ -213,6 +213,8 @@ GBinFormat *g_mclf_format_new(GBinContent *content, GExeFormat *parent, GtkStatu
     if (!read_mclf_header(result, &result->header, result->endian))
         goto gmfn_error;
 
+    g_executable_format_setup_portions(G_EXE_FORMAT(result), status);
+
     if (!load_mclf_symbols(result))
         goto gmfn_error;
 
diff --git a/src/format/executable-int.c b/src/format/executable-int.c
index e13a7c9..d20a776 100644
--- a/src/format/executable-int.c
+++ b/src/format/executable-int.c
@@ -79,3 +79,77 @@ bool g_exe_format_without_virt_translate_address_into_vmpa(const GExeFormat *for
     return true;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                off    = position physique à retrouver.                      *
+*                pos    = position correspondante. [OUT]                      *
+*                                                                             *
+*  Description : Fournit l'emplacement correspondant à une position physique. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_exe_format_translate_offset_into_vmpa_using_portions(GExeFormat *format, phys_t off, vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinPortion *portions;                  /* Liste de découpages         */
+
+    portions = g_exe_format_get_portions(format);
+
+    if (portions == NULL)
+        result = false;
+
+    else
+    {
+        result = g_binary_portion_translate_offset_into_vmpa(portions, off, pos);
+
+        g_object_unref(G_OBJECT(portions));
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = description de l'exécutable à consulter.            *
+*                addr   = adresse virtuelle à retrouver.                      *
+*                pos    = position correspondante. [OUT]                      *
+*                                                                             *
+*  Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_exe_format_translate_address_into_vmpa_using_portions(GExeFormat *format, virt_t addr, vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+    GBinPortion *portions;                  /* Liste de découpages         */
+
+    portions = g_exe_format_get_portions(format);
+
+    if (portions == NULL)
+        result = false;
+
+    else
+    {
+        result = g_binary_portion_translate_address_into_vmpa(portions, addr, pos);
+
+        g_object_unref(G_OBJECT(portions));
+
+    }
+
+    return result;
+
+}
diff --git a/src/format/executable-int.h b/src/format/executable-int.h
index ed2c7c1..58eba25 100644
--- a/src/format/executable-int.h
+++ b/src/format/executable-int.h
@@ -42,10 +42,10 @@ typedef bool (* get_main_addr_fc) (GExeFormat *, vmpa2t *);
 typedef void (* refine_portions_fc) (GExeFormat *);
 
 /* Fournit l'emplacement correspondant à une position physique. */
-typedef bool (* translate_phys_fc) (const GExeFormat *, phys_t, vmpa2t *);
+typedef bool (* translate_phys_fc) (GExeFormat *, phys_t, vmpa2t *);
 
 /* Fournit l'emplacement correspondant à une adresse virtuelle. */
-typedef bool (* translate_virt_fc) (const GExeFormat *, virt_t, vmpa2t *);
+typedef bool (* translate_virt_fc) (GExeFormat *, virt_t, vmpa2t *);
 
 /* Fournit l'emplacement d'une section donnée. */
 typedef bool (* get_range_by_name_fc) (const GExeFormat *, const char *, mrange_t *);
@@ -82,6 +82,9 @@ struct _GExeFormatClass
 };
 
 
+/* Crée les portions potentiellement utiles aux traductions. */
+void g_executable_format_setup_portions(GExeFormat *, GtkStatusStack *);
+
 /* Effectue les ultimes opérations de chargement d'un binaire. */
 bool g_executable_format_complete_loading(GExeFormat *, GtkStatusStack *);
 
@@ -91,6 +94,12 @@ bool g_exe_format_without_virt_translate_offset_into_vmpa(const GExeFormat *, ph
 /* Fournit l'emplacement correspondant à une adresse virtuelle. */
 bool g_exe_format_without_virt_translate_address_into_vmpa(const GExeFormat *, virt_t, vmpa2t *);
 
+/* Fournit l'emplacement correspondant à une position physique. */
+bool g_exe_format_translate_offset_into_vmpa_using_portions(GExeFormat *, phys_t, vmpa2t *);
+
+/* Fournit l'emplacement correspondant à une adresse virtuelle. */
+bool g_exe_format_translate_address_into_vmpa_using_portions(GExeFormat *, virt_t, vmpa2t *);
+
 
 
 #endif  /* _FORMAT_EXECUTABLE_INT_H */
diff --git a/src/format/executable.c b/src/format/executable.c
index 0107074..a2ee569 100644
--- a/src/format/executable.c
+++ b/src/format/executable.c
@@ -289,39 +289,57 @@ bool g_exe_format_get_main_address(GExeFormat *format, vmpa2t *addr)
 *  Paramètres  : format = instance à traiter.                                 *
 *                status = barre de statut à tenir informée.                   *
 *                                                                             *
-*  Description : Effectue les ultimes opérations de chargement d'un binaire.  *
+*  Description : Crée les portions potentiellement utiles aux traductions.    *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool g_executable_format_complete_loading(GExeFormat *format, GtkStatusStack *status)
+void g_executable_format_setup_portions(GExeFormat *format, GtkStatusStack *status)
 {
-    bool result;                            /* Bilan à faire remonter      */
     GBinFormat *base;                       /* Version basique du format   */
     vmpa2t addr;                            /* Emplacement vide de sens    */
     phys_t length;                          /* Taille de portion globale   */
 
     base = G_BIN_FORMAT(format);
 
-    result = g_binary_format_complete_loading(base, status);
+    /**
+     * Avant de lire l'entête du format, on ne sait pas où on se trouve !
+     */
+    init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
 
-    if (result)
-    {
-        /**
-         * Avant de lire l'entête du format, on ne sait pas où on se trouve !
-         */
-        init_vmpa(&addr, 0, VMPA_NO_VIRTUAL);
+    length = g_binary_content_compute_size(base->content);
+
+    format->portions = g_binary_portion_new(BPC_RAW, &addr, length);
 
-        length = g_binary_content_compute_size(base->content);
+    G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format);
 
-        format->portions = g_binary_portion_new(BPC_RAW, &addr, length);
+}
 
-        G_EXE_FORMAT_GET_CLASS(format)->refine_portions(format);
 
-    }
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = instance à traiter.                                 *
+*                status = barre de statut à tenir informée.                   *
+*                                                                             *
+*  Description : Effectue les ultimes opérations de chargement d'un binaire.  *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_executable_format_complete_loading(GExeFormat *format, GtkStatusStack *status)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    GBinFormat *base;                       /* Version basique du format   */
+
+    base = G_BIN_FORMAT(format);
+
+    result = g_binary_format_complete_loading(base, status);
 
     return result;
 
@@ -447,7 +465,7 @@ GBinPortion *g_exe_format_get_portions(GExeFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-bool g_exe_format_translate_offset_into_vmpa(const GExeFormat *format, phys_t off, vmpa2t *pos)
+bool g_exe_format_translate_offset_into_vmpa(GExeFormat *format, phys_t off, vmpa2t *pos)
 {
     bool result;                            /* Bilan à retourner           */
 
@@ -472,7 +490,7 @@ bool g_exe_format_translate_offset_into_vmpa(const GExeFormat *format, phys_t of
 *                                                                             *
 ******************************************************************************/
 
-bool g_exe_format_translate_address_into_vmpa(const GExeFormat *format, virt_t addr, vmpa2t *pos)
+bool g_exe_format_translate_address_into_vmpa(GExeFormat *format, virt_t addr, vmpa2t *pos)
 {
     bool result;                            /* Bilan à retourner           */
 
diff --git a/src/format/executable.h b/src/format/executable.h
index af69029..293a0c0 100644
--- a/src/format/executable.h
+++ b/src/format/executable.h
@@ -76,10 +76,10 @@ GBinPortion *g_exe_format_get_portions(GExeFormat *);
 mrange_t *g_exe_format_get_x_ranges(GExeFormat *format, size_t *count);
 
 /* Fournit l'emplacement correspondant à une position physique. */
-bool g_exe_format_translate_offset_into_vmpa(const GExeFormat *, phys_t, vmpa2t *);
+bool g_exe_format_translate_offset_into_vmpa(GExeFormat *, phys_t, vmpa2t *);
 
 /* Fournit l'emplacement correspondant à une position physique. */
-bool g_exe_format_translate_address_into_vmpa(const GExeFormat *, virt_t, vmpa2t *);
+bool g_exe_format_translate_address_into_vmpa(GExeFormat *, virt_t, vmpa2t *);
 
 
 #define g_exe_format_translate_offset_into_address(fmt, off, addr)              \
diff --git a/src/glibext/gbinportion.c b/src/glibext/gbinportion.c
index 2275583..27413f6 100644
--- a/src/glibext/gbinportion.c
+++ b/src/glibext/gbinportion.c
@@ -119,7 +119,13 @@ static void g_binary_portion_print(GBinPortion *, GBufferLine *, size_t, size_t,
 
 
 /* Détermine si une portion contient une adresse donnée. */
-static bool g_portion_layer_contains_addr(const GBinPortion *, const vmpa2t *);
+static bool g_binary_portion_contains_vmpa(const GBinPortion *, const vmpa2t *);
+
+/* Détermine si une portion contient une position donnée. */
+static bool g_binary_portion_contains_physical(const GBinPortion *, phys_t);
+
+/* Détermine si une portion contient une adresse donnée. */
+static bool g_binary_portion_contains_virtual(const GBinPortion *, virt_t);
 
 
 
@@ -1196,7 +1202,7 @@ GBinPortion *g_binary_portion_find_at_pos(GBinPortion *portion, gint x, GdkRecta
 *                                                                             *
 ******************************************************************************/
 
-static bool g_portion_layer_contains_addr(const GBinPortion *portion, const vmpa2t *addr)
+static bool g_binary_portion_contains_vmpa(const GBinPortion *portion, const vmpa2t *addr)
 {
     bool result;                            /* Bilan à retourner           */
 
@@ -1245,7 +1251,7 @@ GBinPortion *g_binary_portion_find_at_addr(GBinPortion *portion, const vmpa2t *a
     {
         sub = portion->subs[i];
 
-        if (!g_portion_layer_contains_addr(sub, addr))
+        if (!g_binary_portion_contains_vmpa(sub, addr))
             continue;
 
         if (!g_binary_portion_compute_sub_area(sub, full, area, &sub_area))
@@ -1372,3 +1378,191 @@ gboolean query_tooltip_for_binary_portion(GBinPortion *root, gint x, gint y, con
     return TRUE;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : portion = portion mère à consulter.                          *
+*                off     = position physique du point de recherche.           *
+*                                                                             *
+*  Description : Détermine si une portion contient une position donnée.       *
+*                                                                             *
+*  Retour      : true ou false selon le résultat.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_binary_portion_contains_physical(const GBinPortion *portion, phys_t off)
+{
+    bool result;                            /* Bilan à retourner           */
+    const mrange_t *range;                  /* Emplacement de portion      */
+    const vmpa2t *addr;                     /* Départ de la portion        */
+
+    range = g_binary_portion_get_range(portion);
+    addr = get_mrange_addr(range);
+
+    if (!has_phys_addr(addr))
+        result = false;
+
+    else
+        result = (addr->physical <= off && off < (addr->physical + range->length));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : portion = couche de portions à parcourir pour les recherches.*
+*                off     = position physique à retrouver.                     *
+*                pos     = position correspondante. [OUT]                     *
+*                                                                             *
+*  Description : Fournit l'emplacement correspondant à une position physique. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_portion_translate_offset_into_vmpa(const GBinPortion *portion, phys_t off, vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours #1       */
+    GBinPortion *sub;                       /* Portion incluse à traiter   */
+    const mrange_t *range;                  /* Emplacement de portion      */
+    const vmpa2t *addr;                     /* Départ de la portion        */
+
+    result = false;
+
+    for (i = 0; i < portion->count; i++)
+    {
+        sub = portion->subs[i];
+
+        if (!g_binary_portion_contains_physical(sub, off))
+            continue;
+
+        result = g_binary_portion_translate_offset_into_vmpa(sub, off, pos);
+
+        break;
+
+    }
+
+    if (i == portion->count)
+    {
+        result = g_binary_portion_contains_physical(portion, off);
+
+        if (result)
+        {
+            range = g_binary_portion_get_range(portion);
+            addr = get_mrange_addr(range);
+
+            if (has_virt_addr(get_mrange_addr(range)))
+                init_vmpa(pos, off, addr->virtual + off - addr->physical);
+
+            else
+                init_vmpa(pos, off, VMPA_NO_VIRTUAL);
+
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : portion = portion mère à consulter.                          *
+*                virt    = adresse virtuelle du point de recherche.           *
+*                                                                             *
+*  Description : Détermine si une portion contient une adresse donnée.        *
+*                                                                             *
+*  Retour      : true ou false selon le résultat.                             *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool g_binary_portion_contains_virtual(const GBinPortion *portion, virt_t virt)
+{
+    bool result;                            /* Bilan à retourner           */
+    const mrange_t *range;                  /* Emplacement de portion      */
+    const vmpa2t *addr;                     /* Départ de la portion        */
+
+    range = g_binary_portion_get_range(portion);
+    addr = get_mrange_addr(range);
+
+    if (!has_virt_addr(addr))
+        result = false;
+
+    else
+        result = (addr->virtual <= virt && virt < (addr->virtual + range->length));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : portion = couche de portions à parcourir pour les recherches.*
+*                virt    = adresse virtuelle à retrouver.                     *
+*                pos     = position correspondante. [OUT]                     *
+*                                                                             *
+*  Description : Fournit l'emplacement correspondant à une adresse virtuelle. *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool g_binary_portion_translate_address_into_vmpa(const GBinPortion *portion, virt_t virt, vmpa2t *pos)
+{
+    bool result;                            /* Bilan à retourner           */
+    size_t i;                               /* Boucle de parcours #1       */
+    GBinPortion *sub;                       /* Portion incluse à traiter   */
+    const mrange_t *range;                  /* Emplacement de portion      */
+    const vmpa2t *addr;                     /* Départ de la portion        */
+
+    result = false;
+
+    for (i = 0; i < portion->count; i++)
+    {
+        sub = portion->subs[i];
+
+        if (!g_binary_portion_contains_virtual(sub, virt))
+            continue;
+
+        result = g_binary_portion_translate_address_into_vmpa(sub, virt, pos);
+
+        break;
+
+    }
+
+    if (i == portion->count)
+    {
+        result = g_binary_portion_contains_virtual(portion, virt);
+
+        if (result)
+        {
+            range = g_binary_portion_get_range(portion);
+            addr = get_mrange_addr(range);
+
+            if (has_phys_addr(addr) && has_virt_addr(addr))
+                init_vmpa(pos, addr->physical + virt - addr->virtual, virt);
+
+            else
+                init_vmpa(pos, VMPA_NO_PHYSICAL, virt);
+
+        }
+
+    }
+
+    return result;
+
+}
diff --git a/src/glibext/gbinportion.h b/src/glibext/gbinportion.h
index b1184fb..581be68 100644
--- a/src/glibext/gbinportion.h
+++ b/src/glibext/gbinportion.h
@@ -159,6 +159,12 @@ bool get_binary_portion_pos_from_addr(GBinPortion *, const vmpa2t *, const GdkRe
 /* Prépare une astuce concernant une portion pour son affichage. */
 gboolean query_tooltip_for_binary_portion(GBinPortion *, gint, gint, const GdkRectangle *, GtkTooltip *);
 
+/* Fournit l'emplacement correspondant à une position physique. */
+bool g_binary_portion_translate_offset_into_vmpa(const GBinPortion *, phys_t, vmpa2t *);
+
+/* Fournit l'emplacement correspondant à une adresse virtuelle. */
+bool g_binary_portion_translate_address_into_vmpa(const GBinPortion *, virt_t, vmpa2t *);
+
 
 
 #endif  /* _GLIBEXT_BINPORTION_H */
-- 
cgit v0.11.2-87-g4458