diff options
Diffstat (limited to 'plugins/arm/v7/helpers.c')
-rw-r--r-- | plugins/arm/v7/helpers.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/plugins/arm/v7/helpers.c b/plugins/arm/v7/helpers.c new file mode 100644 index 0000000..03786c0 --- /dev/null +++ b/plugins/arm/v7/helpers.c @@ -0,0 +1,277 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helpers.c - aide à la mise en place des opérandes ARMv7 + * + * Copyright (C) 2014-2017 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "helpers.h" + + +#include <arch/register.h> +#include <arch/immediate.h> +#include <common/asm.h> +#include <common/bconst.h> + + +#include "register.h" + + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* shift = nombre de décallages visés. * +* * +* Description : Effectue une rotation vers la droit d'une valeur. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : Correspond à la pseudo fonction 'ROR_C'. * +* * +******************************************************************************/ + +GArchOperand *ror_armv7_imm(uint32_t x, unsigned int shift) +{ + GArchOperand *result; /* Opérande à faire remonter */ + uint32_t val32; /* Valeur sur 32 bits */ + + shift %= 32; + + val32 = (x >> shift) | (x << (32 - shift)); + + result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, val32); + + return result; + +} + + + + + + + + + + + + +#if 0 + +// Shift_C() +// ========= +(bits(N), bit) Shift_C(bits(N) value, SRType type, integer amount, bit carry_in) +assert !(type == SRType_RRX && amount != 1); +if amount == 0 then +(result, carry_out) = (value, carry_in); +else +case type of + +when SRType_LSL +(result, carry_out) = LSL_C(value, amount); + +when SRType_LSR +(result, carry_out) + +when SRType_ASR +(result, carry_out) + +when SRType_ROR +(result, carry_out) + +when SRType_RRX +(result, carry_out) += LSR_C(value, amount); += ASR_C(value, amount); += ROR_C(value, amount); += RRX_C(value, carry_in); + +#endif + + + + + + +/****************************************************************************** +* * +* Paramètres : value = valeur sur 32 bits maximum à traiter. * +* topbit = valeur du bit de poids fort manipulé. * +* size = taille de la valeur finale à constituer. * +* * +* Description : Crée un opérande de valeur immédiate avec extension de signe.* +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *sign_extend_armv7_imm(uint32_t value, bool topbit, unsigned int size) +{ + GArchOperand *result; /* Opérande à faire remonter */ + unsigned int msb; /* Position du premier bit à 1 */ + MemoryDataSize mds; /* Conversion de la taille */ + uint32_t val4; /* Valeur sur 4 bits */ + uint32_t val8; /* Valeur sur 8 bits */ + uint32_t val16; /* Valeur sur 16 bits */ + uint32_t val32; /* Valeur sur 32 bits */ + unsigned int i; /* Boucle de parcours */ + + result = NULL; + + topbit &= msb_32(value, &msb); + + switch (size) + { + +#define SIGN_EXTEND_CASE(sz) \ + case sz: \ + mds = MDS_ ## sz ## _BITS_SIGNED; \ + val ## sz = value; \ + if (topbit) \ + for (i = msb; i < sz; i++) \ + val ## sz |= (1 << i); \ + result = g_imm_operand_new_from_value(mds, val ## sz); \ + break; + + SIGN_EXTEND_CASE(4); + SIGN_EXTEND_CASE(8); + SIGN_EXTEND_CASE(16); + SIGN_EXTEND_CASE(32); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : value = valeur sur 32 bits maximum à traiter. * +* * +* Description : Etend une valeur immédiate en mode 'Thumb' ARMv7. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *thumb_expand_armv7_imm(uint32_t value) +{ + GArchOperand *result; /* Opérande à faire remonter */ + uint8_t byte; /* Octet à reproduire */ + uint32_t val32; /* Valeur sur 32 bits */ + uint32_t unrotated; /* Transformation à décaller */ + + result = NULL; + + if (((value >> 10) & b11) == b00) + { + byte = value & 0xff; + + switch ((value >> 8) & b11) + { + case b00: + result = zero_extend_armv7_imm(byte, 32); + break; + + case b01: + if (byte == 0) return NULL; + val32 = byte << 16 | byte; + result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, val32); + break; + + case b10: + if (byte == 0) return NULL; + val32 = byte << 24 | byte << 8; + result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, val32); + break; + + case b11: + if (byte == 0) return NULL; + val32 = byte << 24 | byte << 16 | byte << 8 | byte; + result = g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, val32); + break; + + } + + } + else + { + unrotated = 1 << 7 | (value & 0x3f); + result = ror_armv7_imm(unrotated, (value >> 7) & 0x1f); + } + + return result; + +} + + + + + + +/****************************************************************************** +* * +* Paramètres : value = valeur sur 32 bits maximum à traiter. * +* size = taille de la valeur finale à constituer. * +* * +* Description : Réalise un simple transtypage de valeur entière. * +* * +* Retour : Adresse de la structure mise en place. * +* * +* Remarques : Correspond à la pseudo fonction 'ZeroExtend'. * +* * +******************************************************************************/ + +GArchOperand *zero_extend_armv7_imm(uint32_t value, unsigned int size) +{ + GArchOperand *result; /* Opérande à faire remonter */ + MemoryDataSize mds; /* Conversion de la taille */ + uint32_t val4; /* Valeur sur 4 bits */ + uint32_t val8; /* Valeur sur 8 bits */ + uint32_t val16; /* Valeur sur 16 bits */ + uint32_t val32; /* Valeur sur 32 bits */ + + result = NULL; + + switch (size) + { + +#define ZERO_EXTEND_CASE(sz) \ + case sz: \ + mds = MDS_ ## sz ## _BITS_UNSIGNED; \ + val ## sz = value; \ + result = g_imm_operand_new_from_value(mds, val ## sz); \ + break; + + ZERO_EXTEND_CASE(4); + ZERO_EXTEND_CASE(8); + ZERO_EXTEND_CASE(16); + ZERO_EXTEND_CASE(32); + + } + + return result; + +} |