diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/analysis/binary.c | 6 | ||||
| -rw-r--r-- | src/analysis/block-int.h | 4 | ||||
| -rw-r--r-- | src/analysis/block.c | 21 | ||||
| -rw-r--r-- | src/analysis/block.h | 16 | ||||
| -rw-r--r-- | src/analysis/blocks/flow.c | 62 | ||||
| -rw-r--r-- | src/analysis/blocks/flow.h | 3 | ||||
| -rw-r--r-- | src/analysis/blocks/virtual.c | 54 | ||||
| -rw-r--r-- | src/analysis/blocks/virtual.h | 3 | ||||
| -rw-r--r-- | src/analysis/decomp/decompiler.c | 2 | ||||
| -rw-r--r-- | src/analysis/disass/macro.c | 125 | ||||
| -rw-r--r-- | src/decomp/expr/immediate.c | 1 | ||||
| -rw-r--r-- | src/gtkext/graph/layout.c | 120 | ||||
| -rw-r--r-- | src/gtkext/graph/layout.h | 2 | ||||
| -rw-r--r-- | src/gtkext/graph/node.c | 78 | ||||
| -rw-r--r-- | src/gtkext/graph/node.h | 13 | ||||
| -rw-r--r-- | src/gtkext/gtkgraphview.c | 16 | 
16 files changed, 454 insertions, 72 deletions
diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 61f826a..e3b3e9d 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * binary.c - traitement des flots de code binaire   * - * Copyright (C) 2008-2012 Cyrille Bagard + * Copyright (C) 2008-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -797,10 +797,10 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binar      if (binary->decbuf_count > 0)      {          binary->dec_buffers = (GCodeBuffer **)calloc(binary->decbuf_count, sizeof(GCodeBuffer *)); -        /* +          for (i = 0; i < binary->decbuf_count; i++)              binary->dec_buffers[i] = decompile_all_from_file(binary, files[i]); -        */ +      } diff --git a/src/analysis/block-int.h b/src/analysis/block-int.h index e194ace..ba84fcb 100644 --- a/src/analysis/block-int.h +++ b/src/analysis/block-int.h @@ -29,6 +29,9 @@ +/* Parcours tous les blocs d'instructions dans un ordre donné. */ +typedef bool (* visit_all_blocks_fc) (GInstrBlock *, instr_block_visitor_cb, void *); +  /* Etablit la liste de tous les blocs présents. */  typedef void (* list_all_blocks_fc) (const GInstrBlock *, GInstrBlock ***, size_t *); @@ -42,6 +45,7 @@ struct _GInstrBlock  {      GObject parent;                         /* A laisser en premier        */ +    visit_all_blocks_fc visit_blocks;       /* Visite des différents blocs */      list_all_blocks_fc list_blocks;         /* Liste de tous les blocs     */      list_regs_accesses_fc list_regs;        /* Liste des accès registres   */ diff --git a/src/analysis/block.c b/src/analysis/block.c index 3093a98..3b3eaf3 100644 --- a/src/analysis/block.c +++ b/src/analysis/block.c @@ -157,6 +157,27 @@ static void g_instr_block_finalize(GInstrBlock *block)  /******************************************************************************  *                                                                             * +*  Paramètres  : block    = bloc d'instructions démarrant la visite.          * +*                callback = ensemble de blocs à parcourir.                    * +*                data     = donnée utilisateur à associer au parcours.        * +*                                                                             * +*  Description : Parcours tous les blocs d'instructions dans un ordre donné.  * +*                                                                             * +*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool g_instr_block_visit(GInstrBlock *block, instr_block_visitor_cb callback, void *data) +{ +    return block->visit_blocks(block, callback, data); + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : block = bloc d'instructions à consulter.                     *  *                list  = ensemble de blocs à compléter. [OUT]                 *  *                count = nombre de blocs au total. [OUT]                      * diff --git a/src/analysis/block.h b/src/analysis/block.h index 9e136a3..a85e4aa 100644 --- a/src/analysis/block.h +++ b/src/analysis/block.h @@ -79,9 +79,25 @@ typedef struct _GInstrBlock GInstrBlock;  typedef struct _GInstrBlockClass GInstrBlockClass; +/* Position au cours d'une visite */ +typedef enum _BlockVisitOrder +{ +    BVO_IN,                                 /* Entrée dans un gros bloc    */ +    BVO_PENDING,                            /* Visite d'un bloc simple     */ +    BVO_OUT                                 /* Sortie d'un gros bloc       */ + +} BlockVisitOrder; + +/* Rappel à chaque bloc visité */ +typedef bool (* instr_block_visitor_cb) (GInstrBlock *, BlockVisitOrder, void *); + +  /* Indique le type défini pour un bloc d'instructions. */  GType g_instr_block_get_type(void); +/* Parcours tous les blocs d'instructions dans un ordre donné. */ +bool g_instr_block_visit(GInstrBlock *, instr_block_visitor_cb, void *); +  /* Etablit la liste de tous les blocs présents. */  void g_instr_block_list_all_blocks(const GInstrBlock *, GInstrBlock ***, size_t *); diff --git a/src/analysis/blocks/flow.c b/src/analysis/blocks/flow.c index f80b7c8..85d98ee 100644 --- a/src/analysis/blocks/flow.c +++ b/src/analysis/blocks/flow.c @@ -65,15 +65,18 @@ static void g_flow_block_dispose(GFlowBlock *);  /* Procède à la libération totale de la mémoire. */  static void g_flow_block_finalize(GFlowBlock *); +/* Parcours le bloc d'instructions dans un ordre donné. */ +static bool g_flow_block_visit(GFlowBlock *, instr_block_visitor_cb, void *); + +/* Etablit la liste de tous les blocs présents. */ +static void g_flow_block_list_all_blocks(const GFlowBlock *, GInstrBlock ***, size_t *); +  /* Prend note de l'usage d'un registre, au besoin. */  static void g_flow_block_memorize_access(GFlowBlock *, GArchRegister *, RegAccessType, vmpa_t);  /* Note les différents accès aux registres. */  static void g_flow_block_compute_regs_access(GFlowBlock *); -/* Etablit la liste de tous les blocs présents. */ -static void g_flow_block_list_all_blocks(const GFlowBlock *, GInstrBlock ***, size_t *); -  /* Fournit les différents accès aux registres. */  static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *, size_t *); @@ -125,6 +128,7 @@ static void g_flow_block_init(GFlowBlock *block)      parent = G_INSTR_BLOCK(block); +    parent->visit_blocks = (visit_all_blocks_fc)g_flow_block_visit;      parent->list_blocks = (list_all_blocks_fc)g_flow_block_list_all_blocks;      parent->list_regs = (list_regs_accesses_fc)g_flow_block_list_regs_accesses; @@ -199,7 +203,7 @@ GInstrBlock *g_flow_block_new(GArchInstruction *instrs, GArchInstruction *first,  {      GFlowBlock *result;                     /* Structure à retourner       */ -    vmpa_t addr;                            /* Adresse de la destination   */ +    //vmpa_t addr;                            /* Adresse de la destination   */      result = g_object_new(G_TYPE_FLOW_BLOCK, NULL); @@ -232,6 +236,27 @@ GInstrBlock *g_flow_block_new(GArchInstruction *instrs, GArchInstruction *first,  /******************************************************************************  *                                                                             * +*  Paramètres  : block    = bloc d'instructions concerné par la visite.       * +*                callback = ensemble de blocs à parcourir.                    * +*                data     = donnée utilisateur à associer au parcours.        * +*                                                                             * +*  Description : Parcours le bloc d'instructions dans un ordre donné.         * +*                                                                             * +*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_flow_block_visit(GFlowBlock *block, instr_block_visitor_cb callback, void *data) +{ +    return callback(G_INSTR_BLOCK(block), BVO_PENDING, data); + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : block = bloc d'instructions à consulter.                     *  *                list  = ensemble de blocs à compléter. [OUT]                 *  *                count = nombre de blocs au total. [OUT]                      * @@ -394,6 +419,28 @@ static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *block  /******************************************************************************  *                                                                             *  *  Paramètres  : block = bloc d'instructions à consulter.                     * +*                first = instruction de départ du bloc. [OUT]                 * +*                last  = dernière instruction du bloc. [OUT]                  * +*                                                                             * +*  Description : Fournit les instructions limites d'un bloc d'exécution.      * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_flow_block_get_boundary(const GFlowBlock *block, GArchInstruction **first, GArchInstruction **last) +{ +    *first = block->first; +    *last = block->last; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc d'instructions à consulter.                     *  *                start = adresse de départ du bloc. [OUT]                     *  *                end   = dernière adresse du bloc. [OUT]                      *  *                                                                             * @@ -407,7 +454,10 @@ static const reg_access *g_flow_block_list_regs_accesses(const GFlowBlock *block  void g_flow_block_get_boundary_addresses(const GFlowBlock *block, vmpa_t *start, vmpa_t *end)  { -    g_arch_instruction_get_location(block->first, NULL, NULL, start); -    g_arch_instruction_get_location(block->last, NULL, NULL, end); +    if (start != NULL) +        g_arch_instruction_get_location(block->first, NULL, NULL, start); + +    if (end != NULL) +        g_arch_instruction_get_location(block->last, NULL, NULL, end);  } diff --git a/src/analysis/blocks/flow.h b/src/analysis/blocks/flow.h index 14f49ec..8bd7257 100644 --- a/src/analysis/blocks/flow.h +++ b/src/analysis/blocks/flow.h @@ -55,6 +55,9 @@ GType g_flow_block_get_type(void);  /* Crée un bloc d'exécution d'instructions. */  GInstrBlock *g_flow_block_new(GArchInstruction *, GArchInstruction *, GArchInstruction *); +/* Fournit les instructions limites d'un bloc d'exécution. */ +void g_flow_block_get_boundary(const GFlowBlock *, GArchInstruction **, GArchInstruction **); +  /* Fournit les adresses limites d'un bloc d'exécution. */  void g_flow_block_get_boundary_addresses(const GFlowBlock *, vmpa_t *, vmpa_t *); diff --git a/src/analysis/blocks/virtual.c b/src/analysis/blocks/virtual.c index c981ece..90bccca 100644 --- a/src/analysis/blocks/virtual.c +++ b/src/analysis/blocks/virtual.c @@ -69,6 +69,9 @@ static void g_virtual_block_dispose(GVirtualBlock *);  /* Procède à la libération totale de la mémoire. */  static void g_virtual_block_finalize(GVirtualBlock *); +/* Parcours le bloc d'instructions dans un ordre donné. */ +static bool g_virtual_block_visit(GVirtualBlock *, instr_block_visitor_cb, void *); +  /* Etablit la liste de tous les blocs présents. */  static void g_virtual_block_list_all_blocks(const GVirtualBlock *, GInstrBlock ***, size_t *); @@ -123,6 +126,7 @@ static void g_virtual_block_init(GVirtualBlock *block)      parent = G_INSTR_BLOCK(block); +    parent->visit_blocks = (visit_all_blocks_fc)g_virtual_block_visit;      parent->list_blocks = (list_all_blocks_fc)g_virtual_block_list_all_blocks;      parent->list_regs = (list_regs_accesses_fc)g_virtual_block_list_regs_accesses; @@ -203,6 +207,37 @@ GInstrBlock *g_virtual_block_new(void)  /******************************************************************************  *                                                                             * +*  Paramètres  : block    = bloc d'instructions concerné par la visite.       * +*                callback = ensemble de blocs à parcourir.                    * +*                data     = donnée utilisateur à associer au parcours.        * +*                                                                             * +*  Description : Parcours le bloc d'instructions dans un ordre donné.         * +*                                                                             * +*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_virtual_block_visit(GVirtualBlock *block, instr_block_visitor_cb callback, void *data) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours          */ + +    result = callback(G_INSTR_BLOCK(block), BVO_IN, data); + +    for (i = 0; i < block->children_count && result; i++) +        result = g_instr_block_visit(block->children[i], callback, data); + +    result &= callback(G_INSTR_BLOCK(block), BVO_OUT, data); + +    return true; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : block = bloc d'instructions à consulter.                     *  *                list  = ensemble de blocs à compléter. [OUT]                 *  *                count = nombre de blocs au total. [OUT]                      * @@ -270,3 +305,22 @@ void g_virtual_block_add_child(GVirtualBlock *block, GInstrBlock *child)      g_object_ref(G_OBJECT(child));  } + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block = bloc d'instructions à consulter.                     * +*                                                                             * +*  Description : Compte le nombre de blocs contenus dans le groupe courant.   * +*                                                                             * +*  Retour      : Quantité normalement non nulle.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +size_t g_virtual_block_count_children(GVirtualBlock *block) +{ +    return block->children_count; + +} diff --git a/src/analysis/blocks/virtual.h b/src/analysis/blocks/virtual.h index f1f559f..5e8ddcd 100644 --- a/src/analysis/blocks/virtual.h +++ b/src/analysis/blocks/virtual.h @@ -58,6 +58,9 @@ GInstrBlock *g_virtual_block_new(void);  /* Ajoute un bloc au groupe courant. */  void g_virtual_block_add_child(GVirtualBlock *, GInstrBlock *); +/* Compte le nombre de blocs contenus dans le groupe courant. */ +size_t g_virtual_block_count_children(GVirtualBlock *); +  #endif  /* _ANALYSIS_BLOCKS_VIRTUAL_H */ diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c index 1ac177a..c824697 100644 --- a/src/analysis/decomp/decompiler.c +++ b/src/analysis/decomp/decompiler.c @@ -217,6 +217,7 @@ GCodeBuffer *decompile_all_from_file(const GLoadedBinary *binary, const char *fi      build_decomp_prologue(result, filename); +    /*      prepare_all_routines_for_decomp(binary, filename); @@ -224,6 +225,7 @@ GCodeBuffer *decompile_all_from_file(const GLoadedBinary *binary, const char *fi      format = g_loaded_binary_get_format(binary);      g_binary_format_decompile(G_BIN_FORMAT(format), result, filename); +    */      return result; diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index 46dc0d3..2e5c0ee 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -277,6 +277,7 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t  static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop)  {      GInstrBlock *result;                    /* Regroupement à retourner    */ +    GInstrBlock *result_cached;             /* Temporisation pour unicité  */      branch_info main_branch;                /* Flot d'exécution complet    */      GArchInstruction *first;                /* Première instruction        */      GArchInstruction *last;                 /* Dernière instruction        */ @@ -287,6 +288,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta      size_t dcount;                          /* Nombre de liens de dest.    */      size_t i;                               /* Boucle de parcours #1       */      GInstrBlock *block;                     /* Nouveau bloc mis en place   */ +    GInstrBlock *group;                     /* Regroupement de blocs       */      branch_info *cases_branches;            /* Branches d'un aiguillage    */      size_t cases_count;                     /* Nombre d'aiguillages        */      branch_info true_branch;                /* Branche 'condition vraie'   */ @@ -298,6 +300,32 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta      vmpa_t stop_addr;                       /* Adresse de fin de bloc      */      result = NULL; +    result_cached = NULL; + +    /** +     * Procédure d'ajout de blocs : pour le premier, on conserve le bloc en mémoire +     * et on attend. Si rien ne suit, il constitura l'unique retour. Sinon, on +     * l'ajoute à partir de la sauvegarde, et le reste suit. +     */ +#define DELAYED_BLOCK_ADDING(res, cache, blk)                               \ +    do                                                                      \ +    {                                                                       \ +        if (res == NULL)                                                    \ +        {                                                                   \ +            if (cache == NULL)                                              \ +                cache = blk;                                                \ +            else                                                            \ +            {                                                               \ +                res = g_virtual_block_new();                                \ +                g_virtual_block_add_child(G_VIRTUAL_BLOCK(res), cache);     \ +            }                                                               \ +        }                                                                   \ +                                                                            \ +        if (res != NULL)                                                    \ +            g_virtual_block_add_child(G_VIRTUAL_BLOCK(res), blk);           \ +                                                                            \ +    }                                                                       \ +    while (0)      first = NULL;      last = NULL; @@ -347,14 +375,13 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta                  case ILT_EXEC_FLOW:                  case ILT_JUMP: -                    if (result == NULL) -                        result = g_virtual_block_new();                      block = g_flow_block_new(instrs, first, iter);                      MACRO_MARK_AS_PROCESSED(first); -                    g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);                      first = NULL; +                    DELAYED_BLOCK_ADDING(result, result_cached, block); +                      g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr);                      break; @@ -401,15 +428,14 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta          /* Post-traitements de ILT_CASE_JUMP */          if (cases_count > 0)          { -            if (result == NULL) -                result = g_virtual_block_new(); -              if (first != NULL)              {                  block = g_flow_block_new(instrs, first, iter);                  MACRO_MARK_AS_PROCESSED(first); -                g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);                  first = NULL; + +                DELAYED_BLOCK_ADDING(result, result_cached, block); +              }              //printf(" --- cases --- start\n"); @@ -417,6 +443,8 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              next_addr = compute_first_common_addr_in_group(cases_branches, cases_count);              //printf("    stop :: 0x%08llx\n", next_addr); +            group = g_virtual_block_new(); +              for (j = 0; j < cases_count; j++)              {                  //printf(" ## %zu\n", j); @@ -425,12 +453,17 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta                  if (block != NULL) -                g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); +                g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block);                  free(cases_branches[j].jumps);              } +            if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0) +                DELAYED_BLOCK_ADDING(result, result_cached, group); +            else +                g_object_unref(G_OBJECT(group)); +              //printf(" --- cases --- end\n"); @@ -441,15 +474,14 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta          /* Post-traitements de ILT_CATCH_EXCEPTION */          if (excep_count > 0)          { -            if (result == NULL) -                result = g_virtual_block_new(); -              if (first != NULL)              {                  block = g_flow_block_new(instrs, first, iter);                  MACRO_MARK_AS_PROCESSED(first); -                g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);                  first = NULL; + +                DELAYED_BLOCK_ADDING(result, result_cached, block); +              }              for (j = 0; j < excep_count; j++) @@ -482,28 +514,30 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              next_addr = compute_first_common_addr(&true_branch, &false_branch);              next_addr = MIN(next_addr, end); -            if (result == NULL) -                result = g_virtual_block_new(); -              if (first != NULL)              {                  block = g_flow_block_new(instrs, first, iter);                  MACRO_MARK_AS_PROCESSED(first); -                g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block);                  first = NULL; -            } -            block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr); +                DELAYED_BLOCK_ADDING(result, result_cached, block); -                if (block != NULL) +            } -            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); +            group = g_virtual_block_new(); -            block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr); +            block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr); +            if (block != NULL) +                g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); -                if (block != NULL) +            block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr); +            if (block != NULL) +                g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); -            g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); +            if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0) +                DELAYED_BLOCK_ADDING(result, result_cached, group); +            else +                g_object_unref(G_OBJECT(group));              free(true_branch.jumps);              free(false_branch.jumps); @@ -526,21 +560,51 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              MACRO_MARK_AS_PROCESSED(first);              //printf("--close!--\n"); -            if (result == NULL) -                result = block; -            else -                g_virtual_block_add_child(G_VIRTUAL_BLOCK(result), block); +            DELAYED_BLOCK_ADDING(result, result_cached, block); +          }      } -    if (result == NULL) +    if ((result != NULL ? result : result_cached) == NULL)      {          //printf("WARNING :: null !\n");          //exit(0);      } -    return result; +    return (result != NULL ? result : result_cached); + +} + + +static bool print_blocks(GInstrBlock *blk, BlockVisitOrder order, int *pad) +{ +    int i; +    vmpa_t start, end; + +    if (order != BVO_OUT) +        for (i = 0; i < *pad; i++) +            printf("   "); + +    if (G_IS_FLOW_BLOCK(blk)) +    { +        g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(blk), &start, &end); +        printf(" - flow %p : 0x%08lx -> 0x%08lx\n", blk, start, end); +    } +    else +    { +        if (order != BVO_OUT) +        { +            printf(" - virtual %p\n", blk); +            *pad += 1; +        } +        else *pad -= 1; + +    } + +    fflush(NULL); + +    return true;  } @@ -580,6 +644,9 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines,          block = build_instruction_block(list, start, end, VMPA_MAX);          g_binary_routine_set_basic_blocks(routines[i], block); + +        //g_instr_block_visit(block, (instr_block_visitor_cb)print_blocks, (int []){ 0 }); +          gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);      } diff --git a/src/decomp/expr/immediate.c b/src/decomp/expr/immediate.c index a17b2a1..18af422 100644 --- a/src/decomp/expr/immediate.c +++ b/src/decomp/expr/immediate.c @@ -122,6 +122,7 @@ GDecInstruction *g_imm_expression_new(GImmOperand *operand)      result = g_object_new(G_TYPE_IMM_EXPRESSION, NULL);      result->operand = operand; +    g_object_ref(G_OBJECT(operand));      return G_DEC_INSTRUCTION(result); diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c index 45e3a82..2cf4a36 100644 --- a/src/gtkext/graph/layout.c +++ b/src/gtkext/graph/layout.c @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * layout.c - mise en place de graphique   * - * Copyright (C) 2009-2012 Cyrille Bagard + * Copyright (C) 2009-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -33,14 +33,33 @@  #include "node.h"  #include "../gtkbufferview.h"  #include "../../analysis/binary.h" +#include "../../analysis/blocks/flow.h"  #include "../../common/extstr.h" +/* Taille maximale des introductions aux clusters */ +#define CLUSTER_DESC_LEN 128 +  /* Taille maximale des descriptions de liens */  #define LINKS_DESC_LEN 128 +/* Paramètres de construction des commandes */ +typedef struct _visitor_dot_params +{ +    GGraphNode **nodes;                     /* Intermédiaires en place     */ +    size_t count;                           /* Quantité de noeuds en place */ + +    unsigned int level;                     /* Profondeur de la visite     */ +    char *cmds;                             /* Description à envoyer à dot */ + +} visitor_dot_params; + + +/* Construit les commandes pour dot en parcourant les noeuds. */ +static bool register_graph_nodes(GInstrBlock *, BlockVisitOrder, visitor_dot_params *); +  /* Etablit tous les liens entre les différents morceaux de code. */  static char *complete_graph_links(const GtkGraphView *, GtkViewPanel **, size_t, char *); @@ -60,47 +79,118 @@ static char *complete_graph_links(const GtkGraphView *, GtkViewPanel **, size_t,  *                                                                             *  ******************************************************************************/ -bool build_graph_view(GtkGraphView *view, GtkViewPanel **views, size_t count) +bool build_graph_view(GtkGraphView *view, GInstrBlock *blocks, GtkViewPanel **views, size_t count)  { -    GGraphNode **nodes;                     /* Intermédiaires en place     */ +    visitor_dot_params params;              /* Paramètres de construction  */      size_t i;                               /* Boucle de parcours          */ -    char *cmds;                             /* Description à envoyer à dot */      graph_layout *layout;                   /* Graphique construit         */      GtkLinkRenderer **links;                /* Liens graphiques construits */      size_t links_count;                     /* Quantité de ces liens       */      /* Création de la glue */ -    nodes = (GGraphNode **)calloc(count, sizeof(GGraphNode *)); +    params.nodes = (GGraphNode **)calloc(count, sizeof(GGraphNode *)); +    params.count = count;      for (i = 0; i < count; i++) -        nodes[i] = g_graph_node_new(GTK_WIDGET(views[i])); +        params.nodes[i] = g_graph_node_new(GTK_WIDGET(views[i]));      /* Définition du graphique */ -    cmds = strdup("digraph G {\n  overlap=false;\n  splines=ortho;\n  compound=true;\n"); +    params.level = 1; +    params.cmds = strdup("digraph G {\n  overlap=false;\n  splines=ortho;\n  compound=true;\n"); -    for (i = 0; i < count; i++) -        cmds = g_graph_node_register_for_dot(nodes[i], cmds); +    g_instr_block_visit(blocks, (instr_block_visitor_cb)register_graph_nodes, ¶ms); -    cmds = complete_graph_links(view, views, count, cmds); +    params.cmds = complete_graph_links(view, views, count, params.cmds); -    cmds = stradd(cmds, "}"); +    params.cmds = stradd(params.cmds, "}"); -    layout = create_graph_layout(cmds); +    layout = create_graph_layout(params.cmds);      /* Affichage du graphique */ -    place_nodes_of_graph_layout(layout, view,  nodes, count); +    place_nodes_of_graph_layout(layout, view,  params.nodes, count); -    links = create_links_from_graph_layout(layout, &links_count,  nodes, count); +    links = create_links_from_graph_layout(layout, &links_count,  params.nodes, count);      gtk_graph_view_attach_links(view, links, links_count);      gtk_widget_queue_draw(GTK_WIDGET(view));      delete_graph_layout(layout); -    /* TODO : free nodes */ +    for (i = 0; i < count; i++) +        g_object_unref(params.nodes[i]); + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : block  = bloc d'instructions concerné par la visite.         * +*                order  = position dans la visite.                            * +*                params = informations à mettre à jour pour dot.              * +*                                                                             * +*  Description : Construit les commandes pour dot en parcourant les noeuds.   * +*                                                                             * +*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool register_graph_nodes(GInstrBlock *block, BlockVisitOrder order, visitor_dot_params *params) +{ +    char *cmds;                             /* Raccourci d'usage pratique  */ +    vmpa_t start;                           /* Adresse de départ d'un bloc */ +    GGraphNode *node;                       /* Noeud rattaché              */ +    unsigned int i;                         /* Boucle de parcours          */ +    char buffer[CLUSTER_DESC_LEN];          /* Tampon pour les commandes   */ + +    cmds = params->cmds; + +    if (G_IS_FLOW_BLOCK(block)) +    { +        g_flow_block_get_boundary_addresses(G_FLOW_BLOCK(block), &start, NULL); +        node = find_graph_node_by_start_address(params->nodes, params->count, start); + +        cmds = g_graph_node_register_for_dot(node, cmds, params->level); + +    } +    else +    { +        if (order == BVO_IN) +        { +            for (i = 0; i < params->level; i++) +                cmds = stradd(cmds, DOT_IDENT); + +            snprintf(buffer, CLUSTER_DESC_LEN, "subgraph cluster_v%p {\n", block); +            cmds = stradd(cmds, buffer); + +            params->level++; + +            for (i = 0; i < params->level; i++) +                cmds = stradd(cmds, DOT_IDENT); + +            cmds = stradd(cmds, "style=invisible;\n"); + +        } +        else if (order == BVO_OUT) +        { +            params->level--; + +            for (i = 0; i < params->level; i++) +                cmds = stradd(cmds, DOT_IDENT); + +            cmds = stradd(cmds, "}\n"); + +        } + +    } + +    params->cmds = cmds;      return true; diff --git a/src/gtkext/graph/layout.h b/src/gtkext/graph/layout.h index ffb227f..7a3bf1e 100644 --- a/src/gtkext/graph/layout.h +++ b/src/gtkext/graph/layout.h @@ -34,7 +34,7 @@  /* Dispose une série de morceaux d'affichage en graphique. */ -bool build_graph_view(GtkGraphView *, GtkViewPanel **, size_t); +bool build_graph_view(GtkGraphView *, GInstrBlock *, GtkViewPanel **, size_t); diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c index 0d746e2..d9b0eca 100644 --- a/src/gtkext/graph/node.c +++ b/src/gtkext/graph/node.c @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * node.c - éléments de graphiques chez dot   * - * Copyright (C) 2009-2012 Cyrille Bagard + * Copyright (C) 2009-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -29,6 +29,7 @@  #include <string.h> +#include "../gtkbufferview.h"  #include "../../common/extstr.h" @@ -60,6 +61,10 @@ struct _GGraphNodeClass  }; +/* Taille maximale des lignes de description de noeud */ +#define NODE_DESC_LEN 128 + +  /* Initialise la classe des intermédiaires avec les noeuds dot. */  static void g_graph_node_class_init(GGraphNodeClass *); @@ -184,8 +189,9 @@ GGraphNode *g_graph_node_new(GtkWidget *view)  /******************************************************************************  *                                                                             * -*  Paramètres  : node = intermédiaire à consulter.                            * -*                cmds = description pour dot à compléter.                     * +*  Paramètres  : node  = intermédiaire à consulter.                           * +*                cmds  = description pour dot à compléter.                    * +*                level = profondeur du noeud pour l'indentation.              *  *                                                                             *  *  Description : Déclare l'intermédiaire en tant que noeud pour dot.          *  *                                                                             * @@ -195,33 +201,45 @@ GGraphNode *g_graph_node_new(GtkWidget *view)  *                                                                             *  ******************************************************************************/ -char *g_graph_node_register_for_dot(const GGraphNode *node, char *cmds) +char *g_graph_node_register_for_dot(const GGraphNode *node, char *cmds, unsigned int level)  {      GtkRequisition requisition;             /* Taille à l'écran requise    */ -    char buffer[128]; +    unsigned int i;                         /* Boucle de parcours          */ +    char buffer[NODE_DESC_LEN];             /* Tampon pour les commandes   */      gtk_widget_size_request(node->view, &requisition); -    snprintf(buffer, 128, "  subgraph cluster%s {\n", node->name); +    for (i = 0; i < level; i++) +        cmds = stradd(cmds, DOT_IDENT); + +    snprintf(buffer, NODE_DESC_LEN, "subgraph cluster%s {\n", node->name);      cmds = stradd(cmds, buffer); -    cmds = stradd(cmds, "    style=invisible;\n"); +    for (i = 0; i < (level + 1); i++) +        cmds = stradd(cmds, DOT_IDENT); + +    cmds = stradd(cmds, "style=invisible;\n"); + +    for (i = 0; i < (level + 1); i++) +        cmds = stradd(cmds, DOT_IDENT); -    cmds = stradd(cmds, "    ");      cmds = stradd(cmds, node->name);      cmds = stradd(cmds, " [shape=box, fixedsize "); -    snprintf(buffer, 128, ", width=\"%g\"", +    snprintf(buffer, NODE_DESC_LEN, ", width=\"%g\"",               requisition.width / G_GRAPH_NODE_GET_CLASS(node)->dpi_x);      cmds = stradd(cmds, buffer); -    snprintf(buffer, 128, ", height=\"%g\"", +    snprintf(buffer, NODE_DESC_LEN, ", height=\"%g\"",               requisition.height / G_GRAPH_NODE_GET_CLASS(node)->dpi_y);      cmds = stradd(cmds, buffer);      cmds = stradd(cmds, "];\n"); -    cmds = stradd(cmds, "  }\n"); +    for (i = 0; i < level; i++) +        cmds = stradd(cmds, DOT_IDENT); + +    cmds = stradd(cmds, "}\n");      return cmds; @@ -327,6 +345,44 @@ void g_graph_node_connect(const GGraphNode *node, gint x, gint y, GdkPoint **poi  /******************************************************************************  *                                                                             * +*  Paramètres  : nodes = liste de noeuds à parcourir.                         * +*                count = taille de la liste.                                  * +*                addrt = adresse de début du noeud recherché.                 * +*                                                                             * +*  Description : Recherche un noeud donné dans une série de noeuds.           * +*                                                                             * +*  Retour      : Noeud trouvé ou NULL si aucun.                               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GGraphNode *find_graph_node_by_start_address(GGraphNode **nodes, size_t count, vmpa_t addr) +{ +    GGraphNode *result;                     /* Trouvaille à remonter       */ +    size_t i;                               /* Boucle de parcours          */ +    GBufferView *buffer;                    /* Tampon d'une partie de code */ +    vmpa_t start;                           /* Adresse de départ du tampon */ + +    result = NULL; + +    for (i = 0; i < count && result == NULL; i++) +    { +        buffer = gtk_buffer_view_get_buffer(GTK_BUFFER_VIEW(nodes[i]->view)); +        g_buffer_view_get_restrictions(buffer, &start, NULL); + +        if (start == addr) +            result = nodes[i]; + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : nodes  = liste de noeuds à parcourir.                        *  *                count  = taille de la liste.                                 *  *                target = nom du noeud recherché.                             * diff --git a/src/gtkext/graph/node.h b/src/gtkext/graph/node.h index 515c92b..57d0932 100644 --- a/src/gtkext/graph/node.h +++ b/src/gtkext/graph/node.h @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * node.h - prototypes pour les éléments de graphiques chez dot   * - * Copyright (C) 2009-2012 Cyrille Bagard + * Copyright (C) 2009-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -26,6 +26,12 @@  #include "../gtkgraphview.h" +#include "../../arch/archbase.h" + + + +/* Indentation pour l'édition des commandes */ +#define DOT_IDENT "   " @@ -53,7 +59,7 @@ GType g_graph_node_get_type(void);  GGraphNode *g_graph_node_new(GtkWidget *);  /* Déclare l'intermédiaire en tant que noeud pour dot. */ -char *g_graph_node_register_for_dot(const GGraphNode *, char *); +char *g_graph_node_register_for_dot(const GGraphNode *, char *, unsigned int);  /* Place le morceau de code de l'intermédiaire à l'écran. */  void g_graph_node_place(GGraphNode *, GtkGraphView *, gint , gint); @@ -67,6 +73,9 @@ void g_graph_node_connect(const GGraphNode *, gint, gint, GdkPoint **, size_t *)  /* Recherche un noeud donné dans une série de noeuds. */ +GGraphNode *find_graph_node_by_start_address(GGraphNode **, size_t, vmpa_t); + +/* Recherche un noeud donné dans une série de noeuds. */  GGraphNode *find_graph_node_by_name(GGraphNode **, size_t, const char *); diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c index 67fb577..6aedf26 100644 --- a/src/gtkext/gtkgraphview.c +++ b/src/gtkext/gtkgraphview.c @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * gtkgraphview.c - affichage de morceaux de code sous forme graphique   * - * Copyright (C) 2009-2012 Cyrille Bagard + * Copyright (C) 2009-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -39,8 +39,9 @@ struct _GtkGraphView      GtkViewPanel parent;                    /* A laisser en premier        */      GtkFixed *support;                      /* Support des vues en bloc    */ -    vmpa_t start;                           /* Début de la portion vue     */ -    vmpa_t end;                             /* Fin de la portion affichée  */ +    GBinRoutine *routine;                   /* Routine en cours d'affichage*/ +    vmpa_t start;                           /* Début de la portion vue     */ /* FIXME : à garder ? */ +    vmpa_t end;                             /* Fin de la portion affichée  */ /* FIXME : à garder ? */      GtkViewPanel **children;                /* Liste des sous-blocs        */      GtkAllocation *allocs;                  /* Emplacements prévisibles    */ @@ -380,6 +381,9 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, vmpa_t addr)              if (start <= addr && addr < end)              { +                view->routine = routines[i]; +                g_object_ref(G_OBJECT(view->routine)); +                  view->start = start;                  view->end = end; @@ -389,7 +393,8 @@ static void gtk_graph_view_define_main_address(GtkGraphView *view, vmpa_t addr)                  view->allocs = (GtkAllocation *)calloc(view->children_count,                                                         sizeof(GtkAllocation)); -                build_graph_view(view, view->children, view->children_count); +                build_graph_view(view, g_binary_routine_get_basic_blocks(view->routine), +                                 view->children, view->children_count);                  break; @@ -425,7 +430,8 @@ static void gtk_graph_view_prepare_resize(GtkGraphView *view)          for (i = 0; i < view->children_count; i++)              gtk_widget_queue_resize(GTK_WIDGET(view->children[i])); -        build_graph_view(view, view->children, view->children_count); +        build_graph_view(view, g_binary_routine_get_basic_blocks(view->routine), +                         view->children, view->children_count);          change_editor_items_current_view_content(GTK_VIEW_PANEL(view));  | 
