diff options
| author | Cyrille Bagard <nocbos@gmail.com> | 2013-01-31 21:29:49 (GMT) | 
|---|---|---|
| committer | Cyrille Bagard <nocbos@gmail.com> | 2013-01-31 21:29:49 (GMT) | 
| commit | 0936f64aac6a4fa9ebc08962bc9cac663f210c00 (patch) | |
| tree | e888b4d7b547680bb26082913216bc637073e734 /src/analysis | |
| parent | b6341581220e92114b0838a15a1c1cec1078efc2 (diff) | |
Saved the first steps of switch instructions decompilation.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@335 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis')
| -rw-r--r-- | src/analysis/blocks/flow.c | 2 | ||||
| -rw-r--r-- | src/analysis/decomp/il.c | 51 | ||||
| -rw-r--r-- | src/analysis/disass/macro.c | 14 | 
3 files changed, 58 insertions, 9 deletions
| diff --git a/src/analysis/blocks/flow.c b/src/analysis/blocks/flow.c index 49b9c6b..4df729c 100644 --- a/src/analysis/blocks/flow.c +++ b/src/analysis/blocks/flow.c @@ -510,7 +510,7 @@ bool g_flow_block_follow(GFlowBlock *block, const GInstrBlock *list, BlockFollow      if (mask & BFP_ENTER)          result = callback(block, BFP_ENTER, data); -    dcount = g_arch_instruction_get_destinations(block->last, &dests, &types); +    dcount = g_arch_instruction_get_destinations(block->last, &dests, &types, NULL);      for (i = 0; i < dcount && result; i++)          switch (types[i]) diff --git a/src/analysis/decomp/il.c b/src/analysis/decomp/il.c index 64f6398..f241e46 100644 --- a/src/analysis/decomp/il.c +++ b/src/analysis/decomp/il.c @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * il.h - mise en place d'un langage intermédiaire   * - * Copyright (C) 2012 Cyrille Bagard + * Copyright (C) 2012-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -27,7 +27,9 @@  #include "../blocks/flow.h"  #include "../blocks/virtual.h"  #include "../../decomp/expr/block.h" +#include "../../decomp/expr/immediate.h"  #include "../../decomp/instr/ite.h" +#include "../../decomp/instr/switch.h" @@ -328,7 +330,7 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon      GArchInstruction *first;                /* Première instruction du lot */      GArchInstruction *last;                 /* Dernière instruction du lot */      vmpa_t max;                             /* Adresse de fin du bloc      */ -    GArchInstruction *iter;                 /* Boucle de parcours          */ +    GArchInstruction *iter;                 /* Boucle de parcours #1       */      GDecInstruction *decomp;                /* Dernier résultat de décomp. */      GInstrBlock *sub_parent;                /* Groupe des sous-branches    */      GHashTable *sub_shared;                 /* Allocations communes        */ @@ -338,6 +340,12 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon      GArchInstruction *next;                 /* Instruction de branchement  */      vmpa_t next_addr;                       /* Adresse de cette instruct°  */      GInstrBlock *next_block;                /* Sous-bloc basique direct    */ +    GArchInstruction **dests;               /* Instr. visée par une autre  */ +    link_extra_info *info;                  /* Compléments pour les liens  */ +    size_t dcount;                          /* Nombre de liens de dest.    */ +    size_t i;                               /* Boucle de parcours #2       */ +    GDecInstruction *case_dinstr;           /* Décompilation 'case'        */ +    GDecExpression *case_value;             /* Valeur d'aiguillage         */      instrs = g_flow_block_get_all_instructions_list(block);      g_flow_block_get_boundary(block, &first, &last); @@ -406,6 +414,45 @@ static GDecInstruction *decompiled_instructions_block(GFlowBlock *block, GDecCon      } +    /* switch ... case ... */ +    else if (G_IS_SWITCH_INSTRUCTION(decomp)) +    { +        sub_parent = g_instr_block_get_links_block(G_INSTR_BLOCK(block)); +        sub_shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash, +                                           (GEqualFunc)g_arch_register_equal, +                                           g_object_unref, g_object_unref); + +        dcount = g_arch_instruction_get_destinations(last, &dests, NULL, &info); + +        for (i = 0; i < dcount; i++) +        { +            g_arch_instruction_get_location(dests[i], NULL, NULL, &next_addr); +            next_block = g_instr_block_find_by_addr(sub_parent, next_addr, false); + +            if (next_block != NULL) +            { +                sub_ctx = create_new_context_for_sub_block(ctx, next_block, sub_shared); +                case_dinstr = decompiled_basic_block(next_block, sub_ctx); +                g_dec_context_spread_allocated_shared_regs(ctx, sub_ctx); +                g_object_unref(G_OBJECT(sub_ctx)); + +                if (info[i].imm != NULL) +                { +                    case_value = G_DEC_EXPRESSION(g_imm_expression_new(info[i].imm)); +                    g_switch_instruction_add_case(G_SWITCH_INSTRUCTION(decomp), +                                                  case_value, case_dinstr, next_addr); +                } +                else g_switch_instruction_set_default_case(G_SWITCH_INSTRUCTION(decomp), +                                                           case_dinstr); + +            } + +        } + +        g_hash_table_unref(sub_shared); + +    } +      /* Renvoi des instructions mises en place */      return g_dec_context_get_decomp_instrs(ctx); diff --git a/src/analysis/disass/macro.c b/src/analysis/disass/macro.c index 0fef9a0..14dad95 100644 --- a/src/analysis/disass/macro.c +++ b/src/analysis/disass/macro.c @@ -150,7 +150,7 @@ static void find_next_jumps(GArchInstruction *instrs, vmpa_t start, vmpa_t end,          if (!g_arch_instruction_has_destinations(iter))              continue; -        dcount = g_arch_instruction_get_destinations(iter, &dests, &types); +        dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL);          for (i = 0; i < dcount; i++)              switch (types[i]) @@ -360,7 +360,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta          /* Adaptations en fonction du type de bifurcation */ -        dcount = g_arch_instruction_get_destinations(iter, &dests, &types); +        dcount = g_arch_instruction_get_destinations(iter, &dests, &types, NULL);          next_addr = 0;          cases_branches = NULL; @@ -439,20 +439,22 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              DELAYED_BLOCK_ADDING(result, result_cached, block); -            //printf(" --- cases --- start\n"); +            printf(" --- cases --- start\n");              next_addr = compute_first_common_addr_in_group(cases_branches, cases_count); -            //printf("    stop :: 0x%08llx\n", next_addr); +            printf("    stop :: 0x%08llx\n", next_addr);              parent = block;              group = g_virtual_block_new();              for (j = 0; j < cases_count; j++)              { -                //printf(" ## %zu\n", j); +                printf(" ## %zu...", j);                  block = build_instruction_block(instrs, cases_branches[j].jumps[0], end, next_addr); +                printf(" %p\n", block); +                  if (block != NULL)                  g_virtual_block_add_child(G_VIRTUAL_BLOCK(group), block); @@ -469,7 +471,7 @@ static GInstrBlock *build_instruction_block(GArchInstruction *instrs, vmpa_t sta              else                  g_object_unref(G_OBJECT(group)); -            //printf(" --- cases --- end\n"); +            printf(" --- cases --- end\n");              free(cases_branches); | 
