diff options
Diffstat (limited to 'src/analysis')
| -rw-r--r-- | src/analysis/decomp/reduce.c | 2 | ||||
| -rw-r--r-- | src/analysis/disass/macro.c | 456 | 
2 files changed, 288 insertions, 170 deletions
| diff --git a/src/analysis/decomp/reduce.c b/src/analysis/decomp/reduce.c index 2d6fce3..c372f2a 100644 --- a/src/analysis/decomp/reduce.c +++ b/src/analysis/decomp/reduce.c @@ -332,7 +332,7 @@ static void replace_useless_variable(GDecInstruction *block, GHashTable *table)      while (g_hash_table_iter_next(&iter, (gpointer *)&var, (gpointer *)&val))      { -        replace = G_IS_IMM_EXPRESSION(val->value); +        replace = (G_IS_IMM_EXPRESSION(val->value) && (val->used_counter > 1));          replace |= (val->used_counter == 2);    /* 1 assign. + 1 usage */          if (!replace) continue; diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index 993f70f..8766ed9 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -24,6 +24,7 @@  #include "macro.h" +#include <malloc.h>  #include <string.h> @@ -32,6 +33,40 @@ +/* ------------------------ COUVERTURE D'UNE ZONE A DECOUPER ------------------------ */ + + +/* Bornes d'une zone à couvrir */ +typedef struct _code_coverage +{ +    vmpa_t start;                           /* Adresse de départ           */ + +    vmpa_t *ends;                           /* Adresses butoir de fin      */ +    size_t ends_count;                      /* Quantité de fins possibles  */ + +} code_coverage; + + +/* Met en place les délimitations d'une zone de code. */ +static code_coverage *create_code_coverage(vmpa_t, vmpa_t); + +/* Crée une copie d'une couverture de zone de code. */ +static code_coverage *dup_code_coverage(vmpa_t, const code_coverage *); + +/* Détruit des délimitations d'une zone de code. */ +static void delete_code_coverage(code_coverage *); + +/* Indique si une adresse est hors zone ou non. */ +static bool code_coverage_stop_here(const code_coverage *, const vmpa_t *); + +/* Ajoute une adresse butoir pour la zone à couvrir. */ +static void add_ending_address_code_coverage(code_coverage *, const vmpa_t *); + + + +/* ------------------------- SUIVI DES FLOTS D'INSTRUCTIONS ------------------------- */ + +  /* Indications sur une branche */  typedef struct _branch_info  { @@ -41,6 +76,23 @@ typedef struct _branch_info  } branch_info; +/* Indique si une adresse est retenue comme point de passage. */ +static bool is_addr_in_branch(const branch_info *, const vmpa_t *); + +/* Identifie les différents points de passage d'une branche. */ +static void find_next_jumps(GArchInstruction *, vmpa_t, const code_coverage *, branch_info *); + +/* Retrouve le point de ralliement entre deux branches. */ +static vmpa_t compute_first_common_addr(branch_info *, branch_info *); + +/* Retrouve le point de ralliement entre un groupe de branches. */ +static vmpa_t compute_first_common_addr_in_group(const branch_info *, size_t); + + + +/* --------------------------- DECOUPAGE EN BLOCS DE CODE --------------------------- */ + +  /**   * Macros pour le marquage des instructions traitées.   * Dans un soucis d'optimisation, on ne traite que les instructions @@ -51,29 +103,159 @@ typedef struct _branch_info  #define MACRO_CLEAR_PROCESSED(_instr) g_object_set_data(G_OBJECT(_instr), "macro_done", NULL) -/* Indique si une adresse est retenue comme point de passage. */ -static bool is_addr_in_branch(const branch_info *, const vmpa_t *, bool, size_t *); +/* Procède à la définition de bloc regroupant des instructions. */ +static GInstrBlock *build_instruction_block(GArchInstruction *, const code_coverage *); -/* Identifie les différents points de passage d'une branche. */ -static void find_next_jumps(GArchInstruction *, vmpa_t, vmpa_t, branch_info *); -/* Retrouve le point de ralliement entre deux branches. */ -static vmpa_t compute_first_common_addr(branch_info *, branch_info *); -/* Retrouve le point de ralliement entre un groupe de branches. */ -static vmpa_t compute_first_common_addr_in_group(const branch_info *, size_t); +/* ---------------------------------------------------------------------------------- */ +/*                          COUVERTURE D'UNE ZONE A DECOUPER                          */ +/* ---------------------------------------------------------------------------------- */ -/* Procède à la définition de bloc regroupant des instructions. */ -static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t, vmpa_t); +/****************************************************************************** +*                                                                             * +*  Paramètres  : start = adresse du début de la zone à couvrir.               * +*                end   = adresse de fin de la zone à couvrir (exclusive).     * +*                                                                             * +*  Description : Met en place les délimitations d'une zone de code.           * +*                                                                             * +*  Retour      : Couverture d'une zone de code.                               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static code_coverage *create_code_coverage(vmpa_t start, vmpa_t end) +{ +    code_coverage *result;                  /* Couverture à retourner      */ + +    result = (code_coverage *)calloc(1, sizeof(code_coverage)); + +    result->start = start; + +    result->ends = (vmpa_t *)calloc(1, sizeof(vmpa_t)); +    result->ends_count = 1; + +    result->ends[0] = end; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : start = nouvelle adresse de début, plus profonde.            * +*                src   = informations de couverture à consulter.              * +*                                                                             * +*  Description : Crée une copie d'une couverture de zone de code.             * +*                                                                             * +*  Retour      : Couverture d'une zone de code copiée.                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static code_coverage *dup_code_coverage(vmpa_t start, const code_coverage *src) +{ +    code_coverage *result;                  /* Couverture à retourner      */ +    size_t i;                               /* Boucle de parcours          */ + +    result = (code_coverage *)calloc(1, sizeof(code_coverage)); + +    result->start = start; + +    result->ends = (vmpa_t *)calloc(src->ends_count, sizeof(vmpa_t)); +    result->ends_count = src->ends_count; + +    for (i = 0; i < result->ends_count; i++) +        result->ends[i] = src->ends[i]; + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : coverage = structure à libérer de la mémoire.                * +*                                                                             * +*  Description : Détruit des délimitations d'une zone de code.                * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void delete_code_coverage(code_coverage *coverage) +{ +    free(coverage->ends); + +    free(coverage); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : coverage = informations de couverture à consulter.           * +*                addr     = adresse à tester.                                 * +*                                                                             * +*  Description : Indique si une adresse est hors zone ou non.                 * +*                                                                             * +*  Retour      : true si l'adresse ne doit pas être couverte, false sinon.    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool code_coverage_stop_here(const code_coverage *coverage, const vmpa_t *addr) +{ +    void *ptr;                              /* Résultat des recherches     */ + +    ptr = bsearch(addr, coverage->ends, coverage->ends_count, +                  sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); + +    return (ptr != NULL); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : coverage = informations de couverture à compléter.           * +*                addr     = adresse à ajouter.                                * +*                                                                             * +*  Description : Ajoute une adresse butoir pour la zone à couvrir.            * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void add_ending_address_code_coverage(code_coverage *coverage, const vmpa_t *addr) +{ +    coverage->ends = (vmpa_t *)realloc(coverage->ends, ++coverage->ends_count * sizeof(vmpa_t)); +    coverage->ends[coverage->ends_count - 1] = *addr; + +    qsort(coverage->ends, coverage->ends_count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/*                           SUIVI DES FLOTS D'INSTRUCTIONS                           */ +/* ---------------------------------------------------------------------------------- */  /******************************************************************************  *                                                                             *  *  Paramètres  : info = informations à consulter.                             *  *                addr = adresse à rechercher.                                 * -*                fast = autorise une recherche rapide.                        * -*                pos  = enregistrement de la position de la trouvaille. [OUT] *  *                                                                             *  *  Description : Indique si une adresse est retenue comme point de passage.   *  *                                                                             * @@ -83,31 +265,15 @@ static GInstrBlock *build_instruction_block(GArchInstruction *, vmpa_t, vmpa_t,  *                                                                             *  ******************************************************************************/ -static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool fast, size_t *pos) +static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr)  {      bool result;                            /* Bilan à retourner           */      size_t i;                               /* Boucle de parcours          */ -    void *ptr;                              /* Résultat des recherches     */      result = false; -    if (!fast) -        for (i = 0; i < info->count && !result; i++) -        { -            result = (info->jumps[i] == *addr); -            if (result && pos != NULL) -                *pos = i; -        } - -    else -    { -        ptr = bsearch(addr, info->jumps, info->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); -        result = (ptr != NULL); - -        if (result && pos != NULL) -            *pos = (ptr - ((void *)info->jumps)) / sizeof(vmpa_t); - -    } +    for (i = 0; i < info->count && !result; i++) +        result = (info->jumps[i] == *addr);      return result; @@ -116,10 +282,10 @@ static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool  /******************************************************************************  *                                                                             * -*  Paramètres  : instrs = ensemble des instructions d'assemblage.             * -*                start  = adresse de début du bloc.                           * -*                end    = adresse de fin du bloc (exclusive).                 * -*                count  = nombre de sauts détectés. [OUT]                     * +*  Paramètres  : instrs   = ensemble des instructions d'assemblage.           * +*                start    = adresse de début du bloc.                         * +*                coverage = liste des adresses de fin butoir.                 * +*                count    = nombre de sauts détectés. [OUT]                   *  *                                                                             *  *  Description : Identifie les différents points de passage d'une branche.    *  *                                                                             * @@ -129,17 +295,17 @@ static bool is_addr_in_branch(const branch_info *info, const vmpa_t *addr, bool  *                                                                             *  ******************************************************************************/ -static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end, branch_info *info) +static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, const code_coverage *coverage, branch_info *info)  {      GArchInstruction *iter;                 /* Boucle de parcours #1       */ +    vmpa_t addr;                            /* Adresse d'une instruction   */      GArchInstruction **dests;               /* Instr. visée par une autre  */      InstructionLinkType *types;             /* Type de lien entre lignes   */      size_t dcount;                          /* Nombre de liens de dest.    */      size_t i;                               /* Boucle de parcours #2       */ -    vmpa_t addr;                            /* Adresse de la destination   */      /* On évite de boucler... */ -    if (is_addr_in_branch(info, &start, false, NULL)) +    if (is_addr_in_branch(info, &start))          return;      info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t)); @@ -148,8 +314,13 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,      /* On suit le flot jusqu'à la prochaine bifurcation */      for (iter = g_arch_instruction_find_by_address(instrs, start, true);           iter != NULL; -         iter = g_arch_instruction_get_next_iter(instrs, iter, end)) +         iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX))      { +        g_arch_instruction_get_location(iter, NULL, NULL, &addr); + +        if (code_coverage_stop_here(coverage, &addr)) +            break; +          if (g_arch_instruction_is_return(iter))          {              iter = NULL; @@ -170,7 +341,7 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,                  case ILT_JUMP_IF_TRUE:                  case ILT_JUMP_IF_FALSE:                      g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); -                    find_next_jumps(instrs, addr, end, info); +                    find_next_jumps(instrs, addr, coverage, info);                      break;                  default: @@ -183,10 +354,10 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,      }      /* Si on termine... */ -    if (iter != NULL && !is_addr_in_branch(info, &end, false, NULL)) +    if (iter != NULL && !is_addr_in_branch(info, &addr))      {          info->jumps = (vmpa_t *)realloc(info->jumps, ++(info->count) * sizeof(vmpa_t)); -        info->jumps[info->count - 1] = end; +        info->jumps[info->count - 1] = addr;      }  } @@ -213,11 +384,8 @@ static vmpa_t compute_first_common_addr(branch_info *a, branch_info *b)      /* Valeur conceptuellement impossible à renvoyer */      result = VMPA_MAX; -    //qsort(a->jumps, a->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); -    //qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); -      for (i = 0; i < a->count && result == VMPA_MAX; i++) -        if (is_addr_in_branch(b, &a->jumps[i], false, NULL)) +        if (is_addr_in_branch(b, &a->jumps[i]))              result = a->jumps[i];      return result; @@ -248,15 +416,12 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t      /* Valeur conceptuellement impossible à renvoyer */      result = VMPA_MAX; -    //qsort(a->jumps, a->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); -    //qsort(b->jumps, b->count, sizeof(vmpa_t), (__compar_fn_t)compare_vmpa); -      for (i = 0; i < list[0].count && result == VMPA_MAX; i++)      {          keep = true;          for (j = 1; j < count && keep; j++) -            keep = is_addr_in_branch(&list[j], &list[0].jumps[i], false, NULL); +            keep = is_addr_in_branch(&list[j], &list[0].jumps[i]);          if (keep)              result = list[0].jumps[i]; @@ -269,56 +434,15 @@ static vmpa_t compute_first_common_addr_in_group(const branch_info *list, size_t +/* ---------------------------------------------------------------------------------- */ +/*                             DECOUPAGE EN BLOCS DE CODE                             */ +/* ---------------------------------------------------------------------------------- */  /******************************************************************************  *                                                                             * -*  Paramètres  : list  = liste d'ensembles de jalons à parcourir.             * -*                count = taille de cette liste.                               * -*                                                                             * -*  Description : Retrouve le point de ralliement entre un groupe de branches. * -*                                                                             * -*  Retour      : Adresse commune aux branches.                                * -*                                                                             * -*  Remarques   : -                                                            * -*                                                                             * -******************************************************************************/ - -static vmpa_t avoid_cases_common_part(const branch_info *list, size_t cur, size_t count, vmpa_t max) -{ -    vmpa_t result;                          /* Adresse trouvée à retourner */ -    size_t found_pos;                       /* Plus petit tronc commun     */ -    size_t i;                               /* Boucle de parcours          */ -    size_t pos;                             /* Emplacement du cas commun   */ - -    result = max; - -    found_pos = list[cur].count; - -    for (i = 0; i < count; i++) -    { -        if (i == cur) continue; - -        if (is_addr_in_branch(&list[cur], &list[i].jumps[0], false, &pos)) -        { -            if (pos < found_pos) -                result = list[i].jumps[0]; -        } - -    } - -    return result; - -} - - - -/****************************************************************************** -*                                                                             * -*  Paramètres  : instrs = ensemble des instructions d'assemblage.             * -*                start  = adresse de début du bloc.                           * -*                end    = adresse de fin du bloc (exclusive).                 * -*                stop   = adresse d'arrêt en cas de saut ou VMPA_MAX.         * +*  Paramètres  : instrs   = ensemble des instructions d'assemblage.           * +*                coverage = délimitations de la zone à couvrir.               *  *                                                                             *  *  Description : Procède à la définition de bloc regroupant des instructions. *  *                                                                             * @@ -328,7 +452,7 @@ static vmpa_t avoid_cases_common_part(const branch_info *list, size_t cur, size_  *                                                                             *  ******************************************************************************/ -static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t start, vmpa_t end, vmpa_t stop) +static GInstrBlock *build_instruction_block(GArchInstruction *instrs, const code_coverage *coverage)  {      GInstrBlock *result;                    /* Regroupement à retourner    */      GInstrBlock *result_cached;             /* Temporisation pour unicité  */ @@ -344,13 +468,15 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta      GInstrBlock *block;                     /* Nouveau bloc mis en place   */      GInstrBlock *parent;                    /* Mémorisation pour les liens */      GInstrBlock *group;                     /* Regroupement de blocs       */ +    size_t not_handled;                     /* Quantité de liens non gérés */ +    vmpa_t next_addr;                       /* Prochaine instruction visée */      branch_info *cases_branches;            /* Branches d'un aiguillage    */      size_t cases_count;                     /* Nombre d'aiguillages        */      branch_info true_branch;                /* Branche 'condition vraie'   */      branch_info false_branch;               /* Branche 'condition fausse'  */      branch_info *excep_branches;            /* Branches d'exceptions       */      size_t excep_count;                     /* Nombre d'exceptions         */ -    vmpa_t next_addr;                       /* Prochaine instruction visée */ +    code_coverage *sub_coverage;            /* Couverture pour les suivants*/      size_t j;                               /* Boucle de parcours #2       */      vmpa_t stop_addr;                       /* Adresse de fin de bloc      */ @@ -386,16 +512,15 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta      last = NULL;      memset(&main_branch, 0, sizeof(branch_info)); -    find_next_jumps(instrs, start, end, &main_branch); +    find_next_jumps(instrs, coverage->start, coverage, &main_branch); -    //printf("[+] blocking 0x%08llx -> 0x%08llx... stop @ 0x%08llx\n", start, end, stop); - -    for (iter = g_arch_instruction_find_by_address(instrs, start, true); +    for (iter = g_arch_instruction_find_by_address(instrs, coverage->start, true);           iter != NULL;           )      {          g_arch_instruction_get_location(iter, NULL, NULL, &addr); -        if (addr == stop) break; + +        if (code_coverage_stop_here(coverage, &addr)) break;          /* On s'arrêter si l'instruction est déjà décompilée */          if (MACRO_IS_PROCESSED(iter)) break; @@ -408,7 +533,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta          /* On n'approfondit que les chemins qui se séparent */          if (!g_arch_instruction_has_destinations(iter))          { -            iter = g_arch_instruction_get_next_iter(instrs, iter, end); +            iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX);              continue;          } @@ -416,7 +541,8 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta          dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL); -        next_addr = 0; +        not_handled = 0; +        next_addr = VMPA_MAX;          cases_branches = NULL;          cases_count = 0;          memset(&true_branch, 0, sizeof(branch_info)); @@ -447,18 +573,18 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta                      cases_branches = (branch_info *)realloc(cases_branches,                                                              ++cases_count * sizeof(branch_info));                      memset(&cases_branches[cases_count - 1], 0, sizeof(branch_info)); -                    find_next_jumps(instrs, addr, end, &cases_branches[cases_count - 1]); +                    find_next_jumps(instrs, addr, coverage, &cases_branches[cases_count - 1]);                      break;                  case ILT_JUMP_IF_TRUE:                      g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); -                    find_next_jumps(instrs, addr, end, &true_branch); +                    find_next_jumps(instrs, addr, coverage, &true_branch);                      break;                  case ILT_JUMP_IF_FALSE:                      g_arch_instruction_get_location(dests[i], NULL, NULL, &addr); -                    find_next_jumps(instrs, addr, end, &false_branch); +                    find_next_jumps(instrs, addr, coverage, &false_branch);                      break;                  case ILT_CATCH_EXCEPTION: @@ -468,13 +594,16 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta                      excep_branches = (branch_info *)realloc(excep_branches,                                                              ++excep_count * sizeof(branch_info));                      memset(&excep_branches[excep_count - 1], 0, sizeof(branch_info)); -                    find_next_jumps(instrs, addr, end, &excep_branches[excep_count - 1]); +                    find_next_jumps(instrs, addr, coverage, &excep_branches[excep_count - 1]); -                    break; +                    /** +                     * Les deux cas sont les seuls à ne pas conduire à une définition de +                     * next_addr, donc on les comptabilise sur un pied d'égalité ! +                     */ +                    //break;                  default: -                    if (next_addr == 0) -                        next_addr = VMPA_MAX; +                    not_handled++;                      break;              } @@ -493,52 +622,30 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              DELAYED_BLOCK_ADDING(result, result_cached, block); -            printf(" --- cases --- start\n"); -              next_addr = compute_first_common_addr_in_group(cases_branches, cases_count); -            printf("    stop :: 0x%08llx\n", next_addr);              parent = block;              group = g_virtual_block_new(); -            do +            for (i = 0; i < cases_count; i++)              { -                size_t _i, _j; - -                for (_i = 0; _i < cases_count; _i++) -                { -                    printf("  [case %d] : ", _i); +                sub_coverage = dup_code_coverage(cases_branches[i].jumps[0], coverage); -                    for (_j = 0; _j < cases_branches[_i].count; _j++) -                        printf("0x%08lx ", cases_branches[_i].jumps[_j]); +                add_ending_address_code_coverage(sub_coverage, &next_addr); -                    printf("\n"); +                for (j = 0; j < cases_count; j++) +                    if (cases_branches[j].jumps[0] != cases_branches[i].jumps[0]) +                        add_ending_address_code_coverage(sub_coverage, &cases_branches[j].jumps[0]); -                } +                block = build_instruction_block(instrs, sub_coverage); -            } while (0); - - -            for (j = 0; j < cases_count; j++) -            { -                printf(" ## %zu start=0x%08lx (0x%08lx)...\n", j, cases_branches[j].jumps[0], -                       next_addr); - -                //block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, next_addr); - -                //next_addr = avoid_cases_common_part(cases_branches, j, cases_count, next_addr); - -                block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, -                                                avoid_cases_common_part(cases_branches, j, cases_count, next_addr)); - -                printf(" %p (0x%08lx)\n", block, -                       avoid_cases_common_part(cases_branches, j, cases_count, next_addr)); +                delete_code_coverage(sub_coverage);                  if (block != NULL)                  g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); -                free(cases_branches[j].jumps); +                free(cases_branches[i].jumps);              } @@ -550,23 +657,13 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              else                  g_object_unref(G_OBJECT(group)); -            printf(" --- cases --- end\n"); - -              free(cases_branches);          } -        if (next_addr == VMPA_MAX) -        { -            iter = g_arch_instruction_get_next_iter(instrs, iter, end); -            continue; -        } -          else if (true_branch.count > 0 || false_branch.count > 0)          {              next_addr = compute_first_common_addr(&true_branch, &false_branch); -            next_addr = MIN(next_addr, end);              /**               * On doit clôturer le bloc renvoyant vers les branches 'true' et 'false' ici. @@ -582,14 +679,32 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              parent = block;              group = g_virtual_block_new(); -            block = build_instruction_block(instrs, true_branch.jumps[0], end, next_addr); +            /* Branche 'true' */ + +            sub_coverage = dup_code_coverage(true_branch.jumps[0], coverage); +            add_ending_address_code_coverage(sub_coverage, &next_addr); +            add_ending_address_code_coverage(sub_coverage, &false_branch.jumps[0]); + +            block = build_instruction_block(instrs, sub_coverage);              if (block != NULL)                  g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); -            block = build_instruction_block(instrs, false_branch.jumps[0], end, next_addr); +            delete_code_coverage(sub_coverage); + +            /* Branche 'false' */ + +            sub_coverage = dup_code_coverage(false_branch.jumps[0], coverage); +            add_ending_address_code_coverage(sub_coverage, &next_addr); +            add_ending_address_code_coverage(sub_coverage, &true_branch.jumps[0]); + +            block = build_instruction_block(instrs, sub_coverage);              if (block != NULL)                  g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); +            delete_code_coverage(sub_coverage); + +            /* Conclusion */ +              if (g_virtual_block_count_children(G_VIRTUAL_BLOCK(group)) > 0)              {                  DELAYED_BLOCK_ADDING(result, result_cached, group); @@ -601,8 +716,6 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              free(true_branch.jumps);              free(false_branch.jumps); -            if (next_addr == end) break; -          }          /* Post-traitements de ILT_CATCH_EXCEPTION */ @@ -621,9 +734,13 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              for (j = 0; j < excep_count; j++)              {                  stop_addr = compute_first_common_addr(&main_branch, &excep_branches[j]); -                //next_addr = MIN(next_addr, end); -                block = build_instruction_block(instrs, excep_branches[j].jumps[0], end, stop_addr); +                sub_coverage = dup_code_coverage(excep_branches[j].jumps[0], coverage); +                add_ending_address_code_coverage(sub_coverage, &stop_addr); + +                block = build_instruction_block(instrs, sub_coverage); + +                delete_code_coverage(sub_coverage);                  if (block != NULL) @@ -638,7 +755,11 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta          }          /* Détermination du prochain point de chute */ -        iter = g_arch_instruction_find_by_address(instrs, next_addr, true); + +        if (not_handled == dcount) +            iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX); +        else +            iter = g_arch_instruction_find_by_address(instrs, next_addr, true);      } @@ -646,10 +767,8 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta      {          if (!MACRO_IS_PROCESSED(first))          { -            //printf("--close?--\n");              block = g_flow_block_new(instrs, first, last);              MACRO_MARK_AS_PROCESSED(first); -            //printf("--close!--\n");              DELAYED_BLOCK_ADDING(result, result_cached, block); @@ -657,12 +776,6 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta      } -    if ((result != NULL ? result : result_cached) == NULL) -    { -        //printf("WARNING :: null !\n"); -        //exit(0); -    } -      return (result != NULL ? result : result_cached);  } @@ -689,6 +802,7 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines,      size_t i;                               /* Boucle de parcours          */      vmpa_t start;                           /* Adresse de départ           */      vmpa_t end;                             /* Adresse de fin              */ +    code_coverage *coverage;                /* Couverture de zone de code  */      GInstrBlock *block;                     /* Regroupement d'instructions */      for (i = 0; i < count; i++) @@ -696,9 +810,13 @@ void group_routines_instructions(GArchInstruction *list, GBinRoutine **routines,          start = g_binary_routine_get_address(routines[i]);          end = start + g_binary_routine_get_size(routines[i]); -        block = build_instruction_block(list, start, end, VMPA_MAX); +        coverage = create_code_coverage(start, end); + +        block = build_instruction_block(list, coverage);          g_binary_routine_set_basic_blocks(routines[i], block); +        delete_code_coverage(coverage); +          gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count);      } | 
