diff options
Diffstat (limited to 'src/arch')
| -rw-r--r-- | src/arch/arm/v7/arm.c | 121 | ||||
| -rw-r--r-- | src/arch/arm/v7/helpers.c | 56 | ||||
| -rw-r--r-- | src/arch/arm/v7/helpers.h | 4 | ||||
| -rw-r--r-- | src/arch/arm/v7/opcodes/Makefile.am | 1 | ||||
| -rw-r--r-- | src/arch/arm/v7/opdefs/Makefile.am | 4 | ||||
| -rw-r--r-- | src/arch/arm/v7/opdefs/bl_A8825.d | 84 | 
6 files changed, 267 insertions, 3 deletions
diff --git a/src/arch/arm/v7/arm.c b/src/arch/arm/v7/arm.c index 5295ef8..b7d4ff1 100644 --- a/src/arch/arm/v7/arm.c +++ b/src/arch/arm/v7/arm.c @@ -39,6 +39,8 @@ static GArchInstruction *process_armv7_data_processing_and_miscellaneous_instruc  /* Désassemble une instruction ARMv7 de données de registre. */  static GArchInstruction *process_armv7_data_processing_register(uint32_t); +/* Désassemble une instruction ARMv7 de données ou autre. */ +static GArchInstruction *process_armv7_branch_branch_with_link_and_block_data_transfer(uint32_t); @@ -47,7 +49,7 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t);  #define process_armv7_load_store_word_and_unsigned_byte(raw) NULL  #define process_armv7_load_store_word_and_unsigned_byte(raw) NULL  #define process_armv7_media_instructions(raw) NULL -#define process_armv7_branch_branch_with_link_and_block_data_transfer(raw) NULL +//#define process_armv7_branch_branch_with_link_and_block_data_transfer(raw) NULL  #define process_armv7_coprocessor_instructions_and_Supervisor_call(raw) NULL  #define process_armv7_unconditional_instructions(raw) NULL @@ -93,6 +95,26 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t);  #define armv7_read_instr_mvn_register(raw) NULL +// process_armv7_branch_branch_with_link_and_block_data_transfer + +#define armv7_read_instr_stmda_stmed(raw) NULL +#define armv7_read_instr_ldmda_ldmfa(raw) NULL +#define armv7_read_instr_stm_stmia_stmea(raw) NULL +#define armv7_read_instr_ldm_ldmia_ldmfd_arm(raw) NULL +#define armv7_read_instr_ldm_ldmia_ldmfd_arm(raw) NULL +#define armv7_read_instr_pop_arm(raw) NULL +#define armv7_read_instr_stmdb_stmfd(raw) NULL +#define armv7_read_instr_stmdb_stmfd(raw) NULL +#define armv7_read_instr_push(raw) NULL +#define armv7_read_instr_ldmdb_ldmea(raw) NULL +#define armv7_read_instr_stmib_stmfa(raw) NULL +#define armv7_read_instr_ldmib_ldmed(raw) NULL +#define armv7_read_instr_stm_user_registers(raw) NULL +#define armv7_read_instr_ldm_user_registers(raw) NULL +#define armv7_read_instr_ldm_exception_return(raw) NULL +#define armv7_read_instr_b(raw) NULL +//#define armv7_read_instr_bl_blx_immediate(raw) NULL + @@ -127,7 +149,6 @@ GArchInstruction *process_armv7_instruction_set_encoding(uint32_t raw)      op1 = (raw >> 25) & 0x7;      op = (raw >> 4) & 0x1; -      if (cond != b1111)      {          if ((op1 & b110) == b000) @@ -403,3 +424,99 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t raw) + + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : raw = donnée brute de 32 bits à désassembler.                * +*                                                                             * +*  Description : Désassemble une instruction ARMv7 de données ou autre.       * +*                                                                             * +*  Retour      : Instruction mise en place ou NULL en cas d'échec.            * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static GArchInstruction *process_armv7_branch_branch_with_link_and_block_data_transfer(uint32_t raw) +{ +    GArchInstruction *result;               /* Instruction à retourner     */ +    uint32_t op;                            /* Champ 'op' à retrouver      */ +    uint32_t rn;                            /* Champ 'rn' à retrouver      */ +    uint32_t r;                             /* Champ 'r' à retrouver       */ + +    /** +     * Suit les directives de : +     * § A5.5 Branch, branch with link, and block data transferr +     */ + +    result = NULL; + +    op = (raw >> 20) & 0x3f; +    rn = (raw >> 16) & 0xf; +    r = (raw >> 15) & 0x1; + +    if ((op & b111101) == b000000) +        result = armv7_read_instr_stmda_stmed(raw); + +    else if ((op & b111101) == b000001)  +        result = armv7_read_instr_ldmda_ldmfa(raw); + +    else if ((op & b111101) == b001000) +        result = armv7_read_instr_stm_stmia_stmea(raw); + +    else if (op == b001001) +        result = armv7_read_instr_ldm_ldmia_ldmfd_arm(raw); + +    else if (op == b001011) +    { +        if (rn != b1101) +            result = armv7_read_instr_ldm_ldmia_ldmfd_arm(raw); +        else /* if (rn == b1101) */ +            result = armv7_read_instr_pop_arm(raw); +     } + +    else if (op == b010000) +        result = armv7_read_instr_stmdb_stmfd(raw); + +    else if (op == b010010) +    { +        if (rn != b1101) +            result = armv7_read_instr_stmdb_stmfd(raw); +        else /* if (rn == b1101) */ +            result = armv7_read_instr_push(raw); +    } + +    else if ((op & b111101) == b010001) +        result = armv7_read_instr_ldmdb_ldmea(raw); + +    else if ((op & b111101) == b011000) +        result = armv7_read_instr_stmib_stmfa(raw); + +    else if ((op & b111101) == b011001) +        result = armv7_read_instr_ldmib_ldmed(raw); + +    else if ((op & b100101) == b000100) +        result = armv7_read_instr_stm_user_registers(raw); + +    else if ((op & b100101) == b000101) +    { +        if (r == b0) +            result = armv7_read_instr_ldm_user_registers(raw); +        else /* if (r == b1) */ +            result = armv7_read_instr_ldm_exception_return(raw); +    } + +    else if ((op & b110000) == b100000) +        result = armv7_read_instr_b(raw); + +    else if ((op & b110000) == b110000) +        result = armv7_read_instr_bl_blx_immediate(raw); + +    return result; + +} diff --git a/src/arch/arm/v7/helpers.c b/src/arch/arm/v7/helpers.c index 632c1b7..e7c9ad8 100644 --- a/src/arch/arm/v7/helpers.c +++ b/src/arch/arm/v7/helpers.c @@ -26,11 +26,67 @@  #include "register.h"  #include "../../register.h" +#include "../../immediate.h" +#include "../../../common/asm.h"  /******************************************************************************  *                                                                             * +*  Paramètres  : value  = valeur sur 32 bits maximum à traiter.               * +*                topbit = valeur du bit de poids fort manipulé.               * +*                size   = taille de la valeur finale à constituer.            * +*                                                                             * +*  Description : Crée un opérande de valeur immédiate avec extension de signe.* +*                                                                             * +*  Retour      : Adresse de la structure mise en place.                       * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +GArchOperand *sign_extend_armv7_imm(uint32_t value, bool topbit, unsigned int size) +{ +    GArchOperand *result;                   /* Opérande à faire remonter   */ +    unsigned int msb;                       /* Position du premier bit à 1 */ +    MemoryDataSize mds;                     /* Conversion de la taille     */ +    uint32_t val4;                          /* Valeur sur 4 bits           */ +    uint32_t val8;                          /* Valeur sur 8 bits           */ +    uint32_t val16;                         /* Valeur sur 16 bits          */ +    uint32_t val32;                         /* Valeur sur 32 bits          */ +    unsigned int i;                         /* Boucle de parcours          */ + +    result = NULL; + +    topbit &= msb_32(value, &msb); + +    switch (size) +    { + +#define SIGN_EXTEND_CASE(sz)                                        \ +        case sz:                                                    \ +            mds = MDS_ ## sz ## _BITS_SIGNED;                       \ +            val ## sz = value;                                      \ +            if (topbit)                                             \ +                for (i = msb + 1; i < sz; i++)                      \ +                    val ## sz |= (1 << i);                          \ +            result = g_imm_operand_new_from_value(mds, val ## sz);  \ +            break; + +        SIGN_EXTEND_CASE(4); +        SIGN_EXTEND_CASE(8); +        SIGN_EXTEND_CASE(16); +        SIGN_EXTEND_CASE(32); + +    } + +    return result; + +} + + +/****************************************************************************** +*                                                                             *  *  Paramètres  : index = indice du registre correspondant.                    *  *                                                                             *  *  Description : Crée un opérande représentant un registre ARMv7.             * diff --git a/src/arch/arm/v7/helpers.h b/src/arch/arm/v7/helpers.h index 9ea0d74..087b2e7 100644 --- a/src/arch/arm/v7/helpers.h +++ b/src/arch/arm/v7/helpers.h @@ -25,6 +25,7 @@  #define _ARCH_ARM_V7_HELPERS_H +#include <stdbool.h>  #include <stdint.h> @@ -32,6 +33,9 @@ +/* Crée un opérande de valeur immédiate avec extension de signe. */ +GArchOperand *sign_extend_armv7_imm(uint32_t, bool, unsigned int); +  /* Crée un opérande représentant un registre ARMv7. */  GArchOperand *translate_armv7_register(uint8_t); diff --git a/src/arch/arm/v7/opcodes/Makefile.am b/src/arch/arm/v7/opcodes/Makefile.am index e77b7e8..dc5c8d9 100644 --- a/src/arch/arm/v7/opcodes/Makefile.am +++ b/src/arch/arm/v7/opcodes/Makefile.am @@ -2,6 +2,7 @@  noinst_LTLIBRARIES = libarcharmv7opcodes.la  libarcharmv7opcodes_la_SOURCES = 		\ +	bl.c								\  	mov.c								\  	subs.c diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am index f2c5a35..9aa6a82 100644 --- a/src/arch/arm/v7/opdefs/Makefile.am +++ b/src/arch/arm/v7/opdefs/Makefile.am @@ -17,9 +17,11 @@ D2C_MACROS =											\      -M SetFlags=g_armv7_instruction_define_setflags		\      -M Condition=g_arm_instruction_set_cond				\      -M Register=translate_armv7_register				\ -    -M "ExpandImmC32=g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, " +    -M "ExpandImmC32=g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, " \ +    -M SignExtend=sign_extend_armv7_imm  ARMV7_DEFS = 							\ +	bl_A8825.d							\  	mov_A88104.d						\  	subs_B9320.d diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d new file mode 100644 index 0000000..c9ef5d0 --- /dev/null +++ b/src/arch/arm/v7/opdefs/bl_A8825.d @@ -0,0 +1,84 @@ + +/* 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 BL, BLX (immediate) + +@encoding(T1) { + +    @word 1 1 1 1 0 S(1) imm10H(10) 1 1 J1(1) 1 J2(1) imm10L(10) H(1) + +    @syntax <imm32> + +    @conv { + +        I1 = NOT(J1 EOR S) +        I2 = NOT(J2 EOR S) +        imm32 = SignExtend(S:I1:I2:imm10H:imm10L:'00', s, 32) + +    } + +} + +@encoding(T2) { + +    @word 1 1 1 1 0 S(1) imm10(10) 1 1 J1(1) 0 J2(1) imm11(11) + +    @syntax <imm32> + +    @conv { + +        I1 = NOT(J1 EOR S) +        I2 = NOT(J2 EOR S) +        imm32 = SignExtend(S:I1:I2:imm10:imm11:'0', S, 32) + +    } + +} + +@encoding(A1) { + +    @word cond(4) 1 0 1 1 imm24(24) + +    @syntax <imm32> + +    @conv { + +        imm32 = SignExtend(imm24:'00', 0, 32) + +    } + +} + +@encoding(A2) { + +    @word cond(4) 1 0 1 H(1) imm24(24) + +    @syntax <imm32> + +    @conv { + +        imm32 = SignExtend(imm24:H:'0', 0, 32) + +    } + +}  | 
