From 224a2ef04e37cd180a58ede3469fddc59e39bc13 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 9 Dec 2014 23:07:29 +0000 Subject: Supported new ARMv7 instructions. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@438 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 35 +++ src/arch/arm/v7/helpers.h | 23 ++ src/arch/arm/v7/opcodes/Makefile.am | 15 ++ src/arch/arm/v7/opcodes/opcodes_tmp_arm.h | 1 - src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h | 5 - src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h | 4 - src/arch/arm/v7/opdefs/Makefile.am | 5 + src/arch/arm/v7/opdefs/ldrb_A8867.d | 121 +++++++++ src/arch/arm/v7/opdefs/nop_A88119.d | 50 ++++ src/arch/arm/v7/opdefs/pop_A88131.d | 87 +++++++ src/arch/arm/v7/opdefs/push_A88133.d | 128 ++++++++++ src/arch/arm/v7/opdefs/strb_A88206.d | 116 +++++++++ src/arch/arm/v7/operands/Makefile.am | 1 + src/arch/arm/v7/operands/reglist.c | 325 +++++++++++++++++++++++++ src/arch/arm/v7/operands/reglist.h | 72 ++++++ tools/d2c/d2c_tok.l | 4 +- 16 files changed, 980 insertions(+), 12 deletions(-) create mode 100644 src/arch/arm/v7/opdefs/ldrb_A8867.d create mode 100644 src/arch/arm/v7/opdefs/nop_A88119.d create mode 100644 src/arch/arm/v7/opdefs/pop_A88131.d create mode 100644 src/arch/arm/v7/opdefs/push_A88133.d create mode 100644 src/arch/arm/v7/opdefs/strb_A88206.d create mode 100644 src/arch/arm/v7/operands/reglist.c create mode 100644 src/arch/arm/v7/operands/reglist.h diff --git a/ChangeLog b/ChangeLog index 9157004..ca48b3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +14-12-09 Cyrille Bagard + + * src/arch/arm/v7/helpers.h: + Add some sugar for the lists of registers. + + * src/arch/arm/v7/opcodes/Makefile.am: + Update libarcharmv7opcodes_la_SOURCES. + + * src/arch/arm/v7/opcodes/opcodes_tmp_arm.h: + * src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h: + * src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h: + Update missing prototypes. + + * src/arch/arm/v7/opdefs/ldrb_A8867.d: + New entries: support new ARMv7 instructions. + + * src/arch/arm/v7/opdefs/Makefile.am: + Add new definitions to ARMV7_DEFS. + + * src/arch/arm/v7/opdefs/nop_A88119.d: + * src/arch/arm/v7/opdefs/pop_A88131.d: + * src/arch/arm/v7/opdefs/push_A88133.d: + * src/arch/arm/v7/opdefs/strb_A88206.d: + New entries: support new ARMv7 instructions. + + * src/arch/arm/v7/operands/Makefile.am: + Add the 'reglist.[ch]' files to libarcharmv7operands_la_SOURCES. + + * src/arch/arm/v7/operands/reglist.c: + * src/arch/arm/v7/operands/reglist.h: + New entries: handle list of ARM regisers. + + * tools/d2c/d2c_tok.l: + Allow underscores in more names. + 14-12-08 Cyrille Bagard * src/arch/arm/v7/helpers.h: diff --git a/src/arch/arm/v7/helpers.h b/src/arch/arm/v7/helpers.h index fee5aea..919611e 100644 --- a/src/arch/arm/v7/helpers.h +++ b/src/arch/arm/v7/helpers.h @@ -31,6 +31,7 @@ #include "pseudo.h" #include "operands/maccess.h" #include "operands/offset.h" +#include "operands/reglist.h" #include "operands/shift.h" #include "../../operand.h" @@ -188,8 +189,30 @@ return shift_t; +/** + * Glue purement interne pour les listes de registres. + */ + +#define RegistersList(mask) \ + ({ \ + GArchOperand *__result; \ + __result = g_armv7_reglist_operand_new(); \ + if (!g_armv7_reglist_load_registers(G_ARMV7_REGLIST_OPERAND(__result), mask)) \ + { \ + g_object_unref(G_OBJECT(__result)); \ + __result = NULL; \ + } \ + __result; \ + }) +#define ListFromRegister(reg) \ + ({ \ + GArchOperand *__result; \ + __result = g_armv7_reglist_operand_new(); \ + g_armv7_reglist_add_register(G_ARMV7_REGLIST_OPERAND(__result), reg); \ + __result; \ + }) diff --git a/src/arch/arm/v7/opcodes/Makefile.am b/src/arch/arm/v7/opcodes/Makefile.am index be437b9..0bff196 100644 --- a/src/arch/arm/v7/opcodes/Makefile.am +++ b/src/arch/arm/v7/opcodes/Makefile.am @@ -15,19 +15,24 @@ libarcharmv7opcodes_la_SOURCES = \ arm_cmp.c \ arm_eor.c \ arm_ldr.c \ + arm_ldrb.c \ arm_lsl.c \ arm_mla.c \ arm_mls.c \ arm_mov.c \ arm_mul.c \ arm_mvn.c \ + arm_nop.c \ arm_orr.c \ + arm_pop.c \ + arm_push.c \ arm_rsb.c \ arm_rsc.c \ arm_sbc.c \ arm_smlal.c \ arm_smull.c \ arm_str.c \ + arm_strb.c \ arm_sub.c \ arm_subs.c \ arm_teq.c \ @@ -48,19 +53,24 @@ libarcharmv7opcodes_la_SOURCES = \ thumb_16_cmp.c \ thumb_16_eor.c \ thumb_16_ldr.c \ + thumb_16_ldrb.c \ thumb_16_lsl.c \ thumb_16_mla.c \ thumb_16_mls.c \ thumb_16_mov.c \ thumb_16_mul.c \ thumb_16_mvn.c \ + thumb_16_nop.c \ thumb_16_orr.c \ + thumb_16_pop.c \ + thumb_16_push.c \ thumb_16_rsb.c \ thumb_16_rsc.c \ thumb_16_sbc.c \ thumb_16_smlal.c \ thumb_16_smull.c \ thumb_16_str.c \ + thumb_16_strb.c \ thumb_16_sub.c \ thumb_16_subs.c \ thumb_16_teq.c \ @@ -81,19 +91,24 @@ libarcharmv7opcodes_la_SOURCES = \ thumb_32_cmp.c \ thumb_32_eor.c \ thumb_32_ldr.c \ + thumb_32_ldrb.c \ thumb_32_lsl.c \ thumb_32_mla.c \ thumb_32_mls.c \ thumb_32_mov.c \ thumb_32_mul.c \ thumb_32_mvn.c \ + thumb_32_nop.c \ thumb_32_orr.c \ + thumb_32_pop.c \ + thumb_32_push.c \ thumb_32_rsb.c \ thumb_32_rsc.c \ thumb_32_sbc.c \ thumb_32_smlal.c \ thumb_32_smull.c \ thumb_32_str.c \ + thumb_32_strb.c \ thumb_32_sub.c \ thumb_32_subs.c \ thumb_32_teq.c \ diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h index 1cd3e24..612b45e 100644 --- a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h +++ b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h @@ -11,7 +11,6 @@ #define armv7_read_arm_instr_lsr_immediate(r) NULL #define armv7_read_arm_instr_movt(r) NULL #define armv7_read_arm_instr_pop_arm(r) NULL -#define armv7_read_arm_instr_push(r) NULL #define armv7_read_arm_instr_ror_immediate(r) NULL #define armv7_read_arm_instr_rrx(r) NULL #define armv7_read_arm_instr_stmda_stmed(r) NULL diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h b/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h index f9ef7d9..fe67305 100644 --- a/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h +++ b/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h @@ -17,7 +17,6 @@ #define armv7_read_thumb_16_instr_eor_register(r) NULL #define armv7_read_thumb_16_instr_it(r) NULL #define armv7_read_thumb_16_instr_ldm_ldmia_ldmfd_thumb(r) NULL -#define armv7_read_thumb_16_instr_ldrb_immediate_thumb(r) NULL #define armv7_read_thumb_16_instr_ldrb_register(r) NULL #define armv7_read_thumb_16_instr_ldrh_immediate_thumb(r) NULL #define armv7_read_thumb_16_instr_ldrh_register(r) NULL @@ -28,10 +27,7 @@ #define armv7_read_thumb_16_instr_lsr_register(r) NULL #define armv7_read_thumb_16_instr_mul(r) NULL #define armv7_read_thumb_16_instr_mvn_register(r) NULL -#define armv7_read_thumb_16_instr_nop(r) NULL #define armv7_read_thumb_16_instr_orr_register(r) NULL -#define armv7_read_thumb_16_instr_pop_thumb(r) NULL -#define armv7_read_thumb_16_instr_push(r) NULL #define armv7_read_thumb_16_instr_rev(r) NULL #define armv7_read_thumb_16_instr_rev16(r) NULL #define armv7_read_thumb_16_instr_revsh(r) NULL @@ -41,7 +37,6 @@ #define armv7_read_thumb_16_instr_setend(r) NULL #define armv7_read_thumb_16_instr_sev(r) NULL #define armv7_read_thumb_16_instr_stm_stmia_stmea(r) NULL -#define armv7_read_thumb_16_instr_strb_immediate_thumb(r) NULL #define armv7_read_thumb_16_instr_strb_register(r) NULL #define armv7_read_thumb_16_instr_strh_immediate_thumb(r) NULL #define armv7_read_thumb_16_instr_strh_register(r) NULL diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h b/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h index 966d6a2..1f0abb9 100644 --- a/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h +++ b/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h @@ -28,12 +28,9 @@ #define armv7_read_thumb_32_instr_mrs_banked_register(r) NULL #define armv7_read_thumb_32_instr_msr_banked_register(r) NULL #define armv7_read_thumb_32_instr_msr_register(r) NULL -#define armv7_read_thumb_32_instr_nop(r) NULL #define armv7_read_thumb_32_instr_orn_immediate(r) NULL #define armv7_read_thumb_32_instr_orn_register(r) NULL #define armv7_read_thumb_32_instr_pkh(r) NULL -#define armv7_read_thumb_32_instr_pop_thumb(r) NULL -#define armv7_read_thumb_32_instr_push(r) NULL #define armv7_read_thumb_32_instr_qadd(r) NULL #define armv7_read_thumb_32_instr_qdadd(r) NULL #define armv7_read_thumb_32_instr_qdsub(r) NULL @@ -86,7 +83,6 @@ #define armv7_read_thumb_32_instr_ssub8(r) NULL #define armv7_read_thumb_32_instr_stmdb_stmfd(r) NULL #define armv7_read_thumb_32_instr_stm_stmia_stmea(r) NULL -#define armv7_read_thumb_32_instr_strb_immediate_thumb(r) NULL #define armv7_read_thumb_32_instr_strb_register(r) NULL #define armv7_read_thumb_32_instr_strbt(r) NULL #define armv7_read_thumb_32_instr_strh_immediate_thumb(r) NULL diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am index 948c9da..a24e706 100644 --- a/src/arch/arm/v7/opdefs/Makefile.am +++ b/src/arch/arm/v7/opdefs/Makefile.am @@ -44,6 +44,7 @@ ARMV7_DEFS = \ ldr_A8862.d \ ldr_A8864.d \ ldr_A8865.d \ + ldrb_A8867.d \ lsl_A8894.d \ mla_A88100.d \ mls_A88101.d \ @@ -53,8 +54,11 @@ ARMV7_DEFS = \ mul_A88114.d \ mvn_A88115.d \ mvn_A88116.d \ + nop_A88119.d \ orr_A88122.d \ orr_A88123.d \ + pop_A88131.d \ + push_A88133.d \ rsb_A88152.d \ rsb_A88153.d \ rsc_A88155.d \ @@ -64,6 +68,7 @@ ARMV7_DEFS = \ smlal_A88178.d \ smull_A88189.d \ str_A88203.d \ + strb_A88206.d \ sub_A88222.d \ sub_A88223.d \ teq_A88237.d \ diff --git a/src/arch/arm/v7/opdefs/ldrb_A8867.d b/src/arch/arm/v7/opdefs/ldrb_A8867.d new file mode 100644 index 0000000..8097fd0 --- /dev/null +++ b/src/arch/arm/v7/opdefs/ldrb_A8867.d @@ -0,0 +1,121 @@ + +/* 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 . + */ + + +@title LDRB (immediate, Thumb) + +@encoding(t1) { + + @half 0 1 1 1 1 imm5(5) Rn(3) Rt(3) + + @syntax , + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm5, 5, 32) + access = MakeMemoryAccess(Rgn, imm32, 1, 0) + + } + +} + +@encoding(T2) { + + @word 1 1 1 1 1 0 0 0 1 0 0 1 Rn(4) Rt(4) imm12(12) + + @syntax "ldrb.W" , + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm12, 12, 32) + access = MakeMemoryAccess(Rgn, imm32, 1, 0) + + } + + @rules { + + //if Rt == '1111' then SEE PLD; + //if Rn == '1111' then SEE LDRB (literal); + //if t == 13 then UNPREDICTABLE; + + } + +} + +@encoding(T31) { + + @word 1 1 1 1 1 0 0 0 0 0 0 1 Rn(4) Rt(4) 1 1 U(1) W(1) imm8(8) + + @syntax + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm8, 8, 32); + access = MakeMemoryAccess(Rgn, imm32, U, W) + + } + + @rules { + + //if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD, PLDW (immediate); + //if Rn == '1111' then SEE LDRB (literal); + //if P == '1' && U == '1' && W == '0' then SEE LDRBT; + //if P == '0' && W == '0' then UNDEFINED; + //if t == 13 || (t == 15 && W == '1') || (wback && n == t) then UNPREDICTABLE; + + } + +} + +@encoding(T32) { + + @word 1 1 1 1 1 0 0 0 0 0 0 1 Rn(4) Rt(4) 1 0 U(1) W(1) imm8(8) + + @syntax + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm8, 8, 32); + base = MakeMemoryNotIndexed(Rgn, W) + offset = MakeAccessOffset(U, imm32) + + } + + @rules { + + //if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD, PLDW (immediate); + //if Rn == '1111' then SEE LDRB (literal); + //if P == '1' && U == '1' && W == '0' then SEE LDRBT; + //if P == '0' && W == '0' then UNDEFINED; + //if t == 13 || (t == 15 && W == '1') || (wback && n == t) then UNPREDICTABLE; + + } + +} diff --git a/src/arch/arm/v7/opdefs/nop_A88119.d b/src/arch/arm/v7/opdefs/nop_A88119.d new file mode 100644 index 0000000..d47c346 --- /dev/null +++ b/src/arch/arm/v7/opdefs/nop_A88119.d @@ -0,0 +1,50 @@ + +/* 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 . + */ + + +@title NOP + +@encoding(t1) { + + @half 1 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 + +} + +@encoding(T2) { + + @word 1 1 1 1 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + +} + +@encoding(A1) { + + @word cond(4) 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 + + @syntax {c} + + @conv { + + c = Condition(cond) + + } + +} diff --git a/src/arch/arm/v7/opdefs/pop_A88131.d b/src/arch/arm/v7/opdefs/pop_A88131.d new file mode 100644 index 0000000..329b705 --- /dev/null +++ b/src/arch/arm/v7/opdefs/pop_A88131.d @@ -0,0 +1,87 @@ + +/* 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 . + */ + + +@title POP (Thumb) + +@encoding(t1) { + + @half 1 0 1 1 1 1 0 P(1) register_list(8) + + @syntax + + @conv { + + registers = RegistersList(P:'0000000':register_list) + + } + + @rules { + + //if BitCount(registers) < 1 then UNPREDICTABLE; + //if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + + } + +} + +@encoding(T2) { + + @word 1 1 1 0 1 0 0 0 1 0 1 1 1 1 0 1 P(1) M(1) 0 register_list(13) + + @syntax "push.W" + + @conv { + + registers = RegistersList(P:M:'0':register_list) + + } + + @rules { + + //if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; + //if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + + } + +} + +@encoding(T3) { + + @word 1 1 1 1 1 0 0 0 0 1 0 1 1 1 0 1 Rt(4) 1 0 1 1 0 0 0 0 0 1 0 0 + + @syntax "push.W" + + @conv { + + Rgt = Register(Rt) + registers = ListFromRegister(Rgt) + + } + + @rules { + + //if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; + + } + +} diff --git a/src/arch/arm/v7/opdefs/push_A88133.d b/src/arch/arm/v7/opdefs/push_A88133.d new file mode 100644 index 0000000..0526a56 --- /dev/null +++ b/src/arch/arm/v7/opdefs/push_A88133.d @@ -0,0 +1,128 @@ + +/* 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 . + */ + + +@title PUSH + +@encoding(t1) { + + @half 1 0 1 1 0 1 0 M(1) register_list(8) + + @syntax + + @conv { + + registers = RegistersList('0':M:'000000':register_list) + + } + + @rules { + + //if BitCount(registers) < 1 then UNPREDICTABLE; + + } + +} + +@encoding(T2) { + + @word 1 1 1 0 1 0 0 1 0 0 1 0 1 1 0 1 0 M(1) 0 register_list(13) + + @syntax "push.W" + + @conv { + + registers = RegistersList('0':M:'0':register_list) + + } + + @rules { + + //if BitCount(registers) < 2 then UNPREDICTABLE; + + } + +} + +@encoding(T3) { + + @word 1 1 1 1 1 0 0 0 0 1 0 0 1 1 0 1 Rt(4) 1 1 0 1 0 0 0 0 0 1 0 0 + + @syntax "push.W" + + @conv { + + Rgt = Register(Rt) + registers = ListFromRegister(Rgt) + + } + + @rules { + + //if t IN {13,15} then UNPREDICTABLE + + } + +} + +@encoding(A1) { + + @word cond(4) 1 0 0 1 0 0 1 0 1 1 0 1 register_list(16) + + @syntax {c} + + @conv { + + c = Condition(cond) + registers = RegistersList(register_list) + + } + + @rules { + + //if BitCount(register_list) < 2 then SEE STMDB / STMFD; + + } + +} + +@encoding(A2) { + + @word cond(4) 0 1 0 1 0 0 1 0 1 1 0 1 Rt(4) 0 0 0 0 0 0 0 0 0 1 0 0 + + @syntax {c} + + @conv { + + c = Condition(cond) + Rgt = Register(Rt) + registers = ListFromRegister(Rgt) + + } + + @rules { + + //if t == 13 then UNPREDICTABLE; + + } + +} diff --git a/src/arch/arm/v7/opdefs/strb_A88206.d b/src/arch/arm/v7/opdefs/strb_A88206.d new file mode 100644 index 0000000..4799f61 --- /dev/null +++ b/src/arch/arm/v7/opdefs/strb_A88206.d @@ -0,0 +1,116 @@ + +/* 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 . + */ + + +@title STRB (immediate, Thumb) + +@encoding(t1) { + + @half 0 1 1 1 0 imm5(5) Rn(3) Rt(3) + + @syntax , + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm5, 5, 32) + access = MakeMemoryAccess(Rgn, imm32, 1, 0) + + } + +} + +@encoding(T2) { + + @word 1 1 1 1 1 0 0 0 1 0 0 0 Rn(4) Rt(4) imm12(12) + + @syntax "strb.W" , + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm12, 12, 32) + access = MakeMemoryAccess(Rgn, imm32, 1, 0) + + } + + @rules { + + //if Rn == '1111' then UNDEFINED; + //if t IN {13,15} then UNPREDICTABLE; + + } + +} + +@encoding(T31) { + + @word 1 1 1 1 1 0 0 0 0 0 0 0 Rn(4) Rt(4) 1 1 U(1) W(1) imm8(8) + + @syntax + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm8, 8, 32); + access = MakeMemoryAccess(Rgn, imm32, U, W) + + } + + @rules { + + //if P == '1' && U == '1' && W == '0' then SEE STRBT; + //if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; + //if t IN {13,15} || (wback && n == t) then UNPREDICTABLE; + + } + +} + +@encoding(T32) { + + @word 1 1 1 1 1 0 0 0 0 0 0 0 Rn(4) Rt(4) 1 0 U(1) W(1) imm8(8) + + @syntax + + @conv { + + Rgt = Register(Rt) + Rgn = Register(Rn) + imm32 = ZeroExtend(imm8, 8, 32); + base = MakeMemoryNotIndexed(Rgn, W) + offset = MakeAccessOffset(U, imm32) + + } + + @rules { + + //if P == '1' && U == '1' && W == '0' then SEE STRBT; + //if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; + //if t IN {13,15} || (wback && n == t) then UNPREDICTABLE; + + } + +} diff --git a/src/arch/arm/v7/operands/Makefile.am b/src/arch/arm/v7/operands/Makefile.am index 8733bfe..32648c9 100644 --- a/src/arch/arm/v7/operands/Makefile.am +++ b/src/arch/arm/v7/operands/Makefile.am @@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libarcharmv7operands.la libarcharmv7operands_la_SOURCES = \ maccess.h maccess.c \ offset.h offset.c \ + reglist.h reglist.c \ shift.h shift.c libarcharmv7operands_la_LIBADD = diff --git a/src/arch/arm/v7/operands/reglist.c b/src/arch/arm/v7/operands/reglist.c new file mode 100644 index 0000000..a54d148 --- /dev/null +++ b/src/arch/arm/v7/operands/reglist.c @@ -0,0 +1,325 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * reglist.c - accès à la mémorie à partir d'un registre et d'un décallage + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 . + */ + + +#include "reglist.h" + + +#include +#include + + +#include "../../../operand-int.h" +#include "../../../register.h" + + + +/* Définition d'un opérande listant une série de registres ARM (instance) */ +struct _GArmV7RegListOperand +{ + GArchOperand parent; /* Instance parente */ + + GArmV7Register **registers; /* Liste de registres intégrés */ + size_t count; /* Taille de cette liste */ + +}; + + +/* Définition d'un opérande listant une série de registres ARM (classe) */ +struct _GArmV7RegListOperandClass +{ + GArchOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des listes de registres ARM. */ +static void g_armv7_reglist_operand_class_init(GArmV7RegListOperandClass *); + +/* Initialise une instance de liste de registres ARM. */ +static void g_armv7_reglist_operand_init(GArmV7RegListOperand *); + +/* Supprime toutes les références externes. */ +static void g_armv7_reglist_operand_dispose(GArmV7RegListOperand *); + +/* Procède à la libération totale de la mémoire. */ +static void g_armv7_reglist_operand_finalize(GArmV7RegListOperand *); + +/* Traduit un opérande en version humainement lisible. */ +static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *, GBufferLine *, AsmSyntax); + + + +/* Indique le type défini par la GLib pour une liste de registres ARM. */ +G_DEFINE_TYPE(GArmV7RegListOperand, g_armv7_reglist_operand, G_TYPE_ARCH_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des listes de registres ARM. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_reglist_operand_class_init(GArmV7RegListOperandClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + GArchOperandClass *operand; /* Version de classe parente */ + + object = G_OBJECT_CLASS(klass); + operand = G_ARCH_OPERAND_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_reglist_operand_dispose; + object->finalize = (GObjectFinalizeFunc)g_armv7_reglist_operand_finalize; + + operand->print = (operand_print_fc)g_armv7_reglist_operand_print; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance de liste de registres ARM. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_reglist_operand_init(GArmV7RegListOperand *operand) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_reglist_operand_dispose(GArmV7RegListOperand *operand) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < operand->count; i++) + g_object_unref(G_OBJECT(operand->registers[i])); + + G_OBJECT_CLASS(g_armv7_reglist_operand_parent_class)->dispose(G_OBJECT(operand)); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_reglist_operand_finalize(GArmV7RegListOperand *operand) +{ + if (operand->registers != NULL) + free(operand->registers); + + G_OBJECT_CLASS(g_armv7_reglist_operand_parent_class)->finalize(G_OBJECT(operand)); + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une liste vierge de registres ARM. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_armv7_reglist_operand_new(void) +{ + GArmV7RegListOperand *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ARMV7_REGLIST_OPERAND, NULL); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *operand, GBufferLine *line, AsmSyntax syntax) +{ + size_t i; /* Boucle de parcours */ + + g_buffer_line_insert_text(line, BLC_ASSEMBLY, "{", 1, RTT_HOOK); + + for (i = 0; i < operand->count; i++) + { + if (i > 0) + { + g_buffer_line_insert_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT); + g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW); + } + + g_arch_register_print(G_ARCH_REGISTER(operand->registers[i]), line, syntax); + + } + + g_buffer_line_insert_text(line, BLC_ASSEMBLY, "}", 1, RTT_HOOK); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = liste de registres à compléter. * +* selected = masque de bits pour les registres à intégrer. * +* * +* Description : Remplit une liste de registres de registres ARM. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_armv7_reglist_load_registers(GArmV7RegListOperand *operand, uint32_t selected) +{ + uint8_t i; /* Boucle de parcours */ + GArmV7Register *reg; /* Nouveau registre à intégrer */ + + for (i = 18; i < 32; i++) + if (selected & (1 << i)) return false; + + for (i = 0; i < 18; i++) + { + if ((selected & (1 << i)) == 0) continue; + + reg = g_armv7_register_new(i); + g_armv7_reglist_add_register(operand, reg); + + } + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = liste de registres à compléter. * +* reg = nouveau registre à intégrer. * +* * +* Description : Ajoute un registre à une liste de registres ARM. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_armv7_reglist_add_register(GArmV7RegListOperand *operand, GArmV7Register *reg) +{ + operand->registers = (GArmV7Register **)realloc(operand->registers, + ++operand->count * sizeof(GArmV7Register *)); + + operand->registers[operand->count - 1] = reg; + +} + + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à consulter. * +* * +* Description : Compte le nombre de registres ARM composant la liste. * +* * +* Retour : Nombre positif ou nul. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_armv7_reglist_count_registers(const GArmV7RegListOperand *operand) +{ + return operand->count; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à consulter. * +* index = indice de l'élément à fournier. * +* * +* Description : Founit un élément donné d'une liste de registres ARM. * +* * +* Retour : Registre intégré à la liste manipulée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArmV7Register *g_armv7_reglist_operand_get_register(const GArmV7RegListOperand *operand, size_t index) +{ + assert(index < operand->count); + + return operand->registers[index]; + +} diff --git a/src/arch/arm/v7/operands/reglist.h b/src/arch/arm/v7/operands/reglist.h new file mode 100644 index 0000000..cf0b9c0 --- /dev/null +++ b/src/arch/arm/v7/operands/reglist.h @@ -0,0 +1,72 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * reglist.h - prototypes pour les accès à la mémorie à partir d'un registre et d'un décallage + * + * Copyright (C) 2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 . + */ + + +#ifndef _ARCH_ARM_V7_OPERANDS_REGLIST_H +#define _ARCH_ARM_V7_OPERANDS_REGLIST_H + + +#include +#include + + +#include "../register.h" +#include "../../../operand.h" + + + +#define G_TYPE_ARMV7_REGLIST_OPERAND g_armv7_reglist_operand_get_type() +#define G_ARMV7_REGLIST_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_reglist_operand_get_type(), GArmV7RegListOperand)) +#define G_IS_ARMV7_REGLIST_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_reglist_operand_get_type())) +#define G_ARMV7_REGLIST_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperandClass)) +#define G_IS_ARMV7_REGLIST_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_REGLIST_OPERAND)) +#define G_ARMV7_REGLIST_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperandClass)) + + +/* Définition d'un opérande listant une série de registres ARM (instance) */ +typedef struct _GArmV7RegListOperand GArmV7RegListOperand; + +/* Définition d'un opérande listant une série de registres ARM (classe) */ +typedef struct _GArmV7RegListOperandClass GArmV7RegListOperandClass; + + +/* Indique le type défini par la GLib pour une liste de registres ARM. */ +GType g_armv7_reglist_operand_get_type(void); + +/* Crée une liste vierge de registres ARM. */ +GArchOperand *g_armv7_reglist_operand_new(void); + +/* Remplit une liste de registres de registres ARM. */ +bool g_armv7_reglist_load_registers(GArmV7RegListOperand *, uint32_t); + +/* Ajoute un registre à une liste de registres ARM. */ +void g_armv7_reglist_add_register(GArmV7RegListOperand *, GArmV7Register *); + +/* Compte le nombre de registres ARM composant la liste. */ +size_t g_armv7_reglist_count_registers(const GArmV7RegListOperand *); + +/* Founit un élément donné d'une liste de registres ARM. */ +GArmV7Register *g_armv7_reglist_operand_get_register(const GArmV7RegListOperand *, size_t ); + + + +#endif /* _ARCH_ARM_V7_OPERANDS_REGLIST_H */ diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l index b7e50fd..71f1a15 100644 --- a/tools/d2c/d2c_tok.l +++ b/tools/d2c/d2c_tok.l @@ -80,7 +80,7 @@ void free_flex_memory(void) ; " " { } "\n" { BEGIN(encoding_content); } -[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return NAME; } +[A-Za-z][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; } "(" { BEGIN(encoding_bits_size); } [0-9]+ { d2c_lval.integer = atoi(yytext); return SIZE; } @@ -125,7 +125,7 @@ void free_flex_memory(void) ; } "=" { return EQ; } "(" { BEGIN(conv_arg); return OP; } -[A-Za-z][A-Za-z0-9]* { +[A-Za-z][A-Za-z0-9_]* { if (strcmp(yytext, "NOT") == 0) return NOT; else if (strcmp(yytext, "EOR") == 0) return EOR; else -- cgit v0.11.2-87-g4458