From c4231094c9c77c685371d726d28e65c0459486de Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 11 Mar 2009 22:59:46 +0000
Subject: Inserted comments into disassembled code.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@53 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                   |  25 +++++
 src/analysis/line.c         | 226 ++++++++++++++++++++++++++++++++++++++++++--
 src/analysis/line.h         |  31 ++++--
 src/analysis/prototype.c    |  46 +++++++++
 src/analysis/prototype.h    |   9 ++
 src/binary.c                |  40 ++++++--
 src/common/dllist.c         |   4 +-
 src/common/dllist.h         |  12 +++
 src/format/elf/e_elf.c      |  36 +++++++
 src/format/elf/e_elf.h      |   2 +
 src/format/exe_format-int.h |   3 +
 src/format/exe_format.c     |  45 +++++++++
 src/format/exe_format.h     |   9 ++
 13 files changed, 461 insertions(+), 27 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3603eed..420ecf8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2009-03-11  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/line.c:
+	* src/analysis/line.h:
+	Attach an offset to lines and create comment lines. Provide disassembly
+	options for lines rendering (this part needs to be rewritten).
+
+	* src/analysis/prototype.c:
+	* src/analysis/prototype.h:
+	Add an offset to routines information.
+
+	* src/binary.c:
+	Insert comments into disassembled code.
+
+	* src/common/dllist.c:
+	* src/common/dllist.h:
+	Add a macro for inserting items.
+
+	* src/format/elf/e_elf.c:
+	* src/format/elf/e_elf.h:
+	* src/format/exe_format.c:
+	* src/format/exe_format.h:
+	* src/format/exe_format-int.h:
+	Load all routine prototypes. Enable binary parts sorting.
+
 2009-03-04  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac:
