diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/androhelpers/switch.c | 46 | 
1 files changed, 46 insertions, 0 deletions
| diff --git a/plugins/androhelpers/switch.c b/plugins/androhelpers/switch.c index 0a1e488..3bb900f 100644 --- a/plugins/androhelpers/switch.c +++ b/plugins/androhelpers/switch.c @@ -42,6 +42,9 @@ static bool load_dex_switch(const GArchInstruction *, GArchInstruction *, const  /* Lie les instructions selon les cas d'un aiguillage. */  static void link_all_switch_cases(GArchInstruction *, const dex_switch *, GArchInstruction *, vmpa_t, vmpa_t); +/* Prend en compte les absences de 'break' dans les cas. */ +static void ensure_each_case_has_its_block(GArchInstruction *, GArchInstruction *); +  /* Insère des indications dans le texte humainement lisibles. */  static void mark_all_switch_cases(const GArchInstruction *, const dex_switch *, GArchInstruction *, const GLoadedBinary *, vmpa_t, vmpa_t); @@ -166,6 +169,7 @@ static void link_all_switch_cases(GArchInstruction *instr, const dex_switch *dsw              imm = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, value);              g_arch_instruction_link_with(instr, next, ILT_CASE_JUMP, imm); +            ensure_each_case_has_its_block(next, instrs);          } @@ -176,7 +180,49 @@ 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, NULL); +        ensure_each_case_has_its_block(next, instrs); +    } + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : instr   = instruction d'aiguillage rencontrée.               * +*                instrs  = liste des instructions pour tout le binaire.       * +*                                                                             * +*  Description : Prend en compte les absences de 'break' dans les cas.        * +*                                                                             * +*  Retour      : -                                                            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static void ensure_each_case_has_its_block(GArchInstruction *instr, GArchInstruction *instrs) +{ +    GArchInstruction *prev;                 /* Instruction avant un cas    */ + +    /** +     * La situation où un cas n'a pas de 'break' conduit à une fusion du corps +     * du cas avec le corps du cas suivant (partie commune). +     * La fin du premier cas n'ayant pas de saut enregistré, rien n'entraîne un +     * lien logique, et donc une séparation des deux cas en blocs distincts. +     * +     * Cette procédure établit les vérifications nécessaires, et rétablit +     * la logique des liens et des blocs en cas de besoin. +     */ + +    prev = g_arch_instruction_get_prev_iter(instrs, instr); + +    if (prev != NULL +        && !g_arch_instruction_has_destinations(prev) +        && !g_arch_instruction_is_return(prev)) +    { +        g_arch_instruction_link_with(prev, instr, ILT_EXEC_FLOW, NULL); +    }  } | 
