diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-05-19 10:28:27 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-05-19 10:28:27 (GMT) |
commit | 5e6f3a42a2f57c563f34e5ea4d9c377d8618e871 (patch) | |
tree | 9b245999585accb100a09df44a0f254ece4d9209 /plugins/arm/v7/fetch.c | |
parent | d52e16c97aa88ecf6a3643ef454e1aa857e0e7dd (diff) |
Added support for a few extra ARMv7 instructions.
Diffstat (limited to 'plugins/arm/v7/fetch.c')
-rw-r--r-- | plugins/arm/v7/fetch.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/plugins/arm/v7/fetch.c b/plugins/arm/v7/fetch.c index 20918c5..bf60d9c 100644 --- a/plugins/arm/v7/fetch.c +++ b/plugins/arm/v7/fetch.c @@ -35,7 +35,11 @@ #include <format/preload.h> +#include "operands/it.h" #include "operands/offset.h" +#include "operands/register.h" +#include "operands/reglist.h" +#include "../instruction.h" #include "../register.h" @@ -532,3 +536,171 @@ void help_fetching_with_instruction_ldr_literal_with_orig(GArchInstruction *inst //exit(0); } + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* iset = type de jeu d'instructions courant. * +* * +* Description : Applique la mise à jour d'un registre après coup. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void apply_write_back(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format, ArmV7InstrSet iset) +{ + GArchOperand *op; /* Opérande de registre */ + + g_arch_instruction_lock_operands(instr); + + op = _g_arch_instruction_get_operand(instr, 0); + assert(G_IS_ARMV7_REGISTER_OPERAND(op)); + + g_armv7_register_operand_write_back(G_ARMV7_REGISTER_OPERAND(op), true); + + g_object_unref(G_OBJECT(op)); + + g_arch_instruction_unlock_operands(instr); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* iset = type de jeu d'instructions courant. * +* * +* Description : Applique la mise à jour d'un registre après coup au besoin. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void apply_write_back_from_registers(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format, ArmV7InstrSet iset) +{ + GArchOperand *op; /* Opérande à manipuler */ + GArmV7RegisterOperand *regop; /* Opérande de registre */ + GArchRegister *reg_ref; /* Registre de référence */ + GArmV7RegListOperand *reglist; /* Opérande de liste de reg. */ + size_t count; /* Taille de la liste */ + bool inside; /* Intersection de registres */ + size_t i; /* Boucle de parcours */ + GArmV7Register *reg; /* Registre à analyser */ + + g_arch_instruction_lock_operands(instr); + + op = _g_arch_instruction_get_operand(instr, 0); + assert(G_IS_ARMV7_REGISTER_OPERAND(op)); + + regop = G_ARMV7_REGISTER_OPERAND(op); + + reg_ref = G_ARCH_REGISTER(g_armv7_register_operand_get(regop)); + + op = _g_arch_instruction_get_operand(instr, 1); + assert(G_IS_ARMV7_REGLIST_OPERAND(op)); + + reglist = G_ARMV7_REGLIST_OPERAND(op); + + count = g_armv7_reglist_count_registers(reglist); + + inside = false; + + for (i = 0; i < count && !inside; i++) + { + reg = g_armv7_reglist_operand_get_register(reglist, i); + + inside = (g_arch_register_compare(reg_ref, G_ARCH_REGISTER(reg)) == 0); + + } + + if (!inside) + g_armv7_register_operand_write_back(regop, true); + + g_object_unref(G_OBJECT(regop)); + g_object_unref(G_OBJECT(reglist)); + + g_arch_instruction_unlock_operands(instr); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction ARMv7 à traiter. * +* proc = représentation de l'architecture utilisée. * +* context = contexte associé à la phase de désassemblage. * +* format = acès aux données du binaire d'origine. * +* iset = type de jeu d'instructions courant. * +* * +* Description : Construit un suffixe adapté à une instruction IT. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void build_it_instruction_suffix(GArchInstruction *instr, GArchProcessor *proc, GArmV7Context *context, GExeFormat *format, ArmV7InstrSet iset) +{ + GArchOperand *op; /* Opérande à manipuler */ + GArmV7ITCondOperand *itcond; /* Opérande de l'instruction */ + uint8_t firstcond; /* Indication sur la condition */ + uint8_t mask; /* Masque d'application */ + char suffix[4]; /* Suffixe à attribuer */ + + g_arch_instruction_lock_operands(instr); + + op = _g_arch_instruction_get_operand(instr, 0); + assert(G_IS_ARMV7_ITCOND_OPERAND(op)); + + itcond = G_ARMV7_ITCOND_OPERAND(op); + + firstcond = g_armv7_itcond_operand_get_firstcond(itcond); + mask = g_armv7_itcond_operand_get_mask(itcond); + + firstcond &= 0x1; + + if ((mask & 0x7) == 0x4) + { + suffix[0] = ((mask & 0x8) >> 3) == firstcond ? 't' : 'e'; + suffix[1] = '\0'; + } + + else if ((mask & 0x3) == 0x2) + { + suffix[0] = ((mask & 0x8) >> 3) == firstcond ? 't' : 'e'; + suffix[1] = ((mask & 0x4) >> 2) == firstcond ? 't' : 'e'; + suffix[2] = '\0'; + } + + else if ((mask & 0x1) == 0x1) + { + suffix[0] = ((mask & 0x8) >> 3) == firstcond ? 't' : 'e'; + suffix[1] = ((mask & 0x4) >> 2) == firstcond ? 't' : 'e'; + suffix[2] = ((mask & 0x2) >> 1) == firstcond ? 't' : 'e'; + suffix[3] = '\0'; + } + + else + suffix[0] = '\0'; + + if (suffix[0] != '\0') + g_arm_instruction_extend_keyword(G_ARM_INSTRUCTION(instr), suffix); + + g_object_unref(G_OBJECT(itcond)); + + g_arch_instruction_unlock_operands(instr); + +} |