diff options
34 files changed, 1763 insertions, 1560 deletions
@@ -1,3 +1,73 @@ +10-12-20 Cyrille Bagard <nocbos@gmail.com> + + * configure.ac: + Add the new Makefile 'src/analysis/disass' directoriy to AC_CONFIG_FILES. + + * src/analysis/binary.c: + Begin to clean the code by moving the disassembling process into disass/. + + * src/analysis/binary.h: + Add a function to provide the buffer of disassembled instructions. + + * src/analysis/decomp/decompiler.c: + Make a better prologue. + + * src/analysis/disass/disassembler.c: + * src/analysis/disass/disassembler.h: + * src/analysis/disass/fetch.c: + * src/analysis/disass/fetch.h: + * src/analysis/disass/links.c: + * src/analysis/disass/links.h: + * src/analysis/disass/Makefile.am: + * src/analysis/disass/output.c: + * src/analysis/disass/output.h: + New entries: move the disassembling process into several parts here. + + * src/analysis/Makefile.am: + Add 'disass/libanalysisdisass.la' to libanalysis_la_LIBADD + and 'disass' to SUBDIRS. + + * src/arch/archbase.h: + Define VMPA_MAX. + + * src/arch/instruction.c: + * src/arch/instruction.h: + * src/arch/instruction-int.h: + Register links between instructions. + + * src/decomp/lang/asm.c: + * src/decomp/lang/asm.h: + New entries: produce assembly output. + + * src/decomp/lang/java.c: + Introduce long comments. + + * src/decomp/lang/Makefile.am: + Add asm.[ch] to libdecomplang_la_SOURCES. + + * src/decomp/output.c: + * src/decomp/output.h: + * src/decomp/output-int.h: + Introduce long comments. + + * src/glibext/delayed.c: + * src/glibext/delayed.h: + * src/glibext/delayed-int.h: + Wait for the completion of a delayed work. + + * src/gtkext/gtkblockview.c: + * src/gtkext/gtkblockview.h: + Make the block view inheriting of the buffered view. + + * src/gtkext/gtkgraphview.c: + Disable the graphic view. + + * src/gtkext/gtksourceview.c: + Typo. + + * src/project.c: + Update call to gtk_block_view_new(). + 10-12-12 Cyrille Bagard <nocbos@gmail.com> * configure.ac: diff --git a/configure.ac b/configure.ac index f456684..d03d8fe 100644 --- a/configure.ac +++ b/configure.ac @@ -243,6 +243,7 @@ AC_CONFIG_FILES([Makefile src/Makefile src/analysis/Makefile src/analysis/decomp/Makefile + src/analysis/disass/Makefile src/arch/Makefile src/arch/arm/Makefile src/arch/dalvik/Makefile diff --git a/src/analysis/Makefile.am b/src/analysis/Makefile.am index 604835d..e59b648 100755 --- a/src/analysis/Makefile.am +++ b/src/analysis/Makefile.am @@ -16,7 +16,8 @@ libanalysis_la_SOURCES = \ variable.h variable.c libanalysis_la_LIBADD = \ - decomp/libanalysisdecomp.la + decomp/libanalysisdecomp.la \ + disass/libanalysisdisass.la libanalysis_la_LDFLAGS = @@ -27,4 +28,4 @@ AM_CPPFLAGS = AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) -SUBDIRS = decomp +SUBDIRS = decomp disass diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 4093f6e..f13a887 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -41,10 +41,11 @@ #include "line_comment.h" /* TODO : supprimer ? */ #include "line_prologue.h" #include "routine.h" +#include "decomp/decompiler.h" +#include "disass/disassembler.h" #include "../common/cpp.h" #include "../common/extstr.h" #include "../debug/break.h" -#include "../glibext/delayed-int.h" #include "../format/format.h" #include "../panels/log.h" #include "../plugins/pglist.h" @@ -59,56 +60,8 @@ /* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */ -#define G_TYPE_DELAYED_DISASSEMBLY g_delayed_disassembly_get_type() -#define G_DELAYED_DISASSEMBLY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_disassembly_get_type(), GDelayedDisassembly)) -#define G_IS_DELAYED_DISASSEMBLY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_disassembly_get_type())) -#define G_DELAYED_DISASSEMBLY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass)) -#define G_IS_DELAYED_DISASSEMBLY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_DISASSEMBLY)) -#define G_DELAYED_DISASSEMBLY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass)) - - -/* Ensembles binaires à désassembler (instance) */ -typedef struct _GDelayedDisassembly -{ - GDelayedWork parent; /* A laisser en premier */ - - GOpenidaBinary *binary; /* Destinataire final */ - - GBinPart **parts; /* Parties binaires à traiter */ - size_t count; /* Nombre de ces parties */ - - GRenderingLine *lines; /* Lignes de rendu résultantes */ - -} GDelayedDisassembly; - -/* Ensembles binaires à désassembler (classe) */ -typedef struct _GDelayedDisassemblyClass -{ - GDelayedWorkClass parent; /* A laisser en premier */ - -} GDelayedDisassemblyClass; - - -/* Indique le type défini pour les tâches de désassemblage différé. */ -static GType g_delayed_disassembly_get_type(void); - -/* Initialise la classe des tâches de désassemblage différé. */ -static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *); - -/* Initialise une tâche de désassemblage différé. */ -static void g_delayed_disassembly_init(GDelayedDisassembly *); - -/* Crée une tâche de désassemblage différé. */ -static GDelayedDisassembly *g_delayed_disassembly_new(GOpenidaBinary *, GBinPart **, size_t); - -/* Assure le désassemblage en différé. */ -static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkExtStatusBar *); - -/* Procède au désassemblage basique d'un contenu binaire. */ -static GRenderingLine *disassemble_binary_parts(GDelayedDisassembly *, GBinRoutine **, size_t, GtkExtStatusBar *, guint); +#if 0 -/* Etablit les liens entres les différentes lignes de code. */ -static void establish_links_between_lines(GRenderingLine *, GBinRoutine **, size_t, GtkExtStatusBar *, guint); /* S'assure que toutes les routines ont une taille définie. */ static void limit_all_routines(GRenderingLine *, GBinRoutine **, size_t, GtkExtStatusBar *, guint); @@ -118,6 +71,7 @@ static vmpa_t find_best_ending_address_for_routine(GRenderingLine *, size_t, con +#endif @@ -142,6 +96,7 @@ struct _GOpenidaBinary GRenderingLine *lines; /* Lignes de rendu en place */ GRenderingOptions *options; /* Options de désassemblage */ + GCodeBuffer *disass_buffer; /* Instructions lisibles */ GCodeBuffer **dec_buffers; /* Sources sous forme de texte */ size_t decbuf_count; /* Taille des tableaux */ size_t defsrc; /* Fichier source principal */ @@ -173,11 +128,8 @@ static void g_openida_binary_init(GOpenidaBinary *); /* Charge en mémoire le contenu d'un fichier. */ bin_t *map_binary_file(const char *, off_t *); -/* Construit la description d'introduction du désassemblage. */ -GRenderingLine *build_binary_prologue(const char *, const uint8_t *, off_t); - /* Acquitte la fin d'un désasemblage différé et complet. */ -void ack_completed_disassembly(GDelayedDisassembly *, GOpenidaBinary *); +void ack_completed_disassembly(void/*GDelayedDisassembly*/ *, GOpenidaBinary *); @@ -193,361 +145,9 @@ static void g_openida_binary_breakpoint_added(GBreakGroup *, GBreakPoint *, GOpe static void g_openida_binary_breakpoint_removed(GBreakGroup *, GBreakPoint *, GOpenidaBinary *); - -/* ---------------------------------------------------------------------------------- */ -/* DESASSEMBLAGE DE BINAIRE DIFFERE */ -/* ---------------------------------------------------------------------------------- */ - - -/* Indique le type défini pour les tâches de désassemblage différé. */ -G_DEFINE_TYPE(GDelayedDisassembly, g_delayed_disassembly, G_TYPE_DELAYED_WORK); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des tâches de désassemblage différé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *klass) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : disass = instance à initialiser. * -* * -* Description : Initialise une tâche de désassemblage différé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_delayed_disassembly_init(GDelayedDisassembly *disass) -{ - G_DELAYED_WORK(disass)->run = (run_task_fc)g_delayed_disassembly_process; - -} - - -/****************************************************************************** -* * -* Paramètres : binary = binaire chargé en attente des résultats. * -* parts = parties binaires à désassembler. * -* count = nombre de parties à traiter. * -* * -* Description : Crée une tâche de désassemblage différé. * -* * -* Retour : Tâche créée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GDelayedDisassembly *g_delayed_disassembly_new(GOpenidaBinary *binary, GBinPart **parts, size_t count) -{ - GDelayedDisassembly *result; /* Tâche à retourner */ - - result = g_object_new(G_TYPE_DELAYED_DISASSEMBLY, NULL); - - result->binary = binary; - - result->parts = parts; - result->count = count; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : disass = analyse à mener. * -* statusbar = barre de statut à tenir informée. * -* * -* Description : Assure le désassemblage en différé. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar) -{ - GBinRoutine **routines; /* Liste des routines trouvées */ - size_t routines_count; /* Nombre de ces routines */ - guint id; /* Identifiant de statut */ - - routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->binary->format), &routines_count); - qsort(routines, routines_count, sizeof(GBinRoutine *), g_binary_routine_rcompare); - - /* Première étape */ - - id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true); - - disass->lines = disassemble_binary_parts(disass, routines, routines_count, statusbar, id); - - gtk_extended_status_bar_remove(statusbar, id); - - /* Seconde étape */ - - id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true); - - establish_links_between_lines(disass->lines, routines, routines_count, statusbar, id); - - gtk_extended_status_bar_remove(statusbar, id); - - /* Troisième étape */ - - id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true); - - limit_all_routines(disass->lines, routines, routines_count, statusbar, id); - - gtk_extended_status_bar_remove(statusbar, id); - -} - - -/****************************************************************************** -* * -* Paramètres : disass = tâche à l'origine du traitement. * -* routines = prototypes existants à insérer. * -* count = quantité de ces prototypes. * -* statusbar = barre de statut avec progression à mettre à jour.* -* id = identifiant du message affiché à l'utilisateur. * -* * -* Description : Procède au désassemblage basique d'un contenu binaire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GRenderingLine *disassemble_binary_parts(GDelayedDisassembly *disass, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id) -{ - GRenderingLine *result; /* Ligne de rendu à retourner */ - GArchInstruction *first; /* Première instruction vue */ - GArchProcessor *proc; /* Architecture du binaire */ - GRenderingOptions *options; /* Options de désassemblage */ - bin_t *bin_data; /* Données binaires à lire */ - size_t i; /* Boucle de parcours #1 */ - off_t sum; /* Somme de toutes les tailles */ - off_t done; /* Quantité déjà traitée */ - off_t pos; /* Début d'une zone binaire */ - off_t len; /* Taille de cette même zone */ - vmpa_t base; /* Adresse de la zone binaire */ - off_t start; /* Conservation du pt de départ*/ - vmpa_t addr; /* Adresse d'une instruction */ - GArchInstruction *instr; /* Instruction décodée */ - GRenderingLine *line; /* Nouvelle ligne de rendu */ - size_t k; /* Boucle de parcours #2 */ - uint64_t routine_offset; /* Point de départ de routine */ - char *routine_desc; /* Prototype d'une routine */ - - result = NULL; - - first = NULL; - - proc = get_arch_processor_from_format(g_openida_binary_get_format(disass->binary)); - options = g_openida_binary_get_options(disass->binary); - bin_data = g_openida_binary_get_data(disass->binary, NULL); - - /* Préparation du suivi de la progression */ - - sum = 0; - - for (i = 0; i < disass->count; i++) - { - g_binary_part_get_values(disass->parts[i], NULL, &len, NULL); - if (len > disass->binary->bin_length) continue; - sum += len; - } - - done = 0; - - k = 0; - - for (i = 0; i < disass->count; i++) - { - g_binary_part_get_values(disass->parts[i], &pos, &len, &base); - - if (len > disass->binary->bin_length) continue; - - /* Décodage des instructions */ - - start = pos; - pos = 0; - - while (pos < len) - { - addr = base + pos; - - instr = g_arch_processor_decode_instruction(proc, &bin_data[start], - &pos, len, start, addr); - g_arch_instruction_add_to_list(&first, instr); - - line = g_code_line_new(addr, instr, options); - g_rendering_line_add_to_lines(&result, line); - - /* Ajout des prototypes de fonctions */ - - for (; k < count; k++) - { - routine_offset = g_binary_routine_get_address(routines[k]); - - if (routine_offset > addr) break; - - routine_desc = g_binary_routine_to_string(routines[k]); - - line = g_comment_line_new(routine_offset, routine_desc, options); - g_rendering_line_insert_into_lines(&result, line, true); - - free(routine_desc); - - } - - if (pos < len) - gtk_extended_status_bar_update_activity(statusbar, id, (done + pos) * 1.0 / sum); - - } - - done += len; - gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum); #if 0 - /* Ajout des prototypes de fonctions */ - - printf("BASE == 0x%08llx\n", base); - - for (; k < count; k++) - { - routine_offset = g_binary_routine_get_address(routines[k]); - - if (!(base <= routine_offset && routine_offset < (base + len))) continue; - routine_desc = g_binary_routine_to_string(routines[k]); - line = g_comment_line_new(routine_offset, routine_desc, options); - g_rendering_line_insert_into_lines(&result, line, true); - - free(routine_desc); - - } -#endif - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : lines = lignes de rendu à relier. * -* routines = prototypes existants à insérer. * -* count = quantité de ces prototypes. * -* statusbar = barre de statut avec progression à mettre à jour.* -* id = identifiant du message affiché à l'utilisateur. * -* * -* Description : Etablit les liens entres les différentes lignes de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void establish_links_between_lines(GRenderingLine *lines, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id) -{ - size_t i; /* Boucle de parcours */ - vmpa_t start; /* Adresse de départ */ - vmpa_t end; /* Adresse de fin */ - GRenderingLine *iter; /* Boucle de parcours */ - GArchInstruction *instr; /* Instruction à ausculter */ - vmpa_t addr; /* Adresse référencée */ - InstructionLinkType type; /* Type de référence */ - GRenderingLine *target; /* Ligne visée par la référence*/ - - for (i = 0; i < count; i++) - { - start = g_binary_routine_get_address(routines[i]); - end = start + g_binary_routine_get_size(routines[i]); - - for (iter = g_rendering_line_find_by_address(lines, NULL, start); - iter != NULL; - iter = g_rendering_line_get_next_iter(lines, iter, NULL)) - { - /* Si on sort de la zone... */ - if (get_rendering_line_address(iter) >= end) break; - - /* On ne traite que du code ici ! */ - if (!G_IS_CODE_LINE(iter)) continue; - - instr = g_code_line_get_instruction(G_CODE_LINE(iter)); - type = g_arch_instruction_get_link(instr, &addr); - - switch (type) - { - case ILT_NONE: - break; - - case ILT_JUMP: - - target = g_rendering_line_find_by_address(lines, NULL, addr); - - if (target != NULL) - g_rendering_line_link_with(iter, target, type); - - break; - - case ILT_JUMP_IF_FALSE: - break; - - case ILT_JUMP_IF_TRUE: - - target = g_rendering_line_find_by_address(lines, NULL, addr); - - if (target != NULL) - { - g_rendering_line_link_with(iter, target, type); - - target = g_rendering_line_get_next_iter(lines, iter, NULL); - if (target != NULL) - g_rendering_line_link_with(iter, target, ILT_JUMP_IF_FALSE); - - } - - break; - - case ILT_CALL: - - target = g_rendering_line_find_by_address(lines, NULL, addr); - - if (target != NULL) - g_rendering_line_link_with(iter, target, type); - - break; - - } - - } - - gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count); - - } - -} /****************************************************************************** @@ -696,7 +296,7 @@ static vmpa_t find_best_ending_address_for_routine(GRenderingLine *line, size_t } - +#endif @@ -806,7 +406,7 @@ GOpenidaBinary *g_openida_binary_new_from_file(const char *filename) break; } - result->lines = build_binary_prologue(filename, result->bin_data, result->bin_length); + result->lines = NULL; result->proc = get_arch_processor_from_format(result->format); @@ -1148,13 +748,8 @@ GBinPart ***g_openida_binary_get_parts(const GOpenidaBinary *binary, BinaryPartM void g_openida_binary_analyse(GOpenidaBinary *binary) { - GWorkQueue *queue; /* Gestionnaire de différés */ GBinPart **parts; /* Parties d'élément binaire */ size_t parts_count; /* Nombre de ces parties */ - GDelayedDisassembly *disass; /* Désassemblage à mener */ - - queue = get_work_queue(); - if (binary->parts_count[BPM_ROUTINES] > 0) binary->model = BPM_ROUTINES; @@ -1179,12 +774,10 @@ void g_openida_binary_analyse(GOpenidaBinary *binary) } } - disass = g_delayed_disassembly_new(binary, parts, parts_count); + binary->disass_buffer = disassemble_binary(binary, parts, parts_count); - g_signal_connect(disass, "work-completed", - G_CALLBACK(ack_completed_disassembly), binary); - - g_work_queue_schedule_work(queue, G_DELAYED_WORK(disass)); + /* TODO : remme ! */ + ack_completed_disassembly(NULL, binary); } @@ -1363,6 +956,25 @@ GArchInstruction *g_openida_binary_get_instructions(const GOpenidaBinary *binary /****************************************************************************** * * * Paramètres : binary = élément binaire à consulter. * +* * +* Description : Fournit le tampon associé au contenu assembleur d'un binaire.* +* * +* Retour : Tampon mis en place ou NULL si aucun (!). * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCodeBuffer *g_openida_binary_get_disassembled_buffer(const GOpenidaBinary *binary) +{ + return binary->disass_buffer; + +} + + +/****************************************************************************** +* * +* Paramètres : binary = élément binaire à consulter. * * index = indice du fichier à retrouver. * * * * Description : Fournit le tampon associé au contenu d'un fichier source. * @@ -1443,82 +1055,6 @@ bin_t *map_binary_file(const char *filename, off_t *length) /****************************************************************************** * * -* Paramètres : filename = nom du fichier chargé. * -* data = données en mémoire pour l'empreinte. * -* length = quantité de données à prendre en compte. * -* * -* Description : Construit la description d'introduction du désassemblage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -GRenderingLine *build_binary_prologue(const char *filename, const uint8_t *data, off_t length) -{ - GRenderingLine *result; /* Contenu à renvoyer */ - size_t len; /* Taille du texte */ - char *content; /* Contenu textuel d'une ligne */ - GRenderingLine *line; /* Représentation à ajouter */ - GChecksum *checksum; /* Calcul de l'empreinte */ - const gchar *hex; /* Valeur hexadécimale du SHA */ - - result = NULL;/* FIXME DL_LIST_HEAD_INIT( **/ - - line = g_prologue_line_new(_("Disassembly generated by OpenIDA")); - g_rendering_line_add_to_lines(&result, line); - - line = g_prologue_line_new("OpenIDA is free software - © 2008-2010 Cyrille Bagard"); - g_rendering_line_add_to_lines(&result, line); - - line = g_prologue_line_new(""); - g_rendering_line_add_to_lines(&result, line); - - /* Fichier */ - - len = strlen(_("File: ")) + strlen(filename); - content = (char *)calloc(len + 1, sizeof(char)); - - snprintf(content, len + 1, "%s%s", _("File: "), filename); - - line = g_prologue_line_new(content); - g_rendering_line_add_to_lines(&result, line); - - free(content); - - /* Checksum SHA256 */ - - checksum = g_checksum_new(G_CHECKSUM_SHA256); - - g_checksum_update(checksum, data, length); - hex = g_checksum_get_string(checksum); - - len = strlen(_("Sha256: ")) + strlen(hex); - content = (char *)calloc(len + 1, sizeof(char)); - - snprintf(content, len + 1, "%s%s", _("Sha256: "), hex); - - g_checksum_free(checksum); - - line = g_prologue_line_new(content); - g_rendering_line_add_to_lines(&result, line); - - free(content); - - line = g_prologue_line_new(""); - g_rendering_line_add_to_lines(&result, line); - - line = g_prologue_line_new(""); - g_rendering_line_add_to_lines(&result, line); - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : disass = travail de désassemblage mené à bien. * * binary = représentation de binaire à l'origine de l'opérat°. * * * @@ -1530,7 +1066,7 @@ GRenderingLine *build_binary_prologue(const char *filename, const uint8_t *data, * * ******************************************************************************/ -void ack_completed_disassembly(GDelayedDisassembly *disass, GOpenidaBinary *binary) +void ack_completed_disassembly(void/*GDelayedDisassembly*/ *disass, GOpenidaBinary *binary) { GRenderingLine *line; /* "Première" ligne de rendu */ GPluginModule **pglist; /* Liste de greffons */ @@ -1556,7 +1092,7 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GOpenidaBinary *bina - +#if 0 g_rendering_line_merge(&binary->lines, &disass->lines); @@ -1580,6 +1116,7 @@ void ack_completed_disassembly(GDelayedDisassembly *disass, GOpenidaBinary *bina } /* On réintègre le flot premier */ +#endif g_signal_emit_by_name(binary, "disassembly-done"); diff --git a/src/analysis/binary.h b/src/analysis/binary.h index cac3b86..1de0970 100644 --- a/src/analysis/binary.h +++ b/src/analysis/binary.h @@ -109,6 +109,9 @@ GRenderingLine *g_openida_binary_get_lines(const GOpenidaBinary *); /* Fournit les instructions issues du désassemblage. */ GArchInstruction *g_openida_binary_get_instructions(const GOpenidaBinary *); +/* Fournit le tampon associé au contenu assembleur d'un binaire. */ +GCodeBuffer *g_openida_binary_get_disassembled_buffer(const GOpenidaBinary *); + /* Fournit le tampon associé au contenu d'un fichier source. */ GCodeBuffer *g_openida_binary_get_decompiled_buffer(const GOpenidaBinary *, size_t); diff --git a/src/analysis/decomp/decompiler.c b/src/analysis/decomp/decompiler.c index c446c0e..de1b6d2 100644 --- a/src/analysis/decomp/decompiler.c +++ b/src/analysis/decomp/decompiler.c @@ -1,6 +1,6 @@ /* OpenIDA - Outil d'analyse de fichiers binaires - * decompiler.h - prototypes pour l'encadrement des phases de décompilation + * decompiler.c - encadrement des phases de décompilation * * Copyright (C) 2010 Cyrille Bagard * @@ -68,17 +68,20 @@ static void build_decomp_prologue(GCodeBuffer *buffer, const char *filename) output = g_java_output_new(); + line = g_lang_output_start_comments(output, buffer); + if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS); + /* Introduction */ - line = g_lang_output_write_comments(output, buffer, - SL(_("Binary data decompiled by OpenIDA"))); + line = g_lang_output_continue_comments(output, buffer, + SL(_("Binary data decompiled by OpenIDA"))); g_buffer_line_start_merge_at(line, BLC_ADDRESS); - line = g_lang_output_write_comments(output, buffer, - SL(_("OpenIDA is free software - © 2008-2010 Cyrille Bagard"))); + line = g_lang_output_continue_comments(output, buffer, + SL(_("OpenIDA is free software - © 2008-2010 Cyrille Bagard"))); g_buffer_line_start_merge_at(line, BLC_ADDRESS); - line = g_lang_output_write_comments(output, buffer, NULL, 0); + line = g_lang_output_continue_comments(output, buffer, NULL, 0); g_buffer_line_start_merge_at(line, BLC_ADDRESS); /* Fichier */ @@ -91,18 +94,22 @@ static void build_decomp_prologue(GCodeBuffer *buffer, const char *filename) snprintf(content, len, "%s%s", _("File: "), filename); - line = g_lang_output_write_comments(output, buffer, content, len - 1); + line = g_lang_output_continue_comments(output, buffer, content, len - 1); g_buffer_line_start_merge_at(line, BLC_ADDRESS); free(content); - /* Lignes de séparation */ + /* Ligne de séparation */ - line = g_lang_output_write_comments(output, buffer, NULL, 0); + line = g_lang_output_continue_comments(output, buffer, NULL, 0); g_buffer_line_start_merge_at(line, BLC_ADDRESS); - line = g_lang_output_write_comments(output, buffer, NULL, 0); - g_buffer_line_start_merge_at(line, BLC_ADDRESS); + /* Conclusion */ + + line = g_lang_output_end_comments(output, buffer); + if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + g_object_unref(G_OBJECT(output)); } diff --git a/src/analysis/disass/Makefile.am b/src/analysis/disass/Makefile.am new file mode 100644 index 0000000..784731a --- /dev/null +++ b/src/analysis/disass/Makefile.am @@ -0,0 +1,17 @@ + +noinst_LTLIBRARIES = libanalysisdisass.la + +libanalysisdisass_la_SOURCES = \ + disassembler.h disassembler.c \ + fetch.h fetch.c \ + links.h links.c \ + output.h output.c + +libanalysisdisass_la_LDFLAGS = + + +INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) + +AM_CPPFLAGS = + +AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c new file mode 100644 index 0000000..4004de9 --- /dev/null +++ b/src/analysis/disass/disassembler.c @@ -0,0 +1,374 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * disassembler.c - encadrement des phases de désassemblage + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "disassembler.h" + + +#include <malloc.h> +#include <stdio.h> +#include <string.h> + + +#include <i18n.h> + + +#include "fetch.h" +#include "links.h" +#include "output.h" +#include "../../decomp/lang/asm.h" +#include "../../format/format.h" +#include "../../glibext/delayed-int.h" + + + +/* ------------------------ DESASSEMBLAGE DE BINAIRE DIFFERE ------------------------ */ + + +#define G_TYPE_DELAYED_DISASSEMBLY g_delayed_disassembly_get_type() +#define G_DELAYED_DISASSEMBLY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_disassembly_get_type(), GDelayedDisassembly)) +#define G_IS_DELAYED_DISASSEMBLY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_disassembly_get_type())) +#define G_DELAYED_DISASSEMBLY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass)) +#define G_IS_DELAYED_DISASSEMBLY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_DISASSEMBLY)) +#define G_DELAYED_DISASSEMBLY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_DISASSEMBLY, GDelayedDisassemblyClass)) + + +/* Ensembles binaires à désassembler (instance) */ +typedef struct _GDelayedDisassembly +{ + GDelayedWork parent; /* A laisser en premier */ + + const GOpenidaBinary *binary; /* Destinataire final */ + const GBinFormat *format; /* Format du binaire représenté*/ + + GBinPart **parts; /* Parties binaires à traiter */ + size_t count; /* Nombre de ces parties */ + + GArchInstruction *instrs; /* Instructions résultantes */ + GCodeBuffer *buffer; /* Tampon pour le rendu */ + +} GDelayedDisassembly; + +/* Ensembles binaires à désassembler (classe) */ +typedef struct _GDelayedDisassemblyClass +{ + GDelayedWorkClass parent; /* A laisser en premier */ + +} GDelayedDisassemblyClass; + + +/* Indique le type défini pour les tâches de désassemblage différé. */ +static GType g_delayed_disassembly_get_type(void); + +/* Initialise la classe des tâches de désassemblage différé. */ +static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *); + +/* Initialise une tâche de désassemblage différé. */ +static void g_delayed_disassembly_init(GDelayedDisassembly *); + +/* Crée une tâche de désassemblage différé. */ +static GDelayedDisassembly *g_delayed_disassembly_new(const GOpenidaBinary *, GBinPart **, size_t, GCodeBuffer *); + +/* Assure le désassemblage en différé. */ +static void g_delayed_disassembly_process(GDelayedDisassembly *, GtkExtStatusBar *); + + + +/* -------------------------- GESTION GLOBALE DE PROCEDURE -------------------------- */ + +/* Construit la description d'introduction du désassemblage. */ +static void build_disass_prologue(GCodeBuffer *, const char *, const uint8_t *, off_t); + + + +/* ---------------------------------------------------------------------------------- */ +/* DESASSEMBLAGE DE BINAIRE DIFFERE */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour les tâches de désassemblage différé. */ +G_DEFINE_TYPE(GDelayedDisassembly, g_delayed_disassembly, G_TYPE_DELAYED_WORK); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des tâches de désassemblage différé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_disassembly_class_init(GDelayedDisassemblyClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : disass = instance à initialiser. * +* * +* Description : Initialise une tâche de désassemblage différé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_disassembly_init(GDelayedDisassembly *disass) +{ + G_DELAYED_WORK(disass)->run = (run_task_fc)g_delayed_disassembly_process; + +} + + +/****************************************************************************** +* * +* Paramètres : binary = binaire chargé en attente des résultats. * +* format = format du binaire représenté. * +* parts = parties binaires à désassembler. * +* count = nombre de parties à traiter. * +* buffer = tampon de sortie pour les instructions. * +* * +* Description : Crée une tâche de désassemblage différé. * +* * +* Retour : Tâche créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GDelayedDisassembly *g_delayed_disassembly_new(const GOpenidaBinary *binary, GBinPart **parts, size_t count, GCodeBuffer *buffer) +{ + GDelayedDisassembly *result; /* Tâche à retourner */ + + result = g_object_new(G_TYPE_DELAYED_DISASSEMBLY, NULL); + + result->binary = binary; + result->format = G_BIN_FORMAT(g_openida_binary_get_format(binary)); + + result->parts = parts; + result->count = count; + + result->buffer = buffer; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : disass = analyse à mener. * +* statusbar = barre de statut à tenir informée. * +* * +* Description : Assure le désassemblage en différé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtStatusBar *statusbar) +{ + GBinRoutine **routines; /* Liste des routines trouvées */ + size_t routines_count; /* Nombre de ces routines */ + guint id; /* Identifiant de statut */ + + routines = g_binary_format_get_routines(disass->format, &routines_count); + qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare); + + /* Première étape */ + + id = gtk_extended_status_bar_push(statusbar, _("Disassembling..."), true); + + disass->instrs = disassemble_binary_parts(disass->binary, disass->parts, disass->count, + statusbar, id); + + gtk_extended_status_bar_remove(statusbar, id); + + /* Seconde étape */ + + id = gtk_extended_status_bar_push(statusbar, _("Establishing links..."), true); + + establish_links_between_lines(disass->instrs, routines, routines_count, statusbar, id); + + gtk_extended_status_bar_remove(statusbar, id); +#if 0 + /* Troisième étape */ + + id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true); + + limit_all_routines(disass->lines, routines, routines_count, statusbar, id); + + gtk_extended_status_bar_remove(statusbar, id); +#endif + /* Quatrième étape */ + + id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true); + + print_disassembled_instructions(disass->buffer, disass->instrs, routines, routines_count); + + gtk_extended_status_bar_remove(statusbar, id); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION GLOBALE DE PROCEDURE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : buffer = tampon de destination pour le texte. * +* filename = nom du fichier ciblé à décompiler. * +* data = données en mémoire pour l'empreinte. * +* length = quantité de données à prendre en compte. * +* * +* Description : Construit la description d'introduction du désassemblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, const uint8_t *data, off_t length) +{ + GLangOutput *output; /* Modèle de sortie adéquat */ + GBufferLine *line; /* Ligne de destination */ + size_t len; /* Taille du texte */ + char *content; /* Contenu textuel d'une ligne */ + GChecksum *checksum; /* Calcul de l'empreinte */ + const gchar *hex; /* Valeur hexadécimale du SHA */ + + output = g_asm_output_new(); + + line = g_lang_output_start_comments(output, buffer); + if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + /* Introduction */ + + line = g_lang_output_continue_comments(output, buffer, + SL(_("Disassembly generated by OpenIDA"))); + g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + line = g_lang_output_continue_comments(output, buffer, + SL(_("OpenIDA is free software - © 2008-2010 Cyrille Bagard"))); + g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + line = g_lang_output_continue_comments(output, buffer, NULL, 0); + g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + /* Fichier */ + + len = strlen(_("File: ")) + strlen(filename) + 1; + content = (char *)calloc(len, sizeof(char)); + + snprintf(content, len, "%s%s", _("File: "), filename); + + line = g_lang_output_continue_comments(output, buffer, content, len - 1); + g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + free(content); + + /* Checksum SHA256 */ + + checksum = g_checksum_new(G_CHECKSUM_SHA256); + + g_checksum_update(checksum, data, length); + hex = g_checksum_get_string(checksum); + + len = strlen(_("Sha256: ")) + strlen(hex); + content = (char *)calloc(len + 1, sizeof(char)); + + snprintf(content, len + 1, "%s%s", _("Sha256: "), hex); + + g_checksum_free(checksum); + + line = g_lang_output_continue_comments(output, buffer, content, len - 1); + g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + free(content); + + /* Ligne de séparation */ + + line = g_lang_output_continue_comments(output, buffer, NULL, 0); + g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + /* Conclusion */ + + line = g_lang_output_end_comments(output, buffer); + if (line != NULL) g_buffer_line_start_merge_at(line, BLC_ADDRESS); + + g_object_unref(G_OBJECT(output)); + +} + + +/****************************************************************************** +* * +* Paramètres : binary = représentation de binaire chargé. * +* parts = parties binaires à désassembler. * +* count = nombre de parties à traiter. * +* * +* Description : Procède au désassemblage d'un contenu binaire donné. * +* * +* Retour : Tampon de code mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCodeBuffer *disassemble_binary(const GOpenidaBinary *binary, GBinPart **parts, size_t parts_count) +{ + GCodeBuffer *result; /* Tampon constitué à renvoyer */ + const uint8_t *data; /* Données binaires brutes */ + off_t length; /* Quantité de ces données */ + GDelayedDisassembly *disass; /* Désassemblage à mener */ + GWorkQueue *queue; /* Gestionnaire de différés */ + + result = g_code_buffer_new(); + + data = g_openida_binary_get_data(binary, &length); + build_disass_prologue(result, g_openida_binary_get_filename(binary), data, length); + + disass = g_delayed_disassembly_new(binary, parts, parts_count, result); + + queue = get_work_queue(); + g_work_queue_schedule_work(queue, G_DELAYED_WORK(disass)); + + g_delayed_work_wait_for_completion(G_DELAYED_WORK(disass)); + + g_object_unref(G_OBJECT(disass)); + + return result; + +} diff --git a/src/analysis/disass/disassembler.h b/src/analysis/disass/disassembler.h new file mode 100644 index 0000000..7cfdcc5 --- /dev/null +++ b/src/analysis/disass/disassembler.h @@ -0,0 +1,38 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * disassembler.h - prototypes pour l'encadrement des phases de désassemblage + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DISASS_DISASSEMBLER_H +#define _ANALYSIS_DISASS_DISASSEMBLER_H + + +#include "../binary.h" +#include "../../format/part.h" + + + +/* Procède à la décompilation des routines d'un fichier donné. */ +GCodeBuffer *disassemble_binary(const GOpenidaBinary *, GBinPart **parts, size_t parts_count); + + + +#endif /* _ANALYSIS_DISASS_DISASSEMBLER_H */ diff --git a/src/analysis/disass/fetch.c b/src/analysis/disass/fetch.c new file mode 100644 index 0000000..575eb06 --- /dev/null +++ b/src/analysis/disass/fetch.c @@ -0,0 +1,109 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * fetch.c - récupération d'instructions à partir de binaire brut + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "fetch.h" + + + +/****************************************************************************** +* * +* Paramètres : binary = représentation de binaire chargé. * +* parts = parties binaires à désassembler. * +* count = nombre de parties à traiter. * +* statusbar = barre de statut avec progression à mettre à jour.* +* id = identifiant du message affiché à l'utilisateur. * +* * +* Description : Procède au désassemblage basique d'un contenu binaire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *disassemble_binary_parts(const GOpenidaBinary *binary, GBinPart **parts, size_t count, GtkExtStatusBar *statusbar, guint id) +{ + GArchInstruction *result; /* Liste d'instr. à renvoyer */ + GArchProcessor *proc; /* Architecture du binaire */ + off_t bin_length; /* Taille des données à lire */ + bin_t *bin_data; /* Données binaires à lire */ + size_t i; /* Boucle de parcours #1 */ + off_t sum; /* Somme de toutes les tailles */ + off_t done; /* Quantité déjà traitée */ + off_t pos; /* Début d'une zone binaire */ + off_t len; /* Taille de cette même zone */ + vmpa_t base; /* Adresse de la zone binaire */ + off_t start; /* Conservation du pt de départ*/ + vmpa_t addr; /* Adresse d'une instruction */ + GArchInstruction *instr; /* Instruction décodée */ + + result = NULL; + + proc = get_arch_processor_from_format(g_openida_binary_get_format(binary)); + bin_data = g_openida_binary_get_data(binary, &bin_length); + + /* Préparation du suivi de la progression */ + + sum = 0; + + for (i = 0; i < count; i++) + { + g_binary_part_get_values(parts[i], NULL, &len, NULL); + if (len > bin_length) continue; + sum += len; + } + + done = 0; + + for (i = 0; i < count; i++) + { + g_binary_part_get_values(parts[i], &pos, &len, &base); + + if (len > bin_length) continue; + + /* Décodage des instructions */ + + start = pos; + pos = 0; + + while (pos < len) + { + addr = base + pos; + + instr = g_arch_processor_decode_instruction(proc, &bin_data[start], + &pos, len, start, addr); + g_arch_instruction_add_to_list(&result, instr); + + if (pos < len) + gtk_extended_status_bar_update_activity(statusbar, id, (done + pos) * 1.0 / sum); + + } + + done += len; + gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / sum); + + } + + return result; + +} diff --git a/src/analysis/disass/fetch.h b/src/analysis/disass/fetch.h new file mode 100644 index 0000000..09bb584 --- /dev/null +++ b/src/analysis/disass/fetch.h @@ -0,0 +1,38 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * fetch.h - prototypes pour la récupération d'instructions à partir de binaire brut + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DISASS_INSTR_H +#define _ANALYSIS_DISASS_INSTR_H + + +#include "../binary.h" +#include "../../format/part.h" +#include "../../gtkext/gtkextstatusbar.h" + + +/* Procède au désassemblage basique d'un contenu binaire. */ +GArchInstruction *disassemble_binary_parts(const GOpenidaBinary *, GBinPart **, size_t, GtkExtStatusBar *, guint); + + + +#endif /* _ANALYSIS_DISASS_INSTR_H */ diff --git a/src/analysis/disass/links.c b/src/analysis/disass/links.c new file mode 100644 index 0000000..4d799fc --- /dev/null +++ b/src/analysis/disass/links.c @@ -0,0 +1,115 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * links.c - résolution des liens entre différentes instructions + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "links.h" + + + +/****************************************************************************** +* * +* Paramètres : list = ensemble d'instructions à relier. * +* routines = prototypes existants à insérer. * +* count = quantité de ces prototypes. * +* statusbar = barre de statut avec progression à mettre à jour.* +* id = identifiant du message affiché à l'utilisateur. * +* * +* Description : Etablit les liens entres les différentes lignes de code. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void establish_links_between_lines(GArchInstruction *list, GBinRoutine **routines, size_t count, GtkExtStatusBar *statusbar, guint id) +{ + size_t i; /* Boucle de parcours */ + vmpa_t start; /* Adresse de départ */ + vmpa_t end; /* Adresse de fin */ + GArchInstruction *iter; /* Boucle de parcours */ + vmpa_t addr; /* Adresse référencée */ + InstructionLinkType type; /* Type de référence */ + GArchInstruction *target; /* Ligne visée par la référence*/ + + for (i = 0; i < count; i++) + { + start = g_binary_routine_get_address(routines[i]); + end = start + g_binary_routine_get_size(routines[i]); + + for (iter = g_arch_instruction_find_by_address(list, start, true); + iter != NULL; + iter = g_arch_instruction_get_next_iter(list, iter, end)) + { + type = g_arch_instruction_get_link(iter, &addr); + + switch (type) + { + case ILT_NONE: + break; + + case ILT_JUMP: + + target = g_arch_instruction_find_by_address(list, addr, true); + + if (target != NULL) + g_arch_instruction_link_with(iter, target, type); + + break; + + case ILT_JUMP_IF_FALSE: + break; + + case ILT_JUMP_IF_TRUE: + + target = g_arch_instruction_find_by_address(list, addr, true); + + if (target != NULL) + { + g_arch_instruction_link_with(iter, target, type); + + target = g_arch_instruction_get_next_iter(list, iter, end); + if (target != NULL) + g_arch_instruction_link_with(iter, target, ILT_JUMP_IF_FALSE); + + } + + break; + + case ILT_CALL: + + target = g_arch_instruction_find_by_address(list, addr, true); + + if (target != NULL) + g_arch_instruction_link_with(iter, target, type); + + break; + + } + + } + + gtk_extended_status_bar_update_activity(statusbar, id, (i + 1) * 1.0 / count); + + } + +} diff --git a/src/analysis/disass/links.h b/src/analysis/disass/links.h new file mode 100644 index 0000000..0ca7816 --- /dev/null +++ b/src/analysis/disass/links.h @@ -0,0 +1,37 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * links.h - prototypes pour la résolution des liens entre différentes instructions + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DISASS_LINKS_H +#define _ANALYSIS_DISASS_LINKS_H + + +#include "../routine.h" +#include "../../gtkext/gtkextstatusbar.h" + + +/* Etablit les liens entres les différentes lignes de code. */ +void establish_links_between_lines(GArchInstruction *, GBinRoutine **, size_t, GtkExtStatusBar *, guint); + + + +#endif /* _ANALYSIS_DISASS_LINKS_H */ diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c new file mode 100644 index 0000000..9c4ba2f --- /dev/null +++ b/src/analysis/disass/output.c @@ -0,0 +1,59 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * output.h - prototypes pour l'impression des instructions désassemblées + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "output.h" + + +#include "../../decomp/lang/asm.h" + + + +/****************************************************************************** +* * +* Paramètres : buffer = tampon de récueil des résultats d'impression. * +* instrs = ensemble d'instructions à traiter. * +* routines = liste de routines intervenant dans le flot. * +* count = quantité de ces routines. * +* * +* Description : Transcrit du code désassemblé en texte humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void print_disassembled_instructions(GCodeBuffer *buffer, const GArchInstruction *instrs, const GBinRoutine **routines, size_t count) +{ + + /* + for (iter = disass->instrs; + iter != NULL; + iter = g_arch_instruction_get_next_iter(disass->instrs, iter, VMPA_MAX)) + { + + + } + */ + +} diff --git a/src/analysis/disass/output.h b/src/analysis/disass/output.h new file mode 100644 index 0000000..f6c56f3 --- /dev/null +++ b/src/analysis/disass/output.h @@ -0,0 +1,39 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * output.h - prototypes pour l'impression des instructions désassemblées + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _ANALYSIS_DISASS_OUTPUT_H +#define _ANALYSIS_DISASS_OUTPUT_H + + +#include "../routine.h" +#include "../../arch/instruction.h" +#include "../../glibext/gcodebuffer.h" + + + +/* Transcrit du code désassemblé en texte humainement lisible. */ +void print_disassembled_instructions(GCodeBuffer *, const GArchInstruction *, const GBinRoutine **, size_t); + + + +#endif /* _ANALYSIS_DISASS_OUTPUT_H */ diff --git a/src/arch/archbase.h b/src/arch/archbase.h index 61de861..0299227 100644 --- a/src/arch/archbase.h +++ b/src/arch/archbase.h @@ -37,7 +37,8 @@ typedef uint8_t bin_t; typedef uint64_t vmpa_t; -#define VMPA_MAX_SIZE 19 +#define VMPA_MAX 0xffffffffffffffffull +#define VMPA_MAX_SIZE 19 /* Taille des données intégrées */ diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index 2a92bad..4eca0a5 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -58,6 +58,12 @@ struct _GArchInstruction GArchOperand **operands; /* Liste des opérandes */ size_t operands_count; /* Nbre. d'opérandes utilisées */ + GArchInstruction **from; /* Origines des références */ + size_t from_count; /* Nombre de ces origines */ + GArchInstruction **to; /* Eventuelles lignes visées */ + InstructionLinkType *links_type; /* Type des liens de dest. */ + size_t to_count; /* Nombre de ces destinations */ + get_instruction_text_fc get_text; /* Texte humain équivalent */ get_instruction_link_fc get_link; /* Référence à une instruction */ is_instruction_return_fc is_return; /* Retour de fonction ou pas ? */ diff --git a/src/arch/instruction.c b/src/arch/instruction.c index dd43e14..cfc8ace 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -424,6 +424,12 @@ char *g_arch_instruction_get_text(const GArchInstruction *instr, const GExeForma } + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION DES LIAISONS ENTRE INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * * Paramètres : instr = instruction à consulter. * @@ -465,6 +471,113 @@ bool g_arch_instruction_is_return(const GArchInstruction *instr) /****************************************************************************** * * +* Paramètres : instr = instruction dont les informations sont à consulter. * +* dest = ligne visée par la liaison (côté destination). * +* type = type de lien à construire. * +* * +* Description : Etablit un lien entre deux instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type) +{ + /* Côté destination */ + + dest->from = (GArchInstruction **)realloc(dest->from, + ++dest->from_count * sizeof(GArchInstruction *)); + + dest->from[dest->from_count - 1] = instr; + + /* Côté point de départ */ + + instr->to_count++; + + instr->to = (GArchInstruction **)realloc(instr->to, + instr->to_count * sizeof(GArchInstruction *)); + instr->links_type = (InstructionLinkType *)realloc(instr->links_type, + instr->to_count * sizeof(InstructionLinkType)); + + instr->to[instr->to_count - 1] = dest; + instr->links_type[instr->to_count - 1] = type; + + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont les informations sont à consulter. * +* * +* Description : Indique si l'instruction a une ou plusieurs origines. * +* * +* Retour : Bilan de la consultation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_instruction_has_sources(const GArchInstruction *instr) +{ + return (instr->from_count > 0); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont les informations sont à consulter. * +* * +* Description : Indique si l'instruction a une suite autre que la suivante. * +* * +* Retour : Bilan de la consultation. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_instruction_has_destinations(const GArchInstruction *instr) +{ + return (instr->to_count > 1 || (instr->to_count == 1 && instr->links_type[0] != ILT_CALL)); + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction dont les informations sont à consulter. * +* dests = liste des instructions de destination. [OUT] * +* types = liste des types de liens présents. [OUT] * +* * +* Description : Fournit les destinations d'une instruction donnée. * +* * +* Retour : Nombre de ces destinations. * +* * +* Remarques : - * +* * +******************************************************************************/ + +size_t g_arch_instruction_get_destinations(const GArchInstruction *instr, GArchInstruction ***dests, InstructionLinkType **types) +{ + *dests = instr->to; + *types = instr->links_type; + + return instr->to_count; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* CONVERSIONS DU FORMAT DES INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * * Paramètres : instr = instruction d'origine à convertir. * * ctx = contexte de la phase de décompilation. * * * diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 4dcba44..7932fdc 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -90,12 +90,34 @@ void g_arch_instruction_detach_operand(GArchInstruction *, GArchOperand *); /* Traduit une instruction en version humainement lisible. */ char *g_arch_instruction_get_text(const GArchInstruction *, const GExeFormat *, AsmSyntax); + + +/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */ + + /* Informe sur une éventuelle référence à une autre instruction. */ InstructionLinkType g_arch_instruction_get_link(const GArchInstruction *, vmpa_t *); /* Indique si l'instruction correspond à un retour de fonction. */ bool g_arch_instruction_is_return(const GArchInstruction *instr); +/* Etablit un lien entre deux instructions. */ +void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType); + +/* Indique si l'instruction a une ou plusieurs origines. */ +bool g_arch_instruction_has_sources(const GArchInstruction *); + +/* Indique si l'instruction a une suite autre que la suivante. */ +bool g_arch_instruction_has_destinations(const GArchInstruction *); + +/* Fournit les destinations d'une instruction donnée. */ +size_t g_arch_instruction_get_destinations(const GArchInstruction *, GArchInstruction ***, InstructionLinkType **); + + + +/* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */ + + /* Décompile une instruction de façon générique. */ GDecInstruction *g_arch_instruction_decompile(const GArchInstruction *, GDecContext *); diff --git a/src/decomp/lang/Makefile.am b/src/decomp/lang/Makefile.am index 2523bbf..6f5fd59 100755 --- a/src/decomp/lang/Makefile.am +++ b/src/decomp/lang/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libdecomplang.la libdecomplang_la_SOURCES = \ + asm.h asm.c \ java.h java.c libdecomplang_la_LDFLAGS = diff --git a/src/decomp/lang/asm.c b/src/decomp/lang/asm.c new file mode 100644 index 0000000..276d323 --- /dev/null +++ b/src/decomp/lang/asm.c @@ -0,0 +1,266 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * asm.c - sorties en langage d'assemblage + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "asm.h" + + +#include "../output-int.h" + + + +/* Sortie selon le langage d'assemblage (instance) */ +struct _GAsmOutput +{ + GLangOutput parent; /* A laisser en premier */ + +}; + + +/* Sortie selon le langage d'assemblage (classe) */ +struct _GAsmOutputClass +{ + GLangOutputClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des sorties en langage d'assemblage. */ +static void g_asm_output_class_init(GAsmOutputClass *); + +/* Initialise une instance de sortie en langage d'assemblage. */ +static void g_asm_output_init(GAsmOutput *); + +/* Ajoute un commentaire à un tampon donné. */ +static GBufferLine *g_asm_output_write_comments(GAsmOutput *, GCodeBuffer *, const char *, size_t); + +/* Imprime dans un tampon donné une méthode de comparaison. */ +static void g_asm_output_write_comp_sign(GAsmOutput *, GBufferLine *, CompSignType); + +/* Débute la définition d'une routine. */ +static GBufferLine *g_asm_output_start_routine_prototype(GAsmOutput *, GCodeBuffer *, const GOpenidaType *); + +/* Termine la définition d'une routine. */ +static void g_asm_output_end_routine_prototype(GAsmOutput *, GCodeBuffer *, GBufferLine *); + + + +/* Indique le type défini pour une sortie en langage d'assemblage. */ +G_DEFINE_TYPE(GAsmOutput, g_asm_output, G_TYPE_LANG_OUTPUT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des sorties en langage d'assemblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_output_class_init(GAsmOutputClass *klass) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : output = instance à initialiser. * +* * +* Description : Initialise une instance de sortie en langage d'assemblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_output_init(GAsmOutput *output) +{ + GLangOutput *lang; /* Autre version de l'objet */ + + lang = G_LANG_OUTPUT(output); + + lang->cont_comments = (write_comments_fc)g_asm_output_write_comments; + lang->write_comments = (write_comments_fc)g_asm_output_write_comments; + + lang->comp_sign = (write_comp_sign_fc)g_asm_output_write_comp_sign; + + lang->start_routine_proto = (rlgbuftp_fc)g_asm_output_start_routine_prototype; + lang->end_routine_proto = (lgbufln_fc)g_asm_output_end_routine_prototype; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Crée une nouvelle sortie en langage d'assemblage. * +* * +* Retour : Imprimeur créé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GLangOutput *g_asm_output_new(void) +{ + GBufferLine *result; /* Composant à retourner */ + + result = g_object_new(G_TYPE_ASM_OUTPUT, NULL); + + return G_LANG_OUTPUT(result); + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* text = texte à insérer dans l'existant. * +* length = taille du texte à traiter. * +* * +* Description : Ajoute un commentaire à un tampon donné. * +* * +* Retour : Ligne nouvellement créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_asm_output_write_comments(GAsmOutput *output, GCodeBuffer *buffer, const char *text, size_t length) +{ + GBufferLine *result; /* Adresse nouvelle à remonter */ + + result = g_code_buffer_append_new_line(buffer); + + g_buffer_line_insert_text(result, BLC_COMMENTS, "; ", 2, RTT_COMMENT); + + if (length > 0) + g_buffer_line_insert_text(result, BLC_COMMENTS, text, length, RTT_COMMENT); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* line = tampon de sortie à disposition. * +* sign = méthode de comparaison à imprimer. * +* * +* Description : Imprime dans un tampon donné une méthode de comparaison. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_output_write_comp_sign(GAsmOutput *output, GBufferLine *line, CompSignType sign) +{ + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); + + switch (sign) + { + case CST_EQ: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "==", 2, RTT_SIGNS); + break; + case CST_NE: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "!=", 2, RTT_SIGNS); + break; + case CST_LT: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "<", 1, RTT_SIGNS); + break; + case CST_GE: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ">=", 2, RTT_SIGNS); + break; + case CST_GT: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ">", 1, RTT_SIGNS); + break; + case CST_LE: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "<=", 2, RTT_SIGNS); + break; + default: + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "?", 1, RTT_SIGNS); + break; + } + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, " ", 1, RTT_RAW); + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* ret = type de retour de la routine traitée. * +* * +* Description : Débute la définition d'une routine. * +* * +* Retour : Ligne nouvellement créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_asm_output_start_routine_prototype(GAsmOutput *output, GCodeBuffer *buffer, const GOpenidaType *ret) +{ + GBufferLine *result; /* Adresse nouvelle à remonter */ + + result = g_code_buffer_append_new_line(buffer); + + /* TODO */ + g_buffer_line_insert_text(result, BLC_ASSEMBLY_HEAD, "XXX", 3, RTT_RAW); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* line = ligne contenant le prototype de la routine traitée. * +* * +* Description : Termine la définition d'une routine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_asm_output_end_routine_prototype(GAsmOutput *output, GCodeBuffer *buffer, GBufferLine *line) +{ + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, ";", 1, RTT_PUNCT); + +} diff --git a/src/decomp/lang/asm.h b/src/decomp/lang/asm.h new file mode 100644 index 0000000..af96a46 --- /dev/null +++ b/src/decomp/lang/asm.h @@ -0,0 +1,55 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * asm.h - prototypes pour les sorties en langage d'assemblage + * + * Copyright (C) 2010 Cyrille Bagard + * + * This file is part of OpenIDA. + * + * OpenIDA 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. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _DECOMP_LANG_ASM_H +#define _DECOMP_LANG_ASM_H + + +#include "../output.h" + + + +#define G_TYPE_ASM_OUTPUT g_asm_output_get_type() +#define G_ASM_OUTPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_asm_output_get_type(), GAsmOutput)) +#define G_IS_ASM_OUTPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_asm_output_get_type())) +#define G_ASM_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ASM_OUTPUT, GAsmOutputClass)) +#define G_IS_ASM_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ASM_OUTPUT)) +#define G_ASM_OUTPUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ASM_OUTPUT, GAsmOutputClass)) + + +/* Sortie selon le langage d'assemblage (instance) */ +typedef struct _GAsmOutput GAsmOutput; + +/* Sortie selon le langage d'assemblage (classe) */ +typedef struct _GAsmOutputClass GAsmOutputClass; + + +/* Indique le type défini pour une sortie en langage d'assemblage. */ +GType g_asm_output_get_type(void); + +/* Crée une nouvelle sortie en langage d'assemblage. */ +GLangOutput *g_asm_output_new(void); + + + +#endif /* _DECOMP_LANG_ASM_H */ diff --git a/src/decomp/lang/java.c b/src/decomp/lang/java.c index 90a0ddc..471b63c 100644 --- a/src/decomp/lang/java.c +++ b/src/decomp/lang/java.c @@ -50,6 +50,15 @@ static void g_java_output_class_init(GJavaOutputClass *); /* Initialise une instance de sortie en langage Java. */ static void g_java_output_init(GJavaOutput *); +/* Marque le début d'une série de commentaires. */ +static GBufferLine *g_java_output_start_comments(GJavaOutput *, GCodeBuffer *); + +/* Poursuit l'ajout d'une ligne de commentaires. */ +static GBufferLine *g_java_output_continue_comments(GJavaOutput *, GCodeBuffer *, const char *, size_t); + +/* Marque la fin d'une série de commentaires. */ +static GBufferLine *g_java_output_end_comments(GJavaOutput *, GCodeBuffer *); + /* Ajoute un commentaire à un tampon donné. */ static GBufferLine *g_java_output_write_comments(GJavaOutput *, GCodeBuffer *, const char *, size_t); @@ -116,6 +125,10 @@ static void g_java_output_init(GJavaOutput *output) lang = G_LANG_OUTPUT(output); + + lang->start_comments = (rlgbuf_fc)g_java_output_start_comments; + lang->cont_comments = (write_comments_fc)g_java_output_continue_comments; + lang->end_comments = (rlgbuf_fc)g_java_output_end_comments; lang->write_comments = (write_comments_fc)g_java_output_write_comments; lang->comp_sign = (write_comp_sign_fc)g_java_output_write_comp_sign; @@ -158,7 +171,89 @@ GLangOutput *g_java_output_new(void) * * * Paramètres : output = encadrant de l'impression en langage de prog. * * buffer = tampon de sortie à disposition. * -* column = colonne de la ligne visée par l'insertion. * +* * +* Description : Marque le début d'une série de commentaires. * +* * +* Retour : Nouvelle ligne constituée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_java_output_start_comments(GJavaOutput *output, GCodeBuffer *buffer) +{ + GBufferLine *result; /* Nouvelle ligne à retourner */ + + result = g_code_buffer_append_new_line(buffer); + + g_buffer_line_insert_text(result, BLC_COMMENTS, "/**", 3, RTT_COMMENT); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* text = texte à insérer dans l'existant. * +* length = taille du texte à traiter. * +* * +* Description : Poursuit l'ajout d'une ligne de commentaires. * +* * +* Retour : Ligne nouvellement créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_java_output_continue_comments(GJavaOutput *output, GCodeBuffer *buffer, const char *text, size_t length) +{ + GBufferLine *result; /* Adresse nouvelle à remonter */ + + result = g_code_buffer_append_new_line(buffer); + + g_buffer_line_insert_text(result, BLC_COMMENTS, " * ", 3, RTT_COMMENT); + + if (length > 0) + g_buffer_line_insert_text(result, BLC_COMMENTS, text, length, RTT_COMMENT); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* * +* Description : Marque la fin d'une série de commentaires. * +* * +* Retour : Nouvelle ligne constituée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GBufferLine *g_java_output_end_comments(GJavaOutput *output, GCodeBuffer *buffer) +{ + GBufferLine *result; /* Nouvelle ligne à retourner */ + + result = g_code_buffer_append_new_line(buffer); + + g_buffer_line_insert_text(result, BLC_COMMENTS, " */", 3, RTT_COMMENT); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * * text = texte à insérer dans l'existant. * * length = taille du texte à traiter. * * * diff --git a/src/decomp/output-int.h b/src/decomp/output-int.h index 8aae974..885d9ca 100644 --- a/src/decomp/output-int.h +++ b/src/decomp/output-int.h @@ -29,6 +29,9 @@ +/* Xxx. */ +typedef GBufferLine * (* rlgbuf_fc) (GLangOutput *, GCodeBuffer *); + /* Ajoute un commentaire à un tampon donné. */ typedef GBufferLine * (* write_comments_fc) (GLangOutput *, GCodeBuffer *, const char *, size_t); @@ -51,6 +54,9 @@ struct _GLangOutput { GObject parent; /* A laisser en premier */ + rlgbuf_fc start_comments; /* Plusieurs commentaires (#1) */ + write_comments_fc cont_comments; /* Plusieurs commentaires (#2) */ + rlgbuf_fc end_comments; /* Plusieurs commentaires (#3) */ write_comments_fc write_comments; /* Commentaires sur une ligne */ write_comp_sign_fc comp_sign; /* Méthde de comparaison */ diff --git a/src/decomp/output.c b/src/decomp/output.c index 16cab19..99d1912 100644 --- a/src/decomp/output.c +++ b/src/decomp/output.c @@ -72,7 +72,89 @@ static void g_lang_output_init(GLangOutput *output) * * * Paramètres : output = encadrant de l'impression en langage de prog. * * buffer = tampon de sortie à disposition. * -* column = colonne de la ligne visée par l'insertion. * +* * +* Description : Marque le début d'une série de commentaires. * +* * +* Retour : Nouvelle ligne constituée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_lang_output_start_comments(GLangOutput *output, GCodeBuffer *buffer) +{ + GBufferLine *result; /* Adresse nouvelle à remonter */ + + if (output->start_comments != NULL) + result = output->start_comments(output, buffer); + + else result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* text = texte à insérer dans l'existant. * +* length = taille du texte à traiter. * +* * +* Description : Poursuit l'ajout d'une ligne de commentaires. * +* * +* Retour : Ligne nouvellement créée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_lang_output_continue_comments(GLangOutput *output, GCodeBuffer *buffer, const char *text, size_t length) +{ + GBufferLine *result; /* Adresse nouvelle à remonter */ + + if (output->cont_comments != NULL) + result = output->cont_comments(output, buffer, text, length); + + else result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * +* * +* Description : Marque la fin d'une série de commentaires. * +* * +* Retour : Nouvelle ligne constituée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_lang_output_end_comments(GLangOutput *output, GCodeBuffer *buffer) +{ + GBufferLine *result; /* Adresse nouvelle à remonter */ + + if (output->end_comments != NULL) + result = output->end_comments(output, buffer); + + else result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : output = encadrant de l'impression en langage de prog. * +* buffer = tampon de sortie à disposition. * * text = texte à insérer dans l'existant. * * length = taille du texte à traiter. * * * diff --git a/src/decomp/output.h b/src/decomp/output.h index 73e1e76..6a1c4a1 100644 --- a/src/decomp/output.h +++ b/src/decomp/output.h @@ -48,6 +48,15 @@ typedef struct _GLangOutputClass GLangOutputClass; /* Indique le type défini pour une sortie de langage de programmation. */ GType g_lang_output_get_type(void); +/* Marque le début d'une série de commentaires. */ +GBufferLine *g_lang_output_start_comments(GLangOutput *, GCodeBuffer *); + +/* Poursuit l'ajout d'une ligne de commentaires. */ +GBufferLine *g_lang_output_continue_comments(GLangOutput *, GCodeBuffer *, const char *, size_t); + +/* Marque la fin d'une série de commentaires. */ +GBufferLine *g_lang_output_end_comments(GLangOutput *, GCodeBuffer *); + /* Ajoute un commentaire à un tampon donné. */ GBufferLine *g_lang_output_write_comments(GLangOutput *, GCodeBuffer *, const char *, size_t); diff --git a/src/glibext/delayed-int.h b/src/glibext/delayed-int.h index b2e2b23..2aabf0b 100644 --- a/src/glibext/delayed-int.h +++ b/src/glibext/delayed-int.h @@ -45,6 +45,10 @@ struct _GDelayedWork run_task_fc run; /* Traitement externalisé */ + bool completed; /* Fin de la tâche ? */ + GMutex *mutex; /* Accès à la variable */ + GCond *cond; /* Attente de changement */ + }; /* Travail différé (classe) */ diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c index 8f23538..92e167a 100644 --- a/src/glibext/delayed.c +++ b/src/glibext/delayed.c @@ -40,6 +40,12 @@ static void g_delayed_work_class_init(GDelayedWorkClass *); /* Initialise une instance de travail différé. */ static void g_delayed_work_init(GDelayedWork *); +/* Supprime toutes les références externes. */ +static void g_delayed_work_dispose(GDelayedWork *); + +/* Procède à la libération totale de la mémoire. */ +static void g_delayed_work_finalize(GDelayedWork *); + /* Mène l'opération programmée. */ static void g_delayed_work_process(GDelayedWork *, GtkExtStatusBar *); @@ -155,6 +161,13 @@ G_DEFINE_TYPE(GDelayedWork, g_delayed_work, G_TYPE_OBJECT); static void g_delayed_work_class_init(GDelayedWorkClass *klass) { + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_delayed_work_dispose; + object->finalize = (GObjectFinalizeFunc)g_delayed_work_finalize; + g_signal_new("work-completed", G_TYPE_DELAYED_WORK, G_SIGNAL_RUN_LAST, @@ -180,6 +193,58 @@ static void g_delayed_work_class_init(GDelayedWorkClass *klass) static void g_delayed_work_init(GDelayedWork *work) { + work->completed = false; + work->mutex = g_mutex_new(); + work->cond = g_cond_new(); + +} + + +/****************************************************************************** +* * +* Paramètres : work = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_work_dispose(GDelayedWork *work) +{ + gpointer obj_class; /* Classe parente */ + + g_mutex_free(work->mutex); + g_cond_free(work->cond); + + obj_class = g_type_class_peek_parent(G_DELAYED_WORK_GET_CLASS(work)); + + //G_OBJECT_CLASS(obj_class)->dispose(G_OBJECT(work)); + +} + + +/****************************************************************************** +* * +* Paramètres : work = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_delayed_work_finalize(GDelayedWork *work) +{ + gpointer obj_class; /* Classe parente */ + + obj_class = g_type_class_peek_parent(G_DELAYED_WORK_GET_CLASS(work)); + + //G_OBJECT_CLASS(obj_class)->finalize(G_OBJECT(work)); } @@ -203,6 +268,37 @@ static void g_delayed_work_process(GDelayedWork *work, GtkExtStatusBar *statusba g_signal_emit_by_name(work, "work-completed"); + g_mutex_lock(work->mutex); + + work->completed = true; + + g_cond_signal(work->cond); + g_mutex_unlock(work->mutex); + +} + + +/****************************************************************************** +* * +* Paramètres : work = travail à surveiller. * +* * +* Description : Attend la fin de l'exécution d'une tâche donnée. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_delayed_work_wait_for_completion(GDelayedWork *work) +{ + g_mutex_lock(work->mutex); + + while (!work->completed) + g_cond_wait(work->cond, work->mutex); + + g_mutex_unlock(work->mutex); + } diff --git a/src/glibext/delayed.h b/src/glibext/delayed.h index 501bb7f..d2649e1 100644 --- a/src/glibext/delayed.h +++ b/src/glibext/delayed.h @@ -51,6 +51,9 @@ typedef struct _GDelayedWorkClass GDelayedWorkClass; /* Indique le type défini pour les travaux différés. */ GType g_delayed_work_get_type(void); +/* Attend la fin de l'exécution d'une tâche donnée. */ +void g_delayed_work_wait_for_completion(GDelayedWork *); + /* ------------------------- TRAITEMENT DE TACHES DIFFEREES ------------------------- */ diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c index acce2d6..1964ea5 100644 --- a/src/gtkext/gtkblockview.c +++ b/src/gtkext/gtkblockview.c @@ -24,266 +24,53 @@ #include "gtkblockview.h" -#include <malloc.h> -#include <string.h> - - -#include "gtkbinview-int.h" -#include "support.h" -#include "../analysis/exporter.h" -#include "../common/dllist.h" -#include "../glibext/delayed-int.h" -#include "../glibext/gcodebuffer.h" - - - - -#ifndef _ -# define _(str) str -#endif - - -static void gtk_block_view_compute_real_coord(GtkBlockView *view, gint *x, gint *y); - - - - -/* -------------------------- INSERTION DIFFEREE DE LIGNES -------------------------- */ - - -#define G_TYPE_DELAYED_INSERTION g_delayed_insertion_get_type() -#define G_DELAYED_INSERTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_delayed_insertion_get_type(), GDelayedInsertion)) -#define G_IS_DELAYED_INSERTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_delayed_insertion_get_type())) -#define G_DELAYED_INSERTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_DELAYED_INSERTION, GDelayedInsertionClass)) -#define G_IS_DELAYED_INSERTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_DELAYED_INSERTION)) -#define G_DELAYED_INSERTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_DELAYED_INSERTION, GDelayedInsertionClass)) - - -/* Ensembles binaires à désassembler (instance) */ -typedef struct _GDelayedInsertion -{ - GDelayedWork parent; /* A laisser en premier */ - - GtkBlockView *view; /* Visualisation à constituer */ - -} GDelayedInsertion; - -/* Ensembles binaires à désassembler (classe) */ -typedef struct _GDelayedInsertionClass -{ - GDelayedWorkClass parent; /* A laisser en premier */ - -} GDelayedInsertionClass; - - -/* Indique le type défini pour les tâches d'insertions différées. */ -static GType g_delayed_insertion_get_type(void); - -/* Initialise la classe des tâches d'insertions différées. */ -static void g_delayed_insertion_class_init(GDelayedInsertionClass *); - -/* Initialise une tâche d'insertions différées. */ -static void g_delayed_insertion_init(GDelayedInsertion *); - -/* Crée une tâche d'insertions différées. */ -static GDelayedInsertion *g_delayed_insertion_new(GtkBlockView *); - -/* Assure des insertion de lignes en différé. */ -static void g_delayed_insertion_process(GDelayedInsertion *, GtkExtStatusBar *); +#include "gtkbufferview-int.h" +/* -------------------------- INTERACTION DIRECTE AVEC GTK -------------------------- */ +/* Composant d'affichage de bloc d'assembleur (instance) */ struct _GtkBlockView { - GtkBinView parent; /* A laisser en premier */ - - MainRendering rendering; /* Support final des lignes */ - - bool show_vaddress; /* Affichage des adresses ? */ - bool show_code; /* Affichage du code brut ? */ - - GBufferView *buffer_view; /* Code sous forme de texte */ - - gint line_height; /* Hauteur maximale des lignes */ - gint left_margin; /* Marge gauche + espace */ - gint left_text; /* Début d'impression du code */ - - - const exe_format *format; /* Format du contenu bianire */ - - - - GCodeBuffer *_buffer; /* Code sous forme de texte */ - - + GtkBufferView parent; /* A laisser en premier */ }; +/* Composant d'affichage de code d'assembleur (classe) */ struct _GtkBlockViewClass { - GtkBinViewClass parent; /* A laisser en premier */ - - GdkPixbuf *entry_pix; /* Image du point d'entrée */ - GdkPixbuf *breakpoint_pix; /* Image de point d'arrêt */ - GdkPixbuf *stopped_pix; /* Image de point actif */ + GtkBufferViewClass parent; /* A laisser en premier */ }; +/* Procède à l'initialisation des afficheurs de bloc assembleur. */ +static void gtk_block_view_class_init(GtkBlockViewClass *); - - - - -/* Procède à l'initialisation de l'afficheur d'un bloc binaire. */ +/* Procède à l'initialisation de l'afficheur de bloc assembleur. */ static void gtk_block_view_init(GtkBlockView *); -/* Encadre la construction graphique initiale de la visualisation. */ -static void gtk_block_view_realize(GtkWidget *); - -/* Fournit la taille de composant requise pour un plein rendu. */ -static void gtk_block_view_size_request(GtkWidget *, GtkRequisition *); - -/* S'adapte à la surface concédée par le composant parent. */ -static void gtk_block_view_size_allocate(GtkWidget *, GtkAllocation *); - - - - -/* Réagit à un défilement quelconque. */ -static void gtk_block_view_scroll(GtkBlockView *); - -/* Définit les lignes du bloc de représentation. */ -static void gtk_block_view_set_rendering_lines(GtkBlockView *, GRenderingLine *, GRenderingLine *); - -/* Achève la construction de la visualisation des lignes. */ -static void gtk_block_view_complete_building_content(GDelayedInsertion *, GtkBlockView *); - - - - - -/* Redessine l'affichage suite une mise à jour dans la marge. */ -void gtk_block_view_update_margin(GRenderingLine *, GtkBlockView *); - - - - - -/* Réclame une nouvelle taille adaptée au contenu présent. */ -void gtk_block_view_recompute_size_request(GtkBlockView *); - - - - -/* Indique la position d'affichage d'une adresse donnée. */ -static bool gtk_block_view_get_address_coordinates(const GtkBlockView *, vmpa_t, gint *, gint *); - - - - - -static void gtk_block_view_class_init(GtkBlockViewClass *klass); -static void gtk_block_view_size_allocate(GtkWidget *widget, - GtkAllocation *allocation); - - -static gboolean gtk_block_view_button_press(GtkWidget *, GdkEventButton *event); - - -/* Imprime d'éventuelles informations liées à une ligne. */ -static void gtk_block_view_draw_line_extra(GBufferLine *, GdkDrawable *, GdkGC *, gint, gint, void *); - -/* Met à jour l'affichage de la vue sous forme de bloc. */ -static gboolean gtk_block_view_expose(GtkWidget *, GdkEventExpose *); - - - -static void gtk_block_view_destroy(GtkObject *object); - - +/* Prend acte de l'association d'un binaire chargé. */ +static void gtk_block_view_attach_binary(GtkBlockView *, GOpenidaBinary *); /* ---------------------------------------------------------------------------------- */ -/* INSERTION DIFFEREE DE LIGNES */ +/* INTERACTION DIRECTE AVEC GTK */ /* ---------------------------------------------------------------------------------- */ -/* Indique le type défini pour les tâches d'insertions différées. */ -G_DEFINE_TYPE(GDelayedInsertion, g_delayed_insertion, G_TYPE_DELAYED_WORK); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des tâches d'insertions différées. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_delayed_insertion_class_init(GDelayedInsertionClass *klass) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : insertion = instance à initialiser. * -* * -* Description : Initialise une tâche d'insertions différées. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_delayed_insertion_init(GDelayedInsertion *insertion) -{ - G_DELAYED_WORK(insertion)->run = (run_task_fc)g_delayed_insertion_process; - -} - - -/****************************************************************************** -* * -* Paramètres : view = visualisation de lignes à constituer. * -* * -* Description : Crée une tâche d'insertions différées. * -* * -* Retour : Tâche créée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static GDelayedInsertion *g_delayed_insertion_new(GtkBlockView *view) -{ - GDelayedInsertion *result; /* Tâche à retourner */ - - result = g_object_new(G_TYPE_DELAYED_INSERTION, NULL); - - result->view = view; - - return result; - -} +/* Détermine le type du composant d'affichage de bloc en langage d'assemblage. */ +G_DEFINE_TYPE(GtkBlockView, gtk_block_view, GTK_TYPE_BUFFER_VIEW) /****************************************************************************** * * -* Paramètres : insertion = insertions de lignes à mener. * -* statusbar = barre de statut à tenir informée. * +* Paramètres : class = classe GTK à initialiser. * * * -* Description : Assure des insertion de lignes en différé. * +* Description : Procède à l'initialisation des afficheurs de bloc assembleur.* * * * Retour : - * * * @@ -291,177 +78,8 @@ static GDelayedInsertion *g_delayed_insertion_new(GtkBlockView *view) * * ******************************************************************************/ -static void g_delayed_insertion_process(GDelayedInsertion *insertion, GtkExtStatusBar *statusbar) -{ - GtkBlockView *view; /* Visualisation à constituer */ - GRenderingLine *lines; /* Liste de lignes à intégrer */ - GRenderingLine *last; /* Dernière ligne ou NULL */ - vmpa_t start; /* Adresse de début de parcours*/ - vmpa_t end; /* Adresse de fin de parcours */ - guint id; /* Identifiant de statut */ - GRenderingOptions *options; /* Options de rendu */ - GRenderingLine *iter; /* Boucle de parcours */ - GtkTextIter pos; /* Point d'insertion */ - GBufferLine *line; /* Ligne de destination */ - vmpa_t done; /* Quantité déjà parcourue */ - - clock_t _start, _end; - double cpu_time_used; - - view = insertion->view; - - lines = GTK_BIN_VIEW(view)->lines; - last = GTK_BIN_VIEW(view)->last; - - if (lines == NULL) return; - - iter = g_rendering_line_loop_for_code(lines, last); - start = get_rendering_line_address(lines); - - iter = g_rendering_line_get_last_iter(lines, last); - end = get_rendering_line_address(iter) + get_rendering_line_length(iter) - start; - - id = gtk_extended_status_bar_push(statusbar, _("Inserting lines..."), true); - - options = g_openida_binary_get_options(GTK_BIN_VIEW(view)->binary); - - _start = clock(); - - for (iter = lines; - iter != NULL; - iter = g_rendering_line_get_next_iter(lines, iter, last)) - { - g_signal_connect(iter, "rendering-line-flags-changed", - G_CALLBACK(gtk_block_view_update_margin), view); - - //gdk_threads_enter(); - - line = g_code_buffer_append_new_line(view->_buffer); - - g_content_exporter_to_buffer(G_CONTENT_EXPORTER(iter), line, options); - g_object_set_data(G_OBJECT(line), "line", iter); - - - /* - gdk_flush (); - gdk_threads_leave(); - */ - - done = get_rendering_line_address(iter) + get_rendering_line_length(iter) - start; - gtk_extended_status_bar_update_activity(statusbar, id, done * 1.0 / end); - - } - - - _end = clock(); - - cpu_time_used = ((double) (_end - _start)) / (CLOCKS_PER_SEC / 1000); - - printf(" ### TEMPS passé ::: %g ms (pid = %d)\n", cpu_time_used, getpid()); - - - gtk_extended_status_bar_remove(statusbar, id); - - view->buffer_view = g_buffer_view_new(view->_buffer); - - g_buffer_view_define_extra_drawing(view->buffer_view, gtk_block_view_draw_line_extra, view); - - -} - - - - - - - - - - - - - - - -/* Détermine le type du composant d'affichage en block. */ -G_DEFINE_TYPE(GtkBlockView, gtk_block_view, GTK_TYPE_BIN_VIEW) - - -/****************************************************************************** -* * -* Paramètres : rendering = support effectif des lignes au final. * -* * -* Description : Crée un nouveau composant pour l'affichage en block. * -* * -* Retour : Composant GTK créé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GtkWidget * gtk_block_view_new(MainRendering rendering) -{ - GtkBlockView *result; - - result = gtk_type_new(gtk_block_view_get_type()); - - result->rendering = rendering; - - return GTK_WIDGET(result); - -} - - - -static void gtk_block_view_class_init(GtkBlockViewClass *klass) +static void gtk_block_view_class_init(GtkBlockViewClass *class) { - GtkWidgetClass *widget_class; /* Classe version Widget */ - GtkObjectClass *object_class; - - gchar *filename; /* Fichier d'image à charger */ - - widget_class = (GtkWidgetClass *) klass; - object_class = (GtkObjectClass *) klass; - - - widget_class->button_press_event = gtk_block_view_button_press; - widget_class->realize = gtk_block_view_realize; - widget_class->size_request = gtk_block_view_size_request; - widget_class->size_allocate = gtk_block_view_size_allocate; - widget_class->expose_event = gtk_block_view_expose; - - object_class->destroy = gtk_block_view_destroy; - - - - /* Image de la marge gauche */ - - filename = find_pixmap_file("entry.png"); - - if (filename == NULL) klass->entry_pix = NULL; - else - { - klass->entry_pix = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); - } - - filename = find_pixmap_file("breakpoint.png"); - - if (filename == NULL) klass->breakpoint_pix = NULL; - else - { - klass->breakpoint_pix = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); - } - - filename = find_pixmap_file("stopped.png"); - - if (filename == NULL) klass->stopped_pix = NULL; - else - { - klass->stopped_pix = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); - } } @@ -470,7 +88,7 @@ static void gtk_block_view_class_init(GtkBlockViewClass *klass) * * * Paramètres : view = composant GTK à initialiser. * * * -* Description : Procède à l'initialisation de l'afficheur d'un bloc binaire. * +* Description : Procède à l'initialisation de l'afficheur de bloc assembleur.* * * * Retour : - * * * @@ -480,518 +98,44 @@ static void gtk_block_view_class_init(GtkBlockViewClass *klass) static void gtk_block_view_init(GtkBlockView *view) { - GtkViewPanel *viewpanel; /* Instance parente #1 */ - GtkBinView *binview; /* Instance parente #2 */ - - viewpanel = GTK_VIEW_PANEL(view); - - viewpanel->scroll = (scroll_fc)gtk_block_view_scroll; - - binview = GTK_BIN_VIEW(view); - - binview->set_lines = (set_rendering_lines_fc)gtk_block_view_set_rendering_lines; - binview->get_coordinates = (get_addr_coordinates_fc)gtk_block_view_get_address_coordinates; - - view->_buffer = g_code_buffer_new(); - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK à redessiner. * -* * -* Description : Encadre la construction graphique initiale de la visualisat°.* -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_realize(GtkWidget *widget) -{ - GtkBinViewClass *parent_class; /* Version pure du parent */ - - parent_class = GTK_BIN_VIEW_CLASS(g_type_class_peek_parent(GTK_BLOCK_VIEW_GET_CLASS(widget))); - - GTK_WIDGET_CLASS(parent_class)->realize(widget); - -} - - -/****************************************************************************** -* * -* Paramètres : widget = composant GTK à consulter. * -* requisition = dimensions souhaitées. [OUT] * -* * -* Description : Fournit la taille de composant requise pour un plein rendu. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_size_request(GtkWidget *widget, GtkRequisition *requisition) -{ - g_buffer_view_get_size(GTK_BLOCK_VIEW(widget)->buffer_view, - &requisition->width, &requisition->height); - - printf(" === size req :: (%d ; %d)\n", - requisition->width, requisition->height); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* allocation = étendue accordée à la vue. * -* * -* Description : S'adapte à la surface concédée par le composant parent. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - GtkViewPanel *panel; /* Autre version du composant */ - gint width; /* Largeur de l'objet actuelle */ - gint height; /* Hauteur de l'objet actuelle */ - GtkAllocation valloc; /* Surface utilisable */ - gboolean changed; /* Changement de valeur ? */ - - /* Mise à jour GTK */ - - widget->allocation = *allocation; - - if (GTK_WIDGET_REALIZED(widget)) - gdk_window_move_resize(widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); - - panel = GTK_VIEW_PANEL(widget); - - if (panel->hadjustment == NULL || panel->vadjustment == NULL) - return; - - g_buffer_view_get_size(GTK_BLOCK_VIEW(widget)->buffer_view, &width, &height); - - gtk_view_panel_compute_allocation(panel, &valloc); - - /* Défilement horizontal */ - - panel->hadjustment->page_size = valloc.width; - panel->hadjustment->step_increment = valloc.width * 0.1; - panel->hadjustment->page_increment = valloc.width * 0.9; - - panel->hadjustment->upper = MAX(width, valloc.width); - - gtk_view_panel_reclamp_adjustment(panel->hadjustment, &changed); - - gtk_adjustment_changed(panel->hadjustment); - - if (changed) - gtk_adjustment_value_changed(panel->hadjustment); - - /* Défilement vertical */ - - panel->vadjustment->page_size = valloc.height; - panel->vadjustment->step_increment = GTK_BLOCK_VIEW(widget)->line_height; - panel->vadjustment->page_increment = panel->vadjustment->step_increment * 10.0; - - panel->vadjustment->upper = MAX(height, valloc.height); - - gtk_view_panel_reclamp_adjustment(panel->vadjustment, &changed); - - gtk_adjustment_changed(panel->vadjustment); - - if (changed) - gtk_adjustment_value_changed(panel->vadjustment); - -} - - - - -static gboolean gtk_block_view_button_press(GtkWidget *widget, GdkEventButton *event) -{ - gboolean result; /* Décision à retourner */ - GtkBlockView *view; /* Composant GTK réel */ - gint real_x; /* Abscisse réelle du point */ - gint real_y; /* Ordonnée réelle du point */ - GBufferLine *bline; /* Ligne intégrée au tampon */ - GRenderingLine *line; /* Ligne de rendu interne */ - - result = FALSE; - - view = GTK_BLOCK_VIEW(widget); - - real_x = event->x; - real_y = event->y; - gtk_block_view_compute_real_coord(view, &real_x, &real_y); - - /* Clic dans la marge */ - if (event->type == GDK_BUTTON_PRESS && real_x < view->left_margin) - { - bline = g_buffer_view_find_line_at(view->buffer_view, real_y); - - if (bline != NULL) - { - line = G_RENDERING_LINE(g_object_get_data(G_OBJECT(bline), "line")); - - g_openida_binary_toggle_breakpoint(GTK_BIN_VIEW(view)->binary, - get_rendering_line_address(line)); - - result = TRUE; - - } - - } - - return result; - -} - - - -/****************************************************************************** -* * -* Paramètres : line = ligne dont un drapeau a évolué. * -* view = composant GTK à mettre à jour. * -* * -* Description : Redessine l'affichage suite une mise à jour dans la marge. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_block_view_update_margin(GRenderingLine *line, GtkBlockView *view) -{ - - - /* TODO : à améliorer ! */ - gtk_widget_queue_draw(GTK_WIDGET(view)); - - - - -} - - - - - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à redessiner. * -* event = informations liées à l'événement. * -* * -* Description : Met à jour l'affichage de la vue sous forme de bloc. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_compute_fake_coord(GtkBlockView *view, gint *x, gint *y) -{ - if (GTK_VIEW_PANEL(view)->hadjustment != NULL) - *x -= gtk_adjustment_get_value(GTK_VIEW_PANEL(view)->hadjustment); - - if (GTK_VIEW_PANEL(view)->vadjustment != NULL) - *y += gtk_adjustment_get_value(GTK_VIEW_PANEL(view)->vadjustment); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à redessiner. * -* event = informations liées à l'événement. * -* * -* Description : Met à jour l'affichage de la vue sous forme de bloc. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_compute_real_coord(GtkBlockView *view, gint *x, gint *y) -{ - if (x != NULL && GTK_VIEW_PANEL(view)->hadjustment != NULL) - *x += gtk_adjustment_get_value(GTK_VIEW_PANEL(view)->hadjustment); - - if (y != NULL && GTK_VIEW_PANEL(view)->vadjustment != NULL) - *y += gtk_adjustment_get_value(GTK_VIEW_PANEL(view)->vadjustment); - -} - - -/****************************************************************************** -* * -* Paramètres : line = ligne de texte à manipuler. * -* drawable = surface de rendu où travailler. * -* gc = contexte graphique à utiliser pour les pinceaux. * -* x = abscisse du point d'impression décallé. * -* y = ordonnée du point d'impression décallé. * -* data = pointeur vers le composant GTK de support. * -* * -* Description : Imprime d'éventuelles informations liées à une ligne. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_draw_line_extra(GBufferLine *line, GdkDrawable *drawable, GdkGC *gc, gint x, gint y, void *data) -{ - GRenderingLine *rline; /* Ligne de rendu représentée */ - GtkBlockViewClass *class; /* Classe contenant les images */ - gint line_height; /* Hauteur d'une ligne */ - RenderingLineFlag flags; /* Propriétés de la ligne */ - int height; /* Hauteur de l'image */ - GdkPixbuf *pixbuf; /* Données utiles au dessin */ - - rline = G_RENDERING_LINE(g_object_get_data(G_OBJECT(line), "line")); - class = GTK_BLOCK_VIEW_GET_CLASS(data); - - line_height = g_buffer_view_get_line_height(GTK_BLOCK_VIEW(data)->buffer_view); - - flags = g_rendering_line_get_flags(rline); - - if (flags & RLF_RUNNING_BP) - pixbuf = class->stopped_pix; - - else if (flags & RLF_BREAK_POINT) - pixbuf = class->breakpoint_pix; - - else pixbuf = NULL; - - if (pixbuf != NULL) - { - height = gdk_pixbuf_get_height(pixbuf); - - gdk_draw_pixbuf(drawable, gc, pixbuf, 0, 0, x + 10, - y + (line_height - height) / 2, - gdk_pixbuf_get_width(pixbuf), height, - GDK_RGB_DITHER_NORMAL, 0, 0); - - } - - /* Le point d'entrée prime */ - if (flags & RLF_ENTRY_POINT) - { - pixbuf = class->entry_pix; - height = gdk_pixbuf_get_height(pixbuf); - - gdk_draw_pixbuf(drawable, gc, pixbuf, 0, 0, x + 10, - y + (line_height - height) / 2, - gdk_pixbuf_get_width(pixbuf), height, - GDK_RGB_DITHER_NORMAL, 0, 0); - - } - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à redessiner. * -* event = informations liées à l'événement. * -* * -* Description : Met à jour l'affichage de la vue sous forme de bloc. * -* * -* Retour : FALSE pour poursuivre la propagation de l'événement. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event) -{ - GtkBlockView *view; /* Autre version du composant */ - GtkViewPanel *pview; /* Autre version du composant */ - GtkStyle *style; /* Style associé au composant */ - GdkDrawable *drawable; /* Surface de dessin */ - gint fake_x; /* Abscisse virtuelle */ - gint fake_y; /* Ordonnée virtuelle */ - GtkBinViewClass *parent_class; /* Version pure du parent */ - - view = GTK_BLOCK_VIEW(widget); - widget = GTK_WIDGET(view); - pview = GTK_VIEW_PANEL(widget); - - drawable = GDK_DRAWABLE(event->window); - - gdk_window_begin_paint_region(drawable, event->region); - - gdk_gc_set_clip_region(pview->gc, event->region); - - style = gtk_widget_get_style(GTK_WIDGET(view)); - - fake_x = 0; - fake_y = 0; - gtk_block_view_compute_fake_coord(view, &fake_x, &fake_y); - - /* Dessin de la marge gauche */ - - gdk_gc_set_foreground(pview->gc, &style->mid[GTK_WIDGET_STATE(widget)]); - - gdk_draw_rectangle(drawable, pview->gc, TRUE, - fake_x, event->area.y, view->left_margin, event->area.y + event->area.height); - - gdk_gc_set_foreground(pview->gc, &style->dark[GTK_WIDGET_STATE(widget)]); - - gdk_draw_line(drawable, pview->gc, - fake_x + view->left_margin, event->area.y, - fake_x + view->left_margin, event->area.y + event->area.height); - - /* Eventuelle bordure globale */ - - parent_class = GTK_BIN_VIEW_CLASS(g_type_class_peek_parent(GTK_BLOCK_VIEW_GET_CLASS(view))); - - GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); - - /* Impression du désassemblage */ - - g_buffer_view_draw(view->buffer_view, event, pview->gc, fake_x, fake_y); - - gdk_window_end_paint(drawable); - - return TRUE; - -} - - - - -static void -gtk_block_view_destroy(GtkObject *object) -{ - GtkBlockView *cpu; - GtkBlockViewClass *klass; - - g_return_if_fail(object != NULL); - g_return_if_fail(GTK_IS_BLOCK_VIEW(object)); + GtkViewPanel *panel; /* Instance parente */ - cpu = GTK_BLOCK_VIEW(object); + panel = GTK_VIEW_PANEL(view); - klass = gtk_type_class(gtk_widget_get_type()); + panel->attach = (attach_binary_fc)gtk_block_view_attach_binary; - if (GTK_OBJECT_CLASS(klass)->destroy) { - (* GTK_OBJECT_CLASS(klass)->destroy) (object); - } } - - - - /****************************************************************************** * * -* Paramètres : view = composant GTK à mettre à jour. * -* show = état de l'affichage auquel parvenir. * +* Paramètres : - * * * -* Description : Choisit d'afficher les adresses virtuelles ou non. * +* Description : Crée un nouveau composant pour l'affichage de bloc en ASM. * * * -* Retour : - * +* Retour : Composant GTK créé. * * * * Remarques : - * * * ******************************************************************************/ -void gtk_block_view_show_vaddress(GtkBlockView *view, gboolean show) +GtkWidget *gtk_block_view_new(void) { - view->show_vaddress = show; - - //gtk_block_view_build_content(view); - -} + GtkBlockView *result; /* Composant à retourner */ + result = gtk_type_new(GTK_TYPE_BLOCK_VIEW); -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* show = état de l'affichage auquel parvenir. * -* * -* Description : Choisit d'afficher le code brut ou non. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_block_view_show_code(GtkBlockView *view, gboolean show) -{ - view->show_code = show; - - //gtk_block_view_build_content(view); + return GTK_WIDGET(result); } - - - /****************************************************************************** * * * Paramètres : view = composant GTK à mettre à jour. * -* format = format du binaire affiché. * -* * -* Description : Définit le format auquel le contenu est lié. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_block_view_set_format(GtkBlockView *view, const exe_format *format) -{ - view->format = format; - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* * -* Description : Réagit à un défilement quelconque. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_scroll(GtkBlockView *view) -{ - gtk_widget_queue_draw(GTK_WIDGET(view)); - -} - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* lines = informations à intégrer. * -* last = dernière ligne à intégrer ou NULL pour toutes. * +* binary = binaire associé à intégrer. * * * -* Description : Définit les lignes du bloc de représentation. * +* Description : Prend acte de l'association d'un binaire chargé. * * * * Retour : - * * * @@ -999,127 +143,12 @@ static void gtk_block_view_scroll(GtkBlockView *view) * * ******************************************************************************/ -static void gtk_block_view_set_rendering_lines(GtkBlockView *view, GRenderingLine *lines, GRenderingLine *last) +static void gtk_block_view_attach_binary(GtkBlockView *view, GOpenidaBinary *binary) { - GWorkQueue *queue; /* Gestionnaire de différés */ - GDelayedInsertion *insertion; /* Insertions à mener */ - - queue = get_work_queue(); - - insertion = g_delayed_insertion_new(view); - - g_signal_connect(insertion, "work-completed", - G_CALLBACK(gtk_block_view_complete_building_content), view); - - g_work_queue_schedule_work(queue, G_DELAYED_WORK(insertion)); - -} - - -/****************************************************************************** -* * -* Paramètres : insertion = travail d'insertion effectué. * -* view = composant GTK à mettre à jour. * -* * -* Description : Achève la construction de la visualisation des lignes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void gtk_block_view_complete_building_content(GDelayedInsertion *insertion, GtkBlockView *view) -{ - gdk_threads_enter(); - - /* Taille des marges */ - - view->line_height = g_buffer_view_get_line_height(view->buffer_view); - view->left_margin = 2 * view->line_height; - view->left_text = -2.5 * view->line_height; - - /* Validation finale */ - - gtk_block_view_recompute_size_request(view); - - gdk_flush (); - gdk_threads_leave(); - - g_signal_emit_by_name(view, "lines-set"); - -} - - - - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à mettre à jour. * -* * -* Description : Réclame une nouvelle taille adaptée au contenu présent. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void gtk_block_view_recompute_size_request(GtkBlockView *view) -{ - gint width; /* Largeur de l'objet actuelle */ - gint height; /* Hauteur de l'objet actuelle */ - - g_buffer_view_get_size(view->buffer_view, &width, &height); - - width += -view->left_text + 1; - height += 1; - - gtk_widget_set_size_request(GTK_WIDGET(view), width, height); - -} - - - - - - - - -/****************************************************************************** -* * -* Paramètres : view = composant GTK à consulter. * -* addr = adresse à présenter à l'écran. * -* x = position horizontale au sein du composant. [OUT] * -* y = position verticale au sein du composant. [OUT] * -* * -* Description : Indique la position d'affichage d'une adresse donnée. * -* * -* Retour : TRUE si l'adresse fait partie du composant, FALSE sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gtk_block_view_get_address_coordinates(const GtkBlockView *view, vmpa_t addr, gint *x, gint *y) -{ - bool result; /* Bilan à retourner */ - GRenderingLine *iter; /* Boucle de parcours */ - - result = false; - - *x = 0; - *y = 0; + GCodeBuffer *buffer; /* Tampon par défaut */ - for (iter = GTK_BIN_VIEW(view)->lines; - iter != NULL && !result; - iter = g_rendering_line_get_next_iter(GTK_BIN_VIEW(view)->lines, iter, GTK_BIN_VIEW(view)->last)) - { - if (get_rendering_line_address(iter) == addr) result = true; - else *y += view->line_height; - } + buffer = g_openida_binary_get_disassembled_buffer(binary); - return result; + gtk_buffer_view_attach_buffer(GTK_BUFFER_VIEW(view), buffer); } diff --git a/src/gtkext/gtkblockview.h b/src/gtkext/gtkblockview.h index ed958d0..af2ba2b 100644 --- a/src/gtkext/gtkblockview.h +++ b/src/gtkext/gtkblockview.h @@ -25,13 +25,8 @@ #define _GTKEXT_GTKBLOCKVIEW_H -#include <stdint.h> -#include <gtk/gtk.h> -#include <cairo.h> - - -#include "../analysis/line.h" -#include "../format/exe_format.h" +#include <glib-object.h> +#include <gtk/gtkwidget.h> @@ -43,46 +38,18 @@ #define GTK_BLOCK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_BLOCK_VIEW, GtkBlockViewClass)) - +/* Composant d'affichage de code d'assembleur (instance) */ typedef struct _GtkBlockView GtkBlockView; - +/* Composant d'affichage de code d'assembleur (classe) */ typedef struct _GtkBlockViewClass GtkBlockViewClass; - -/* Détermine le type du composant d'affichage en block. */ +/* Détermine le type du composant d'affichage de bloc en langage d'assemblage. */ GType gtk_block_view_get_type(void); -/* Crée un nouveau composant pour l'affichage en block. */ -GtkWidget *gtk_block_view_new(MainRendering); - - - - - - - - - - - - -/* Choisit d'afficher les adresses virtuelles ou non. */ -void gtk_block_view_show_vaddress(GtkBlockView *, gboolean); - -/* Choisit d'afficher le code brut ou non. */ -void gtk_block_view_show_code(GtkBlockView *, gboolean); - - - - -/* Définit le format auquel le contenu est lié. */ -void gtk_block_view_set_format(GtkBlockView *, const exe_format *); - - - - +/* Crée un nouveau composant pour l'affichage de bloc en ASM. */ +GtkWidget *gtk_block_view_new(void); diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c index 756c00a..07ae8ba 100644 --- a/src/gtkext/gtkgraphview.c +++ b/src/gtkext/gtkgraphview.c @@ -543,6 +543,7 @@ static bool gtk_graph_view_get_address_coordinates(const GtkGraphView *view, vmp static GtkBinView **gtk_graph_view_load_nodes(GtkGraphView *view, GOpenidaBinary *binary, GRenderingLine *first, GRenderingLine *last) { +#if 0 GtkBinView **result; /* Liste à retourner */ size_t *count; /* Nombre d'éléments créés. */ GRenderingLine *begin; /* Début d'un groupe de lignes */ @@ -624,7 +625,8 @@ static GtkBinView **gtk_graph_view_load_nodes(GtkGraphView *view, GOpenidaBinary gdk_threads_enter(); return result; - +#endif + return NULL; } diff --git a/src/gtkext/gtksourceview.c b/src/gtkext/gtksourceview.c index c44b41f..33b61c5 100644 --- a/src/gtkext/gtksourceview.c +++ b/src/gtkext/gtksourceview.c @@ -121,7 +121,7 @@ static void gtk_source_view_init(GtkSourceView *view) GtkWidget *gtk_source_view_new(void) { - GtkSourceView *result; + GtkSourceView *result; /* Composant à retourner */ result = gtk_type_new(GTK_TYPE_SOURCE_VIEW); diff --git a/src/project.c b/src/project.c index 2fa2750..70cbef1 100644 --- a/src/project.c +++ b/src/project.c @@ -34,6 +34,7 @@ #include "gtkext/gtkblockview.h" #include "gtkext/gtkdockpanel.h" #include "gtkext/gtkgraphview.h" +#include "gtkext/gtksourceview.h" #include "gtkext/gtkviewpanel.h" #include "panels/panel.h" @@ -126,7 +127,7 @@ static loaded_binary *load_openida_binary(GOpenidaBinary *binary) switch (i) { case BVW_BLOCK: - view = gtk_block_view_new(MRD_BLOCK); + view = gtk_block_view_new(/*MRD_BLOCK*/); break; case BVW_GRAPH: view = gtk_graph_view_new(); |