diff --git a/src/analysis/line.c b/src/analysis/line.c
index 052adea..f5f3d9c 100644
--- a/src/analysis/line.c
+++ b/src/analysis/line.c
@@ -55,6 +55,8 @@ struct _rendering_line
 {
     DL_LIST_ITEM;
 
+    uint64_t offset;                        /* Position en mémoire/physique*/
+
     RenderingLineType type;                 /* Type de représentation      */
 
     PangoLayout *layout;                    /* Moteur de rendu du code/txt */
@@ -75,7 +77,6 @@ void init_rendering_line(rendering_line *);
 
 
 
-
 /* ------------------------- LIGNE EN TETE DE DESASSEMBLAGE ------------------------- */
 
 
@@ -94,6 +95,25 @@ void refresh_prologue_markup(prologue_line *);
 
 
 
+/* ----------------------- COMMENTAIRES SUR UNE LIGNE ENTIERE ----------------------- */
+
+
+/* Ligne de commantaires entière */
+typedef struct _comment_line
+{
+    rendering_line basic;                   /* A laisser en premier        */
+
+    char *comment;                          /* Texte à afficher            */
+    const disass_options *options;          /* Options de représentation   */
+
+} comment_line;
+
+
+/* Met à jour la ligne de représentation de commentaires. */
+void refresh_comment_markup(comment_line *);
+
+
+
 /* ------------------------ LIGNE DE CODE EN LANGAGE MACHINE ------------------------ */
 
 
@@ -162,7 +182,7 @@ void init_rendering_line(rendering_line *line)
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
-*  Remarques   : -                                                            *
+*  Remarques   : La ligne est considérée comme étant insérée au bon endroit.  *
 *                                                                             *
 ******************************************************************************/
 
@@ -173,6 +193,48 @@ void add_line_to_rendering_lines(rendering_line **lines, rendering_line *line)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : lines = liste de lignes à compléter, ou NULL.                *
+*                line  = nouvelle ligne à intégrer à l'ensemble.              *
+*                first = position de la ligne en cas d'adresse partagée.      *
+*                                                                             *
+*  Description : Insère une ligne dans un ensemble existant.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void insert_line_into_rendering_lines(rendering_line **lines, rendering_line *line, bool first)
+{
+    rendering_line *iter;                   /* Boucle de parcours          */
+    rendering_line *next;                   /* Prochaine ligne parcourue   */
+
+    dl_list_for_each_safe(iter, DLL_HCAST(lines), next, rendering_line *)
+    {
+        if (first && iter->offset >= line->offset) break;
+        else if (!first)
+        {
+            /* TODO */;
+        }
+
+    }
+
+    if (iter == NULL)
+        dl_list_add_tail(line, DLL_HCAST(lines));
+
+    else
+    {
+        if (first)
+            dl_list_insert_before(line, iter, DLL_HCAST(lines));
+        else
+            /* TODO */;
+    }
+
+}
+
 
 
 
@@ -295,6 +357,8 @@ rendering_line *create_prologue_line(const char *comment)
 
     init_rendering_line(RENDERING_LINE(result));
 
+    RENDERING_LINE(result)->offset = 0;
+
     RENDERING_LINE(result)->type = RLT_PROLOGUE;
 
     RENDERING_LINE(result)->refresh_markup = (refresh_markup_fc)refresh_prologue_markup;
@@ -340,6 +404,154 @@ void refresh_prologue_markup(prologue_line *line)
 
 
 /* ---------------------------------------------------------------------------------- */
+/*                         COMMENTAIRES SUR UNE LIGNE ENTIERE                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : offset  = position dans la mémoire ou le fichier.            *
+*                type    = type du commentaire.                               *
+*                comment = texte à afficher au final.                         *
+*                options = paramétrage du rendu.                              *
+*                                                                             *
+*  Description : Crée une ligne de commentaires entière.                      *
+*                                                                             *
+*  Retour      : Adresse de la structure mise en place.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+rendering_line *create_comment_line(uint64_t offset, RenderingLineType type, const char *comment, const disass_options *options)
+{
+    comment_line *result;                   /* Structure à retourner       */
+
+    result = (prologue_line *)calloc(1, sizeof(prologue_line));
+
+    init_rendering_line(RENDERING_LINE(result));
+
+    RENDERING_LINE(result)->offset = offset;
+
+    RENDERING_LINE(result)->type = type;
+
+    RENDERING_LINE(result)->refresh_markup = (refresh_markup_fc)refresh_comment_markup;
+
+    result->comment = strdup(comment);
+    result->options = options;
+
+    return RENDERING_LINE(result);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : line = ligne de représentation à actualiser.                 *
+*                                                                             *
+*  Description : Met à jour la ligne de représentation de commentaires.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void refresh_comment_markup(comment_line *line)
+{
+    size_t len;                             /* Taille du contenu           */
+    char *content;                          /* Contenu réellement imprimé  */
+    char buffer[CODE_BUFFER_LEN];           /* Zone tampon à utiliser      */
+    size_t clen;                            /* Taille du commentaire       */
+
+    len = strlen("<tt>") + 1;
+    content = (char *)calloc(len, sizeof(char));
+    strcpy(content, "<tt>");
+
+    /* Eventuelle adresse virtuelle */
+
+    if (line->options->show_address)
+    {
+        switch (ADM_32BITS  /* FIXME */)
+        {
+            case ADM_32BITS:
+                snprintf(buffer, CODE_BUFFER_LEN,
+                         "<span foreground='#333333'>0x%08llx</span>",
+                         RENDERING_LINE(line)->offset);
+                break;
+
+            case ADM_64BITS:
+                snprintf(buffer, CODE_BUFFER_LEN,
+                         "<span foreground='#333333'>0x%16llx</span>",
+                         RENDERING_LINE(line)->offset);
+                break;
+
+        }
+
+        len += strlen(buffer);
+        content = (char *)realloc(content, len * sizeof(char));
+        strcat(content, buffer);
+
+    }
+
+    /* Eventuel code brut (sauté) */
+
+    if (line->options->show_code)
+    {
+        clen = (line->options->show_address ? strlen("\t") : 0);
+        clen += RENDERING_LINE(line)->max_bin_len;
+
+        content = (char *)realloc(content, (len + clen) * sizeof(char));
+
+        if (line->options->show_address)
+        {
+            strcat(content, "\t");
+            len += strlen("\t");
+        }
+
+        memset(&content[len - 1], RENDERING_LINE(line)->type == RLT_PROTOTYPE ? '-' : ' ',
+               RENDERING_LINE(line)->max_bin_len);
+        len += RENDERING_LINE(line)->max_bin_len;
+
+        content[len] = '\0';
+
+    }
+
+    /* Commentaire proprement dit */
+
+    clen = (line->options->show_address || line->options->show_code ? strlen("\t") : 0);
+    clen += strlen("<b><span foreground='#003300'>");
+    clen += strlen("; ") + strlen(line->comment);
+    clen += strlen("</span></b>");
+
+    content = (char *)realloc(content, (len + clen) * sizeof(char));
+
+    if (line->options->show_address || line->options->show_code)
+    {
+        strcat(content, "\t");
+        len += strlen("\t");
+        clen -= strlen("\t");
+    }
+
+    snprintf(&content[len - 1], clen + 1, "<b><span foreground='#003300'>; %s</span></b>", line->comment);
+
+    len += clen;
+
+    /* Finalisation */
+
+    len += strlen("</tt>");
+    content = (char *)realloc(content, len * sizeof(char));
+    strcat(content, "</tt>");
+
+    pango_layout_set_markup(RENDERING_LINE(line)->layout, content, len - 1);
+
+    free(content);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
 /*                          LIGNE DE CODE EN LANGAGE MACHINE                          */
 /* ---------------------------------------------------------------------------------- */
 
@@ -357,7 +569,7 @@ void refresh_prologue_markup(prologue_line *line)
 *                                                                             *
 ******************************************************************************/
 
-rendering_line *create_code_line(asm_instr *instr, const disass_options *options)
+rendering_line *create_code_line(asm_instr *instr, uint64_t offset, const disass_options *options)
 {
     code_line *result;                      /* Structure à retourner       */
 
@@ -365,6 +577,8 @@ rendering_line *create_code_line(asm_instr *instr, const disass_options *options
 
     init_rendering_line(RENDERING_LINE(result));
 
+    RENDERING_LINE(result)->offset = offset;
+
     RENDERING_LINE(result)->type = RLT_CODE;
 
     RENDERING_LINE(result)->get_bin_len = (get_bin_len_fc)get_code_binary_len;
@@ -430,7 +644,7 @@ void refresh_code_markup(code_line *line)
     content = (char *)calloc(len, sizeof(char));
     strcpy(content, "<tt>");
 
-    if (line->options->show_address || line->options->show_code)
+    if (line->options->show_code)
         get_asm_instr_offset_and_length(line->instr, &bin_offset, &bin_len);
 
     /* Eventuelle adresse virtuelle */
@@ -442,13 +656,13 @@ void refresh_code_markup(code_line *line)
             case ADM_32BITS:
                 snprintf(buffer, CODE_BUFFER_LEN,
                          "<span foreground='#333333'>0x%08llx</span>",
-                         bin_offset);
+                         RENDERING_LINE(line)->offset);
                 break;
 
             case ADM_64BITS:
                 snprintf(buffer, CODE_BUFFER_LEN,
                          "<span foreground='#333333'>0x%16llx</span>",
-                         bin_offset);
+                         RENDERING_LINE(line)->offset);
                 break;
 
         }
diff --git a/src/analysis/line.h b/src/analysis/line.h
index cd2ec71..b0635bf 100644
--- a/src/analysis/line.h
+++ b/src/analysis/line.h
@@ -25,6 +25,7 @@
 #define _ANALYSIS_LINE_H
 
 
+#include <stdbool.h>
 #include <gtk/gtk.h>
 
 
@@ -37,10 +38,21 @@
 typedef enum _RenderingLineType
 {
     RLT_PROLOGUE,                           /* Description de l'analyse    */
+    RLT_PROTOTYPE,                          /* Prototype de fonction       */
     RLT_CODE                                /* Code en langage machine     */
 
 } RenderingLineType;
 
+/* Passage de paramètres compact */
+typedef struct _disass_options
+{
+    bool show_address;                      /* Affichage de l'adresse ?    */
+    bool show_code;                         /* Affichage du code brut ?    */
+
+    exe_format *format;                     /* Format du contenu bianire   */
+    asm_processor *proc;                    /* Architecture utilisée       */
+
+} disass_options;
 
 
 
@@ -52,6 +64,9 @@ typedef struct _rendering_line rendering_line;
 /* Ajoute une ligne à un ensemble existant. */
 void add_line_to_rendering_lines(rendering_line **, rendering_line *);
 
+/* Insère une ligne dans un ensemble existant.  */
+void insert_line_into_rendering_lines(rendering_line **, rendering_line *, bool);
+
 
 
 /* Met à jour la nombre d'octets maximale par instruction. */
@@ -76,23 +91,19 @@ rendering_line *create_prologue_line(const char *);
 
 
 
-/* ------------------------ LIGNE DE CODE EN LANGAGE MACHINE ------------------------ */
+/* ----------------------- COMMENTAIRES SUR UNE LIGNE ENTIERE ----------------------- */
 
 
-/* Passage de paramètres compact */
-typedef struct _disass_options
-{
-    bool show_address;                      /* Affichage de l'adresse ?    */
-    bool show_code;                         /* Affichage du code brut ?    */
+/* Crée une ligne de commentaires entière. */
+rendering_line *create_comment_line(uint64_t, RenderingLineType, const char *, const disass_options *);
 
-    exe_format *format;                     /* Format du contenu bianire   */
-    asm_processor *proc;                    /* Architecture utilisée       */
 
-} disass_options;
+
+/* ------------------------ LIGNE DE CODE EN LANGAGE MACHINE ------------------------ */
 
 
 /* Crée une ligne de représentation de code binaire. */
-rendering_line *create_code_line(asm_instr *, const disass_options *);
+rendering_line *create_code_line(asm_instr *, uint64_t, const disass_options *);
 
 
 
diff --git a/src/analysis/prototype.c b/src/analysis/prototype.c
index aa3ca2f..0d2ebf5 100644
--- a/src/analysis/prototype.c
+++ b/src/analysis/prototype.c
@@ -25,6 +25,7 @@
 
 
 #include <malloc.h>
+#include <string.h>
 
 
 #include "../common/extstr.h"
@@ -34,6 +35,12 @@
 /* Variable représentant un prototype de routine */
 struct _bin_routine
 {
+
+    uint64_t offset;                        /* Position physique/mémoire   */
+
+
+
+
     RoutineType type;                       /* Type de routine             */
 
     variable *ret_type;                     /* Type retourné               */
@@ -103,6 +110,45 @@ void delete_binary_routine(bin_routine *routine)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : routine = routine à mettre à jour.                           *
+*                offset  = position mémoire ou physique déclarée.             *
+*                                                                             *
+*  Description : Définit la position physique / en mémoire d'une routine.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_binary_routine_offset(bin_routine *routine, uint64_t offset)
+{
+    routine->offset = offset;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = routine à mettre à jour.                           *
+*                                                                             *
+*  Description : Fournit la position physique / en mémoire d'une routine.     *
+*                                                                             *
+*  Retour      : Position mémoire ou physique déclarée.                       *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+uint64_t get_binary_routine_offset(const bin_routine *routine)
+{
+    return routine->offset;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : routine = routine à mettre à jour.                           *
 *                type    = type de routine spécifié.                          *
 *                                                                             *
 *  Description : Définit le type d'une routine.                               *
diff --git a/src/analysis/prototype.h b/src/analysis/prototype.h
index f86d541..891f294 100644
--- a/src/analysis/prototype.h
+++ b/src/analysis/prototype.h
@@ -25,6 +25,9 @@
 #define _ANALYSIS_PROTOTYPE_H
 
 
+#include <stdint.h>
+
+
 #include "variable.h"
 
 
@@ -49,6 +52,12 @@ bin_routine *create_binary_routine(void);
 /* Supprime une représentation de routine de la mémoire. */
 void delete_binary_routine(bin_routine *);
 
+/* Définit la position physique / en mémoire d'une routine. */
+void set_binary_routine_offset(bin_routine *, uint64_t);
+
+/* Fournit la position physique / en mémoire d'une routine. */
+uint64_t get_binary_routine_offset(const bin_routine *);
+
 /* Définit le type d'une routine. */
 void set_binary_routine_type(bin_routine *, RoutineType);
 
diff --git a/src/binary.c b/src/binary.c
index 427ad4e..5093335 100644
--- a/src/binary.c
+++ b/src/binary.c
@@ -35,7 +35,7 @@
 #include <sys/types.h>
 
 
-
+#include "analysis/prototype.h"
 #include "arch/processor.h"
 
 
@@ -435,6 +435,9 @@ void fill_snippet(GtkSnippet *snippet, GtkWidget *panel, GtkWidget *panel2)
     asm_processor *proc;
     asm_instr *instr;
 
+    bin_routine **routines;                 /* Liste des routines trouvées */
+    size_t routines_count;                  /* Nombre de ces routines      */
+
     bin_part **parts;
     size_t parts_count;
 
@@ -464,6 +467,10 @@ void fill_snippet(GtkSnippet *snippet, GtkWidget *panel, GtkWidget *panel2)
 
     size_t k;
 
+    uint64_t routine_offset;                /* Point de départ de routine  */
+    char *routine_desc;                     /* Prototype d'une routine     */
+
+
     disass_options options;
 
     proc = create_x86_processor();
@@ -497,21 +504,27 @@ void fill_snippet(GtkSnippet *snippet, GtkWidget *panel, GtkWidget *panel2)
 
 
 
+
     options.show_address = true;
     options.show_code = true;
 
     options.format = format;
     options.proc = proc;
 
+    routines = get_all_exe_routines(format, &routines_count);
+
 
     parts = get_elf_default_code_parts(format, &parts_count);
+    qsort(parts, parts_count, sizeof(bin_part *), compare_bin_parts);
+
+
 
 
     for (i = 0; i < parts_count; i++)
     {
         get_bin_part_values(parts[i], &pos, &len, &base);
 
-
+        /* Décodage des instructions */
 
         start = pos;
         pos = 0;
@@ -524,19 +537,27 @@ void fill_snippet(GtkSnippet *snippet, GtkWidget *panel, GtkWidget *panel2)
             instr = decode_instruction(proc, &bin_data[start], &pos, len, start, offset);
 
 
-            line = create_code_line(instr, &options);
+            line = create_code_line(instr, offset, &options);
             add_line_to_rendering_lines(&lines, line);
 
         }
 
+        /* Ajout des prototypes de fonctions */
 
-        /****
-             ret = munmap(bin_data, length);
-        ****/
+        for (k = 0; k < routines_count; k++)
+        {
+            routine_offset = get_binary_routine_offset(routines[k]);
 
-        /*
-          gtk_snippet_build_content(snippet);
-        */
+            if (!(base <= routine_offset && routine_offset < (base + len))) continue;
+
+            routine_desc = routine_to_string(routines[k]);
+
+            line = create_comment_line(routine_offset, RLT_PROTOTYPE, routine_desc, &options);
+            insert_line_into_rendering_lines(&lines, line, true);
+
+            free(routine_desc);
+
+        }
 
     }
 
@@ -547,6 +568,7 @@ void fill_snippet(GtkSnippet *snippet, GtkWidget *panel, GtkWidget *panel2)
 
 
 
+
     gtk_snippet_set_rendering_lines(snippet, lines);
 
     handle_new_exe_on_symbols_panel(panel, format);
diff --git a/src/common/dllist.c b/src/common/dllist.c
index 10f73e1..7e56bf4 100644
--- a/src/common/dllist.c
+++ b/src/common/dllist.c
@@ -45,11 +45,11 @@
 
 void __dl_list_add(dl_list_item *new, dl_list_head *head, dl_list_item *prev, dl_list_item *next)
 {
-    if (prev != NULL) prev->next = new;
+    prev->next = new;
     new->prev = prev;
 
     new->next = next;
-    if (next != NULL) next->prev = new;
+    next->prev = new;
 
     if (*head == NULL)
         *head = new;
diff --git a/src/common/dllist.h b/src/common/dllist.h
index 970edf9..670d3b9 100644
--- a/src/common/dllist.h
+++ b/src/common/dllist.h
@@ -44,6 +44,7 @@ typedef dl_list_item *dl_list_head;
 #define DL_LIST_ITEM dl_list_item dummy
 
 #define DLL_CAST(item) ((dl_list_item *)item)
+#define DLL_HCAST(item) ((dl_list_item **)item)
 
 #define DL_LIST_HEAD_INIT(head)                                         \
     *(head) = NULL
@@ -87,6 +88,17 @@ unsigned int count_dl_list_items(dl_list_head);
 #define dl_list_add_tail(new, head)                                     \
     __dl_list_add(DLL_CAST(new), (head), (dl_list_empty(*(head)) ? DLL_CAST(new) : (*(head))->prev), (dl_list_empty(*(head)) ? DLL_CAST(new) : *(head)))
 
+#define dl_list_insert_before(new, target, head)                        \
+    do                                                                  \
+    {                                                                   \
+        DLL_CAST(new)->prev = DLL_CAST(target)->prev;                   \
+        DLL_CAST(target)->prev->next = DLL_CAST(new);                   \
+        DLL_CAST(new)->next = DLL_CAST(target);                         \
+        DLL_CAST(target)->prev = DLL_CAST(new);                         \
+        if (DLL_CAST(target) == *head) *head = DLL_CAST(target);        \
+                                                                        \
+    } while (0)
+
 #define dl_list_del(item, head)                                         \
     do                                                                  \
     {                                                                   \
diff --git a/src/format/elf/e_elf.c b/src/format/elf/e_elf.c
index a69be68..91e0403 100644
--- a/src/format/elf/e_elf.c
+++ b/src/format/elf/e_elf.c
@@ -106,6 +106,7 @@ elf_format *load_elf(const uint8_t *content, off_t length)
     EXE_FORMAT(result)->get_symbols = (get_symbols_fc)get_elf_symbols;
     EXE_FORMAT(result)->get_resolved = (get_resolved_fc)get_elf_resolved_items;
     EXE_FORMAT(result)->resolve_symbol = (resolve_symbol_fc)resolve_elf_symbol;
+    EXE_FORMAT(result)->get_all_routines = (get_all_routines_fc)get_all_elf_routines;
 
     memcpy(&result->header, content, sizeof(Elf32_Ehdr));
 
@@ -394,3 +395,38 @@ bool resolve_elf_symbol(const elf_format *format, char **label, SymbolType *type
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                count  = taille du tableau créé. [OUT]                       *
+*                                                                             *
+*  Description : Fournit le prototype de toutes les routines détectées.       *
+*                                                                             *
+*  Retour      : Tableau créé ou NULL si aucun symbole de routine trouvé.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bin_routine **get_all_elf_routines(const elf_format *format, size_t *count)
+{
+    bin_routine **result;                   /* Tableau à retourner         */
+    size_t i;                               /* Boucle de parcours          */
+
+    result = (bin_routine **)calloc(format->sym_count, sizeof(bin_routine *));
+    *count = format->sym_count;
+
+    for (i = 0; i < format->sym_count; i++)
+    {
+        result[i] = create_binary_routine();
+
+        set_binary_routine_offset(result[i], format->symbols[i].address);
+        set_binary_routine_name(result[i], strdup(format->symbols[i].name));
+
+    }
+
+    return result;
+
+}
diff --git a/src/format/elf/e_elf.h b/src/format/elf/e_elf.h
index fffeff2..f0c2c12 100644
--- a/src/format/elf/e_elf.h
+++ b/src/format/elf/e_elf.h
@@ -55,6 +55,8 @@ size_t get_elf_symbols(const elf_format *, char ***, SymbolType **, uint64_t **)
 /* Recherche le symbole correspondant à une adresse. */
 bool resolve_elf_symbol(const elf_format *, char **, SymbolType *, uint64_t *);
 
+/* Fournit le prototype de toutes les routines détectées. */
+bin_routine **get_all_elf_routines(const elf_format *, size_t *);
 
 
 
diff --git a/src/format/exe_format-int.h b/src/format/exe_format-int.h
index 2fdb673..a882891 100644
--- a/src/format/exe_format-int.h
+++ b/src/format/exe_format-int.h
@@ -63,6 +63,8 @@ typedef size_t (* get_resolved_fc) (const exe_format *, char ***, ResolvedType *
 /* Recherche le symbole correspondant à une adresse. */
 typedef bool (* resolve_symbol_fc) (const exe_format *, char **, SymbolType *, uint64_t *);
 
+/* Fournit le prototype de toutes les routines détectées. */
+typedef bin_routine ** (* get_all_routines_fc) (const exe_format *, size_t *);
 
 
 /* Support générique d'un format d'exécutable */
@@ -76,6 +78,7 @@ struct _exe_format
     get_symbols_fc get_symbols;             /* Liste des symboles présents */
     get_resolved_fc get_resolved;           /* Liste des éléments présents */
     resolve_symbol_fc resolve_symbol;       /* Recherche de symboles       */
+    get_all_routines_fc get_all_routines;   /* Liste de routines détectées */
 
 };
 
diff --git a/src/format/exe_format.c b/src/format/exe_format.c
index 8a03243..be0e1f1 100644
--- a/src/format/exe_format.c
+++ b/src/format/exe_format.c
@@ -178,6 +178,31 @@ void delete_bin_part(bin_part *part)
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : a = premières informations à consulter.                      *
+*                b = secondes informations à consulter.                       *
+*                                                                             *
+*  Description : Etablit la comparaison entre deux blocs binaires.            *
+*                                                                             *
+*  Retour      : Bilan : -1 (a < b), 0 (a == b) ou 1 (a > b).                 *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int compare_bin_parts(const bin_part **a, const bin_part **b)
+{
+    int result;                             /* Bilan à renvoyer            */
+
+    if ((*a)->offset < (*b)->offset) result = -1;
+    else if((*a)->offset > (*b)->offset) result = 1;
+    else result = 0;
+
+    return result;
+
+}
+
 
 
 
@@ -378,3 +403,23 @@ bool resolve_exe_symbol(const exe_format *format, char **label, SymbolType *type
     return format->resolve_symbol(format, label, type, offset);
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = informations chargées à consulter.                  *
+*                count  = taille du tableau créé. [OUT]                       *
+*                                                                             *
+*  Description : Fournit le prototype de toutes les routines détectées.       *
+*                                                                             *
+*  Retour      : Tableau créé ou NULL si aucun symbole de routine trouvé.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bin_routine **get_all_exe_routines(const exe_format *format, size_t *count)
+{
+    return format->get_all_routines(format, count);
+
+}
diff --git a/src/format/exe_format.h b/src/format/exe_format.h
index 4fedf13..48cb989 100644
--- a/src/format/exe_format.h
+++ b/src/format/exe_format.h
@@ -30,6 +30,9 @@
 #include <sys/types.h>
 
 
+#include "../analysis/prototype.h"
+
+
 
 /* ------------------------ MANIPULATION DES PARTIES DE CODE ------------------------ */
 
@@ -53,6 +56,9 @@ void get_bin_part_values(const bin_part *, off_t *, off_t *, uint64_t *);
 /* Supprime de la mémoire une description de partie de code. */
 void delete_bin_part(bin_part *);
 
+/* Etablit la comparaison entre deux blocs binaires. */
+int compare_bin_parts(const bin_part **, const bin_part **);
+
 
 
 
@@ -117,6 +123,9 @@ size_t get_exe_resolved_items(const exe_format *, char ***, ResolvedType **, uin
 /* Recherche le symbole correspondant à une adresse. */
 bool resolve_exe_symbol(const exe_format *, char **, SymbolType *, uint64_t *);
 
+/* Fournit le prototype de toutes les routines détectées. */
+bin_routine **get_all_exe_routines(const exe_format *, size_t *);
+
 
 
 #endif  /* _FORMAT_EXE_FORMAT_H */
-- 
cgit v0.11.2-87-g4458