diff options
Diffstat (limited to 'src/analysis/disass')
| -rw-r--r-- | src/analysis/disass/macro.c | 125 | 
1 files changed, 96 insertions, 29 deletions
| 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);      } | 
