diff options
Diffstat (limited to 'src/arch/arm')
-rw-r--r-- | src/arch/arm/v7/link.c | 90 | ||||
-rw-r--r-- | src/arch/arm/v7/link.h | 19 | ||||
-rw-r--r-- | src/arch/arm/v7/opcodes/opcodes_tmp_arm.h | 1 | ||||
-rw-r--r-- | src/arch/arm/v7/opdefs/Makefile.am | 1 | ||||
-rw-r--r-- | src/arch/arm/v7/opdefs/bx_A8827.d | 12 | ||||
-rw-r--r-- | src/arch/arm/v7/opdefs/ldr_A8863.d | 2 | ||||
-rw-r--r-- | src/arch/arm/v7/opdefs/str_A88204.d | 77 | ||||
-rw-r--r-- | src/arch/arm/v7/post.c | 16 |
8 files changed, 212 insertions, 6 deletions
diff --git a/src/arch/arm/v7/link.c b/src/arch/arm/v7/link.c index c1f83ac..da5e30e 100644 --- a/src/arch/arm/v7/link.c +++ b/src/arch/arm/v7/link.c @@ -28,6 +28,9 @@ #include <operands/offset.h> +#include "../register.h" + + /****************************************************************************** * * @@ -56,7 +59,25 @@ void handle_links_with_instruction_b_with_orig(GArchInstruction *instr, GArmV7Co pc = get_virt_addr(get_mrange_addr(range)); - pc += get_mrange_length(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_arch_instruction_get_operand(instr, 0); @@ -197,6 +218,68 @@ void handle_links_with_instruction_blx_with_dest(GArchInstruction *instr, GArmV7 * Paramètres : instr = instruction ARMv7 à traiter. * * 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 handle_links_with_instruction_bx_with_orig(GArchInstruction *instr, GArmV7Context *context, GBinFormat *format, ArmV7InstrSet iset) +{ + GArchOperand *op; /* Opérande numérique en place */ + GArmRegister *reg; /* Registre matériel manipulé */ + 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)); + + reg = G_ARM_REGISTER(g_register_operand_get_register(G_REGISTER_OPERAND(op))); + + /** + * On ne sait agir qu'avec le seul contenu facilement prédictible : pc ! + */ + + if (g_arm_register_get_index(reg) != 15 /* pc */) + return; + + /** + * 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_armv7_context_push_drop_point_ext(context, pc, AV7IS_THUMB); + break; + case AV7IS_THUMB: + pc += 4; + //g_armv7_context_define_encoding(context, + g_armv7_context_push_drop_point_ext(context, pc, AV7IS_ARM); + break; + default: + assert(0); + break; + } + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* 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. * * * @@ -342,6 +425,11 @@ void handle_links_with_instruction_ldr_literal_with_orig(GArchInstruction *instr //g_imm_operand_set_value(G_IMM_OPERAND(sub_op), MDS_32_BITS_UNSIGNED, target); + + if (target < 0x8000) return; + + + new = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, target); g_arch_instruction_replace_operand(instr, new, op); diff --git a/src/arch/arm/v7/link.h b/src/arch/arm/v7/link.h index 87bef54..9e52fe6 100644 --- a/src/arch/arm/v7/link.h +++ b/src/arch/arm/v7/link.h @@ -37,12 +37,12 @@ void handle_links_with_instruction_b_with_orig(GArchInstruction *, GArmV7Context static inline void handle_links_with_instruction_b_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) { - handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_THUMB); + handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_ARM); } static inline void handle_links_with_instruction_b_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) { - handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_ARM); + handle_links_with_instruction_b_with_orig(ins, ctx, fmt, AV7IS_THUMB); } @@ -77,6 +77,21 @@ static inline void handle_links_with_instruction_blx_from_thumb(GArchInstruction /* Complète un désassemblage accompli pour une instruction. */ +void handle_links_with_instruction_bx_with_orig(GArchInstruction *, GArmV7Context *, GBinFormat *, ArmV7InstrSet); + + +static inline void handle_links_with_instruction_bx_from_arm(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) +{ + handle_links_with_instruction_bx_with_orig(ins, ctx, fmt, AV7IS_ARM); +} + +static inline void handle_links_with_instruction_bx_from_thumb(GArchInstruction *ins, GArmV7Context *ctx, GBinFormat *fmt) +{ + handle_links_with_instruction_bx_with_orig(ins, ctx, fmt, AV7IS_THUMB); +} + + +/* Complète un désassemblage accompli pour une instruction. */ void handle_links_with_instruction_cb_n_z(GArchInstruction *, GArmV7Context *, GBinFormat *); /* Complète un désassemblage accompli pour une instruction. */ diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h index 36e2193..3a5e646 100644 --- a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h +++ b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h @@ -15,7 +15,6 @@ #define armv7_read_arm_instr_stmib_stmfa(r) NULL #define armv7_read_arm_instr_stm_stmia_stmea(r) NULL #define armv7_read_arm_instr_stm_user_registers(r) NULL -#define armv7_read_arm_instr_str_immediate_arm(r) NULL #define armv7_read_arm_instr_str_register(r) NULL #define armv7_read_arm_instr_strt(r) NULL #endif diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am index fa42230..36509b4 100644 --- a/src/arch/arm/v7/opdefs/Makefile.am +++ b/src/arch/arm/v7/opdefs/Makefile.am @@ -77,6 +77,7 @@ ARMV7_DEFS = \ smlal_A88178.d \ smull_A88189.d \ str_A88203.d \ + str_A88204.d \ strb_A88206.d \ sub_A88222.d \ sub_A88223.d \ diff --git a/src/arch/arm/v7/opdefs/bx_A8827.d b/src/arch/arm/v7/opdefs/bx_A8827.d index b8ab6f8..dd06901 100644 --- a/src/arch/arm/v7/opdefs/bx_A8827.d +++ b/src/arch/arm/v7/opdefs/bx_A8827.d @@ -36,6 +36,12 @@ } + @hooks { + + link = handle_links_with_instruction_bx_from_thumb + + } + @rules { call DefineAsReturn(1) @@ -57,6 +63,12 @@ } + @hooks { + + link = handle_links_with_instruction_bx_from_thumb + + } + @rules { call DefineAsReturn(1) diff --git a/src/arch/arm/v7/opdefs/ldr_A8863.d b/src/arch/arm/v7/opdefs/ldr_A8863.d index 0158c3d..39b9079 100644 --- a/src/arch/arm/v7/opdefs/ldr_A8863.d +++ b/src/arch/arm/v7/opdefs/ldr_A8863.d @@ -54,7 +54,7 @@ @encoding(A12) { - @word cond(4) 0 1 0 0 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12) + @word cond(4) 0 1 0 0 U(1) 0 W(1) 1 Rn(4) Rt(4) imm12(12) @syntax <Rgt> <base> <offset> diff --git a/src/arch/arm/v7/opdefs/str_A88204.d b/src/arch/arm/v7/opdefs/str_A88204.d new file mode 100644 index 0000000..d4e9377 --- /dev/null +++ b/src/arch/arm/v7/opdefs/str_A88204.d @@ -0,0 +1,77 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * ##FILE## - traduction d'instructions ARMv7 + * + * Copyright (C) 2014 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/>. + */ + + +@title STR (immediate, ARM) + +@encoding(A11) { + + @word cond(4) 0 1 0 1 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12) + + @syntax <Rgt> <access> + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm12, 12, 32); + access = MakeMemoryAccess(Rgn, imm32, U, 1) + + } + + @rules { + + //if P == '0' && W == '1' then SEE STRT; + //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH; + //if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (Rt == '1111'); call DefineAsReturn(1) + + } + +} + +@encoding(A12) { + + @word cond(4) 0 1 0 0 U(1) 0 W(1) 0 Rn(4) Rt(4) imm12(12) + + @syntax <Rgt> <base> <offset> + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm12, 12, 32); + base = MakeMemoryNotIndexed(Rgn, W) + offset = MakeAccessOffset(U, imm32) + + } + + @rules { + + //if P == '0' && W == '1' then SEE STRT; + //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH; + //if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (Rt == '1111'); call DefineAsReturn(1) + + } + +} diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c index 8895740..084fc84 100644 --- a/src/arch/arm/v7/post.c +++ b/src/arch/arm/v7/post.c @@ -24,6 +24,9 @@ #include "post.h" +#include <assert.h> + + #include "../../target.h" @@ -245,17 +248,26 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex op = g_arch_instruction_get_operand(instr, 1); + + if (!G_IS_IMM_OPERAND(op)) return; + + if (g_imm_operand_get_value(G_IMM_OPERAND(op), MDS_32_BITS_UNSIGNED, &addr)) { new = g_target_operand_new(MDS_32_BITS_UNSIGNED, addr); if (!g_target_operand_resolve(G_TARGET_OPERAND(new), format)) { + addr &= ~0x1; + + + printf("RESOLVING FOR 0x%08x\n", (unsigned int)addr); + init_vmpa(&target, VMPA_NO_PHYSICAL, addr); init_mrange(&trange, &target, 0); vmpa2_virt_to_string(&target, MDS_32_BITS, loc, NULL); - snprintf(name, sizeof(name), "loc_%s", loc + 2); + snprintf(name, sizeof(name), "loccc_%s", loc + 2); routine = g_binary_routine_new(); g_binary_routine_set_name(routine, strdup(name)); @@ -272,9 +284,11 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex g_target_operand_resolve(G_TARGET_OPERAND(new), format); } + else printf("RESOLVED FOR 0x%08x\n", (unsigned int)addr); g_arch_instruction_replace_operand(instr, new, op); } + else assert(0); } |