/* OpenIDA - Outil d'analyse de fichiers binaires * operand.c - gestion générique des opérandes * * Copyright (C) 2008 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 "operand.h" #include #include "operand-int.h" /****************************************************************************** * * * Paramètres : operand = structure dont le contenu est à définir. * * value = valeur immédiate à renseigner. * * * * Description : Crée une opérande pour l'instruction 'db'. * * * * Retour : true si l'opérande a été définie avec succès, false sinon. * * * * Remarques : - * * * ******************************************************************************/ bool fill_db_operand(asm_operand *operand, uint8_t value) { operand->type = AOT_NONE; operand->size = AOS_8_BITS; operand->value.val8 = value; return true; } /****************************************************************************** * * * Paramètres : operand = instruction à traiter. * * buffer = tampon de sortie mis à disposition. [OUT] * * len = taille de ce tampon. * * syntax = type de représentation demandée. * * * * Description : Traduit une opérande de type 'db' en texte. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void print_db_operand(const asm_operand *operand, char *buffer, size_t len, AsmSyntax syntax) { switch (syntax) { case ASX_INTEL: snprintf(buffer, len, "0x%02hhx", operand->value.val8); break; case ASX_ATT: snprintf(buffer, len, "$0x%02hhx", operand->value.val8); break; } } /****************************************************************************** * * * Paramètres : operand = structure dont le contenu est à définir. * * size = taille de l'opérande souhaitée. * * data = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * len = taille totale des données à analyser. * * * * Description : Crée une opérande contenant une valeur sur x bits. * * * * Retour : true si l'opération s'est effectuée avec succès, false sinon.* * * * Remarques : - * * * ******************************************************************************/ bool fill_imm_operand(asm_operand *operand, AsmOperandSize size, const uint8_t *data, off_t *pos, off_t len) { /* Vérifications sanitaires */ switch (size) { case AOS_8_BITS: if ((len - *pos) < 1) return false; break; case AOS_16_BITS: if ((len - *pos) < 2) return false; break; case AOS_32_BITS: if ((len - *pos) < 4) return false; break; case AOS_64_BITS: if ((len - *pos) < 8) return false; break; } operand->type = AOT_IMM; operand->size = size; switch (size) { case AOS_8_BITS: operand->value.val8 = data[*pos]; *pos += 1; break; case AOS_16_BITS: operand->value.val16 = data[*pos] | (uint16_t)data[*pos + 1] << 8; *pos += 2; break; case AOS_32_BITS: operand->value.val32 = data[*pos] | (uint32_t)data[*pos + 1] << 8 | (uint32_t)data[*pos + 2] << 16 | (uint32_t)data[*pos + 3] << 24; *pos += 4; break; case AOS_64_BITS: operand->value.val64 = data[*pos] | (uint64_t)data[*pos + 1] << 8 | (uint64_t)data[*pos + 2] << 16 | (uint64_t)data[*pos + 3] << 24 | (uint64_t)data[*pos + 4] << 32 | (uint64_t)data[*pos + 5] << 40 | (uint64_t)data[*pos + 6] << 48 | (uint64_t)data[*pos + 7] << 56; *pos += 8; break; } return true; } /****************************************************************************** * * * Paramètres : operand = structure dont le contenu est à définir. * * size = taille de l'opérande souhaitée. * * data = flux de données à analyser. * * pos = position courante dans ce flux. [OUT] * * len = taille totale des données à analyser. * * ref = adresse de référence. * * * * Description : Crée une opérande contenant une valeur relative sur x bits. * * * * Retour : true si l'opération s'est effectuée avec succès, false sinon.* * * * Remarques : - * * * ******************************************************************************/ bool fill_relimm_operand(asm_operand *operand, AsmOperandSize size, const uint8_t *data, off_t *pos, off_t len, uint64_t ref) { bool result; /* Bilan à retourner */ off_t old_pos; /* Sauvegarde de l'évolution */ int8_t val8; /* Valeur sur 8 bits */ int16_t val16; /* Valeur sur 16 bits */ uint32_t val32; /* Valeur sur 32 bits */ int64_t val64; /* Valeur sur 64 bits */ old_pos = *pos; result = fill_imm_operand(operand, size, data, pos, len); if (result) switch (size) { case AOS_8_BITS: if (operand->value.val8 & 0x80) { val8 = operand->value.val8 - 1; val8 = ~val8; operand->value.val8 = ref + (*pos - old_pos); operand->value.val8 -= val8; } else operand->value.val8 += ref + (*pos - old_pos); break; case AOS_16_BITS: if (operand->value.val16 & 0x8000) { val16 = operand->value.val16 - 1; val16 = ~val16; operand->value.val16 = ref + (*pos - old_pos); operand->value.val16 -= val16; } else operand->value.val16 += ref + (*pos - old_pos); break; case AOS_32_BITS: if (operand->value.val32 & 0x80000000) { val32 = operand->value.val32 - 1; val32 = ~val32; operand->value.val32 = ref + (*pos - old_pos); operand->value.val32 -= val32; } else operand->value.val32 += ref + (*pos - old_pos); break; case AOS_64_BITS: if (operand->value.val64 & 0x8000000000000000ull) { val64 = operand->value.val64 - 1; val64 = ~val64; operand->value.val64 = ref + (*pos - old_pos); operand->value.val64 -= val64; } else operand->value.val64 += ref + (*pos - old_pos); break; } return result; } /****************************************************************************** * * * Paramètres : operand = instruction à traiter. * * buffer = tampon de sortie mis à disposition. [OUT] * * len = taille de ce tampon. * * syntax = type de représentation demandée. * * * * Description : Traduit une opérande de valeur immédiate en texte. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void print_imm_operand(const asm_operand *operand, char *buffer, size_t len, AsmSyntax syntax) { switch (syntax) { case ASX_INTEL: switch (operand->size) { case AOS_8_BITS: snprintf(buffer, len, "0x%hhx", operand->value.val8); break; case AOS_16_BITS: snprintf(buffer, len, "0x%hx", operand->value.val16); break; case AOS_32_BITS: snprintf(buffer, len, "0x%x", operand->value.val32); break; case AOS_64_BITS: snprintf(buffer, len, "0x%llx", operand->value.val64); break; } break; case ASX_ATT: switch (operand->size) { case AOS_8_BITS: snprintf(buffer, len, "$0x%hhx", operand->value.val8); break; case AOS_16_BITS: snprintf(buffer, len, "$0x%hx", operand->value.val16); break; case AOS_32_BITS: snprintf(buffer, len, "$0x%x", operand->value.val32); break; case AOS_64_BITS: snprintf(buffer, len, "$0x%llx", operand->value.val64); break; } break; } }