summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/androhelpers/switch.c46
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);
+ }
}