/* OpenIDA - Outil d'analyse de fichiers binaires
* instruction.c - gestion générique des instructions
*
* 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 "instruction.h"
#include
#include "instruction-int.h"
#include "../common/extstr.h"
/* Initialise la classe générique des instructions. */
static void g_arch_instruction_class_init(GArchInstructionClass *);
/* Initialise une instance d'opérande d'architecture. */
static void g_arch_instruction_init(GArchInstruction *);
/* Indique le type défini pour une instruction d'architecture. */
G_DEFINE_TYPE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe générique des instructions. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_arch_instruction_class_init(GArchInstructionClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : instr = instance à initialiser. *
* *
* Description : Initialise une instance d'instruction d'architecture. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_arch_instruction_init(GArchInstruction *instr)
{
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à modifier. *
* offset = position physique dans le code binaire. *
* length = taille de l'instruction. *
* address = adresse virtuelle ou position physique. *
* *
* Description : Définit la localisation d'une instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_set_location(GArchInstruction *instr, off_t offset, off_t length, vmpa_t address)
{
instr->offset = offset;
instr->length = length;
instr->address = address;
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à consulter. *
* offset = position physique dans le code binaire/NULL. [OUT] *
* length = taille de l'instruction ou NULL. [OUT] *
* address = adresse virtuelle ou position physique/NULL. [OUT] *
* *
* Description : Fournit la localisation d'une instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_get_location(GArchInstruction *instr, off_t *offset, off_t *length, vmpa_t *address)
{
if (offset != NULL) *offset = instr->offset;
if (length != NULL) *length = instr->length;
if (address != NULL) *address = instr->address;
}
/******************************************************************************
* *
* Paramètres : instr = instance à mettre à jour. *
* opererand = instruction à venir associer. *
* *
* Description : Attache un seul opérande à un instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_attach_one_operand(GArchInstruction *instr, GArchOperand *operand)
{
instr->operands = (GArchOperand **)calloc(1, sizeof(GArchOperand *));
instr->operands_count = 1;
instr->operands[0] = operand;
}
/******************************************************************************
* *
* Paramètres : instr = instance à mettre à jour. *
* operand1 = première instruction à venir associer. *
* operand2 = seconde instruction à venir associer. *
* *
* Description : Attache deux opérandes à un instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_attach_two_operands(GArchInstruction *instr, GArchOperand *operand1, GArchOperand *operand2)
{
instr->operands = (GArchOperand **)calloc(2, sizeof(GArchOperand *));
instr->operands_count = 2;
instr->operands[0] = operand1;
instr->operands[1] = operand2;
}
/******************************************************************************
* *
* Paramètres : instr = instance à mettre à jour. *
* opererand = instruction à venir associer. *
* *
* Description : Attache un opérande supplémentaire à une instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand)
{
instr->operands_count++;
instr->operands = (GArchOperand **)realloc(instr->operands, instr->operands_count * sizeof(GArchOperand *));
instr->operands[instr->operands_count - 1] = operand;
}
/******************************************************************************
* *
* Paramètres : instr = instance à mettre à jour. *
* opererand = instruction à venir dissocier. *
* *
* Description : Détache un opérande liée d'une instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *operand)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < instr->operands_count; i++)
if (instr->operands[i] == operand)
break;
if ((i + 1) < instr->operands_count)
memmove(&instr->operands[i], &instr->operands[i + 1],
(instr->operands_count - i - 1) * sizeof(GArchOperand *));
instr->operands_count--;
instr->operands = (GArchOperand **)realloc(instr->operands, instr->operands_count * sizeof(GArchOperand *));
}
/******************************************************************************
* *
* Paramètres : instr = instruction à traiter. *
* format = format du binaire manipulé. *
* syntax = type de représentation demandée. *
* *
* Description : Traduit une instruction en version humainement lisible. *
* *
* Retour : Chaîne de caractères à libérer de la mémoire. *
* *
* Remarques : - *
* *
******************************************************************************/
char *g_arch_instruction_get_text(const GArchInstruction *instr, const exe_format *format, AsmSyntax syntax)
{
char *result; /* Chaîne à retourner */
size_t i; /* Boucle de parcours */
char *opstr; /* Chaîne d'opérande */
if (instr->operands_count == 0)
result = strdup(instr->get_text(instr, format, syntax));
else
{
result = g_arch_operand_get_text(G_ARCH_INSTRUCTION(instr)->operands[0], format, syntax);
for (i = 1; i < instr->operands_count; i++)
{
result = stradd(result, ", ");
opstr = g_arch_operand_get_text(G_ARCH_INSTRUCTION(instr)->operands[i], format, syntax);
result = stradd(result, opstr);
free(opstr);
}
result = strprep(result, "\t");
result = strprep(result, instr->get_text(instr, format, syntax));
}
return result;
}