diff options
Diffstat (limited to 'src/arch')
44 files changed, 4365 insertions, 4331 deletions
diff --git a/src/arch/Makefile.am b/src/arch/Makefile.am index 6ee2690..6683854 100644 --- a/src/arch/Makefile.am +++ b/src/arch/Makefile.am @@ -1,43 +1,57 @@ -noinst_LTLIBRARIES = libarch4.la # libarch.la +noinst_LTLIBRARIES = libarch.la libarchui.la + +# libarch_la_SOURCES = \ +# archbase.h archbase.c \ +# context-int.h \ +# context.h context.c \ +# instriter.h instriter.c \ +# link.h link.c \ +# post.h post.c \ +# storage.h storage.c + +# libarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) + +# libarch_la_LIBADD = \ +# operands/libarchoperands.la + + +# +# processor-int.h \ +# processor.h processor.c \ +# libarch_la_SOURCES = \ - archbase.h archbase.c \ - context-int.h \ - context.h context.c \ - instriter.h instriter.c \ instruction-int.h \ instruction.h instruction.c \ - link.h link.c \ - operand-int.h operand-int.c \ + operand-int.h \ operand.h operand.c \ - post.h post.c \ - processor-int.h \ - processor.h processor.c \ register-int.h \ register.h register.c \ - storage.h storage.c \ vmpa.h vmpa.c -libarch_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) +libarch_la_CFLAGS = $(LIBGOBJ_CFLAGS) libarch_la_LIBADD = \ instructions/libarchinstructions.la \ operands/libarchoperands.la -libarch4_la_SOURCES = \ - vmpa.h vmpa.c +libarchui_la_SOURCES = \ + instruction-ui-int.h \ + instruction-ui.h instruction-ui.c \ + operand-ui-int.h \ + operand-ui.h operand-ui.c -libarch4_la_CFLAGS = $(TOOLKIT_CFLAGS) +libarchui_la_CFLAGS = $(LIBGTK_CFLAGS) -libarch4_la_LIBADD = +libarchui_la_LIBADD = \ + operands/libarchoperandsui.la devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) -dev_HEADERS = $(libarch_la_SOURCES:%c=) - +dev_HEADERS = $(libarch_la_SOURCES:%c=) $(libarchui_la_SOURCES:%c=) -#SUBDIRS = instructions operands +SUBDIRS = instructions operands diff --git a/src/arch/archbase.h b/src/arch/archbase.h index 59bf18e..b29d2a1 100644 --- a/src/arch/archbase.h +++ b/src/arch/archbase.h @@ -50,6 +50,7 @@ typedef uint64_t vmpa_t; #define VMPA_MAX_SIZE 19 +#if 0 /* Taille des données intégrées */ typedef enum _MemoryDataSize { @@ -68,6 +69,7 @@ typedef enum _MemoryDataSize MDS_64_BITS_SIGNED = 0x85 /* Opérande sur 64 bits signés */ } MemoryDataSize; +#endif #define MDS_RANGE(mds) ((mds & 0xf) - 1) @@ -99,13 +101,13 @@ typedef enum _MemoryDataSize __result; \ }) - +#if 0 #define MDS_4_BITS MDS_4_BITS_UNSIGNED #define MDS_8_BITS MDS_8_BITS_UNSIGNED #define MDS_16_BITS MDS_16_BITS_UNSIGNED #define MDS_32_BITS MDS_32_BITS_UNSIGNED #define MDS_64_BITS MDS_64_BITS_UNSIGNED - +#endif /* Etablit la comparaison entre deux adresses. */ diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index 7dbbe27..d426cea 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * instruction-int.h - prototypes pour la définition générique interne des instructions * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,18 +25,29 @@ #define _ARCH_INSTRUCTION_INT_H +#include <stdint.h> + + #include "instruction.h" -#include "../analysis/storage/storage.h" #include "../common/array.h" -#include "../glibext/objhole.h" +#include "../glibext/objhole-int.h" /* Indique l'encodage d'une instruction de façon détaillée. */ -typedef const char * (* get_instruction_encoding_fc) (const GArchInstruction *); +typedef char * (* get_instruction_encoding_fc) (const GArchInstruction *); /* Fournit le nom humain de l'instruction manipulée. */ -typedef const char * (* get_instruction_keyword_fc) (GArchInstruction * ); +typedef char * (* get_instruction_keyword_fc) (const GArchInstruction *); + + + +#if 0 + +#include "../analysis/storage/storage.h" + + + /* Complète un désassemblage accompli pour une instruction. */ typedef void (* call_instruction_hook_fc) (GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *); @@ -67,80 +78,45 @@ typedef bool (* store_instruction_fc) (GArchInstruction *, GObjectStorage *, pac -/* Informations glissées dans la structure GObject de GArchOperand */ -typedef struct _instr_extra_data_t -{ - itid_t uid; /* Identifiant unique du type */ - - ArchInstrFlag flags; /* Informations complémentaires*/ - -} instr_extra_data_t; +#endif -/* Informations glissées dans la structure GObject de GArchInstruction */ -typedef union _instr_obj_extra_t -{ - instr_extra_data_t data; /* Données embarquées */ - lockable_obj_extra_t lockable; /* Gestion d'accès aux fanions */ -} instr_obj_extra_t; +/* Conservation d'une adresse et de propriétées */ +typedef unsigned long compact_ins_link_t; /* Définition générique d'une instruction d'architecture (instance) */ struct _GArchInstruction { - GObject parent; /* A laisser en premier */ + GThickObject parent; /* A laisser en premier */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ + GBinaryPortion *rel_area; /* Zone de référence */ + rel_mrange_t rel_range; /* Emplacement compressé */ /** - * L'inclusion des informations suivantes dépend de l'architecture. - * - * Si la structure GObject possède un trou, on remplit de préférence - * ce dernier. + * A laisser à la suite de la localisation précédente pour éviter + * les espaces vide dans la structure. */ + uint16_t link_count; /* Quantité de liens établis */ - instr_obj_extra_t extra; /* Externalisation embarquée */ - -#endif - - mrange_t range; /* Emplacement en mémoire */ + compact_ins_link_t *links; /* Liste de ces liens */ flat_array_t *operands; /* Liste des opérandes */ - /** - * Il existe le besoin indéniable d'un verrou pour les accès aux instructions - * liées. Il faut par ailleurs un verrou distinct pour les sources et les - * destinations car une même instruction peut boucler sur elle même et la - * fonction g_arch_instruction_change_link() pose des verrous sur les - * deux extrémités. - * - * La GLib propose les fonctions g_bit_lock() / g_bit_unlock(), légères mais - * sans distinction entre lectures et écritures. Tant pis : la réduction de - * l'empreinte mémoire prime ! - * - * Par contre la documentation indique : - * - * """ - * Attempting to lock on two different bits within the same integer is not supported. - * """ - * - * Donc on doit bien conserver un compteur distinct pour chaque extrémité. - * Cela correspond de toute façon à la définition optimisée des tableaux - * suivante. - */ - - flat_array_t *from; /* Origines des références */ - flat_array_t *to; /* Instructions visées */ - }; /* Définition générique d'une instruction d'architecture (classe) */ struct _GArchInstructionClass { - GObjectClass parent; /* A laisser en premier */ + GThickObjectClass parent; /* A laisser en premier */ get_instruction_encoding_fc get_encoding; /* Obtention de l'encodage */ get_instruction_keyword_fc get_keyword; /* Texte humain équivalent */ + +#if 0 + + //get_instruction_encoding_fc get_encoding; /* Obtention de l'encodage */ + //get_instruction_keyword_fc get_keyword; /* Texte humain équivalent */ call_instruction_hook_fc call_hook; /* Décrochages éventuels */ build_instruction_tooltip_fc build_tooltip; /* Construction d'une bulle*/ get_instruction_desc_fc get_desc; /* Description assez complète */ @@ -155,22 +131,50 @@ struct _GArchInstructionClass //get_instruction_rw_regs_fc get_rw_regs; /* Liste des registres liés */ +#endif + }; +/* Met en place une instruction d'architecture. */ +bool g_arch_instruction_create(GArchInstruction *, itid_t); + + + /** * Accès aux informations éventuellement déportées. */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ -# define GET_ARCH_INSTR_EXTRA(ins) (instr_extra_data_t *)&ins->extra +#define ARCH_INSTRUCTION_EXTRA_DATA \ + \ + unsigned int reserved : GOBJECT_RESERVED_EXTRA_BITS; \ + \ + /** \ + * itid_t \ + */ \ + unsigned int tid : 16; \ + \ + /** \ + * ArchOperandFlag \ + */ \ + unsigned int flags : 8; -#else -# define GET_ARCH_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), instr_extra_data_t) +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _instruction_extra_data_t +{ + ARCH_INSTRUCTION_EXTRA_DATA; /* Socle commun */ + +} instruction_extra_data_t; + + +#define GET_ARCH_INSTR_EXTRA(op) \ + GET_GOBJECT_EXTRA(op, instruction_extra_data_t) + +#define SET_ARCH_INSTR_EXTRA(op, data) \ + SET_GOBJECT_EXTRA(op, instruction_extra_data_t, data) -#endif /** diff --git a/src/arch/instruction-ui-int.h b/src/arch/instruction-ui-int.h new file mode 100644 index 0000000..b07f40c --- /dev/null +++ b/src/arch/instruction-ui-int.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction-ui-int.h - prototypes pour la définition générique interne des instructions sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_INSTRUCTION_UI_INT_H +#define _ARCH_INSTRUCTION_UI_INT_H + + +#include "instruction-ui.h" + + + +#if 0 + +/* Traduit un opérande en version humainement lisible. */ +typedef void (* print_operand_ui_fc) (const GArchOperandUI *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +typedef char * (* build_operand_ui_tooltip_fc) (const GArchOperandUI *, const GLoadedBinary *); + + + +/* Définition générique d'un opérande d'architecture (interface) */ +struct _GArchOperandUIInterface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + print_operand_ui_fc print; /* Texte humain équivalent */ + build_operand_ui_tooltip_fc build_tooltip; /* Définition de description*/ + +}; + +#endif + + +#endif /* _ARCH_INSTRUCTION_UI_INT_H */ diff --git a/src/arch/instruction-ui.c b/src/arch/instruction-ui.c new file mode 100644 index 0000000..7f923d8 --- /dev/null +++ b/src/arch/instruction-ui.c @@ -0,0 +1,254 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction-ui.c - gestion générique des instructions sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "instruction-ui.h" + + +#include "instruction-int.h" +#include "operand-ui.h" +#include "../analysis/content.h" +#include "../common/cpp.h" +#include "../glibext/generator-int.h" +#include "../glibext/options/asm.h" + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Renseigne sur les propriétés liées à un générateur. */ +static BufferLineFlags g_arch_instruction_ui_get_flags(const GTokenGenerator *, size_t, size_t); + +/* Etablit dans une ligne de rendu le contenu représenté. */ +static void g_arch_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); + +#if 0 + +/* Retrouve l'emplacement correspondant à une position donnée. */ +static void g_arch_instruction_ui_compute_cursor(const GArchInstruction *, gint, size_t, size_t, GLineCursor **); + +/* Détermine si le conteneur s'inscrit dans une plage donnée. */ +static int g_arch_instruction_ui_contain_cursor(const GArchInstruction *, size_t, size_t, const GLineCursor *); + +#endif + + + +/* ---------------------------------------------------------------------------------- */ +/* OFFRE DE CAPACITES DE GENERATION */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface) +{ + /** + * La procédure par défaut de iface->count() ne doit pas être retouchée ! + */ + + iface->get_flags = g_arch_instruction_ui_get_flags; + iface->populate = g_arch_instruction_ui_populate_line; + +#if 0 + iface->compute = (linegen_compute_fc)g_arch_instruction_ui_compute_cursor; + iface->contain = (linegen_contain_fc)g_arch_instruction_ui_contain_cursor; +#endif + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à consulter. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* * +* Description : Renseigne sur les propriétés liées à un générateur. * +* * +* Retour : Propriétés particulières associées. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static BufferLineFlags g_arch_instruction_ui_get_flags(const GTokenGenerator *generator, size_t index, size_t repeat) +{ + BufferLineFlags result; /* Fanions à retourner */ + + result = BLF_HAS_CODE; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * +* * +* Description : Etablit dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) +{ + GArchInstruction *instr; /* Version spécialisée */ + GBinContent *content; /* Contenu brut d'origine */ + mrange_t range; /* Emplacement couvert */ + char *key; /* Mot clef principal */ + size_t count; /* Nombre d'opérandes en place */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à manipuler */ + + instr = G_ARCH_INSTRUCTION(generator); + content = G_BIN_CONTENT(data); + + /* Prologue */ + + if (g_arch_instruction_get_range(instr, &range)) + { + g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_content(line, ACO_BINARY, content, &range, VMPA_NO_PHYSICAL); + + } + + /* Instruction proprement dite */ + + key = g_arch_instruction_get_keyword(instr); + + g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_INSTRUCTION, SL(key), NULL, G_OBJECT(instr)); + + free(key); + + /* Liste des opérandes */ + + g_thick_object_lock(G_THICK_OBJECT(instr)); + + count = g_arch_instruction_count_operands(instr); + + if (count > 0) + { + op = g_arch_instruction_get_operand(instr, 0); + g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line); + unref_object(op); + + for (i = 1; i < count; i++) + { + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL); + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_NONE, STCSL(" "), NULL, NULL); + + op = g_arch_instruction_get_operand(instr, i); + g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line); + unref_object(op); + + } + + } + + g_thick_object_unlock(G_THICK_OBJECT(instr)); + +} + + +#if 0 + + +/****************************************************************************** +* * +* 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] * +* * +* Description : Retrouve l'emplacement correspondant à une position donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_instruction_ui_compute_cursor(const GArchInstruction *instr, gint x, size_t index, size_t repeat, GLineCursor **cursor) +{ + *cursor = g_binary_cursor_new(); + + g_binary_cursor_update(G_BINARY_CURSOR(*cursor), get_mrange_addr(&instr->range)); + +} + + +/****************************************************************************** +* * +* 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 : - * +* * +******************************************************************************/ + +static int g_arch_instruction_ui_contain_cursor(const GArchInstruction *instr, size_t index, size_t repeat, const GLineCursor *cursor) +{ + int result; /* Conclusion à retourner */ + vmpa2t addr; /* Autre emplacement à comparer*/ + + assert(G_IS_BINARY_CURSOR(cursor)); + + g_binary_cursor_retrieve(G_BINARY_CURSOR(cursor), &addr); + + result = cmp_mrange_with_vmpa(&instr->range, &addr); + + return result; + +} + + +#endif diff --git a/src/arch/instruction-ui.h b/src/arch/instruction-ui.h new file mode 100644 index 0000000..62a52f2 --- /dev/null +++ b/src/arch/instruction-ui.h @@ -0,0 +1,41 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * instruction-ui.h - prototypes pour la gestion générique des instructions sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_INSTRUCTION_UI_H +#define _ARCH_INSTRUCTION_UI_H + + +#include "../glibext/generator.h" +#include "../glibext/helpers.h" + + + +/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ + + +/* Procède à l'initialisation de l'interface de génération. */ +void g_arch_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *); + + + +#endif /* _ARCH_INSTRUCTION_UI_H */ 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 + + + + + + + + + + diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 3c9c149..98bc73e 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * instruction.h - prototypes pour la gestion générique des instructions * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,194 +25,118 @@ #define _ARCH_INSTRUCTION_H -#include <sys/types.h> +#include <stdbool.h> +#include <stdint.h> -#include "context.h" #include "operand.h" -#include "register.h" #include "vmpa.h" -#include "../analysis/type.h" -#include "../common/packed.h" -#include "../format/executable.h" +#include "../glibext/helpers.h" +#include "../glibext/portion.h" -#define G_TYPE_ARCH_INSTRUCTION g_arch_instruction_get_type() -#define G_ARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_arch_instruction_get_type(), GArchInstruction)) -#define G_IS_ARCH_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_arch_instruction_get_type())) -#define G_ARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass)) -#define G_IS_ARCH_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_INSTRUCTION)) -#define G_ARCH_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_INSTRUCTION, GArchInstructionClass)) +/* ----------------------- DEFINITION GENERIQUE D'INSTRUCTION ----------------------- */ -/* Définition générique d'une instruction d'architecture (instance) */ -typedef struct _GArchInstruction GArchInstruction; +#define G_TYPE_ARCH_INSTRUCTION (g_arch_instruction_get_type()) -/* Définition générique d'une instruction d'architecture (classe) */ -typedef struct _GArchInstructionClass GArchInstructionClass; +DECLARE_GTYPE(GArchInstruction, g_arch_instruction, G, ARCH_INSTRUCTION); -/* Drapeaux pour informations complémentaires */ - -#define AIF_USER_BIT 4 - -typedef enum _ArchInstrFlag -{ - AIF_NONE = (0 << 0), /* Aucune information */ - AIF_ROUTINE_START = (1 << 0), /* Début de routine */ - AIF_RETURN_POINT = (1 << 1), /* Retour de fonction appelée */ - AIF_COND_RETURN_POINT = (1 << 2), /* Retour éventuel de fonction */ - AIF_CALL = (1 << 3), /* Instruction d'appel */ - - AIF_LOW_USER = (1 << AIF_USER_BIT), /* Premier bit disponible */ - AIF_HIGH_USER = (1 << 7), /* Dernier bit disponible */ - -} ArchInstrFlag; - /* Type pour les types d'instructions */ typedef uint16_t itid_t; -/* Types de crochet de traitement */ -typedef enum _InstrProcessHook -{ - IPH_FETCH, /* Itinéraire de désassemblage */ - IPH_LINK, /* Edition des liens */ - IPH_POST, /* Résolution des symboles */ - - IPH_COUNT - -} InstrProcessHook; - - -/* Indique le type défini pour une instruction d'architecture. */ -GType g_arch_instruction_get_type(void); +/* Fournit l'identifiant correspondant à un type d'instructions. */ +itid_t g_arch_instruction_get_type_id(const GArchInstruction *); /* Indique l'encodage d'une instruction de façon détaillée. */ -const char *g_arch_instruction_get_encoding(const GArchInstruction *); - -/* Ajoute une information complémentaire à une instruction. */ -bool g_arch_instruction_set_flag(GArchInstruction *, ArchInstrFlag); +char *g_arch_instruction_get_encoding(const GArchInstruction *); -/* Retire une information complémentaire à une instruction. */ -bool g_arch_instruction_unset_flag(GArchInstruction *, ArchInstrFlag); - -/* Détermine si une instruction possède un fanion particulier. */ -bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstrFlag); +/* Fournit le nom humain de l'instruction manipulée. */ +char *g_arch_instruction_get_keyword(const GArchInstruction *); -/* Fournit les informations complémentaires d'une instruction. */ -ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *); -/* Définit l'identifiant unique pour un ensemble d'instructions. */ -void g_arch_instruction_set_unique_id(GArchInstruction *, itid_t); + /* Type de masques pour les encodages d'instructions */ +typedef enum _InstructionBytesMask +{ + /** + * Correspond aux bits fixes : pas de valeurs de registre ni de valeur entière. + */ + IBM_LOOSE, -/* Fournit l'identifiant unique pour un ensemble d'instructions. */ -itid_t g_arch_instruction_get_unique_id(const GArchInstruction *); + /** + * Dissimulation des références à des éléments externes pouvant varier avec + * entre compilations : adresses de saut ou d'appel, références vers des tables, + * etc. + */ + IBM_LOCAL, + /** + * Dissimulation des déplacements à partir d'une base. + */ + IBM_STRICT, -/** - * La définition de "GArchProcessor", utile aux traitements complémentaires, ne peut - * se faire en incluant le fichier d'en-tête "processor.h", pour cause de références - * circulaires. - * - * On procède donc à une seconde déclaration, en attendant éventuellement mieux. - */ + /** + * Conservation de toutes les valeurs immédiates et dissimulation des registres. + */ + IBM_LARGE, -/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */ -typedef struct _GArchProcessor GArchProcessor; + IBM_COUNT +} InstructionBytesMask; -/* Complète un désassemblage accompli pour une instruction. */ -typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *); - -/* Complète un désassemblage accompli pour une instruction. */ -void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *); -/* Définit la localisation d'une instruction. */ -void g_arch_instruction_set_range(GArchInstruction *, const mrange_t *); +/* Calcule la localisation d'une instruction. */ +void g_arch_instruction_compute_range(GArchInstruction *, GBinaryPortion *, const vmpa2t *, phys_t); /* Fournit la place mémoire d'une instruction. */ -const mrange_t *g_arch_instruction_get_range(const GArchInstruction *); - - - -/* Fournit la localisation d'une instruction. */ -void g_arch_instruction_get_location(const GArchInstruction *, off_t *, off_t *, vmpa_t *) __attribute__ ((deprecated)); +bool g_arch_instruction_get_range(const GArchInstruction *, mrange_t *); +#define AIF_USER_BIT 4 -/* Liste les registres lus et écrits par l'instruction. */ -void g_arch_instruction_get_rw_registers(const GArchInstruction *, GArchRegister ***, size_t *, GArchRegister ***, size_t *) __attribute__ ((deprecated)); +typedef enum _ArchInstructionFlag +{ + AIF_NONE = (0 << 0), /* Aucune information */ + AIF_ROUTINE_START = (1 << 0), /* Début de routine */ + AIF_RETURN_POINT = (1 << 1), /* Retour de fonction appelée */ + AIF_COND_RETURN_POINT = (1 << 2), /* Retour éventuel de fonction */ + AIF_CALL = (1 << 3), /* Instruction d'appel */ + AIF_LOW_USER = (1 << AIF_USER_BIT), /* Premier bit disponible */ + AIF_HIGH_USER = (1 << 7), /* Dernier bit disponible */ +} ArchInstructionFlag; -/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */ +#define AIF_USER_FLAG(n) (1 << (AIF_USER_BIT + n)) -/* Verrouille les accès à la liste des opérandes. */ -void g_arch_instruction_lock_operands(GArchInstruction *); +/* Ajoute une information complémentaire à une instruction. */ +bool g_arch_instruction_set_flag(GArchInstruction *, ArchInstructionFlag); -/* Déverrouille les accès à la liste des opérandes. */ -void g_arch_instruction_unlock_operands(GArchInstruction *); +/* Retire une information complémentaire à une instruction. */ +bool g_arch_instruction_unset_flag(GArchInstruction *, ArchInstructionFlag); -/* Attache un opérande supplémentaire à une instruction. */ -void g_arch_instruction_attach_extra_operand(GArchInstruction *, GArchOperand *); +/* Détermine si une instruction possède un fanion particulier. */ +bool g_arch_instruction_has_flag(const GArchInstruction *, ArchInstructionFlag); -/* Indique la quantité d'opérandes présents dans l'instruction. */ -size_t _g_arch_instruction_count_operands(const GArchInstruction *); +/* Fournit les particularités de l'instruction. */ +ArchInstructionFlag g_arch_instruction_get_flags(const GArchInstruction *); -/* Fournit un opérande donné d'une instruction. */ -GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *, size_t); -/* Remplace un opérande d'une instruction par un autre. */ -bool _g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *); +/* Types de crochet de traitement */ +typedef enum _InstrProcessHook +{ + IPH_FETCH, /* Itinéraire de désassemblage */ + IPH_LINK, /* Edition des liens */ + IPH_POST, /* Résolution des symboles */ -/* Détache un opérande liée d'une instruction. */ -bool _g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *); - - -#define g_arch_instruction_count_operands(ins) \ - ({ \ - size_t __result; \ - g_arch_instruction_lock_operands(ins); \ - __result = _g_arch_instruction_count_operands(ins); \ - g_arch_instruction_unlock_operands(ins); \ - __result; \ - }) - -#define g_arch_instruction_get_operand(ins, idx) \ - ({ \ - GArchOperand *__result; \ - g_arch_instruction_lock_operands(ins); \ - __result = _g_arch_instruction_get_operand(ins, idx); \ - g_arch_instruction_unlock_operands(ins); \ - __result; \ - }) - -#define g_arch_instruction_replace_operand(ins, o, n) \ - ({ \ - bool __result; \ - g_arch_instruction_lock_operands(ins); \ - __result = _g_arch_instruction_replace_operand(ins, o, n); \ - g_arch_instruction_unlock_operands(ins); \ - __result; \ - }) - -#define g_arch_instruction_detach_operand(ins, o) \ - ({ \ - bool __result; \ - g_arch_instruction_lock_operands(ins); \ - __result = _g_arch_instruction_detach_operand(ins, o); \ - g_arch_instruction_unlock_operands(ins); \ - __result; \ - }) + IPH_COUNT +} InstrProcessHook; -/* Détermine le chemin conduisant à un opérande. */ -char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *); -/* Obtient l'opérande correspondant à un chemin donné. */ -GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *); @@ -236,30 +160,24 @@ typedef enum _InstructionLinkType } InstructionLinkType; -/* Déscription d'une liaison entre deux instructions */ -typedef struct _instr_link_t -{ - GArchInstruction *linked; /* Autre instruction liée */ - InstructionLinkType type; /* Type de liaison */ - -} instr_link_t; - -#define ref_instr_link(l) g_object_ref(G_OBJECT(l->linked)); -#define unref_instr_link(l) g_object_unref(G_OBJECT(l->linked)); +/* Détermine si un type de lien amène à une instruction. */ +bool g_arch_instruction_has_src_link(const GArchInstruction *, InstructionLinkType); +/* Détermine si un type de lien émerge d'une instruction. */ +bool g_arch_instruction_has_dest_link(const GArchInstruction *, InstructionLinkType); -/* Met à disposition un encadrement des accès aux liens. */ -void g_arch_instruction_lock_unlock_links(GArchInstruction *, bool, bool); +/* Détermine si une instruction est source d'une autre. */ +bool g_arch_instruction_has_src_link_with(const GArchInstruction *, const GArchInstruction *); -/* Détermine si un type de lien existe dans une instruction. */ -bool g_arch_instruction_has_link(GArchInstruction *, InstructionLinkType); - -/* Détermine si un lien est déjà établi entre deux instructions. */ -bool g_arch_instruction_has_link_to(GArchInstruction *, const GArchInstruction *); +/* Détermine si une instruction est destination d'une autre. */ +bool g_arch_instruction_has_dest_link_with(const GArchInstruction *, const GArchInstruction *); /* Etablit un lien entre deux instructions. */ -void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType); +void g_arch_instruction_link(GArchInstruction *, GArchInstruction *, InstructionLinkType); + +/* Supprime un lien entre deux instructions. */ +void g_arch_instruction_unlink(GArchInstruction *, GArchInstruction *, InstructionLinkType); /* Change la nature d'un lien entre deux instructions. */ bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType); @@ -267,46 +185,72 @@ bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, Inst /* Supprime tous les liens établis avec d'autres instructions. */ void g_arch_instruction_delete_all_links(GArchInstruction *); -#define g_arch_instruction_lock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true) -#define g_arch_instruction_unlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false) +/* Fournit la quantité d'instructions placées en source. */ +size_t g_arch_instruction_count_src_links(const GArchInstruction *); -/* Fournit la quantité d'instructions pointant vers une autre. */ -size_t g_arch_instruction_count_sources(const GArchInstruction *); +/* Fournit la quantité d'instructions placées en destination. */ +size_t g_arch_instruction_count_dest_links(const GArchInstruction *); -/* Fournit les détails d'une origine d'une instruction donnée. */ -const instr_link_t *g_arch_instruction_get_source(GArchInstruction *, size_t); +/* Fournit les détails d'une source donnée d'une instruction. */ +GArchInstruction *g_arch_instruction_get_linked_source(const GArchInstruction *, size_t, InstructionLinkType *); -/* Fournit tous les détails d'origine d'une instruction donnée. */ -instr_link_t *g_arch_instruction_get_sources(GArchInstruction *, size_t *); +/* Fournit les détails d'une destination donnée d'une instruction. */ +GArchInstruction *g_arch_instruction_get_linked_destination(const GArchInstruction *, size_t, InstructionLinkType *); -#define g_arch_instruction_lock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true) -#define g_arch_instruction_unlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false) -/* Donne le nombre d'instructions non naturellement suivantes. */ -size_t g_arch_instruction_count_destinations(const GArchInstruction *); -/* Fournit les détails d'une destination d'une instruction. */ -const instr_link_t *g_arch_instruction_get_destination(GArchInstruction *, size_t); +/* --------------------------- MANIPULATION DES OPERANDES --------------------------- */ -/* Fournit la destination d'une instruction et d'un type donné. */ -GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *, InstructionLinkType); -/* Fournit tous les détails de destination d'une instruction. */ -instr_link_t *g_arch_instruction_get_destinations(GArchInstruction *, size_t *); +/* Indique la quantité d'opérandes présents dans l'instruction. */ +size_t g_arch_instruction_count_operands(const GArchInstruction *); +/* Attache un opérande supplémentaire à une instruction. */ +void g_arch_instruction_attach_operand(GArchInstruction *, GArchOperand *); +/* Remplace un opérande d'une instruction par un autre. */ +bool g_arch_instruction_replace_operand(GArchInstruction *, GArchOperand *, GArchOperand *); -/* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */ +/* Détache un opérande liée d'une instruction. */ +bool g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *); +/* Fournit un opérande donné d'une instruction. */ +GArchOperand *g_arch_instruction_get_operand(const GArchInstruction *, size_t); + +/* Détermine le chemin conduisant à un opérande. */ +char *g_arch_instruction_find_operand_path(GArchInstruction *, const GArchOperand *); + +/* Obtient l'opérande correspondant à un chemin donné. */ +GArchOperand *g_arch_instruction_get_operand_from_path(GArchInstruction *, const char *); + + + + +#if 0 + + + +/** + * La définition de "GArchProcessor", utile aux traitements complémentaires, ne peut + * se faire en incluant le fichier d'en-tête "processor.h", pour cause de références + * circulaires. + * + * On procède donc à une seconde déclaration, en attendant éventuellement mieux. + */ + +/* Depuis "processeur.h" : définition générique d'un processeur d'architecture (instance) */ +typedef struct _GArchProcessor GArchProcessor; + + +/* Complète un désassemblage accompli pour une instruction. */ +typedef void (* instr_hook_fc) (GArchInstruction *, GArchProcessor *, GProcContext *, GExeFormat *); + +/* Complète un désassemblage accompli pour une instruction. */ +void g_arch_instruction_call_hook(GArchInstruction *, InstrProcessHook, GArchProcessor *, GProcContext *, GExeFormat *); -/* Fournit le nom humain de l'instruction manipulée. */ -const char *g_arch_instruction_get_keyword(GArchInstruction *); -/* Construit un petit résumé concis de l'instruction. */ -char *g_arch_instruction_build_tooltip(const GArchInstruction *); -/* Fournit une description pour l'instruction manipulée. */ -const char *g_arch_instruction_get_description(const GArchInstruction *); +#endif diff --git a/src/arch/instructions/Makefile.am b/src/arch/instructions/Makefile.am index 28cf90f..d6fc4bd 100644 --- a/src/arch/instructions/Makefile.am +++ b/src/arch/instructions/Makefile.am @@ -1,12 +1,19 @@ -noinst_LTLIBRARIES = libarchinstructions.la +noinst_LTLIBRARIES = libarchinstructions.la libarchinstructionsui.la libarchinstructions_la_SOURCES = \ + raw-int.h \ raw.h raw.c \ undefined-int.h \ undefined.h undefined.c -libarchinstructions_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) +libarchinstructions_la_CFLAGS = $(LIBGOBJ_CFLAGS) + +libarchinstructionsui_la_SOURCES = \ + raw-ui.h raw-ui.c \ + undefined-ui.h undefined-ui.c + +libarchinstructionsui_la_CFLAGS = $(LIBGTK4_CFLAGS) devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) diff --git a/src/arch/instructions/raw-int.h b/src/arch/instructions/raw-int.h new file mode 100644 index 0000000..4a5e64b --- /dev/null +++ b/src/arch/instructions/raw-int.h @@ -0,0 +1,56 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * raw-int.h - prototypes pour la définition interne des instructions de données brutes + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_INSTRUCTIONS_RAW_INT_H +#define _ARCH_INSTRUCTIONS_RAW_INT_H + + +#include "raw.h" +#include "../instruction-int.h" + + + +/* Définition générique d'une instruction brute d'architecture (instance) */ +struct _GRawInstruction +{ + GArchInstruction parent; /* A laisser en premier */ + +}; + +/* Définition générique d'une instruction brute d'architecture (instance) */ +struct _GRawInstructionClass +{ + GArchInstructionClass parent; /* A laisser en premier */ + +}; + + +/* Met en place une instruction de type 'db/dw/etc' simple. */ +bool g_raw_instruction_create_value(GRawInstruction *, GBinaryPortion *, const vmpa2t *, MemoryDataSize, uint64_t); + +/* Met en place une instruction de type 'db/dw/etc' étendue. */ +bool g_raw_instruction_create_array(GRawInstruction *, GBinaryPortion *, vmpa2t *, MemoryDataSize, const GBinContent *, size_t, SourceEndian); + + + +#endif /* _ARCH_INSTRUCTIONS_RAW_INT_H */ diff --git a/src/arch/instructions/raw-ui.c b/src/arch/instructions/raw-ui.c new file mode 100644 index 0000000..1026dfb --- /dev/null +++ b/src/arch/instructions/raw-ui.c @@ -0,0 +1,261 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * raw-ui.c - opérandes représentant des instructions de données brutes sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "raw-ui.h" + + +#include <assert.h> +#include <ctype.h> +#include <malloc.h> + + +#include "raw.h" +#include "../operand-ui.h" +#include "../operands/immediate.h" +#include "../../glibext/objhole.h" +#include "../../glibext/options/asm.h" + + + +/* Etablit dans une ligne de rendu le contenu représenté. */ +static void g_raw_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_raw_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface) +{ + iface->populate = g_raw_instruction_ui_populate_line; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * +* * +* Description : Etablit dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_raw_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) +{ + GArchInstruction *instr; /* Version spécialisée #1 */ + GRawInstruction *raw; /* Version spécialisée #2 */ + GBinContent *content; /* Contenu brut d'origine */ + mrange_t range; /* Emplacement couvert */ + phys_t max_displayed_len; /* Quantité de code affichée */ + char *key; /* Mot clef principal */ + char *string; /* Chaîne reconstituée */ + size_t iter; /* Tête d'écriture */ + bool first; /* Mémorise une énumération */ + size_t count; /* Nombre d'opérandes en place */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à manipuler */ + GImmediateOperand *imm; /* Version opérande de valeur */ + char byte; /* Octet à afficher (ou pas) */ +#ifndef NDEBUG + bool status; /* Bilan d'une récupération */ +#endif + + instr = G_ARCH_INSTRUCTION(generator); + raw = G_RAW_INSTRUCTION(instr); + content = G_BIN_CONTENT(data); + + g_thick_object_lock(G_THICK_OBJECT(instr)); + + /* Prologue */ + + if (g_arch_instruction_get_range(instr, &range)) + { + /* Localisation */ + + g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + /* Contenu */ + + if (g_raw_instruction_is_padding(raw)) + max_displayed_len = 0; + + else if (g_raw_instruction_is_string(raw)) + max_displayed_len = 1; + + else + { + max_displayed_len = get_mrange_length(&range); + max_displayed_len /= g_arch_instruction_count_operands(instr); + } + + g_buffer_line_fill_content(line, ACO_BINARY, content, &range, max_displayed_len); + + } + + /* Instruction proprement dite */ + + key = g_arch_instruction_get_keyword(instr); + + g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_INSTRUCTION, SL(key), NULL, G_OBJECT(instr)); + + free(key); + + /* Contenu sous forme d'opérandes */ + + if (g_raw_instruction_is_padding(raw)) + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL("..."), NULL, NULL); + + else + { + string = NULL; + iter = 0; + + first = true; + + count = g_arch_instruction_count_operands(instr); + + for (i = 0; i < count; i++) + { + op = g_arch_instruction_get_operand(instr, i); + + if (!G_IS_IMMEDIATE_OPERAND(op)) + goto fallback; + + imm = G_IMMEDIATE_OPERAND(op); + + if (g_immediate_operand_get_size(imm) != MDS_8_BITS) + goto fallback; + + if (!g_raw_instruction_is_string(raw) && g_immediate_operand_get_display(imm) != IOD_CHAR) + goto fallback; + +#ifndef NDEBUG + status = g_immediate_operand_get_value(imm, MDS_8_BITS, &byte); + assert(status); +#else + g_immediate_operand_get_value(imm, MDS_8_BITS, &byte); +#endif + + /* Si le caractère doit apparaître en hexadécimal... */ + + if (!isprint(byte)) + goto fallback; + + /* Impression de l'octet */ + + if (string == NULL) + { + string = calloc(count + 3, sizeof(char)); + + strcpy(string, "\""); + iter = 1; + + } + + string[iter++] = byte; + + unref_object(op); + + continue; + + fallback: + + /* Si une chaîne précède */ + + if (string != NULL && iter > 1) + { + if (!first) + { + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL); + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL); + } + else + first = false; + + string[iter++] = '"'; + + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_STRING, string, iter, NULL, NULL); + + iter = 1; + + } + + /* Intégration en tant qu'opérande classique */ + + if (!first) + { + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL); + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL); + } + else + first = false; + + g_arch_operand_ui_print(G_ARCH_OPERAND_UI(op), line); + + unref_object(op); + + } + + /* Si au final une chaîne traine encore */ + + if (string != NULL && iter > 1) + { + if (!first) + { + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_PUNCT, STCSL(","), NULL, NULL); + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_CHR_PRINTABLE, STCSL(" "), NULL, NULL); + } + + string[iter++] = '"'; + + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_STRING, string, iter, NULL, NULL); + + } + + if (string != NULL) + free(string); + + } + + g_thick_object_unlock(G_THICK_OBJECT(instr)); + +} diff --git a/src/arch/instructions/raw-ui.h b/src/arch/instructions/raw-ui.h new file mode 100644 index 0000000..cd604e6 --- /dev/null +++ b/src/arch/instructions/raw-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * raw-ui.h - prototypes pour les opérandes représentant des instructions de données brutes sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERANDS_RAW_UI_H +#define _ARCH_OPERANDS_RAW_UI_H + + +#include "../../glibext/generator-int.h" + + + +/* Procède à l'initialisation de l'interface de génération. */ +void g_raw_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *); + + + +#endif /* _ARCH_OPERANDS_RAW_UI_H */ diff --git a/src/arch/instructions/raw.c b/src/arch/instructions/raw.c index 26282fa..87297f1 100644 --- a/src/arch/instructions/raw.c +++ b/src/arch/instructions/raw.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * raw.c - instructions pures vues de l'esprit * - * Copyright (C) 2014-2020 Cyrille Bagard + * Copyright (C) 2014-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,36 +25,19 @@ #include <assert.h> -#include <ctype.h> #include <string.h> #include <i18n.h> -#include "../instruction-int.h" +#include "raw-int.h" #include "../operands/immediate.h" -#include "../operands/target.h" -#include "../../core/columns.h" +//#include "../operands/target.h" // FIXME -/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */ - - -/* Définition générique d'une instruction brute d'architecture (instance) */ -struct _GRawInstruction -{ - GArchInstruction parent; /* A laisser en premier */ - -}; - -/* Définition générique d'une instruction brute d'architecture (classe) */ -struct _GRawInstructionClass -{ - GArchInstructionClass parent; /* A laisser en premier */ - -}; +/* --------------------- INSTRUCTION AVEC JEU DE DONNEES BRUTES --------------------- */ /* Initialise la classe des instructions brutes d'architecture. */ @@ -64,40 +47,26 @@ static void g_raw_instruction_class_init(GRawInstructionClass *); static void g_raw_instruction_init(GRawInstruction *); /* Supprime toutes les références externes. */ -static void g_raw_instruction_dispose(GRawInstruction *); +static void g_raw_instruction_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_raw_instruction_finalize(GRawInstruction *); - -/* Indique l'encodage d'une instruction de façon détaillée. */ -static const char *g_raw_instruction_get_encoding(const GRawInstruction *); - -/* Fournit le nom humain de l'instruction manipulée. */ -static const char *g_raw_instruction_get_keyword(const GRawInstruction *); +static void g_raw_instruction_finalize(GObject *); -/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Charge une instruction depuis une mémoire tampon. */ -static bool g_raw_instruction_unserialize(GRawInstruction *, GAsmStorage *, GBinFormat *, packed_buffer_t *); - -/* Sauvegarde une instruction dans une mémoire tampon. */ -static bool g_raw_instruction_serialize(GRawInstruction *, GAsmStorage *, packed_buffer_t *); - - - -/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ - +/* Indique l'encodage d'une instruction de façon détaillée. */ +static char *g_raw_instruction_get_encoding(const GArchInstruction *); -/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static void g_raw_instruction_print(GRawInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); +/* Fournit le nom humain de l'instruction manipulée. */ +static char *g_raw_instruction_get_keyword(const GArchInstruction *); /* ---------------------------------------------------------------------------------- */ -/* INSTRUCTION INCONNUE / DONNEES */ +/* INSTRUCTION AVEC JEU DE DONNEES BRUTES */ /* ---------------------------------------------------------------------------------- */ @@ -124,18 +93,13 @@ static void g_raw_instruction_class_init(GRawInstructionClass *klass) object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_raw_instruction_dispose; - object->finalize = (GObjectFinalizeFunc)g_raw_instruction_finalize; + object->dispose = g_raw_instruction_dispose; + object->finalize = g_raw_instruction_finalize; instr = G_ARCH_INSTRUCTION_CLASS(klass); - instr->get_encoding = (get_instruction_encoding_fc)g_raw_instruction_get_encoding; - instr->get_keyword = (get_instruction_keyword_fc)g_raw_instruction_get_keyword; - - instr->unserialize = (unserialize_instruction_fc)g_raw_instruction_unserialize; - instr->serialize = (serialize_instruction_fc)g_raw_instruction_serialize; - - instr->print = (print_instruction_fc)g_raw_instruction_print; + instr->get_encoding = g_raw_instruction_get_encoding; + instr->get_keyword = g_raw_instruction_get_keyword; } @@ -160,7 +124,7 @@ static void g_raw_instruction_init(GRawInstruction *instr) /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -170,16 +134,16 @@ static void g_raw_instruction_init(GRawInstruction *instr) * * ******************************************************************************/ -static void g_raw_instruction_dispose(GRawInstruction *instr) +static void g_raw_instruction_dispose(GObject *object) { - G_OBJECT_CLASS(g_raw_instruction_parent_class)->dispose(G_OBJECT(instr)); + G_OBJECT_CLASS(g_raw_instruction_parent_class)->dispose(object); } /****************************************************************************** * * -* 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. * * * @@ -189,16 +153,17 @@ static void g_raw_instruction_dispose(GRawInstruction *instr) * * ******************************************************************************/ -static void g_raw_instruction_finalize(GRawInstruction *instr) +static void g_raw_instruction_finalize(GObject *object) { - G_OBJECT_CLASS(g_raw_instruction_parent_class)->finalize(G_OBJECT(instr)); + G_OBJECT_CLASS(g_raw_instruction_parent_class)->finalize(object); } /****************************************************************************** * * -* Paramètres : addr = position à associer à l'instruction. * +* Paramètres : area = portion de binaire incluant l'instruction. * +* addr = adresse virtuelle et/ou position physique. * * size = taille de l'opérande souhaitée. * * value = valeur sur x bits à venir récupérer. * * * @@ -210,127 +175,106 @@ static void g_raw_instruction_finalize(GRawInstruction *instr) * * ******************************************************************************/ -GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *addr, MemoryDataSize size, uint64_t value) +GArchInstruction *g_raw_instruction_new_from_value(GBinaryPortion *area, const vmpa2t *addr, MemoryDataSize size, uint64_t value) { GArchInstruction *result; /* Instruction à retourner */ - GArchOperand *operand; /* Octet non décodé à afficher */ - mrange_t range; /* Couverture de l'instruction */ result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL); - operand = g_imm_operand_new_from_value(size, value); - if (operand == NULL) goto error; + if (!g_raw_instruction_create_value(G_RAW_INSTRUCTION(result), area, addr, size, value)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instance à initialiser pleinement. * +* area = portion de binaire incluant l'instruction. * +* addr = adresse virtuelle et/ou position physique. * +* size = taille de chacun des éléments à représenter. * +* value = valeur sur x bits à venir récupérer. * +* * +* Description : Met en place une instruction de type 'db/dw/etc' simple. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_raw_instruction_create_value(GRawInstruction *instr, GBinaryPortion *area, const vmpa2t *addr, MemoryDataSize size, uint64_t value) +{ + bool result; /* Bilan à retourner */ + GArchOperand *operand; /* Octet non décodé à afficher */ + uint16_t length; /* Taille de l'instruction */ + + result = false; + + operand = g_immediate_operand_new_from_value(size, value); + if (operand == NULL) goto exit; g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING); - g_arch_instruction_attach_extra_operand(result, operand); + g_thick_object_lock(G_THICK_OBJECT(instr)); + + g_arch_instruction_attach_operand(G_ARCH_INSTRUCTION(instr), operand); + unref_object(operand); + + g_thick_object_unlock(G_THICK_OBJECT(instr)); switch (size) { case MDS_8_BITS_UNSIGNED: case MDS_8_BITS_SIGNED: - init_mrange(&range, addr, 1); + length = 1; break; case MDS_16_BITS_UNSIGNED: case MDS_16_BITS_SIGNED: - init_mrange(&range, addr, 2); + length = 2; break; case MDS_32_BITS_UNSIGNED: case MDS_32_BITS_SIGNED: - init_mrange(&range, addr, 4); + length = 4; break; case MDS_64_BITS_UNSIGNED: case MDS_64_BITS_SIGNED: - init_mrange(&range, addr, 8); + length = 8; break; default: assert(false); - goto error; + goto exit; break; } - g_arch_instruction_set_range(result, &range); + g_arch_instruction_compute_range(G_ARCH_INSTRUCTION(instr), area, addr, length); - return result; - - error: - - g_object_unref(G_OBJECT(result)); - - return NULL; - -} + result = true; - -/****************************************************************************** -* * -* Paramètres : content = flux de données à analyser. * -* addr = position courante dans ce flux. [OUT] * -* * -* Description : Crée une instruction de type 'db/dw/etc' pour un uleb128. * -* * -* Retour : Instruction mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa2t *addr) -{ - GArchInstruction *result; /* Instruction à retourner */ - vmpa2t start; /* Départ original de lecture */ - uleb128_t value; /* Valeur uleb128 à représenter*/ - phys_t diff; /* Couverture de la lecture */ - MemoryDataSize leb_size; /* Taille de la valeur */ - GArchOperand *operand; /* Octet non décodé à afficher */ - mrange_t range; /* Couverture de l'instruction */ - - result = NULL; - - copy_vmpa(&start, addr); - - if (!g_binary_content_read_uleb128(content, addr, &value)) - goto error; - - diff = compute_vmpa_diff(&start, addr); - - leb_size = MDS_FROM_BYTES(diff); - assert(leb_size != MDS_UNDEFINED); - - result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL); - - init_mrange(&range, &start, diff); - g_arch_instruction_set_range(result, &range); - - operand = g_imm_operand_new_from_value(leb_size, (uint64_t)value); - if (operand == NULL) goto error; - - g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING); - - g_arch_instruction_attach_extra_operand(result, operand); + exit: return result; - error: - - g_clear_object(&result); - - return NULL; - } /****************************************************************************** * * -* Paramètres : content = flux de données à analyser. * -* addr = position courante dans ce flux. [OUT] * +* Paramètres : area = portion de binaire incluant l'instruction. * +* addr = adresse virtuelle et/ou position physique. * +* size = taille de chacun des éléments à représenter. * +* content = flux de données à analyser. * +* count = nombre de ces éléments. * +* endian = ordre des bits dans la source. * * * -* Description : Crée une instruction de type 'db/dw/etc' pour un sleb128. * +* Description : Crée une instruction de type 'db/dw/etc' étendue. * * * * Retour : Instruction mise en place. * * * @@ -338,256 +282,174 @@ GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa * * ******************************************************************************/ -GArchInstruction *g_raw_instruction_new_sleb128(const GBinContent *content, vmpa2t *addr) +GArchInstruction *g_raw_instruction_new_array(GBinaryPortion *area, vmpa2t *addr, MemoryDataSize size, const GBinContent *content, size_t count, SourceEndian endian) { GArchInstruction *result; /* Instruction à retourner */ - vmpa2t start; /* Départ original de lecture */ - uleb128_t value; /* Valeur uleb128 à représenter*/ - phys_t diff; /* Couverture de la lecture */ - MemoryDataSize leb_size; /* Taille de la valeur */ - GArchOperand *operand; /* Octet non décodé à afficher */ - mrange_t range; /* Couverture de l'instruction */ - - result = NULL; - - copy_vmpa(&start, addr); - - if (!g_binary_content_read_uleb128(content, addr, &value)) - goto error; - - diff = compute_vmpa_diff(&start, addr); - - leb_size = MDS_FROM_BYTES(diff) | MDS_SIGN; - assert(leb_size != MDS_SIGN); result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL); - init_mrange(&range, &start, diff); - g_arch_instruction_set_range(result, &range); - - operand = g_imm_operand_new_from_value(leb_size, (uint64_t)value); - if (operand == NULL) goto error; - - g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING); - - g_arch_instruction_attach_extra_operand(result, operand); + if (!g_raw_instruction_create_array(G_RAW_INSTRUCTION(result), area, addr, size, content, count, endian)) + g_clear_object(&result); return result; - error: - - g_clear_object(&result); - - return NULL; - } /****************************************************************************** * * -* Paramètres : content = flux de données à analyser. * +* Paramètres : instr = instance à initialiser pleinement. * +* area = portion de binaire incluant l'instruction. * +* addr = adresse virtuelle et/ou position physique. * * size = taille de chacun des éléments à représenter. * +* content = flux de données à analyser. * * count = nombre de ces éléments. * -* addr = position courante dans ce flux. [OUT] * * endian = ordre des bits dans la source. * * * -* Description : Crée une instruction de type 'db/dw/etc' étendue. * +* Description : Met en place une instruction de type 'db/dw/etc' étendue. * * * -* Retour : Instruction mise en place. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -GArchInstruction *g_raw_instruction_new_array(const GBinContent *content, MemoryDataSize size, size_t count, vmpa2t *addr, SourceEndian endian) +bool g_raw_instruction_create_array(GRawInstruction *instr, GBinaryPortion *area, vmpa2t *addr, MemoryDataSize size, const GBinContent *content, size_t count, SourceEndian endian) { - GArchInstruction *result; /* Instruction à retourner */ - vmpa2t old; /* Sauvegarde de la position */ + bool result; /* Bilan à retourner */ + vmpa2t start; /* Sauvegarde de la position */ size_t i; /* Boucle de parcours */ GArchOperand *operand; /* Octet non décodé à afficher */ - mrange_t range; /* Couverture de l'instruction */ + phys_t diff; /* Décalage à appliquer */ + + result = false; /* Par soucis de cohérence */ - if (count == 0) return NULL; + if (count == 0) + goto exit; - result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL); + copy_vmpa(&start, addr); - copy_vmpa(&old, addr); + g_thick_object_lock(G_THICK_OBJECT(instr)); for (i = 0; i < count; i++) { - operand = g_imm_operand_new_from_data(size, content, addr, endian); - if (operand == NULL) goto error; + operand = g_immediate_operand_new_from_data(size, content, addr, (bool []){ false /* unused */ }, endian); + if (operand == NULL) break; g_arch_operand_set_flag(operand, IOF_ZERO_PADDING_BY_DEFAULT | IOF_ZERO_PADDING); - g_arch_instruction_attach_extra_operand(result, operand); + g_arch_instruction_attach_operand(G_ARCH_INSTRUCTION(instr), operand); + unref_object(operand); } - init_mrange(&range, &old, compute_vmpa_diff(addr, &old)); + g_thick_object_unlock(G_THICK_OBJECT(instr)); - g_arch_instruction_set_range(result, &range); + if (i < count) + goto exit; - return result; + diff = compute_vmpa_diff(addr, &start); + + g_arch_instruction_compute_range(G_ARCH_INSTRUCTION(instr), area, &start, diff); - error: + result = true; - g_object_unref(G_OBJECT(result)); + exit: - return NULL; + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction quelconque à consulter. * +* Paramètres : instr = instruction à traiter. * +* is_padding = nouveau statut à associer au contenu. * * * -* Description : Indique l'encodage d'une instruction de façon détaillée. * +* Description : Marque l'instruction comme ne contenant que du bourrage. * * * -* Retour : Description humaine de l'encodage utilisé. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static const char *g_raw_instruction_get_encoding(const GRawInstruction *instr) +void g_raw_instruction_mark_as_padding(GRawInstruction *instr, bool is_padding) { - const char *result; /* Description à retourner */ - - if (g_raw_instruction_is_string(instr)) - result = _("String"); + if (is_padding) + g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); else - result = _("Raw"); - - return result; + g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); } /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * +* Paramètres : instr = instruction à traiter. * +* is_padding = nouveau statut à associer au contenu. * * * -* Description : Fournit le nom humain de l'instruction manipulée. * +* Description : Indique si le contenu de l'instruction est du bourrage. * * * -* Retour : Mot clef de bas niveau. * +* Retour : Statut du contenu de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -static const char *g_raw_instruction_get_keyword(const GRawInstruction *instr) +bool g_raw_instruction_is_padding(const GRawInstruction *instr) { - GArchOperand *operand; /* Octet décodé à afficher */ - MemoryDataSize size; /* Taille de valeur associée */ - - static char *defines[] = { "dn", "db", "dw", "dd", "dq" }; - - operand = g_arch_instruction_get_operand(G_ARCH_INSTRUCTION(instr), 0); - - if (G_IS_TARGET_OPERAND(operand)) - size = g_target_operand_get_size(G_TARGET_OPERAND(operand)); - else - size = g_imm_operand_get_size(G_IMM_OPERAND(operand)); + bool result; /* Indication à retourner */ - g_object_unref(G_OBJECT(operand)); + result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); - return defines[MDS_RANGE(size)]; + return result; } - -/* ---------------------------------------------------------------------------------- */ -/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * -* pbuf = zone tampon à remplir. * +* Paramètres : instr = instruction à traiter. * +* is_string = nouveau statut à associer au contenu. * * * -* Description : Charge une instruction depuis une mémoire tampon. * +* Description : Marque l'instruction comme contenant une chaîne de texte. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool g_raw_instruction_unserialize(GRawInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) +void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - uint8_t boolean; /* Valeur booléenne */ - - parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class); - - result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf); - - if (result) - { - result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - - if (result) - g_raw_instruction_mark_as_padding(instr, (boolean == 1)); - - } - - if (result) - { - result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - - if (result) - g_raw_instruction_mark_as_string(instr, (boolean == 1)); - - } - - return result; + if (is_string) + g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); + else + g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); } /****************************************************************************** * * -* Paramètres : instr = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* pbuf = zone tampon à remplir. * +* Paramètres : instr = instruction à traiter. * +* is_string = nouveau statut à associer au contenu. * * * -* Description : Sauvegarde une instruction dans une mémoire tampon. * +* Description : Indique si le contenu de l'instruction est un texte. * * * -* Retour : Bilan de l'opération. * +* Retour : Statut du contenu de l'instruction. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf) +bool g_raw_instruction_is_string(const GRawInstruction *instr) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - uint8_t boolean; /* Valeur booléenne */ - - parent = G_ARCH_INSTRUCTION_CLASS(g_raw_instruction_parent_class); - - result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf); - - if (result) - { - boolean = (g_raw_instruction_is_padding(instr) ? 1 : 0); - result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - } + bool result; /* Indication à retourner */ - if (result) - { - boolean = (g_raw_instruction_is_string(instr) ? 1 : 0); - result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - } + result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); return result; @@ -596,285 +458,73 @@ static bool g_raw_instruction_serialize(GRawInstruction *instr, GAsmStorage *sto /* ---------------------------------------------------------------------------------- */ -/* OFFRE DE CAPACITES DE GENERATION */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* 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 : instr = instruction quelconque à consulter. * * * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * +* Description : Indique l'encodage d'une instruction de façon détaillée. * * * -* Retour : - * +* Retour : Description humaine de l'encodage utilisé. * * * * Remarques : - * * * ******************************************************************************/ -static void g_raw_instruction_print(GRawInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) +static char *g_raw_instruction_get_encoding(const GArchInstruction *instr) { - GArchInstruction *base; /* Autre version de l'instance */ - phys_t max_displayed_len; /* Quantité de code affichée */ - const char *key; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ - char *string; /* Chaîne reconstituée */ - size_t iter; /* Tête d'écriture */ - bool first; /* Mémorise une énumération */ - size_t count; /* Nombre d'opérandes en place */ - size_t i; /* Boucle de parcours */ - GArchOperand *op; /* Opérande à manipuler */ - GImmOperand *imm; /* Version opérande de valeur */ - char byte; /* Octet à afficher (ou pas) */ -#ifndef NDEBUG - bool status; /* Bilan d'une récupération */ -#endif - - base = G_ARCH_INSTRUCTION(instr); - - /* Localisation */ - - g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range)); - - g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range)); - - /* Contenu */ - - if (g_raw_instruction_is_padding(instr)) - max_displayed_len = 0; - - else if (g_raw_instruction_is_string(instr)) - max_displayed_len = 1; - - else - { - max_displayed_len = get_mrange_length(&base->range); - max_displayed_len /= g_arch_instruction_count_operands(base); - } - - g_buffer_line_fill_content(line, DLC_BINARY, content, &base->range, max_displayed_len); - - /* Zone du code d'assemblage */ + char *result; /* Description à retourner */ + GRawInstruction *raw; /* Version spécialisée */ - key = g_arch_instruction_get_keyword(base); - klen = strlen(key); - - g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL); - - if (g_raw_instruction_is_padding(instr)) - g_buffer_line_append_text(line, DLC_ASSEMBLY, "...", 3, RTT_RAW, NULL); + raw = G_RAW_INSTRUCTION(instr); + if (g_raw_instruction_is_string(raw)) + result = strdup(_("String")); else - { - string = NULL; - iter = 0; - - first = true; - - g_arch_instruction_lock_operands(base); - - count = _g_arch_instruction_count_operands(base); - - for (i = 0; i < count; i++) - { - op = _g_arch_instruction_get_operand(base, i); - - if (!G_IS_IMM_OPERAND(op)) - goto grip_fallback; - - imm = G_IMM_OPERAND(op); - - if (g_imm_operand_get_size(imm) != MDS_8_BITS) - goto grip_fallback; - - if (!g_raw_instruction_is_string(instr) && g_imm_operand_get_display(imm) != IOD_CHAR) - goto grip_fallback; - -#ifndef NDEBUG - status = g_imm_operand_get_value(imm, MDS_8_BITS, &byte); - assert(status); -#else - g_imm_operand_get_value(imm, MDS_8_BITS, &byte); -#endif - - /* Si le caractère doit apparaître en hexadécimal... */ - - if (!isprint(byte)) - goto grip_fallback; - - /* Impression de l'octet */ - - if (string == NULL) - { - string = (char *)calloc(count + 3, sizeof(char)); - - strcpy(string, "\""); - iter = 1; - - } - - string[iter++] = byte; - - g_object_unref(G_OBJECT(op)); - - continue; - - grip_fallback: - - /* Si une chaîne précède */ - - if (string != NULL && iter > 1) - { - if (!first) - { - g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); - } - else - first = false; - - string[iter++] = '"'; - - g_buffer_line_append_text(line, DLC_ASSEMBLY, string, iter, RTT_STRING, NULL); - - iter = 1; - - } - - /* Intégration en tant qu'opérande classique */ - - if (!first) - { - g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); - } - else - first = false; - - g_arch_operand_print(op, line); - - g_object_unref(G_OBJECT(op)); - - } - - /* Si au final une chaîne traine encore */ - - if (string != NULL && iter > 1) - { - if (!first) - { - g_buffer_line_append_text(line, DLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL); - g_buffer_line_append_text(line, DLC_ASSEMBLY, " ", 1, RTT_RAW, NULL); - } - - string[iter++] = '"'; - - g_buffer_line_append_text(line, DLC_ASSEMBLY, string, iter, RTT_STRING, NULL); - - } + result = strdup(_("Raw")); - g_arch_instruction_unlock_operands(base); - - if (string != NULL) - free(string); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : instr = instruction à traiter. * -* is_padding = nouveau statut à associer au contenu. * -* * -* Description : Marque l'instruction comme ne contenant que du bourrage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_raw_instruction_mark_as_padding(GRawInstruction *instr, bool is_padding) -{ - if (is_padding) - g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); - else - g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); + return result; } /****************************************************************************** * * -* Paramètres : instr = instruction à traiter. * -* is_padding = nouveau statut à associer au contenu. * +* Paramètres : instr = instruction d'assemblage à consulter. * * * -* Description : Indique si le contenu de l'instruction est du bourrage. * +* Description : Fournit le nom humain de l'instruction manipulée. * * * -* Retour : Statut du contenu de l'instruction. * +* Retour : Mot clef de bas niveau. * * * * Remarques : - * * * ******************************************************************************/ -bool g_raw_instruction_is_padding(const GRawInstruction *instr) +static char *g_raw_instruction_get_keyword(const GArchInstruction *instr) { - bool result; /* Indication à retourner */ - - result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_PADDING); - - return result; - -} + char *result; /* Désignation à retourner */ + GArchOperand *operand; /* Octet décodé à afficher */ + MemoryDataSize size; /* Taille de valeur associée */ + static char *defines[] = { "dn", "db", "dw", "dd", "dq" }; -/****************************************************************************** -* * -* Paramètres : instr = instruction à traiter. * -* is_string = nouveau statut à associer au contenu. * -* * -* Description : Marque l'instruction comme contenant une chaîne de texte. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + g_thick_object_lock(G_THICK_OBJECT(instr)); -void g_raw_instruction_mark_as_string(GRawInstruction *instr, bool is_string) -{ - if (is_string) - g_arch_instruction_set_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); - else - g_arch_instruction_unset_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); - -} + operand = g_arch_instruction_get_operand(instr, 0); + /*if (G_IS_TARGET_OPERAND(operand)) FIXME + size = g_target_operand_get_size(G_TARGET_OPERAND(operand)); + else*/ + size = g_immediate_operand_get_size(G_IMMEDIATE_OPERAND(operand)); -/****************************************************************************** -* * -* Paramètres : instr = instruction à traiter. * -* is_string = nouveau statut à associer au contenu. * -* * -* Description : Indique si le contenu de l'instruction est un texte. * -* * -* Retour : Statut du contenu de l'instruction. * -* * -* Remarques : - * -* * -******************************************************************************/ + unref_object(operand); -bool g_raw_instruction_is_string(const GRawInstruction *instr) -{ - bool result; /* Indication à retourner */ + g_thick_object_unlock(G_THICK_OBJECT(instr)); - result = g_arch_instruction_has_flag(G_ARCH_INSTRUCTION(instr), RIF_STRING); + result = strdup(defines[MDS_RANGE(size)]); return result; diff --git a/src/arch/instructions/raw.h b/src/arch/instructions/raw.h index 4e92cd4..712f877 100644 --- a/src/arch/instructions/raw.h +++ b/src/arch/instructions/raw.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * raw.h - prototypes pour les instructions pures vues de l'esprit + * raw.h - prototypes pour les instructions de données brutes * - * Copyright (C) 2014-2020 Cyrille Bagard + * Copyright (C) 2014-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,46 +25,24 @@ #define _ARCH_INSTRUCTIONS_RAW_H -#include <glib-object.h> - - #include "../instruction.h" #include "../vmpa.h" +#include "../../analysis/content.h" +#include "../../glibext/helpers.h" -/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */ - - -#define G_TYPE_RAW_INSTRUCTION g_raw_instruction_get_type() -#define G_RAW_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_RAW_INSTRUCTION, GRawInstruction)) -#define G_IS_RAW_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_RAW_INSTRUCTION)) -#define G_RAW_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_RAW_INSTRUCTION, GRawInstructionClass)) -#define G_IS_RAW_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_RAW_INSTRUCTION)) -#define G_RAW_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_RAW_INSTRUCTION, GRawInstructionClass)) - +#define G_TYPE_RAW_INSTRUCTION (g_raw_instruction_get_type()) -/* Définition générique d'une instruction brute d'architecture (instance) */ -typedef struct _GRawInstruction GRawInstruction; +DECLARE_GTYPE(GRawInstruction, g_raw_instruction, G, RAW_INSTRUCTION); -/* Définition générique d'une instruction brute d'architecture (classe) */ -typedef struct _GRawInstructionClass GRawInstructionClass; - - -/* Indique le type défini pour une instruction inconnue d'architecture. */ -GType g_raw_instruction_get_type(void); /* Crée une instruction de type 'db/dw/etc' simple. */ -GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *, MemoryDataSize, uint64_t); +GArchInstruction *g_raw_instruction_new_from_value(GBinaryPortion *, const vmpa2t *, MemoryDataSize, uint64_t); -/* Crée une instruction de type 'db/dw/etc' pour un uleb128. */ -GArchInstruction *g_raw_instruction_new_uleb128(const GBinContent *content, vmpa2t *); +/* Crée une instruction de type 'db/dw/etc' étendue. */ +GArchInstruction *g_raw_instruction_new_array(GBinaryPortion *, vmpa2t *, MemoryDataSize, const GBinContent *, size_t, SourceEndian); -/* Crée une instruction de type 'db/dw/etc' pour un sleb128. */ -GArchInstruction *g_raw_instruction_new_sleb128(const GBinContent *content, vmpa2t *); - -/* Crée une instruction de type 'db/dw/etc' étendue. */ -GArchInstruction *g_raw_instruction_new_array(const GBinContent *, MemoryDataSize, size_t, vmpa2t *, SourceEndian); /* Drapeaux pour informations complémentaires */ typedef enum _RawInstrFlag @@ -74,6 +52,7 @@ typedef enum _RawInstrFlag } RawInstrFlag; + /* Marque l'instruction comme ne contenant que du bourrage. */ void g_raw_instruction_mark_as_padding(GRawInstruction *, bool); diff --git a/src/arch/instructions/undefined-int.h b/src/arch/instructions/undefined-int.h index a9b7627..faf0b4b 100644 --- a/src/arch/instructions/undefined-int.h +++ b/src/arch/instructions/undefined-int.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * undefined-int.h - prototypes pour la définition générique interne des instructions au comportement non défini + * undefined-int.h - prototypes pour la définition interne des instructions au comportement non défini * - * Copyright (C) 2019 Cyrille Bagard + * Copyright (C) 2019-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -27,42 +27,18 @@ #include "undefined.h" #include "../instruction-int.h" -#include "../../glibext/objhole.h" -/* Informations glissées dans la structure GObject de GArchInstruction */ -typedef struct _undef_extra_data_t -{ - /** - * Le champ uid de la structure parente attendue conduit à une taille - * alignée sur 2 octets, donc à une taille totale de 4 octets ce qui - * représente la limite maximale de taille supportée. - * - * Pour 3 octets à la base, qui devraient laisser 8 - 1 octets disponbibles - * en incluant le bit de verrouillage. - * - * On reproduit donc la structure instr_extra_data_t ici, en basculant - * l'énumération InstrExpectedBehavior en champ de bits. - */ - - itid_t uid; /* Identifiant unique du type */ - ArchInstrFlag flags; /* Informations complémentaires*/ - - unsigned int behavior : 2; /* Conséquences réelles */ - -} undef_extra_data_t; - - /* Définition générique d'une instruction au comportement non défini (instance) */ -struct _GUndefInstruction +struct _GUndefinedInstruction { GArchInstruction parent; /* A laisser en premier */ }; /* Définition générique d'une instruction au comportement non défini (classe) */ -struct _GUndefInstructionClass +struct _GUndefinedInstructionClass { GArchInstructionClass parent; /* A laisser en premier */ @@ -73,15 +49,25 @@ struct _GUndefInstructionClass * Accès aux informations éventuellement déportées. */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ +/* Informations glissées dans la structure GObject de GArchInstruction */ +typedef struct _undef_extra_data_t +{ + ARCH_INSTRUCTION_EXTRA_DATA + + unsigned int behavior : 2; /* Conséquences réelles */ + +} undef_extra_data_t; + -# define GET_UNDEF_INSTR_EXTRA(ins) ((undef_extra_data_t *)&((GArchInstruction *)ins)->extra) +#define GET_UNDEF_INSTR_EXTRA(op) \ + GET_GOBJECT_EXTRA(op, undef_extra_data_t) -#else +#define SET_UNDEF_INSTR_EXTRA(op, data) \ + SET_GOBJECT_EXTRA(op, undef_extra_data_t, data) -# define GET_UNDEF_INSTR_EXTRA(ins) GET_GOBJECT_EXTRA(G_OBJECT(ins), undef_extra_data_t) -#endif +/* Met en place une instruction au comportement indéfini. */ +bool g_undefined_instruction_create(GUndefinedInstruction *, InstrExpectedBehavior); diff --git a/src/arch/instructions/undefined-ui.c b/src/arch/instructions/undefined-ui.c new file mode 100644 index 0000000..fbc0452 --- /dev/null +++ b/src/arch/instructions/undefined-ui.c @@ -0,0 +1,102 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * undefined-ui.c - opérandes représentant des instructions indéfinies sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "undefined-ui.h" + + +#include "../instruction.h" +#include "../../glibext/options/asm.h" + + + +/* Etablit dans une ligne de rendu le contenu représenté. */ +static void g_undefined_instruction_ui_populate_line(const GTokenGenerator *, size_t, size_t, GBufferLine *, void *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de génération. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_undefined_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *iface) +{ + iface->populate = g_undefined_instruction_ui_populate_line; + +} + + +/****************************************************************************** +* * +* Paramètres : generator = générateur à utiliser pour l'impression. * +* index = indice de cette même ligne dans le tampon global.* +* repeat = indice d'utilisations successives du générateur. * +* line = ligne de rendu à compléter. * +* data = éventuelle donnée complémentaire fournie. * +* * +* Description : Etablit dans une ligne de rendu le contenu représenté. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_undefined_instruction_ui_populate_line(const GTokenGenerator *generator, size_t index, size_t repeat, GBufferLine *line, void *data) +{ + GArchInstruction *instr; /* Version spécialisée */ + GBinContent *content; /* Contenu brut d'origine */ + mrange_t range; /* Emplacement couvert */ + char *key; /* Mot clef principal */ + + instr = G_ARCH_INSTRUCTION(generator); + content = G_BIN_CONTENT(data); + + /* Prologue */ + + if (g_arch_instruction_get_range(instr, &range)) + { + g_buffer_line_fill_physical(line, ACO_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_virtual(line, ACO_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&range)); + + g_buffer_line_fill_content(line, ACO_BINARY, content, &range, VMPA_NO_PHYSICAL); + + } + + /* Instruction proprement dite */ + + key = g_arch_instruction_get_keyword(instr); + + g_buffer_line_append_text(line, ACO_ASSEMBLY_HEAD, TRT_ERROR, SL(key), NULL, G_OBJECT(instr)); + + free(key); + +} diff --git a/src/arch/instructions/undefined-ui.h b/src/arch/instructions/undefined-ui.h new file mode 100644 index 0000000..8bc2d67 --- /dev/null +++ b/src/arch/instructions/undefined-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * undefined-ui.h - prototypes pour les opérandes représentant des instructions indéfinies sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERANDS_UNDEFINED_UI_H +#define _ARCH_OPERANDS_UNDEFINED_UI_H + + +#include "../../glibext/generator-int.h" + + + +/* Procède à l'initialisation de l'interface de génération. */ +void g_undefined_instruction_ui_token_generator_iface_init(GTokenGeneratorInterface *); + + + +#endif /* _ARCH_OPERANDS_UNDEFINED_UI_H */ diff --git a/src/arch/instructions/undefined.c b/src/arch/instructions/undefined.c index 15c63e7..75df493 100644 --- a/src/arch/instructions/undefined.c +++ b/src/arch/instructions/undefined.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * undefined.c - instructions au comportement non défini * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,63 +25,42 @@ #include <assert.h> +#include <string.h> #include <i18n.h> #include "undefined-int.h" -#include "../../core/columns.h" +#include "../../glibext/serialize-int.h" +/* ------------------------- INSTRUCTION INCONNUE / DONNEES ------------------------- */ + + /* Initialise la classe des instructions non définies. */ -static void g_undef_instruction_class_init(GUndefInstructionClass *); +static void g_undefined_instruction_class_init(GUndefinedInstructionClass *); /* Initialise une instance d'instruction non définie. */ -static void g_undef_instruction_init(GUndefInstruction *); +static void g_undefined_instruction_init(GUndefinedInstruction *); /* Supprime toutes les références externes. */ -static void g_undef_instruction_dispose(GUndefInstruction *); +static void g_undefined_instruction_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_undef_instruction_finalize(GUndefInstruction *); - -/* Indique l'encodage d'une instruction de façon détaillée. */ -static const char *g_undef_instruction_get_encoding(const GUndefInstruction *); - -/* Fournit le nom humain de l'instruction manipulée. */ -static const char *g_undef_instruction_get_keyword(const GUndefInstruction *); - - - -/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ - - -/* Charge une instruction depuis une mémoire tampon. */ -static bool g_undef_instruction_unserialize(GUndefInstruction *, GAsmStorage *, GBinFormat *, packed_buffer_t *); - -/* Sauvegarde une instruction dans une mémoire tampon. */ -static bool g_undef_instruction_serialize(GUndefInstruction *, GAsmStorage *, packed_buffer_t *); - - - -/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ - - -/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */ -static void g_undef_instruction_print(GUndefInstruction *, GBufferLine *, size_t, size_t, const GBinContent *); +static void g_undefined_instruction_finalize(GObject *); /* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_undef_instruction_load(GUndefInstruction *, GObjectStorage *, packed_buffer_t *); +/* Indique l'encodage d'une instruction de façon détaillée. */ +static char *g_undefined_instruction_get_encoding(const GArchInstruction *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, packed_buffer_t *); +/* Fournit le nom humain de l'instruction manipulée. */ +static char *g_undefined_instruction_get_keyword(const GArchInstruction *); @@ -91,7 +70,9 @@ static bool g_undef_instruction_store(GUndefInstruction *, GObjectStorage *, pac /* Indique le type défini pour une instruction au comportement non défini. */ -G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION); +G_DEFINE_TYPE_WITH_CODE(GUndefinedInstruction, g_undefined_instruction, G_TYPE_ARCH_INSTRUCTION, + G_IMPLEMENT_INTERFACE_IF_SYM(g_token_generator_get_type, g_undefined_instruction_ui_token_generator_iface_init)); + /****************************************************************************** @@ -106,28 +87,20 @@ G_DEFINE_TYPE(GUndefInstruction, g_undef_instruction, G_TYPE_ARCH_INSTRUCTION); * * ******************************************************************************/ -static void g_undef_instruction_class_init(GUndefInstructionClass *klass) +static void g_undefined_instruction_class_init(GUndefinedInstructionClass *klass) { GObjectClass *object; /* Autre version de la classe */ GArchInstructionClass *instr; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_undef_instruction_dispose; - object->finalize = (GObjectFinalizeFunc)g_undef_instruction_finalize; + object->dispose = g_undefined_instruction_dispose; + object->finalize = g_undefined_instruction_finalize; instr = G_ARCH_INSTRUCTION_CLASS(klass); - instr->get_encoding = (get_instruction_encoding_fc)g_undef_instruction_get_encoding; - instr->get_keyword = (get_instruction_keyword_fc)g_undef_instruction_get_keyword; - - instr->unserialize = (unserialize_instruction_fc)g_undef_instruction_unserialize; - instr->serialize = (serialize_instruction_fc)g_undef_instruction_serialize; - - instr->print = (print_instruction_fc)g_undef_instruction_print; - - instr->load = (load_instruction_fc)g_undef_instruction_load; - instr->store = (store_instruction_fc)g_undef_instruction_store; + instr->get_encoding = g_undefined_instruction_get_encoding; + instr->get_keyword = g_undefined_instruction_get_keyword; } @@ -144,16 +117,22 @@ static void g_undef_instruction_class_init(GUndefInstructionClass *klass) * * ******************************************************************************/ -static void g_undef_instruction_init(GUndefInstruction *instr) +static void g_undefined_instruction_init(GUndefinedInstruction *instr) { - GET_UNDEF_INSTR_EXTRA(instr)->behavior = IEB_UNDEFINED; + undef_extra_data_t extra; /* Données insérées à consulter*/ + + extra = GET_UNDEF_INSTR_EXTRA(instr); + + extra.behavior = IEB_UNDEFINED; + + SET_UNDEF_INSTR_EXTRA(instr, &extra); } /****************************************************************************** * * -* Paramètres : instr = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -163,16 +142,16 @@ static void g_undef_instruction_init(GUndefInstruction *instr) * * ******************************************************************************/ -static void g_undef_instruction_dispose(GUndefInstruction *instr) +static void g_undefined_instruction_dispose(GObject *object) { - G_OBJECT_CLASS(g_undef_instruction_parent_class)->dispose(G_OBJECT(instr)); + G_OBJECT_CLASS(g_undefined_instruction_parent_class)->dispose(object); } /****************************************************************************** * * -* 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. * * * @@ -182,9 +161,9 @@ static void g_undef_instruction_dispose(GUndefInstruction *instr) * * ******************************************************************************/ -static void g_undef_instruction_finalize(GUndefInstruction *instr) +static void g_undefined_instruction_finalize(GObject *object) { - G_OBJECT_CLASS(g_undef_instruction_parent_class)->finalize(G_OBJECT(instr)); + G_OBJECT_CLASS(g_undefined_instruction_parent_class)->finalize(object); } @@ -201,16 +180,14 @@ static void g_undef_instruction_finalize(GUndefInstruction *instr) * * ******************************************************************************/ -GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior behavior) +GArchInstruction *g_undefined_instruction_new(InstrExpectedBehavior behavior) { GArchInstruction *result; /* Instruction à retourner */ - undef_extra_data_t *extra; /* Données insérées à modifier */ - result = g_object_new(G_TYPE_UNDEF_INSTRUCTION, NULL); + result = g_object_new(G_TYPE_UNDEFINED_INSTRUCTION, NULL); - extra = GET_UNDEF_INSTR_EXTRA(result); - - extra->behavior = behavior; + if (!g_undefined_instruction_create(G_UNDEFINED_INSTRUCTION(result), behavior)) + g_clear_object(&result); return result; @@ -219,90 +196,10 @@ GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior behavior) /****************************************************************************** * * -* 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 : - * -* * -******************************************************************************/ - -static const char *g_undef_instruction_get_encoding(const GUndefInstruction *instr) -{ - const char *result; /* Description à retourner */ - - result = _("Undefined"); - - return result; - -} - - -/****************************************************************************** +* Paramètres : instr = instance à initialiser pleinement. * +* behavior = état réel du CPU après une passe de l'instruction.* * * -* Paramètres : instr = instruction d'assemblage à consulter. * -* * -* Description : Fournit le nom humain de l'instruction manipulée. * -* * -* Retour : Mot clef de bas niveau. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr) -{ - const char *result; /* Désignation à retourner */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_UNDEF_INSTR_EXTRA(instr); - - switch (extra->behavior) - { - case IEB_NOP: - result = "nop"; - break; - - case IEB_UNDEFINED: - result = "undefined"; - break; - - case IEB_UNPREDICTABLE: - result = "unpredictable"; - break; - - case IEB_RESERVED: - result = "reserved"; - break; - - default: - assert(false); - result = NULL; - break; - - } - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* format = format binaire chargé associé à l'architecture. * -* pbuf = zone tampon à remplir. * -* * -* Description : Charge une instruction depuis une mémoire tampon. * +* Description : Met en place une instruction au comportement indéfini. * * * * Retour : Bilan de l'opération. * * * @@ -310,122 +207,24 @@ const char *g_undef_instruction_get_keyword(const GUndefInstruction *instr) * * ******************************************************************************/ -static bool g_undef_instruction_unserialize(GUndefInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) +bool g_undefined_instruction_create(GUndefinedInstruction *instr, InstrExpectedBehavior behavior) { bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - uint8_t val; /* Champ de bits manipulé */ - - parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); + undef_extra_data_t extra; /* Données insérées à modifier */ - result = parent->unserialize(G_ARCH_INSTRUCTION(instr), storage, format, pbuf); + result = true; - if (result) - { - extra = GET_UNDEF_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); - - result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); - extra->behavior = val; - - UNLOCK_GOBJECT_EXTRA(extra); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : instr = instruction d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde une instruction dans une mémoire tampon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_undef_instruction_serialize(GUndefInstruction *instr, GAsmStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - - parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); - - result = parent->serialize(G_ARCH_INSTRUCTION(instr), storage, pbuf); - - if (result) - { - extra = GET_UNDEF_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); - - result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false); + extra = GET_UNDEF_INSTR_EXTRA(instr); - UNLOCK_GOBJECT_EXTRA(extra); + extra.behavior = behavior; - } + SET_UNDEF_INSTR_EXTRA(instr, &extra); return result; } - -/* ---------------------------------------------------------------------------------- */ -/* OFFRE DE CAPACITES DE GENERATION */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* 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. * -* * -* Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *line, size_t index, size_t repeat, const GBinContent *content) -{ - GArchInstruction *base; /* Version de base */ - const char *key; /* Mot clef principal */ - size_t klen; /* Taille de ce mot clef */ - - base = G_ARCH_INSTRUCTION(instr); - - g_buffer_line_fill_phys(line, DLC_PHYSICAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range)); - - g_buffer_line_fill_virt(line, DLC_VIRTUAL, MDS_32_BITS_UNSIGNED, get_mrange_addr(&base->range)); - - g_buffer_line_fill_content(line, DLC_BINARY, content, &base->range, VMPA_NO_PHYSICAL); - - /* Instruction proprement dite */ - - key = g_arch_instruction_get_keyword(base); - klen = strlen(key); - - g_buffer_line_append_text(line, DLC_ASSEMBLY_HEAD, key, klen, RTT_ERROR, NULL); - -} - - /****************************************************************************** * * * Paramètres : instr = instruction à consulter. * @@ -438,18 +237,14 @@ static void g_undef_instruction_print(GUndefInstruction *instr, GBufferLine *lin * * ******************************************************************************/ -InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *instr) +InstrExpectedBehavior g_undefined_instruction_get_behavior(const GUndefinedInstruction *instr) { InstrExpectedBehavior result; /* Comportement à retourner */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ + undef_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_UNDEF_INSTR_EXTRA(instr); - LOCK_GOBJECT_EXTRA(extra); - - result = extra->behavior; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.behavior; return result; @@ -464,41 +259,21 @@ InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction * /****************************************************************************** * * -* Paramètres : instr = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : instr = instruction quelconque à consulter. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Indique l'encodage d'une instruction de façon détaillée. * * * -* Retour : Bilan de l'opération. * +* Retour : Description humaine de l'encodage utilisé. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +static char *g_undefined_instruction_get_encoding(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - uint8_t val; /* Champ de bits manipulé */ - - parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); - - result = parent->load(G_ARCH_INSTRUCTION(instr), storage, pbuf); - - if (result) - { - extra = GET_UNDEF_INSTR_EXTRA(instr); - - LOCK_GOBJECT_EXTRA(extra); + char *result; /* Description à retourner */ - result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); - extra->behavior = val; - - UNLOCK_GOBJECT_EXTRA(extra); - - } + result = strdup(_("Undefined")); return result; @@ -507,37 +282,45 @@ static bool g_undef_instruction_load(GUndefInstruction *instr, GObjectStorage *s /****************************************************************************** * * -* Paramètres : instr = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : instr = instruction d'assemblage à consulter. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Fournit le nom humain de l'instruction manipulée. * * * -* Retour : Bilan de l'opération. * +* Retour : Mot clef de bas niveau. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_undef_instruction_store(GUndefInstruction *instr, GObjectStorage *storage, packed_buffer_t *pbuf) +static char *g_undefined_instruction_get_keyword(const GArchInstruction *instr) { - bool result; /* Bilan à retourner */ - GArchInstructionClass *parent; /* Classe parente à consulter */ - undef_extra_data_t *extra; /* Données insérées à consulter*/ - - parent = G_ARCH_INSTRUCTION_CLASS(g_undef_instruction_parent_class); + char *result; /* Désignation à retourner */ + undef_extra_data_t extra; /* Données insérées à consulter*/ - result = parent->store(G_ARCH_INSTRUCTION(instr), storage, pbuf); + extra = GET_UNDEF_INSTR_EXTRA(instr); - if (result) + switch (extra.behavior) { - extra = GET_UNDEF_INSTR_EXTRA(instr); + case IEB_NOP: + result = strdup("nop"); + break; - LOCK_GOBJECT_EXTRA(extra); + case IEB_UNDEFINED: + result = strdup("undefined"); + break; - result = extend_packed_buffer(pbuf, (uint8_t []){ extra->behavior }, sizeof(uint8_t), false); + case IEB_UNPREDICTABLE: + result = strdup("unpredictable"); + break; - UNLOCK_GOBJECT_EXTRA(extra); + case IEB_RESERVED: + result = strdup("reserved"); + break; + + default: + assert(false); + result = NULL; + break; } diff --git a/src/arch/instructions/undefined.h b/src/arch/instructions/undefined.h index 8f35f35..d4b35f4 100644 --- a/src/arch/instructions/undefined.h +++ b/src/arch/instructions/undefined.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * undefined.h - prototypes pour les instructions au comportement non défini * - * Copyright (C) 2016-2019 Cyrille Bagard + * Copyright (C) 2016-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,27 +25,14 @@ #define _ARCH_INSTRUCTIONS_UNDEFINED_H -#include <glib-object.h> - - #include "../instruction.h" -#include "../vmpa.h" - +#include "../../glibext/helpers.h" -#define G_TYPE_UNDEF_INSTRUCTION g_undef_instruction_get_type() -#define G_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstruction)) -#define G_IS_UNDEF_INSTRUCTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_UNDEF_INSTRUCTION)) -#define G_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) -#define G_IS_UNDEF_INSTRUCTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_UNDEF_INSTRUCTION)) -#define G_UNDEF_INSTRUCTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_UNDEF_INSTRUCTION, GUndefInstructionClass)) +#define G_TYPE_UNDEFINED_INSTRUCTION (g_undefined_instruction_get_type()) -/* Définition générique d'une instruction au comportement non défini (instance) */ -typedef struct _GUndefInstruction GUndefInstruction; - -/* Définition générique d'une instruction au comportement non défini (classe) */ -typedef struct _GUndefInstructionClass GUndefInstructionClass; +DECLARE_GTYPE(GUndefinedInstruction, g_undefined_instruction, G, UNDEFINED_INSTRUCTION); /* Etat précis de l'instruction */ @@ -59,14 +46,11 @@ typedef enum _InstrExpectedBehavior } InstrExpectedBehavior; -/* Indique le type défini pour une instruction au comportement non défini. */ -GType g_undef_instruction_get_type(void); - /* Crée une instruction au comportement nominalement indéfini. */ -GArchInstruction *g_undef_instruction_new(InstrExpectedBehavior); +GArchInstruction *g_undefined_instruction_new(InstrExpectedBehavior); /* Indique le type de conséquences réél de l'instruction. */ -InstrExpectedBehavior g_undef_instruction_get_behavior(const GUndefInstruction *); +InstrExpectedBehavior g_undefined_instruction_get_behavior(const GUndefinedInstruction *); diff --git a/src/arch/operand-int.h b/src/arch/operand-int.h index e6c1232..10c079b 100644 --- a/src/arch/operand-int.h +++ b/src/arch/operand-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * operand-int.h - prototypes pour la définition générique interne des opérandes * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -26,13 +26,23 @@ #include "operand.h" +#include "../common/szbin.h" +#include "../glibext/objhole-int.h" + + + +/* Exporte une chaîne de caractères à partir d'un objet. */ +//typedef bool (* arch_operand_to_string_fc) (const GArchOperand *operand, unsigned int flags, sized_binary_t *); + + + +#if 0 #include <stdbool.h> #include "../analysis/storage/storage.h" -#include "../glibext/objhole.h" @@ -71,46 +81,29 @@ typedef bool (* load_operand_fc) (GArchOperand *, GObjectStorage *, packed_buffe typedef bool (* store_operand_fc) (GArchOperand *, GObjectStorage *, packed_buffer_t *); -/* Informations glissées dans la structure GObject de GArchOperand */ -typedef struct _operand_extra_data_t -{ - ArchOperandFlag flags; /* Informations diverses */ -} operand_extra_data_t; -/* Encapsulation avec un verrou d'accès */ -typedef union _operand_obj_extra_t -{ - operand_extra_data_t data; /* Données embarquées */ - lockable_obj_extra_t lockable; /* Gestion d'accès aux fanions */ +#endif -} operand_obj_extra_t; /* Définition générique d'un opérande d'architecture (instance) */ struct _GArchOperand { - GObject parent; /* A laisser en premier */ - -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ - - /** - * L'inclusion des informations suivantes dépend de l'architecture. - * - * Si la structure GObject possède un trou, on remplit de préférence - * ce dernier. - */ - - operand_obj_extra_t extra; /* Externalisation embarquée */ - -#endif + GThickObject parent; /* A laisser en premier */ }; /* Définition générique d'un opérande d'architecture (classe) */ struct _GArchOperandClass { - GObjectClass parent; /* A laisser en premier */ + GThickObjectClass parent; /* A laisser en premier */ + + + + + +#if 0 operand_compare_fc compare; /* Comparaison d'opérandes */ find_inner_operand_fc find_inner; /* Définition d'un chemin */ @@ -128,29 +121,57 @@ struct _GArchOperandClass load_operand_fc load; /* Chargement depuis un tampon */ store_operand_fc store; /* Conservation dans un tampon */ +#endif + }; + /** * Accès aux informations éventuellement déportées. */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ -# define GET_ARCH_OP_EXTRA(op) (operand_extra_data_t *)&op->extra +#define ARCH_OPERAND_EXTRA_DATA(mx) \ + \ + unsigned int reserved : GOBJECT_RESERVED_EXTRA_BITS; \ + \ + /** \ + * ArchOperandFlag \ + */ \ + unsigned int flags : mx; -#else -# define GET_ARCH_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), operand_extra_data_t) +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _operand_extra_data_t +{ + ARCH_OPERAND_EXTRA_DATA(3); /* Informations pour l'opérande*/ + +} operand_extra_data_t; + + +#define GET_ARCH_OP_EXTRA(op) \ + GET_GOBJECT_EXTRA(op, operand_extra_data_t) + +#define SET_ARCH_OP_EXTRA(op, data) \ + SET_GOBJECT_EXTRA(op, operand_extra_data_t, data) + + + + + + + + +#if 0 -#endif /* Ajoute une information complémentaire à un opérande. */ -bool _g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag, bool); +//bool _g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag, bool); /* Retire une information complémentaire à un opérande. */ -bool _g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag, bool); +//bool _g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag, bool); @@ -190,5 +211,7 @@ bool g_arch_operand_store_generic_fixed(GArchOperand *, GObjectStorage *, packed bool g_arch_operand_store_generic_variadic(GArchOperand *, GObjectStorage *, packed_buffer_t *); +#endif + #endif /* _ARCH_OPERAND_INT_H */ diff --git a/src/arch/operand-ui-int.h b/src/arch/operand-ui-int.h new file mode 100644 index 0000000..c1173f3 --- /dev/null +++ b/src/arch/operand-ui-int.h @@ -0,0 +1,52 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-ui-int.h - prototypes pour la définition générique interne des opérandes sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERAND_UI_INT_H +#define _ARCH_OPERAND_UI_INT_H + + +#include "operand-ui.h" + + + +/* Traduit un opérande en version humainement lisible. */ +typedef void (* print_operand_ui_fc) (const GArchOperandUI *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +typedef char * (* build_operand_ui_tooltip_fc) (const GArchOperandUI *, const GLoadedBinary *); + + + +/* Définition générique d'un opérande d'architecture (interface) */ +struct _GArchOperandUIInterface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + print_operand_ui_fc print; /* Texte humain équivalent */ + build_operand_ui_tooltip_fc build_tooltip; /* Définition de description*/ + +}; + + + +#endif /* _ARCH_OPERAND_UI_INT_H */ diff --git a/src/arch/operand-ui.c b/src/arch/operand-ui.c new file mode 100644 index 0000000..ff7ad1b --- /dev/null +++ b/src/arch/operand-ui.c @@ -0,0 +1,111 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-ui.c - gestion générique des opérandes sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "operand-ui.h" + + +#include "operand-ui-int.h" + + + +/* Procède à l'initialisation de l'interface d'opérande UI. */ +static void g_arch_operand_ui_default_init(GArchOperandUIInterface *); + + + +/* Indique le type défini pour un opérande d'architecture avec représentation graphique. */ +G_DEFINE_INTERFACE(GArchOperandUI, g_arch_operand_ui, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'opérande UI. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_arch_operand_ui_default_init(GArchOperandUIInterface *iface) +{ + iface->print = NULL; + iface->build_tooltip = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line) +{ + GArchOperandUIInterface *iface; /* Interface utilisée */ + + iface = G_ARCH_OPERAND_UI_GET_IFACE(operand); + + iface->print(operand, line); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à consulter. * +* binary = informations relatives au binaire chargé. * +* * +* Description : Construit un petit résumé concis de l'opérande. * +* * +* Retour : Chaîne de caractères à libérer après usage ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *g_arch_operand_ui_build_tooltip(const GArchOperandUI *operand, const GLoadedBinary *binary) +{ + char *result; /* Description à retourner */ + GArchOperandUIInterface *iface; /* Interface utilisée */ + + iface = G_ARCH_OPERAND_UI_GET_IFACE(operand); + + if (iface->build_tooltip != NULL) + result = iface->build_tooltip(operand, binary); + else + result = NULL; + + return result; + +} diff --git a/src/arch/operand-ui.h b/src/arch/operand-ui.h new file mode 100644 index 0000000..b197645 --- /dev/null +++ b/src/arch/operand-ui.h @@ -0,0 +1,54 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * operand-ui.h - prototypes pour la gestion générique des opérandes sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERAND_UI_H +#define _ARCH_OPERAND_UI_H + + +#include "../glibext/bufferline.h" +#include "../glibext/helpers.h" + + + +#define G_TYPE_ARCH_OPERAND_UI (g_arch_operand_ui_get_type()) + +DECLARE_INTERFACE(GArchOperandUI, g_arch_operand_ui, G, ARCH_OPERAND_UI); + + + +// TODO : REMME +//typedef void *GBufferLine; +typedef void *GLoadedBinary; +///// + + + +/* Traduit un opérande en version humainement lisible. */ +void g_arch_operand_ui_print(const GArchOperandUI *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +char *g_arch_operand_ui_build_tooltip(const GArchOperandUI *, const GLoadedBinary *); + + + +#endif /* _ARCH_OPERAND_UI_H */ diff --git a/src/arch/operand.c b/src/arch/operand.c index 0f5ffd5..d3e837c 100644 --- a/src/arch/operand.c +++ b/src/arch/operand.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * operand.c - gestion générique des opérandes * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,17 +25,16 @@ #include <assert.h> -#include <malloc.h> -#include <string.h> #include "operand-int.h" -#include "storage.h" -#include "../analysis/storage/serialize-int.h" #include "../common/fnv1a.h" #include "../common/sort.h" -#include "../core/logs.h" +#include "../glibext/comparable-int.h" +#include "../glibext/hashable-int.h" +#include "../glibext/serialize-int.h" #include "../glibext/singleton-int.h" +#include "../glibext/strbuilder-int.h" @@ -45,66 +44,67 @@ /* Initialise la classe générique des opérandes. */ static void g_arch_operand_class_init(GArchOperandClass *); -/* Initialise une instance d'opérande d'architecture. */ -static void g_arch_operand_init(GArchOperand *); +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_arch_operand_comparable_object_iface_init(GComparableObjectInterface *); -/* Procède à l'initialisation de l'interface de singleton. */ -static void g_arch_operand_singleton_init(GSingletonCandidateInterface *); +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_arch_operand_hashable_object_iface_init(GHashableObjectInterface *); /* Procède à l'initialisation de l'interface de sérialisation. */ -static void g_arch_operand_serializable_init(GSerializableObjectInterface *); +static void g_arch_operand_serializable_object_iface_init(GSerializableObjectInterface *); + +/* Procède à l'initialisation de l'interface de rassemblement. */ +static void g_arch_operand_singleton_candidate_iface_init(GSingletonCandidateInterface *); + +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_arch_operand_string_builder_iface_init(GStringBuilderInterface *); + +/* Initialise une instance d'opérande d'architecture. */ +static void g_arch_operand_init(GArchOperand *); /* Supprime toutes les références externes. */ -static void g_arch_operand_dispose(GArchOperand *); +static void g_arch_operand_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_arch_operand_finalize(GArchOperand *); +static void g_arch_operand_finalize(GObject *); -/* Compare un opérande avec un autre. */ -static int _g_arch_operand_compare(const GArchOperand *, const GArchOperand *, bool); +/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */ -/* ------------------------ CONTROLE DU VOLUME DES INSTANCES ------------------------ */ +/* Réalise une comparaison étendue entre objets. */ +static int g_arch_operand_compare(const GComparableObject *, const GComparableObject *); -/* Fournit une liste de candidats embarqués par un candidat. */ -GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *, size_t *); -/* Met à jour une liste de candidats embarqués par un candidat. */ -void g_arch_operand_update_inner_instances(GArchOperand *, GArchOperand **, size_t); -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint _g_arch_operand_hash(const GArchOperand *, bool); +/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */ -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint g_arch_operand_hash(const GArchOperand *); -/* Détermine si deux candidats à l'unicité sont identiques. */ -static gboolean g_arch_operand_is_equal(const GArchOperand *, const GArchOperand *); +/* Calcule l'empreinte sur 32 bits d'un objet. */ +static guint g_arch_operand_hash(const GHashableObject *); -/* Marque un candidat comme figé. */ -static void g_arch_operand_set_read_only(GArchOperand *); -/* Indique si le candidat est figé. */ -static bool g_arch_operand_is_read_only(GArchOperand *); +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ -/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ +/* Charge un objet depuis un flux de données. */ +static bool g_arch_operand_load(GSerializableObject *, GObjectStorage *, int); +/* Sauvegarde un objet dans un flux de données. */ +static bool g_arch_operand_store(const GSerializableObject *, GObjectStorage *, int); -/* Charge un contenu depuis une mémoire tampon. */ -static bool _g_arch_operand_load(GArchOperand *, GObjectStorage *, packed_buffer_t *); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_arch_operand_load(GArchOperand *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool _g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer_t *); +/* ------------------------ CONTROLE DU VOLUME DES INSTANCES ------------------------ */ -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer_t *); + +/* Marque un candidat comme figé. */ +static void g_arch_operand_mark_as_read_only(GSingletonCandidate *); + +/* Indique si le candidat est figé. */ +static bool g_arch_operand_is_read_only(const GSingletonCandidate *); @@ -114,9 +114,12 @@ static bool g_arch_operand_store(GArchOperand *, GObjectStorage *, packed_buffer /* Indique le type défini pour un opérande d'architecture. */ -G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_SINGLETON_CANDIDATE, g_arch_operand_singleton_init) - G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_operand_serializable_init)); +G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_THICK_OBJECT, + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_arch_operand_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_arch_operand_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_operand_serializable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SINGLETON_CANDIDATE, g_arch_operand_singleton_candidate_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_arch_operand_string_builder_iface_init)); /****************************************************************************** @@ -134,30 +137,20 @@ G_DEFINE_TYPE_WITH_CODE(GArchOperand, g_arch_operand, G_TYPE_OBJECT, static void g_arch_operand_class_init(GArchOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Encore une autre vision... */ object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_arch_operand_finalize; - - operand = G_ARCH_OPERAND_CLASS(klass); - - operand->compare = (operand_compare_fc)_g_arch_operand_compare; - - operand->hash = _g_arch_operand_hash; - - operand->load = (load_operand_fc)_g_arch_operand_load; - operand->store = (store_operand_fc)_g_arch_operand_store; + object->dispose = g_arch_operand_dispose; + object->finalize = g_arch_operand_finalize; } /****************************************************************************** * * -* Paramètres : operand = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise une instance d'opérande d'architecture. * +* Description : Procède à l'initialisation de l'interface de comparaison. * * * * Retour : - * * * @@ -165,13 +158,9 @@ static void g_arch_operand_class_init(GArchOperandClass *klass) * * ******************************************************************************/ -static void g_arch_operand_init(GArchOperand *operand) +static void g_arch_operand_comparable_object_iface_init(GComparableObjectInterface *iface) { - operand_extra_data_t *extra; /* Données insérées à modifier */ - - extra = GET_ARCH_OP_EXTRA(operand); - - INIT_GOBJECT_EXTRA_LOCK(extra); + iface->compare = g_arch_operand_compare; } @@ -180,7 +169,7 @@ static void g_arch_operand_init(GArchOperand *operand) * * * Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de singleton. * +* Description : Procède à l'initialisation de l'interface de détermination. * * * * Retour : - * * * @@ -188,16 +177,9 @@ static void g_arch_operand_init(GArchOperand *operand) * * ******************************************************************************/ -static void g_arch_operand_singleton_init(GSingletonCandidateInterface *iface) +static void g_arch_operand_hashable_object_iface_init(GHashableObjectInterface *iface) { - iface->list_inner = (list_inner_instances_fc)g_arch_operand_list_inner_instances; - iface->update_inner = (update_inner_instances_fc)g_arch_operand_update_inner_instances; - - iface->hash = (hash_candidate_fc)g_arch_operand_hash; - iface->is_equal = (is_candidate_equal_fc)g_arch_operand_is_equal; - - iface->set_ro = (set_candidate_ro_fc)g_arch_operand_set_read_only; - iface->is_ro = (is_candidate_ro_fc)g_arch_operand_is_read_only; + iface->hash = g_arch_operand_hash; } @@ -214,38 +196,19 @@ static void g_arch_operand_singleton_init(GSingletonCandidateInterface *iface) * * ******************************************************************************/ -static void g_arch_operand_serializable_init(GSerializableObjectInterface *iface) +static void g_arch_operand_serializable_object_iface_init(GSerializableObjectInterface *iface) { - iface->load = (load_serializable_object_cb)g_arch_operand_load; - iface->store = (store_serializable_object_cb)g_arch_operand_store; + iface->load = g_arch_operand_load; + iface->store = g_arch_operand_store; } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_arch_operand_dispose(GArchOperand *operand) -{ - G_OBJECT_CLASS(g_arch_operand_parent_class)->dispose(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à la libération totale de la mémoire. * +* Description : Procède à l'initialisation de l'interface de rassemblement. * * * * Retour : - * * * @@ -253,147 +216,59 @@ static void g_arch_operand_dispose(GArchOperand *operand) * * ******************************************************************************/ -static void g_arch_operand_finalize(GArchOperand *operand) +static void g_arch_operand_singleton_candidate_iface_init(GSingletonCandidateInterface *iface) { - G_OBJECT_CLASS(g_arch_operand_parent_class)->finalize(G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* lock = précise le besoin en verrouillage. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int _g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b, bool lock) -{ - int result; /* Bilan à faire remonter */ - operand_extra_data_t *ea; /* Données insérées à consulter*/ - operand_extra_data_t *eb; /* Données insérées à consulter*/ - - assert(!lock); - - ea = GET_ARCH_OP_EXTRA(a); - eb = GET_ARCH_OP_EXTRA(b); + iface->list_inner = NULL; + iface->update_inner = NULL; - result = sort_unsigned_long(ea->flags, eb->flags); - - return result; + iface->mark_as_ro = g_arch_operand_mark_as_read_only; + iface->is_ro = g_arch_operand_is_read_only; } /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -int g_arch_operand_compare(const GArchOperand *a, const GArchOperand *b) -{ - int result; /* Bilan à faire remonter */ - GType type_a; /* Type de l'object A */ - GType type_b; /* Type de l'object B */ - - type_a = G_OBJECT_TYPE(G_OBJECT(a)); - type_b = G_OBJECT_TYPE(G_OBJECT(b)); - - assert(sizeof(GType) <= sizeof(unsigned long)); - - result = sort_unsigned_long(type_a, type_b); - - if (result == 0) - result = G_ARCH_OPERAND_GET_CLASS(a)->compare(a, b, true); - - return result; - -} - - -/****************************************************************************** +* Paramètres : iface = interface GLib à initialiser. * * * -* Paramètres : operand = opérande à consulter. * -* target = instruction à venir retrouver. * +* Description : Procède à l'initialisation de l'interface d'exportation. * * * -* Description : Détermine le chemin conduisant à un opérande interne. * -* * -* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -char *g_arch_operand_find_inner_operand_path(const GArchOperand *operand, const GArchOperand *target) +static void g_arch_operand_string_builder_iface_init(GStringBuilderInterface *iface) { - char *result; /* Chemin à retourner */ - GArchOperandClass *class; /* Classe associée à l'objet */ - - class = G_ARCH_OPERAND_GET_CLASS(operand); - - if (class->find_inner != NULL) - result = class->find_inner(operand, target); - - else - result = NULL; - - return result; + iface->to_string = NULL; } /****************************************************************************** * * -* Paramètres : operand = opérande à consulter. * -* path = chemin d'accès à un opérande à retrouver. * +* Paramètres : operand = instance à initialiser. * * * -* Description : Obtient l'opérande correspondant à un chemin donné. * +* Description : Initialise une instance d'opérande d'architecture. * * * -* Retour : Opérande trouvé ou NULL en cas d'échec. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *operand, const char *path) +static void g_arch_operand_init(GArchOperand *operand) { - GArchOperand *result; /* Opérande trouvée à renvoyer */ - GArchOperandClass *class; /* Classe associée à l'objet */ - - class = G_ARCH_OPERAND_GET_CLASS(operand); - - if (class->get_inner != NULL) - result = class->get_inner(operand, path); - - else - result = NULL; - - return result; } /****************************************************************************** * * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Traduit un opérande en version humainement lisible. * +* Description : Supprime toutes les références externes. * * * * Retour : - * * * @@ -401,54 +276,36 @@ GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *ope * * ******************************************************************************/ -void g_arch_operand_print(const GArchOperand *operand, GBufferLine *line) +static void g_arch_operand_dispose(GObject *object) { - G_ARCH_OPERAND_GET_CLASS(operand)->print(operand, line); + G_OBJECT_CLASS(g_arch_operand_parent_class)->dispose(object); } -#ifdef INCLUDE_GTK_SUPPORT - - /****************************************************************************** * * -* Paramètres : operand = opérande à consulter. * -* binary = informations relatives au binaire chargé. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Construit un petit résumé concis de l'opérande. * +* Description : Procède à la libération totale de la mémoire. * * * -* Retour : Chaîne de caractères à libérer après usage ou NULL. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBinary *binary) +static void g_arch_operand_finalize(GObject *object) { - char *result; /* Description à retourner */ - GArchOperandClass *class; /* Classe associée à l'objet */ - - class = G_ARCH_OPERAND_GET_CLASS(operand); - - if (class->build_tooltip != NULL) - result = class->build_tooltip(operand, binary); - else - result = NULL; - - return result; + G_OBJECT_CLASS(g_arch_operand_parent_class)->finalize(object); } -#endif - - /****************************************************************************** * * * Paramètres : operand = opérande à venir modifier. * * flag = drapeau d'information complémentaire à planter. * -* lock = indique un besoin de verrouillage des données. * * * * Description : Ajoute une information complémentaire à un opérande. * * * @@ -458,48 +315,20 @@ char *g_arch_operand_build_tooltip(const GArchOperand *operand, const GLoadedBin * * ******************************************************************************/ -bool _g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag, bool lock) +bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) { bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à modifier */ + operand_extra_data_t extra; /* Données insérées à modifier */ assert(flag <= AOF_HIGH_USER); extra = GET_ARCH_OP_EXTRA(operand); - if (lock) - LOCK_GOBJECT_EXTRA(extra); - - result = !(extra->flags & flag); - - extra->flags |= flag; - - if (lock) - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à venir modifier. * -* flag = drapeau d'information complémentaire à planter. * -* * -* Description : Ajoute une information complémentaire à un opérande. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ + result = !(extra.flags & flag); -bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) -{ - bool result; /* Bilan à retourner */ + extra.flags |= flag; - result = _g_arch_operand_set_flag(operand, flag, true); + SET_ARCH_OP_EXTRA(operand, &extra); return result; @@ -510,7 +339,6 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) * * * Paramètres : operand = opérande à venir modifier. * * flag = drapeau d'information complémentaire à planter. * -* lock = indique un besoin de verrouillage des données. * * * * Description : Retire une information complémentaire à un opérande. * * * @@ -520,46 +348,20 @@ bool g_arch_operand_set_flag(GArchOperand *operand, ArchOperandFlag flag) * * ******************************************************************************/ -bool _g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag, bool lock) +bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) { bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à modifier */ + operand_extra_data_t extra; /* Données insérées à modifier */ assert(flag <= AOF_HIGH_USER); extra = GET_ARCH_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = (extra->flags & flag); - - extra->flags &= ~flag; - - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à venir modifier. * -* flag = drapeau d'information complémentaire à planter. * -* * -* Description : Retire une information complémentaire à un opérande. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ + result = (extra.flags & flag); -bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) -{ - bool result; /* Bilan à retourner */ + extra.flags &= ~flag; - result = _g_arch_operand_unset_flag(operand, flag, true); + SET_ARCH_OP_EXTRA(operand, &extra); return result; @@ -582,17 +384,13 @@ bool g_arch_operand_unset_flag(GArchOperand *operand, ArchOperandFlag flag) bool g_arch_operand_has_flag(const GArchOperand *operand, ArchOperandFlag flag) { bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à modifier */ + operand_extra_data_t extra; /* Données insérées à modifier */ assert(flag <= AOF_HIGH_USER); extra = GET_ARCH_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = (extra->flags & flag); - - UNLOCK_GOBJECT_EXTRA(extra); + result = (extra.flags & flag); return result; @@ -614,15 +412,11 @@ bool g_arch_operand_has_flag(const GArchOperand *operand, ArchOperandFlag flag) ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *operand) { ArchOperandFlag result; /* Fanions à retourner */ - operand_extra_data_t *extra; /* Données insérées à modifier */ + operand_extra_data_t extra; /* Données insérées à modifier */ extra = GET_ARCH_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = extra->flags; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.flags; return result; @@ -630,39 +424,40 @@ ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *operand) -/* ---------------------------------------------------------------------------------- */ -/* CONTROLE DU VOLUME DES INSTANCES */ -/* ---------------------------------------------------------------------------------- */ + + + + +#if 0 + + /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* count = quantité d'instances à l'unicité internes. * +* Paramètres : operand = opérande à consulter. * +* target = instruction à venir retrouver. * * * -* Description : Fournit une liste de candidats embarqués par un candidat. * +* Description : Détermine le chemin conduisant à un opérande interne. * * * -* Retour : Liste de candidats internes ou NULL si aucun. * +* Retour : Chemin d'accès à l'opérande ou NULL en cas d'absence. * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand, size_t *count) +char *g_arch_operand_find_inner_operand_path(const GArchOperand *operand, const GArchOperand *target) { - GArchOperand **result; /* Instances à retourner */ + char *result; /* Chemin à retourner */ GArchOperandClass *class; /* Classe associée à l'objet */ class = G_ARCH_OPERAND_GET_CLASS(operand); - if (class->list_inner == NULL) - { - *count = 0; - result = NULL; - } + if (class->find_inner != NULL) + result = class->find_inner(operand, target); else - result = class->list_inner(operand, count); + result = NULL; return result; @@ -671,105 +466,59 @@ GArchOperand **g_arch_operand_list_inner_instances(const GArchOperand *operand, /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* instances = liste de candidats internes devenus singletons. * -* count = quantité d'instances à l'unicité internes. * +* Paramètres : operand = opérande à consulter. * +* path = chemin d'accès à un opérande à retrouver. * * * -* Description : Met à jour une liste de candidats embarqués par un candidat. * +* Description : Obtient l'opérande correspondant à un chemin donné. * * * -* Retour : - * +* Retour : Opérande trouvé ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -void g_arch_operand_update_inner_instances(GArchOperand *operand, GArchOperand **instances, size_t count) +GArchOperand *g_arch_operand_get_inner_operand_from_path(const GArchOperand *operand, const char *path) { + GArchOperand *result; /* Opérande trouvée à renvoyer */ GArchOperandClass *class; /* Classe associée à l'objet */ class = G_ARCH_OPERAND_GET_CLASS(operand); - if (class->update_inner == NULL) - assert(class->list_inner == NULL); + if (class->get_inner != NULL) + result = class->get_inner(operand, path); else - { - assert(class->list_inner != NULL); - class->update_inner(operand, instances, count); - } + result = NULL; + + return result; } -/****************************************************************************** -* * -* Paramètres : operand = objet dont l'instance se veut unique. * -* lock = précise le besoin en verrouillage. * -* * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * -* * -* Retour : Empreinte de l'élément représenté. * -* * -* Remarques : - * -* * -******************************************************************************/ +#endif -static guint _g_arch_operand_hash(const GArchOperand *operand, bool lock) -{ - guint result; /* Valeur à retourner */ - const char *name; /* Désignation du type d'object*/ - fnv64_t name_hash; /* Empreinte du nom */ - operand_extra_data_t *extra; /* Données insérées à modifier */ - assert(!lock); - name = G_OBJECT_TYPE_NAME(G_OBJECT(operand)); - name_hash = fnv_64a_hash(name); - result = (name_hash & 0xffffffff); - result ^= (name_hash >> 32); - extra = GET_ARCH_OP_EXTRA(operand); - result ^= extra->flags; - return result; -} -/****************************************************************************** -* * -* Paramètres : operand = objet dont l'instance se veut unique. * -* * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * -* * -* Retour : Empreinte de l'élément représenté. * -* * -* Remarques : - * -* * -******************************************************************************/ -static guint g_arch_operand_hash(const GArchOperand *operand) -{ - guint result; /* Valeur à retourner */ - GArchOperandClass *class; /* Classe associée à l'objet */ - - class = G_ARCH_OPERAND_GET_CLASS(operand); - - result = class->hash(operand, true); - return result; - -} +/* ---------------------------------------------------------------------------------- */ +/* COMPARAISON DETAILLEE DE DEUX OBJETS */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* other = second élément à analyser. * +* Paramètres : object = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * * * -* Description : Détermine si deux candidats à l'unicité sont identiques. * +* Description : Réalise une comparaison étendue entre objets. * * * * Retour : Bilan de la comparaison. * * * @@ -777,56 +526,56 @@ static guint g_arch_operand_hash(const GArchOperand *operand) * * ******************************************************************************/ -static gboolean g_arch_operand_is_equal(const GArchOperand *operand, const GArchOperand *other) +static int g_arch_operand_compare(const GComparableObject *object, const GComparableObject *other) { - gboolean result; /* Bilan à renvoyer */ - int ret; /* Bilan d'une comparaison */ + int result; /* Bilan à retourner */ + operand_extra_data_t extra_op; /* Données insérées à consulter*/ + operand_extra_data_t extra_other; /* Données insérées à consulter*/ - ret = g_arch_operand_compare(operand, other); + extra_op = GET_ARCH_OP_EXTRA(object); + extra_other = GET_ARCH_OP_EXTRA(other); - result = (ret == 0); + result = sort_unsigned_long(extra_op.flags, extra_other.flags); return result; } -/****************************************************************************** -* * -* Paramètres : operand = objet dont l'instance se veut unique. * -* * -* Description : Marque un candidat comme figé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_arch_operand_set_read_only(GArchOperand *operand) -{ - g_arch_operand_set_flag(operand, AOF_READ_ONLY); -} +/* ---------------------------------------------------------------------------------- */ +/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * +* Paramètres : object = objet dont l'instance est à consulter. * * * -* Description : Indique si le candidat est figé. * +* Description : Calcule l'empreinte sur 32 bits d'un objet. * * * -* Retour : true si le contenu du candidat ne peut plus être modifié. * +* Retour : Valeur de représentation, unique pour l'objet ou non. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_arch_operand_is_read_only(GArchOperand *operand) +static guint g_arch_operand_hash(const GHashableObject *object) { - bool result; /* Etat à retourner */ + guint result; /* Valeur à retourner */ + const char *name; /* Désignation du type d'object*/ + fnv64_t name_hash; /* Empreinte du nom */ + operand_extra_data_t extra; /* Données insérées à consulter*/ - result = g_arch_operand_has_flag(operand, AOF_READ_ONLY); + name = G_OBJECT_TYPE_NAME(G_OBJECT(object)); + name_hash = fnv_64a_hash(name); + + result = (name_hash & 0xffffffff); + result ^= (name_hash >> 32); + + extra = GET_ARCH_OP_EXTRA(object); + + result ^= extra.flags; return result; @@ -835,17 +584,17 @@ static bool g_arch_operand_is_read_only(GArchOperand *operand) /* ---------------------------------------------------------------------------------- */ -/* CONSERVATION ET RECHARGEMENT DES DONNEES */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Charge un objet depuis un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -853,22 +602,15 @@ static bool g_arch_operand_is_read_only(GArchOperand *operand) * * ******************************************************************************/ -static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_arch_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à consulter*/ - uleb128_t value; /* Valeur ULEB128 à charger */ - - extra = GET_ARCH_OP_EXTRA(operand); + uleb128_t extra; /* Données embarquées */ - LOCK_GOBJECT_EXTRA(extra); - - result = unpack_uleb128(&value, pbuf); + result = load_uleb128(&extra, fd); if (result) - extra->flags = value; - - UNLOCK_GOBJECT_EXTRA(extra); + g_thick_object_set_extra(G_THICK_OBJECT(object), extra); return result; @@ -877,11 +619,11 @@ static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, /****************************************************************************** * * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Sauvegarde un objet dans un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -889,74 +631,69 @@ static bool _g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, * * ******************************************************************************/ -static bool g_arch_operand_load(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_arch_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GArchOperandClass *class; /* Classe à activer */ + guint extra; /* Données embarquées */ - class = G_ARCH_OPERAND_GET_CLASS(operand); + extra = g_thick_object_get_extra(G_THICK_OBJECT(object)); - result = class->load(operand, storage, pbuf); + result = store_uleb128((uleb128_t []) { extra }, fd); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* CONTROLE DU VOLUME DES INSTANCES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : candidate = objet dont l'instance se veut unique. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Marque un candidat comme figé. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool _g_arch_operand_store(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static void g_arch_operand_mark_as_read_only(GSingletonCandidate *candidate) { - bool result; /* Bilan à retourner */ - operand_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_ARCH_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = pack_uleb128((uleb128_t []){ extra->flags }, pbuf); + GArchOperand *operand; /* Version spécialisée */ - UNLOCK_GOBJECT_EXTRA(extra); + operand = G_ARCH_OPERAND(candidate); - return result; + g_arch_operand_set_flag(operand, AOF_READ_ONLY); } /****************************************************************************** * * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : operand = objet dont l'instance se veut unique. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Indique si le candidat est figé. * * * -* Retour : Bilan de l'opération. * +* Retour : true si le contenu du candidat ne peut plus être modifié. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_arch_operand_store(GArchOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_arch_operand_is_read_only(const GSingletonCandidate *candidate) { - bool result; /* Bilan à retourner */ - GArchOperandClass *class; /* Classe à activer */ + bool result; /* Etat à retourner */ + GArchOperand *operand; /* Version spécialisée */ - class = G_ARCH_OPERAND_GET_CLASS(operand); + operand = G_ARCH_OPERAND(candidate); - result = class->store(operand, storage, pbuf); + result = g_arch_operand_has_flag(operand, AOF_READ_ONLY); return result; diff --git a/src/arch/operand.h b/src/arch/operand.h index 234ee64..72a1b56 100644 --- a/src/arch/operand.h +++ b/src/arch/operand.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * operand.h - prototypes pour la gestion générique des opérandes * - * Copyright (C) 2008-2020 Cyrille Bagard + * Copyright (C) 2008-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,20 +25,16 @@ #define _ARCH_OPERAND_H -#include <glib-object.h> - +#include <stdbool.h> -#include "../common/packed.h" -#include "../format/format.h" -#include "../glibext/bufferline.h" +#include "../glibext/helpers.h" -/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */ +#define G_TYPE_ARCH_OPERAND (g_arch_operand_get_type()) -/* Depuis "../analysis/binary.h" : description de fichier binaire */ -typedef struct _GLoadedBinary GLoadedBinary; +DECLARE_GTYPE(GArchOperand, g_arch_operand, G, ARCH_OPERAND); /* Indications supplémentaires liées aux opérandes */ @@ -58,6 +54,41 @@ typedef enum _ArchOperandFlag #define AOF_USER_FLAG(n) (1 << (AOF_USER_BIT + n)) +/* Ajoute une information complémentaire à un opérande. */ +bool g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag); + +/* Retire une information complémentaire à un opérande. */ +bool g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag); + +/* Détermine si un opérande possède un fanion particulier. */ +bool g_arch_operand_has_flag(const GArchOperand *, ArchOperandFlag); + +/* Fournit les particularités de l'opérande. */ +ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *); + + + + +#if 0 + + +#include <glib-object.h> + + +#include "../common/packed.h" +#include "../format/format.h" +#include "../glibext/bufferline.h" + + + +/* ------------------------ DEFINITION D'OPERANDE QUELCONQUE ------------------------ */ + + +/* Depuis "../analysis/binary.h" : description de fichier binaire */ +typedef struct _GLoadedBinary GLoadedBinary; + + + #define G_TYPE_ARCH_OPERAND g_arch_operand_get_type() #define G_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_OPERAND, GArchOperand)) #define G_IS_ARCH_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_OPERAND)) @@ -95,18 +126,6 @@ char *g_arch_operand_build_tooltip(const GArchOperand *, const GLoadedBinary *); #endif -/* Ajoute une information complémentaire à un opérande. */ -bool g_arch_operand_set_flag(GArchOperand *, ArchOperandFlag); - -/* Retire une information complémentaire à un opérande. */ -bool g_arch_operand_unset_flag(GArchOperand *, ArchOperandFlag); - -/* Détermine si un opérande possède un fanion particulier. */ -bool g_arch_operand_has_flag(const GArchOperand *, ArchOperandFlag); - -/* Fournit les particularités de l'opérande. */ -ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *); - /* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ @@ -116,5 +135,8 @@ ArchOperandFlag g_arch_operand_get_flags(const GArchOperand *); typedef struct _GAsmStorage GAsmStorage; +#endif + + #endif /* _ARCH_OPERAND_H */ diff --git a/src/arch/operands/Makefile.am b/src/arch/operands/Makefile.am index f2a8767..3d9cbde 100644 --- a/src/arch/operands/Makefile.am +++ b/src/arch/operands/Makefile.am @@ -1,26 +1,36 @@ -noinst_LTLIBRARIES = libarchoperands.la +noinst_LTLIBRARIES = libarchoperands.la libarchoperandsui.la + +# libarchoperands_la_SOURCES = \ +# feeder-int.h \ +# feeder.h feeder.c \ +# proxy-int.h \ +# proxy.h proxy.c \ +# rename-int.h \ +# rename.h rename.c \ +# target-int.h \ +# target.h target.c \ +# targetable-int.h \ +# targetable.h targetable.c libarchoperands_la_SOURCES = \ - feeder-int.h \ - feeder.h feeder.c \ immediate-int.h \ immediate.h immediate.c \ + known-int.h \ known.h known.c \ register-int.h \ - register.h register.c \ - proxy-int.h \ - proxy.h proxy.c \ - rename-int.h \ - rename.h rename.c \ - target-int.h \ - target.h target.c \ - targetable-int.h \ - targetable.h targetable.c + register.h register.c + +libarchoperands_la_CFLAGS = $(LIBGOBJ_CFLAGS) + +libarchoperandsui_la_SOURCES = \ + immediate-ui.h immediate-ui.c \ + known-ui.h known-ui.c \ + register-ui.h register-ui.c -libarchoperands_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) +libarchoperandsui_la_CFLAGS = $(LIBGTK4_CFLAGS) devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) -dev_HEADERS = $(libarchoperands_la_SOURCES:%c=) +dev_HEADERS = $(libarchoperands_la_SOURCES:%c=) $(libarchoperandsui_la_SOURCES:%c=) diff --git a/src/arch/operands/immediate-int.h b/src/arch/operands/immediate-int.h index d2313f5..3d60c7d 100644 --- a/src/arch/operands/immediate-int.h +++ b/src/arch/operands/immediate-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * immediate-int.h - définitions internes propres aux opérandes représentant des valeurs numériques * - * Copyright (C) 2021 Cyrille Bagard + * Copyright (C) 2021-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -30,27 +30,8 @@ -/* Informations glissées dans la structure GObject de GArchOperand */ -typedef struct _immop_extra_data_t -{ - operand_extra_data_t parent; /* A laisser en premier */ - - MemoryDataSize size; /* Taille de l'opérande */ - - /** - * Les deux éléments suivants sont de type ImmOperandDisplay ; - * leur espace de conservation est réduit au maximum afin d'éviter - * un recouvrement . - */ - - unsigned int def_display : 3; /* Type par défaut d'affichage */ - unsigned int display : 3; /* Format général d'affichage */ - -} immop_extra_data_t; - - /* Définition d'un opérande de valeur numérique (instance) */ -struct _GImmOperand +struct _GImmediateOperand { GArchOperand parent; /* Instance parente */ @@ -59,7 +40,7 @@ struct _GImmOperand }; /* Définition d'un opérande de valeur numérique (classe) */ -struct _GImmOperandClass +struct _GImmediateOperandClass { GArchOperandClass parent; /* Classe parente */ @@ -70,15 +51,46 @@ struct _GImmOperandClass * Accès aux informations éventuellement déportées. */ -#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _immop_extra_data_t +{ + ARCH_OPERAND_EXTRA_DATA(3); /* Informations pour l'opérande*/ -# define GET_IMM_OP_EXTRA(op) ((immop_extra_data_t *)&((GArchOperand *)op)->extra) + /** + * MemoryDataSize + */ + unsigned int size : 4; /* Taille de l'opérande */ + + /** + * ImmOperandDisplay x 2 + */ + unsigned int def_display : 3; /* Type par défaut d'affichage */ + unsigned int display : 3; /* Format général d'affichage */ + +} immop_extra_data_t; + + +#define GET_IMM_OP_EXTRA(op) \ + GET_GOBJECT_EXTRA(op, immop_extra_data_t) + +#define SET_IMM_OP_EXTRA(op, data) \ + SET_GOBJECT_EXTRA(op, immop_extra_data_t, data) -#else -# define GET_IMM_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), immop_extra_data_t) +/* Met en place un opérande réprésentant une valeur numérique. */ +bool g_immediate_operand_create_from_value(GImmediateOperand *, MemoryDataSize, uint64_t); + +/* Crée un opérande réprésentant une valeur numérique. */ +bool g_immediate_operand_create_from_data(GImmediateOperand *, MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian); + +/** + * La taille d'impression d'un opérande n'est pas VMPA_MAX_SIZE, + * mais 1 + 64 caractères + octet nul final en cas d'impression en binaire. + */ +#define IMM_MAX_SIZE 66 -#endif +/* Construit la chaîne de caractères correspondant à l'opérande. */ +size_t _g_immediate_operand_to_string(const GImmediateOperand *, ImmOperandDisplay, char [IMM_MAX_SIZE]); diff --git a/src/arch/operands/immediate-ui.c b/src/arch/operands/immediate-ui.c new file mode 100644 index 0000000..62058b3 --- /dev/null +++ b/src/arch/operands/immediate-ui.c @@ -0,0 +1,184 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * immediate-ui.c - opérandes représentant des valeurs numériques sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "immediate-ui.h" + + +#include <i18n.h> + + +#include "immediate-int.h" +#include "../../common/extstr.h" +#include "../../glibext/tokenstyle.h" +#include "../../glibext/options/asm.h" + + + +/* Traduit un opérande en version humainement lisible. */ +static void g_immediate_operand_ui_print(const GImmediateOperand *, GBufferLine *); + +/* Construit un petit résumé concis de l'opérande. */ +static char *g_immediate_operand_ui_build_tooltip(const GImmediateOperand *, const GLoadedBinary *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'opérande UI. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface) +{ + iface->print = (print_operand_ui_fc)g_immediate_operand_ui_print; + iface->build_tooltip = (build_operand_ui_tooltip_fc)g_immediate_operand_ui_build_tooltip; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_immediate_operand_ui_print(const GImmediateOperand *operand, GBufferLine *line) +{ + GImmediateOperand *base; /* Version d'instance basique */ + ImmOperandDisplay display; /* Type d'affichage courant */ + char value[IMM_MAX_SIZE]; /* Chaîne à imprimer */ + size_t len; /* Taille de l'élément inséré */ + + base = G_IMMEDIATE_OPERAND(operand); + + display = g_immediate_operand_get_display(base); + + len = _g_immediate_operand_to_string(base, display, value); + + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_IMMEDIATE, value, len, NULL, G_OBJECT(operand)); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à consulter. * +* binary = informations relatives au binaire chargé. * +* * +* Description : Construit un petit résumé concis de l'opérande. * +* * +* Retour : Chaîne de caractères à libérer après usage ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_immediate_operand_ui_build_tooltip(const GImmediateOperand *operand, const GLoadedBinary *binary) +{ + char *result; /* Description à retourner */ + GImmediateOperand *base; /* Version d'instance basique */ + char value[IMM_MAX_SIZE]; /* Conversion artificielle */ + char *conv; /* Affichage de la Conversion */ + + base = G_IMMEDIATE_OPERAND(operand); + + if (base->raw <= UCHAR_MAX && isprint(base->raw)) + switch (base->raw) + { + case '&': + asprintf(&result, _("Character: '&'")); + break; + case '<': + asprintf(&result, _("Character: '<'")); + break; + case '>': + asprintf(&result, _("Character: '>'")); + break; + default: + asprintf(&result, _("Character: '%c'"), (char)base->raw); + break; + } + + else + asprintf(&result, _("Character: <not printable>")); + + /* Binaire */ + + _g_immediate_operand_to_string(base, IOD_BIN, value); + + asprintf(&conv, _("Binary: %s"), value); + + result = stradd(result, "\n"); + result = stradd(result, conv); + + free(conv); + + /* Octal */ + + _g_immediate_operand_to_string(base, IOD_OCT, value); + + asprintf(&conv, _("Octal: %s"), value); + + result = stradd(result, "\n"); + result = stradd(result, conv); + + free(conv); + + /* Décimal */ + + _g_immediate_operand_to_string(base, IOD_DEC, value); + + asprintf(&conv, _("Decimal: %s"), value); + + result = stradd(result, "\n"); + result = stradd(result, conv); + + free(conv); + + /* Hexadécimal */ + + _g_immediate_operand_to_string(base, IOD_HEX, value); + + asprintf(&conv, _("Hexadecimal: %s"), value); + + result = stradd(result, "\n"); + result = stradd(result, conv); + + free(conv); + + return result; + +} diff --git a/src/arch/operands/immediate-ui.h b/src/arch/operands/immediate-ui.h new file mode 100644 index 0000000..4dbddae --- /dev/null +++ b/src/arch/operands/immediate-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * immediate-ui.h - prototypes pour les opérandes représentant des valeurs numériques sous forme graphique + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERANDS_IMMEDIATE_UI_H +#define _ARCH_OPERANDS_IMMEDIATE_UI_H + + +#include "../operand-ui-int.h" + + + +/* Procède à l'initialisation de l'interface d'opérande UI. */ +void g_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *); + + + +#endif /* _ARCH_OPERANDS_IMMEDIATE_UI_H */ diff --git a/src/arch/operands/immediate.c b/src/arch/operands/immediate.c index f40c645..f99b421 100644 --- a/src/arch/operands/immediate.c +++ b/src/arch/operands/immediate.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * immediate.c - opérandes représentant des valeurs numériques * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,25 +25,32 @@ #include <assert.h> +#include <stdarg.h> + + + +#if 0 + #include <ctype.h> #include <inttypes.h> #include <limits.h> #include <malloc.h> -#include <stdarg.h> #include <stdio.h> #include <i18n.h> +#endif + + #include "immediate-int.h" -#include "known.h" -#include "rename-int.h" -#include "targetable-int.h" #include "../../common/asm.h" -#include "../../common/extstr.h" #include "../../common/sort.h" -#include "../../core/columns.h" +#include "../../glibext/comparable-int.h" +#include "../../glibext/hashable-int.h" +#include "../../glibext/serialize-int.h" +#include "../../glibext/strbuilder-int.h" @@ -51,68 +58,75 @@ /* Initialise la classe des opérandes de valeur immédiate. */ -static void g_imm_operand_class_init(GImmOperandClass *); +static void g_immediate_operand_class_init(GImmediateOperandClass *); -/* Initialise un opérande de valeur immédiate. */ -static void g_imm_operand_init(GImmOperand *); +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *); + +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *); + +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_immediate_operand_serializable_object_iface_init(GSerializableObjectInterface *); + +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_immediate_operand_string_builder_iface_init(GStringBuilderInterface *, gpointer); + +#if 0 /* Procède à l'initialisation de l'interface de ciblage. */ -static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface *); +static void g_immediate_operand_targetable_interface_init(GTargetableOperandInterface *); /* Procède à l'initialisation de l'interface de renommage. */ -static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface *); +static void g_immediate_operand_renameable_interface_init(GRenameableOperandInterface *); + +#endif + +/* Initialise un opérande de valeur immédiate. */ +static void g_immediate_operand_init(GImmediateOperand *); /* Supprime toutes les références externes. */ -static void g_imm_operand_dispose(GImmOperand *); +static void g_immediate_operand_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_imm_operand_finalize(GImmOperand *); +static void g_immediate_operand_finalize(GObject *); -/* Construit la chaîne de caractères correspondant à l'opérande. */ -static size_t _g_imm_operand_to_string(const GImmOperand *, ImmOperandDisplay, char [IMM_MAX_SIZE]); -/* Traduit un opérande en version humainement lisible. */ -static void g_imm_operand_print(const GImmOperand *, GBufferLine *); +/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */ -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Réalise une comparaison étendue entre objets. */ +static int g_immediate_operand_compare(const GComparableObject *, const GComparableObject *); -/* Compare un opérande avec un autre. */ -static int g_imm_operand_compare(const GImmOperand *, const GImmOperand *, bool); -#ifdef INCLUDE_GTK_SUPPORT +/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */ -/* Construit un petit résumé concis de l'opérande. */ -static char *g_imm_operand_build_tooltip(const GImmOperand *, const GLoadedBinary *); -#endif +/* Calcule l'empreinte sur 32 bits d'un objet. */ +static guint g_immediate_operand_hash(const GHashableObject *); -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint g_imm_operand_hash(const GImmOperand *, bool); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_imm_operand_load(GImmOperand *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_imm_operand_store(GImmOperand *, GObjectStorage *, packed_buffer_t *); +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ +/* Charge un objet depuis un flux de données. */ +static bool g_immediate_operand_load(GSerializableObject *, GObjectStorage *, int); -/* ---------------------- COMMUNICATION D'UN CIBLAGE POTENTIEL ---------------------- */ +/* Sauvegarde un objet dans un flux de données. */ +static bool g_immediate_operand_store(const GSerializableObject *, GObjectStorage *, int); -/* Obtient l'adresse de la cible visée par un opérande. */ -static bool g_imm_operand_get_addr(const GImmOperand *, const vmpa2t *, GBinFormat *, GArchProcessor *, vmpa2t *); +/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */ -/* ---------------------- CONSTRUCTION D'UN CONTENU ALTERNATIF ---------------------- */ +/* Exporte une chaîne de caractères à partir d'un objet. */ +static bool g_immediate_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *); -/* Construit un opérande de représentation alternative. */ -static GRenamedOperand *g_imm_operand_build(const GImmOperand *, const char *); @@ -122,9 +136,12 @@ static GRenamedOperand *g_imm_operand_build(const GImmOperand *, const char *); /* Indique le type défini pour un opérande de valeur numérique. */ -G_DEFINE_TYPE_WITH_CODE(GImmOperand, g_imm_operand, G_TYPE_ARCH_OPERAND, - G_IMPLEMENT_INTERFACE(G_TYPE_TARGETABLE_OPERAND, g_imm_operand_targetable_interface_init) - G_IMPLEMENT_INTERFACE(G_TYPE_RENAMEABLE_OPERAND, g_imm_operand_renameable_interface_init)); +G_DEFINE_TYPE_WITH_CODE(GImmediateOperand, g_immediate_operand, G_TYPE_ARCH_OPERAND, + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_immediate_operand_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_immediate_operand_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_immediate_operand_serializable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_immediate_operand_string_builder_iface_init) + G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_immediate_operand_ui_arch_operand_ui_iface_init)); /****************************************************************************** @@ -139,36 +156,42 @@ G_DEFINE_TYPE_WITH_CODE(GImmOperand, g_imm_operand, G_TYPE_ARCH_OPERAND, * * ******************************************************************************/ -static void g_imm_operand_class_init(GImmOperandClass *klass) +static void g_immediate_operand_class_init(GImmediateOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_imm_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_imm_operand_finalize; + object->dispose = g_immediate_operand_dispose; + object->finalize = g_immediate_operand_finalize; - operand->compare = (operand_compare_fc)g_imm_operand_compare; - operand->print = (operand_print_fc)g_imm_operand_print; -#ifdef INCLUDE_GTK_SUPPORT - operand->build_tooltip = (operand_build_tooltip_fc)g_imm_operand_build_tooltip; -#endif +} - operand->hash = (operand_hash_fc)g_imm_operand_hash; - operand->load = (load_operand_fc)g_imm_operand_load; - operand->store = (store_operand_fc)g_imm_operand_store; +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de comparaison. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *iface) +{ + iface->compare = g_immediate_operand_compare; } /****************************************************************************** * * -* Paramètres : operand = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise un opérande de valeur immédiate. * +* Description : Procède à l'initialisation de l'interface de détermination. * * * * Retour : - * * * @@ -176,23 +199,39 @@ static void g_imm_operand_class_init(GImmOperandClass *klass) * * ******************************************************************************/ -static void g_imm_operand_init(GImmOperand *operand) +static void g_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *iface) { - GET_IMM_OP_EXTRA(operand)->size = MDS_UNDEFINED; + iface->hash = g_immediate_operand_hash; - GET_IMM_OP_EXTRA(operand)->def_display = IOD_HEX; - GET_IMM_OP_EXTRA(operand)->display = IOD_COUNT; +} - operand->raw = 0; + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de sérialisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_immediate_operand_serializable_object_iface_init(GSerializableObjectInterface *iface) +{ + iface->load = g_immediate_operand_load; + iface->store = g_immediate_operand_store; } /****************************************************************************** * * -* Paramètres : iface = interface GLib à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * +* unused = pointeur non utilisé ici. * * * -* Description : Procède à l'initialisation de l'interface de ciblage. * +* Description : Procède à l'initialisation de l'interface d'exportation. * * * * Retour : - * * * @@ -200,18 +239,18 @@ static void g_imm_operand_init(GImmOperand *operand) * * ******************************************************************************/ -static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface *iface) +static void g_immediate_operand_string_builder_iface_init(GStringBuilderInterface *iface, gpointer unused) { - iface->get_addr = (get_targetable_addr_fc)g_imm_operand_get_addr; + iface->to_string = g_immediate_operand_to_string; } /****************************************************************************** * * -* Paramètres : iface = interface GLib à initialiser. * +* Paramètres : operand = instance à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de renommage. * +* Description : Initialise un opérande de valeur immédiate. * * * * Retour : - * * * @@ -219,16 +258,27 @@ static void g_imm_operand_targetable_interface_init(GTargetableOperandInterface * * ******************************************************************************/ -static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface *iface) +static void g_immediate_operand_init(GImmediateOperand *operand) { - iface->build = (build_renameable_fc)g_imm_operand_build; + immop_extra_data_t extra; /* Données insérées à consulter*/ + + extra = GET_IMM_OP_EXTRA(operand); + + extra.size = MDS_UNDEFINED; + + extra.def_display = IOD_HEX; + extra.display = IOD_COUNT; + + SET_IMM_OP_EXTRA(operand, &extra); + + operand->raw = 0; } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -238,16 +288,16 @@ static void g_imm_operand_renameable_interface_init(GRenameableOperandInterface * * ******************************************************************************/ -static void g_imm_operand_dispose(GImmOperand *operand) +static void g_immediate_operand_dispose(GObject *object) { - G_OBJECT_CLASS(g_imm_operand_parent_class)->dispose(G_OBJECT(operand)); + G_OBJECT_CLASS(g_immediate_operand_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -257,9 +307,74 @@ static void g_imm_operand_dispose(GImmOperand *operand) * * ******************************************************************************/ -static void g_imm_operand_finalize(GImmOperand *operand) +static void g_immediate_operand_finalize(GObject *object) +{ + G_OBJECT_CLASS(g_immediate_operand_parent_class)->finalize(object); + +} + + +/****************************************************************************** +* * +* Paramètres : size = taille de l'opérande souhaitée. * +* value = valeur sur x bits à venir récupérer. * +* * +* Description : Crée un opérande réprésentant une valeur numérique. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchOperand *g_immediate_operand_new_from_value(MemoryDataSize size, uint64_t value) { - G_OBJECT_CLASS(g_imm_operand_parent_class)->finalize(G_OBJECT(operand)); + GImmediateOperand *result; /* Opérande à retourner */ + + result = g_object_new(G_TYPE_IMMEDIATE_OPERAND, NULL); + + if (!g_immediate_operand_create_from_value(result, size, value)) + g_clear_object(&result); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser pleinement. * +* size = taille de l'opérande souhaitée. * +* value = valeur sur x bits à venir récupérer. * +* * +* Description : Met en place un opérande réprésentant une valeur numérique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_immediate_operand_create_from_value(GImmediateOperand *operand, MemoryDataSize size, uint64_t value) +{ + bool result; /* Bilan à retourner */ + immop_extra_data_t extra; /* Données insérées à consulter*/ + + result = (size != MDS_UNDEFINED); + + if (result) + { + extra = GET_IMM_OP_EXTRA(operand); + + extra.size = size; + + operand->raw = value; + + SET_IMM_OP_EXTRA(operand, &extra); + + } + + return result; } @@ -280,10 +395,41 @@ static void g_imm_operand_finalize(GImmOperand *operand) * * ******************************************************************************/ -GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian) +GArchOperand *g_immediate_operand_new_from_data(MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian) { - GImmOperand *result; /* Opérande à retourner */ - immop_extra_data_t *extra; /* Données insérées à modifier */ + GImmediateOperand *result; /* Opérande à retourner */ + + result = g_object_new(G_TYPE_IMMEDIATE_OPERAND, NULL); + + if (!g_immediate_operand_create_from_data(result, size, content, addr, low, endian)) + g_clear_object(&result); + + return G_ARCH_OPERAND(result); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser pleinement. * +* size = taille de l'opérande souhaitée. * +* content = flux de données à analyser. * +* addr = position courante dans ce flux. [OUT] * +* low = position éventuelle des 4 bits visés. [OUT] * +* endian = ordre des bits dans la source. * +* * +* Description : Crée un opérande réprésentant une valeur numérique. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_immediate_operand_create_from_data(GImmediateOperand *operand, MemoryDataSize size, const GBinContent *content, vmpa2t *addr, bool *low, SourceEndian endian) +{ + bool result; /* Bilan à retourner */ + uint64_t raw; /* Valeur brute lue */ uint8_t uval8; /* Valeur sur 8 bits */ uint16_t uval16; /* Valeur sur 16 bits */ uint32_t uval32; /* Valeur sur 32 bits */ @@ -293,125 +439,78 @@ GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize size, const GBinConten int32_t sval32; /* Valeur sur 32 bits */ int64_t sval64; /* Valeur sur 64 bits */ - result = g_object_new(G_TYPE_IMM_OPERAND, NULL); - - extra = GET_IMM_OP_EXTRA(result); - - extra->size = size; - switch (size) { case MDS_4_BITS_UNSIGNED: - if (!g_binary_content_read_u4(content, addr, low, &uval8)) - goto gionfd_error; - result->raw = uval8; + result = g_binary_content_read_u4(content, addr, low, &uval8); + if (result) + raw = uval8; break; case MDS_8_BITS_UNSIGNED: - if (!g_binary_content_read_u8(content, addr, &uval8)) - goto gionfd_error; - result->raw = uval8; + result = g_binary_content_read_u8(content, addr, &uval8); + if (result) + raw = uval8; break; case MDS_16_BITS_UNSIGNED: - if (!g_binary_content_read_u16(content, addr, endian, &uval16)) - goto gionfd_error; - result->raw = uval16; + result = g_binary_content_read_u16(content, addr, endian, &uval16); + if (result) + raw = uval16; break; case MDS_32_BITS_UNSIGNED: - if (!g_binary_content_read_u32(content, addr, endian, &uval32)) - goto gionfd_error; - result->raw = uval32; + result = g_binary_content_read_u32(content, addr, endian, &uval32); + if (result) + raw = uval32; break; case MDS_64_BITS_UNSIGNED: - if (!g_binary_content_read_u64(content, addr, endian, &uval64)) - goto gionfd_error; - result->raw = uval64; + result = g_binary_content_read_u64(content, addr, endian, &uval64); + if (result) + raw = uval64; break; case MDS_4_BITS_SIGNED: - if (!g_binary_content_read_s4(content, addr, low, &sval8)) - goto gionfd_error; - result->raw = sval8; + result = g_binary_content_read_s4(content, addr, low, &sval8); + if (result) + raw = sval8; break; case MDS_8_BITS_SIGNED: - if (!g_binary_content_read_s8(content, addr, &sval8)) - goto gionfd_error; - result->raw = sval8; + result = g_binary_content_read_s8(content, addr, &sval8); + if (result) + raw = sval8; break; case MDS_16_BITS_SIGNED: - if (!g_binary_content_read_s16(content, addr, endian, &sval16)) - goto gionfd_error; - result->raw = sval16; + result = g_binary_content_read_s16(content, addr, endian, &sval16); + if (result) + raw = sval16; break; case MDS_32_BITS_SIGNED: - if (!g_binary_content_read_s32(content, addr, endian, &sval32)) - goto gionfd_error; - result->raw = sval32; + result = g_binary_content_read_s32(content, addr, endian, &sval32); + if (result) + raw = sval32; break; case MDS_64_BITS_SIGNED: - if (!g_binary_content_read_s64(content, addr, endian, &sval64)) - goto gionfd_error; - result->raw = sval64; + result = g_binary_content_read_s64(content, addr, endian, &sval64); + if (result) + raw = sval64; break; case MDS_UNDEFINED: - goto gionfd_error; + result = false; break; } - return G_ARCH_OPERAND(result); - - gionfd_error: - - g_object_unref(G_OBJECT(result)); - - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : size = taille de l'opérande souhaitée. * -* value = valeur sur x bits à venir récupérer. * -* * -* Description : Crée un opérande réprésentant une valeur numérique. * -* * -* Retour : Instruction mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GArchOperand *g_imm_operand_new_from_value(MemoryDataSize size, uint64_t value) -{ - GImmOperand *result; /* Opérande à retourner */ - immop_extra_data_t *extra; /* Données insérées à modifier */ - - if (size == MDS_UNDEFINED) - result = NULL; - - else - { - result = g_object_new(G_TYPE_IMM_OPERAND, NULL); - - extra = GET_IMM_OP_EXTRA(result); - - extra->size = size; - - result->raw = value; - - } + if (result) + result = g_immediate_operand_create_from_value(operand, size, raw); - return (result != NULL ? G_ARCH_OPERAND(result) : NULL); + return result; } @@ -428,18 +527,14 @@ GArchOperand *g_imm_operand_new_from_value(MemoryDataSize size, uint64_t value) * * ******************************************************************************/ -MemoryDataSize g_imm_operand_get_size(const GImmOperand *operand) +MemoryDataSize g_immediate_operand_get_size(const GImmediateOperand *operand) { MemoryDataSize result; /* Taille à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = extra->size; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.size; return result; @@ -460,10 +555,10 @@ MemoryDataSize g_imm_operand_get_size(const GImmOperand *operand) * * ******************************************************************************/ -bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, ...) +bool g_immediate_operand_get_value(const GImmediateOperand *operand, MemoryDataSize size, ...) { bool result; /* Bilan à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ va_list ap; /* Liste des compléments */ uint8_t *uval8; /* Valeur sur 8 bits */ uint16_t *uval16; /* Valeur sur 16 bits */ @@ -478,9 +573,7 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, .. extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - if (extra->size != size) + if (extra.size != size) goto exit; va_start(ap, size); @@ -533,8 +626,6 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, .. exit: - UNLOCK_GOBJECT_EXTRA(extra); - return result; } @@ -542,6 +633,37 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, .. /****************************************************************************** * * +* Paramètres : operand = structure dont le contenu est à actualiser. [OUT] * +* size = taille de l'opérande souhaitée. * +* value = valeur sur x bits à venir récupérer. * +* * +* Description : Définit la nouvelle valeur de l'opérande à une valeur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_immediate_operand_set_value(GImmediateOperand *operand, MemoryDataSize size, uint64_t value) +{ + immop_extra_data_t extra; /* Données insérées à consulter*/ + + assert(size != MDS_UNDEFINED); + + extra = GET_IMM_OP_EXTRA(operand); + + extra.size = size; + + operand->raw = value; + + SET_IMM_OP_EXTRA(operand, &extra); + +} + + +/****************************************************************************** +* * * Paramètres : operand = opérande à consulter. * * * * Description : Fournit la valeur brute représentée par l'opérande. * @@ -552,42 +674,55 @@ bool g_imm_operand_get_value(const GImmOperand *operand, MemoryDataSize size, .. * * ******************************************************************************/ -uint64_t g_imm_operand_get_raw_value(const GImmOperand *operand) +uint64_t g_immediate_operand_get_raw_value(const GImmediateOperand *operand) { - return operand->raw; + uint64_t result; /* Valeur brute à retourner */ + + result = operand->raw; + + return result; } /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à actualiser. [OUT] * -* size = taille de l'opérande souhaitée. * -* value = valeur sur x bits à venir récupérer. * +* Paramètres : operand = structure dont le contenu est à consulter. * * * -* Description : Définit la nouvelle valeur de l'opérande à une valeur. * +* Description : Indique le signe d'une valeur immédiate. * * * -* Retour : - * +* Retour : true si la valeur est strictement négative, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -void g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t value) +bool g_immediate_operand_is_negative(const GImmediateOperand *operand) { - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - assert(size != MDS_UNDEFINED); + bool result; /* Bilan à renvoyer */ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - extra->size = size; - - operand->raw = value; + switch (extra.size) + { + case MDS_4_BITS_SIGNED: + case MDS_8_BITS_SIGNED: + case MDS_16_BITS_SIGNED: + case MDS_32_BITS_SIGNED: + case MDS_64_BITS_SIGNED: + /** + * Pour les valeurs plus petites que 64 bits, le compilateur + * réalise une extension de signe lors du transtypage. + */ + result = (operand->raw & 0x8000000000000000ll); + break; + default: + result = false; + break; + } - UNLOCK_GOBJECT_EXTRA(extra); + return result; } @@ -605,17 +740,15 @@ void g_imm_operand_set_value(GImmOperand *operand, MemoryDataSize size, uint64_t * * ******************************************************************************/ -void g_imm_operand_set_default_display(GImmOperand *operand, ImmOperandDisplay display) +void g_immediate_operand_set_default_display(GImmediateOperand *operand, ImmOperandDisplay display) { - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); + extra.def_display = display; - extra->def_display = display; - - UNLOCK_GOBJECT_EXTRA(extra); + SET_IMM_OP_EXTRA(operand, &extra); } @@ -632,18 +765,14 @@ void g_imm_operand_set_default_display(GImmOperand *operand, ImmOperandDisplay d * * ******************************************************************************/ -ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand) +ImmOperandDisplay g_immediate_operand_get_default_display(const GImmediateOperand *operand) { ImmOperandDisplay result; /* Affichage à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - result = extra->def_display; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.def_display; return result; @@ -663,17 +792,15 @@ ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *operand) * * ******************************************************************************/ -void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display) +void g_immediate_operand_set_display(GImmediateOperand *operand, ImmOperandDisplay display) { - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); + extra.display = display; - extra->display = display; - - UNLOCK_GOBJECT_EXTRA(extra); + SET_IMM_OP_EXTRA(operand, &extra); } @@ -690,94 +817,225 @@ void g_imm_operand_set_display(GImmOperand *operand, ImmOperandDisplay display) * * ******************************************************************************/ -ImmOperandDisplay g_imm_operand_get_display(const GImmOperand *operand) +ImmOperandDisplay g_immediate_operand_get_display(const GImmediateOperand *operand) { ImmOperandDisplay result; /* Affichage à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ extra = GET_IMM_OP_EXTRA(operand); - LOCK_GOBJECT_EXTRA(extra); - - if (extra->display != IOD_COUNT) - result = extra->display; + if (extra.display != IOD_COUNT) + result = extra.display; else - result = extra->def_display; - - UNLOCK_GOBJECT_EXTRA(extra); + result = extra.def_display; return result; } + +/* ---------------------------------------------------------------------------------- */ +/* COMPARAISON DETAILLEE DE DEUX OBJETS */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à consulter. * +* Paramètres : object = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * * * -* Description : Indique le signe d'une valeur immédiate. * +* Description : Réalise une comparaison étendue entre objets. * * * -* Retour : true si la valeur est strictement négative, false sinon. * +* Retour : Bilan de la comparaison. * * * * Remarques : - * * * ******************************************************************************/ -bool g_imm_operand_is_negative(const GImmOperand *operand) +static int g_immediate_operand_compare(const GComparableObject *object, const GComparableObject *other) { - bool result; /* Bilan à renvoyer */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + int result; /* Bilan à retourner */ + GComparableObjectInterface *iface; /* Interface utilisée */ + GComparableObjectInterface *parent_iface; /* Interface parente */ + GImmediateOperand *operand_a; /* Version spécialisée #0 */ + GImmediateOperand *operand_b; /* Version spécialisée #1 */ + immop_extra_data_t extra_a; /* Données insérées à consulter*/ + immop_extra_data_t extra_b; /* Données insérées à consulter*/ - extra = GET_IMM_OP_EXTRA(operand); + iface = G_COMPARABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); - LOCK_GOBJECT_EXTRA(extra); + result = parent_iface->compare(object, other); - switch (extra->size) + if (result == 0) { - case MDS_4_BITS_SIGNED: - case MDS_8_BITS_SIGNED: - case MDS_16_BITS_SIGNED: - case MDS_32_BITS_SIGNED: - case MDS_64_BITS_SIGNED: - /** - * Pour les valeurs plus petites que 64 bits, le compilateur - * réalise une extension de signe lors du transtypage. - */ - result = (operand->raw & 0x8000000000000000ll); - break; - default: - result = false; - break; + operand_a = G_IMMEDIATE_OPERAND(object); + + extra_a = GET_IMM_OP_EXTRA(operand_a); + + operand_b = G_IMMEDIATE_OPERAND(other); + + extra_b = GET_IMM_OP_EXTRA(operand_b); + + result = sort_unsigned_long(extra_a.size, extra_b.size); + + if (result == 0) + sort_uint64_t(operand_a->raw, operand_b->raw); + + if (result == 0) + result = sort_unsigned_long(extra_a.def_display, extra_b.def_display); + + if (result == 0) + result = sort_unsigned_long(extra_a.display, extra_b.display); + } - UNLOCK_GOBJECT_EXTRA(extra); + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : object = objet dont l'instance est à consulter. * +* * +* Description : Calcule l'empreinte sur 32 bits d'un objet. * +* * +* Retour : Valeur de représentation, unique pour l'objet ou non. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static guint g_immediate_operand_hash(const GHashableObject *object) +{ + guint result; /* Valeur à retourner */ + GHashableObjectInterface *iface; /* Interface utilisée */ + GHashableObjectInterface *parent_iface; /* Interface parente */ + GImmediateOperand *operand; /* Version spécialisée */ + + iface = G_HASHABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->hash(object); + + operand = G_IMMEDIATE_OPERAND(object); + + result ^= (operand->raw & 0xffffffff); + result ^= (operand->raw >> 32); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = structure dont le contenu est à consulter. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Indique si une valeur immédiate est nulle ou non. * +* Description : Charge un objet depuis un flux de données. * * * -* Retour : true si la valeur est nulle, false sinon. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -bool g_imm_operand_is_null(const GImmOperand *operand) +static bool g_immediate_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd) { - return (operand->raw == 0ll); + bool result; /* Bilan à retourner */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + uleb128_t val; /* Valeur sauvegardée */ + GImmediateOperand *operand; /* Version spécialisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->load(object, storage, fd); + + if (result) + { + result = load_uleb128(&val, fd); + + if (result) + { + operand = G_IMMEDIATE_OPERAND(object); + operand->raw = val; + } + + } + + return result; } /****************************************************************************** * * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * +* * +* Description : Sauvegarde un objet dans un flux de données. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_immediate_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd) +{ + bool result; /* Bilan à retourner */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + GImmediateOperand *operand; /* Version spécialisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->store(object, storage, fd); + if (!result) goto exit; + + operand = G_IMMEDIATE_OPERAND(object); + + result = store_uleb128((uleb128_t []) { operand->raw }, fd); + + exit: + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * * Paramètres : operand = opérande à transcrire. * * display = type d'affichage demandé. * * value = valeur portée par l'opérande transcrite. [OUT] * @@ -790,10 +1048,10 @@ bool g_imm_operand_is_null(const GImmOperand *operand) * * ******************************************************************************/ -static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDisplay display, char value[IMM_MAX_SIZE]) +size_t _g_immediate_operand_to_string(const GImmediateOperand *operand, ImmOperandDisplay display, char value[IMM_MAX_SIZE]) { size_t result; /* Longueur à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ + immop_extra_data_t extra; /* Données insérées à consulter*/ unsigned int range; /* Catégorie de la taille */ const char *prefix; /* Entrée en matière */ const char *suffix; /* Sortie de matière */ @@ -813,13 +1071,11 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis static const char *conv_si_defs[] = { "", "o", "d", "x", "c" }; static const char *conv_us_defs[] = { "", "o", "u", "x", "c" }; - assert(display <= IOD_LAST_VALID); + assert(display < IOD_COUNT); extra = GET_IMM_OP_EXTRA(operand); - //LOCK_GOBJECT_EXTRA(extra); - - range = MDS_RANGE(extra->size); + range = MDS_RANGE(extra.size); /* Encadrement pour les caractères */ if (display == IOD_CHAR) @@ -862,10 +1118,10 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis if (do_padding) { - if (extra->display != IOD_COUNT) - do_padding = (extra->display != IOD_BIN && extra->display != IOD_HEX); + if (extra.display != IOD_COUNT) + do_padding = (extra.display == IOD_BIN || extra.display == IOD_HEX); else - do_padding = (extra->def_display != IOD_BIN && extra->def_display != IOD_HEX); + do_padding = (extra.def_display == IOD_BIN || extra.def_display == IOD_HEX); } switch (display) @@ -892,7 +1148,7 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis if (display != IOD_BIN) { - if (MDS_IS_SIGNED(extra->size)) + if (MDS_IS_SIGNED(extra.size)) conv = conv_si_defs[display]; else conv = conv_us_defs[display]; @@ -929,7 +1185,7 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis snprintf(format, sizeof(format), "%s%s%s%s%s%s%s", prefix, alternate, intro, zpad, lmod, conv, suffix); - switch (extra->size) + switch (extra.size) { case MDS_UNDEFINED: result = snprintf(value, IMM_MAX_SIZE, "<? undef value ?>"); @@ -982,8 +1238,6 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis } - //UNLOCK_GOBJECT_EXTRA(extra); - assert(result > 0); return result; @@ -993,555 +1247,37 @@ static size_t _g_imm_operand_to_string(const GImmOperand *operand, ImmOperandDis /****************************************************************************** * * -* Paramètres : operand = opérande à transcrire. * -* syntax = type de représentation demandée. * -* value = valeur portée par l'opérande transcrite. [OUT] * +* Paramètres : builder = objet dont l'instance est exportable. * +* flags = éventuelles indications pour l'opération. * +* out = chaîne de caractères mise en place. [OUT] * * * -* Description : Construit la chaîne de caractères correspondant à l'opérande.* +* Description : Exporte une chaîne de caractères à partir d'un objet. * * * -* Retour : Nombre de caractères utilisés. * +* Retour : Bilan de l'opération. * * * -* Remarques : - * +* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après * +* usage. * * * ******************************************************************************/ -size_t g_imm_operand_to_string(const GImmOperand *operand, char value[IMM_MAX_SIZE]) +static bool g_immediate_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out) { - size_t result; /* Longueur à retourner */ + bool result; /* Bilan à retourner */ + const GImmediateOperand *operand; /* Version spécialisée */ ImmOperandDisplay display; /* Type d'affichage courant */ - - display = g_imm_operand_get_display(operand); - - result = _g_imm_operand_to_string(operand, display, value); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_imm_operand_print(const GImmOperand *operand, GBufferLine *line) -{ char value[IMM_MAX_SIZE]; /* Chaîne à imprimer */ size_t len; /* Taille de l'élément inséré */ - len = g_imm_operand_to_string(operand, value); - - g_buffer_line_append_text(line, DLC_ASSEMBLY, value, len, RTT_IMMEDIATE, G_OBJECT(operand)); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* pos = valeur résultante. [OUT] * -* * -* Description : Convertit une valeur immédiate en position de type phys_t. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_imm_operand_to_phys_t(const GImmOperand *operand, phys_t *pos) -{ - bool result; /* Bilan à renvoyer */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = !MDS_IS_SIGNED(extra->size); - - if (result) - *pos = operand->raw; - - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* addr = valeur résultante. [OUT] * -* * -* Description : Convertit une valeur immédiate en adresse de type virt_t. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_imm_operand_to_virt_t(const GImmOperand *operand, virt_t *addr) -{ - bool result; /* Bilan à renvoyer */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = !MDS_IS_SIGNED(extra->size); - - if (result) - *addr = operand->raw; - - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* val = valeur résultante. [OUT] * -* * -* Description : Convertit une valeur immédiate en valeur de type leb128_t. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_imm_operand_as_leb128(const GImmOperand *operand, leb128_t *val) -{ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - *val = operand->raw; - - UNLOCK_GOBJECT_EXTRA(extra); - -} - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à traiter. * -* val = valeur résultante. [OUT] * -* * -* Description : Convertit une valeur immédiate en valeur de type uleb128_t. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_imm_operand_as_uleb128(const GImmOperand *operand, uleb128_t *val) -{ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - *val = operand->raw; - - UNLOCK_GOBJECT_EXTRA(extra); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* lock = précise le besoin en verrouillage. * -* * -* Description : Compare un opérande avec un autre. * -* * -* Retour : Bilan de la comparaison. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static int g_imm_operand_compare(const GImmOperand *a, const GImmOperand *b, bool lock) -{ - int result; /* Bilan à retourner */ - immop_extra_data_t *ea; /* Données insérées à modifier */ - immop_extra_data_t *eb; /* Données insérées à modifier */ - GArchOperandClass *class; /* Classe parente normalisée */ - - ea = GET_IMM_OP_EXTRA(a); - eb = GET_IMM_OP_EXTRA(b); - - if (lock) - { - LOCK_GOBJECT_EXTRA(ea); - LOCK_GOBJECT_EXTRA(eb); - } - - result = sort_unsigned_long(ea->size, eb->size); - - if (result == 0) - sort_uint64_t(a->raw, b->raw); - - if (result == 0) - result = sort_unsigned_long(ea->def_display, eb->def_display); - - if (result == 0) - result = sort_unsigned_long(ea->display, eb->display); - - if (result == 0) - { - class = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); - result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); - } - - if (lock) - { - UNLOCK_GOBJECT_EXTRA(eb); - UNLOCK_GOBJECT_EXTRA(ea); - } - - return result; - -} - - -#ifdef INCLUDE_GTK_SUPPORT - - -/****************************************************************************** -* * -* Paramètres : operand = opérande à consulter. * -* binary = informations relatives au binaire chargé. * -* * -* Description : Construit un petit résumé concis de l'opérande. * -* * -* Retour : Chaîne de caractères à libérer après usage ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static char *g_imm_operand_build_tooltip(const GImmOperand *operand, const GLoadedBinary *binary) -{ - char *result; /* Description à retourner */ - char value[IMM_MAX_SIZE]; /* Conversion artificielle */ - char *conv; /* Affichage de la Conversion */ - - if (operand->raw <= UCHAR_MAX && isprint(operand->raw)) - switch (operand->raw) - { - case '&': - asprintf(&result, _("Character: '&'")); - break; - case '<': - asprintf(&result, _("Character: '<'")); - break; - case '>': - asprintf(&result, _("Character: '>'")); - break; - default: - asprintf(&result, _("Character: '%c'"), (char)operand->raw); - break; - } - - else - asprintf(&result, _("Character: <not printable>")); - - /* Binaire */ - - _g_imm_operand_to_string(operand, IOD_BIN, value); - - asprintf(&conv, _("Binary: %s"), value); - - result = stradd(result, "\n"); - result = stradd(result, conv); - - free(conv); - - /* Octal */ - - _g_imm_operand_to_string(operand, IOD_OCT, value); - - asprintf(&conv, _("Octal: %s"), value); - - result = stradd(result, "\n"); - result = stradd(result, conv); - - free(conv); - - /* Décimal */ - - _g_imm_operand_to_string(operand, IOD_DEC, value); - - asprintf(&conv, _("Decimal: %s"), value); - - result = stradd(result, "\n"); - result = stradd(result, conv); - - free(conv); - - /* Hexadécimal */ - - _g_imm_operand_to_string(operand, IOD_HEX, value); - - asprintf(&conv, _("Hexadecimal: %s"), value); - - result = stradd(result, "\n"); - result = stradd(result, conv); - - free(conv); - - return result; - -} - - -#endif - - -/****************************************************************************** -* * -* Paramètres : operand = objet dont l'instance se veut unique. * -* lock = précise le besoin en verrouillage. * -* * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * -* * -* Retour : Empreinte de l'élément représenté. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static guint g_imm_operand_hash(const GImmOperand *operand, bool lock) -{ - guint result; /* Valeur à retourner */ - immop_extra_data_t *extra; /* Données insérées à modifier */ - GArchOperandClass *class; /* Classe parente normalisée */ - - extra = GET_IMM_OP_EXTRA(operand); - - if (lock) - LOCK_GOBJECT_EXTRA(extra); - - class = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); - result = class->hash(G_ARCH_OPERAND(operand), false); - - result ^= (operand->raw & 0xffffffff); - result ^= (operand->raw >> 32); - - if (lock) - UNLOCK_GOBJECT_EXTRA(extra); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = é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 : - * -* * -******************************************************************************/ - -static bool g_imm_operand_load(GImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - immop_extra_data_t *extra; /* Données insérées à modifier */ - uleb128_t value; /* Valeur ULEB128 à charger */ - uint8_t val; /* Champ de bits manipulé */ - - parent = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); - - result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); - - if (result) - { - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = unpack_uleb128(&value, pbuf); - - if (result) - extra->size = value; - - if (result) - { - result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); - - if (result) - extra->def_display = val; - - } - - if (result) - { - result = extract_packed_buffer(pbuf, &val, sizeof(uint8_t), false); - - if (result) - extra->display = val; - - } - - UNLOCK_GOBJECT_EXTRA(extra); - - } - - if (result) - result = extract_packed_buffer(pbuf, &operand->raw, sizeof(uint64_t), true); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : operand = é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_imm_operand_store(GImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - immop_extra_data_t *extra; /* Données insérées à modifier */ + operand = G_IMMEDIATE_OPERAND(builder); - parent = G_ARCH_OPERAND_CLASS(g_imm_operand_parent_class); + display = g_immediate_operand_get_display(operand); - result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); + len = _g_immediate_operand_to_string(operand, display, value); - if (result) - { - extra = GET_IMM_OP_EXTRA(operand); - - LOCK_GOBJECT_EXTRA(extra); - - result = pack_uleb128((uleb128_t []){ extra->size }, pbuf); - - if (result) - result = extend_packed_buffer(pbuf, (uint8_t []) { extra->def_display }, sizeof(uint8_t), false); - - if (result) - result = extend_packed_buffer(pbuf, (uint8_t []) { extra->display }, sizeof(uint8_t), false); - - UNLOCK_GOBJECT_EXTRA(extra); - - } + result = (len > 0); if (result) - result = extend_packed_buffer(pbuf, &operand->raw, sizeof(uint64_t), true); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* COMMUNICATION D'UN CIBLAGE POTENTIEL */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : operand = operande à consulter. * -* src = localisation de l'instruction mère. * -* format = format reconnu pour le binaire chargé. * -* proc = architecture associée à ce même binaire. * -* addr = localisation de la cible. [OUT] * -* * -* Description : Obtient l'adresse de la cible visée par un opérande. * -* * -* Retour : true si la cible est valide, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_imm_operand_get_addr(const GImmOperand *operand, const vmpa2t *src, GBinFormat *format, GArchProcessor *proc, vmpa2t *addr) -{ - bool result; /* Bilan à retourner */ - virt_t virt; /* Adresse virtuelle */ - - result = g_imm_operand_to_virt_t(operand, &virt); - - if (result) - result = g_exe_format_translate_address_into_vmpa(G_EXE_FORMAT(format), virt, addr); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONSTRUCTION D'UN CONTENU ALTERNATIF */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : operand = operande à consulter. * -* text = texte alternatif de représentation. * -* * -* Description : Construit un opérande de représentation alternative. * -* * -* Retour : Nouvel opérande, en version renommée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GRenamedOperand *g_imm_operand_build(const GImmOperand *operand, const char *text) -{ - GRenamedOperand *result; /* Instance à retourner */ - - result = G_RENAMED_OPERAND(g_known_imm_operand_new(operand, text)); + add_to_sized_binary(out, value, len); return result; diff --git a/src/arch/operands/immediate.h b/src/arch/operands/immediate.h index 7c1ff03..d66349a 100644 --- a/src/arch/operands/immediate.h +++ b/src/arch/operands/immediate.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * immediate.h - prototypes pour les opérandes représentant des valeurs numériques * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2024 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,17 +25,22 @@ #define _ARCH_OPERANDS_IMMEDIATE_H -#include <glib-object.h> #include <stdbool.h> #include <stdint.h> -#include "../archbase.h" #include "../operand.h" #include "../../analysis/content.h" +#include "../../common/datatypes.h" +#include "../../glibext/helpers.h" +#define G_TYPE_IMMEDIATE_OPERAND (g_immediate_operand_get_type()) + +DECLARE_GTYPE(GImmediateOperand, g_immediate_operand, G, IMMEDIATE_OPERAND); + + /* Etats particuliers d'un opérande de valeur immédiate */ typedef enum _ImmOpFlag { @@ -57,86 +62,39 @@ typedef enum _ImmOperandDisplay } ImmOperandDisplay; -#define IOD_LAST_VALID IOD_CHAR - - -#define G_TYPE_IMM_OPERAND g_imm_operand_get_type() -#define G_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_IMM_OPERAND, GImmOperand)) -#define G_IS_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_IMM_OPERAND)) -#define G_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_IMM_OPERAND, GImmOperandClass)) -#define G_IS_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_IMM_OPERAND)) -#define G_IMM_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_IMM_OPERAND, GImmOperandClass)) - - -/* Définition d'un opérande de valeur numérique (instance) */ -typedef struct _GImmOperand GImmOperand; - -/* Définition d'un opérande de valeur numérique (classe) */ -typedef struct _GImmOperandClass GImmOperandClass; - - -/* Indique le type défini pour un opérande d'architecture. */ -GType g_imm_operand_get_type(void); /* Crée un opérande réprésentant une valeur numérique. */ -GArchOperand *_g_imm_operand_new_from_data(MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian); - -#define g_imm_operand_new_from_data(size, content, addr, endian) \ - _g_imm_operand_new_from_data(size, content, addr, NULL, endian) +GArchOperand *g_immediate_operand_new_from_value(MemoryDataSize, uint64_t); /* Crée un opérande réprésentant une valeur numérique. */ -GArchOperand *g_imm_operand_new_from_value(MemoryDataSize, uint64_t); +GArchOperand *g_immediate_operand_new_from_data(MemoryDataSize, const GBinContent *, vmpa2t *, bool *, SourceEndian); /* Renseigne la taille de la valeur indiquée à la construction. */ -MemoryDataSize g_imm_operand_get_size(const GImmOperand *); +MemoryDataSize g_immediate_operand_get_size(const GImmediateOperand *); /* Fournit la valeur portée par une opérande numérique. */ -bool g_imm_operand_get_value(const GImmOperand *, MemoryDataSize, ...); +bool g_immediate_operand_get_value(const GImmediateOperand *, MemoryDataSize, ...); + +/* Définit la nouvelle valeur de l'opérande à une valeur. */ +void g_immediate_operand_set_value(GImmediateOperand *, MemoryDataSize, uint64_t); /* Fournit la valeur brute représentée par l'opérande. */ -uint64_t g_imm_operand_get_raw_value(const GImmOperand *); +uint64_t g_immediate_operand_get_raw_value(const GImmediateOperand *); -/* Définit la nouvelle valeur de l'opérande à une valeur. */ -void g_imm_operand_set_value(GImmOperand *, MemoryDataSize, uint64_t); +/* Indique le signe d'une valeur immédiate. */ +bool g_immediate_operand_is_negative(const GImmediateOperand *); /* Définit le format textuel par défaut de la valeur. */ -void g_imm_operand_set_default_display(GImmOperand *, ImmOperandDisplay); +void g_immediate_operand_set_default_display(GImmediateOperand *, ImmOperandDisplay); /* Indique le format textuel par défaut de la valeur. */ -ImmOperandDisplay g_imm_operand_get_default_display(const GImmOperand *); +ImmOperandDisplay g_immediate_operand_get_default_display(const GImmediateOperand *); /* Définit la grande ligne du format textuel de la valeur. */ -void g_imm_operand_set_display(GImmOperand *, ImmOperandDisplay); +void g_immediate_operand_set_display(GImmediateOperand *, ImmOperandDisplay); /* Indique la grande ligne du format textuel de la valeur. */ -ImmOperandDisplay g_imm_operand_get_display(const GImmOperand *); - -/* Indique le signe d'une valeur immédiate. */ -bool g_imm_operand_is_negative(const GImmOperand *); - -/* Indique si une valeur immédiate est nulle ou non. */ -bool g_imm_operand_is_null(const GImmOperand *); - -/** - * La taille d'impression d'un opérande n'est pas VMPA_MAX_SIZE, - * mais 1 + 64 caractères + octet nul final en cas d'impression en binaire. - */ -#define IMM_MAX_SIZE 66 - -/* Construit la chaîne de caractères correspondant à l'opérande. */ -size_t g_imm_operand_to_string(const GImmOperand *, char [IMM_MAX_SIZE]); - -/* Convertit une valeur immédiate en position de type phys_t. */ -bool g_imm_operand_to_phys_t(const GImmOperand *, phys_t *); - -/* Convertit une valeur immédiate en adresse de type virt_t. */ -bool g_imm_operand_to_virt_t(const GImmOperand *, virt_t *); - -/* Convertit une valeur immédiate en valeur de type leb128_t. */ -void g_imm_operand_as_leb128(const GImmOperand *, leb128_t *); - -/* Convertit une valeur immédiate en valeur de type uleb128_t. */ -void g_imm_operand_as_uleb128(const GImmOperand *, uleb128_t *); +ImmOperandDisplay g_immediate_operand_get_display(const GImmediateOperand *); diff --git a/src/arch/operands/known-int.h b/src/arch/operands/known-int.h new file mode 100644 index 0000000..021fbf2 --- /dev/null +++ b/src/arch/operands/known-int.h @@ -0,0 +1,55 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * known-int.h - définitions internes pour les opérandes représentant des valeurs numériques avec sémantique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERANDS_KNOWN_INT_H +#define _ARCH_OPERANDS_KNOWN_INT_H + + +#include "immediate-int.h" +#include "known.h" + + + +/* Définition d'un remplacement d'opérande de valeur numérique (instance) */ +struct _GKnownImmediateOperand +{ + GImmediateOperand parent; /* Instance parente */ + + char *alt_text; /* Alternative humaine */ + +}; + +/* Définition d'un remplacement d'opérande de valeur numérique (classe) */ +struct _GKnownImmediateOperandClass +{ + GImmediateOperandClass parent; /* Classe parente */ + +}; + + +/* Met en place un opérande remplaçant visuellement une valeur. */ +bool g_known_immediate_operand_create(GKnownImmediateOperand *, const GImmediateOperand *, const char *); + + + +#endif /* _ARCH_OPERANDS_KNOWN_INT_H */ diff --git a/src/arch/operands/known-ui.c b/src/arch/operands/known-ui.c new file mode 100644 index 0000000..9b7507a --- /dev/null +++ b/src/arch/operands/known-ui.c @@ -0,0 +1,79 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * known-ui.c - opérandes représentant des valeurs numériques avec sémantique sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "known-ui.h" + + +#include "known-int.h" +#include "../../common/cpp.h" +#include "../../glibext/options/asm.h" + + + +/* Traduit un opérande en version humainement lisible. */ +static void g_known_immediate_operand_ui_print(const GArchOperandUI *, GBufferLine *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'opérande UI. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_known_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface) +{ + iface->print = g_known_immediate_operand_ui_print; + iface->build_tooltip = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_known_immediate_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line) +{ + GKnownImmediateOperand *known; /* Version de base */ + + known = G_KNOWN_IMMEDIATE_OPERAND(operand); + + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_IMMEDIATE, SL(known->alt_text), NULL, G_OBJECT(operand)); + +} diff --git a/src/arch/operands/known-ui.h b/src/arch/operands/known-ui.h new file mode 100644 index 0000000..fa2dc62 --- /dev/null +++ b/src/arch/operands/known-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * known-ui.h - prototypes pour les opérandes représentant des valeurs numériques avec sémantique sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERANDS_KNOWN_UI_H +#define _ARCH_OPERANDS_KNOWN_UI_H + + +#include "../operand-ui-int.h" + + + +/* Procède à l'initialisation de l'interface d'opérande UI. */ +void g_known_immediate_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *); + + + +#endif /* _ARCH_OPERANDS_KNOWN_UI_H */ diff --git a/src/arch/operands/known.c b/src/arch/operands/known.c index 5402879..c9e177f 100644 --- a/src/arch/operands/known.c +++ b/src/arch/operands/known.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * known.c - opérandes représentant des valeurs numériques avec sémantique * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -24,81 +24,80 @@ #include "known.h" -#include <assert.h> #include <malloc.h> #include <string.h> -#include "immediate-int.h" -#include "rename-int.h" -#include "../../analysis/db/misc/rlestr.h" -#include "../../core/columns.h" -#include "../../core/logs.h" +#include "known-int.h" +#include "../../common/cpp.h" +#include "../../glibext/comparable-int.h" +#include "../../glibext/hashable-int.h" +#include "../../glibext/serialize-int.h" +#include "../../glibext/strbuilder-int.h" /* ----------------------- REMPLACEMENT DE VALEURS IMMEDIATES ----------------------- */ -/* Définition d'un remplacement d'opérande de valeur numérique (instance) */ -struct _GKnownImmOperand -{ - GImmOperand parent; /* Instance parente */ +/* Initialise la classe des remplacements d'opérandes. */ +static void g_known_immediate_operand_class_init(GKnownImmediateOperandClass *); - char *alt_text; /* Alternative humaine */ +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_known_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *); -}; +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_known_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *); -/* Définition d'un remplacement d'opérande de valeur numérique (classe) */ -struct _GKnownImmOperandClass -{ - GImmOperandClass parent; /* Classe parente */ +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_known_immediate_operand_serializable_object_iface_init(GSerializableObjectInterface *); -}; - - -/* Initialise la classe des remplacements d'opérandes. */ -static void g_known_imm_operand_class_init(GKnownImmOperandClass *); +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_known_immediate_operand_string_builder_iface_init(GStringBuilderInterface *); /* Initialise un remplacement d'opérande de valeur immédiate. */ -static void g_known_imm_operand_init(GKnownImmOperand *); - -/* Procède à l'initialisation de l'interface de renommage. */ -static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface *); +static void g_known_immediate_operand_init(GKnownImmediateOperand *); /* Supprime toutes les références externes. */ -static void g_known_imm_operand_dispose(GKnownImmOperand *); +static void g_known_immediate_operand_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_known_imm_operand_finalize(GKnownImmOperand *); +static void g_known_immediate_operand_finalize(GObject *); + + +/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */ -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Réalise une comparaison étendue entre objets. */ +static int g_known_immediate_operand_compare(const GComparableObject *, const GComparableObject *); -/* Compare un opérande avec un autre. */ -static int g_known_imm_operand_compare(const GKnownImmOperand *, const GKnownImmOperand *, bool); -/* Traduit un opérande en version humainement lisible. */ -static void g_known_imm_operand_print(const GKnownImmOperand *, GBufferLine *); +/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */ -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint g_known_imm_operand_hash(const GKnownImmOperand *, bool); -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_known_imm_operand_load(GKnownImmOperand *, GObjectStorage *, packed_buffer_t *); +/* Calcule l'empreinte sur 32 bits d'un objet. */ +static guint g_known_immediate_operand_hash(const GHashableObject *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_known_imm_operand_store(GKnownImmOperand *, GObjectStorage *, packed_buffer_t *); +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ -/* ------------------------- AFFICHAGE D'UN CONTENU RENOMME ------------------------- */ +/* Charge un objet depuis un flux de données. */ +static bool g_known_immediate_operand_load(GSerializableObject *, GObjectStorage *, int); -/* Fournit un texte comme représentation alternative d'opérande. */ -static const char *g_known_imm_operand_get_text(const GKnownImmOperand *); +/* Sauvegarde un objet dans un flux de données. */ +static bool g_known_immediate_operand_store(const GSerializableObject *, GObjectStorage *, int); + + + +/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */ + + +/* Exporte une chaîne de caractères à partir d'un objet. */ +static bool g_known_immediate_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *); @@ -108,8 +107,12 @@ static const char *g_known_imm_operand_get_text(const GKnownImmOperand *); /* Indique le type défini pour un remplacemet d'opérande de valeur numérique. */ -G_DEFINE_TYPE_WITH_CODE(GKnownImmOperand, g_known_imm_operand, G_TYPE_IMM_OPERAND, - G_IMPLEMENT_INTERFACE(G_TYPE_RENAMED_OPERAND, g_known_imm_operand_renamed_interface_init)); +G_DEFINE_TYPE_WITH_CODE(GKnownImmediateOperand, g_known_immediate_operand, G_TYPE_IMMEDIATE_OPERAND, + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_known_immediate_operand_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_known_immediate_operand_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_known_immediate_operand_serializable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_known_immediate_operand_string_builder_iface_init) + G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_known_immediate_operand_ui_arch_operand_ui_iface_init)); /****************************************************************************** @@ -124,33 +127,42 @@ G_DEFINE_TYPE_WITH_CODE(GKnownImmOperand, g_known_imm_operand, G_TYPE_IMM_OPERAN * * ******************************************************************************/ -static void g_known_imm_operand_class_init(GKnownImmOperandClass *klass) +static void g_known_immediate_operand_class_init(GKnownImmediateOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_known_imm_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_known_imm_operand_finalize; + object->dispose = g_known_immediate_operand_dispose; + object->finalize = g_known_immediate_operand_finalize; + +} - operand->compare = (operand_compare_fc)g_known_imm_operand_compare; - operand->print = (operand_print_fc)g_known_imm_operand_print; - operand->hash = (operand_hash_fc)g_known_imm_operand_hash; +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de comparaison. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - operand->load = (load_operand_fc)g_known_imm_operand_load; - operand->store = (store_operand_fc)g_known_imm_operand_store; +static void g_known_immediate_operand_comparable_object_iface_init(GComparableObjectInterface *iface) +{ + iface->compare = g_known_immediate_operand_compare; } /****************************************************************************** * * -* Paramètres : operand = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise un remplacement d'opérande de valeur immédiate. * +* Description : Procède à l'initialisation de l'interface de détermination. * * * * Retour : - * * * @@ -158,9 +170,9 @@ static void g_known_imm_operand_class_init(GKnownImmOperandClass *klass) * * ******************************************************************************/ -static void g_known_imm_operand_init(GKnownImmOperand *operand) +static void g_known_immediate_operand_hashable_object_iface_init(GHashableObjectInterface *iface) { - operand->alt_text = NULL; + iface->hash = g_known_immediate_operand_hash; } @@ -169,7 +181,7 @@ static void g_known_imm_operand_init(GKnownImmOperand *operand) * * * Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de renommage. * +* Description : Procède à l'initialisation de l'interface de sérialisation. * * * * Retour : - * * * @@ -177,18 +189,19 @@ static void g_known_imm_operand_init(GKnownImmOperand *operand) * * ******************************************************************************/ -static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface *iface) +static void g_known_immediate_operand_serializable_object_iface_init(GSerializableObjectInterface *iface) { - iface->get_text = (get_renamed_text_fc)g_known_imm_operand_get_text; + iface->load = g_known_immediate_operand_load; + iface->store = g_known_immediate_operand_store; } /****************************************************************************** * * -* Paramètres : operand = instance d'objet GLib à traiter. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Supprime toutes les références externes. * +* Description : Procède à l'initialisation de l'interface d'exportation. * * * * Retour : - * * * @@ -196,12 +209,28 @@ static void g_known_imm_operand_renamed_interface_init(GRenamedOperandInterface * * ******************************************************************************/ -static void g_known_imm_operand_dispose(GKnownImmOperand *operand) +static void g_known_immediate_operand_string_builder_iface_init(GStringBuilderInterface *iface) { - if (operand->alt_text != NULL) - free(operand->alt_text); + iface->to_string = g_known_immediate_operand_to_string; - G_OBJECT_CLASS(g_known_imm_operand_parent_class)->dispose(G_OBJECT(operand)); +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser. * +* * +* Description : Initialise un remplacement d'opérande de valeur immédiate. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_known_immediate_operand_init(GKnownImmediateOperand *operand) +{ + operand->alt_text = NULL; } @@ -210,7 +239,7 @@ static void g_known_imm_operand_dispose(GKnownImmOperand *operand) * * * Paramètres : operand = instance d'objet GLib à traiter. * * * -* Description : Procède à la libération totale de la mémoire. * +* Description : Supprime toutes les références externes. * * * * Retour : - * * * @@ -218,180 +247,199 @@ static void g_known_imm_operand_dispose(GKnownImmOperand *operand) * * ******************************************************************************/ -static void g_known_imm_operand_finalize(GKnownImmOperand *operand) +static void g_known_immediate_operand_dispose(GObject *object) { - G_OBJECT_CLASS(g_known_imm_operand_parent_class)->finalize(G_OBJECT(operand)); + G_OBJECT_CLASS(g_known_immediate_operand_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : old = opérande à venir copier avant son remplacement. * -* alt = texte alternatif à présenter pour l'impression. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Crée un opérande remplaçant visuellement une valeur. * +* Description : Procède à la libération totale de la mémoire. * * * -* Retour : Instruction mise en place. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -GArchOperand *g_known_imm_operand_new(const GImmOperand *old, const char *alt) +static void g_known_immediate_operand_finalize(GObject *object) { - GKnownImmOperand *result; /* Remplacement à retourner */ - immop_extra_data_t *src; /* Données insérées à consulter*/ - immop_extra_data_t *dest; /* Données insérées à modifier */ + GKnownImmediateOperand *operand; /* Version spécialisée */ - result = g_object_new(G_TYPE_KNOWN_IMM_OPERAND, NULL); + operand = G_KNOWN_IMMEDIATE_OPERAND(object); - result->parent.raw = old->raw; + if (operand->alt_text != NULL) + free(operand->alt_text); - src = GET_IMM_OP_EXTRA(old); - dest = GET_IMM_OP_EXTRA(&result->parent); + G_OBJECT_CLASS(g_known_immediate_operand_parent_class)->finalize(object); - LOCK_GOBJECT_EXTRA(src); +} - *(&dest->parent) = *(&src->parent); - dest->size = src->size; +/****************************************************************************** +* * +* Paramètres : old = opérande à venir copier avant son remplacement. * +* alt = texte alternatif à présenter pour l'impression. * +* * +* Description : Crée un opérande remplaçant visuellement une valeur. * +* * +* Retour : Instruction mise en place. * +* * +* Remarques : - * +* * +******************************************************************************/ - dest->def_display = src->def_display; - dest->display = src->display; +GArchOperand *g_known_immediate_operand_new(const GImmediateOperand *old, const char *alt) +{ + GKnownImmediateOperand *result; /* Remplacement à retourner */ - UNLOCK_GOBJECT_EXTRA(src); + result = g_object_new(G_TYPE_KNOWN_IMMEDIATE_OPERAND, NULL); - result->alt_text = strdup(alt); + if (!g_known_immediate_operand_create(result, old, alt)) + g_clear_object(&result); return G_ARCH_OPERAND(result); } - -/* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* lock = précise le besoin en verrouillage. * +* Paramètres : operand = instance à initialiser pleinement. * +* old = opérande à venir copier avant son remplacement. * +* alt = texte alternatif à présenter pour l'impression. * * * -* Description : Compare un opérande avec un autre. * +* Description : Met en place un opérande remplaçant visuellement une valeur. * * * -* Retour : Bilan de la comparaison. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static int g_known_imm_operand_compare(const GKnownImmOperand *a, const GKnownImmOperand *b, bool lock) +bool g_known_immediate_operand_create(GKnownImmediateOperand *operand, const GImmediateOperand *old, const char *alt) { - int result; /* Bilan à retourner */ - immop_extra_data_t *ea; /* Données insérées à consulter*/ - immop_extra_data_t *eb; /* Données insérées à consulter*/ - GArchOperandClass *class; /* Classe parente normalisée */ + bool result; /* Bilan à retourner */ + immop_extra_data_t extra; /* Données insérées à consulter*/ - ea = GET_IMM_OP_EXTRA(G_IMM_OPERAND(a)); - eb = GET_IMM_OP_EXTRA(G_IMM_OPERAND(b)); + result = true; - if (lock) - { - LOCK_GOBJECT_EXTRA(ea); - LOCK_GOBJECT_EXTRA(eb); - } + extra = GET_IMM_OP_EXTRA(old); - result = strcmp(a->alt_text, b->alt_text); + SET_IMM_OP_EXTRA(operand, &extra); - if (result == 0) - { - class = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class); - result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); - } + G_IMMEDIATE_OPERAND(operand)->raw = G_IMMEDIATE_OPERAND(old)->raw; - if (lock) - { - UNLOCK_GOBJECT_EXTRA(eb); - UNLOCK_GOBJECT_EXTRA(ea); - } + operand->alt_text = strdup(alt); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* COMPARAISON DETAILLEE DE DEUX OBJETS */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * +* Paramètres : object = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * * * -* Description : Traduit un opérande en version humainement lisible. * +* Description : Réalise une comparaison étendue entre objets. * * * -* Retour : - * +* Retour : Bilan de la comparaison. * * * * Remarques : - * * * ******************************************************************************/ -static void g_known_imm_operand_print(const GKnownImmOperand *operand, GBufferLine *line) +static int g_known_immediate_operand_compare(const GComparableObject *object, const GComparableObject *other) { - size_t len; /* Taille de l'élément inséré */ + int result; /* Bilan à retourner */ + GComparableObjectInterface *iface; /* Interface utilisée */ + GComparableObjectInterface *parent_iface; /* Interface parente */ + GKnownImmediateOperand *operand_a; /* Version spécialisée #0 */ + GKnownImmediateOperand *operand_b; /* Version spécialisée #1 */ + + iface = G_COMPARABLE_OBJECT_GET_IFACE(object); - len = strlen(operand->alt_text); + parent_iface = g_type_interface_peek_parent(iface); - g_buffer_line_append_text(line, DLC_ASSEMBLY, operand->alt_text, len, RTT_IMMEDIATE, G_OBJECT(operand)); + result = parent_iface->compare(object, other); + + if (result == 0) + { + operand_a = G_KNOWN_IMMEDIATE_OPERAND(object); + operand_b = G_KNOWN_IMMEDIATE_OPERAND(other); + + result = strcmp(operand_a->alt_text, operand_b->alt_text); + + } + + return result; } +/* ---------------------------------------------------------------------------------- */ +/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* lock = précise le besoin en verrouillage. * +* Paramètres : object = objet dont l'instance est à consulter. * * * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* Description : Calcule l'empreinte sur 32 bits d'un objet. * * * -* Retour : Empreinte de l'élément représenté. * +* Retour : Valeur de représentation, unique pour l'objet ou non. * * * * Remarques : - * * * ******************************************************************************/ -static guint g_known_imm_operand_hash(const GKnownImmOperand *operand, bool lock) +static guint g_known_immediate_operand_hash(const GHashableObject *object) { guint result; /* Valeur à retourner */ - immop_extra_data_t *extra; /* Données insérées à consulter*/ - GArchOperandClass *class; /* Classe parente normalisée */ + GHashableObjectInterface *iface; /* Interface utilisée */ + GHashableObjectInterface *parent_iface; /* Interface parente */ + GKnownImmediateOperand *operand; /* Version spécialisée */ - extra = GET_IMM_OP_EXTRA(G_IMM_OPERAND(operand)); + iface = G_HASHABLE_OBJECT_GET_IFACE(object); - if (lock) - LOCK_GOBJECT_EXTRA(extra); + parent_iface = g_type_interface_peek_parent(iface); - class = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class); - result = class->hash(G_ARCH_OPERAND(operand), false); + result = parent_iface->hash(object); - result ^= g_str_hash(operand->alt_text); + operand = G_KNOWN_IMMEDIATE_OPERAND(object); - if (lock) - UNLOCK_GOBJECT_EXTRA(extra); + result ^= g_str_hash(operand->alt_text); return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Charge un objet depuis un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -399,30 +447,31 @@ static guint g_known_imm_operand_hash(const GKnownImmOperand *operand, bool lock * * ******************************************************************************/ -static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_known_immediate_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - rle_string str; /* Chaîne à charger */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + sized_binary_t str; /* Texte alternatif rechargé */ + GKnownImmediateOperand *operand; /* Version spécialisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - parent = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class); + parent_iface = g_type_interface_peek_parent(iface); - result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); + result = parent_iface->load(object, storage, fd); if (result) { - setup_empty_rle_string(&str); + init_sized_binary(&str); - result = unpack_rle_string(&str, pbuf); + load_sized_binary_as_string(&str, fd); - if (result) - { - if (get_rle_string(&str) != NULL) - operand->alt_text = strdup(get_rle_string(&str)); + operand = G_KNOWN_IMMEDIATE_OPERAND(object); - exit_rle_string(&str); + operand->alt_text = strdup(str.static_data); - } + exit_sized_binary(&str); } @@ -433,11 +482,11 @@ static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage * /****************************************************************************** * * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Sauvegarde un objet dans un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -445,54 +494,64 @@ static bool g_known_imm_operand_load(GKnownImmOperand *operand, GObjectStorage * * * ******************************************************************************/ -static bool g_known_imm_operand_store(GKnownImmOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_known_immediate_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - rle_string str; /* Chaîne à conserver */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + GKnownImmediateOperand *operand; /* Version spécialisée */ + sized_binary_t str; /* Texte alternatif à conserver*/ - parent = G_ARCH_OPERAND_CLASS(g_known_imm_operand_parent_class); + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); + parent_iface = g_type_interface_peek_parent(iface); - if (result) - { - init_static_rle_string(&str, operand->alt_text); + result = parent_iface->store(object, storage, fd); + if (!result) goto exit; - result = pack_rle_string(&str, pbuf); + operand = G_KNOWN_IMMEDIATE_OPERAND(object); - exit_rle_string(&str); + setup_sized_binary_from_static_string(&str, operand->alt_text); - } + result = store_sized_binary_as_string(&str, fd); + + exit: return result; } - /* ---------------------------------------------------------------------------------- */ -/* AFFICHAGE D'UN CONTENU RENOMME */ +/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : operand = operande à consulter. * +* Paramètres : builder = objet dont l'instance est exportable. * +* flags = éventuelles indications pour l'opération. * +* out = chaîne de caractères mise en place. [OUT] * * * -* Description : Fournit un texte comme représentation alternative d'opérande.* +* Description : Exporte une chaîne de caractères à partir d'un objet. * * * -* Retour : Chaîne de caractère de représentation alternative. * +* Retour : Bilan de l'opération. * * * -* Remarques : - * +* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après * +* usage. * * * ******************************************************************************/ -static const char *g_known_imm_operand_get_text(const GKnownImmOperand *operand) +static bool g_known_immediate_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out) { - const char *result; /* Texte à retourner */ + bool result; /* Bilan à retourner */ + const GKnownImmediateOperand *operand; /* Version spécialisée */ + + result = true; + + operand = G_KNOWN_IMMEDIATE_OPERAND(builder); - result = operand->alt_text; + add_to_sized_binary(out, operand->alt_text, strlen(operand->alt_text)); return result; diff --git a/src/arch/operands/known.h b/src/arch/operands/known.h index eb84d3b..a8b563f 100644 --- a/src/arch/operands/known.h +++ b/src/arch/operands/known.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * known.h - prototypes pour les opérandes représentant des valeurs numériques avec sémantique * - * Copyright (C) 2021 Cyrille Bagard + * Copyright (C) 2021-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,34 +25,18 @@ #define _ARCH_OPERANDS_KNOWN_H -#include <glib-object.h> - - #include "immediate.h" -#include "../operand.h" - - - -#define G_TYPE_KNOWN_IMM_OPERAND g_known_imm_operand_get_type() -#define G_KNOWN_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperand)) -#define G_IS_KNOWN_IMM_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_KNOWN_IMM_OPERAND)) -#define G_KNOWN_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperandClass)) -#define G_IS_KNOWN_IMM_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_KNOWN_IMM_OPERAND)) -#define G_KNOWN_IMM_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_KNOWN_IMM_OPERAND, GKnownImmOperandClass)) +#include "../../glibext/helpers.h" -/* Définition d'un remplacement d'opérande de valeur numérique (instance) */ -typedef struct _GKnownImmOperand GKnownImmOperand; -/* Définition d'un remplacement d'opérande de valeur numérique (classe) */ -typedef struct _GKnownImmOperandClass GKnownImmOperandClass; +#define G_TYPE_KNOWN_IMMEDIATE_OPERAND (g_known_immediate_operand_get_type()) +DECLARE_GTYPE(GKnownImmediateOperand, g_known_immediate_operand, G, KNOWN_IMMEDIATE_OPERAND); -/* Indique le type défini pour un remplacemet d'opérande de valeur numérique. */ -GType g_known_imm_operand_get_type(void); /* Crée un opérande remplaçant visuellement une valeur. */ -GArchOperand *g_known_imm_operand_new(const GImmOperand *, const char *); +GArchOperand *g_known_immediate_operand_new(const GImmediateOperand *, const char *); diff --git a/src/arch/operands/register-int.h b/src/arch/operands/register-int.h index a887567..93cf025 100644 --- a/src/arch/operands/register-int.h +++ b/src/arch/operands/register-int.h @@ -26,8 +26,6 @@ #include "register.h" - - #include "../operand-int.h" @@ -49,5 +47,9 @@ struct _GRegisterOperandClass }; +/* Met en place un opérande réprésentant une valeur numérique. */ +bool g_register_operand_create(GRegisterOperand *, GArchRegister *); + + #endif /* _ARCH_OPERANDS_REGISTER_INT_H */ diff --git a/src/arch/operands/register-ui.c b/src/arch/operands/register-ui.c new file mode 100644 index 0000000..513a24f --- /dev/null +++ b/src/arch/operands/register-ui.c @@ -0,0 +1,93 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register-ui.c - opérandes représentant des registres sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "register-ui.h" + + +#include "register.h" +#include "../../glibext/strbuilder.h" +#include "../../glibext/options/asm.h" + + + +/* Traduit un opérande en version humainement lisible. */ +static void g_register_operand_ui_print(const GArchOperandUI *, GBufferLine *); + + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'opérande UI. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_register_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *iface) +{ + iface->print = g_register_operand_ui_print; + iface->build_tooltip = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_register_operand_ui_print(const GArchOperandUI *operand, GBufferLine *line) +{ + GStringBuilder *builder; /* Autre version de l'opérande */ + sized_binary_t str; /* Chaîne équivalente produite */ + bool status; /* Bilan d'une conversion */ + + builder = G_STRING_BUILDER(operand); + + init_sized_binary(&str); + + status = g_string_builder_to_string(builder, 0 /* flags */, &str); + + if (status) + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_REGISTER, + str.static_data, str.size, NULL, G_OBJECT(operand)); + + else + g_buffer_line_append_text(line, ACO_ASSEMBLY, TRT_REGISTER, + "??", 2, NULL, G_OBJECT(operand)); + + exit_sized_binary(&str); + +} diff --git a/src/arch/operands/register-ui.h b/src/arch/operands/register-ui.h new file mode 100644 index 0000000..16be67b --- /dev/null +++ b/src/arch/operands/register-ui.h @@ -0,0 +1,37 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * register-ui.h - prototypes pour les opérandes représentant des registres sous forme graphique + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ARCH_OPERANDS_REGISTER_UI_H +#define _ARCH_OPERANDS_REGISTER_UI_H + + +#include "../operand-ui-int.h" // FIXME ?? + + + +/* Procède à l'initialisation de l'interface d'opérande UI. */ +void g_register_operand_ui_arch_operand_ui_iface_init(GArchOperandUIInterface *); + + + +#endif /* _ARCH_OPERANDS_REGISTER_UI_H */ diff --git a/src/arch/operands/register.c b/src/arch/operands/register.c index 4615a99..cad2c4e 100644 --- a/src/arch/operands/register.c +++ b/src/arch/operands/register.c @@ -28,7 +28,10 @@ #include "register-int.h" -#include "../storage.h" +#include "../../glibext/comparable-int.h" +#include "../../glibext/hashable-int.h" +#include "../../glibext/serialize-int.h" +#include "../../glibext/strbuilder-int.h" @@ -38,34 +41,61 @@ /* Initialise la classe des opérandes de registre. */ static void g_register_operand_class_init(GRegisterOperandClass *); +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_register_operand_comparable_object_iface_init(GComparableObjectInterface *); + +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_register_operand_hashable_object_iface_init(GHashableObjectInterface *); + +/* Procède à l'initialisation de l'interface de sérialisation. */ +static void g_register_operand_serializable_object_iface_init(GSerializableObjectInterface *); + +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_register_operand_string_builder_iface_init(GStringBuilderInterface *); + /* Initialise une instance d'opérande de registre. */ static void g_register_operand_init(GRegisterOperand *); /* Supprime toutes les références externes. */ -static void g_register_operand_dispose(GRegisterOperand *); +static void g_register_operand_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_register_operand_finalize(GRegisterOperand *); +static void g_register_operand_finalize(GObject *); + + + +/* ---------------------- COMPARAISON DETAILLEE DE DEUX OBJETS ---------------------- */ + + +/* Réalise une comparaison étendue entre objets. */ +static int g_register_operand_compare(const GComparableObject *, const GComparableObject *); + +/* ---------------------- CALCUL D'UNE EMPREINTE DE L'INSTANCE ---------------------- */ -/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ +/* Calcule l'empreinte sur 32 bits d'un objet. */ +static guint g_register_operand_hash(const GHashableObject *); -/* Compare un opérande avec un autre. */ -static int g_register_operand_compare(const GRegisterOperand *, const GRegisterOperand *, bool); -/* Traduit un opérande en version humainement lisible. */ -static void g_register_operand_print(const GRegisterOperand *, GBufferLine *); -/* Fournit l'empreinte d'un candidat à une centralisation. */ -static guint g_register_operand_hash(const GRegisterOperand *, bool); +/* ------------------- MECANISMES DE CONSERVATION ET RESTAURATION ------------------- */ -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_register_operand_load(GRegisterOperand *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_register_operand_store(GRegisterOperand *, GObjectStorage *, packed_buffer_t *); +/* Charge un objet depuis un flux de données. */ +static bool g_register_operand_load(GSerializableObject *, GObjectStorage *, int); + +/* Sauvegarde un objet dans un flux de données. */ +static bool g_register_operand_store(const GSerializableObject *, GObjectStorage *, int); + + + +/* ----------------- EXPORTATION SOUS FORME DE CHAINE DE CARACTERES ----------------- */ + + +/* Exporte une chaîne de caractères à partir d'un objet. */ +static bool g_register_operand_to_string(const GStringBuilder *, unsigned int, sized_binary_t *); @@ -75,7 +105,12 @@ static bool g_register_operand_store(GRegisterOperand *, GObjectStorage *, packe /* Indique le type défini par la GLib pour un opérande de registre Dalvik. */ -G_DEFINE_TYPE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND); +G_DEFINE_TYPE_WITH_CODE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND, + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_register_operand_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_register_operand_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_register_operand_serializable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_register_operand_string_builder_iface_init) + G_IMPLEMENT_INTERFACE_IF_SYM(g_arch_operand_ui_get_type, g_register_operand_ui_arch_operand_ui_iface_init)); /****************************************************************************** @@ -93,23 +128,88 @@ G_DEFINE_TYPE(GRegisterOperand, g_register_operand, G_TYPE_ARCH_OPERAND); static void g_register_operand_class_init(GRegisterOperandClass *klass) { GObjectClass *object; /* Autre version de la classe */ - GArchOperandClass *operand; /* Version de classe parente */ object = G_OBJECT_CLASS(klass); - operand = G_ARCH_OPERAND_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_register_operand_dispose; - object->finalize = (GObjectFinalizeFunc)g_register_operand_finalize; + object->dispose = g_register_operand_dispose; + object->finalize = g_register_operand_finalize; - operand = G_ARCH_OPERAND_CLASS(klass); +} - operand->compare = (operand_compare_fc)g_register_operand_compare; - operand->print = (operand_print_fc)g_register_operand_print; - operand->hash = (operand_hash_fc)g_register_operand_hash; +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de comparaison. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - operand->load = (load_operand_fc)g_register_operand_load; - operand->store = (store_operand_fc)g_register_operand_store; +static void g_register_operand_comparable_object_iface_init(GComparableObjectInterface *iface) +{ + iface->compare = g_register_operand_compare; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de détermination. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_register_operand_hashable_object_iface_init(GHashableObjectInterface *iface) +{ + iface->hash = g_register_operand_hash; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de sérialisation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_register_operand_serializable_object_iface_init(GSerializableObjectInterface *iface) +{ + iface->load = g_register_operand_load; + iface->store = g_register_operand_store; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'exportation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_register_operand_string_builder_iface_init(GStringBuilderInterface *iface) +{ + iface->to_string = g_register_operand_to_string; } @@ -135,7 +235,7 @@ static void g_register_operand_init(GRegisterOperand *operand) /****************************************************************************** * * -* Paramètres : binary = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -145,18 +245,22 @@ static void g_register_operand_init(GRegisterOperand *operand) * * ******************************************************************************/ -static void g_register_operand_dispose(GRegisterOperand *operand) +static void g_register_operand_dispose(GObject *object) { + GRegisterOperand *operand; /* Version spécialisée */ + + operand = G_REGISTER_OPERAND(object); + g_clear_object(&operand->reg); - G_OBJECT_CLASS(g_register_operand_parent_class)->dispose(G_OBJECT(operand)); + G_OBJECT_CLASS(g_register_operand_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : binary = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -166,9 +270,36 @@ static void g_register_operand_dispose(GRegisterOperand *operand) * * ******************************************************************************/ -static void g_register_operand_finalize(GRegisterOperand *operand) +static void g_register_operand_finalize(GObject *object) +{ + G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(object); + +} + + +/****************************************************************************** +* * +* Paramètres : operand = instance à initialiser pleinement. * +* reg = registre matériel à représenter. * +* * +* Description : Met en place un opérande réprésentant une valeur numérique. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_register_operand_create(GRegisterOperand *operand, GArchRegister *reg) { - G_OBJECT_CLASS(g_register_operand_parent_class)->finalize(G_OBJECT(operand)); + bool result; /* Bilan à retourner */ + + result = true; + + operand->reg = reg; + ref_object(reg); + + return result; } @@ -190,8 +321,7 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand) GArchRegister *result; /* Instance à retourner */ result = operand->reg; - - g_object_ref(G_OBJECT(result)); + ref_object(result); return result; @@ -200,17 +330,16 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand) /* ---------------------------------------------------------------------------------- */ -/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* COMPARAISON DETAILLEE DE DEUX OBJETS */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * -* Paramètres : a = premier opérande à consulter. * -* b = second opérande à consulter. * -* lock = précise le besoin en verrouillage. * +* Paramètres : object = premier objet à consulter pour une comparaison. * +* other = second objet à consulter pour une comparaison. * * * -* Description : Compare un opérande avec un autre. * +* Description : Réalise une comparaison étendue entre objets. * * * * Retour : Bilan de la comparaison. * * * @@ -218,17 +347,25 @@ GArchRegister *g_register_operand_get_register(const GRegisterOperand *operand) * * ******************************************************************************/ -static int g_register_operand_compare(const GRegisterOperand *a, const GRegisterOperand *b, bool lock) +static int g_register_operand_compare(const GComparableObject *object, const GComparableObject *other) { int result; /* Bilan à retourner */ - GArchOperandClass *class; /* Classe parente normalisée */ + GComparableObjectInterface *iface; /* Interface utilisée */ + GComparableObjectInterface *parent_iface; /* Interface parente */ + GRegisterOperand *operand; /* Version spécialisée */ + + iface = G_COMPARABLE_OBJECT_GET_IFACE(object); - result = g_arch_register_compare(a->reg, b->reg); + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->compare(object, other); if (result == 0) { - class = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); - result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); + operand = G_REGISTER_OPERAND(object); + + result = g_comparable_object_compare(G_COMPARABLE_OBJECT(operand->reg), other); + } return result; @@ -236,53 +373,96 @@ static int g_register_operand_compare(const GRegisterOperand *a, const GRegister } + +/* ---------------------------------------------------------------------------------- */ +/* CALCUL D'UNE EMPREINTE DE L'INSTANCE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * +* Paramètres : object = objet dont l'instance est à consulter. * * * -* Description : Traduit un opérande en version humainement lisible. * +* Description : Calcule l'empreinte sur 32 bits d'un objet. * * * -* Retour : - * +* Retour : Valeur de représentation, unique pour l'objet ou non. * * * * Remarques : - * * * ******************************************************************************/ -static void g_register_operand_print(const GRegisterOperand *operand, GBufferLine *line) +static guint g_register_operand_hash(const GHashableObject *object) { - g_arch_register_print(operand->reg, line); + guint result; /* Valeur à retourner */ + GHashableObjectInterface *iface; /* Interface utilisée */ + GHashableObjectInterface *parent_iface; /* Interface parente */ + GRegisterOperand *operand; /* Version spécialisée */ + + iface = G_HASHABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->hash(object); + + operand = G_REGISTER_OPERAND(object); + + result ^= g_hashable_object_hash(G_HASHABLE_OBJECT(operand->reg)); + + return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE CONSERVATION ET RESTAURATION */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = objet dont l'instance se veut unique. * -* lock = précise le besoin en verrouillage. * +* Paramètres : object = élément GLib à constuire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Fournit l'empreinte d'un candidat à une centralisation. * +* Description : Charge un objet depuis un flux de données. * * * -* Retour : Empreinte de l'élément représenté. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock) +static bool g_register_operand_load(GSerializableObject *object, GObjectStorage *storage, int fd) { - guint result; /* Valeur à retourner */ - GArchOperandClass *class; /* Classe parente normalisée */ - GArchRegister *reg; /* Registre visé par l'opérande*/ + bool result; /* Bilan à retourner */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ + GSerializableObject *reg; /* Registre récupéré */ + GRegisterOperand *operand; /* Version spécialisée */ + + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); + + parent_iface = g_type_interface_peek_parent(iface); + + result = parent_iface->load(object, storage, fd); + + if (result) + { + reg = g_object_storage_unpack_object(storage, fd, "registers"); - class = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); - result = class->hash(G_ARCH_OPERAND(operand), false); + if (reg == NULL) + result = false; - reg = g_register_operand_get_register(operand); + else + { + operand = G_REGISTER_OPERAND(object); - result ^= g_arch_register_hash(reg); + operand->reg = G_ARCH_REGISTER(reg); + + } - g_object_unref(G_OBJECT(reg)); + } return result; @@ -291,11 +471,11 @@ static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock) /****************************************************************************** * * -* Paramètres : operand = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* Paramètres : object = élément GLib à consulter. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Charge un contenu depuis une mémoire tampon. * +* Description : Sauvegarde un objet dans un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -303,61 +483,64 @@ static guint g_register_operand_hash(const GRegisterOperand *operand, bool lock) * * ******************************************************************************/ -static bool g_register_operand_load(GRegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_register_operand_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - GSerializableObject *reg; /* Registre manipulé */ + GRegisterOperand *operand; /* Version spécialisée */ + off64_t reg_pos; /* Position renvoyant au reg. */ + GSerializableObjectInterface *iface; /* Interface utilisée */ + GSerializableObjectInterface *parent_iface; /* Interface parente */ - parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); + operand = G_REGISTER_OPERAND(object); - result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); + result = g_object_storage_store_object(storage, "registers", G_SERIALIZABLE_OBJECT(operand->reg), ®_pos); + if (!result) goto exit; - if (result) - { - reg = g_object_storage_unpack_object(storage, "registers", pbuf); + iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - result = (reg != NULL); + parent_iface = g_type_interface_peek_parent(iface); - if (result) - operand->reg = G_ARCH_REGISTER(reg); + result = parent_iface->store(object, storage, fd); + if (!result) goto exit; - } + result = store_uleb128((uleb128_t []) { reg_pos }, fd); + + exit: return result; } + +/* ---------------------------------------------------------------------------------- */ +/* EXPORTATION SOUS FORME DE CHAINE DE CARACTERES */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* Paramètres : builder = objet dont l'instance est exportable. * +* flags = éventuelles indications pour l'opération. * +* out = chaîne de caractères mise en place. [OUT] * * * -* Description : Sauvegarde un contenu dans une mémoire tampon. * +* Description : Exporte une chaîne de caractères à partir d'un objet. * * * * Retour : Bilan de l'opération. * * * -* Remarques : - * +* Remarques : La sortie out est à nettoyer avec exit_sized_binary() après * +* usage. * * * ******************************************************************************/ -static bool g_register_operand_store(GRegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_register_operand_to_string(const GStringBuilder *builder, unsigned int flags, sized_binary_t *out) { bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - GSerializableObject *reg; /* Registre manipulé */ + const GRegisterOperand *operand; /* Version spécialisée */ - parent = G_ARCH_OPERAND_CLASS(g_register_operand_parent_class); + operand = G_REGISTER_OPERAND(builder); - result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); - - if (result) - { - reg = G_SERIALIZABLE_OBJECT(operand->reg); - result = g_object_storage_pack_object(storage, "registers", reg, pbuf); - } + result = g_string_builder_to_string(G_STRING_BUILDER(operand->reg), flags, out); return result; diff --git a/src/arch/register-int.h b/src/arch/register-int.h index f0b9af9..22ef2cc 100644 --- a/src/arch/register-int.h +++ b/src/arch/register-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * register-int.h - définitions internes pour la représentation générique d'un registre * - * Copyright (C) 2012-2018 Cyrille Bagard + * Copyright (C) 2012-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -26,31 +26,15 @@ #include "register.h" -#include "../analysis/storage/serialize-int.h" -/* Produit une empreinte à partir d'un registre. */ -typedef guint (* reg_hash_fc) (const GArchRegister *); - -/* Compare un registre avec un autre. */ -typedef int (* reg_compare_fc) (const GArchRegister *, const GArchRegister *); - -/* Traduit un registre en version humainement lisible. */ -typedef void (* reg_print_fc) (const GArchRegister *, GBufferLine *); - /* Indique si le registre correspond à ebp ou similaire. */ typedef bool (* reg_is_base_pointer_fc) (const GArchRegister *); /* Indique si le registre correspond à esp ou similaire. */ typedef bool (* reg_is_stack_pointer_fc) (const GArchRegister *); -/* Charge un contenu depuis une mémoire tampon. */ -typedef bool (* load_register_fc) (GArchRegister *, GObjectStorage *, packed_buffer_t *); - -/* Sauvegarde un contenu dans une mémoire tampon. */ -typedef bool (* store_register_fc) (GArchRegister *, GObjectStorage *, packed_buffer_t *); - /* Représentation d'un registre (instance) */ struct _GArchRegister @@ -64,15 +48,9 @@ struct _GArchRegisterClass { GObjectClass parent; /* A laisser en premier */ - reg_hash_fc hash; /* Production d'empreinte */ - reg_compare_fc compare; /* Comparaison de registres */ - reg_print_fc print; /* Impression du registre */ reg_is_base_pointer_fc is_bp; /* Correspondance avec ebp */ reg_is_stack_pointer_fc is_sp; /* Correspondance avec esp */ - load_register_fc load; /* Chargement depuis un tampon */ - store_register_fc store; /* Conservation dans un tampon */ - }; diff --git a/src/arch/register.c b/src/arch/register.c index f487419..6017373 100644 --- a/src/arch/register.c +++ b/src/arch/register.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * registers.c - aides auxiliaires relatives aux registres Dalvik * - * Copyright (C) 2012-2018 Cyrille Bagard + * Copyright (C) 2012-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,6 +25,10 @@ #include "register-int.h" +#include "../glibext/comparable-int.h" +#include "../glibext/hashable-int.h" +#include "../glibext/serialize-int.h" +#include "../glibext/strbuilder-int.h" @@ -34,34 +38,26 @@ /* Initialise la classe des registres. */ static void g_arch_register_class_init(GArchRegisterClass *); -/* Initialise une instance de registre. */ -static void g_arch_register_init(GArchRegister *); +/* Procède à l'initialisation de l'interface de comparaison. */ +static void g_arch_register_comparable_object_iface_init(GComparableObjectInterface *); + +/* Procède à l'initialisation de l'interface de détermination. */ +static void g_arch_register_hashable_object_iface_init(GHashableObjectInterface *); /* Procède à l'initialisation de l'interface de sérialisation. */ static void g_arch_register_serializable_init(GSerializableObjectInterface *); -/* Supprime toutes les références externes. */ -static void g_arch_register_dispose(GArchRegister *); - -/* Procède à la libération totale de la mémoire. */ -static void g_arch_register_finalize(GArchRegister *); - +/* Procède à l'initialisation de l'interface d'exportation. */ +static void g_arch_register_string_builder_iface_init(GStringBuilderInterface *); +/* Initialise une instance de registre. */ +static void g_arch_register_init(GArchRegister *); -/* -------------------- CONSERVATION ET RECHARGEMENT DES DONNEES -------------------- */ - - -/* Charge un contenu depuis une mémoire tampon. */ -static bool _g_arch_register_load(GArchRegister *, GObjectStorage *, packed_buffer_t *); - -/* Charge un contenu depuis une mémoire tampon. */ -static bool g_arch_register_load(GArchRegister *, GObjectStorage *, packed_buffer_t *); - -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool _g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buffer_t *); +/* Supprime toutes les références externes. */ +static void g_arch_register_dispose(GObject *); -/* Sauvegarde un contenu dans une mémoire tampon. */ -static bool g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buffer_t *); +/* Procède à la libération totale de la mémoire. */ +static void g_arch_register_finalize(GObject *); @@ -72,7 +68,10 @@ static bool g_arch_register_store(GArchRegister *, GObjectStorage *, packed_buff /* Indique le type défini pour une représentation d'un registre. */ G_DEFINE_TYPE_WITH_CODE(GArchRegister, g_arch_register, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_register_serializable_init)); + G_IMPLEMENT_INTERFACE(G_TYPE_COMPARABLE_OBJECT, g_arch_register_comparable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_HASHABLE_OBJECT, g_arch_register_hashable_object_iface_init) + G_IMPLEMENT_INTERFACE(G_TYPE_SERIALIZABLE_OBJECT, g_arch_register_serializable_init) + G_IMPLEMENT_INTERFACE(G_TYPE_STRING_BUILDER, g_arch_register_string_builder_iface_init)); /****************************************************************************** @@ -93,20 +92,18 @@ static void g_arch_register_class_init(GArchRegisterClass *klass) object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_register_dispose; - object->finalize = (GObjectFinalizeFunc)g_arch_register_finalize; - - klass->load = (load_register_fc)_g_arch_register_load; - klass->store = (store_register_fc)_g_arch_register_store; + object->dispose = g_arch_register_dispose; + object->finalize = g_arch_register_finalize; } + /****************************************************************************** * * -* Paramètres : reg = instance à initialiser. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Initialise une instance de registre. * +* Description : Procède à l'initialisation de l'interface de comparaison. * * * * Retour : - * * * @@ -114,8 +111,9 @@ static void g_arch_register_class_init(GArchRegisterClass *klass) * * ******************************************************************************/ -static void g_arch_register_init(GArchRegister *reg) +static void g_arch_register_comparable_object_iface_init(GComparableObjectInterface *iface) { + iface->compare = NULL; } @@ -124,7 +122,7 @@ static void g_arch_register_init(GArchRegister *reg) * * * Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à l'initialisation de l'interface de sérialisation. * +* Description : Procède à l'initialisation de l'interface de détermination. * * * * Retour : - * * * @@ -132,19 +130,18 @@ static void g_arch_register_init(GArchRegister *reg) * * ******************************************************************************/ -static void g_arch_register_serializable_init(GSerializableObjectInterface *iface) +static void g_arch_register_hashable_object_iface_init(GHashableObjectInterface *iface) { - iface->load = (load_serializable_object_cb)g_arch_register_load; - iface->store = (store_serializable_object_cb)g_arch_register_store; + iface->hash = NULL; } /****************************************************************************** * * -* Paramètres : reg = instance d'objet GLib à traiter. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Supprime toutes les références externes. * +* Description : Procède à l'initialisation de l'interface de sérialisation. * * * * Retour : - * * * @@ -152,18 +149,19 @@ static void g_arch_register_serializable_init(GSerializableObjectInterface *ifac * * ******************************************************************************/ -static void g_arch_register_dispose(GArchRegister *reg) +static void g_arch_register_serializable_init(GSerializableObjectInterface *iface) { - G_OBJECT_CLASS(g_arch_register_parent_class)->dispose(G_OBJECT(reg)); + iface->load = NULL; + iface->store = NULL; } /****************************************************************************** * * -* Paramètres : reg = instance d'objet GLib à traiter. * +* Paramètres : iface = interface GLib à initialiser. * * * -* Description : Procède à la libération totale de la mémoire. * +* Description : Procède à l'initialisation de l'interface d'exportation. * * * * Retour : - * * * @@ -171,58 +169,55 @@ static void g_arch_register_dispose(GArchRegister *reg) * * ******************************************************************************/ -static void g_arch_register_finalize(GArchRegister *reg) +static void g_arch_register_string_builder_iface_init(GStringBuilderInterface *iface) { - G_OBJECT_CLASS(g_arch_register_parent_class)->finalize(G_OBJECT(reg)); + iface->to_string = NULL; } /****************************************************************************** * * -* Paramètres : reg = opérande à consulter pour le calcul. * +* Paramètres : reg = instance à initialiser. * * * -* Description : Produit une empreinte à partir d'un registre. * +* Description : Initialise une instance de registre. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -guint g_arch_register_hash(const GArchRegister *reg) +static void g_arch_register_init(GArchRegister *reg) { - return G_ARCH_REGISTER_GET_CLASS(reg)->hash(reg); } /****************************************************************************** * * -* Paramètres : a = premier registre à consulter. * -* b = second registre à consulter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Compare un registre avec un autre. * +* Description : Supprime toutes les références externes. * * * -* Retour : Bilan de la comparaison. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -int g_arch_register_compare(const GArchRegister *a, const GArchRegister *b) +static void g_arch_register_dispose(GObject *object) { - return G_ARCH_REGISTER_GET_CLASS(a)->compare(a, b); + G_OBJECT_CLASS(g_arch_register_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : reg = registre à transcrire. * -* line = ligne tampon où imprimer l'opérande donné. * +* Paramètres : object = instance d'objet GLib à traiter. * * * -* Description : Traduit un registre en version humainement lisible. * +* Description : Procède à la libération totale de la mémoire. * * * * Retour : - * * * @@ -230,9 +225,9 @@ int g_arch_register_compare(const GArchRegister *a, const GArchRegister *b) * * ******************************************************************************/ -void g_arch_register_print(const GArchRegister *reg, GBufferLine *line) +static void g_arch_register_finalize(GObject *object) { - G_ARCH_REGISTER_GET_CLASS(reg)->print(reg, line); + G_OBJECT_CLASS(g_arch_register_parent_class)->finalize(object); } @@ -287,115 +282,3 @@ bool g_arch_register_is_stack_pointer(const GArchRegister *reg) return result; } - - - -/* ---------------------------------------------------------------------------------- */ -/* CONSERVATION ET RECHARGEMENT DES DONNEES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : reg = é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 : - * -* * -******************************************************************************/ - -static bool _g_arch_register_load(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - - result = true; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : reg = é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 : - * -* * -******************************************************************************/ - -static bool g_arch_register_load(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchRegisterClass *class; /* Classe à activer */ - - class = G_ARCH_REGISTER_GET_CLASS(reg); - - result = class->load(reg, storage, pbuf); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : reg = é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_register_store(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - - result = true; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : reg = é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_register_store(GArchRegister *reg, GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - GArchRegisterClass *class; /* Classe à activer */ - - class = G_ARCH_REGISTER_GET_CLASS(reg); - - result = class->store(reg, storage, pbuf); - - return result; - -} diff --git a/src/arch/register.h b/src/arch/register.h index 0265a73..16275e0 100644 --- a/src/arch/register.h +++ b/src/arch/register.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * register.h - prototypes pour les aides auxiliaires relatives aux registres Dalvik * - * Copyright (C) 2012-2018 Cyrille Bagard + * Copyright (C) 2012-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,44 +25,19 @@ #define _ARCH_REGISTER_H -#include <glib-object.h> #include <stdbool.h> -#include "../glibext/bufferline.h" +#include "../glibext/helpers.h" -/* ---------------------------- PUR REGISTRE DU MATERIEL ---------------------------- */ +#define G_TYPE_ARCH_REGISTER (g_arch_register_get_type()) +DECLARE_GTYPE(GArchRegister, g_arch_register, G, ARCH_REGISTER); -#define G_TYPE_ARCH_REGISTER g_arch_register_get_type() -#define G_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_ARCH_REGISTER, GArchRegister)) -#define G_IS_ARCH_REGISTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_ARCH_REGISTER)) -#define G_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARCH_REGISTER, GArchRegisterClass)) -#define G_IS_ARCH_REGISTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARCH_REGISTER)) -#define G_ARCH_REGISTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARCH_REGISTER, GArchRegisterClass)) -/* Représentation d'un registre (instance) */ -typedef struct _GArchRegister GArchRegister; - -/* Représentation d'un registre (classe) */ -typedef struct _GArchRegisterClass GArchRegisterClass; - - -/* Indique le type défini pour une représentation d'un registre. */ -GType g_arch_register_get_type(void); - -/* Produit une empreinte à partir d'un registre. */ -guint g_arch_register_hash(const GArchRegister *); - -/* Compare un registre avec un autre. */ -int g_arch_register_compare(const GArchRegister *, const GArchRegister *); - -/* Traduit un registre en version humainement lisible. */ -void g_arch_register_print(const GArchRegister *, GBufferLine *); - /* Indique si le registre correspond à ebp ou similaire. */ bool g_arch_register_is_base_pointer(const GArchRegister *); diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 42136e2..7a11deb 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -30,7 +30,6 @@ #include <stdint.h> -#include "archbase.h" #include "../common/cpp.h" #include "../common/datatypes.h" #include "../common/packed.h" @@ -297,4 +296,33 @@ char *mrange_length_to_string(const mrange_t *, MemoryDataSize, char [VMPA_MAX_L +/* ------------------- DEFINITION D'UN ESPACE RELATIVE EN MEMOIRE ------------------- */ + + +/* Couverture mémoire */ +typedef struct _rel_mrange_t +{ + uint32_t offset; /* Décalage depuis une ref. */ + uint16_t length; /* Taille de la couverture */ + +} rel_mrange_t; + + +#define init_rel_mrange(rr, o, l) \ + do \ + { \ + (rr)->offset = o; \ + (rr)->length = l; \ + } \ + while (0); + + +#define get_rel_mrange_offset(rr) \ + (rr)->offset + +#define get_rel_mrange_length(rr) \ + (rr)->length + + + #endif /* _ARCH_VMPA_H */ |