diff options
Diffstat (limited to 'src/arch/instruction.c')
-rw-r--r-- | src/arch/instruction.c | 1935 |
1 files changed, 722 insertions, 1213 deletions
diff --git a/src/arch/instruction.c b/src/arch/instruction.c index cd1e9c7..36bdecb 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * instruction.c - gestion générique des instructions * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -26,102 +26,93 @@ #include <assert.h> #include <malloc.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> +#include <limits.h> #include <string.h> #include "instruction-int.h" -#include "storage.h" -#include "../analysis/storage/serialize-int.h" -#include "../core/columns.h" +#include "../common/leb128.h" #include "../core/logs.h" #include "../core/processors.h" -#include "../glibext/gbinarycursor.h" -#include "../glibext/linegen-int.h" +#include "../glibext/serialize-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_generator_init(GLineGeneratorInterface *); -/* Procède à l'initialisation de l'interface de sérialisation. */ -static void g_arch_instruction_serializable_init(GSerializableObjectInterface *); - -/* 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 GENERIQUE D'INSTRUCTION ----------------------- */ +/* Initialise la classe générique des instructions. */ +static void g_arch_instruction_class_init(GArchInstructionClass *); +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_arch_instruction_serializable_object_iface_init(GSerializableObjectInterface *); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_arch_instruction_load_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* Initialise une instance d'opérande d'architecture. */ +static void g_arch_instruction_init(GArchInstruction *); -/* Sauvegarde toutes les destinations d'une instruction. */ -bool g_arch_instruction_store_destinations(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* Supprime toutes les références externes. */ +static void g_arch_instruction_dispose(GObject *); +/* Procède à la libération totale de la mémoire. */ +static void g_arch_instruction_finalize(GObject *); +/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */ -/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ +#define COMPACT_INS_LINK_MASK_DIR (1ul << (__WORDSIZE - 1)) +#define COMPACT_INS_LINK_MASK_TYPE 0xf +#define COMPACT_INS_LINK_MASK (COMPACT_INS_LINK_MASK_DIR | COMPACT_INS_LINK_MASK_TYPE) -/* Indique le nombre de ligne prêtes à être générées. */ -static size_t g_arch_instruction_count_lines(const GArchInstruction *); +#define COMPACT_INS_LINK_FROM (0ul << (__WORDSIZE - 1)) +#define COMPACT_INS_LINK_TO (1ul << (__WORDSIZE - 1)) -#ifdef INCLUDE_GTK_SUPPORT +#define COMPACT_INS_LINK_DIR(cl) (cl & COMPACT_INS_LINK_MASK_DIR) +#define COMPACT_INS_LINK_PTR(cl) ((GArchInstruction *)(cl & ~COMPACT_INS_LINK_MASK)) +#define COMPACT_INS_LINK_TYPE(cl) (cl & COMPACT_INS_LINK_MASK_TYPE) -/* Retrouve l'emplacement correspondant à une position donnée. */ -static void g_arch_instruction_compute_cursor(const GArchInstruction *, gint, size_t, size_t, GLineCursor **); +#define MAKE_COMPACT_INS_LINK(d, i, t) \ + (compact_ins_link_t)(d | (unsigned long)i | t) -/* Détermine si le conteneur s'inscrit dans une plage donnée. */ -static int g_arch_instruction_contain_cursor(const GArchInstruction *, size_t, size_t, const GLineCursor *); +/* Détermine si un type de lien existe dans une instruction. */ +static bool _g_arch_instruction_has_link(const GArchInstruction *, compact_ins_link_t, InstructionLinkType); -#endif +/* Détermine si un lien existe entre deux instructions. */ +static bool _g_arch_instruction_has_link_with(const GArchInstruction *, compact_ins_link_t, const GArchInstruction *); -/* 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); +/* Fournit la quantité d'instructions pointant vers une autre. */ +static size_t _g_arch_instruction_count_links(const GArchInstruction *, compact_ins_link_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 *); +/* Fournit les détails d'un lien donné avec une instruction. */ +static GArchInstruction *_g_arch_instruction_get_linked_instruction(const GArchInstruction *, size_t, compact_ins_link_t, InstructionLinkType *); -/* Imprime dans une ligne de rendu le contenu représenté. */ -static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); -/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ -/* Charge un contenu depuis une mémoire tampon. */ -static bool _g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* Charge un objet depuis un flux de données. */ +static bool g_arch_instruction_load(GSerializableObject *, GObjectStorage *, int); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_arch_instruction_load(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* Sauvegarde un objet dans un flux de données. */ +static bool g_arch_instruction_store(const GSerializableObject *, GObjectStorage *, int); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool _g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_arch_instruction_store(GArchInstruction *, GObjectStorage *, packed_buffer_t *); +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION GENERIQUE D'INSTRUCTION */ +/* ---------------------------------------------------------------------------------- */ /* 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_generator_init) - G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_init)); +G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_THICK_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_instruction_serializable_object_iface_init) + G_IMPLEMENT_INTERFACE_IF_SYM(g_token_generator_get_type, g_arch_instruction_ui_token_generator_iface_init)); + /****************************************************************************** @@ -139,28 +130,20 @@ G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT, 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; - - instr->load = (load_instruction_fc)_g_arch_instruction_load; - instr->store = (store_instruction_fc)_g_arch_instruction_store; + object->dispose = g_arch_instruction_dispose; + object->finalize = g_arch_instruction_finalize; } /****************************************************************************** * * -* Paramètres : instr = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise une instance d'instruction d'architecture. * +* Description : Procède à l'initialisation de l'interface de sérialisation. * * * * Retour : - * * * @@ -168,27 +151,19 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass) * * ******************************************************************************/ -static void g_arch_instruction_init(GArchInstruction *instr) +static void g_arch_instruction_serializable_object_iface_init(GSerializableObjectInterface *iface) { - instr_extra_data_t *extra; /* Données insérées à modifier */ - - extra = GET_ARCH_INSTR_EXTRA(instr); - - INIT_GOBJECT_EXTRA_LOCK(extra); - - instr->operands = NULL; - - instr->from = NULL; - instr->to = NULL; + iface->load = g_arch_instruction_load; + iface->store = g_arch_instruction_store; } /****************************************************************************** * * -* Paramètres : iface = interface GLib à initialiser. * +* Paramètres : instr = instance à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de génération. * +* Description : Initialise une instance d'instruction d'architecture. * * * * Retour : - * * * @@ -196,42 +171,22 @@ static void g_arch_instruction_init(GArchInstruction *instr) * * ******************************************************************************/ -static void g_arch_instruction_generator_init(GLineGeneratorInterface *iface) +static void g_arch_instruction_init(GArchInstruction *instr) { - iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines; -#ifdef INCLUDE_GTK_SUPPORT - iface->compute = (linegen_compute_fc)g_arch_instruction_compute_cursor; - iface->contain = (linegen_contain_fc)g_arch_instruction_contain_cursor; -#endif - iface->get_flags = (linegen_get_flags_fc)g_arch_instruction_get_flags2; - iface->print = (linegen_print_fc)g_arch_instruction_print; - -} + instr->rel_area = NULL; + instr->link_count = 0; -/****************************************************************************** -* * -* Paramètres : iface = interface GLib à initialiser. * -* * -* Description : Procède à l'initialisation de l'interface de sérialisation. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + instr->links = NULL; -static void g_arch_instruction_serializable_init(GSerializableObjectInterface *iface) -{ - iface->load = (load_serializable_object_cb)g_arch_instruction_load; - iface->store = (store_serializable_object_cb)g_arch_instruction_store; + instr->operands = NULL; } /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -241,43 +196,38 @@ static void g_arch_instruction_serializable_init(GSerializableObjectInterface *i * * ******************************************************************************/ -static void g_arch_instruction_dispose(GArchInstruction *instr) +static void g_arch_instruction_dispose(GObject *object) { + GArchInstruction *instr; /* Version spécialisée */ size_t count; /* Nombre d'opérandes en place */ size_t i; /* Boucle de parcours */ GArchOperand *op; /* Opérande à manipuler */ - g_arch_instruction_lock_operands(instr); + instr = G_ARCH_INSTRUCTION(object); + + g_clear_object(&instr->rel_area); + + g_arch_instruction_delete_all_links(instr); - count = _g_arch_instruction_count_operands(instr); + g_thick_object_lock(G_THICK_OBJECT(instr)); + + count = g_arch_instruction_count_operands(instr); for (i = 0; i < count; i++) { - op = _g_arch_instruction_get_operand(instr, 0); + op = g_arch_instruction_get_operand(instr, 0); rem_item_from_flat_array(&instr->operands, 0, sizeof(GArchOperand *)); /** * Une fois pour l'obtention, une autre pour la libération ! */ - g_object_unref(G_OBJECT(op)); - g_object_unref(G_OBJECT(op)); + unref_object(op); + unref_object(op); } - g_arch_instruction_unlock_operands(instr); - -#ifndef NDEBUG - g_arch_instruction_lock_src(instr); - assert(count_flat_array_items(instr->from) == 0); - g_arch_instruction_unlock_src(instr); -#endif - -#ifndef NDEBUG - g_arch_instruction_lock_dest(instr); - assert(count_flat_array_items(instr->to) == 0); - g_arch_instruction_unlock_dest(instr); -#endif + g_thick_object_unlock(G_THICK_OBJECT(instr)); G_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr)); @@ -286,7 +236,7 @@ static void g_arch_instruction_dispose(GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -296,38 +246,26 @@ static void g_arch_instruction_dispose(GArchInstruction *instr) * * ******************************************************************************/ -static void g_arch_instruction_finalize(GArchInstruction *instr) +static void g_arch_instruction_finalize(GObject *object) { - G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr)); + GArchInstruction *instr; /* Version spécialisée */ -} + instr = G_ARCH_INSTRUCTION(object); + if (instr->links != NULL) + free(instr->links); -/****************************************************************************** -* * -* 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); + G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr)); } /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à modifier. * -* flag = drapeau d'information complémentaire à planter. * +* Paramètres : instr = instance à initialiser pleinement. * +* tid = identifiant associé au type d'instructions ciblé. * * * -* Description : Ajoute une information complémentaire à une instruction. * +* Description : Met en place une instruction d'architecture. * * * * Retour : Bilan de l'opération. * * * @@ -335,22 +273,18 @@ const char *g_arch_instruction_get_encoding(const GArchInstruction *instr) * * ******************************************************************************/ -bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag) +bool g_arch_instruction_create(GArchInstruction *instr, itid_t tid) { bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à modifier */ + instruction_extra_data_t extra; /* Données insérées à modifier */ - assert(flag <= AIF_HIGH_USER); + result = true; extra = GET_ARCH_INSTR_EXTRA(instr); - LOCK_GOBJECT_EXTRA(extra); - - result = !(extra->flags & flag); + extra.tid = tid; - extra->flags |= flag; - - UNLOCK_GOBJECT_EXTRA(extra); + SET_ARCH_INSTR_EXTRA(instr, &extra); return result; @@ -359,33 +293,24 @@ bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag) /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à modifier. * -* flag = drapeau d'information complémentaire à planter. * +* Paramètres : instr = instruction quelconque à consulter. * * * -* Description : Retire une information complémentaire à une instruction. * +* Description : Fournit l'identifiant correspondant à un type d'instructions.* * * -* Retour : Bilan de l'opération. * +* Retour : Identifiant unique par type d'instruction et architecture. * * * * Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstrFlag flag) +itid_t g_arch_instruction_get_type_id(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à modifier */ - - assert(flag <= AIF_HIGH_USER); + itid_t result; /* Numéro à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ extra = GET_ARCH_INSTR_EXTRA(instr); - LOCK_GOBJECT_EXTRA(extra); - - result = (extra->flags & flag); - - extra->flags &= ~flag; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.tid; return result; @@ -395,30 +320,23 @@ bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstrFlag flag) /****************************************************************************** * * * Paramètres : instr = instruction quelconque à consulter. * -* flag = drapeau d'information à rechercher. * * * -* Description : Détermine si une instruction possède un fanion particulier. * +* Description : Indique l'encodage d'une instruction de façon détaillée. * * * -* Retour : Bilan de la détection. * +* Retour : Description humaine de l'encodage utilisé. * * * * Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag flag) +char *g_arch_instruction_get_encoding(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à modifier */ - - assert(flag <= AIF_HIGH_USER); - - extra = GET_ARCH_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); + char *result; /* Encodage à retourner */ + GArchInstructionClass *class; /* Classe des instructions */ - result = (extra->flags & flag); + class = G_ARCH_INSTRUCTION_GET_CLASS(instr); - UNLOCK_GOBJECT_EXTRA(extra); + result = class->get_encoding(instr); return result; @@ -427,28 +345,24 @@ bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstrFlag fl /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à modifier. * +* Paramètres : instr = instruction d'assemblage à consulter. * * * -* Description : Fournit les informations complémentaires d'une instruction. * +* Description : Fournit le nom humain de l'instruction manipulée. * * * -* Retour : Eventuels drapeaux d'information complémentaire à plantés. * +* Retour : Mot clef de bas niveau. * * * * Remarques : - * * * ******************************************************************************/ -ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) +char *g_arch_instruction_get_keyword(const GArchInstruction *instr) { - ArchInstrFlag result; /* Fanions à retourner */ - instr_extra_data_t *extra; /* Données insérées à modifier */ - - extra = GET_ARCH_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); + char *result; /* Etiquette à retourner */ + GArchInstructionClass *class; /* Classe des instructions */ - result = extra->flags; + class = G_ARCH_INSTRUCTION_GET_CLASS(instr); - UNLOCK_GOBJECT_EXTRA(extra); + result = class->get_keyword(instr); return result; @@ -457,10 +371,12 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * -* uid = identifiant unique par type d'instruction. * +* Paramètres : instr = instruction quelconque à compléter. * +* area = portion de binaire incluant l'instruction. * +* start = adresse virtuelle et/ou position physique. * +* length = taille de l'instruction. * * * -* Description : Définit l'identifiant unique pour un ensemble d'instructions.* +* Description : Calcule la localisation d'une instruction. * * * * Retour : - * * * @@ -468,358 +384,214 @@ ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr) * * ******************************************************************************/ -void g_arch_instruction_set_unique_id(GArchInstruction *instr, itid_t uid) +void g_arch_instruction_compute_range(GArchInstruction *instr, GBinaryPortion *area, const vmpa2t *start, phys_t length) { - instr_extra_data_t *extra; /* Données insérées à modifier */ + const mrange_t *a_range; /* Couverture de la portion */ + phys_t diff; /* Décalage à appliquer */ - extra = GET_ARCH_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); + a_range = g_binary_portion_get_range(area); - extra->uid = uid; + assert(mrange_contains_addr(a_range, start)); - UNLOCK_GOBJECT_EXTRA(extra); + diff = compute_vmpa_diff(get_mrange_addr(a_range), start); -} + instr->rel_area = area; + ref_object(area); - -/****************************************************************************** -* * -* Paramètres : instr = instruction quelconque à consulter. * -* * -* Description : Fournit l'identifiant unique pour un ensemble d'instructions.* -* * -* Retour : Identifiant unique par type d'instruction et architecture. * -* * -* Remarques : - * -* * -******************************************************************************/ - -itid_t g_arch_instruction_get_unique_id(const GArchInstruction *instr) -{ - itid_t result; /* Numéro à retourner */ - instr_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_ARCH_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); - - result = extra->uid; - - UNLOCK_GOBJECT_EXTRA(extra); - - return result; + init_rel_mrange(&instr->rel_range, diff, length); } /****************************************************************************** * * -* 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. * +* Paramètres : instr = instruction quelconque à consulter. * +* range = localisation de l'instruction. [OUT] * * * -* Description : Complète un désassemblage accompli pour une instruction. * +* Description : Fournit la place mémoire d'une instruction. * * * -* Retour : - * +* Retour : Validité de la localisation : existence d'une définition ? * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format) +bool g_arch_instruction_get_range(const GArchInstruction *instr, mrange_t *range) { - GArchInstructionClass *class; /* Classe des instructions */ + bool result; /* Statut à retourner */ + const mrange_t *a_range; /* Couverture de la portion */ + vmpa2t start; /* Position de départ complète */ - class = G_ARCH_INSTRUCTION_GET_CLASS(instr); + result = (instr->rel_area != NULL); - if (class->call_hook != NULL) - class->call_hook(instr, type, proc, context, format); + if (result) + { + a_range = g_binary_portion_get_range(instr->rel_area); -} + copy_vmpa(&start, get_mrange_addr(a_range)); + advance_vmpa(&start, get_rel_mrange_offset(&instr->rel_range)); + init_mrange(range, &start, get_rel_mrange_length(&instr->rel_range)); -/****************************************************************************** -* * -* 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); + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * +* Paramètres : instr = instruction à venir modifier. * +* flag = drapeau d'information complémentaire à planter. * * * -* Description : Fournit la place mémoire d'une instruction. * +* Description : Ajoute une information complémentaire à une instruction. * * * -* Retour : Zone mémoire couverte par l'instruction. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -const mrange_t *g_arch_instruction_get_range(const GArchInstruction *instr) +bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstructionFlag flag) { - return &instr->range; + bool result; /* Bilan à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ -} + assert(flag <= AIF_HIGH_USER); + extra = GET_ARCH_INSTR_EXTRA(instr); + result = !(extra.flags & flag); -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ + extra.flags |= flag; -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; + SET_ARCH_INSTR_EXTRA(instr, &extra); - //if (address != NULL) *address = instr->address; + return result; } - /****************************************************************************** * * -* 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] * +* Paramètres : instr = instruction à venir modifier. * +* flag = drapeau d'information complémentaire à planter. * * * -* Description : Liste les registres lus et écrits par l'instruction. * +* Description : Retire une information complémentaire à une instruction. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * -* Remarques : Les compteurs de références sont à décrémenter après usage ! * +* Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount) +bool g_arch_instruction_unset_flag(GArchInstruction *instr, ArchInstructionFlag flag) { -#if 0 + bool result; /* Bilan à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ - size_t i; /* Boucle de parcours */ + assert(flag <= AIF_HIGH_USER); - *rregs = NULL; - *rcount = 0; - *wregs = NULL; - *wcount = 0; + extra = GET_ARCH_INSTR_EXTRA(instr); - instr->get_rw_regs(instr, rregs, rcount, wregs, wcount); + result = (extra.flags & flag); - for (i = 0; i < *rcount; i++) - g_object_ref(G_OBJECT((*rregs)[i])); + extra.flags &= ~flag; - for (i = 0; i < *wcount; i++) - g_object_ref(G_OBJECT((*wregs)[i])); + SET_ARCH_INSTR_EXTRA(instr, &extra); -#endif + return result; } - -/* ---------------------------------------------------------------------------------- */ -/* MANIPULATION DES OPERANDES */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : instr = instruction à mettre à jour. * +* Paramètres : instr = instruction à venir consulter. * +* flag = drapeau d'information à rechercher. * * * -* Description : Verrouille les accès à la liste des opérandes. * +* Description : Détermine si une instruction possède un fanion particulier. * * * -* Retour : - * +* Retour : Bilan de la détection. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_lock_operands(GArchInstruction *instr) +bool g_arch_instruction_has_flag(const GArchInstruction *instr, ArchInstructionFlag flag) { - lock_flat_array(&instr->operands); + bool result; /* Bilan à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ -} + assert(flag <= AIF_HIGH_USER); + extra = GET_ARCH_INSTR_EXTRA(instr); -/****************************************************************************** -* * -* Paramètres : instr = instruction à mettre à jour. * -* * -* Description : Déverrouille les accès à la liste des opérandes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + result = (extra.flags & flag); -void g_arch_instruction_unlock_operands(GArchInstruction *instr) -{ - unlock_flat_array(&instr->operands); + return result; } /****************************************************************************** * * -* Paramètres : instr = instance à mettre à jour. * -* operand = instruction à venir associer. * +* Paramètres : instr = instruction à venir consulter. * * * -* Description : Attache un opérande supplémentaire à une instruction. * +* Description : Fournit les particularités de l'instruction. * * * -* Retour : - * +* Retour : Somme de tous les fanions associés à l'opérande. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand) +ArchInstructionFlag g_arch_instruction_get_flags(const GArchInstruction *instr) { - GSingletonFactory *factory; /* Unise à instances uniques */ - GArchOperand *singleton; /* Instance retenue */ - - factory = get_operands_factory(); - - singleton = G_ARCH_OPERAND(g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(operand))); - - g_object_unref(G_OBJECT(operand)); - g_object_unref(G_OBJECT(factory)); - - g_arch_instruction_lock_operands(instr); - - add_item_to_flat_array(&instr->operands, &singleton, sizeof(GArchOperand *)); - - g_arch_instruction_unlock_operands(instr); + ArchInstructionFlag result; /* Fanions à retourner */ + instruction_extra_data_t extra; /* Données insérées à modifier */ -} - - -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ + extra = GET_ARCH_INSTR_EXTRA(instr); -size_t _g_arch_instruction_count_operands(const GArchInstruction *instr) -{ - size_t result; /* Décompte à retourner */ - - result = count_flat_array_items(instr->operands); + result = extra.flags; 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; - - g_object_ref(G_OBJECT(result)); - - return result; -} +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : instr = instance à mettre à jour. * -* old = ancienne opérande à détacher. * -* new = nouvelle opérande à attacher. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* dir = direction du lien recherché. * +* type = type de lien à détecter. * * * -* Description : Remplace un opérande d'une instruction par un autre. * +* Description : Détermine si un type de lien existe dans une instruction. * * * -* Retour : Bilan de l'opération. * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new) +static bool _g_arch_instruction_has_link(const GArchInstruction *instr, compact_ins_link_t dir, InstructionLinkType type) { 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 && !result; i++) - { - op = _g_arch_instruction_get_operand(instr, i); + uint16_t i; /* Boucle de parcours */ - result = (op == old); - - g_object_unref(G_OBJECT(op)); - - } - - if (result) - { - rpl_item_in_flat_array(instr->operands, i - 1, &new, sizeof(GArchOperand *)); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - g_object_unref(G_OBJECT(old)); + result = false; - } + for (i = 0; i < instr->link_count && !result; i++) + result = COMPACT_INS_LINK_DIR(instr->links[i]) == dir; return result; @@ -828,45 +600,22 @@ bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand * /****************************************************************************** * * -* Paramètres : instr = instance à mettre à jour. * -* target = instruction à venir dissocier. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* type = type de lien à détecter. * * * -* Description : Détache un opérande liée d'une instruction. * +* Description : Détermine si un type de lien amène à une instruction. * * * -* Retour : Bilan de l'opération. * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target) +bool g_arch_instruction_has_src_link(const GArchInstruction *instr, InstructionLinkType type) { 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 && !result; i++) - { - op = _g_arch_instruction_get_operand(instr, i); - - result = (op == target); - - g_object_unref(G_OBJECT(op)); - - } - - if (result) - { - rem_item_from_flat_array(&instr->operands, i - 1, sizeof(GArchOperand *)); - - g_object_unref(G_OBJECT(target)); - - } + result = _g_arch_instruction_has_link(instr, COMPACT_INS_LINK_FROM, type); return result; @@ -875,78 +624,22 @@ bool _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t /****************************************************************************** * * -* Paramètres : instr = instance à consulter. * -* target = instruction à venir retrouver. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* type = type de lien à détecter. * * * -* Description : Détermine le chemin conduisant à un opérande. * +* Description : Détermine si un type de lien émerge d'une instruction. * * * -* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target) +bool g_arch_instruction_has_dest_link(const GArchInstruction *instr, InstructionLinkType type) { - char *result; /* Chemin à retourner */ - size_t count; /* Nombre d'opérandes en place */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à manipuler */ - int ret; /* Bilan d'une construction */ - char *sub_path; /* Sous-chemin emprunté */ - - result = NULL; - - g_arch_instruction_lock_operands(instr); - - count = _g_arch_instruction_count_operands(instr); - - /* Première passe : accès direct */ - - for (i = 0; i < count && result == NULL; i++) - { - op = _g_arch_instruction_get_operand(instr, i); - - if (op == target) - { - ret = asprintf(&result, "%zu", i); - if (ret == -1) - { - LOG_ERROR_N("asprintf"); - result = NULL; - } - } - - g_object_unref(G_OBJECT(op)); - - } - - /* Seconde passe : accès profond */ - - for (i = 0; i < count && result == NULL; i++) - { - op = _g_arch_instruction_get_operand(instr, i); - - sub_path = g_arch_operand_find_inner_operand_path(op, target); - - if (sub_path != NULL) - { - ret = asprintf(&result, "%zu:%s", i, sub_path); - if (ret == -1) - { - LOG_ERROR_N("asprintf"); - result = NULL; - } - - free(sub_path); - - } - - g_object_unref(G_OBJECT(op)); - - } + bool result; /* Bilan à retourner */ - g_arch_instruction_unlock_operands(instr); + result = _g_arch_instruction_has_link(instr, COMPACT_INS_LINK_TO, type); return result; @@ -955,104 +648,65 @@ char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchO /****************************************************************************** * * -* Paramètres : instr = instance à consulter. * -* path = chemin d'accès à un opérande à retrouver. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* dir = direction du lien recherché. * +* linked = seconde instruction à considérer. * * * -* Description : Obtient l'opérande correspondant à un chemin donné. * +* Description : Détermine si un lien existe entre deux instructions. * * * -* Retour : Opérande trouvé ou NULL en cas d'échec. * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path) +static bool _g_arch_instruction_has_link_with(const GArchInstruction *instr, compact_ins_link_t dir, const GArchInstruction *linked) { - GArchOperand *result; /* Opérande trouvée à renvoyer */ - size_t index; /* Indice de l'opérande visé */ - char *end; /* Poursuite du parcours ? */ - GArchOperand *found; /* Opérande trouvé */ - - result = NULL; - - g_arch_instruction_lock_operands(instr); - - /* Recherche au premier niveau */ - - index = strtoul(path, &end, 10); - - if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL)) - { - LOG_ERROR_N("strtoul"); - goto done; - } - - found = _g_arch_instruction_get_operand(instr, index); - if (found == NULL) goto done; - - if (*end == '\0') - { - result = found; - goto done; - } - - /* Recherche en profondeur */ - - assert(*end == ':'); - - result = g_arch_operand_get_inner_operand_from_path(found, end + 1); + bool result; /* Bilan à retourner */ + uint16_t i; /* Boucle de parcours */ - g_object_unref(G_OBJECT(found)); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - done: + result = false; - g_arch_instruction_unlock_operands(instr); + for (i = 0; i < instr->link_count && !result; i++) + result = COMPACT_INS_LINK_PTR(instr->links[i]) == linked; return result; } - -/* ---------------------------------------------------------------------------------- */ -/* 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. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* src = seconde instruction à considérer. * * * -* Description : Met à disposition un encadrement des accès aux liens. * +* Description : Détermine si une instruction est source d'une autre. * * * -* Retour : - * +* Retour : Bilan du statut courant de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool lock) +bool g_arch_instruction_has_src_link_with(const GArchInstruction *instr, const GArchInstruction *src) { - flat_array_t **array; /* Choix du tableau ciblé */ + bool result; /* Bilan à retourner */ - array = (src ? &instr->from : &instr->to); + result = _g_arch_instruction_has_link_with(instr, COMPACT_INS_LINK_FROM, src); - if (lock) - lock_flat_array(array); - else - unlock_flat_array(array); + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* type = type de lien à détecter. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* dest = seconde instruction à considérer. * * * -* Description : Détermine si un type de lien existe dans une instruction. * +* Description : Détermine si une instruction est destination d'une autre. * * * * Retour : Bilan du statut courant de l'instruction. * * * @@ -1060,30 +714,11 @@ void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, boo * * ******************************************************************************/ -bool g_arch_instruction_has_link(GArchInstruction *instr, InstructionLinkType type) +bool g_arch_instruction_has_dest_link_with(const GArchInstruction *instr, const GArchInstruction *dest) { bool result; /* Bilan à retourner */ - size_t count; /* Nombre de liens à parcourir */ - size_t i; /* Boucle de parcours */ - const 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->type == type); - - unref_instr_link(dlink); - - } - - g_arch_instruction_unlock_dest(instr); + result = _g_arch_instruction_has_link_with(instr, COMPACT_INS_LINK_TO, dest); return result; @@ -1092,54 +727,53 @@ bool g_arch_instruction_has_link(GArchInstruction *instr, InstructionLinkType ty /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * +* Paramètres : instr = instruction dont les informations sont à manipuler. * * dest = ligne visée par la liaison (côté destination). * +* type = type de lien à construire. * * * -* Description : Détermine si un lien est déjà établi entre deux instructions.* +* Description : Etablit un lien entre deux instructions. * * * -* Retour : Bilan de l'état actuel des liaisons. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruction *dest) +void g_arch_instruction_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type) { - bool result; /* Bilan à retourner */ - size_t count; /* Nombre de liens à parcourir */ - size_t i; /* Boucle de parcours */ - const instr_link_t *dlink; /* Définition de destination */ + compact_ins_link_t new_from; /* Nouvel enregistrement #1 */ + compact_ins_link_t new_to; /* Nouvel enregistrement #2 */ - result = false; + new_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, type); + ref_object(instr); - g_arch_instruction_lock_dest(instr); + new_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, type); + ref_object(dest); - count = g_arch_instruction_count_destinations(instr); + g_thick_object_lock(G_THICK_OBJECT(instr)); + g_thick_object_lock(G_THICK_OBJECT(dest)); - for (i = 0; i < count && !result; i++) - { - dlink = g_arch_instruction_get_destination(instr, i); - - result = (dlink->linked == dest); + dest->links = realloc(dest->links, ++dest->link_count * sizeof(compact_ins_link_t)); - unref_instr_link(dlink); + dest->links[dest->link_count - 1] = new_from; - } + instr->links = realloc(instr->links, ++instr->link_count * sizeof(compact_ins_link_t)); - g_arch_instruction_unlock_dest(instr); + instr->links[instr->link_count - 1] = new_to; - return result; + g_thick_object_unlock(G_THICK_OBJECT(dest)); + g_thick_object_unlock(G_THICK_OBJECT(instr)); } /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * +* Paramètres : instr = instruction dont les informations sont à manipuler. * * dest = ligne visée par la liaison (côté destination). * * type = type de lien à construire. * * * -* Description : Etablit un lien entre deux instructions. * +* Description : Supprime un lien entre deux instructions. * * * * Retour : - * * * @@ -1147,43 +781,59 @@ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruct * * ******************************************************************************/ -void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type) +void g_arch_instruction_unlink(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 */ + compact_ins_link_t old_from; /* Ancien enregistrement #1 */ + compact_ins_link_t old_to; /* Ancien enregistrement #2 */ + uint16_t i_from; /* Boucle de parcours #1 */ + uint16_t i_to; /* Boucle de parcours #2 */ + bool status; /* Bilan des recherches */ + + old_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, type); + + old_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, type); - /* Côté destination */ + g_thick_object_lock(G_THICK_OBJECT(instr)); + g_thick_object_lock(G_THICK_OBJECT(dest)); - new_src.linked = instr; - new_src.type = type; + for (i_from = 0; i_from < dest->link_count; i_from++) + if (dest->links[i_from] == old_from) + break; - ref_instr_link((&new_src)); + for (i_to = 0; i_to < instr->link_count; i_to++) + if (instr->links[i_to] == old_to) + break; - /* Côté point de départ */ + assert((i_from < dest->link_count && i_to < instr->link_count) + || (i_from == dest->link_count && i_to == instr->link_count)); - new_dst.linked = dest; - new_dst.type = type; + status = (i_from < dest->link_count && i_to < instr->link_count); - ref_instr_link((&new_dst)); + if (status) + { + if ((i_from + 1) < dest->link_count) + memmove(&dest->links[i_from], &dest->links[i_from + 1], + (dest->link_count - i_from - 1) * sizeof(compact_ins_link_t)); - /* Ajout dans le respect d'une cohérence globale */ + dest->links = realloc(dest->links, --dest->link_count * sizeof(compact_ins_link_t)); - g_arch_instruction_lock_src(dest); - g_arch_instruction_lock_dest(instr); + if ((i_to + 1) < instr->link_count) + memmove(&instr->links[i_to], &instr->links[i_to + 1], + (instr->link_count - i_to - 1) * sizeof(compact_ins_link_t)); - add_item_to_flat_array(&dest->from, &new_src, sizeof(instr_link_t)); + instr->links = realloc(instr->links, --instr->link_count * sizeof(compact_ins_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); + g_thick_object_unlock(G_THICK_OBJECT(dest)); + g_thick_object_unlock(G_THICK_OBJECT(instr)); } /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * +* Paramètres : instr = instruction dont les informations sont à manipuler. * * dest = ligne visée par la liaison (côté destination). * * old = ancien type de lien construit. * * new = nouveau type de lien à construire. * @@ -1199,67 +849,43 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des 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; + compact_ins_link_t old_from; /* Ancien enregistrement #1 */ + compact_ins_link_t new_from; /* Nouvel enregistrement #1 */ + compact_ins_link_t old_to; /* Ancien enregistrement #2 */ + compact_ins_link_t new_to; /* Nouvel enregistrement #2 */ + uint16_t i_from; /* Boucle de parcours #1 */ + uint16_t i_to; /* Boucle de parcours #2 */ - /** - * Note : pour la récupération des liens de sources et de destinations, - * on n'utilise pas les fonctions g_arch_instruction_get_(source|destination)(), - * qui renvoient un pointeur non modifiable. - * - * On a en effet besoin de modifier le type de lien. - */ + old_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, old); + new_from = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_FROM, instr, new); + old_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, old); + new_to = MAKE_COMPACT_INS_LINK(COMPACT_INS_LINK_TO, dest, new); - g_arch_instruction_lock_src(dest); + g_thick_object_lock(G_THICK_OBJECT(instr)); + g_thick_object_lock(G_THICK_OBJECT(dest)); - /* Côté destination */ - - count = g_arch_instruction_count_sources(dest); - - for (i = 0; i < count; i++) - { - slink = get_flat_array_item(dest->from, i, sizeof(instr_link_t)); - - if (slink->linked == instr && slink->type == old) + for (i_from = 0; i_from < dest->link_count; i_from++) + if (dest->links[i_from] == old_from) break; - } - - if (i == count) - goto gaicl_exit; + for (i_to = 0; i_to < instr->link_count; i_to++) + if (instr->links[i_to] == old_to) + break; - /* Côté point de départ */ + assert((i_from < dest->link_count && i_to < instr->link_count) + || (i_from == dest->link_count && i_to == instr->link_count)); - count = g_arch_instruction_count_destinations(instr); + result = (i_from < dest->link_count && i_to < instr->link_count); - for (i = 0; i < count; i++) + if (result) { - dlink = get_flat_array_item(instr->to, i, sizeof(instr_link_t)); - - if (dlink->linked == dest && dlink->type == old) - break; - + dest->links[i_from] = new_from; + instr->links[i_to] = new_to; } - 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); + g_thick_object_unlock(G_THICK_OBJECT(dest)); + g_thick_object_unlock(G_THICK_OBJECT(instr)); return result; @@ -1280,116 +906,92 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d void g_arch_instruction_delete_all_links(GArchInstruction *instr) { - instr_link_t *link_src; /* Lien à supprimer #2 */ - GArchInstruction *other; /* Instruction de l'autre bout */ - size_t count; /* Quantié de liens présents */ - size_t i; /* Boucle de parcours */ - instr_link_t *link_dst; /* Lien à supprimer #1 */ + GArchInstruction *linked; /* Autre instruction liée */ + InstructionLinkType type; /* Type de liaison */ - /* Coté sources */ + g_thick_object_lock(G_THICK_OBJECT(instr)); - g_arch_instruction_lock_src(instr); - - while (count_flat_array_items(instr->from) > 0) + while (g_arch_instruction_count_src_links(instr) > 0) { - link_src = get_flat_array_item(instr->from, 0, sizeof(instr_link_t)); - - other = link_src->linked; + linked = g_arch_instruction_get_linked_source(instr, 0, &type); - g_arch_instruction_lock_dest(other); + g_thick_object_unlock(G_THICK_OBJECT(instr)); - count = count_flat_array_items(other->to); + g_arch_instruction_unlink(linked, instr, type); - for (i = 0; i < count; i++) - { - link_dst = get_flat_array_item(other->to, i, sizeof(instr_link_t)); + g_thick_object_lock(G_THICK_OBJECT(instr)); - if (link_dst->linked == instr && link_dst->type == link_src->type) - { - unref_instr_link(link_dst); - - rem_item_from_flat_array(&other->to, i, sizeof(instr_link_t)); - - break; - - } - - } - - assert(i < count); - - g_arch_instruction_unlock_dest(other); - - unref_instr_link(link_src); - - rem_item_from_flat_array(&instr->from, 0, sizeof(instr_link_t)); + unref_object(linked); } - g_arch_instruction_unlock_src(instr); - - /* Coté destinations */ - - g_arch_instruction_lock_dest(instr); - - while (count_flat_array_items(instr->to) > 0) + while (g_arch_instruction_count_dest_links(instr) > 0) { - link_dst = get_flat_array_item(instr->to, 0, sizeof(instr_link_t)); + linked = g_arch_instruction_get_linked_destination(instr, 0, &type); - other = link_dst->linked; + g_thick_object_unlock(G_THICK_OBJECT(instr)); - g_arch_instruction_lock_src(other); + g_arch_instruction_unlink(instr, linked, type); - count = count_flat_array_items(other->from); + g_thick_object_lock(G_THICK_OBJECT(instr)); - for (i = 0; i < count; i++) - { - link_src = get_flat_array_item(other->from, i, sizeof(instr_link_t)); + unref_object(linked); - if (link_src->linked == instr && link_src->type == link_dst->type) - { - unref_instr_link(link_src); - - rem_item_from_flat_array(&other->from, i, sizeof(instr_link_t)); + } - break; + g_thick_object_unlock(G_THICK_OBJECT(instr)); - } +} - } - assert(i < count); +/****************************************************************************** +* * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* dir = direction des liens à considérer. * +* * +* Description : Fournit la quantité d'instructions pointant vers une autre. * +* * +* Retour : Nombre de ces liens. * +* * +* Remarques : - * +* * +******************************************************************************/ - g_arch_instruction_unlock_src(other); +static size_t _g_arch_instruction_count_links(const GArchInstruction *instr, compact_ins_link_t dir) +{ + size_t result; /* Nombre de liens à renvoyer */ + uint16_t i; /* Boucle de parcours */ - unref_instr_link(link_dst); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - rem_item_from_flat_array(&instr->to, 0, sizeof(instr_link_t)); + result = 0; - } + for (i = 0; i < instr->link_count; i++) + if (COMPACT_INS_LINK_DIR(instr->links[i]) == dir) + result++; - g_arch_instruction_unlock_dest(instr); + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * +* Paramètres : instr = instruction dont les liens sont à consulter. * * * -* Description : Fournit la quantité d'instructions pointant vers une autre. * +* Description : Fournit la quantité d'instructions placées en source. * * * -* Retour : Nombre de ces origines. * +* Retour : Nombre de ces liens. * * * * Remarques : - * * * ******************************************************************************/ -size_t g_arch_instruction_count_sources(const GArchInstruction *instr) +size_t g_arch_instruction_count_src_links(const GArchInstruction *instr) { size_t result; /* Nombre de liens à renvoyer */ - result = count_flat_array_items(instr->from); + result = _g_arch_instruction_count_links(instr, COMPACT_INS_LINK_FROM); return result; @@ -1398,24 +1000,21 @@ size_t g_arch_instruction_count_sources(const GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* index = indice de l'élément à retrouver. * +* Paramètres : instr = instruction dont les liens sont à consulter. * * * -* Description : Fournit les détails d'une origine d'une instruction donnée. * +* Description : Fournit la quantité d'instructions placées en destination. * * * -* Retour : Lien déterminé vers une instruction d'origine. * +* Retour : Nombre de ces liens. * * * * Remarques : - * * * ******************************************************************************/ -const instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_t index) +size_t g_arch_instruction_count_dest_links(const GArchInstruction *instr) { - instr_link_t *result; /* Détails présents à renvoyer */ - - result = get_flat_array_item(instr->from, index, sizeof(instr_link_t)); + size_t result; /* Nombre de liens à renvoyer */ - ref_instr_link(result); + result = _g_arch_instruction_count_links(instr, COMPACT_INS_LINK_TO); return result; @@ -1424,43 +1023,47 @@ const instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_ /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* count = quantié de liens présents. [OUT] * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* index = indice de l'élément à retrouver. * +* dir = direction des liens à considérer. * +* type = type de lien enregistré. [OUT] * * * -* Description : Fournit tous les détails d'origine d'une instruction donnée. * +* Description : Fournit les détails d'un lien donné avec une instruction. * * * -* Retour : Liens vers des instructions d'origine à libérer. * +* Retour : Autre instruction pointée par l'instruction, voire NULL. * * * * Remarques : - * * * ******************************************************************************/ -instr_link_t *g_arch_instruction_get_sources(GArchInstruction *instr, size_t *count) +static GArchInstruction *_g_arch_instruction_get_linked_instruction(const GArchInstruction *instr, size_t index, compact_ins_link_t dir, InstructionLinkType *type) { - instr_link_t *result; /* Détails présents à renvoyer */ - size_t i; /* Boucle de parcours */ - const instr_link_t *link; /* Lien à fournir */ - - g_arch_instruction_lock_src(instr); + GArchInstruction *result; /* Instance ciblée à renvoyer */ + uint16_t i; /* Boucle de parcours */ - *count = g_arch_instruction_count_sources(instr); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - if (*count == 0) - result = NULL; + result = NULL; + *type = ILT_COUNT; - else + for (i = 0; i < instr->link_count; i++) { - result = (instr_link_t *)malloc(*count * sizeof(instr_link_t)); + if (COMPACT_INS_LINK_DIR(instr->links[i]) != dir) + continue; - for (i = 0; i < *count; i++) + if (index == 0) { - link = g_arch_instruction_get_source(instr, i); - memcpy(&result[i], link, sizeof(instr_link_t)); + result = COMPACT_INS_LINK_PTR(instr->links[i]); + *type = COMPACT_INS_LINK_TYPE(instr->links[i]); } + else + index--; + } - g_arch_instruction_unlock_src(instr); + if (result != NULL) + ref_object(result); return result; @@ -1469,21 +1072,23 @@ instr_link_t *g_arch_instruction_get_sources(GArchInstruction *instr, size_t *co /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * +* Paramètres : instr = instruction dont les liens sont à consulter. * +* index = indice de l'élément à retrouver. * +* type = type de lien enregistré. [OUT] * * * -* Description : Donne le nombre d'instructions non naturellement suivantes. * +* Description : Fournit les détails d'une source donnée d'une instruction. * * * -* Retour : Nombre de ces destinations. * +* Retour : Autre instruction pointée par l'instruction, voire NULL. * * * * Remarques : - * * * ******************************************************************************/ -size_t g_arch_instruction_count_destinations(const GArchInstruction *instr) +GArchInstruction *g_arch_instruction_get_linked_source(const GArchInstruction *instr, size_t index, InstructionLinkType *type) { - size_t result; /* Nombre de liens à renvoyer */ + GArchInstruction *result; /* Instance ciblée à renvoyer */ - result = count_flat_array_items(instr->to); + result = _g_arch_instruction_get_linked_instruction(instr, index, COMPACT_INS_LINK_FROM, type); return result; @@ -1492,71 +1097,54 @@ size_t g_arch_instruction_count_destinations(const GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * +* Paramètres : instr = instruction dont les liens sont à consulter. * * index = indice de l'élément à retrouver. * +* type = type de lien enregistré. [OUT] * * * -* Description : Fournit les détails d'une destination d'une instruction. * +* Description : Fournit les détails d'une destination donnée d'une instruct. * * * -* Retour : Lien déterminé vers une instruction de destination. * +* Retour : Autre instruction pointée par l'instruction, voire NULL. * * * * Remarques : - * * * ******************************************************************************/ -const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, size_t index) +GArchInstruction *g_arch_instruction_get_linked_destination(const GArchInstruction *instr, size_t index, InstructionLinkType *type) { - instr_link_t *result; /* Détails présents à renvoyer */ - - result = get_flat_array_item(instr->to, index, sizeof(instr_link_t)); + GArchInstruction *result; /* Instance ciblée à renvoyer */ - ref_instr_link(result); + result = _g_arch_instruction_get_linked_instruction(instr, index, COMPACT_INS_LINK_TO, type); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MANIPULATION DES OPERANDES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* type = type de lien recherché. * +* Paramètres : instr = instance à consulter. * * * -* Description : Fournit la destination d'une instruction et d'un type donné. * +* Description : Indique la quantité d'opérandes présents dans l'instruction. * * * -* Retour : Instruction de destination trouvée ou NULL. * +* Retour : Nombre d'opérandes attachés. * * * * Remarques : - * * * ******************************************************************************/ -GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *instr, InstructionLinkType type) +size_t g_arch_instruction_count_operands(const GArchInstruction *instr) { - GArchInstruction *result; /* Résultat à remonter */ - size_t count; /* Nombre de liens à parcourir */ - size_t i; /* Boucle de parcours */ - const 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)); - } + size_t result; /* Décompte à retourner */ - unref_instr_link(dest); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - } - - g_arch_instruction_unlock_dest(instr); + result = count_flat_array_items(instr->operands); return result; @@ -1565,56 +1153,45 @@ GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *ins /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter. * -* count = quantié de liens présents. [OUT] * +* Paramètres : instr = instance à mettre à jour. * +* operand = instruction à venir associer. * * * -* Description : Fournit tous les détails de destination d'une instruction. * +* Description : Attache un opérande supplémentaire à une instruction. * * * -* Retour : Liens vers des instructions de destination à libérer. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_t *count) +void g_arch_instruction_attach_operand(GArchInstruction *instr, GArchOperand *operand) { - instr_link_t *result; /* Détails présents à renvoyer */ - size_t i; /* Boucle de parcours */ - const instr_link_t *link; /* Lien à fournir */ - - g_arch_instruction_lock_dest(instr); - - *count = g_arch_instruction_count_destinations(instr); + GSingletonFactory *factory; /* Unise à instances uniques */ + GSingletonCandidate *singleton; /* Instance retenue */ + GArchOperand *stored; /* Forme d'opérande conservée */ - if (*count == 0) - result = NULL; + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - else - { - result = (instr_link_t *)malloc(*count * sizeof(instr_link_t)); + factory = get_operands_factory(); - for (i = 0; i < *count; i++) - { - link = g_arch_instruction_get_destination(instr, i); - memcpy(&result[i], link, sizeof(instr_link_t)); - } + singleton = g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(operand)); - } + unref_object(factory); - g_arch_instruction_unlock_dest(instr); + stored = G_ARCH_OPERAND(singleton); - return result; + add_item_to_flat_array(&instr->operands, &stored, sizeof(GArchOperand *)); } /****************************************************************************** * * -* Paramètres : instr = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : instr = instance à mettre à jour. * +* old = ancienne opérande à détacher. * +* new = nouvelle opérande à attacher. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Remplace un opérande d'une instruction par un autre. * * * * Retour : Bilan de l'opération. * * * @@ -1622,40 +1199,47 @@ instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *instr, size_ * * ******************************************************************************/ -static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +bool g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new) { bool result; /* Bilan à retourner */ - uleb128_t count; /* Nombre de liens à charger */ - uleb128_t i; /* Boucle de parcours */ - GArchInstruction *linked; /* Lien vers une instruction */ - uleb128_t type; /* Valeur ULEB128 à charger */ + size_t count; /* Nombre d'opérandes en place */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à manipuler */ + GSingletonFactory *factory; /* Unise à instances uniques */ + GSingletonCandidate *singleton; /* Instance retenue */ + GArchOperand *stored; /* Forme d'opérande conservée */ - g_arch_instruction_lock_dest(instr); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - result = unpack_uleb128(&count, pbuf); + result = false; - for (i = 0; i < count && result; i++) + count = g_arch_instruction_count_operands(instr); + + for (i = 0; i < count && !result; i++) { - linked = G_ARCH_INSTRUCTION(g_object_storage_unpack_object(storage, "instructions", pbuf)); - if (linked == NULL) - { - result = false; - break; - } + op = g_arch_instruction_get_operand(instr, i); - result = unpack_uleb128(&type, pbuf); - if (!result) - { - g_object_unref(G_OBJECT(linked)); - break; - } + result = (op == old); - g_arch_instruction_link_with(instr, linked, type); - g_object_unref(G_OBJECT(linked)); + unref_object(op); } - g_arch_instruction_unlock_dest(instr); + if (result) + { + factory = get_operands_factory(); + + singleton = g_singleton_factory_get_instance(factory, G_SINGLETON_CANDIDATE(new)); + + unref_object(factory); + + stored = G_ARCH_OPERAND(singleton); + + rpl_item_in_flat_array(instr->operands, i - 1, &stored, sizeof(GArchOperand *)); + + unref_object(old); + + } return result; @@ -1664,11 +1248,10 @@ static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjec /****************************************************************************** * * -* Paramètres : instr = instruction dont les informations sont à consulter.* -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : instr = instance à mettre à jour. * +* target = instruction à venir dissocier. * * * -* Description : Sauvegarde toutes les destinations d'une instruction. * +* Description : Détache un opérande liée d'une instruction. * * * * Retour : Bilan de l'opération. * * * @@ -1676,87 +1259,67 @@ static bool g_arch_instruction_load_destinations(GArchInstruction *instr, GObjec * * ******************************************************************************/ -bool g_arch_instruction_store_destinations(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +bool g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target) { bool result; /* Bilan à retourner */ - size_t count; /* Nombre d'éléments à traiter */ - size_t kept; /* Nombre de liens conservés */ + size_t count; /* Nombre d'opérandes en place */ size_t i; /* Boucle de parcours */ - const instr_link_t *link; /* Lien vers une instruction */ - - g_arch_instruction_lock_dest(instr); + GArchOperand *op; /* Opérande à manipuler */ - count = g_arch_instruction_count_destinations(instr); + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - /** - * Le type de lien ILT_REF n'est mis en place que lors de la création - * d'opérandes de type G_TYPE_TARGET_OPERAND, et sera donc remis en place - * dynamiquement lors de la restauration de ces derniers. - */ + result = false; - kept = 0; + count = g_arch_instruction_count_operands(instr); - for (i = 0; i < count; i++) + for (i = 0; i < count && !result; i++) { - link = g_arch_instruction_get_destination(instr, i); + op = g_arch_instruction_get_operand(instr, i); - if (link->type != ILT_REF) - kept++; + result = (op == target); - unref_instr_link(link); + unref_object(op); } - result = pack_uleb128((uleb128_t []){ kept }, pbuf); - - for (i = 0; i < count && result; i++) + if (result) { - link = g_arch_instruction_get_destination(instr, i); - - if (link->type != ILT_REF) - { - result = g_object_storage_pack_object(storage, "instructions", - G_SERIALIZABLE_OBJECT(link->linked), pbuf); - - if (result) - result = pack_uleb128((uleb128_t []){ link->type }, pbuf); - - } + rem_item_from_flat_array(&instr->operands, i - 1, sizeof(GArchOperand *)); - unref_instr_link(link); + unref_object(target); } - g_arch_instruction_unlock_dest(instr); - return result; } - -/* ---------------------------------------------------------------------------------- */ -/* CONVERSIONS DU FORMAT DES INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * +* Paramètres : instr = instance à consulter. * +* index = indice de l'opérande concerné. * * * -* Description : Fournit le nom humain de l'instruction manipulée. * +* Description : Fournit un opérande donné d'une instruction. * * * -* Retour : Mot clef de bas niveau. * +* Retour : Opérande trouvée. * * * * Remarques : - * * * ******************************************************************************/ -const char *g_arch_instruction_get_keyword(GArchInstruction *instr) +GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index) { - const char *result; /* Désignation à retourner */ + GArchOperand *result; /* Opérande à retourner */ + GArchOperand **ptr; /* Adresse dans le tableau */ + + assert(g_thick_object_check_lock(G_THICK_OBJECT(instr))); - result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_keyword(instr); + ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *)); + + result = *ptr; + + ref_object(result); return result; @@ -1765,450 +1328,396 @@ const char *g_arch_instruction_get_keyword(GArchInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * +* Paramètres : instr = instance à consulter. * +* target = instruction à venir retrouver. * * * -* Description : Construit un petit résumé concis de l'instruction. * +* Description : Détermine le chemin conduisant à un opérande. * * * -* Retour : Chaîne de caractères à libérer après usage ou NULL. * +* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. * * * * Remarques : - * * * ******************************************************************************/ -char *g_arch_instruction_build_tooltip(const GArchInstruction *instr) +char *g_arch_instruction_find_operand_path(GArchInstruction *instr, const GArchOperand *target) { - char *result; /* Description à retourner */ - GArchInstructionClass *class; /* Classe des instructions */ + char *result; /* Chemin à retourner */ + size_t count; /* Nombre d'opérandes en place */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à manipuler */ + int ret; /* Bilan d'une construction */ + char *sub_path; /* Sous-chemin emprunté */ - class = G_ARCH_INSTRUCTION_GET_CLASS(instr); + result = NULL; - if (class->build_tooltip != NULL) - result = class->build_tooltip(instr); + g_thick_object_lock(G_THICK_OBJECT(instr)); - else - result = NULL; + count = g_arch_instruction_count_operands(instr); - return result; + /* Première passe : accès direct */ -} + for (i = 0; i < count && result == NULL; i++) + { + op = g_arch_instruction_get_operand(instr, i); + if (op == target) + { + ret = asprintf(&result, "%zu", i); + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + result = NULL; + } + } -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à consulter. * -* * -* Description : Fournit une description pour l'instruction manipulée. * -* * -* Retour : Chaîne de caractères avec balises éventuelles. * -* * -* Remarques : - * -* * -******************************************************************************/ + unref_object(op); -const char *g_arch_instruction_get_description(const GArchInstruction *instr) -{ - const char *result; /* Description à retourner */ + } - result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_desc(instr); + /* Seconde passe : accès profond */ - return result; - -} + for (i = 0; i < count && result == NULL; i++) + { + op = g_arch_instruction_get_operand(instr, i); + sub_path = NULL;//g_arch_operand_find_inner_operand_path(op, target); + if (sub_path != NULL) + { + ret = asprintf(&result, "%zu:%s", i, sub_path); + if (ret == -1) + { + LOG_ERROR_N("asprintf"); + result = NULL; + } -/* ---------------------------------------------------------------------------------- */ -/* OFFRE DE CAPACITES DE GENERATION */ -/* ---------------------------------------------------------------------------------- */ + free(sub_path); + } -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ + unref_object(op); -static size_t g_arch_instruction_count_lines(const GArchInstruction *instr) -{ - return 1; + } -} + g_thick_object_unlock(G_THICK_OBJECT(instr)); + return result; -#ifdef INCLUDE_GTK_SUPPORT +} /****************************************************************************** * * -* Paramètres : instr = générateur à consulter. * -* x = position géographique sur la ligne concernée. * -* index = indice de cette même ligne dans le tampon global. * -* repeat = indice d'utilisations successives du générateur. * -* cursor = emplacement à constituer. [OUT] * +* Paramètres : instr = instance à consulter. * +* path = chemin d'accès à un opérande à retrouver. * * * -* Description : Retrouve l'emplacement correspondant à une position donnée. * +* Description : Obtient l'opérande correspondant à un chemin donné. * * * -* Retour : - * +* Retour : Opérande trouvé ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -static void g_arch_instruction_compute_cursor(const GArchInstruction *instr, gint x, size_t index, size_t repeat, GLineCursor **cursor) +GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *instr, const char *path) { - *cursor = g_binary_cursor_new(); + GArchOperand *result; /* Opérande trouvée à renvoyer */ + size_t index; /* Indice de l'opérande visé */ + char *end; /* Poursuite du parcours ? */ + GArchOperand *found; /* Opérande trouvé */ - g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&instr->range)); + result = NULL; -} + g_thick_object_lock(G_THICK_OBJECT(instr)); + /* Recherche au premier niveau */ -/****************************************************************************** -* * -* 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. * -* cursor = emplacement à analyser. * -* * -* Description : Détermine si le conteneur s'inscrit dans une plage donnée. * -* * -* Retour : Bilan de la détermination, utilisable en comparaisons. * -* * -* Remarques : - * -* * -******************************************************************************/ + index = strtoul(path, &end, 10); -static int g_arch_instruction_contain_cursor(const GArchInstruction *instr, size_t index, size_t repeat, const GLineCursor *cursor) -{ - int result; /* Conclusion à retourner */ - vmpa2t addr; /* Autre emplacement à comparer*/ + if ((index == ULONG_MAX && errno == ERANGE) || (index == 0 && errno == EINVAL)) + { + LOG_ERROR_N("strtoul"); + goto done; + } + + found = g_arch_instruction_get_operand(instr, index); + if (found == NULL) goto done; + + if (*end == '\0') + { + result = found; + goto done; + } + + /* Recherche en profondeur */ + + assert(*end == ':'); + + result = NULL;//g_arch_operand_get_inner_operand_from_path(found, end + 1); - assert(G_IS_BINARY_CURSOR(cursor)); + unref_object(found); - g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr); + done: - result = cmp_mrange_with_vmpa(&instr->range, &addr); + g_thick_object_unlock(G_THICK_OBJECT(instr)); return result; } -#endif + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* 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. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Renseigne sur les propriétés liées à un générateur. * +* Description : Charge un objet depuis un flux de données. * * * -* Retour : Propriétés particulières associées. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *instr, size_t index, size_t repeat) +static bool g_arch_instruction_load(GSerializableObject *object, GObjectStorage *storage, int fd) { - return BLF_HAS_CODE; + bool result; /* Bilan à retourner */ + uleb128_t extra; /* Données embarquées */ + + /* Propriétés internes */ + + result = load_uleb128(&extra, fd); + + if (result) + g_thick_object_set_extra(G_THICK_OBJECT(object), extra); + + /* Liaisons avec d'autres instructions */ + + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à représenter. * -* 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. * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* Description : Sauvegarde un objet dans un flux de données. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static void _g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) +static bool g_arch_instruction_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { - const char *key; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ - size_t count; /* Nombre d'opérandes en place */ + bool result; /* Bilan à retourner */ + GArchInstruction *instr; /* Version spécialisée */ + size_t src_count; /* Quantité de sources */ + size_t dest_count; /* Quantité de destinations */ + off64_t *ins_offsets; /* Emplacements d'instructions */ size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à manipuler */ + GArchInstruction *linked; /* Instruction liée */ + size_t op_count; /* Quantité d'opérandes */ + off64_t *op_offsets; /* Emplacements d'opérandes */ + GArchOperand *op; /* Opérande à traiter */ + guint extra; /* Données embarquées */ + InstructionLinkType type; /* Type de lien */ - g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&instr->range)); + assert(g_thick_object_check_lock(G_THICK_OBJECT(object))); - g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&instr->range)); + /* Préparation des références aux instructions liées */ - g_buffer_line_fill_content(line, DLC_BINARY, content, &instr->range, VMPA_NO_PHYSICAL); + instr = G_ARCH_INSTRUCTION(object); - /* Instruction proprement dite */ + src_count = g_arch_instruction_count_src_links(instr); + dest_count = g_arch_instruction_count_dest_links(instr); - key = g_arch_instruction_get_keyword(instr); - klen = strlen(key); + ins_offsets = malloc((src_count + dest_count) * sizeof(off64_t)); - g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, G_OBJECT(instr)); + for (i = 0; i < src_count && result; i++) + { + linked = g_arch_instruction_get_linked_source(instr, i, (InstructionLinkType []) { 0 }); - /* Liste des opérandes */ + result = g_object_storage_store_object(storage, "instructions", + G_SERIALIZABLE_OBJECT(linked), &ins_offsets[i]); - g_arch_instruction_lock_operands(instr); + unref_object(linked); - count = _g_arch_instruction_count_operands(instr); + } - if (count > 0) + for (i = 0; i < dest_count && result; i++) { - op = _g_arch_instruction_get_operand(instr, 0); - g_arch_operand_print(op, line); - g_object_unref(G_OBJECT(op)); + linked = g_arch_instruction_get_linked_destination(instr, i, (InstructionLinkType []) { 0 }); - for (i = 1; i < count; i++) - { - g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); + result = g_object_storage_store_object(storage, "instructions", + G_SERIALIZABLE_OBJECT(linked), &ins_offsets[src_count + i]); - op = _g_arch_instruction_get_operand(instr, i); + unref_object(linked); - g_arch_operand_print(op, line); + } - g_object_unref(G_OBJECT(op)); + if (!result) + goto exit_with_ins_off; - } + /* Préparation des références aux opérandes embarqués */ - } + op_count = g_arch_instruction_count_operands(instr); - g_arch_instruction_unlock_operands(instr); + op_offsets = malloc(op_count * sizeof(off64_t)); -} + for (i = 0; i < op_count && result; i++) + { + op = g_arch_instruction_get_operand(instr, i); + result = g_object_storage_store_object(storage, "operandss", + G_SERIALIZABLE_OBJECT(op), &op_offsets[i]); -/****************************************************************************** -* * -* 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 : - * -* * -******************************************************************************/ + unref_object(op); -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); + } -} + if (!result) + goto exit_with_op_off; + /* Propriétés internes */ + extra = g_thick_object_get_extra(G_THICK_OBJECT(object)); -/* ---------------------------------------------------------------------------------- */ -/* CONSERVATION ET RECHARGEMENT DES DONNEES */ -/* ---------------------------------------------------------------------------------- */ + result = store_uleb128((uleb128_t []) { extra }, fd); + if (!result) goto exit; + /* Liaisons avec d'autres instructions */ -/****************************************************************************** -* * -* Paramètres : instr = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * -* * -* Description : Charge un contenu depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ + instr = G_ARCH_INSTRUCTION(object); -static bool _g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à consulter*/ - uleb128_t value; /* Valeur ULEB128 à charger */ - uleb128_t count; /* Nombre d'éléments à traiter */ - uleb128_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à traiter */ + src_count = g_arch_instruction_count_src_links(instr); + dest_count = g_arch_instruction_count_dest_links(instr); - extra = GET_ARCH_INSTR_EXTRA(instr); + result = store_uleb128((uleb128_t []) { src_count }, fd); + if (!result) goto exit; - LOCK_GOBJECT_EXTRA(extra); + result = store_uleb128((uleb128_t []) { dest_count }, fd); + if (!result) goto exit; - result = unpack_uleb128(&value, pbuf); + for (i = 0; i < src_count && result; i++) + { + linked = g_arch_instruction_get_linked_source(instr, i, &type); - if (result) - extra->uid = value; + result = store_uleb128((uleb128_t []) { type }, fd); - if (result) - { - result = unpack_uleb128(&value, pbuf); + unref_object(linked); if (result) - extra->flags = value; + result = store_uleb128((uleb128_t []) { ins_offsets[i] }, fd); } - UNLOCK_GOBJECT_EXTRA(extra); - - if (result) - result = unpack_mrange(&instr->range, pbuf); - - if (result) + for (i = 0; i < dest_count && result; i++) { - result = unpack_uleb128(&count, pbuf); + linked = g_arch_instruction_get_linked_destination(instr, i, &type); - for (i = 0; i < count && result; i++) - { - op = G_ARCH_OPERAND(g_object_storage_unpack_object(storage, "operands", pbuf)); - result = (op != NULL); + result = store_uleb128((uleb128_t []) { type }, fd); - if (result) - g_arch_instruction_attach_extra_operand(instr, op); + unref_object(linked); - } + if (result) + result = store_uleb128((uleb128_t []) { ins_offsets[src_count + i] }, fd); } - if (result) - result = g_arch_instruction_load_destinations(instr, storage, pbuf); - - return result; + /* Opérandes embarqués */ -} + result = store_uleb128((uleb128_t []) { op_count }, fd); + if (!result) goto exit; + for (i = 0; i < op_count && result; i++) + result = store_uleb128((uleb128_t []) { op_offsets[i] }, fd); -/****************************************************************************** -* * -* Paramètres : instr = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * -* * -* Description : Charge un contenu depuis une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ + exit: + exit_with_op_off: -static bool g_arch_instruction_load(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchInstructionClass *class; /* Classe à activer */ + free(op_offsets); - class = G_ARCH_INSTRUCTION_GET_CLASS(instr); + exit_with_ins_off: - result = class->load(instr, storage, pbuf); + free(ins_offsets); return result; } -/****************************************************************************** -* * -* Paramètres : instr = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un contenu dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ -static bool _g_arch_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - instr_extra_data_t *extra; /* Données insérées à consulter*/ - size_t count; /* Nombre d'éléments à traiter */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à traiter */ - - extra = GET_ARCH_INSTR_EXTRA(instr); - LOCK_GOBJECT_EXTRA(extra); - result = pack_uleb128((uleb128_t []){ extra->uid }, pbuf); - if (result) - result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf); - UNLOCK_GOBJECT_EXTRA(extra); - if (result) - result = pack_mrange(&instr->range, pbuf); - if (result) - { - g_arch_instruction_lock_operands(instr); - count = _g_arch_instruction_count_operands(instr); - result = pack_uleb128((uleb128_t []){ count }, pbuf); - for (i = 0; i < count && result; i++) - { - op = _g_arch_instruction_get_operand(instr, i); - result = g_object_storage_pack_object(storage, "operands", G_SERIALIZABLE_OBJECT(op), pbuf); - g_object_unref(G_OBJECT(op)); - } - g_arch_instruction_unlock_operands(instr); - } - if (result) - result = g_arch_instruction_store_destinations(instr, storage, pbuf); +#if 0 - return result; -} /****************************************************************************** * * -* Paramètres : instr = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* 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 : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Complète un désassemblage accompli pour une instruction. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool g_arch_instruction_store(GArchInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *class; /* Classe à activer */ + GArchInstructionClass *class; /* Classe des instructions */ class = G_ARCH_INSTRUCTION_GET_CLASS(instr); - result = class->store(instr, storage, pbuf); - - return result; + if (class->call_hook != NULL) + class->call_hook(instr, type, proc, context, format); } + + + + + +#endif + + + + + + + + + + |