diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2017-12-02 11:04:35 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2017-12-02 11:04:35 (GMT) |
commit | 2c988d3ec52cc4c949a35aca7ef335dac773df92 (patch) | |
tree | fe650d2fc8ddceb606abdf0d2e14e5ef6596be82 /plugins/arm/v7/fetch.c | |
parent | 23abef53590bf3dd6f88ff4dbe81e306abfa4386 (diff) |
Created a plugin for the ARM support.
Diffstat (limited to 'plugins/arm/v7/fetch.c')
-rw-r--r-- | plugins/arm/v7/fetch.c | 521 |
1 files changed, 521 insertions, 0 deletions
diff --git a/plugins/arm/v7/fetch.c b/plugins/arm/v7/fetch.c new file mode 100644 index 0000000..005a48d --- /dev/null +++ b/plugins/arm/v7/fetch.c @@ -0,0 +1,521 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * fetch.c - ajouts de sauts à traiter durant la phase de désassemblage + * + * Copyright (C) 2015-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide 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. + * + * Chrysalide 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 "fetch.h" + + +#include <assert.h> +#include <stdio.h> + + +#include <i18n.h> +#include <arch/raw.h> +#include <format/format.h> +#include <format/preload.h> + + +#include "operands/offset.h" +#include "../register.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. * +* iset = type de jeu d'instructions courant à faire suivre. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_b_with_orig(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GImmOperand *op; /* Opérande numérique en place */ + int32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + + + + switch (iset) + { + case AV7IS_ARM: + pc += 8; + break; + case AV7IS_THUMB: + pc += 4; + break; + default: + assert(0); + break; + } + + + + //pc += get_mrange_length(range); + + op = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 0)); + + if (g_imm_operand_get_value(op, MDS_32_BITS_SIGNED, &offset)) + g_imm_operand_set_value(op, MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + g_object_unref(G_OBJECT(op)); + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, iset); + g_proc_context_push_drop_point(G_PROC_CONTEXT(context), DPL_OTHER, target, iset); + +} + + +/****************************************************************************** +* * +* 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. * +* iset = type de jeu d'instructions courant à faire suivre. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_bl_with_orig(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GImmOperand *op; /* Opérande numérique en place */ + int32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + /** + * Qu'on se trouve en mode Thumb ou ARM, l'instruction + * ne peut qu'être encodée sur 4 octets. + */ + + assert(get_mrange_length(range) == 4); + + switch (iset) + { + case AV7IS_ARM: + pc += 8; + break; + case AV7IS_THUMB: + pc += 4; + break; + default: + assert(0); + break; + } + + op = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 0)); + + if (g_imm_operand_get_value(op, MDS_32_BITS_SIGNED, &offset)) + g_imm_operand_set_value(op, MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + g_object_unref(G_OBJECT(op)); + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, iset); + g_proc_context_push_drop_point(G_PROC_CONTEXT(context), DPL_OTHER, target, iset); + +} + + +/****************************************************************************** +* * +* 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. * +* iset = type de jeu d'instructions courant à inverser. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_blx_with_dest(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GImmOperand *op; /* Opérande numérique en place */ + int32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + /** + * Qu'on se trouve en mode Thumb ou ARM, l'instruction + * ne peut qu'être encodée sur 4 octets. + */ + + assert(get_mrange_length(range) == 4); + + pc += 4; + pc -= pc % 4; + + op = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 0)); + + if (g_imm_operand_get_value(op, MDS_32_BITS_SIGNED, &offset)) + g_imm_operand_set_value(op, MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + g_object_unref(G_OBJECT(op)); + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, iset); + g_proc_context_push_drop_point(G_PROC_CONTEXT(context), DPL_OTHER, target, iset); + +} + + +/****************************************************************************** +* * +* 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. * +* iset = type de jeu d'instructions courant à faire suivre. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_bx_with_orig(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format, ArmV7InstrSet iset) +{ + GArchOperand *op; /* Opérande numérique en place */ + GArmRegister *reg; /* Registre matériel manipulé */ + bool is_pc; /* Nature de ce même registre */ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + + op = g_arch_instruction_get_operand(instr, 0); + assert(G_IS_REGISTER_OPERAND(op)); + + /** + * On ne sait agir qu'avec le seul contenu facilement prédictible : pc ! + */ + + reg = G_ARM_REGISTER(g_register_operand_get_register(G_REGISTER_OPERAND(op))); + + is_pc = (g_arm_register_get_index(reg) == 15 /* pc */); + + g_object_unref(G_OBJECT(reg)); + + if (!is_pc) goto hfwibwo_no_pc; + + /** + * On bascule alors le mode de décodage à cette adresse... + */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + switch (iset) + { + case AV7IS_ARM: + pc += 8; + //g_armv7_context_define_encoding(context, + g_proc_context_push_drop_point(G_PROC_CONTEXT(context), DPL_OTHER, pc, AV7IS_THUMB); + break; + case AV7IS_THUMB: + pc += 4; + //g_armv7_context_define_encoding(context, + g_proc_context_push_drop_point(G_PROC_CONTEXT(context), DPL_OTHER, pc, AV7IS_ARM); + break; + default: + assert(0); + break; + } + + hfwibwo_no_pc: + + g_object_unref(G_OBJECT(op)); + +} + + +/****************************************************************************** +* * +* 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 : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_cb_n_z(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + virt_t pc; /* Position dans l'exécution */ + GImmOperand *op; /* Opérande numérique en place */ + uint32_t offset; /* Décallage encodé en dur */ + virt_t target; /* Adresse virtuelle visée */ + + range = g_arch_instruction_get_range(instr); + + pc = get_virt_addr(get_mrange_addr(range)); + + /** + * En mode Thumb, pc a pour valeur l'adresse courante plus 4. + */ + + pc += 4; + + op = G_IMM_OPERAND(g_arch_instruction_get_operand(instr, 1)); + + if (g_imm_operand_get_value(op, MDS_32_BITS_UNSIGNED, &offset)) + g_imm_operand_set_value(op, MDS_32_BITS_UNSIGNED, pc + offset); + + else assert(0); + + g_object_unref(G_OBJECT(op)); + + target = pc + offset; + + //g_armv7_context_define_encoding(context, target, AV7IS_THUMB); + g_proc_context_push_drop_point(G_PROC_CONTEXT(context), DPL_OTHER, target, AV7IS_THUMB); + +} + + +/****************************************************************************** +* * +* 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. * +* iset = type de jeu d'instructions courant. * +* * +* Description : Complète un désassemblage accompli pour une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format, ArmV7InstrSet iset) +{ + const mrange_t *range; /* Emplacementt d'instruction */ + phys_t phys_pc; /* Position dans l'exécution */ + GArchOperand *op; /* Opérande de surcouche */ + uint32_t offset; /* Décallage encodé en dur */ + bool ret; /* Bilan d'une récupération */ + off_t val_offset; /* Position de valeur à lire */ + vmpa2t loaded_addr; /* Adresse de valeur chargée */ + mrange_t loaded_range; /* Espace de chargement */ + GBinContent *content; /* Contenu binaire à relire */ + uint32_t target; /* Adresse virtuelle visée */ + vmpa2t pos; /* Tête de lecture de valeur */ + VMPA_BUFFER(loc); /* Adresse au format texte */ + GPreloadInfo *info; /* Informations préchargées */ + GArchInstruction *loaded; /* Instruction de valeur */ + bool inserted; /* Bilan d'une insertion */ + char *desc; /* Description d'accompagnement*/ + GDbComment *comment; /* Définition de commentaire */ + GArchOperand *new; /* Instruction de ciblage */ + + /* Récupération de l'adresse visée par le chargement */ + + range = g_arch_instruction_get_range(instr); + + phys_pc = get_phy_addr(get_mrange_addr(range)); + + phys_pc &= ~3; + //phys_pc = (phys_pc + 3) & ~3; + + switch (iset) + { + case AV7IS_ARM: + phys_pc += 8; + break; + case AV7IS_THUMB: + phys_pc += 4; + break; + default: + assert(0); + break; + } + + g_arch_instruction_lock_operands(instr); + + op = _g_arch_instruction_get_operand(instr, 1); + assert(G_IS_IMM_OPERAND(op)); + + ret = g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &offset); + if (!ret) + { + assert(0); + g_object_unref(G_OBJECT(op)); + g_arch_instruction_unlock_operands(instr); + return; + } + + /* Transformations et conservation d'une position de chargement */ + + val_offset = phys_pc + offset; + + if (!g_exe_format_translate_offset_into_vmpa(format, val_offset, &loaded_addr)) + { + assert(0); + g_object_unref(G_OBJECT(op)); + g_arch_instruction_unlock_operands(instr); + return; + } + + init_mrange(&loaded_range, &loaded_addr, 4); + + /* Lecture de la valeur vers laquelle renvoyer */ + + content = g_binary_format_get_content(G_BIN_FORMAT(format)); + + copy_vmpa(&pos, &loaded_addr); + + ret = g_binary_content_read_u32(content, &pos, SRE_LITTLE /* FIXME */, &target); + g_object_unref(G_OBJECT(content)); + + if (!ret) + { + g_object_unref(G_OBJECT(op)); + g_arch_instruction_unlock_operands(instr); + return; + } + + /* Réalise l'intégration de la valeur chargée */ + + copy_vmpa(&pos, &loaded_addr); + + info = G_PRELOAD_INFO(context); + + loaded = g_raw_instruction_new_from_value(&pos, MDS_32_BITS_UNSIGNED, target); + + inserted = g_preload_info_add_instruction(info, loaded); + + if (inserted) + { + /* Commentaire associé */ + + vmpa2_virt_to_string(get_mrange_addr(range), MDS_32_BITS, loc, NULL); + asprintf(&desc, _("Value used @ %s"), loc); + + g_preload_info_lock_comments(info); + + comment = _g_preload_info_find_comment_at(info, &loaded_addr); + + if (comment != NULL) + { + g_db_comment_add_static_text(comment, "\n"); + g_db_comment_add_dynamic_text(comment, desc); + } + + else + { + comment = g_db_comment_new_inlined(&loaded_addr, BLF_HAS_CODE, false); + g_db_item_set_volatile(G_DB_ITEM(comment), true); + + g_db_comment_add_dynamic_text(comment, desc); + + _g_preload_info_add_comment(info, comment); + + } + + g_preload_info_unlock_comments(info); + + } + + /* Mise à jour de l'affichage et conclusion */ + + new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target); + _g_arch_instruction_replace_operand(instr, op, new); + + g_object_unref(G_OBJECT(op)); + g_arch_instruction_unlock_operands(instr); + + + + //exit(0); + + + + //target = pc + offset; + + + if (target & 0x1) + iset = AV7IS_THUMB; + //else + // iset = AV7IS_ARM; + + //g_armv7_context_define_encoding(context, target, AV7IS_THUMB); + g_proc_context_push_drop_point(G_PROC_CONTEXT(context), DPL_OTHER, target, iset); + + + //exit(0); + +} |