/* 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 . */ #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