From 64e09a6c3e39785975b5322973ed83734cedb82e Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 16 Dec 2012 21:55:04 +0000 Subject: Reintroduced the delayed disassembling of binaries. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@304 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 33 +++++++++++++++++++++++++++++++ src/analysis/binary.c | 17 ++++++++++------ src/analysis/disass/disassembler.c | 40 +++++++++++++------------------------- src/analysis/disass/disassembler.h | 31 ++++++++++++++++++++++++++++- src/analysis/disass/output.c | 25 +++++++++++++++++------- src/analysis/disass/output.h | 3 ++- src/arch/instruction-int.h | 1 + src/arch/instruction.c | 19 ++++++++++++++++++ src/arch/instruction.h | 3 +++ src/glibext/delayed.c | 4 ++-- src/gtkext/gtkextstatusbar.c | 19 +++++++++--------- src/main.c | 4 ++-- src/plugins/pglist.c | 12 +++++++++++- src/plugins/pglist.h | 2 +- src/project.c | 6 ++++-- 15 files changed, 160 insertions(+), 59 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1423fb8..d797246 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,38 @@ 12-12-16 Cyrille Bagard + * src/analysis/binary.c: + * src/analysis/disass/disassembler.c: + * src/analysis/disass/disassembler.h: + Reintroduce the delayed disassembling of binaries. + + * src/analysis/disass/output.c: + * src/analysis/disass/output.h: + Give information about the progress while printing. + + * src/arch/instruction.c: + * src/arch/instruction.h: + * src/arch/instruction-int.h: + Retrieve the last instruction of a list. + + * src/glibext/delayed.c: + Prevent the current work being deleted on the "work-completed" signal, + and then being updated. + + * src/gtkext/gtkextstatusbar.c: + Reintroduce GDK locks in the official way. + + * src/main.c: + Reintroduce GDK locks in the official way. + + * src/plugins/pglist.c: + * src/plugins/pglist.h: + Provide a global way to protect GTK accesses when dealing with plugins. + + * src/project.c: + Protect GTK accesses when being notified of completed disassembly. + +12-12-16 Cyrille Bagard + * configure.ac: Change the output filename for the GLib marshals. diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 54beba7..ecf9c79 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -65,7 +65,7 @@ static bool g_loaded_binary_load_parts_from_xml(GLoadedBinary *, xmlXPathContext static bool g_loaded_binary_save_parts(const GLoadedBinary *, xmlDocPtr, xmlXPathContextPtr, const char *); /* Acquitte la fin d'un désasemblage différé et complet. */ -void ack_completed_disassembly(void/*GDelayedDisassembly*/ *, GLoadedBinary *); +static void ack_completed_disassembly(GDelayedDisassembly *, GLoadedBinary *); @@ -572,10 +572,11 @@ void g_loaded_binary_analyse(GLoadedBinary *binary) } disassemble_binary(binary, parts, parts_count, - &binary->instrs, &binary->disass_buffer); + &binary->instrs, &binary->disass_buffer, + ack_completed_disassembly); /* TODO : remme ! */ - ack_completed_disassembly(NULL, binary); + //ack_completed_disassembly(NULL, binary); } @@ -783,7 +784,7 @@ bool *g_loaded_binary_display_decomp_lines(GLoadedBinary *binary) * * ******************************************************************************/ -void ack_completed_disassembly(void/*GDelayedDisassembly*/ *disass, GLoadedBinary *binary) +void ack_completed_disassembly(GDelayedDisassembly *disass, GLoadedBinary *binary) { //GRenderingLine *line; /* "Première" ligne de rendu */ @@ -792,6 +793,10 @@ void ack_completed_disassembly(void/*GDelayedDisassembly*/ *disass, GLoadedBinar const char * const *files; /* Liste de fichiers source */ + + g_object_unref(G_OBJECT(disass)); + + /* Décompilation... */ @@ -802,10 +807,10 @@ void ack_completed_disassembly(void/*GDelayedDisassembly*/ *disass, GLoadedBinar if (binary->decbuf_count > 0) { binary->dec_buffers = (GCodeBuffer **)calloc(binary->decbuf_count, sizeof(GCodeBuffer *)); - + /* for (i = 0; i < binary->decbuf_count; i++) binary->dec_buffers[i] = decompile_all_from_file(binary, files[i]); - + */ } diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c index ee56043..e7c972d 100644 --- a/src/analysis/disass/disassembler.c +++ b/src/analysis/disass/disassembler.c @@ -48,16 +48,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 +struct _GDelayedDisassembly { GDelayedWork parent; /* A laisser en premier */ @@ -70,19 +62,16 @@ typedef struct _GDelayedDisassembly GArchInstruction **instrs; /* Instructions résultantes */ GCodeBuffer *buffer; /* Tampon pour le rendu */ -} GDelayedDisassembly; +}; /* Ensembles binaires à désassembler (classe) */ -typedef struct _GDelayedDisassemblyClass +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 *); @@ -99,6 +88,7 @@ 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); @@ -242,7 +232,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta #endif - run_plugins_on_binary(disass->binary, PGA_BINARY_DISASSEMBLED); + run_plugins_on_binary(disass->binary, PGA_BINARY_DISASSEMBLED, true); /* Seconde étape */ @@ -252,7 +242,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta gtk_extended_status_bar_remove(statusbar, id); - run_plugins_on_binary(disass->binary, PGA_BINARY_LINKED); + run_plugins_on_binary(disass->binary, PGA_BINARY_LINKED, true); /* Troisième étape */ @@ -264,7 +254,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta gtk_extended_status_bar_remove(statusbar, id); - run_plugins_on_binary(disass->binary, PGA_BINARY_BOUNDED); + run_plugins_on_binary(disass->binary, PGA_BINARY_BOUNDED, true); /* Quatrième étape */ @@ -276,7 +266,7 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta gtk_extended_status_bar_remove(statusbar, id); - run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED); + run_plugins_on_binary(disass->binary, PGA_BINARY_GROUPED, true); /* Cinquième étape */ @@ -285,11 +275,11 @@ static void g_delayed_disassembly_process(GDelayedDisassembly *disass, GtkExtSta qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare); print_disassembled_instructions(disass->buffer, disass->format, *disass->instrs, - routines, routines_count); + routines, routines_count, statusbar, id); gtk_extended_status_bar_remove(statusbar, id); - run_plugins_on_binary(disass->binary, PGA_BINARY_PRINTED); + run_plugins_on_binary(disass->binary, PGA_BINARY_PRINTED, true); } @@ -395,6 +385,7 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con * count = nombre de parties à traiter. * * instrs = liste des instructions chargées. [OUT] * * buffer = tampon de code mis en place. [OUT] * +* ack = fonction à appeler une fois l'opération terminée. * * * * Description : Procède au désassemblage d'un contenu binaire donné. * * * @@ -404,7 +395,7 @@ static void build_disass_prologue(GCodeBuffer *buffer, const char *filename, con * * ******************************************************************************/ -void disassemble_binary(GLoadedBinary *binary, GBinPart **parts, size_t parts_count, GArchInstruction **instrs, GCodeBuffer **buffer) +void disassemble_binary(GLoadedBinary *binary, GBinPart **parts, size_t parts_count, GArchInstruction **instrs, GCodeBuffer **buffer, disassembly_ack_fc ack) { const uint8_t *data; /* Données binaires brutes */ off_t length; /* Quantité de ces données */ @@ -417,12 +408,9 @@ void disassemble_binary(GLoadedBinary *binary, GBinPart **parts, size_t parts_co build_disass_prologue(*buffer, g_loaded_binary_get_filename(binary, true), data, length); disass = g_delayed_disassembly_new(binary, parts, parts_count, instrs, *buffer); + g_signal_connect(disass, "work-completed", G_CALLBACK(ack), binary); 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)); - } diff --git a/src/analysis/disass/disassembler.h b/src/analysis/disass/disassembler.h index 8cca194..b7c286c 100644 --- a/src/analysis/disass/disassembler.h +++ b/src/analysis/disass/disassembler.h @@ -30,8 +30,37 @@ +/* ------------------------ 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 GDelayedDisassembly; + +/* Ensembles binaires à désassembler (classe) */ +typedef struct _GDelayedDisassemblyClass GDelayedDisassemblyClass; + + +/* Indique le type défini pour les tâches de désassemblage différé. */ +GType g_delayed_disassembly_get_type(void); + + + +/* -------------------------- GESTION GLOBALE DE PROCEDURE -------------------------- */ + + +/* Acquitte la fin d'un désasemblage différé et complet. */ +typedef void (* disassembly_ack_fc) (GDelayedDisassembly *, GLoadedBinary *); + /* Procède à la décompilation des routines d'un fichier donné. */ -void disassemble_binary(GLoadedBinary *, GBinPart **parts, size_t parts_count, GArchInstruction **, GCodeBuffer **); +void disassemble_binary(GLoadedBinary *, GBinPart **parts, size_t parts_count, GArchInstruction **, GCodeBuffer **, disassembly_ack_fc); diff --git a/src/analysis/disass/output.c b/src/analysis/disass/output.c index 812b811..135168e 100644 --- a/src/analysis/disass/output.c +++ b/src/analysis/disass/output.c @@ -32,10 +32,13 @@ /****************************************************************************** * * -* 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. * +* Paramètres : buffer = tampon de récueil des résultats d'impression. * +* format = format du binaire traité. * +* instrs = ensemble d'instructions à traiter. * +* routines = liste de routines intervenant dans le flot. * +* count = quantité de ces routines. * +* statusbar = barre de statut avec progression à mettre à jour.* +* id = identifiant du message affiché à l'utilisateur. * * * * Description : Transcrit du code désassemblé en texte humainement lisible. * * * @@ -45,12 +48,14 @@ * * ******************************************************************************/ -void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *format, const GArchInstruction *instrs, GBinRoutine * const *routines, size_t count) +void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *format, const GArchInstruction *instrs, GBinRoutine * const *routines, size_t count, GtkExtStatusBar *statusbar, guint id) { GLangOutput *output; /* Modèle de sortie adéquat */ GArchProcessor *proc; /* Architecture du binaire */ MemoryDataSize msize; /* Taille du bus d'adresses */ const bin_t *content; /* Contenu binaire global */ + vmpa_t start; /* Adresse de départ */ + vmpa_t end; /* Adresse de fin */ const GArchInstruction *iter; /* Boucle de parcours #1 */ size_t i; /* Boucle de parcours #2 */ vmpa_t iaddr; /* Adresse d'instruction */ @@ -63,16 +68,20 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form content = g_binary_format_get_content(G_BIN_FORMAT(format), NULL); + g_arch_instruction_get_location(instrs, NULL, NULL, &start); + iter = g_arch_instruction_find_last(instrs); + g_arch_instruction_get_location(iter, NULL, NULL, &end); + for (iter = instrs, i = 0; iter != NULL; iter = g_arch_instruction_get_next_iter(instrs, iter, VMPA_MAX)) { + g_arch_instruction_get_location(iter, NULL, NULL, &iaddr); + /* Ajout des prototypes de fonction */ for (; i < count; i++) { - g_arch_instruction_get_location(iter, NULL, NULL, &iaddr); raddr = g_binary_routine_get_address(routines[i]); - if (raddr > iaddr) break; g_binary_routine_output_info(routines[i], output, buffer); @@ -81,6 +90,8 @@ void print_disassembled_instructions(GCodeBuffer *buffer, const GExeFormat *form g_arch_instruction_print(iter, buffer, msize, content, ASX_INTEL); + gtk_extended_status_bar_update_activity(statusbar, id, (iaddr - start) * 1.0 / (end - start)); + } g_object_unref(G_OBJECT(output)); diff --git a/src/analysis/disass/output.h b/src/analysis/disass/output.h index 7e0a3cc..81c028d 100644 --- a/src/analysis/disass/output.h +++ b/src/analysis/disass/output.h @@ -28,11 +28,12 @@ #include "../routine.h" #include "../../arch/instruction.h" #include "../../glibext/gcodebuffer.h" +#include "../../gtkext/gtkextstatusbar.h" /* Transcrit du code désassemblé en texte humainement lisible. */ -void print_disassembled_instructions(GCodeBuffer *, const GExeFormat *, const GArchInstruction *, GBinRoutine * const *, size_t); +void print_disassembled_instructions(GCodeBuffer *, const GExeFormat *, const GArchInstruction *, GBinRoutine * const *, size_t, GtkExtStatusBar *, guint); diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index af72a87..25d65e5 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -87,6 +87,7 @@ struct _GArchInstructionClass }; +#define ainstr_list_last(head) dl_list_last(head, GArchInstruction, flow) #define ainstr_list_prev_iter(iter, head) dl_list_prev_iter(iter, head, GArchInstruction, flow) #define ainstr_list_next_iter(iter, head) dl_list_next_iter(iter, head, GArchInstruction, flow) #define ainstr_list_add_tail(new, head) dl_list_add_tail(new, head, GArchInstruction, flow) diff --git a/src/arch/instruction.c b/src/arch/instruction.c index a45e8fa..b460b37 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -623,6 +623,25 @@ GDecInstruction *g_arch_instruction_decompile(const GArchInstruction *instr, GDe /****************************************************************************** * * +* Paramètres : list = liste d'instructions à consulter. * +* * +* Description : Renvoie vers la dernière instruction d'une série. * +* * +* Retour : Dernière instruction trouvée (ou NULL ?!). * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_arch_instruction_find_last(const GArchInstruction *list) +{ + return ainstr_list_last(list); + +} + + +/****************************************************************************** +* * * Paramètres : list = liste d'instructions à compléter, ou NULL. * * instr = nouvelle instruction à intégrer à l'ensemble. * * * diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 8963284..2eddc3c 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -136,6 +136,9 @@ GDecInstruction *g_arch_instruction_decompile(const GArchInstruction *, GDecCont /* -------------------- TRAITEMENT DES INSTRUCTIONS PAR ENSEMBLE -------------------- */ +/* Renvoie vers la dernière instruction d'une série. */ +GArchInstruction *g_arch_instruction_find_last(const GArchInstruction *); + /* Ajoute une instruction à un ensemble existant. */ void g_arch_instruction_add_to_list(GArchInstruction **, GArchInstruction *); diff --git a/src/glibext/delayed.c b/src/glibext/delayed.c index a183449..e4dc37e 100644 --- a/src/glibext/delayed.c +++ b/src/glibext/delayed.c @@ -266,8 +266,6 @@ static void g_delayed_work_process(GDelayedWork *work, GtkExtStatusBar *statusba { work->run(work, statusbar); - g_signal_emit_by_name(work, "work-completed"); - g_mutex_lock(work->mutex); work->completed = true; @@ -275,6 +273,8 @@ static void g_delayed_work_process(GDelayedWork *work, GtkExtStatusBar *statusba g_cond_signal(work->cond); g_mutex_unlock(work->mutex); + g_signal_emit_by_name(work, "work-completed"); + } diff --git a/src/gtkext/gtkextstatusbar.c b/src/gtkext/gtkextstatusbar.c index c89cfe4..dfb08d7 100644 --- a/src/gtkext/gtkextstatusbar.c +++ b/src/gtkext/gtkextstatusbar.c @@ -124,7 +124,7 @@ guint gtk_extended_status_bar_push(GtkExtStatusBar *bar, const gchar *message, g { guint result; /* Identifiant à retourner */ - //gdk_threads_enter(); + gdk_threads_enter(); result = gtk_statusbar_push(GTK_STATUSBAR(bar), bar->context, message); @@ -145,9 +145,8 @@ guint gtk_extended_status_bar_push(GtkExtStatusBar *bar, const gchar *message, g } else gtk_widget_hide(GTK_WIDGET(bar->progress)); - //gdk_flush (); - - //gdk_threads_leave(); + gdk_flush(); + gdk_threads_leave(); return result; @@ -181,12 +180,13 @@ void gtk_extended_status_bar_update_activity(GtkExtStatusBar *bar, guint id, gdo g_snprintf(percent, 5, "%.0f%%", value * 100); - //gdk_threads_enter(); + gdk_threads_enter(); gtk_progress_bar_set_fraction(bar->progress, value); gtk_progress_bar_set_text(bar->progress, percent); - //gdk_threads_leave(); + gdk_flush(); + gdk_threads_leave(); } @@ -210,7 +210,7 @@ void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, guint id) { size_t i; /* Boucle de parcours */ - //gdk_threads_enter(); + gdk_threads_enter(); gtk_statusbar_remove(GTK_STATUSBAR(bar), bar->context, id); @@ -234,8 +234,7 @@ void gtk_extended_status_bar_remove(GtkExtStatusBar *bar, guint id) else gtk_widget_hide(GTK_WIDGET(bar->progress)); - //gdk_flush (); - - //gdk_threads_leave(); + gdk_flush(); + gdk_threads_leave(); } diff --git a/src/main.c b/src/main.c index 09d9998..8612b1d 100644 --- a/src/main.c +++ b/src/main.c @@ -117,6 +117,7 @@ int main(int argc, char **argv) /* init threads */ g_thread_init(NULL); gdk_threads_init(); + gdk_threads_enter(); /* Initialisation de GTK */ setlocale (LC_ALL, ""); @@ -160,9 +161,8 @@ int main(int argc, char **argv) /* Exécution du programme */ - //gdk_threads_enter(); gtk_main(); - //gdk_threads_leave(); + gdk_threads_leave(); exit_global_pango_context(); diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c index 14e6b48..bca3e6a 100644 --- a/src/plugins/pglist.c +++ b/src/plugins/pglist.c @@ -263,6 +263,7 @@ void add_plugin_to_main_list(GPluginModule *plugin) * * * Paramètres : binary = binaire chargé en mémoire à traiter. * * action = fonctionnalité recherchée. * +* lock = indique si l'exécution n'est pas celle principale. * * * * Description : Opère une action donnée sur un binaire défini. * * * @@ -272,12 +273,21 @@ void add_plugin_to_main_list(GPluginModule *plugin) * * ******************************************************************************/ -void run_plugins_on_binary(GLoadedBinary *binary, PluginAction action) +void run_plugins_on_binary(GLoadedBinary *binary, PluginAction action, bool lock) { size_t i; /* Boucle de parcours */ + if (lock) + gdk_threads_enter(); + for (i = 0; i < _list.plugins_count; i++) if (g_plugin_module_get_action(_list.plugins[i]) & action) g_plugin_module_execute_action_on_binary(_list.plugins[i], binary, action); + if (lock) + { + gdk_flush(); + gdk_threads_leave(); + } + } diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h index 2804108..e77bc8b 100644 --- a/src/plugins/pglist.h +++ b/src/plugins/pglist.h @@ -45,7 +45,7 @@ GPluginModule *get_one_plugin_for_action(PluginAction); GPluginModule **get_all_plugins_for_action(PluginAction, size_t *) __attribute__ ((deprecated)); /*Opère une action donnée sur un binaire défini. */ -void run_plugins_on_binary(GLoadedBinary *, PluginAction); +void run_plugins_on_binary(GLoadedBinary *, PluginAction, bool); diff --git a/src/project.c b/src/project.c index ca49954..8a8f803 100644 --- a/src/project.c +++ b/src/project.c @@ -325,12 +325,14 @@ void g_study_project_add_loaded_binary(GLoadedBinary *binary, GStudyProject *pro { size_t index; /* Indice du nouveau binaire */ + gdk_threads_enter(); + index = g_study_project_attach_binary(project, binary); g_panel_item_dock(G_PANEL_ITEM(project->binaries[index]->item)); - //gdk_flush (); - //gdk_threads_leave(); + gdk_flush(); + gdk_threads_leave(); } -- cgit v0.11.2-87-g4458