/* 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 "sharing/container-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 partage. */ static void g_arch_instruction_share_interface_init(GShareContainerInterface *); /* Procède à l'initialisation de l'interface de génération. */ static void g_arch_instruction_generator_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 *); /* ------------------------ 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, const GBinContent *); /* Imprime dans une ligne de rendu le contenu représenté. */ static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); /* 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_SHARE_CONTAINER, g_arch_instruction_share_interface_init) G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_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->operands = NULL; instr->from = NULL; instr->to = NULL; } /****************************************************************************** * * * Paramètres : iface = interface GLib à initialiser. * * * * Description : Procède à l'initialisation de l'interface de partage. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_arch_instruction_share_interface_init(GShareContainerInterface *iface) { iface->replace = (replace_shared_fc)g_arch_instruction_replace_operand; } /****************************************************************************** * * * 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_generator_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) { 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. * * 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 = 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 } /* ---------------------------------------------------------------------------------- */ /* MANIPULATION DES OPERANDES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : instr = instruction à mettre à jour. * * * * Description : Verrouille les accès à la liste des opérandes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_arch_instruction_lock_operands(GArchInstruction *instr) { lock_flat_array(&instr->operands); } /****************************************************************************** * * * Paramètres : instr = instruction à mettre à jour. * * * * Description : Déverrouille les accès à la liste des opérandes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_arch_instruction_unlock_operands(GArchInstruction *instr) { unlock_flat_array(&instr->operands); } /****************************************************************************** * * * Paramètres : instr = instance à mettre à jour. * * operand = 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) { g_arch_instruction_lock_operands(instr); add_item_to_flat_array(&instr->operands, &operand, sizeof(GArchOperand *)); g_arch_instruction_unlock_operands(instr); } /****************************************************************************** * * * 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) { size_t result; /* Décompte à retourner */ result = count_flat_array_items(instr->operands); return result; } /****************************************************************************** * * * Paramètres : instr = instance à consulter. * * index = indice de l'opérande concerné. * * * * Description : Fournit un opérande donné d'une instruction. * * * * Retour : Opérande trouvée. * * * * Remarques : - * * * ******************************************************************************/ GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index) { GArchOperand *result; /* Opérande à retourner */ GArchOperand **ptr; /* Adresse dans le tableau */ ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *)); result = *ptr; /* TODO : incrémenter la référence ! */ return result; } /****************************************************************************** * * * Paramètres : instr = instance à mettre à jour. * * old = ancien opérande à remplacer. * * new = nouvel opérande à intégrer. * * * * Description : Remplace un opérande d'une instruction par un autre. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new) { bool result; /* Bilan à retourner */ g_arch_instruction_lock_operands(instr); result = _g_arch_instruction_replace_operand(instr, old, new); g_arch_instruction_unlock_operands(instr); return result; } /****************************************************************************** * * * Paramètres : instr = instance à mettre à jour. * * old = ancienne opérande à détacher. * * new = nouvelle opérande à attacher. * * * * Description : Remplace un opérande d'une instruction par un autre. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new) { bool result; /* Bilan à retourner */ size_t count; /* Nombre d'opérandes en place */ size_t i; /* Boucle de parcours */ GArchOperand *op; /* Opérande à manipuler */ result = false; count = _g_arch_instruction_count_operands(instr); for (i = 0; i < count; i++) { op = _g_arch_instruction_get_operand(instr, i); if (op == old) { result = true; break; } } if (result) { rpl_item_in_flat_array(instr->operands, i, &new, sizeof(GArchOperand *)); //g_object_unref(G_OBJECT(old)); } return result; } /****************************************************************************** * * * Paramètres : instr = instance à mettre à jour. * * target = 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 *target) { size_t count; /* Nombre d'opérandes en place */ size_t i; /* Boucle de parcours */ GArchOperand *op; /* Opérande à manipuler */ count = _g_arch_instruction_count_operands(instr); for (i = 0; i < count; i++) { op = _g_arch_instruction_get_operand(instr, i); if (op == target) break; } rem_item_from_flat_array(&instr->operands, i, sizeof(GArchOperand *)); g_object_unref(G_OBJECT(target)); } /* ---------------------------------------------------------------------------------- */ /* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : instr = instruction à mettre à jour. * * src = sélection de l'extrémité à traiter. * * 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 lock) { flat_array_t **array; /* Choix du tableau ciblé */ array = (src ? &instr->from : &instr->to); if (lock) lock_flat_array(array); else unlock_flat_array(array); } /****************************************************************************** * * * Paramètres : instr = instruction dont les informations sont à consulter. * * dest = ligne visée par la liaison (côté destination). * * * * Description : Détermine si un lien est déjà établi entre deux instructions.* * * * Retour : Bilan de l'état actuel des liaisons. * * * * Remarques : - * * * ******************************************************************************/ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruction *dest) { bool result; /* Bilan à retourner */ size_t count; /* Nombre de liens à parcourir */ size_t i; /* Boucle de parcours */ instr_link_t *dlink; /* Définition de destination */ result = false; g_arch_instruction_lock_dest(instr); count = g_arch_instruction_count_destinations(instr); for (i = 0; i < count && !result; i++) { dlink = g_arch_instruction_get_destination(instr, i); result = (dlink->linked == dest); } g_arch_instruction_unlock_dest(instr); 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. * * * * Description : Etablit un lien entre deux instructions. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type) { instr_link_t new_src; /* Nouveau lien à définir #1 */ instr_link_t new_dst; /* Nouveau lien à définir #2 */ /* Côté destination */ new_src.linked = instr; new_src.type = type; /* Côté point de départ */ new_dst.linked = dest; new_dst.type = type; /* Ajout dans le respect d'une cohérence globale */ g_arch_instruction_lock_src(dest); g_arch_instruction_lock_dest(instr); add_item_to_flat_array(&dest->from, &new_src, sizeof(instr_link_t)); add_item_to_flat_array(&instr->to, &new_dst, sizeof(instr_link_t)); g_arch_instruction_unlock_dest(instr); g_arch_instruction_unlock_src(dest); } /****************************************************************************** * * * 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 destinations 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 */ instr_link_t *slink; /* Définition de source */ instr_link_t *dlink; /* Définition de destination */ result = false; g_arch_instruction_lock_src(dest); /* Côté destination */ count = g_arch_instruction_count_sources(dest); for (i = 0; i < count; i++) { slink = g_arch_instruction_get_source(dest, i); if (slink->linked == instr && slink->type == old) break; } if (i == count) goto gaicl_exit; /* Côté point de départ */ count = g_arch_instruction_count_destinations(instr); for (i = 0; i < count; i++) { dlink = g_arch_instruction_get_destination(instr, i); if (dlink->linked == dest && dlink->type == old) break; } if (i == count) goto gaicl_exit; /* Si les deux extrémités sont raccord... */ slink->type = new; dlink->type = new; result = true; gaicl_exit: g_arch_instruction_unlock_src(dest); return result; } /****************************************************************************** * * * Paramètres : instr = instruction dont les informations sont à consulter. * * * * Description : Fournit la quantité d'instructions pointant vers une autre. * * * * Retour : Nombre de ces origines. * * * * Remarques : - * * * ******************************************************************************/ size_t g_arch_instruction_count_sources(const GArchInstruction *instr) { size_t result; /* Nombre de liens à renvoyer */ result = count_flat_array_items(instr->from); return result; } /****************************************************************************** * * * Paramètres : instr = instruction dont les informations sont à consulter. * * index = indice de l'élément à retrouver. * * * * Description : Fournit les détails d'une origine d'une instruction donnée. * * * * Retour : Lien déterminé vers une instruction d'origine. * * * * Remarques : - * * * ******************************************************************************/ instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_t index) { instr_link_t *result; /* Détails présents à renvoyer */ result = get_flat_array_item(instr->from, index, sizeof(instr_link_t)); return result; } /****************************************************************************** * * * Paramètres : instr = instruction dont les informations sont à consulter. * * * * Description : Donne le nombre d'instructions non naturellement suivantes. * * * * Retour : Nombre de ces destinations. * * * * Remarques : - * * * ******************************************************************************/ size_t g_arch_instruction_count_destinations(const GArchInstruction *instr) { size_t result; /* Nombre de liens à renvoyer */ result = count_flat_array_items(instr->to); return result; } /****************************************************************************** * * * Paramètres : instr = instruction dont les informations sont à consulter. * * index = indice de l'élément à retrouver. * * * * Description : Fournit les détails d'une destination d'une instruction. * * * * Retour : Lien déterminé vers une instruction de destination. * * * * Remarques : - * * * ******************************************************************************/ instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, size_t index) { instr_link_t *result; /* Détails présents à renvoyer */ result = get_flat_array_item(instr->to, index, sizeof(instr_link_t)); return result; } /****************************************************************************** * * * 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 */ instr_link_t *dest; /* Destination à étudier */ result = NULL; g_arch_instruction_lock_dest(instr); count = g_arch_instruction_count_destinations(instr); for (i = 0; i < count && result == NULL; i++) { dest = g_arch_instruction_get_destination(instr, i); if (dest->type == type) { result = dest->linked; g_object_ref(G_OBJECT(result)); } } g_arch_instruction_unlock_dest(instr); 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. * * content = éventuel contenu binaire brut à imprimer. * * * * 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 GBinContent *content) { const char *key; /* Mot clef principal */ size_t klen; /* Taille de ce mot clef */ size_t count; /* Nombre d'opérandes en place */ size_t i; /* Boucle de parcours */ GArchOperand *op; /* Opérande à manipuler */ 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, 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); /* Liste des opérandes */ g_arch_instruction_lock_operands(instr); count = _g_arch_instruction_count_operands(instr); if (count > 0) { op = _g_arch_instruction_get_operand(instr, 0); g_arch_operand_print(op, line, 0/*syntax*/); for (i = 1; i < 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); op = _g_arch_instruction_get_operand(instr, i); g_arch_operand_print(op, line, 0/*syntax*/); } } g_arch_instruction_unlock_operands(instr); } /****************************************************************************** * * * 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. * * content = éventuel contenu binaire brut à imprimer. * * * * 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, const GBinContent *content) { G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat, content); }