diff options
Diffstat (limited to 'plugins/arm/v7/pseudo.c')
-rw-r--r-- | plugins/arm/v7/pseudo.c | 683 |
1 files changed, 683 insertions, 0 deletions
diff --git a/plugins/arm/v7/pseudo.c b/plugins/arm/v7/pseudo.c new file mode 100644 index 0000000..f06e6a9 --- /dev/null +++ b/plugins/arm/v7/pseudo.c @@ -0,0 +1,683 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * pseudo.c - implémentation des pseudo-fonctions de spécification + * + * 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 "pseudo.h" + + +#include <stddef.h> + + +#include <common/bconst.h> + + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* shift = nombre de décallages visés. * +* carry = retenue enventuelle à constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'LSL_C'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_lsl_c(uint32_t x, unsigned int n, unsigned int shift, bool *carry, uint32_t *value) +{ + if (n > 32) return false; + if (shift == 0) return false; + + if (carry != NULL) + *carry = x & (1 << (n - 1)); + + *value = x << shift; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* shift = nombre de décallages visés. * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'LSL'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_lsl(uint32_t x, unsigned int n, unsigned int shift, uint32_t *value) +{ + bool result; /* Bilan final à retourner */ + + if (shift == 0) + result = true; + + else + result = armv7_lsl_c(x, n, shift, NULL, value); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* shift = nombre de décallages visés. * +* carry = retenue enventuelle à constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'LSR_C'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_lsr_c(uint32_t x, unsigned int n, unsigned int shift, bool *carry, uint32_t *value) +{ + if (n > 32) return false; + if (shift == 0) return false; + + if (carry != NULL) + *carry = x & (1 << (shift - 1)); + + *value = x >> shift; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* shift = nombre de décallages visés. * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'LSR'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_lsr(uint32_t x, unsigned int n, unsigned int shift, uint32_t *value) +{ + bool result; /* Bilan final à retourner */ + + if (shift == 0) + result = x; + + else + result = armv7_lsr_c(x, n, shift, NULL, value); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* shift = nombre de décallages visés. * +* carry = retenue enventuelle à constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'ASR_C'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_asr_c(uint32_t x, unsigned int n, unsigned int shift, bool *carry, uint32_t *value) +{ + if (n > 32) return false; + if (shift == 0) return false; + + if (carry != NULL) + *carry = x & (1 << (shift - 1)); + + *value = ((int32_t)x) >> shift; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* shift = nombre de décallages visés. * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'ASR'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_asr(uint32_t x, unsigned int n, unsigned int shift, uint32_t *value) +{ + bool result; /* Bilan final à retourner */ + + if (shift == 0) + result = true; + + else + result = armv7_asr_c(x, n, shift, NULL, value); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* shift = nombre de décallages visés. * +* carry = retenue enventuelle à constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'ROR_C'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_ror_c(uint32_t x, unsigned int n, unsigned int shift, bool *carry, uint32_t *value) +{ + if (n > 32) return false; + if (shift == 0) return false; + + *value = (x >> shift) | (x << (32 - shift)); + + if (carry != NULL) + *carry = *value & (1 << (n - 1)); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* shift = nombre de décallages visés. * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'ROR'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_ror(uint32_t x, unsigned int n, unsigned int shift, uint32_t *value) +{ + bool result; /* Bilan final à retourner */ + + if (shift == 0) + result = true; + + else + result = armv7_ror_c(x, n, shift, NULL, value); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* carry = retenue enventuelle à utiliser puis constituer. [OUT]* +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'RRX_C'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_rrx_c(uint32_t x, unsigned int n, bool *carry, uint32_t *value) +{ + bool new_c; /* Nouvelle retenue à retenir */ + + new_c = x & 0x1; + + *value = (*carry ? 1 : 0) << (n - 1) | x >> 1; + + *carry = new_c; + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* carry = retenue enventuelle à utiliser. * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'RRX'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_rrx(uint32_t x, unsigned int n, bool carry, uint32_t *value) +{ + return armv7_rrx_c(x, n, &carry, value); + +} + + +/****************************************************************************** +* * +* Paramètres : imm12 = valeur sur 32 bits maximum à traiter. * +* carry = retenue enventuelle à utiliser / constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'ARMExpandImm_C'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_arm_expand_imm_c(uint32_t imm12, bool *carry, uint32_t *value) +{ + bool result; /* Bilan final à retourner */ + uint32_t unrotated; /* Transformation à décaller */ + + /** + * Selon les spécifications, x contient toujours 12 bits utiles seulement. + */ + + unrotated = armv7_zero_extend(imm12 & 0xff, 8, 32); + + result = armv7_shift(unrotated, 32, SRType_ROR, 2 * ((imm12 >> 8) & 0xf), carry, value); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : imm12 = valeur sur 32 bits maximum à traiter. * +* carry = retenue enventuelle à utiliser / constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'ARMExpandImm'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_arm_expand_imm(uint32_t imm12, uint32_t *value) +{ + return armv7_arm_expand_imm_c(imm12, (bool []) { false /* FIXME : APSR.C */ }, value); + +} + + +/****************************************************************************** +* * +* Paramètres : imm12 = valeur sur 32 bits maximum à traiter. * +* carry = retenue enventuelle à utiliser / constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'ThumbExpandImm_C'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_thumb_expand_imm_c(uint32_t imm12, bool *carry, uint32_t *value) +{ + bool result; /* Conclusion à faire remonter */ + uint8_t byte; /* Octet à reproduire */ + uint32_t unrotated; /* Transformation à décaller */ + + result = true; + + if (((imm12 >> 10) & b11) == b00) + { + byte = imm12 & 0xff; + + switch ((imm12 >> 8) & b11) + { + case b00: + *value = armv7_zero_extend(byte, 8, 32); + break; + + case b01: + if (byte == 0) + result = false; + else + *value = byte << 16 | byte; + break; + + case b10: + if (byte == 0) + result = false; + else + *value = byte << 24 | byte << 8; + break; + + case b11: + if (byte == 0) + result = false; + else + *value = byte << 24 | byte << 16 | byte << 8 | byte; + break; + + } + + } + else + { + unrotated = 1 << 7 | (imm12 & 0x3f); + result = armv7_ror_c(unrotated, 32, (imm12 >> 7) & 0x1f, carry, value); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : imm12 = valeur sur 32 bits maximum à traiter. * +* carry = retenue enventuelle à utiliser / constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'ThumbExpandImm'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_thumb_expand_imm(uint32_t imm12, uint32_t *value) +{ + return armv7_thumb_expand_imm_c(imm12, (bool []) { false /* FIXME : APSR.C */ }, value); + +} + + +/****************************************************************************** +* * +* Paramètres : type2 = type de décallage encodé sur 2 bits. * +* imm5 = valeur de décallage entière sur 5 bits. * +* type = type de décallage à constituer. [OUT] * +* value = valeur pleine et entière à utiliser. [OUT] * +* * +* Description : Traduit la fonction 'DecodeImmShift'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_decode_imm_shift(uint8_t type2, uint8_t imm5, SRType *type, uint32_t *value) +{ + bool result; /* Bilan à retourner */ + + result = true; + + switch (type2) + { + case b00: + *type = SRType_LSL; + *value = imm5; + break; + + case b01: + *type = SRType_LSR; + *value = (imm5 == 0 ? 32 : imm5); + break; + + case b10: + *type = SRType_ASR; + *value = (imm5 == 0 ? 32 : imm5); + break; + + case b11: + if (imm5 == 0) + { + *type = SRType_RRX; + *value = 1; + } + else + { + *type = SRType_ROR; + *value = imm5; + } + break; + + default: + result = false; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : type2 = type de décallage encodé sur 2 bits. * +* type = type de décallage à constituer. [OUT] * +* * +* Description : Traduit la fonction 'DecodeRegShift'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_decode_reg_shift(uint8_t type2, SRType *type) +{ + bool result; /* Bilan à retourner */ + + result = true; + + switch (type2) + { + case b00: + *type = SRType_LSL; + break; + + case b01: + *type = SRType_LSR; + break; + + case b10: + *type = SRType_ASR; + break; + + case b11: + *type = SRType_ROR; + break; + + default: + result = false; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* type = type d'opération à mener. * +* amount = quantité liée à l'opération à mener. * +* carry = retenue enventuelle à utiliser / constituer. [OUT] * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'Shift_C'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_shift_c(uint32_t x, unsigned int n, SRType type, unsigned int amount, bool *carry, uint32_t *value) +{ + bool result; /* Bilan final à retourner */ + + if (type == SRType_RRX && amount != 1) return false; + + if (amount == 0) + { + *value = x; + return true; + } + + result = true; /* Pour GCC... */ + + switch (type) + { + case SRType_LSL: + result = armv7_lsl_c(x, n, amount, carry, value); + break; + + case SRType_LSR: + result = armv7_lsr_c(x, n, amount, carry, value); + break; + + case SRType_ASR: + result = armv7_asr_c(x, n, amount, carry, value); + break; + + case SRType_ROR: + result = armv7_ror_c(x, n, amount, carry, value); + break; + + case SRType_RRX: + result = armv7_rrx_c(x, n, carry, value); + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* type = type d'opération à mener. * +* amount = quantité liée à l'opération à mener. * +* carry = retenue enventuelle à utiliser. * +* value = nouvelle valeur calculée. [OUT] * +* * +* Description : Traduit la fonction 'Shift'. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool armv7_shift(uint32_t x, unsigned int n, SRType type, unsigned int amount, bool carry, uint32_t *value) +{ + return armv7_shift_c(x, n, type, amount, &carry, value); + +} + + +/****************************************************************************** +* * +* Paramètres : x = valeur sur 32 bits maximum à traiter. * +* n = nombre de bits à prendre en compte. * +* i = taille finale à obtenir. * +* * +* Description : Traduit la fonction 'ZeroExtend'. * +* * +* Retour : Nouvelle valeur calculée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +uint32_t armv7_zero_extend(uint32_t x, unsigned int n, unsigned int i) +{ + return x; + +} |