diff options
| -rw-r--r-- | ChangeLog | 50 | ||||
| -rw-r--r-- | plugins/androhelpers/switch.c | 16 | ||||
| -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 | ||||
| -rw-r--r-- | src/arch/dalvik/decomp/Makefile.am | 1 | ||||
| -rw-r--r-- | src/arch/dalvik/decomp/if.c | 8 | ||||
| -rw-r--r-- | src/arch/dalvik/decomp/switch.c | 62 | ||||
| -rw-r--r-- | src/arch/dalvik/decomp/translate.h | 7 | ||||
| -rw-r--r-- | src/arch/dalvik/instruction.c | 4 | ||||
| -rw-r--r-- | src/arch/dalvik/opcodes/switch.c | 2 | ||||
| -rw-r--r-- | src/arch/instruction-int.h | 1 | ||||
| -rw-r--r-- | src/arch/instruction.c | 32 | ||||
| -rw-r--r-- | src/arch/instruction.h | 48 | ||||
| -rw-r--r-- | src/decomp/expr/immediate.c | 2 | ||||
| -rw-r--r-- | src/decomp/instr/Makefile.am | 3 | ||||
| -rw-r--r-- | src/decomp/instr/ite.c | 46 | ||||
| -rw-r--r-- | src/decomp/instr/ite.h | 16 | ||||
| -rw-r--r-- | src/decomp/instr/switch.c | 379 | ||||
| -rw-r--r-- | src/decomp/instr/switch.h | 66 | ||||
| -rw-r--r-- | src/gtkext/graph/layout.c | 2 | 
21 files changed, 733 insertions, 79 deletions
| @@ -1,3 +1,53 @@ +13-01-31  Cyrille Bagard <nocbos@gmail.com> + +	* plugins/androhelpers/switch.c: +	Store the case value with the link of each switch case. + +	* src/analysis/blocks/flow.c: +	Update code. + +	* src/analysis/decomp/il.c: +	Save the first steps of switch instructions decompilation. + +	* src/analysis/disass/macro.c: +	Update code. + +	* src/arch/dalvik/decomp/if.c: +	Typo. + +	* src/arch/dalvik/decomp/Makefile.am: +	Add the 'switch.[ch]' files to libarchdalvikdecomp_la_SOURCES. + +	* src/arch/dalvik/decomp/switch.c: +	* src/arch/dalvik/decomp/translate.h: +	* src/arch/dalvik/instruction.c: +	Decompile Dalvik switch instructions. + +	* src/arch/dalvik/opcodes/switch.c: +	Typo. + +	* src/arch/instruction.c: +	* src/arch/instruction.h: +	* src/arch/instruction-int.h: +	Store extra information with links between instructions. + +	* src/decomp/expr/immediate.c: +	Add a note for later. + +	* src/decomp/instr/ite.c: +	* src/decomp/instr/ite.h: +	Typo. + +	* src/decomp/instr/Makefile.am: +	Add the 'switch.[ch]' files to libdecompinstr_la_SOURCES. + +	* src/decomp/instr/switch.c: +	* src/decomp/instr/switch.h: +	New entries: decompile switch instructions. + +	* src/gtkext/graph/layout.c: +	Update code. +  13-01-28  Cyrille Bagard <nocbos@gmail.com>  	* src/gui/panels/glance.c: diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c index 9e6f306..0a1e488 100644 --- a/plugins/androhelpers/switch.c +++ b/plugins/androhelpers/switch.c @@ -27,6 +27,7 @@  #include <string.h> +#include <arch/immediate.h>  #include <arch/dalvik/instruction.h>  #include <arch/dalvik/instruction-def.h>  #include <arch/dalvik/operands/target.h> @@ -139,6 +140,8 @@ static void link_all_switch_cases(GArchInstruction *instr, const dex_switch *dsw      uint32_t *targets;                      /* Cibles relatives à corriger */      uint16_t i;                             /* Boucle de parcours          */      GArchInstruction *next;                 /* Instruction suivante        */ +    uint32_t value;                         /* Valeur à indiquer           */ +    GArchOperand *imm;                      /* Forme de la valeur reconnue */      /* Valeurs définies */ @@ -155,7 +158,16 @@ static void link_all_switch_cases(GArchInstruction *instr, const dex_switch *dsw          next = g_arch_instruction_find_by_address(instrs, (vmpa_t)targets[i], true);          if (next != NULL) -            g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP); +        { +            if (dswitch->packed.ident == DPO_PACKED_SWITCH) +                value = dswitch->packed.first_key + i; +            else +                value = dswitch->sparse.keys[i]; + +            imm = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, value); +            g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP, imm); + +        }      } @@ -164,7 +176,7 @@ static void link_all_switch_cases(GArchInstruction *instr, const dex_switch *dsw      next = g_arch_instruction_get_next_iter(instrs, instr, end);      if (next != NULL) -        g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP); +        g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP, NULL);  } 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); diff --git a/src/arch/dalvik/decomp/Makefile.am b/src/arch/dalvik/decomp/Makefile.am index 7a7f068..3a0a197 100644 --- a/src/arch/dalvik/decomp/Makefile.am +++ b/src/arch/dalvik/decomp/Makefile.am @@ -14,6 +14,7 @@ libarchdalvikdecomp_la_SOURCES =		\  	move.c								\  	new.c								\  	ret.c								\ +	switch.h switch.c					\  	translate.h  libarchdalvikdecomp_la_LIBADD = diff --git a/src/arch/dalvik/decomp/if.c b/src/arch/dalvik/decomp/if.c index 6a156ec..93e21d9 100644 --- a/src/arch/dalvik/decomp/if.c +++ b/src/arch/dalvik/decomp/if.c @@ -1,8 +1,8 @@  /* OpenIDA - Outil d'analyse de fichiers binaires - * array.c - décompilation des branchements conditionnels + * if.c - décompilation des branchements conditionnels   * - * Copyright (C) 2010-2012 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -35,7 +35,7 @@  *  Paramètres  : instr = instruction d'origine à convertir.                   *  *                ctx   = contexte de la phase de décompilation.               *  *                                                                             * -*  Description : Décompile une instruction de comparaison d'opérandes.        * +*  Description : Décompile une instruction de branchement conditionnel.       *  *                                                                             *  *  Retour      : Instruction mise en place ou NULL.                           *  *                                                                             * @@ -104,7 +104,7 @@ GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *instr, GDecConte  *  Paramètres  : instr = instruction d'origine à convertir.                   *  *                ctx   = contexte de la phase de décompilation.               *  *                                                                             * -*  Description : Décompile une instruction de comparaison d'opérandes.        * +*  Description : Décompile une instruction de branchement conditionnel.       *  *                                                                             *  *  Retour      : Instruction mise en place ou NULL.                           *  *                                                                             * diff --git a/src/arch/dalvik/decomp/switch.c b/src/arch/dalvik/decomp/switch.c new file mode 100644 index 0000000..83da613 --- /dev/null +++ b/src/arch/dalvik/decomp/switch.c @@ -0,0 +1,62 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * switch.c - décompilation des aiguillages multiples du flot d'exécution + * + * Copyright (C) 2013 Cyrille Bagard + * + *  This file is part of OpenIDA. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "translate.h" + + + +#include "../instruction.h" +#include "../../../decomp/instr/switch.h" + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr = instruction d'origine à convertir.                   * +*                ctx   = contexte de la phase de décompilation.               * +*                                                                             * +*  Description : Décompile une instruction d'aiguillages multiples du flux.   * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL.                           * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GDecInstruction *dalvik_decomp_instr_switch(const GArchInstruction *instr, GDecContext *ctx) +{ +    GDecInstruction *result;                /* Instruction à retourner     */ +    vmpa_t addr;                            /* Adresse de l'instruction    */ +    GArchOperand *operand;                  /* Opérande de l'instruction   */ +    GDecInstruction *val;                   /* Valeur décidant du flot     */ + +    g_arch_instruction_get_location(instr, NULL, NULL, &addr); + +    operand = g_arch_instruction_get_operand(instr, 0); +    val = g_dec_context_convert_register(ctx, operand, false, addr); + +    result = g_switch_instruction_new(G_DEC_EXPRESSION(val)); + +    return result; + +} diff --git a/src/arch/dalvik/decomp/translate.h b/src/arch/dalvik/decomp/translate.h index b8753db..1c9f19c 100644 --- a/src/arch/dalvik/decomp/translate.h +++ b/src/arch/dalvik/decomp/translate.h @@ -87,12 +87,15 @@ GDecInstruction *dalvik_decomp_instr_arithm_2addr(const GArchInstruction *, GDec  /* Décompile une instruction de type 'opérations arithmétiques'. */  GDecInstruction *dalvik_decomp_instr_arithm_lit(const GArchInstruction *, GDecContext *); -/* Décompile une instruction de comparaison d'opérandes. */ +/* Décompile une instruction de branchement conditionnel. */  GDecInstruction *dalvik_decomp_instr_if(const GArchInstruction *, GDecContext *); -/* Décompile une instruction de comparaison d'opérandes. */ +/* Décompile une instruction de branchement conditionnel. */  GDecInstruction *dalvik_decomp_instr_if_zero(const GArchInstruction *, GDecContext *); +/* Décompile une instruction d'aiguillages multiples du flux. */ +GDecInstruction *dalvik_decomp_instr_switch(const GArchInstruction *, GDecContext *); +  #endif  /* _ANALYSIS_DECOMP_RTL_DALVIK_TRANSLATE_H */ diff --git a/src/arch/dalvik/instruction.c b/src/arch/dalvik/instruction.c index 20982b7..81b8993 100644 --- a/src/arch/dalvik/instruction.c +++ b/src/arch/dalvik/instruction.c @@ -104,8 +104,8 @@ static dalvik_instruction _instructions[DOP_COUNT] = {      [DOP_GOTO]                  = { 0x28, "goto" },      [DOP_GOTO_16]               = { 0x29, "goto/16" },      [DOP_GOTO_32]               = { 0x2a, "goto/32" }, -    [DOP_PACKED_SWITCH]         = { 0x2b, "packed-switch" }, -    [DOP_SPARSE_SWITCH]         = { 0x2c, "sparse-switch" }, +    [DOP_PACKED_SWITCH]         = { 0x2b, "packed-switch",      dalvik_decomp_instr_switch }, +    [DOP_SPARSE_SWITCH]         = { 0x2c, "sparse-switch",      dalvik_decomp_instr_switch },      [DOP_CMPL_FLOAT]            = { 0x2d, "cmp-long" },      [DOP_CMPG_FLOAT]            = { 0x2e, "cmpg-float" },      [DOP_CMPL_DOUBLE]           = { 0x2f, "cmpl-double" }, diff --git a/src/arch/dalvik/opcodes/switch.c b/src/arch/dalvik/opcodes/switch.c index 0feef9a..48576e9 100644 --- a/src/arch/dalvik/opcodes/switch.c +++ b/src/arch/dalvik/opcodes/switch.c @@ -1,6 +1,6 @@  /* OpenIDA - Outil d'analyse de fichiers binaires - * array.c - décodage de l'opération récupérant la longueur d'un tableau + * switch.c - décompilation des branchements multiples   *   * Copyright (C) 2012 Cyrille Bagard   * diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index 25d65e5..d7da215 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -67,6 +67,7 @@ struct _GArchInstruction      size_t from_count;                      /* Nombre de ces origines      */      GArchInstruction **to;                  /* Eventuelles lignes visées   */      InstructionLinkType *links_type;        /* Type des liens de dest.     */ +    link_extra_info *links_info;            /* Informations complémentaires*/      size_t to_count;                        /* Nombre de ces destinations  */      get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés    */ diff --git a/src/arch/instruction.c b/src/arch/instruction.c index 06d3e71..20b5f3a 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -2,7 +2,7 @@  /* OpenIDA - Outil d'analyse de fichiers binaires   * instruction.c - gestion générique des instructions   * - * Copyright (C) 2008-2012 Cyrille Bagard + * Copyright (C) 2008-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -24,6 +24,7 @@  #include "instruction.h" +#include <stdarg.h>  #include <string.h> @@ -350,6 +351,7 @@ bool g_arch_instruction_is_return(const GArchInstruction *instr)  *  Paramètres  : instr = instruction dont les informations sont à consulter.  *  *                dest  = ligne visée par la liaison (côté destination).       *  *                type  = type de lien à construire.                           * +*                ...   = éventuelles informations complémentaires.            *  *                                                                             *  *  Description : Etablit un lien entre deux instructions.                     *  *                                                                             * @@ -359,8 +361,10 @@ bool g_arch_instruction_is_return(const GArchInstruction *instr)  *                                                                             *  ******************************************************************************/ -void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type) +void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type, ...)  { +    va_list ap;                             /* Gestion des variations      */ +      /* Côté destination */      dest->from = (GArchInstruction **)realloc(dest->from, @@ -376,10 +380,24 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des                                               instr->to_count * sizeof(GArchInstruction *));      instr->links_type = (InstructionLinkType *)realloc(instr->links_type,                                                         instr->to_count * sizeof(InstructionLinkType)); +    instr->links_info = (link_extra_info *)realloc(instr->links_info, +                                                   instr->to_count * sizeof(link_extra_info));      instr->to[instr->to_count - 1] = dest;      instr->links_type[instr->to_count - 1] = type; +    va_start(ap, type); + +    switch (type) +    { +        case ILT_CASE_JUMP: +            instr->links_info[instr->to_count - 1].imm = va_arg(ap, GImmOperand *); +            break; +        default: +            break; +    } + +    va_end(ap);  } @@ -429,6 +447,7 @@ bool g_arch_instruction_has_destinations(const GArchInstruction *instr)  *  Paramètres  : instr = instruction dont les informations sont à consulter.  *  *                dests = liste des instructions de destination. [OUT]         *  *                types = liste des types de liens présents. [OUT]             * +*                info  = éventuelles informations complémentaires. [OUT]      *  *                                                                             *  *  Description : Fournit les destinations d'une instruction donnée.           *  *                                                                             * @@ -438,10 +457,15 @@ bool g_arch_instruction_has_destinations(const GArchInstruction *instr)  *                                                                             *  ******************************************************************************/ -size_t g_arch_instruction_get_destinations(const GArchInstruction *instr, GArchInstruction ***dests, InstructionLinkType **types) +size_t g_arch_instruction_get_destinations(const GArchInstruction *instr, GArchInstruction ***dests, InstructionLinkType **types, link_extra_info **info)  {      *dests = instr->to; -    *types = instr->links_type; + +    if (types != NULL) +        *types = instr->links_type; + +    if (info != NULL) +        *info = instr->links_info;      return instr->to_count; diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 051ce51..ae53dbb 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -25,35 +25,18 @@  #define _ARCH_INSTRUCTION_H -#include <stdbool.h> -#include <glib-object.h>  #include <sys/types.h> -#include "archbase.h" -#include "operand.h" +#include "immediate.h"  #include "register.h" +#include "../analysis/type.h"  #include "../decomp/context.h"  #include "../decomp/instruction.h"  #include "../format/executable.h" -/* Typage des instructions rencontrées */ -typedef enum _InstructionLinkType -{ -    ILT_NONE,                               /* Aucune instruction visée    */ -    ILT_EXEC_FLOW,                          /* Raccord attendu entre blocs */ -    ILT_JUMP,                               /* Saut inconditionnel         */ -    ILT_CASE_JUMP,                          /* Saut suite à aiguillage     */ -    ILT_JUMP_IF_TRUE,                       /* Saut conditionnel (si vrai) */ -    ILT_JUMP_IF_FALSE,                      /* Saut conditionnel (si faux) */ -    ILT_CALL,                               /* Appel d'une fonction        */ -    ILT_CATCH_EXCEPTION                     /* Gestion d'une exception     */ - -} InstructionLinkType; - -  #define G_TYPE_ARCH_INSTRUCTION                 g_arch_instruction_get_type()  #define G_ARCH_INSTRUCTION(obj)                 (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_instruction_get_type(), GArchInstruction))  #define G_IS_ARCH_INSTRUCTION(obj)              (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_instruction_get_type())) @@ -99,6 +82,29 @@ void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister  /* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */ +/* Typage des instructions rencontrées */ +typedef enum _InstructionLinkType +{ +    ILT_NONE,                               /* Aucune instruction visée    */ +    ILT_EXEC_FLOW,                          /* Raccord attendu entre blocs */ +    ILT_JUMP,                               /* Saut inconditionnel         */ +    ILT_CASE_JUMP,                          /* Saut suite à aiguillage     */ +    ILT_JUMP_IF_TRUE,                       /* Saut conditionnel (si vrai) */ +    ILT_JUMP_IF_FALSE,                      /* Saut conditionnel (si faux) */ +    ILT_CALL,                               /* Appel d'une fonction        */ +    ILT_CATCH_EXCEPTION                     /* Gestion d'une exception     */ + +} InstructionLinkType; + +/* Informations complémentaires pour un lien */ +typedef union _link_extra_info +{ +    GImmOperand *imm;                       /* Valeur d'un cas de switch() */ +    GDataType *type;                        /* Type d'une exception        */ + +} link_extra_info; + +  /* Informe sur une éventuelle référence à une autre instruction. */  InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *, vmpa_t *); @@ -106,7 +112,7 @@ InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *, vmpa_t  bool g_arch_instruction_is_return(const GArchInstruction *instr);  /* Etablit un lien entre deux instructions. */ -void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType); +void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType, ...);  /* Indique si l'instruction a une ou plusieurs origines. */  bool g_arch_instruction_has_sources(const GArchInstruction *); @@ -115,7 +121,7 @@ bool g_arch_instruction_has_sources(const GArchInstruction *);  bool g_arch_instruction_has_destinations(const GArchInstruction *);  /* Fournit les destinations d'une instruction donnée. */ -size_t g_arch_instruction_get_destinations(const GArchInstruction *, GArchInstruction ***, InstructionLinkType **); +size_t g_arch_instruction_get_destinations(const GArchInstruction *, GArchInstruction ***, InstructionLinkType **, link_extra_info **);  /* Fournit la destination d'une instruction et d'un type donné. */  GArchInstruction *g_arch_instruction_get_given_destination(const GArchInstruction *, InstructionLinkType); diff --git a/src/decomp/expr/immediate.c b/src/decomp/expr/immediate.c index 18af422..e0c6bd6 100644 --- a/src/decomp/expr/immediate.c +++ b/src/decomp/expr/immediate.c @@ -122,7 +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)); +    g_object_ref(G_OBJECT(operand));    /* FIXME : ref pas déjà acquise ? */      return G_DEC_INSTRUCTION(result); diff --git a/src/decomp/instr/Makefile.am b/src/decomp/instr/Makefile.am index b4e16eb..6120cac 100644 --- a/src/decomp/instr/Makefile.am +++ b/src/decomp/instr/Makefile.am @@ -2,7 +2,8 @@  noinst_LTLIBRARIES = libdecompinstr.la  libdecompinstr_la_SOURCES =				\ -	ite.h ite.c +	ite.h ite.c							\ +	switch.h switch.c  libdecompinstr_la_LDFLAGS =  diff --git a/src/decomp/instr/ite.c b/src/decomp/instr/ite.c index d78bb31..60627a6 100644 --- a/src/decomp/instr/ite.c +++ b/src/decomp/instr/ite.c @@ -1,8 +1,8 @@  /* OpenIDA - Outil d'analyse de fichiers binaires - * cond.c - représentation des conditions + * ite.c - représentation des branchements conditionnels   * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -107,7 +107,7 @@ static void g_ite_instruction_class_init(GITEInstructionClass *klass)  /******************************************************************************  *                                                                             * -*  Paramètres  : expr = instance à initialiser.                               * +*  Paramètres  : instr = instance à initialiser.                              *  *                                                                             *  *  Description : Initialise une instance d'aiguillage du flux d'exécution.    *  *                                                                             * @@ -117,15 +117,15 @@ static void g_ite_instruction_class_init(GITEInstructionClass *klass)  *                                                                             *  ******************************************************************************/ -static void g_ite_instruction_init(GITEInstruction *expr) +static void g_ite_instruction_init(GITEInstruction *instr)  { -    GDecInstruction *instr;                 /* Autre version de l'objet    */ +    GDecInstruction *base;                  /* Autre version de l'objet    */ -    instr = G_DEC_INSTRUCTION(expr); +    base = G_DEC_INSTRUCTION(instr); -    instr->visit = (dec_instr_visit_fc)g_ite_instruction_visit; -    instr->replace = (dec_instr_replace_fc)g_ite_instruction_replace; -    instr->print = (dec_instr_print_fc)g_ite_instruction_print; +    base->visit = (dec_instr_visit_fc)g_ite_instruction_visit; +    base->replace = (dec_instr_replace_fc)g_ite_instruction_replace; +    base->print = (dec_instr_print_fc)g_ite_instruction_print;  } @@ -226,7 +226,7 @@ static bool g_ite_instruction_replace(GITEInstruction *instr, GDecInstruction *o  /******************************************************************************  *                                                                             * -*  Paramètres  : expr   = instruction à transcrire en version humaine.        * +*  Paramètres  : instr  = instruction à transcrire en version humaine.        *  *                buffer = tampon où doit se réaliser l'insertion.             *  *                line   = ligne d'impression prête à emploi ou NULL.          *  *                output = langage de programmation de sortie.                 * @@ -239,24 +239,24 @@ static bool g_ite_instruction_replace(GITEInstruction *instr, GDecInstruction *o  *                                                                             *  ******************************************************************************/ -static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +static GBufferLine *g_ite_instruction_print(const GITEInstruction *instr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output)  {      GBufferLine *result;                    /* Ligne à retourner           */      g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "if ", 3, RTT_KEY_WORD); -    if (expr->inverse) +    if (instr->inverse)          g_buffer_line_insert_text(line /* FIXME */, BLC_ASSEMBLY_HEAD, "!", 1, RTT_KEY_WORD); -    result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->cond), +    result = g_dec_instruction_print(G_DEC_INSTRUCTION(instr->cond),                                       buffer, line, output); -    result = g_dec_instruction_print(expr->true_branch, buffer, result, output); +    result = g_dec_instruction_print(instr->true_branch, buffer, result, output); -    if (expr->false_branch != NULL) +    if (instr->false_branch != NULL)      {          g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "else", 4, RTT_KEY_WORD); -        result = g_dec_instruction_print(expr->false_branch, buffer, result, output); +        result = g_dec_instruction_print(instr->false_branch, buffer, result, output);      }      return result; @@ -266,7 +266,7 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBu  /******************************************************************************  *                                                                             * -*  Paramètres  : cond         = expression fixant le choix de l'aiguillage.   * +*  Paramètres  : instr        = expression fixant le choix de l'aiguillage.   *  *                true_branch  = instructions si la condition est vérifiée.    *  *                false_branch = instructions si la cond. n'est pas vérifiée.  *  *                                                                             * @@ -278,21 +278,21 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBu  *                                                                             *  ******************************************************************************/ -void g_ite_instruction_set_branches(GITEInstruction *expr, GDecInstruction *true_branch, GDecInstruction *false_branch) +void g_ite_instruction_set_branches(GITEInstruction *instr, GDecInstruction *true_branch, GDecInstruction *false_branch)  {      if (true_branch == NULL)      { -        expr->inverse = true; +        instr->inverse = true; -        expr->true_branch = false_branch; -        expr->false_branch = true_branch; +        instr->true_branch = false_branch; +        instr->false_branch = true_branch;      }      else      { -        expr->true_branch = true_branch; -        expr->false_branch = false_branch; +        instr->true_branch = true_branch; +        instr->false_branch = false_branch;      }  } diff --git a/src/decomp/instr/ite.h b/src/decomp/instr/ite.h index e53abe8..7137452 100644 --- a/src/decomp/instr/ite.h +++ b/src/decomp/instr/ite.h @@ -1,8 +1,8 @@  /* OpenIDA - Outil d'analyse de fichiers binaires - * ite.h - prototypes pour la représentation des conditions + * ite.h - prototypes pour la représentation des branchements conditionnels   * - * Copyright (C) 2010 Cyrille Bagard + * Copyright (C) 2010-2013 Cyrille Bagard   *   *  This file is part of OpenIDA.   * @@ -21,8 +21,8 @@   */ -#ifndef _DECOMP_EXPR_ITE_H -#define _DECOMP_EXPR_ITE_H +#ifndef _DECOMP_INSTR_ITE_H +#define _DECOMP_INSTR_ITE_H  #include <glib-object.h> @@ -52,12 +52,12 @@ typedef struct _GITEInstructionClass GITEInstructionClass;  /* Indique le type défini pour un aiguillage du flux d'exécution. */  GType g_ite_instruction_get_type(void); -/* Détermine le corps des différentes branches possibles. */ -void g_ite_instruction_set_branches(GITEInstruction *, GDecInstruction *, GDecInstruction *); -  /* Exprime un aiguillage du flux en fonction d'une condition. */  GDecInstruction *g_ite_instruction_new(GDecExpression *, vmpa_t, vmpa_t); +/* Détermine le corps des différentes branches possibles. */ +void g_ite_instruction_set_branches(GITEInstruction *, GDecInstruction *, GDecInstruction *); + -#endif  /* _DECOMP_EXPR_ITE_H */ +#endif  /* _DECOMP_INSTR_ITE_H */ diff --git a/src/decomp/instr/switch.c b/src/decomp/instr/switch.c new file mode 100644 index 0000000..3c204a0 --- /dev/null +++ b/src/decomp/instr/switch.c @@ -0,0 +1,379 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * switch.c - décodage des aiguillages multiples du flot d'exécution + * + * Copyright (C) 2013 Cyrille Bagard + * + *  This file is part of OpenIDA. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "switch.h" + + +#include <malloc.h> +#include <stdlib.h> + + +#include "../instruction-int.h" + + +/* Détails d'un cas */ +typedef struct _case_info +{ +    vmpa_t addr;                            /* Adresse des blocs associés */ + +    GDecExpression **values;                /* Valeur d'embranchement     */ +    size_t values_count;                    /* Quantité de cas rassemblés */ + +    GDecInstruction *instrs;                /* Instructions du cas        */ + +} case_info; + + +/* Définition d'un aiguillage multiple du flux d'exécution (instance) */ +struct _GSwitchInstruction +{ +    GDecInstruction parent;                 /* A laisser en premier        */ + +    GDecExpression *value;                  /* Valeur décidant du flot     */ + +    case_info *cases;                       /* Embranchements présents     */ +    size_t cases_count;                     /* Nombre de cas de sélection  */ + +    GDecInstruction *def_case;              /* Instructions par défaut     */ + +}; + + +/* Définition d'un aiguillage multiple du flux d'exécution (classe) */ +struct _GSwitchInstructionClass +{ +    GDecInstructionClass parent;            /* A laisser en premier        */ + +}; + + + +/* Initialise la classe des aiguillages de flux d'exécution. */ +static void g_switch_instruction_class_init(GSwitchInstructionClass *); + +/* Initialise une instance d'aiguillage du flux d'exécution. */ +static void g_switch_instruction_init(GSwitchInstruction *); + +/* Visite un ensemble hiérarchique d'instructions décompilées. */ +static bool g_switch_instruction_visit(GSwitchInstruction *, dec_instr_visitor_cb, DecInstrVisitFlags, void *); + +/* Remplace une instruction décompilée par une autre. */ +static bool g_switch_instruction_replace(GSwitchInstruction *, GDecInstruction *, GDecInstruction *); + +/* Imprime pour l'écran un version humaine d'une instruction. */ +static GBufferLine *g_switch_instruction_print(const GSwitchInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *); + + + +/* Indique le type défini pour un aiguillage du flux d'exécution. */ +G_DEFINE_TYPE(GSwitchInstruction, g_switch_instruction, G_TYPE_DEC_INSTRUCTION); + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : klass = classe à initialiser.                                * +*                                                                             * +*  Description : Initialise la classe des aiguillages de flux d'exécution.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_switch_instruction_class_init(GSwitchInstructionClass *klass) +{ + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr = instance à initialiser.                              * +*                                                                             * +*  Description : Initialise une instance d'aiguillage du flux d'exécution.    * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void g_switch_instruction_init(GSwitchInstruction *instr) +{ +    GDecInstruction *base;                  /* Autre version de l'objet    */ + +    base = G_DEC_INSTRUCTION(instr); + +    base->visit = (dec_instr_visit_fc)g_switch_instruction_visit; +    base->replace = (dec_instr_replace_fc)g_switch_instruction_replace; +    base->print = (dec_instr_print_fc)g_switch_instruction_print; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : value = valeur déterminant la voie à suivre.                 * +*                                                                             * +*  Description : Exprime un aiguillage multiple du flux selon une valeur.     * +*                                                                             * +*  Retour      : Expression mise en place.                                    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GDecInstruction *g_switch_instruction_new(GDecExpression *value) +{ +    GSwitchInstruction *result;              /* Expression à retourner      */ + +    result = g_object_new(G_TYPE_SWITCH_INSTRUCTION, NULL); + +    result->value = value; + +    return G_DEC_INSTRUCTION(result); + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr    = première instruction à venir visiter.             * +*                callback = procédure à appeler à chaque instruction visitée. * +*                flags    = moments des appels à réaliser en retour.          * +*                data     = données quelconques associées au visiteur.        * +*                                                                             * +*  Description : Visite un ensemble hiérarchique d'instructions décompilées.  * +*                                                                             * +*  Retour      : true si le parcours a été jusqu'à son terme, false sinon.    * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_switch_instruction_visit(GSwitchInstruction *instr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours          */ + +    result = true; +    return true; +    for (i = 0; i < instr->cases_count && result; i++) +        result = _g_dec_instruction_visit(instr->cases[i].instrs, G_DEC_INSTRUCTION(instr), +                                          callback, flags, data); + +    if (result && instr->def_case != NULL) +        result = _g_dec_instruction_visit(instr->def_case, G_DEC_INSTRUCTION(instr), +                                          callback, flags, data); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr = première instruction à venir ausculter.              * +*                old   = instruction décompilée à venir remplacer.            * +*                new   = instruction décompilée à utiliser dorénavant.        * +*                                                                             * +*  Description : Remplace une instruction décompilée par une autre.           * +*                                                                             * +*  Retour      : true si un remplacement a été effectué, false sinon.         * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static bool g_switch_instruction_replace(GSwitchInstruction *instr, GDecInstruction *old, GDecInstruction *new) +{ +    bool result;                            /* Bilan à retourner           */ +    size_t i;                               /* Boucle de parcours          */ + +    result = false; +    return false; +    for (i = 0; i < instr->cases_count; i++) +        result |= g_dec_instruction_replace(instr->cases[i].instrs, old, new); + +    if (instr->def_case != NULL) +        result |= g_dec_instruction_replace(instr->def_case, old, new); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr  = instruction à transcrire en version humaine.        * +*                buffer = tampon où doit se réaliser l'insertion.             * +*                line   = ligne d'impression prête à emploi ou NULL.          * +*                output = langage de programmation de sortie.                 * +*                                                                             * +*  Description : Imprime pour l'écran un version humaine d'une instruction.   * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GBufferLine *g_switch_instruction_print(const GSwitchInstruction *instr, GCodeBuffer *buffer, GBufferLine *line, GLangOutput *output) +{ +    GBufferLine *result;                    /* Ligne à retourner           */ +    size_t i;                               /* Boucle de parcours #1       */ +    size_t j;                               /* Boucle de parcours #2       */ + +    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "switch", 9, RTT_KEY_WORD); + +    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); +    g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "(", 1, RTT_PUNCT); + +    result = g_dec_instruction_print(G_DEC_INSTRUCTION(instr->value), buffer, line, output); + +    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ")", 1, RTT_PUNCT); + +    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); +    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "{", 1, RTT_HOOK); + +    g_code_buffer_inc_indentation(buffer); + +    /* Cas d'aiguillage définis */ + +    for (i = 0; i < instr->cases_count; i++) +    { +        for (j = 0; j < instr->cases[i].values_count; j++) +        { +            result = g_code_buffer_append_new_line_fixme(buffer); + +            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "case", 4, RTT_KEY_WORD); +            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); + +            result = g_dec_instruction_print(G_DEC_INSTRUCTION(instr->cases[i].values[j]) +                                             , buffer, result, output); + +            g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT); + +        } + +        result = g_dec_instruction_print(instr->cases[i].instrs, buffer, result, output); + +    } + +    /* Cas par défaut */ + +    if (instr->def_case != NULL) +    { +        result = g_code_buffer_append_new_line_fixme(buffer); + +        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "default", 7, RTT_KEY_WORD); +        g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, ":", 1, RTT_PUNCT); + +        result = g_dec_instruction_print(instr->def_case, buffer, result, output); + +    } + +    /* Clôture */ + +    g_code_buffer_dec_indentation(buffer); + +    result = g_code_buffer_append_new_line_fixme(buffer); + +    g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "}", 1, RTT_HOOK); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr  = instruction à compléter avec un nouveau cas.        * +*                value  = valeur validant l'exécution des instructions.       * +*                instrs = instructions associées au cas présenté.             * +*                addr   = adresse du bloc d'instructions.                     * +*                                                                             * +*  Description : Ajoute un cas d'exécution à l'aiguillage multiple.           * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_switch_instruction_add_case(GSwitchInstruction *instr, GDecExpression *value, GDecInstruction *instrs, vmpa_t addr) +{ +    case_info *found;                       /* Cas similaires déjà intégrés*/ + +    found = (case_info *)bsearch(&addr, instr->cases, instr->cases_count, sizeof(case_info), +                                 (__compar_fn_t)compare_vmpa); + +    if (found != NULL) +    { +        found->values = (GDecExpression **)realloc(found->values, +                                                   found->values_count++ * sizeof(GDecExpression *)); + +        found->values[found->values_count - 1] = value; + +    } +    else +    { +        instr->cases = (case_info *)realloc(instr->cases, +                                            ++instr->cases_count * sizeof(case_info)); + +        instr->cases[instr->cases_count - 1].addr = addr; +        instr->cases[instr->cases_count - 1].values = (GDecExpression **)malloc(sizeof(GDecExpression *)); +        instr->cases[instr->cases_count - 1].values_count = 1; +        instr->cases[instr->cases_count - 1].instrs = instrs; + +        instr->cases[instr->cases_count - 1].values[0] = value; + +        qsort(instr->cases, instr->cases_count, sizeof(case_info), (__compar_fn_t)compare_vmpa); + +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr  = instruction à compléter avec un nouveau cas.        * +*                instrs = instructions associées au cas présenté.             * +*                                                                             * +*  Description : Ajoute un cas d'exécution par défaut à l'aiguillage multiple.* +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +void g_switch_instruction_set_default_case(GSwitchInstruction *instr, GDecInstruction *instrs) +{ +    if (instr->def_case != NULL) +        g_object_unref(G_OBJECT(instr->def_case)); + +    instr->def_case = instrs; + +} diff --git a/src/decomp/instr/switch.h b/src/decomp/instr/switch.h new file mode 100644 index 0000000..fa00c3e --- /dev/null +++ b/src/decomp/instr/switch.h @@ -0,0 +1,66 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * switch.h - prototypes pour les aiguillages multiples du flot d'exécution + * + * Copyright (C) 2013 Cyrille Bagard + * + *  This file is part of OpenIDA. + * + *  OpenIDA is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 3 of the License, or + *  (at your option) any later version. + * + *  OpenIDA is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _DECOMP_INSTR_SWITCH_H +#define _DECOMP_INSTR_SWITCH_H + + +#include <glib-object.h> + + +#include "../expression.h" +#include "../instruction.h" + + + +#define G_TYPE_SWITCH_INSTRUCTION               g_switch_instruction_get_type() +#define G_SWITCH_INSTRUCTION(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj), g_switch_instruction_get_type(), GSwitchInstruction)) +#define G_IS_SWITCH_INSTRUCTION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_switch_instruction_get_type())) +#define G_SWITCH_INSTRUCTION_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_SWITCH_INSTRUCTION, GSwitchInstructionClass)) +#define G_IS_SWITCH_INSTRUCTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_SWITCH_INSTRUCTION)) +#define G_SWITCH_INSTRUCTION_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_SWITCH_INSTRUCTION, GSwitchInstructionClass)) + + + +/* Définition d'un aiguillage multiple du flux d'exécution (instance) */ +typedef struct _GSwitchInstruction GSwitchInstruction; + +/* Définition d'un aiguillage multiple du flux d'exécution (classe) */ +typedef struct _GSwitchInstructionClass GSwitchInstructionClass; + + +/* Indique le type défini pour un multiple aiguillage du flux d'exécution. */ +GType g_switch_instruction_get_type(void); + +/* Exprime un aiguillage multiple du flux selon une valeur. */ +GDecInstruction *g_switch_instruction_new(GDecExpression *); + +/* Ajoute un cas d'exécution à l'aiguillage multiple. */ +void g_switch_instruction_add_case(GSwitchInstruction *, GDecExpression *, GDecInstruction *, vmpa_t); + +/* Ajoute un cas d'exécution par défaut à l'aiguillage multiple. */ +void g_switch_instruction_set_default_case(GSwitchInstruction *, GDecInstruction *); + + + +#endif  /* _DECOMP_INSTR_SWITCH_H */ diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c index 2cf4a36..87ae2ec 100644 --- a/src/gtkext/graph/layout.c +++ b/src/gtkext/graph/layout.c @@ -244,7 +244,7 @@ static char *complete_graph_links(const GtkGraphView *view, GtkViewPanel **views          if (g_arch_instruction_has_destinations(last))          { -            dcount = g_arch_instruction_get_destinations(last, &dests, &types); +            dcount = g_arch_instruction_get_destinations(last, &dests, &types, NULL);              for (j = 0; j < dcount; j++)              { | 
