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);  }  | 
