From e5314b83cf2521f4a1fee5d3cbb5011d7ac7bff7 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 30 Jun 2013 13:01:38 +0000 Subject: Provided first basic support for a few ARM instructions. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@354 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 31 ++ configure.ac | 2 + src/arch/arm/Makefile.am | 8 +- src/arch/arm/encoding.h | 70 ++++ src/arch/arm/instruction-int.h | 48 +++ src/arch/arm/instruction.c | 128 ++++++ src/arch/arm/instruction.h | 62 +++ src/arch/arm/processor.c | 24 +- src/arch/arm/v456/Makefile.am | 24 ++ src/arch/arm/v456/addressing.c | 82 ++++ src/arch/arm/v456/addressing.h | 38 ++ src/arch/arm/v456/encoding.h | 188 +++++++++ src/arch/arm/v456/instruction-def.h | 91 +++++ src/arch/arm/v456/instruction.c | 683 +++++++++++++++++++++++++++++++++ src/arch/arm/v456/instruction.h | 105 +++++ src/arch/arm/v456/operands/Makefile.am | 18 + src/arch/arm/v456/operands/content.c | 257 +++++++++++++ src/arch/arm/v456/operands/content.h | 70 ++++ src/arch/arm/v456/operands/register.c | 232 +++++++++++ src/arch/arm/v456/operands/register.h | 69 ++++ src/arch/arm/v456/register.c | 251 ++++++++++++ src/arch/arm/v456/register.h | 69 ++++ src/arch/immediate.c | 60 ++- src/arch/immediate.h | 3 + 24 files changed, 2607 insertions(+), 6 deletions(-) create mode 100644 src/arch/arm/encoding.h create mode 100644 src/arch/arm/instruction-int.h create mode 100644 src/arch/arm/instruction.c create mode 100644 src/arch/arm/instruction.h create mode 100644 src/arch/arm/v456/Makefile.am create mode 100644 src/arch/arm/v456/addressing.c create mode 100644 src/arch/arm/v456/addressing.h create mode 100644 src/arch/arm/v456/encoding.h create mode 100644 src/arch/arm/v456/instruction-def.h create mode 100644 src/arch/arm/v456/instruction.c create mode 100644 src/arch/arm/v456/instruction.h create mode 100644 src/arch/arm/v456/operands/Makefile.am create mode 100644 src/arch/arm/v456/operands/content.c create mode 100644 src/arch/arm/v456/operands/content.h create mode 100644 src/arch/arm/v456/operands/register.c create mode 100644 src/arch/arm/v456/operands/register.h create mode 100644 src/arch/arm/v456/register.c create mode 100644 src/arch/arm/v456/register.h diff --git a/ChangeLog b/ChangeLog index 12453be..042cfaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +13-06-30 Cyrille Bagard + + * configure.ac: + Add various Makefiles for ARM to AC_CONFIG_FILES. + + * src/arch/arm/encoding.h: + * src/arch/arm/instruction.c: + * src/arch/arm/instruction.h: + * src/arch/arm/instruction-int.h: + * src/arch/arm/Makefile.am: + * src/arch/arm/processor.c: + * src/arch/arm/v456/addressing.c: + * src/arch/arm/v456/addressing.h: + * src/arch/arm/v456/encoding.h: + * src/arch/arm/v456/instruction.c: + * src/arch/arm/v456/instruction-def.h: + * src/arch/arm/v456/instruction.h: + * src/arch/arm/v456/Makefile.am: + * src/arch/arm/v456/operands/content.c: + * src/arch/arm/v456/operands/content.h: + * src/arch/arm/v456/operands/Makefile.am: + * src/arch/arm/v456/operands/register.c: + * src/arch/arm/v456/operands/register.h: + * src/arch/arm/v456/register.c: + * src/arch/arm/v456/register.h: + Provide first basic support for a few ARM instructions. + + * src/arch/immediate.c: + * src/arch/immediate.h: + Tell if a value is null or not. + 13-06-14 Cyrille Bagard * configure.ac: diff --git a/configure.ac b/configure.ac index cbd1d3c..92fb005 100644 --- a/configure.ac +++ b/configure.ac @@ -269,6 +269,8 @@ AC_CONFIG_FILES([Makefile src/analysis/types/Makefile src/arch/Makefile src/arch/arm/Makefile + src/arch/arm/v456/Makefile + src/arch/arm/v456/operands/Makefile src/arch/dalvik/Makefile src/arch/dalvik/decomp/Makefile src/arch/dalvik/opcodes/Makefile diff --git a/src/arch/arm/Makefile.am b/src/arch/arm/Makefile.am index f97d24a..16860e3 100644 --- a/src/arch/arm/Makefile.am +++ b/src/arch/arm/Makefile.am @@ -2,8 +2,14 @@ noinst_LTLIBRARIES = libarcharm.la libarcharm_la_SOURCES = \ + encoding.h \ + instruction-int.h \ + instruction.h instruction.c \ processor.h processor.c +libarcharm_la_LIBADD = \ + v456/libarcharmv456.la + libarcharm_la_CFLAGS = $(AM_CFLAGS) @@ -14,4 +20,4 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = +SUBDIRS = v456 diff --git a/src/arch/arm/encoding.h b/src/arch/arm/encoding.h new file mode 100644 index 0000000..35685dd --- /dev/null +++ b/src/arch/arm/encoding.h @@ -0,0 +1,70 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * encoding.h - prototypes pour le décodage des instructions ARM + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_ENCODING_H +#define _ARCH_ARM_ENCODING_H + + + + + + + +/** + * ARMv8 Instruction Set Overview. + * § 4.3 Condition Codes. + */ + + +/* Liste des conditions possibles */ +typedef enum _ArmCondCode +{ + ACC_EQ = 0x0, /* Equal */ + ACC_NE = 0x1, /* Not equal */ + ACC_HS = 0x2, /* Unsigned higher or same */ + ACC_LO = 0x2, /* Unsigned lower */ + ACC_MI = 0x3, /* Minus */ + ACC_PL = 0x4, /* Plus or zero */ + ACC_VS = 0x5, /* Overflow set */ + ACC_VC = 0x6, /* Overflow clear */ + ACC_HI = 0x7, /* Unsigned higher */ + ACC_LS = 0x9, /* Unsigned lower or same */ + ACC_GE = 0xa, /* Signed greater than or equal*/ + ACC_LT = 0xb, /* Signed less than */ + ACC_GT = 0xc, /* Signed greater than */ + ACC_LE = 0xd, /* Signed less than or equal */ + ACC_AL = 0xe, /* Always */ + ACC_NV = 0xf, /* (Never) */ + +} ArmCondCode; + + + +#define INSTR_TO_COND(i) (((i) & 0xf0000000) >> 28) + + + + + + +#endif /* _ARCH_ARM_ENCODING_H */ diff --git a/src/arch/arm/instruction-int.h b/src/arch/arm/instruction-int.h new file mode 100644 index 0000000..b54782b --- /dev/null +++ b/src/arch/arm/instruction-int.h @@ -0,0 +1,48 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction-int.h - prototypes pour la définition générique interne des instructions ARM + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_INSTRUCTION_INT_H +#define _ARCH_ARM_INSTRUCTION_INT_H + + +#include "../instruction-int.h" + + + +/* Définition générique d'une instruction d'architecture ARM (instance) */ +struct _GArmInstruction +{ + GArchInstruction parent; /* A laisser en premier */ + +}; + +/* Définition générique d'une instruction d'architecture ARM (classe) */ +struct _GArmInstructionClass +{ + GArchInstructionClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _ARCH_ARM_INSTRUCTION_INT_H */ diff --git a/src/arch/arm/instruction.c b/src/arch/arm/instruction.c new file mode 100644 index 0000000..eb67e4f --- /dev/null +++ b/src/arch/arm/instruction.c @@ -0,0 +1,128 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.c - gestion des instructions de la ARM + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "instruction.h" + + +#include "instruction-int.h" + + + + + +/* Initialise la classe des instructions pour Arm. */ +static void g_arm_instruction_class_init(GArmInstructionClass *); + +/* Initialise une instance d'opérande d'architecture Arm. */ +static void g_arm_instruction_init(GArmInstruction *); + + + + + + +/* Indique le type défini pour une instruction d'architecture Arm. */ +G_DEFINE_TYPE(GArmInstruction, g_arm_instruction, G_TYPE_ARCH_INSTRUCTION); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des instructions pour ARM. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arm_instruction_class_init(GArmInstructionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser. * +* * +* Description : Initialise une instance d'instruction d'architecture ARM. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arm_instruction_init(GArmInstruction *instr) +{ + GArchInstruction *parent; /* Instance parente */ + + parent = G_ARCH_INSTRUCTION(instr); + + /* ... TODO ! */ + +} + + + + +/* ---------------------------------------------------------------------------------- */ +/* AIDE A LA MISE EN PLACE D'INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + + +#if 0 + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. * +* len = taille totale des données à analyser. * +* * +* Description : Recherche l'identifiant de la prochaine instruction. * +* * +* Retour : Identifiant de la prochaine instruction à tenter de charger. * +* * +* Remarques : - * +* * +******************************************************************************/ + +ArmOpcodes arm_guess_next_instruction(const bin_t *data, off_t pos, off_t len) +{ + ArmOpcodes result; /* Identifiant à retourner */ + + result = (ArmOpcodes)data[pos]; + + /* Si l'instruction est marquée comme non utilisée... */ + if (_instructions[result].keyword == NULL) + result = DOP_COUNT; + + return result; + +} + +#endif diff --git a/src/arch/arm/instruction.h b/src/arch/arm/instruction.h new file mode 100644 index 0000000..1e03523 --- /dev/null +++ b/src/arch/arm/instruction.h @@ -0,0 +1,62 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.h - prototypes pour la gestion des instructions ARM + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_INSTRUCTION_H +#define _ARCH_ARM_INSTRUCTION_H + + +#include "../instruction.h" + + + +#define G_TYPE_ARM_INSTRUCTION g_arm_instruction_get_type() +#define G_ARM_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arm_instruction_get_type(), GArmInstruction)) +#define G_IS_ARM_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arm_instruction_get_type())) +#define G_ARM_INSTRUCTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_arm_instruction_get_type(), GArmInstructionIface)) + + +/* Définition générique d'une instruction d'architecture ARM (instance) */ +typedef struct _GArmInstruction GArmInstruction; + +/* Définition générique d'une instruction d'architecture ARM (classe) */ +typedef struct _GArmInstructionClass GArmInstructionClass; + + +/* Indique le type défini pour une instruction d'architecture ARM. */ +GType g_arm_instruction_get_type(void); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Recherche l'identifiant de la prochaine instruction. */ +//ArmOpcodes arm_guess_next_instruction(const bin_t *, off_t, off_t); + + + +/* ------------------------ AIDE A LA PHASE DE DECOMPILATION ------------------------ */ + + + +#endif /* _ARCH_ARM_INSTRUCTION_H */ diff --git a/src/arch/arm/processor.c b/src/arch/arm/processor.c index 79a44fe..baf13ab 100644 --- a/src/arch/arm/processor.c +++ b/src/arch/arm/processor.c @@ -53,7 +53,7 @@ static void g_arm_processor_class_init(GArmProcessorClass *); static void g_arm_processor_init(GArmProcessor *); /* Décode une instruction dans un flux de données. */ -static GArchInstruction *g_arm_processor_decode_instruction(const GArmProcessor *, const bin_t *, off_t *, off_t, vmpa_t); +static GArchInstruction *g_arm_processor_decode_instruction(const GArmProcessor *, GProcContext *, const bin_t *, off_t *, off_t, vmpa_t, GBinFormat *); /* Indique le type défini par la GLib pour le processeur ARM. */ @@ -131,11 +131,13 @@ GArchProcessor *g_arm_processor_new(void) /****************************************************************************** * * -* Paramètres : proc = architecture visée par la procédure. * +* Paramètres : proc = architecture visée par la procédure. * +* ctx = contexte lié à l'exécution du processeur. * * data = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * len = taille totale des données à analyser. * * addr = adresse virtuelle de l'instruction. * +* format = format du fichier contenant le code. * * * * Description : Décode une instruction dans un flux de données. * * * @@ -144,14 +146,28 @@ GArchProcessor *g_arm_processor_new(void) * Remarques : - * * * ******************************************************************************/ +#include "encoding.h" +extern GArchInstruction *try_to_decode_arm_v456_instr(bin_t *); -static GArchInstruction *g_arm_processor_decode_instruction(const GArmProcessor *proc, const bin_t *data, off_t *pos, off_t len, vmpa_t addr) +static GArchInstruction *g_arm_processor_decode_instruction(const GArmProcessor *proc, GProcContext *ctx, const bin_t *data, off_t *pos, off_t len, vmpa_t addr, GBinFormat *format) { GArchInstruction *result; /* Instruction à renvoyer */ - result = NULL; + uint32_t *instr; + if (data == NULL) + return NULL; + + + instr = (uint32_t *)(data + *pos); + + + //printf("[0x%08x] cond=%x\n", *instr, INSTR_TO_COND(*instr)); + + result = try_to_decode_arm_v456_instr(data + *pos); + + if (result != NULL) *pos += 4; return result; diff --git a/src/arch/arm/v456/Makefile.am b/src/arch/arm/v456/Makefile.am new file mode 100644 index 0000000..744777e --- /dev/null +++ b/src/arch/arm/v456/Makefile.am @@ -0,0 +1,24 @@ + +noinst_LTLIBRARIES = libarcharmv456.la + +libarcharmv456_la_SOURCES = \ + addressing.h addressing.c \ + encoding.h \ + instruction-def.h \ + instruction.h instruction.c \ + register.h register.c + +libarcharmv456_la_LIBADD = \ + operands/libarcharmv456operands.la + +libarcharmv456_la_CFLAGS = $(AM_CFLAGS) + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +SUBDIRS = operands diff --git a/src/arch/arm/v456/addressing.c b/src/arch/arm/v456/addressing.c new file mode 100644 index 0000000..22ce11a --- /dev/null +++ b/src/arch/arm/v456/addressing.c @@ -0,0 +1,82 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * addressing.c - prise en compte des modes d'adressage ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "addressing.h" + + +#include "encoding.h" +#include "register.h" +#include "operands/content.h" +#include "operands/register.h" + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à compléter. * +* data = mot de données contenant les indications. * +* format = format du binaire manipulé. * +* * +* Description : Charge les opérandes selon le mode d'adressage § A5.2.1. * +* * +* Retour : true si le décodage s'est bien déroulé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool build_v456_operands_with_load_immediate_offset(GArmV456Instruction *instr, uint32_t data, const GExeFormat *format) +{ + uint8_t rd_index; /* Indice du registre Rd */ + GArmV456Register *rd_reg; /* Registre Rd en place */ + GArchOperand *op; /* Opérande à ajouter */ + uint8_t rn_index; /* Indice du registre Rn */ + GArmV456Register *rn_reg; /* Registre Rn en place */ + uint16_t value; /* Valeur de décallage */ + GImmOperand *offset; /* Opérande de décallage */ + bool add; /* Utilisation du décallage */ + + /* Destination */ + + rd_index = ARM_V456_REG_RD(data); + rd_reg = g_armv456_register_new(rd_index); + + op = g_armv456_register_operand_new_from_existing(rd_reg); + g_arch_instruction_attach_extra_operand(G_ARCH_INSTRUCTION(instr), op); + + /* Source */ + + rn_index = ARM_V456_REG_RN(data); + rn_reg = g_armv456_register_new(rn_index); + + value = ARM_V456_ADDR_MODE(data); + offset = G_IMM_OPERAND(g_imm_operand_new_from_value(MDS_16_BITS_UNSIGNED, value)); + + add = (data & ARM_V456_BIT_U); + + op = g_armv456_content_operand_new(rn_reg, offset, add); + g_arch_instruction_attach_extra_operand(G_ARCH_INSTRUCTION(instr), op); + + return true; + +} diff --git a/src/arch/arm/v456/addressing.h b/src/arch/arm/v456/addressing.h new file mode 100644 index 0000000..972508d --- /dev/null +++ b/src/arch/arm/v456/addressing.h @@ -0,0 +1,38 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * addressing.h - prototypes pour la prise en compte des modes d'adressage ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_V456_ADDRESSING_H +#define _ARCH_ARM_V456_ADDRESSING_H + + +#include "instruction.h" + + + +/* Charge les opérandes selon le mode d'adressage § A5.2.1. */ +bool build_v456_operands_with_load_immediate_offset(GArmV456Instruction *, uint32_t, const GExeFormat *); + + + + +#endif /* _ARCH_ARM_V456_ADDRESSING_H */ diff --git a/src/arch/arm/v456/encoding.h b/src/arch/arm/v456/encoding.h new file mode 100644 index 0000000..0c9716c --- /dev/null +++ b/src/arch/arm/v456/encoding.h @@ -0,0 +1,188 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * encoding.h - prototypes pour le décodage des instructions ARM v4/v5/v6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_V456_ENCODING_H +#define _ARCH_ARM_V456_ENCODING_H + + +#include + + + +/** + * Coprocessor data processing. + * § A3.1 Instruction set encoding. + */ + + +#define ARM_V456_DATA_PROC_IMM_SHIFT_1_BITS 0x0e000010 +#define ARM_V456_DATA_PROC_IMM_SHIFT_1_MASK 0x00000000 + +#define ARM_V456_MISC_INSTRUCTIONS_BITS 0x0f900010 +#define ARM_V456_MISC_INSTRUCTIONS_MASK 0x01000000 + +#define ARM_V456_DATA_PROC_IMM_SHIFT_2_BITS 0x0e000090 +#define ARM_V456_DATA_PROC_IMM_SHIFT_2_MASK 0x00000010 + +#define ARM_V456_MISC_INSTRS_BITS 0x0f900090 +#define ARM_V456_MISC_INSTRS_MASK 0x01000010 + +#define ARM_V456_MUL_EXTRA_LD_ST_BITS 0x0e000090 +#define ARM_V456_MUL_EXTRA_LD_ST_MASK 0x00000090 + +#define ARM_V456_DATA_PROC_IMM_2_BITS 0x0e000000 +#define ARM_V456_DATA_PROC_IMM_2_MASK 0x02000000 + +#define ARM_V456_UNDEF_INSTR_BITS 0x0fb00000 +#define ARM_V456_UNDEF_INSTR_MASK 0x03000000 + +#define ARM_V456_MOVE_IMM_STATUS_REG_BITS 0x0fb00000 +#define ARM_V456_MOVE_IMM_STATUS_REG_MASK 0x03200000 + +#define ARM_V456_LD_ST_IMM_OFFSET_BITS 0x0e000000 +#define ARM_V456_LD_ST_IMM_OFFSET_MASK 0x04000000 + +#define ARM_V456_ISET_LD_ST_REG_OFFSET_BITS 0x0e000010 +#define ARM_V456_ISET_LD_ST_REG_OFFSET_MASK 0x06000000 + +#define ARM_V456_ISET_MEDIA_INSTRS_4_BITS 0x0e000010 +#define ARM_V456_ISET_MEDIA_INSTRS_4_MASK 0x06000010 + +#define ARM_V456_ISET_ARCH_UNDEFINED_BITS 0x0ff000f0 +#define ARM_V456_ISET_ARCH_UNDEFINED_MASK 0x07f000f0 + +#define ARM_V456_ISET_LD_ST_MULTIPLE_BITS 0x0e000000 +#define ARM_V456_ISET_LD_ST_MULTIPLE_MASK 0x08000000 + +#define ARM_V456_ISET_BRANCH_LINK_BITS 0x0e000000 +#define ARM_V456_ISET_BRANCH_LINK_MASK 0x0a000000 + +#define ARM_V456_ISET_LD_ST_REG_TRANS_BITS 0x0e000000 +#define ARM_V456_ISET_LD_ST_REG_TRANS_MASK 0x0c000000 + +#define ARM_V456_ISET_COPROC_DATA_PROC_BITS 0x0f000010 +#define ARM_V456_ISET_COPROC_DATA_PROC_MASK 0x0e000000 + +#define ARM_V456_ISET_COPROC_REG_TRANS_BITS 0x0f000010 +#define ARM_V456_ISET_COPROC_REG_TRANS_MASK 0x0e000010 + +#define ARM_V456_ISET_SOFT_INTERRUPT_BITS 0x0f000000 +#define ARM_V456_ISET_SOFT_INTERRUPT_MASK 0x0f000000 + +#define ARM_V456_ISET_UNCOND_INSTRS_BITS 0xf0000000 +#define ARM_V456_ISET_UNCOND_INSTRS_MASK 0xf0000000 + + +/* Enumération des jeux possibles */ +typedef enum _ArmV456InstrSets +{ + ARM_V456_ISET_DATA_PROC_IMM_SHIFT_1, /* Data processing immediate shift */ + ARM_V456_ISET_MISC_INSTRUCTIONS, /* Miscellaneous instructions */ + ARM_V456_ISET_DATA_PROC_IMM_SHIFT_2, /* Data processing register shift [2] */ + ARM_V456_MISC_INSTRS, /* Miscellaneous instructions */ + ARM_V456_MUL_EXTRA_LD_ST, /* Multiplies - Extra load/stores */ + ARM_V456_DATA_PROC_IMM_2, /* Data processing immediate [2] */ + ARM_V456_UNDEF_INSTR, /* Undefined instruction */ + ARM_V456_MOVE_IMM_STATUS_REG, /* Move immediate to status register */ + ARM_V456_LD_ST_IMM_OFFSET, /* Load/store immediate offset */ + ARM_V456_ISET_LD_ST_REG_OFFSET, /* Load/store register offset */ + ARM_V456_ISET_MEDIA_INSTRS_4, /* Media instructions [4] */ + ARM_V456_ISET_ARCH_UNDEFINED, /* Architecturally undefined */ + ARM_V456_ISET_LD_ST_MULTIPLE, /* Load/store multiple */ + ARM_V456_ISET_BRANCH_LINK, /* Branch and branch with link */ + ARM_V456_ISET_LD_ST_REG_TRANS, /* Coproc. load/store and double register transfers */ + ARM_V456_ISET_COPROC_DATA_PROC, /* Coprocessor data processing */ + ARM_V456_ISET_COPROC_REG_TRANS, /* Coprocessor register transfers */ + ARM_V456_ISET_SOFT_INTERRUPT, /* Software interrupt */ + ARM_V456_ISET_UNCOND_INSTRS, /* Unconditional instructions */ + + ARM_V456_ISET_COUNT + +} ArmV456InstrSets; + + +/* Jeux réordonnés pour la reconnaissance */ +static const uint32_t _arm_v456_encoding_sets[ARM_V456_ISET_COUNT][2] = { + + /* 0 0 0 */ + { ARM_V456_MISC_INSTRS_BITS, ARM_V456_MISC_INSTRS_MASK }, + { ARM_V456_MISC_INSTRUCTIONS_BITS, ARM_V456_MISC_INSTRUCTIONS_MASK }, + { ARM_V456_DATA_PROC_IMM_SHIFT_2_BITS, ARM_V456_DATA_PROC_IMM_SHIFT_2_MASK }, + { ARM_V456_MUL_EXTRA_LD_ST_BITS, ARM_V456_MUL_EXTRA_LD_ST_MASK }, + { ARM_V456_DATA_PROC_IMM_SHIFT_1_BITS, ARM_V456_DATA_PROC_IMM_SHIFT_1_MASK }, + + /* 0 0 1 */ + { ARM_V456_UNDEF_INSTR_BITS, ARM_V456_UNDEF_INSTR_MASK }, + { ARM_V456_MOVE_IMM_STATUS_REG_BITS, ARM_V456_MOVE_IMM_STATUS_REG_MASK }, + { ARM_V456_DATA_PROC_IMM_2_BITS, ARM_V456_DATA_PROC_IMM_2_MASK }, + + /* 0 1 0 */ + { ARM_V456_LD_ST_IMM_OFFSET_BITS, ARM_V456_LD_ST_IMM_OFFSET_MASK }, + + /* 0 1 1 */ + { ARM_V456_ISET_ARCH_UNDEFINED_BITS, ARM_V456_ISET_ARCH_UNDEFINED_MASK }, + { ARM_V456_ISET_LD_ST_REG_OFFSET_BITS, ARM_V456_ISET_LD_ST_REG_OFFSET_MASK }, + { ARM_V456_ISET_MEDIA_INSTRS_4_BITS, ARM_V456_ISET_MEDIA_INSTRS_4_MASK }, + + /* 1 0 0 */ + { ARM_V456_ISET_LD_ST_MULTIPLE_BITS, ARM_V456_ISET_LD_ST_MULTIPLE_MASK }, + + /* 1 0 1 */ + { ARM_V456_ISET_BRANCH_LINK_BITS, ARM_V456_ISET_BRANCH_LINK_MASK }, + + /* 1 1 0 */ + { ARM_V456_ISET_LD_ST_REG_TRANS_BITS, ARM_V456_ISET_LD_ST_REG_TRANS_MASK }, + + /* 1 1 1 */ + { ARM_V456_ISET_COPROC_DATA_PROC_BITS, ARM_V456_ISET_COPROC_DATA_PROC_MASK }, + { ARM_V456_ISET_COPROC_REG_TRANS_BITS, ARM_V456_ISET_COPROC_REG_TRANS_MASK }, + { ARM_V456_ISET_SOFT_INTERRUPT_BITS, ARM_V456_ISET_SOFT_INTERRUPT_MASK }, + + /* x x x */ + { ARM_V456_ISET_UNCOND_INSTRS_BITS, ARM_V456_ISET_UNCOND_INSTRS_MASK } + +}; + + + + +#define IS_ENCODING_SET(val, set) (((val) & (set[0])) == (set[1])) + + + + +#define ARM_V456_BIT_L (1 << 20) +#define ARM_V456_BIT_W (1 << 21) +#define ARM_V456_BIT_U (1 << 22) +#define ARM_V456_BIT_P (1 << 23) +#define ARM_V456_BIT_I (1 << 24) + +#define ARM_V456_REG_RN(instr) (((instr) >> 16) & 0x0f) +#define ARM_V456_REG_RD(instr) (((instr) >> 12) & 0x0f) + +#define ARM_V456_ADDR_MODE(instr) ((instr) & 0xfff) + + + + +#endif /* _ARCH_ARM_V456_ENCODING_H */ diff --git a/src/arch/arm/v456/instruction-def.h b/src/arch/arm/v456/instruction-def.h new file mode 100644 index 0000000..521f939 --- /dev/null +++ b/src/arch/arm/v456/instruction-def.h @@ -0,0 +1,91 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction-def.h - définition interne des identifiants d'instructions ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_V456_INSTRUCTION_DEF_H +#define _ARCH_ARM_V456_INSTRUCTION_DEF_H + + + + + +/** + * ARM Architecture Reference Manual. + * A4.2 ARM instructions and architecture versions. + */ + +#define ARM_VERSION_4 (1 << 1) +#define ARM_VERSION_V4T (1 << 2) +#define ARM_VERSION_V5T (1 << 3) +#define ARM_VERSION_V5TE (1 << 4) +#define ARM_VERSION_V5TEJ (1 << 5) +#define ARM_VERSION_V6 (1 << 6) +#define ARM_VERSION_V5TEXP (1 << 7) + +#define ARM_VERSION_ALL_456 (ARM_VERSION_4 \ + | ARM_VERSION_V4T \ + | ARM_VERSION_V5T \ + | ARM_VERSION_V5TE \ + | ARM_VERSION_V5TEJ \ + | ARM_VERSION_V6 \ + | ARM_VERSION_V5TEXP) + + + + +/* Enumération de tous les opcodes */ +typedef enum _ArmV456Opcodes +{ + /** + * ARM Architecture Reference Manual. + * § A3.4 Data-processing instructions. + */ + + AOP_AND, /* and (0x00) */ + AOP_EOR, /* eor (0x01) */ + AOP_SUB, /* sub (0x02) */ + AOP_RSB, /* rsb (0x03) */ + AOP_ADD, /* add (0x04) */ + AOP_ADC, /* adc (0x05) */ + AOP_SBC, /* sbc (0x06) */ + AOP_RSC, /* rsc (0x07) */ + AOP_TST, /* tst (0x08) */ + AOP_TEQ, /* teq (0x09) */ + AOP_CMP, /* cmp (0x0a) */ + AOP_CMN, /* cmn (0x0b) */ + AOP_ORR, /* orr (0x0c) */ + AOP_MOV, /* mov (0x0d) */ + AOP_BIC, /* bic (0x0e) */ + AOP_MVN, /* mvn (0x0f) */ + + + AOP_LDR, + AOP_STR, + + + AOP_COUNT + +} ArmV456Opcodes; + + + +#endif /* _ARCH_ARM_V456_INSTRUCTION_DEF_H */ diff --git a/src/arch/arm/v456/instruction.c b/src/arch/arm/v456/instruction.c new file mode 100644 index 0000000..7f69beb --- /dev/null +++ b/src/arch/arm/v456/instruction.c @@ -0,0 +1,683 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.c - gestion des instructions ARM v4/v5/v6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "instruction.h" + + +#include "encoding.h" + + +#include "../instruction-int.h" + + + +//////// +#include +///////// + + + +typedef unsigned char bin_t; + +typedef unsigned int arch_version_t; + + + +/* -------------------------- INSTRUCTIONS POUR ARM v4/5/6 -------------------------- */ + + +/* Définition d'une instruction d'architecture ARM v4/5/6 (instance) */ +struct _GArmV456Instruction +{ + GArchInstruction parent; /* A laisser en premier */ + + ArmV456Opcodes type; /* Type d'instruction en place */ + +}; + +/* Définition d'une instruction d'architecture ARM v4/5/6 (classe) */ +struct _GArmV456InstructionClass +{ + GArchInstructionClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des instructions pour ARM v4/5/6. */ +static void g_armv456_instruction_class_init(GArmV456InstructionClass *); + +/* Initialise une instance d'opérande d'architecture ARM v4/5/6. */ +static void g_armv456_instruction_init(GArmV456Instruction *); + +/* Traduit une instruction en version humainement lisible. */ +static const char *g_armv456_get_instruction_text(const GArmV456Instruction *, const GExeFormat *, AsmSyntax); + + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Répertoire de toutes les instructions ARM v4/5/6 */ +typedef struct _arm_v456_instruction +{ + bin_t opcode; /* Opcode de l'instruction */ + const char *keyword; /* Mot clef de la commande */ + + arch_version_t version; /* Version de l'architecture */ + + //decomp_instr_fc decomp; /* Procédure de décompilation */ + +} arm_v456_instruction; + + +/* Liste de toutes les instructions */ +static arm_v456_instruction _instructions[AOP_COUNT] = { + + [AOP_AND] = { 0x00, "and", ARM_VERSION_ALL_456 }, + [AOP_EOR] = { 0x01, "eor", ARM_VERSION_ALL_456 }, + [AOP_SUB] = { 0x02, "sub", ARM_VERSION_ALL_456 }, + [AOP_RSB] = { 0x03, "rsb", ARM_VERSION_ALL_456 }, + [AOP_ADD] = { 0x04, "add", ARM_VERSION_ALL_456 }, + [AOP_ADC] = { 0x05, "adc", ARM_VERSION_ALL_456 }, + [AOP_SBC] = { 0x06, "sbc", ARM_VERSION_ALL_456 }, + [AOP_RSC] = { 0x07, "rsc", ARM_VERSION_ALL_456 }, + [AOP_TST] = { 0x08, "tst", ARM_VERSION_ALL_456 }, + [AOP_TEQ] = { 0x09, "teq", ARM_VERSION_ALL_456 }, + [AOP_CMP] = { 0x0a, "cmp", ARM_VERSION_ALL_456 }, + [AOP_CMN] = { 0x0b, "cmn", ARM_VERSION_ALL_456 }, + [AOP_ORR] = { 0x0c, "orr", ARM_VERSION_ALL_456 }, + [AOP_MOV] = { 0x0d, "mov", ARM_VERSION_ALL_456 }, + [AOP_BIC] = { 0x0e, "bic", ARM_VERSION_ALL_456 }, + [AOP_MVN] = { 0x0f, "mov", ARM_VERSION_ALL_456 }, + + [AOP_LDR] = { 0xff, "ldr", ARM_VERSION_ALL_456 }, + [AOP_STR] = { 0xff, "ldr", ARM_VERSION_ALL_456 } + + + +}; + + +/* Constitution d'un groupe */ +static arm_v456_instruction *_data_processing_instrs[17] = { + + &_instructions[AOP_AND], &_instructions[AOP_EOR], &_instructions[AOP_SUB], + &_instructions[AOP_RSB], &_instructions[AOP_ADD], &_instructions[AOP_ADC], + &_instructions[AOP_SBC], &_instructions[AOP_RSC], &_instructions[AOP_TST], + &_instructions[AOP_TEQ], &_instructions[AOP_CMP], &_instructions[AOP_CMN], + &_instructions[AOP_ORR], &_instructions[AOP_MOV], &_instructions[AOP_BIC], + &_instructions[AOP_MVN], NULL + +}; + + + + +/* ---------------------------------------------------------------------------------- */ +/* INSTRUCTIONS POUR ARM v4/5/6 */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour une instruction d'architecture Dalvik. */ +G_DEFINE_TYPE(GArmV456Instruction, g_armv456_instruction, G_TYPE_ARCH_INSTRUCTION); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des instructions pour Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv456_instruction_class_init(GArmV456InstructionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser. * +* * +* Description : Initialise une instance d'instruction d'architecture Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv456_instruction_init(GArmV456Instruction *instr) +{ + GArchInstruction *parent; /* Instance parente */ + + parent = G_ARCH_INSTRUCTION(instr); + + parent->get_text = (get_instruction_text_fc)g_armv456_get_instruction_text; + + /* + parent->get_rw_regs = (get_instruction_rw_regs_fc)g_armv456_instruction_get_rw_registers; + parent->get_text = (get_instruction_text_fc)dalvik_get_instruction_text; + parent->get_link = (get_instruction_link_fc)dalvik_get_instruction_link; + parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return; + parent->decomp = (decomp_instr_fc)dalvik_instruction_decompile; + */ + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'instruction à représenter. * +* * +* Description : Crée une instruction pour l'architecture Dalvik. * +* * +* Retour : Architecture mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_armv456_instruction_new(ArmV456Opcodes type) +{ + GArchInstruction *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ARMV456_INSTRUCTION, NULL); + + G_ARMV456_INSTRUCTION(result)->type = type; + + return result; + +} + + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit une instruction en version humainement lisible. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *g_armv456_get_instruction_text(const GArmV456Instruction *instr, const GExeFormat *format, AsmSyntax syntax) +{ + return _instructions[instr->type].keyword; + +} + + +#include "addressing.h" + + +GArchInstruction *try_to_decode_arm_v456_instr(bin_t *data) +{ + GArchInstruction *result; /* Instruction à retourner */ + uint32_t *instr; + + ArmV456InstrSets i; /* Boucle de parcours */ + + result = NULL; + + instr = (uint32_t *)data; + + //printf("instr = 0x%x\n", *instr); + + + + for (i = 0; i < ARM_V456_ISET_COUNT; i++) + if (IS_ENCODING_SET(*instr, _arm_v456_encoding_sets[i])) + break; + + switch (i) + { + case ARM_V456_ISET_COUNT: + printf("failed !\n"); + break; + + + case ARM_V456_LD_ST_IMM_OFFSET: + //printf("LOAD !! %s\n", *instr & ARM_V456_BIT_L ? "load" : "store"); + + + + result = g_armv456_instruction_new(*instr & ARM_V456_BIT_L ? AOP_LDR : AOP_STR); + + + /*bool */build_v456_operands_with_load_immediate_offset(result, *instr, NULL); + + + break; + + + default: + //printf("got it !\n"); + break; + + } + + + + + return result; + +} + + + + +#if 0 + +#include "instruction-int.h" +#include "decomp/translate.h" +#include "operands/register.h" +#include "operands/target.h" +#include "../instruction-int.h" +#include "../register-int.h" + + + +/* Initialise la classe des instructions pour Dalvik. */ +static void g_dalvik_instruction_class_init(GDalvikInstructionClass *); + +/* Initialise une instance d'opérande d'architecture Dalvik. */ +static void g_dalvik_instruction_init(GDalvikInstruction *); + +/* Liste les registres lus et écrits par l'instruction. */ +static void g_dalvik_instruction_get_rw_registers(const GDalvikInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Répertoire de toutes les instructions Dalvik */ +typedef struct _dalvik_instruction +{ + bin_t opcode; /* Opcode de l'instruction */ + + const char *keyword; /* Mot clef de la commande */ + + decomp_instr_fc decomp; /* Procédure de décompilation */ + +} dalvik_instruction; + + +static dalvik_instruction _instructions[DOP_COUNT] = { + +}; + + +/* Traduit une instruction en version humainement lisible. */ +static const char *dalvik_get_instruction_text(const GDalvikInstruction *, const GExeFormat *, AsmSyntax); + +/* Informe sur une éventuelle référence à une autre instruction. */ +static InstructionLinkType dalvik_get_instruction_link(const GDalvikInstruction *, vmpa_t *); + +/* Indique si l'instruction correspond à un retour de fonction. */ +static bool dalvik_instruction_is_return(const GDalvikInstruction *); + +/* Décompile une instruction de la machine virtuelle Dalvik. */ +GDecInstruction *dalvik_instruction_decompile(const GDalvikInstruction *, GDecContext *); + + + +/* Indique le type défini pour une instruction d'architecture Dalvik. */ +G_DEFINE_TYPE(GDalvikInstruction, g_dalvik_instruction, G_TYPE_ARCH_INSTRUCTION); + + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des instructions pour Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_instruction_class_init(GDalvikInstructionClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser. * +* * +* Description : Initialise une instance d'instruction d'architecture Dalvik. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_instruction_init(GDalvikInstruction *instr) +{ + GArchInstruction *parent; /* Instance parente */ + + parent = G_ARCH_INSTRUCTION(instr); + + parent->get_rw_regs = (get_instruction_rw_regs_fc)g_dalvik_instruction_get_rw_registers; + parent->get_text = (get_instruction_text_fc)dalvik_get_instruction_text; + parent->get_link = (get_instruction_link_fc)dalvik_get_instruction_link; + parent->is_return = (is_instruction_return_fc)dalvik_instruction_is_return; + parent->decomp = (decomp_instr_fc)dalvik_instruction_decompile; + +} + + +/****************************************************************************** +* * +* Paramètres : type = type d'instruction à représenter. * +* * +* Description : Crée une instruction pour l'architecture Dalvik. * +* * +* Retour : Architecture mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_dalvik_instruction_new(DalvikOpcodes type) +{ + GArchInstruction *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_DALVIK_INSTRUCTION, NULL); + + G_DALVIK_INSTRUCTION(result)->type = type; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction Dalvik à consulter. * +* * +* Description : Indique l'opcode associé à une instruction Dalvik. * +* * +* Retour : Identifiant de l'instruction en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +DalvikOpcodes g_dalvik_instruction_get_opcode(const GDalvikInstruction *instr) +{ + return instr->type; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à consulter. * +* rregs = liste des rgistres lus. [OUT] * +* rcount = nombre de registres lus. [OUT] * +* wregs = liste des rgistres écrits. [OUT] * +* wcount = nombre de registres écrits. [OUT] * +* * +* Description : Liste les registres lus et écrits par l'instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_dalvik_instruction_get_rw_registers(const GDalvikInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount) +{ + GArchInstruction *base; /* Version basique à manipuler */ + size_t i; /* Boucle de parcours */ + GArchOperand *operand; /* Operande à analyser */ + GDalvikRegister *reg; /* Registre concerné */ + + base = G_ARCH_INSTRUCTION(instr); + + for (i = 0; i < base->operands_count; i++) + { + operand = base->operands[i]; + + if (!G_IS_DALVIK_REGISTER_OPERAND(operand)) + continue; + + reg = g_dalvik_register_operand_get(G_DALVIK_REGISTER_OPERAND(operand)); + + if (g_dalvik_register_operand_is_written(G_DALVIK_REGISTER_OPERAND(operand))) + { + (*wregs) = (GArchRegister **)realloc(*wregs, ++(*wcount) * sizeof(GArchRegister *)); + (*wregs)[(*wcount) - 1] = G_ARCH_REGISTER(reg); + } + else + { + (*rregs) = (GArchRegister **)realloc(*rregs, ++(*rcount) * sizeof(GArchRegister *)); + (*rregs)[(*rcount) - 1] = G_ARCH_REGISTER(reg); + } + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* AIDE A LA MISE EN PLACE D'INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : data = flux de données à analyser. * +* pos = position courante dans ce flux. * +* len = taille totale des données à analyser. * +* * +* Description : Recherche l'identifiant de la prochaine instruction. * +* * +* Retour : Identifiant de la prochaine instruction à tenter de charger. * +* * +* Remarques : - * +* * +******************************************************************************/ + +DalvikOpcodes dalvik_guess_next_instruction(const bin_t *data, off_t pos, off_t len) +{ + DalvikOpcodes result; /* Identifiant à retourner */ + + result = (DalvikOpcodes)data[pos]; + + /* Si l'instruction est marquée comme non utilisée... */ + if (_instructions[result].keyword == NULL) + result = DOP_COUNT; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à traiter. * +* format = format du binaire manipulé. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit une instruction en version humainement lisible. * +* * +* Retour : Chaîne de caractères à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *dalvik_get_instruction_text(const GDalvikInstruction *instr, const GExeFormat *format, AsmSyntax syntax) +{ + return _instructions[instr->type].keyword; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à consulter. * +* addr = eventuelle adresse associée à faire connaître. [OUT] * +* * +* Description : Informe sur une éventuelle référence à une autre instruction.* +* * +* Retour : Type de lien trouvé ou ILT_NONE si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static InstructionLinkType dalvik_get_instruction_link(const GDalvikInstruction *instr, vmpa_t *addr) +{ + InstructionLinkType result; /* Type de lien à retourner */ + GArchOperand *operand; /* Opérande à manipuler */ + const GImmOperand *imm; /* Valeur immédiate */ + + switch (instr->type) + { + case DOP_GOTO: + case DOP_GOTO_16: + case DOP_GOTO_32: + + operand = g_arch_instruction_get_operand(G_ARCH_INSTRUCTION(instr), 0); + imm = g_dalvik_target_operand_get_value(G_DALVIK_TARGET_OPERAND(operand)); + + if (g_imm_operand_to_vmpa_t(imm, addr)) result = ILT_JUMP; + else result = ILT_NONE; + + break; + + case DOP_IF_EQ: + case DOP_IF_NE: + case DOP_IF_LT: + case DOP_IF_GE: + case DOP_IF_GT: + case DOP_IF_LE: + + operand = g_arch_instruction_get_operand(G_ARCH_INSTRUCTION(instr), 2); + imm = g_dalvik_target_operand_get_value(G_DALVIK_TARGET_OPERAND(operand)); + + if (g_imm_operand_to_vmpa_t(imm, addr)) result = ILT_JUMP_IF_TRUE; + else result = ILT_NONE; + + break; + + case DOP_IF_EQZ: + case DOP_IF_NEZ: + case DOP_IF_LTZ: + case DOP_IF_GEZ: + case DOP_IF_GTZ: + case DOP_IF_LEZ: + + operand = g_arch_instruction_get_operand(G_ARCH_INSTRUCTION(instr), 1); + imm = g_dalvik_target_operand_get_value(G_DALVIK_TARGET_OPERAND(operand)); + + if (g_imm_operand_to_vmpa_t(imm, addr)) result = ILT_JUMP_IF_TRUE; + else result = ILT_NONE; + + break; + + default: + result = ILT_NONE; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction à consulter. * +* * +* Description : Indique si l'instruction correspond à un retour de fonction. * +* * +* Retour : true si l'instruction est un 'return' quelconque ou false. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool dalvik_instruction_is_return(const GDalvikInstruction *instr) +{ + return (instr->type == DOP_RETURN_VOID + || instr->type == DOP_RETURN + || instr->type == DOP_RETURN_WIDE + || instr->type == DOP_RETURN_OBJECT); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'origine à convertir. * +* ctx = contexte de la phase de décompilation. * +* * +* Description : Décompile une instruction de la machine virtuelle Dalvik. * +* * +* Retour : Instruction mise en place ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *dalvik_instruction_decompile(const GDalvikInstruction *instr, GDecContext *ctx) +{ + GDecInstruction *result; /* Instruction à retourner */ + + if (_instructions[instr->type].decomp != NULL) + result = _instructions[instr->type].decomp(G_ARCH_INSTRUCTION(instr), ctx); + + else + result = NULL; + + return result; + +} + + + +#endif diff --git a/src/arch/arm/v456/instruction.h b/src/arch/arm/v456/instruction.h new file mode 100644 index 0000000..a9e6b71 --- /dev/null +++ b/src/arch/arm/v456/instruction.h @@ -0,0 +1,105 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * instruction.h - prototypes pour la gestion des instructions ARM v4/v5/v6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_V456_INSTRUCTION_H +#define _ARCH_ARM_V456_INSTRUCTION_H + + +#include "instruction-def.h" +#include "../../instruction.h" + + + +#define G_TYPE_ARMV456_INSTRUCTION g_armv456_instruction_get_type() +#define G_ARMV456_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv456_instruction_get_type(), GArmV456Instruction)) +#define G_IS_ARMV456_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv456_instruction_get_type())) +#define G_ARMV456_INSTRUCTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_armv456_instruction_get_type(), GArmV456InstructionIface)) + + +/* Définition d'une instruction d'architecture ARM v4/5/6 (instance) */ +typedef struct _GArmV456Instruction GArmV456Instruction; + +/* Définition d'une instruction d'architecture ARM v4/5/6 (classe) */ +typedef struct _GArmV456InstructionClass GArmV456InstructionClass; + + +/* Indique le type défini pour une instruction d'architecture ARM v4/5/6. */ +GType g_armv456_instruction_get_type(void); + +/* Crée une instruction pour l'architecture ARM v4/5/6. */ +GArchInstruction *g_armv456_instruction_new(ArmV456Opcodes); + + + + + +GArchInstruction *try_to_decode_arm_v456_instr(bin_t *); + + + + +#if 0 +#include "instruction-def.h" +#include "../../instruction.h" + + + +#define G_TYPE_DALVIK_INSTRUCTION g_dalvik_instruction_get_type() +#define G_DALVIK_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_dalvik_instruction_get_type(), GDalvikInstruction)) +#define G_IS_DALVIK_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_dalvik_instruction_get_type())) +#define G_DALVIK_INSTRUCTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), g_dalvik_instruction_get_type(), GDalvikInstructionIface)) + + +/* Définition générique d'une instruction d'architecture Dalvik (instance) */ +typedef struct _GDalvikInstruction GDalvikInstruction; + +/* Définition générique d'une instruction d'architecture Dalvik (classe) */ +typedef struct _GDalvikInstructionClass GDalvikInstructionClass; + + +/* Indique le type défini pour une instruction d'architecture Dalvik. */ +GType g_dalvik_instruction_get_type(void); + +/* Crée une instruction pour l'architecture Dalvik. */ +GArchInstruction *g_dalvik_instruction_new(DalvikOpcodes); + +/* Indique l'opcode associé à une instruction Dalvik. */ +DalvikOpcodes g_dalvik_instruction_get_opcode(const struct _GDalvikInstruction *); + + + +/* --------------------- AIDE A LA MISE EN PLACE D'INSTRUCTIONS --------------------- */ + + +/* Recherche l'identifiant de la prochaine instruction. */ +DalvikOpcodes dalvik_guess_next_instruction(const bin_t *, off_t, off_t); + + + +/* ------------------------ AIDE A LA PHASE DE DECOMPILATION ------------------------ */ + + +#endif + + +#endif /* _ARCH_ARM_V456_INSTRUCTION_H */ diff --git a/src/arch/arm/v456/operands/Makefile.am b/src/arch/arm/v456/operands/Makefile.am new file mode 100644 index 0000000..9a8973b --- /dev/null +++ b/src/arch/arm/v456/operands/Makefile.am @@ -0,0 +1,18 @@ + +noinst_LTLIBRARIES = libarcharmv456operands.la + +libarcharmv456operands_la_SOURCES = \ + content.h content.c \ + register.h register.c + +libarcharmv456_la_CFLAGS = $(AM_CFLAGS) + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) + + +SUBDIRS = diff --git a/src/arch/arm/v456/operands/content.c b/src/arch/arm/v456/operands/content.c new file mode 100644 index 0000000..1ffceae --- /dev/null +++ b/src/arch/arm/v456/operands/content.c @@ -0,0 +1,257 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * content.c - opérandes visant un registre ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "content.h" + + +#include "../../../operand-int.h" + + + +/* Définition d'un opérande visant un registre ARM v4/5/6 (instance) */ +struct _GArmV456ContentOperand +{ + GArchOperand parent; /* Instance parente */ + + GArmV456Register *reg; /* Registre représenté */ + GImmOperand *offset; /* Décallage à appliquer */ + + bool add; /* Mise à jour du registre ? */ + + bool is_written; /* Changement de contenu */ + +}; + + +/* Définition d'un opérande visant un registre ARM v4/5/6 (classe) */ +struct _GArmV456ContentOperandClass +{ + GArchOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes de registre ARM v4/5/6. */ +static void g_armv456_content_operand_class_init(GArmV456ContentOperandClass *); + +/* Initialise une instance d'opérande de registre ARM v4/5/6. */ +static void g_armv456_content_operand_init(GArmV456ContentOperand *); + +/* Compare un opérande avec un autre. */ +static bool g_armv456_content_operand_compare(const GArmV456ContentOperand *, const GArmV456ContentOperand *); + +/* Traduit un opérande en version humainement lisible. */ +static void g_armv456_content_operand_print(const GArmV456ContentOperand *, GBufferLine *, AsmSyntax); + + + +/* Indique le type défini par la GLib pour un opérande de registre ARM v4/5/6. */ +G_DEFINE_TYPE(GArmV456ContentOperand, g_armv456_content_operand, G_TYPE_ARCH_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes de registre ARM v4/5/6. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv456_content_operand_class_init(GArmV456ContentOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande de registre ARM v4/5/6. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv456_content_operand_init(GArmV456ContentOperand *operand) +{ + GArchOperand *parent; /* Instance parente */ + + parent = G_ARCH_OPERAND(operand); + + parent->compare = (operand_compare_fc)g_armv456_content_operand_compare; + parent->print = (operand_print_fc)g_armv456_content_operand_print; + + operand->is_written = false; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre déjà en place. * +* offset = décallage à appliquer. * +* add = sens du décallage. * +* * +* Description : Crée un opérande visant un registre ARM v4/5/6. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_armv456_content_operand_new(GArmV456Register *reg, GImmOperand *offset, bool add) +{ + GArmV456ContentOperand *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ARMV456_CONTENT_OPERAND, NULL); + + result->reg = reg; + result->offset = offset; + + result->add = add; + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande représentant un registre. * +* * +* Description : Fournit le registre ARM v4/5/6 associé à l'opérande. * +* * +* Retour : Représentation interne du registre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArmV456Register *g_armv456_content_operand_get(const GArmV456ContentOperand *operand) +{ + return operand->reg; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier opérande à consulter. * +* b = second opérande à consulter. * +* * +* Description : Compare un opérande avec un autre. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv456_content_operand_compare(const GArmV456ContentOperand *a, const GArmV456ContentOperand *b) +{ + return false;//(g_armv456_content_compare(a->reg, b->reg) == 0); + +} + + +/****************************************************************************** +* * +* 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_armv456_content_operand_print(const GArmV456ContentOperand *operand, GBufferLine *line, AsmSyntax syntax) +{ + g_buffer_line_insert_text(line, BLC_ASSEMBLY, "[", 1, RTT_HOOK); + + g_armv456_register_print(operand->reg, line, syntax); + + if (!g_imm_operand_is_null(operand->offset)) + { + g_buffer_line_insert_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT); + g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW); + + if (!operand->add) + g_buffer_line_insert_text(line, BLC_ASSEMBLY, "-", 1, RTT_SIGNS); + + g_arch_operand_print(G_ARCH_OPERAND(operand->offset), line, syntax); + + } + + g_buffer_line_insert_text(line, BLC_ASSEMBLY, "]", 1, RTT_HOOK); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande représentant un registre à mettre à jour. * +* * +* Description : Marque l'opérande comme étant écrit plutôt que consulté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_armv456_content_operand_mark_as_written(GArmV456ContentOperand *operand) +{ + operand->is_written = true; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande représentant un registre à consulter. * +* * +* Description : Indique le type d'accès réalisé sur l'opérande. * +* * +* Retour : Type d'accès : true en cas d'écriture, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_armv456_content_operand_is_written(const GArmV456ContentOperand *operand) +{ + return operand->is_written; + +} diff --git a/src/arch/arm/v456/operands/content.h b/src/arch/arm/v456/operands/content.h new file mode 100644 index 0000000..901eae0 --- /dev/null +++ b/src/arch/arm/v456/operands/content.h @@ -0,0 +1,70 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * content.h - prototypes pour les opérandes visant un registre ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_V456_OPERANDS_CONTENT_H +#define _ARCH_ARM_V456_OPERANDS_CONTENT_H + + +#include + + +#include "../register.h" +#include "../../../operand.h" +#include "../../../../arch/immediate.h" +#include "../../../../common/endianness.h" + + + +#define G_TYPE_ARMV456_CONTENT_OPERAND g_armv456_content_operand_get_type() +#define G_ARMV456_CONTENT_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv456_content_operand_get_type(), GArmV456ContentOperand)) +#define G_IS_DALVIK_CONTENT_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv456_content_operand_get_type())) +#define G_ARMV456_CONTENT_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_CONTENT_OPERAND, GArmV456ContentOperandClass)) +#define G_IS_DALVIK_CONTENT_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_CONTENT_OPERAND)) +#define G_ARMV456_CONTENT_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_CONTENT_OPERAND, GArmV456ContentOperandClass)) + + +/* Définition d'un opérande visant un registre ARM v4/5/6 (instance) */ +typedef struct _GArmV456ContentOperand GArmV456ContentOperand; + +/* Définition d'un opérande visant un registre ARM v4/5/6 (classe) */ +typedef struct _GArmV456ContentOperandClass GArmV456ContentOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de registre ARM v4/5/6. */ +GType g_armv456_content_operand_get_type(void); + +/* Crée un opérande visant un registre ARM v4/5/6. */ +GArchOperand *g_armv456_content_operand_new(GArmV456Register *, GImmOperand *, bool); + +/* Fournit le registre ARM v4/5/6 associé à l'opérande. */ +GArmV456Register *g_armv456_content_operand_get(const GArmV456ContentOperand *); + +/* Marque l'opérande comme étant écrit plutôt que consulté. */ +void g_armv456_content_operand_mark_as_written(GArmV456ContentOperand *); + +/* Indique le type d'accès réalisé sur l'opérande. */ +bool g_armv456_content_operand_is_written(const GArmV456ContentOperand *); + + + +#endif /* _ARCH_ARM_V456_OPERANDS_CONTENT_H */ diff --git a/src/arch/arm/v456/operands/register.c b/src/arch/arm/v456/operands/register.c new file mode 100644 index 0000000..ce51cfc --- /dev/null +++ b/src/arch/arm/v456/operands/register.c @@ -0,0 +1,232 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * register.c - opérandes visant un registre ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "register.h" + + +#include "../../../operand-int.h" + + + +/* Définition d'un opérande visant un registre ARM v4/5/6 (instance) */ +struct _GArmV456RegisterOperand +{ + GArchOperand parent; /* Instance parente */ + + GArmV456Register *reg; /* Registre représenté */ + bool is_written; /* Changement de contenu */ + +}; + + +/* Définition d'un opérande visant un registre ARM v4/5/6 (classe) */ +struct _GArmV456RegisterOperandClass +{ + GArchOperandClass parent; /* Classe parente */ + +}; + + +/* Initialise la classe des opérandes de registre ARM v4/5/6. */ +static void g_armv456_register_operand_class_init(GArmV456RegisterOperandClass *); + +/* Initialise une instance d'opérande de registre ARM v4/5/6. */ +static void g_armv456_register_operand_init(GArmV456RegisterOperand *); + +/* Compare un opérande avec un autre. */ +static bool g_armv456_register_operand_compare(const GArmV456RegisterOperand *, const GArmV456RegisterOperand *); + +/* Traduit un opérande en version humainement lisible. */ +static void g_armv456_register_operand_print(const GArmV456RegisterOperand *, GBufferLine *, AsmSyntax); + + + +/* Indique le type défini par la GLib pour un opérande de registre ARM v4/5/6. */ +G_DEFINE_TYPE(GArmV456RegisterOperand, g_armv456_register_operand, G_TYPE_ARCH_OPERAND); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des opérandes de registre ARM v4/5/6. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv456_register_operand_class_init(GArmV456RegisterOperandClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise une instance d'opérande de registre ARM v4/5/6. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv456_register_operand_init(GArmV456RegisterOperand *operand) +{ + GArchOperand *parent; /* Instance parente */ + + parent = G_ARCH_OPERAND(operand); + + parent->compare = (operand_compare_fc)g_armv456_register_operand_compare; + parent->print = (operand_print_fc)g_armv456_register_operand_print; + + operand->is_written = false; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre déjà en place. * +* * +* Description : Crée un opérande visant un registre ARM v4/5/6. * +* * +* Retour : Opérande mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_armv456_register_operand_new_from_existing(GArmV456Register *reg) +{ + GArmV456RegisterOperand *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ARMV456_REGISTER_OPERAND, NULL); + + result->reg = reg; + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande représentant un registre. * +* * +* Description : Fournit le registre ARM v4/5/6 associé à l'opérande. * +* * +* Retour : Représentation interne du registre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArmV456Register *g_armv456_register_operand_get(const GArmV456RegisterOperand *operand) +{ + return operand->reg; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier opérande à consulter. * +* b = second opérande à consulter. * +* * +* Description : Compare un opérande avec un autre. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_armv456_register_operand_compare(const GArmV456RegisterOperand *a, const GArmV456RegisterOperand *b) +{ + return (g_armv456_register_compare(a->reg, b->reg) == 0); + +} + + +/****************************************************************************** +* * +* 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_armv456_register_operand_print(const GArmV456RegisterOperand *operand, GBufferLine *line, AsmSyntax syntax) +{ + g_armv456_register_print(operand->reg, line, syntax); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande représentant un registre à mettre à jour. * +* * +* Description : Marque l'opérande comme étant écrit plutôt que consulté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_armv456_register_operand_mark_as_written(GArmV456RegisterOperand *operand) +{ + operand->is_written = true; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande représentant un registre à consulter. * +* * +* Description : Indique le type d'accès réalisé sur l'opérande. * +* * +* Retour : Type d'accès : true en cas d'écriture, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_armv456_register_operand_is_written(const GArmV456RegisterOperand *operand) +{ + return operand->is_written; + +} diff --git a/src/arch/arm/v456/operands/register.h b/src/arch/arm/v456/operands/register.h new file mode 100644 index 0000000..5fd19cb --- /dev/null +++ b/src/arch/arm/v456/operands/register.h @@ -0,0 +1,69 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * register.h - prototypes pour les opérandes visant un registre ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_V456_OPERANDS_REGISTER_H +#define _ARCH_ARM_V456_OPERANDS_REGISTER_H + + +#include + + +#include "../register.h" +#include "../../../operand.h" +#include "../../../../common/endianness.h" + + + +#define G_TYPE_ARMV456_REGISTER_OPERAND g_armv456_register_operand_get_type() +#define G_ARMV456_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv456_register_operand_get_type(), GArmV456RegisterOperand)) +#define G_IS_DALVIK_REGISTER_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv456_register_operand_get_type())) +#define G_ARMV456_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_REGISTER_OPERAND, GArmV456RegisterOperandClass)) +#define G_IS_DALVIK_REGISTER_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_REGISTER_OPERAND)) +#define G_ARMV456_REGISTER_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_REGISTER_OPERAND, GArmV456RegisterOperandClass)) + + +/* Définition d'un opérande visant un registre ARM v4/5/6 (instance) */ +typedef struct _GArmV456RegisterOperand GArmV456RegisterOperand; + +/* Définition d'un opérande visant un registre ARM v4/5/6 (classe) */ +typedef struct _GArmV456RegisterOperandClass GArmV456RegisterOperandClass; + + +/* Indique le type défini par la GLib pour un opérande de registre ARM v4/5/6. */ +GType g_armv456_register_operand_get_type(void); + +/* Crée un opérande visant un registre ARM v4/5/6. */ +GArchOperand *g_armv456_register_operand_new_from_existing(GArmV456Register *); + +/* Fournit le registre ARM v4/5/6 associé à l'opérande. */ +GArmV456Register *g_armv456_register_operand_get(const GArmV456RegisterOperand *); + +/* Marque l'opérande comme étant écrit plutôt que consulté. */ +void g_armv456_register_operand_mark_as_written(GArmV456RegisterOperand *); + +/* Indique le type d'accès réalisé sur l'opérande. */ +bool g_armv456_register_operand_is_written(const GArmV456RegisterOperand *); + + + +#endif /* _ARCH_ARM_V456_OPERANDS_REGISTER_H */ diff --git a/src/arch/arm/v456/register.c b/src/arch/arm/v456/register.c new file mode 100644 index 0000000..7e101a3 --- /dev/null +++ b/src/arch/arm/v456/register.c @@ -0,0 +1,251 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * registers.c - aides auxiliaires relatives aux registres ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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 "register.h" + + +#include + + +#include "../../register-int.h" + + + +/* Représentation d'un registre ARM v4/5/6 (instance) */ +struct _GArmV456Register +{ + GArchRegister parent; /* Instance parente */ + + uint8_t index; /* Indice du registre */ + +}; + + +/* Représentation d'un registre ARM v4/5/6 (classe) */ +struct _GArmV456RegisterClass +{ + GArchRegisterClass parent; /* Classe parente */ + +}; + + +#define MAX_REGNAME_LEN 8 + + +/* Initialise la classe des registres ARM v4/5/6. */ +static void g_armv456_register_class_init(GArmV456RegisterClass *); + +/* Initialise une instance de registre ARM v4/5/6. */ +static void g_armv456_register_init(GArmV456Register *); + +/* Produit une empreinte à partir d'un registre. */ +static guint g_armv456_register_hash(const GArmV456Register *); + + + +/* Indique le type défini pour une représentation d'un registre ARM v4/5/6. */ +G_DEFINE_TYPE(GArmV456Register, g_armv456_register, G_TYPE_ARCH_REGISTER); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des registres ARM v4/5/6. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv456_register_class_init(GArmV456RegisterClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : reg = instance à initialiser. * +* * +* Description : Initialise une instance de registre ARM v4/5/6. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv456_register_init(GArmV456Register *reg) +{ + GArchRegister *base; /* Version basique */ + + base = G_ARCH_REGISTER(reg); + + base->hash = (reg_hash_fc)g_armv456_register_hash; + base->compare = (reg_compare_fc)g_armv456_register_compare; + base->print = (reg_print_fc)g_armv456_register_print; + +} + + +/****************************************************************************** +* * +* Paramètres : index = indice du registre correspondant. * +* * +* Description : Crée une réprésentation de registre ARM v4/5/6. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArmV456Register *g_armv456_register_new(uint8_t index) +{ + GArmV456Register *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_ARMV456_REGISTER, NULL); + + result->index = index; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à consulter. * +* * +* Description : Fournit l'indice d'un registre ARM v4/5/6. * +* * +* Retour : Inditifiant représentant le registre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint16_t g_armv456_register_get_index(const GArmV456Register *reg) +{ + return reg->index; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = opérande à consulter pour le calcul. * +* * +* Description : Produit une empreinte à partir d'un registre. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_armv456_register_hash(const GArmV456Register *reg) +{ + return reg->index; + +} + + +/****************************************************************************** +* * +* Paramètres : a = premier opérande à consulter. * +* b = second opérande à consulter. * +* * +* Description : Compare un registre avec un autre. * +* * +* Retour : Bilan de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int g_armv456_register_compare(const GArmV456Register *a, const GArmV456Register *b) +{ + int result; /* Bilan à retourner */ + + if (a->index < b->index) + result = -1; + else if (a->index > b->index) + result = 1; + else + result = 0; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : reg = registre à transcrire. * +* line = ligne tampon où imprimer l'opérande donné. * +* syntax = type de représentation demandée. * +* * +* Description : Traduit un registre en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_armv456_register_print(const GArmV456Register *reg, GBufferLine *line, AsmSyntax syntax) +{ + char key[MAX_REGNAME_LEN]; /* Mot clef principal */ + size_t klen; /* Taille de ce mot clef */ + + switch (reg->index) + { + case 0 ... 12: + klen = snprintf(key, MAX_REGNAME_LEN, "r%hhu", reg->index); + break; + case 13: + klen = snprintf(key, MAX_REGNAME_LEN, "sp"); + break; + case 14: + klen = snprintf(key, MAX_REGNAME_LEN, "lr"); + break; + case 15: + klen = snprintf(key, MAX_REGNAME_LEN, "pc"); + break; + case 16: + klen = snprintf(key, MAX_REGNAME_LEN, "cpsr"); + break; + case 17: + klen = snprintf(key, MAX_REGNAME_LEN, "spsr"); + break; + default: + klen = snprintf(key, MAX_REGNAME_LEN, "r??"); + break; + } + + g_buffer_line_insert_text(line, BLC_ASSEMBLY, key, klen, RTT_REGISTER); + +} diff --git a/src/arch/arm/v456/register.h b/src/arch/arm/v456/register.h new file mode 100644 index 0000000..98454fb --- /dev/null +++ b/src/arch/arm/v456/register.h @@ -0,0 +1,69 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * registers.h - prototypes pour les aides auxiliaires relatives aux registres ARM v4/5/6 + * + * Copyright (C) 2013 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * 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_V456_REGISTERS_H +#define _ARCH_ARM_V456_REGISTERS_H + + +#include +#include + + +#include "../../archbase.h" +#include "../../../glibext/gbufferline.h" + + + +#define G_TYPE_ARMV456_REGISTER g_armv456_register_get_type() +#define G_ARMV456_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv456_register_get_type(), GArmV456Register)) +#define G_IS_DALVIK_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv456_register_get_type())) +#define G_ARMV456_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DALVIK_REGISTER, GArmV456RegisterClass)) +#define G_IS_DALVIK_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DALVIK_REGISTER)) +#define G_ARMV456_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DALVIK_REGISTER, GArmV456RegisterClass)) + + +/* Représentation d'un registre ARM v4/5/6 (instance) */ +typedef struct _GArmV456Register GArmV456Register; + +/* Représentation d'un registre ARM v4/5/6 (classe) */ +typedef struct _GArmV456RegisterClass GArmV456RegisterClass; + + +/* Indique le type défini pour une représentation d'un registre ARM v4/5/6. */ +GType g_armv456_register_get_type(void); + +/* Crée une réprésentation de registre ARM v4/5/6. */ +GArmV456Register *g_armv456_register_new(uint8_t); + +/* Fournit l'indice d'un registre ARM v4/5/6. */ +uint16_t g_armv456_register_get_index(const GArmV456Register *); + +/* Compare un registre avec un autre. */ +int g_armv456_register_compare(const GArmV456Register *, const GArmV456Register *); + +/* Traduit un registre en version humainement lisible. */ +void g_armv456_register_print(const GArmV456Register *, GBufferLine *, AsmSyntax); + + + +#endif /* _ARCH_ARM_V456_REGISTERS_H */ diff --git a/src/arch/immediate.c b/src/arch/immediate.c index 19c86b2..4f94be3 100644 --- a/src/arch/immediate.c +++ b/src/arch/immediate.c @@ -359,7 +359,7 @@ bool g_imm_operand_does_padding(const GImmOperand *operand) /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à définir. * +* Paramètres : operand = structure dont le contenu est à consulter. * * * * Description : Indique le signe d'une valeur immédiate. * * * @@ -402,6 +402,64 @@ bool g_imm_operand_is_negative(const GImmOperand *operand) /****************************************************************************** * * +* Paramètres : operand = structure dont le contenu est à consulter. * +* * +* Description : Indique si une valeur immédiate est nulle ou non. * +* * +* Retour : true si la valeur est nulle, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_imm_operand_is_null(const GImmOperand *operand) +{ + bool result; /* Bilan à renvoyer */ + + switch (operand->size) + { + case MDS_4_BITS_SIGNED: + result = !(operand->signed_imm.val8 & 0x0f); + break; + case MDS_4_BITS_UNSIGNED: + result = !(operand->unsigned_imm.val8 & 0x0f); + break; + case MDS_8_BITS_SIGNED: + result = !(operand->signed_imm.val8 & 0xff); + break; + case MDS_8_BITS_UNSIGNED: + result = !(operand->unsigned_imm.val8 & 0xff); + break; + case MDS_16_BITS_SIGNED: + result = !(operand->signed_imm.val16 & 0xffff); + break; + case MDS_16_BITS_UNSIGNED: + result = !(operand->unsigned_imm.val16 & 0xffff); + break; + case MDS_32_BITS_SIGNED: + result = !(operand->signed_imm.val32 & 0xffffffff); + break; + case MDS_32_BITS_UNSIGNED: + result = !(operand->unsigned_imm.val32 & 0xffffffff); + break; + case MDS_64_BITS_SIGNED: + result = !(operand->signed_imm.val64 & 0xffffffffffffffffll); + break; + case MDS_64_BITS_UNSIGNED: + result = !(operand->unsigned_imm.val64 & 0xffffffffffffffffll); + break; + default: + result = false; + break; + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : operand = opérande à transcrire. * * syntax = type de représentation demandée. * * value = valeur portée par l'opérande transcrite. [OUT] * diff --git a/src/arch/immediate.h b/src/arch/immediate.h index 17416dc..3e5a7dc 100644 --- a/src/arch/immediate.h +++ b/src/arch/immediate.h @@ -68,6 +68,9 @@ bool g_imm_operand_does_padding(const GImmOperand *); /* Indique le signe d'une valeur immédiate. */ bool g_imm_operand_is_negative(const GImmOperand *); +/* Indique si une valeur immédiate est nulle ou non. */ +bool g_imm_operand_is_null(const GImmOperand *); + /* Convertit une valeur immédiate en adresse de type vmpa_t. */ bool g_imm_operand_to_vmpa_t(const GImmOperand *, vmpa_t *); -- cgit v0.11.2-87-g4458