/* 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 . */ #include "link.h" #include #include #include #include #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); } } } } }