summaryrefslogtreecommitdiff
path: root/src/arch/dalvik/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/dalvik/link.c')
-rw-r--r--src/arch/dalvik/link.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/arch/dalvik/link.c b/src/arch/dalvik/link.c
new file mode 100644
index 0000000..b698f03
--- /dev/null
+++ b/src/arch/dalvik/link.c
@@ -0,0 +1,154 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * link.c - édition des liens après la phase de désassemblage
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * 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 "link.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <stdio.h>
+
+
+#include <i18n.h>
+
+
+#include "pseudo/switch.h"
+#include "../target.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instruction ARMv7 à traiter. *
+* proc = représentation de l'architecture utilisée. *
+* context = contexte associé à la phase de désassemblage. *
+* format = acès aux données du binaire d'origine. *
+* *
+* Description : Etablit tous les liens liés à un embranchement compressé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void handle_dalvik_packed_switch_links(GArchInstruction *instr, GArchProcessor *proc, GProcContext *context, GBinFormat *format)
+{
+ GArchOperand *op; /* Opérande numérique en place */
+ virt_t virt; /* Adresse virtuelle */
+ vmpa2t addr; /* Adresse de destination */
+ GArchInstruction *switch_ins; /* Instruction de branchements */
+ const mrange_t *range; /* Zone d'occupation */
+ const vmpa2t *start_addr; /* Adresse de référentiel */
+ vmpa2t def_addr; /* Traitement par défaut */
+ GArchInstruction *target; /* Ligne visée par la référence*/
+ GDbComment *comment; /* Indication sur la condition */
+ const uint32_t *keys; /* Conditions de sauts */
+ const uint32_t *targets; /* Positions relatives liées */
+ uint16_t count; /* Taille de ces tableaux */
+ uint16_t i; /* Boucle de parcours */
+ char *int_val;/* Valeur en chaîne de carac. */
+
+ assert(g_arch_instruction_count_operands(instr) == 2);
+
+ op = g_arch_instruction_get_operand(instr, 1);
+
+ virt = VMPA_NO_VIRTUAL;
+
+ if (G_IS_TARGET_OPERAND(op))
+ virt = g_target_operand_get_addr(G_TARGET_OPERAND(op));
+
+ else if (G_IS_IMM_OPERAND(op))
+ {
+ if (!g_imm_operand_to_virt_t(G_IMM_OPERAND(op), &virt))
+ virt = VMPA_NO_VIRTUAL;
+ }
+
+ if (virt != VMPA_NO_VIRTUAL)
+ {
+ /* TODO : utiliser format pour contruire une adresse avec une position physique,
+ * ce qui accélèrerait les recherches.
+ */
+ init_vmpa(&addr, VMPA_NO_PHYSICAL, virt);
+
+ switch_ins = g_arch_processor_find_instr_by_address(proc, &addr);
+
+ if (G_IS_DALVIK_SWITCH_INSTR(switch_ins))
+ {
+ range = g_arch_instruction_get_range(instr);
+
+ start_addr = get_mrange_addr(range);
+
+ /* Cas par défaut */
+
+ compute_mrange_end_addr(range, &def_addr);
+
+ target = g_arch_processor_find_instr_by_address(proc, &def_addr);
+
+ if (target != NULL)
+ {
+ comment = g_db_comment_new_area(&def_addr, BLF_NONE, _("Defaut case"), true);
+
+ // FIXME g_db_item_set_volatile(G_DB_ITEM(comment), true);
+ g_proc_context_add_db_item(context, G_DB_ITEM(comment));
+
+ g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP);
+
+ }
+
+ /* Autres cas */
+
+ assert(G_IS_DALVIK_SWITCH_INSTR(switch_ins));
+
+ count = g_dalvik_switch_get_data(G_DALVIK_SWITCH_INSTR(switch_ins), &keys, &targets);
+
+ for (i = 0; i < count; i++)
+ {
+ copy_vmpa(&addr, start_addr);
+ advance_vmpa(&addr, targets[i] * sizeof(uint16_t));
+
+ if (cmp_vmpa(&addr, &def_addr) == 0)
+ continue;
+
+ target = g_arch_processor_find_instr_by_address(proc, &addr);
+
+ if (target != NULL)
+ {
+ asprintf(&int_val, _("Case %d"), keys[i]);
+ comment = g_db_comment_new_area(&addr, BLF_NONE, int_val, true);
+ free(int_val);
+
+ // FIXME g_db_item_set_volatile(G_DB_ITEM(comment), true);
+ g_proc_context_add_db_item(context, G_DB_ITEM(comment));
+
+ g_arch_instruction_link_with(instr, target, ILT_CASE_JUMP);
+
+ }
+
+ }
+
+ }
+
+ }
+
+}