/* Chrysalide - Outil d'analyse de fichiers binaires
* instruction.c - gestion générique des instructions
*
* Copyright (C) 2008-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 .
*/
#include "instruction.h"
#include
#include
#include
#include "instruction-int.h"
#include "../glibext/linegen-int.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 *);
/* Procède à l'initialisation de l'interface de génération. */
static void g_arch_instruction_interface_init(GLineGeneratorInterface *);
/* Supprime toutes les références externes. */
static void g_arch_instruction_dispose(GArchInstruction *);
/* Procède à la libération totale de la mémoire. */
static void g_arch_instruction_finalize(GArchInstruction *);
/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
/* Dénombre les liens présents à une extrémité donnée. */
static size_t g_arch_instruction_get_link_counter(GArchInstruction *, bool);
#define g_arch_instruction_get_source_counter(ins) \
g_arch_instruction_get_link_counter(ins, true)
#define g_arch_instruction_get_destination_counter(ins) \
g_arch_instruction_get_link_counter(ins, false)
/* Incrémente le nombre de liens définis à une extrémité donnée. */
static size_t g_arch_instruction_inc_link_counter(GArchInstruction *, bool);
#define g_arch_instruction_inc_source_counter(ins) \
g_arch_instruction_inc_link_counter(ins, true)
#define g_arch_instruction_inc_destination_counter(ins) \
g_arch_instruction_inc_link_counter(ins, false)
/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
/* Indique le nombre de ligne prêtes à être générées. */
static size_t g_arch_instruction_count_lines(const GArchInstruction *);
/* Retrouve l'emplacement correspondant à une position donnée. */
static void g_arch_instruction_compute_addr(const GArchInstruction *, gint, vmpa2t *, size_t, size_t);
/* Détermine si le conteneur s'inscrit dans une plage donnée. */
static int g_arch_instruction_contains_addr(const GArchInstruction *, const vmpa2t *, size_t, size_t);
/* Renseigne sur les propriétés liées à un générateur. */
static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *, size_t, size_t);
/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
static void _g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t);
/* Imprime dans une ligne de rendu le contenu représenté. */
static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t);
/* Indique le type défini pour une instruction d'architecture. */
G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_interface_init));
/******************************************************************************
* *
* 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)
{
GObjectClass *object; /* Autre version de la classe */
GArchInstructionClass *instr; /* Encore une autre vision... */
object = G_OBJECT_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_instruction_dispose;
object->finalize = (GObjectFinalizeFunc)g_arch_instruction_finalize;
instr = G_ARCH_INSTRUCTION_CLASS(klass);
instr->print = (print_instruction_fc)_g_arch_instruction_print;
}
/******************************************************************************
* *
* Paramètres : instr = instance à initialiser. *
* *
* Description : Initialise une instance d'instruction d'architecture. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_arch_instruction_init(GArchInstruction *instr)
{
instr->from_count = 0;
instr->to_count = 0;
}
/******************************************************************************
* *
* Paramètres : iface = interface GLib à initialiser. *
* *
* Description : Procède à l'initialisation de l'interface de génération. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_arch_instruction_interface_init(GLineGeneratorInterface *iface)
{
iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines;
iface->compute = (linegen_compute_fc)g_arch_instruction_compute_addr;
iface->contains = (linegen_contains_fc)g_arch_instruction_contains_addr;
iface->get_flags = (linegen_get_flags_fc)g_arch_instruction_get_flags2;
iface->print = (linegen_print_fc)g_arch_instruction_print;
}
/******************************************************************************
* *
* Paramètres : instr = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_arch_instruction_dispose(GArchInstruction *instr)
{
if (instr->content != NULL)
g_object_unref(G_OBJECT(instr->content));
G_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr));
}
/******************************************************************************
* *
* Paramètres : instr = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_arch_instruction_finalize(GArchInstruction *instr)
{
G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr));
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à consulter. *
* *
* Description : Indique l'encodage d'une instruction de façon détaillée. *
* *
* Retour : Description humaine de l'encodage utilisé. *
* *
* Remarques : - *
* *
******************************************************************************/
const char *g_arch_instruction_get_encoding(const GArchInstruction *instr)
{
return G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_encoding(instr);
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à modifier. *
* flag = drapeau d'information complémentaire à planter. *
* *
* Description : Ajoute une information complémentaire à une instruction. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag)
{
instr->flags |= flag;
return true;
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à modifier. *
* *
* Description : Fournit les informations complémentaires d'une instruction. *
* *
* Retour : Eventuels drapeaux d'information complémentaire à plantés. *
* *
* Remarques : - *
* *
******************************************************************************/
ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
{
return instr->flags;
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à modifier. *
* type = type de procédure à mémoriser. *
* hook = fonction à appeler sur commande. *
* *
* Description : Définit un traitement complémentare au désassemblage. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_set_hooks(GArchInstruction *instr, const instr_hook_fc hooks[IPH_COUNT])
{
instr->hooks = hooks;
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à traiter. *
* type = type de procédure à utiliser. *
* proc = représentation de l'architecture utilisée. *
* context = contexte associé à la phase de désassemblage. *
* format = accès aux données du binaire d'origine. *
* *
* Description : Complète un désassemblage accompli pour une instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format)
{
assert(type < IPH_COUNT);
if (instr->hooks != NULL && instr->hooks[type] != NULL)
instr->hooks[type](instr, proc, context, format);
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à modifier. *
* content = contenu binaire global à référencer. *
* *
* Description : Note le contenu du sein duquel l'instruction est issue. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_set_global_content(GArchInstruction *instr, const GBinContent *content)
{
g_object_ref(G_OBJECT(content));
instr->content = content;
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à modifier. *
* address = adresse virtuelle et/ou position physique. *
* length = taille de l'instruction. *
* *
* Description : Définit la localisation d'une instruction. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_set_range(GArchInstruction *instr, const mrange_t *range)
{
copy_mrange(&instr->range, range);
}
/******************************************************************************
* *
* Paramètres : instr = instruction quelconque à consulter. *
* *
* Description : Fournit la place mémoire d'une instruction. *
* *
* Retour : Zone mémoire couverte par l'instruction. *
* *
* Remarques : - *
* *
******************************************************************************/
const mrange_t *g_arch_instruction_get_range(const GArchInstruction *instr)
{
return &instr->range;
}
/******************************************************************************
* *
* 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(const 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 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 à consulter. *
* *
* Description : Indique la quantité d'opérandes présents dans l'instruction. *
* *
* Retour : Nombre d'opérandes attachés. *
* *
* Remarques : - *
* *
******************************************************************************/
size_t g_arch_instruction_count_operands(const GArchInstruction *instr)
{
return instr->operands_count;
}
/******************************************************************************
* *
* Paramètres : instr = instance à mettre à jour. *
* index = indice de l'opérande concernée. *
* *
* Description : Fournit un opérande donné d'une instruction. *
* *
* Retour : Opérande trouvée ou NULL si aucune. *
* *
* Remarques : - *
* *
******************************************************************************/
GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index)
{
GArchOperand *result; /* Opérande à retourner */
if (index >= instr->operands_count) result = NULL;
else result = instr->operands[index];
/* TODO : incrémenter la référence ! */
return result;
}
/******************************************************************************
* *
* Paramètres : instr = instance à mettre à jour. *
* new = nouvelle opérande à attacher. *
* old = ancienne opérande à détacher. *
* *
* Description : Remplace un opérande d'une instruction par un autre. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *new, const GArchOperand *old)
{
size_t i; /* Boucle de parcours */
for (i = 0; i < instr->operands_count; i++)
if (instr->operands[i] == old)
break;
if (i < instr->operands_count)
{
g_object_unref(G_OBJECT(instr->operands[i]));
instr->operands[i] = new;
}
}
/******************************************************************************
* *
* 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 à consulter. *
* rregs = liste des rgistres lus. [OUT] *
* rcount = nombre de registres lus. [OUT] *
* wregs = liste des rgistres écrits. [OUT] *
* wcount = nombre de registres écrits. [OUT] *
* *
* Description : Liste les registres lus et écrits par l'instruction. *
* *
* Retour : - *
* *
* Remarques : Les compteurs de références sont à décrémenter après usage ! *
* *
******************************************************************************/
void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount)
{
#if 0
size_t i; /* Boucle de parcours */
*rregs = NULL;
*rcount = 0;
*wregs = NULL;
*wcount = 0;
instr->get_rw_regs(instr, rregs, rcount, wregs, wcount);
for (i = 0; i < *rcount; i++)
g_object_ref(G_OBJECT((*rregs)[i]));
for (i = 0; i < *wcount; i++)
g_object_ref(G_OBJECT((*wregs)[i]));
#endif
}
/* ---------------------------------------------------------------------------------- */
/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : instr = instruction à mettre à jour. *
* src = sélection de l'extrémité à traiter. *
* write = précise le type d'accès prévu (lecture/écriture). *
* lock = indique le sens du verrouillage à mener. *
* *
* Description : Met à disposition un encadrement des accès aux liens. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool write, bool lock)
{
volatile gint *address; /* Choix de l'entier à traiter */
address = (src ? &instr->from_count : &instr->to_count);
if (lock)
g_bit_lock(address, INSTR_LINK_LOCK_BIT);
else
g_bit_unlock(address, INSTR_LINK_LOCK_BIT);
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* src = sélection de l'extrémité à traiter. *
* *
* Description : Dénombre les liens présents à une extrémité donnée. *
* *
* Retour : Quantité positive. *
* *
* Remarques : - *
* *
******************************************************************************/
static size_t g_arch_instruction_get_link_counter(GArchInstruction *instr, bool src)
{
size_t result; /* Nombre de liens à renvoyer */
volatile gint *address; /* Choix de l'entier à traiter */
address = (src ? &instr->from_count : &instr->to_count);
assert(!g_bit_trylock(address, INSTR_LINK_LOCK_BIT));
result = g_atomic_int_get(address) & ~(1 << INSTR_LINK_LOCK_BIT);
return result;
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* src = sélection de l'extrémité à traiter. *
* *
* Description : Incrémente le nombre de liens définis à une extrémité donnée.*
* *
* Retour : Nouvelle quantité mise à jour. *
* *
* Remarques : - *
* *
******************************************************************************/
static size_t g_arch_instruction_inc_link_counter(GArchInstruction *instr, bool src)
{
size_t result; /* Nombre de liens à renvoyer */
volatile gint *address; /* Choix de l'entier à traiter */
address = (src ? &instr->from_count : &instr->to_count);
assert(!g_bit_trylock(address, INSTR_LINK_LOCK_BIT));
result = g_atomic_int_get(address) & ~(1 << INSTR_LINK_LOCK_BIT);
result++;
assert((result & (1 << INSTR_LINK_LOCK_BIT)) == 0);
g_atomic_int_set(address, (1 << INSTR_LINK_LOCK_BIT) | result);
return result;
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* dest = ligne visée par la liaison (côté destination). *
* type = type de lien à construire. *
* ... = éventuelles informations complémentaires. *
* *
* Description : Etablit un lien entre deux instructions. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
{
size_t count; /* Raccourci pour la lecture */
instr_link_t *new; /* Nouveau lien à définir */
/* Côté destination */
g_arch_instruction_wlock_src(dest);
count = g_arch_instruction_inc_source_counter(dest);
dest->from = (instr_link_t *)realloc(dest->from, count * sizeof(instr_link_t));
new = &dest->from[count - 1];
new->linked = instr;
new->type = type;
g_arch_instruction_wunlock_src(dest);
/* Côté point de départ */
g_arch_instruction_wlock_dest(instr);
count = g_arch_instruction_inc_destination_counter(instr);
instr->to = (instr_link_t *)realloc(instr->to, count * sizeof(instr_link_t));
new = &instr->to[count - 1];
new->linked = dest;
new->type = type;
g_arch_instruction_wunlock_dest(instr);
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* dest = ligne visée par la liaison (côté destination). *
* old = ancien type de lien construit. *
* new = nouveau type de lien à construire. *
* *
* Description : Change la nature d'un lien entre deux instructions. *
* *
* Retour : true pour une mise à jour réussie, false sinon. *
* *
* Remarques : Le verrou doit être posé sur les destination de 'instr'. *
* *
******************************************************************************/
bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new)
{
bool result; /* Bilan à retourner */
size_t count; /* Raccourci pour la lecture */
size_t i; /* Boucle de parcours */
size_t from_idx; /* Indice côté destination */
size_t to_idx; /* Indice côté source */
result = false;
assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
g_arch_instruction_wlock_src(dest);
/* Côté destination */
count = g_arch_instruction_get_source_counter(dest);
for (i = 0; i < count; i++)
if (dest->from[i].linked == instr && dest->from[i].type == old)
break;
if (i == count)
goto gaicl_exit;
else
from_idx = i;
/* Côté point de départ */
count = g_arch_instruction_get_destination_counter(instr);
for (i = 0; i < count; i++)
if (instr->to[i].linked == dest && instr->to[i].type == old)
break;
if (i == count)
goto gaicl_exit;
else
to_idx = i;
/* Si les deux extrémités sont raccord... */
dest->from[from_idx].type = new;
instr->to[to_idx].type = new;
result = true;
gaicl_exit:
g_arch_instruction_wunlock_src(dest);
return result;
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* *
* Description : Indique si l'instruction a une ou plusieurs origines. *
* *
* Retour : Bilan de la consultation. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_arch_instruction_has_sources(GArchInstruction *instr)
{
size_t count; /* Nombre de liens présents */
assert(!g_bit_trylock(&instr->from_count, INSTR_LINK_LOCK_BIT));
count = g_arch_instruction_get_source_counter(instr);
return (count > 0);
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter.*
* sources = liste des liens aux instructions d'origine. [OUT] *
* *
* Description : Fournit les origines d'une instruction donnée. *
* *
* Retour : Nombre de ces origines. *
* *
* Remarques : - *
* *
******************************************************************************/
size_t g_arch_instruction_get_sources(GArchInstruction *instr, instr_link_t **sources)
{
assert(!g_bit_trylock(&instr->from_count, INSTR_LINK_LOCK_BIT));
if (sources != NULL)
*sources = instr->from;
return g_arch_instruction_get_source_counter(instr);
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* *
* Description : Indique si l'instruction a une suite autre que la suivante. *
* *
* Retour : Bilan de la consultation. *
* *
* Remarques : - *
* *
******************************************************************************/
bool g_arch_instruction_has_destinations(GArchInstruction *instr)
{
size_t count; /* Nombre de liens présents */
assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
count = g_arch_instruction_get_destination_counter(instr);
return (count > 0);
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* dests = liste de liens aux instructions de destination. [OUT]*
* *
* Description : Fournit les destinations d'une instruction donnée. *
* *
* Retour : Nombre de ces destinations. *
* *
* Remarques : - *
* *
******************************************************************************/
size_t g_arch_instruction_get_destinations(GArchInstruction *instr, instr_link_t **dests)
{
assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
if (dests != NULL)
*dests = instr->to;
return g_arch_instruction_get_destination_counter(instr);
}
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* type = type de lien recherché. *
* *
* Description : Fournit la destination d'une instruction et d'un type donné. *
* *
* Retour : Instruction de destination trouvée ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *instr, InstructionLinkType type)
{
GArchInstruction *result; /* Résultat à remonter */
size_t count; /* Nombre de liens à parcourir */
size_t i; /* Boucle de parcours */
result = NULL;
assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
count = g_arch_instruction_get_destination_counter(instr);
for (i = 0; i < count && result == NULL; i++)
if (instr->to[i].type == type)
result = instr->to[i].linked;
return result;
}
/******************************************************************************
* *
* Paramètres : iter = membre du groupe donné en référence. *
* list = liste des instructions à analyser. *
* count = taille de cette liste. *
* *
* Description : Indique la position dans les instructions identiques. *
* *
* Retour : Indice dans les instructions identiques du groupe. *
* *
* Remarques : - *
* *
******************************************************************************/
size_t g_arch_instruction_compute_group_index(GArchInstruction **iter, GArchInstruction **list, size_t count)
{
size_t result; /* Valeur à retourner */
size_t i; /* Boucle de parcours */
result = 0;
for (i = 0; i < count; i++)
{
if ((list + i) == iter)
break;
if (list[i] == *iter)
result++;
}
return result;
}
/* ---------------------------------------------------------------------------------- */
/* CONVERSIONS DU FORMAT DES INSTRUCTIONS */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : instr = instruction d'assemblage à consulter. *
* syntax = type de représentation demandée. *
* *
* Description : Fournit le nom humain de l'instruction manipulée. *
* *
* Retour : Mot clef de bas niveau. *
* *
* Remarques : - *
* *
******************************************************************************/
const char *g_arch_instruction_get_keyword(GArchInstruction *instr, AsmSyntax syntax)
{
const char *result; /* Désignation à retourner */
result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_keyword(instr, syntax);
return result;
}
/* ---------------------------------------------------------------------------------- */
/* OFFRE DE CAPACITES DE GENERATION */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
* *
* Paramètres : instr = générateur à consulter. *
* *
* Description : Indique le nombre de ligne prêtes à être générées. *
* *
* Retour : Nombre de lignes devant apparaître au final. *
* *
* Remarques : - *
* *
******************************************************************************/
static size_t g_arch_instruction_count_lines(const GArchInstruction *instr)
{
return 1;
}
/******************************************************************************
* *
* Paramètres : instr = générateur à consulter. *
* x = position géographique sur la ligne concernée. *
* addr = position en mémoire à analyser. *
* index = indice de cette même ligne dans le tampon global. *
* repeat = indice d'utilisations successives du générateur. *
* *
* Description : Retrouve l'emplacement correspondant à une position donnée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_arch_instruction_compute_addr(const GArchInstruction *instr, gint x, vmpa2t *addr, size_t index, size_t repeat)
{
copy_vmpa(addr, get_mrange_addr(&instr->range));
}
/******************************************************************************
* *
* Paramètres : instr = générateur à consulter. *
* addr = position en mémoire à analyser. *
* index = indice de cette même ligne dans le tampon global. *
* repeat = indice d'utilisations successives du générateur. *
* *
* Description : Détermine si le conteneur s'inscrit dans une plage donnée. *
* *
* Retour : Bilan de la détermination, utilisable en comparaisons. *
* *
* Remarques : - *
* *
******************************************************************************/
static int g_arch_instruction_contains_addr(const GArchInstruction *instr, const vmpa2t *addr, size_t index, size_t repeat)
{
int result; /* Conclusion à retourner */
result = cmp_mrange_with_vmpa(&instr->range, addr);
return result;
}
/******************************************************************************
* *
* Paramètres : instr = générateur à consulter. *
* index = indice de cette même ligne dans le tampon global. *
* repeat = indice d'utilisations successives du générateur. *
* *
* Description : Renseigne sur les propriétés liées à un générateur. *
* *
* Retour : Propriétés particulières associées. *
* *
* Remarques : - *
* *
******************************************************************************/
static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *instr, size_t index, size_t repeat)
{
return BLF_HAS_CODE;
}
/******************************************************************************
* *
* Paramètres : instr = instruction d'assemblage à représenter. *
* buffer = espace où placer ledit contenu. *
* msize = taille idéale des positions et adresses; *
* content = contenu binaire global à venir lire. *
* syntax = type de représentation demandée. *
* *
* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void _g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat)
{
const char *key; /* Mot clef principal */
size_t klen; /* Taille de ce mot clef */
size_t i; /* Boucle de parcours */
g_buffer_line_fill_vmpa(line, get_mrange_addr(&instr->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED);
g_buffer_line_fill_content(line, instr->content, &instr->range, VMPA_NO_PHYSICAL);
/* Instruction proprement dite */
key = g_arch_instruction_get_keyword(instr, 0/*, syntax*/);
klen = strlen(key);
g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL);
if (instr->operands_count > 0)
{
g_arch_operand_print(instr->operands[0], line, 0/*syntax*/);
for (i = 1; i < instr->operands_count; i++)
{
g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
g_arch_operand_print(instr->operands[i], line, 0/*syntax*/);
}
}
}
/******************************************************************************
* *
* Paramètres : instr = générateur à utiliser pour l'impression. *
* line = ligne de rendu à compléter. *
* index = indice de cette même ligne dans le tampon global. *
* repeat = indice d'utilisations successives du générateur. *
* *
* Description : Imprime dans une ligne de rendu le contenu représenté. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat)
{
G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat);
}