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