/* Chrysalide - Outil d'analyse de fichiers binaires * helpers.c - aide à la mise en place des opérandes ARMv7 * * Copyright (C) 2014 Cyrille Bagard * * This file is part of Chrysalide. * * Chrysalide is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Chrysalide is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "helpers.h" #include "register.h" #include "../../register.h" #include "../../immediate.h" #include "../../../common/asm.h" #include "../../../common/bconst.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; }