diff options
Diffstat (limited to 'plugins/androhelpers/switch.c')
-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); + } } |