From 12b4201890b4b2eefffaa6615b4b3076253dff6f Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 10 Nov 2008 01:28:23 +0000 Subject: Shown/hidden virtual addresses / binary code. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@41 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 35 +++++++++++ src/arch/instruction-int.h | 3 + src/arch/instruction.c | 21 +++++++ src/arch/instruction.h | 2 + src/arch/processor.c | 4 +- src/arch/processor.h | 2 +- src/binary.c | 2 +- src/easygtk.c | 38 +++++++++++ src/easygtk.h | 3 + src/editor.c | 78 ++++++++++++++++++++++- src/format/elf/symbol.c | 2 +- src/format/exe_format.c | 29 +++++++++ src/format/exe_format.h | 2 + src/gtkcodeview.c | 60 ++++++++++++++++++ src/gtkcodeview.h | 9 +++ src/gtksnippet.c | 153 ++++++++++++++++++++++++++++++++++++++------- src/gtksnippet.h | 12 ++++ 17 files changed, 429 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 13ebfed..f2a4941 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +2008-11-10 Cyrille Bagard + + * src/arch/instruction.c: + * src/arch/instruction.h: + * src/arch/instruction-int.h: + * src/arch/processor.c: + * src/arch/processor.h: + Save and provide the location and the size of an instruction. + + * src/binary.c: + Update a call to decode_instruction. + + * src/easygtk.c: + * src/easygtk.h: + Allow to create check menu items. + + * src/editor.c: + Add two extra menus to show/hide virtual addresses / binary code. + + * src/format/elf/symbol.c: + Update a call to decode_instruction. + + * src/format/exe_format.c: + * src/format/exe_format.h: + Provide the address of the loaded binary content. + + * src/gtkcodeview.c: + * src/gtkcodeview.h: + Add two functions to show/hide virtual addresses / binary code. + + * src/gtksnippet.c: + * src/gtksnippet.h: + Add two functions to show/hide virtual addresses / binary code. Extend + the building of the pango's content. + 2008-10-30 Cyrille Bagard * src/arch/processor.c: diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h index 895c29f..32c8c8c 100644 --- a/src/arch/instruction-int.h +++ b/src/arch/instruction-int.h @@ -65,6 +65,9 @@ struct _asm_instr uint64_t vaddress; /* Adresse virtuelle associée */ + off_t offset; /* Position physique de départ */ + off_t length; /* Taille de l'instruction */ + AsmInstrType type; /* Type d'instruction */ asm_operand **operands; /* Liste des opérandes */ diff --git a/src/arch/instruction.c b/src/arch/instruction.c index ada3d58..a03ced4 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -66,3 +66,24 @@ asm_instr *create_db_instruction(const uint8_t *data, off_t *pos, off_t len) } + +/****************************************************************************** +* * +* Paramètres : instr = instruction quelconque à traiter. * +* offset = position physique dans le code binaire / NULL. [OUT]* +* length = taille de l'instruction ou NULL. [OUT] * +* * +* Description : Indique la position et/ou la taille d'une instruction. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void get_asm_instr_offset_and_length(const asm_instr *instr, off_t *offset, off_t *length) +{ + if (offset != NULL) *offset = instr->offset; + if (length != NULL) *length = instr->length; + +} diff --git a/src/arch/instruction.h b/src/arch/instruction.h index 19cc6ab..6af865b 100644 --- a/src/arch/instruction.h +++ b/src/arch/instruction.h @@ -38,6 +38,8 @@ typedef struct _asm_instr asm_instr; /* Crée une instruction de type 'db' à partir de données. */ asm_instr *create_db_instruction(const uint8_t *, off_t *, off_t); +/* Indique la position et/ou la taille d'une instruction. */ +void get_asm_instr_offset_and_length(const asm_instr *, off_t *, off_t *); diff --git a/src/arch/processor.c b/src/arch/processor.c index 17f88b3..71cdfba 100644 --- a/src/arch/processor.c +++ b/src/arch/processor.c @@ -52,7 +52,7 @@ * * ******************************************************************************/ -asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, off_t *pos, off_t len, uint64_t offset) +asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, off_t *pos, off_t len, off_t off, uint64_t offset) { asm_instr *result; /* Représentation à renvoyer */ @@ -79,6 +79,8 @@ asm_instr *decode_instruction(const asm_processor *proc, const uint8_t *data, of result->vaddress = offset; + result->offset = off + old_pos; + result->length = *pos - old_pos; return result; diff --git a/src/arch/processor.h b/src/arch/processor.h index 287a761..7fc1023 100644 --- a/src/arch/processor.h +++ b/src/arch/processor.h @@ -40,7 +40,7 @@ typedef struct _asm_processor asm_processor; /* Décode une instruction dans un flux de données. */ -asm_instr *decode_instruction(const asm_processor *, const uint8_t *, off_t *, off_t, uint64_t); +asm_instr *decode_instruction(const asm_processor *, const uint8_t *, off_t *, off_t, off_t, uint64_t); /* Traduit une instruction en version humainement lisible. */ void print_hinstruction(const asm_processor *, const exe_format *, const asm_instr *, char *, size_t, AsmSyntax); diff --git a/src/binary.c b/src/binary.c index cc3fd70..4d31c40 100644 --- a/src/binary.c +++ b/src/binary.c @@ -472,7 +472,7 @@ void fill_snippet(GtkSnippet *snippet, GtkWidget *panel, GtkWidget *panel2) } - instr = decode_instruction(proc, &bin_data[start], &pos, len, offset); + instr = decode_instruction(proc, &bin_data[start], &pos, len, start, offset); item = create_code_line_info(offset, instr, NULL); diff --git a/src/easygtk.c b/src/easygtk.c index 4eb5bcd..d53b19e 100644 --- a/src/easygtk.c +++ b/src/easygtk.c @@ -362,6 +362,44 @@ GtkWidget *qck_create_menu_item(GObject *object, const char *name, const char *c /****************************************************************************** * * +* Paramètres : object = espace dédié à l'inscription de références. * +* name = nom à donner au nouveau composant. * +* caption = intitulé du menu à créer. * +* handler = éventuelle fonction de sélection associée. * +* data = données à transmettre avec l'événement si besoin. * +* * +* Description : Crée et enregistre un composant 'GtkCheckMenuItem'. * +* * +* Retour : Simple élément de menu mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *qck_create_check_menu_item(GObject *object, const char *name, const char *caption, GCallback handler, gpointer data) +{ + GtkWidget *result; /* Résultat à renvoyer */ + + result = gtk_check_menu_item_new_with_mnemonic(caption); + + if (G_IS_OBJECT(object) && name != NULL) + { + gtk_widget_ref(result); + g_object_set_data_full(object, name, result, (GtkDestroyNotify)gtk_widget_unref); + } + + gtk_widget_show(result); + + if (handler != NULL) + g_signal_connect(result, "toggled", handler, data); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Crée et enregistre un composant 'GtkSeparatorMenuItem'. * diff --git a/src/easygtk.h b/src/easygtk.h index cfd5b1a..5104588 100644 --- a/src/easygtk.h +++ b/src/easygtk.h @@ -59,6 +59,9 @@ GtkWidget *qck_create_combobox(GObject *, const char *, GCallback, gpointer); /* Crée et enregistre un composant 'GtkMenuItem'. */ GtkWidget *qck_create_menu_item(GObject *, const char *, const char *, GCallback, gpointer); +/* Crée et enregistre un composant 'GtkCheckMenuItem'. */ +GtkWidget *qck_create_check_menu_item(GObject *, const char *, const char *, GCallback, gpointer); + /* Crée et enregistre un composant 'GtkSeparatorMenuItem'. */ GtkWidget *qck_create_menu_separator(void); diff --git a/src/editor.c b/src/editor.c index a07301f..efedfca 100644 --- a/src/editor.c +++ b/src/editor.c @@ -44,7 +44,7 @@ #include #include #include -#include +//#include #include /* For SYS_write etc */ /** Partie ptrace() **/ @@ -86,6 +86,13 @@ void mcb_open_recent_project(GtkMenuItem *, gpointer); +/* Réagit avec le menu "Affichage -> Adresse virtuelle". */ +void mcb_view_vaddress(GtkCheckMenuItem *, gpointer); + +/* Réagit avec le menu "Affichage -> code binaire". */ +void mcb_view_code(GtkCheckMenuItem *, gpointer); + + /* Affiche la boîte d'ajout d'un binaire au projet courant. */ void mcb_project_add_binary(GtkMenuItem *, gpointer); @@ -495,6 +502,22 @@ GtkWidget *create_editor(void) submenubar = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenuitem), submenubar); + menuitem = gtk_menu_item_new_with_mnemonic(_("_View")); + gtk_widget_show(menuitem); + gtk_container_add(GTK_CONTAINER(menuboard), menuitem); + + menubar = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menubar); + + submenuitem = qck_create_check_menu_item(NULL, NULL, _("Virtual address"), G_CALLBACK(mcb_view_vaddress), result); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_check_menu_item(NULL, NULL, _("Binary code"), G_CALLBACK(mcb_view_code), result); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + + + menuitem = gtk_menu_item_new_with_mnemonic(_("_Project")); gtk_widget_show(menuitem); gtk_container_add(GTK_CONTAINER(menuboard), menuitem); @@ -934,6 +957,59 @@ void mcb_open_recent_project(GtkMenuItem *menuitem, gpointer data) +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu ayant basculé. * +* data = adresse de l'espace de référencement global. * +* * +* Description : Réagit avec le menu "Affichage -> Adresse virtuelle". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mcb_view_vaddress(GtkCheckMenuItem *menuitem, gpointer data) +{ + GtkCodeview *codeview; /* Zone de code principale */ + gboolean active; /* Etat de sélection du menu */ + + codeview = GTK_CODE_VIEW(g_object_get_data(G_OBJECT(data), "codeview")); + active = gtk_check_menu_item_get_active(menuitem); + + gtk_codeview_show_vaddress(codeview, active); + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu ayant basculé. * +* data = adresse de l'espace de référencement global. * +* * +* Description : Réagit avec le menu "Affichage -> code binaire". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void mcb_view_code(GtkCheckMenuItem *menuitem, gpointer data) +{ + GtkCodeview *codeview; /* Zone de code principale */ + gboolean active; /* Etat de sélection du menu */ + + codeview = GTK_CODE_VIEW(g_object_get_data(G_OBJECT(data), "codeview")); + active = gtk_check_menu_item_get_active(menuitem); + + gtk_codeview_show_code(codeview, active); + +} + + + /****************************************************************************** diff --git a/src/format/elf/symbol.c b/src/format/elf/symbol.c index 4b7740d..c8a0dac 100644 --- a/src/format/elf/symbol.c +++ b/src/format/elf/symbol.c @@ -513,7 +513,7 @@ asm_instr **decode_elf_relocations(elf_format *format, size_t *count) { offset = rel_vaddress + pos; - instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, offset); + instr = decode_instruction(proc, &EXE_FORMAT(format)->content[rel_start], &pos, rel_size, 0/* FIXME*/, offset); result = (asm_instr **)realloc(result, ++(*count) * sizeof(asm_instr *)); result[*count - 1] = instr; diff --git a/src/format/exe_format.c b/src/format/exe_format.c index 30976f1..7fcbcfb 100644 --- a/src/format/exe_format.c +++ b/src/format/exe_format.c @@ -166,6 +166,35 @@ void delete_bin_part(bin_part *part) /* ---------------------------------------------------------------------------------- */ + + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à consulter. * +* target = nom de la section recherchée. * +* length = taille du contenu à fournir. [OUT] * +* * +* Description : Fournit une référence vers le contenu binaire analysé. * +* * +* Retour : Adresse du tampon contenant le contenu du binaire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const uint8_t *get_exe_content(const exe_format *format, off_t *length) +{ + if (length != NULL) *length = format->length; + + return format->content; + +} + + + + /****************************************************************************** * * * Paramètres : format = description de l'exécutable à consulter. * diff --git a/src/format/exe_format.h b/src/format/exe_format.h index 9be91fb..8e4932f 100644 --- a/src/format/exe_format.h +++ b/src/format/exe_format.h @@ -78,6 +78,8 @@ typedef enum _ResolvedType } ResolvedType; +/* Fournit une référence vers le contenu binaire analysé. */ +const uint8_t *get_exe_content(const exe_format *, off_t *); /* Recherche une section donnée au sein de binaire. */ bool find_exe_section(const exe_format *, const char *, off_t *, off_t *, uint64_t *); diff --git a/src/gtkcodeview.c b/src/gtkcodeview.c index 1062aaf..78d3b24 100644 --- a/src/gtkcodeview.c +++ b/src/gtkcodeview.c @@ -119,6 +119,66 @@ GtkWidget* gtk_codeview_new(void) +/****************************************************************************** +* * +* Paramètres : codeview = composant GTK à manipuler. * +* show = état de l'affichage auquel parvenir. * +* * +* Description : Choisit d'afficher les adresses virtuelles ou non. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_codeview_show_vaddress(GtkCodeview *codeview, gboolean show) +{ + GList *list; /* Ensemble des enfants */ + GList *iter; /* Boucle de parcours */ + + list = gtk_container_get_children(GTK_CONTAINER(codeview)); + + for (iter = g_list_first(list); iter != NULL; iter = g_list_next(iter)) + gtk_snippet_show_vaddress(GTK_SNIPPET(iter->data), show); + + g_list_free(list); + +} + + +/****************************************************************************** +* * +* Paramètres : codeview = composant GTK à manipuler. * +* show = état de l'affichage auquel parvenir. * +* * +* Description : Choisit d'afficher le code brut ou non. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_codeview_show_code(GtkCodeview *codeview, gboolean show) +{ + GList *list; /* Ensemble des enfants */ + GList *iter; /* Boucle de parcours */ + + list = gtk_container_get_children(GTK_CONTAINER(codeview)); + + for (iter = g_list_first(list); iter != NULL; iter = g_list_next(iter)) + gtk_snippet_show_code(GTK_SNIPPET(iter->data), show); + + g_list_free(list); + +} + + + + + + /****************************************************************************** * * diff --git a/src/gtkcodeview.h b/src/gtkcodeview.h index 18bec6e..d1dd308 100644 --- a/src/gtkcodeview.h +++ b/src/gtkcodeview.h @@ -52,6 +52,15 @@ GType gtk_codeview_get_type(void); GtkWidget* gtk_codeview_new(void); + +/* Choisit d'afficher les adresses virtuelles ou non. */ +void gtk_codeview_show_vaddress(GtkCodeview *, gboolean); + +/* Choisit d'afficher le code brut ou non. */ +void gtk_codeview_show_code(GtkCodeview *, gboolean); + + + /* S'assure qu'une adresse donnée est visible à l'écran. */ void gtk_codeview_scroll_to_address(GtkCodeview *, uint64_t); diff --git a/src/gtksnippet.c b/src/gtksnippet.c index 3254d8e..3fc8ccc 100644 --- a/src/gtksnippet.c +++ b/src/gtksnippet.c @@ -446,6 +446,48 @@ void gtk_snippet_test(GtkSnippet *snippet) +/****************************************************************************** +* * +* Paramètres : snippet = composant GTK à mettre à jour. * +* show = état de l'affichage auquel parvenir. * +* * +* Description : Choisit d'afficher les adresses virtuelles ou non. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_snippet_show_vaddress(GtkSnippet *snippet, gboolean show) +{ + snippet->show_vaddress = show; + + gtk_snippet_build_content(snippet); + +} + + +/****************************************************************************** +* * +* Paramètres : snippet = composant GTK à mettre à jour. * +* show = état de l'affichage auquel parvenir. * +* * +* Description : Choisit d'afficher le code brut ou non. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_snippet_show_code(GtkSnippet *snippet, gboolean show) +{ + snippet->show_code = show; + + gtk_snippet_build_content(snippet); + +} @@ -527,17 +569,46 @@ void gtk_snippet_add_line(GtkSnippet *snippet, const code_line_info *line) void gtk_snippet_build_content(GtkSnippet *snippet) { + const uint8_t *exe_content; /* Contenu binaire global */ + off_t max_bin_len; /* Taille max du code brut */ + unsigned int i; /* Boucle de traitement */ + off_t bin_len; /* Taille d'instruction */ + char *bin_code; /* Tampon du code binaire */ char *content; /* Contenu à définir */ size_t content_len; /* Taille du contenu */ AdressMode mode; /* Affichage des adresses */ - unsigned int i; /* Boucle de traitement */ char buffer[CONTENT_BUFFER_LEN]; /* Zone tampon à utiliser */ + off_t bin_offset; /* Début de l'instruction */ + off_t k; /* Boucle de parcours #2 */ + off_t j; /* Boucle de parcours #1 */ int width; /* Largeur de l'objet actuelle */ int height; /* Hauteur de l'objet actuelle */ PangoLayoutIter *iter; /* Boucle de parcours */ int y0; /* Ordonnée du haut d'une ligne*/ int y1; /* Ordonnée du bas d'une ligne */ + /* Calcul de la largeur maximale brute si besoin est */ + if (snippet->show_code) + { + exe_content = get_exe_content(snippet->format, NULL); + + max_bin_len = 1; + + for (i = 0; i < snippet->info_count; i++) + { + /* Commentaire uniquement */ + if (snippet->info[i].instr == NULL) continue; + + get_asm_instr_offset_and_length(snippet->info[i].instr, NULL, &bin_len); + if (bin_len > max_bin_len) max_bin_len = bin_len; + + } + + max_bin_len = max_bin_len * 2 + (max_bin_len - 1); + bin_code = (char *)calloc(max_bin_len + 1, sizeof(char)); + + } + content_len = strlen("") + 1; content = (char *)calloc(content_len, sizeof(char)); strcpy(content, ""); @@ -552,27 +623,62 @@ void gtk_snippet_build_content(GtkSnippet *snippet) strcat(content, "\n"); } - /* Adresse */ + /* Eventuelle adresse virtuelle */ - switch (mode) + if (snippet->show_vaddress) { - case ADM_32BITS: - snprintf(buffer, CONTENT_BUFFER_LEN, - "0x%08llx", - snippet->info[i].offset); - break; - - case ADM_64BITS: - snprintf(buffer, CONTENT_BUFFER_LEN, - "0x%16llx", - snippet->info[i].offset); - break; + switch (mode) + { + case ADM_32BITS: + snprintf(buffer, CONTENT_BUFFER_LEN, + "0x%08llx", + snippet->info[i].offset); + break; + + case ADM_64BITS: + snprintf(buffer, CONTENT_BUFFER_LEN, + "0x%16llx", + snippet->info[i].offset); + break; + + } + + content_len += strlen(buffer); + content = (char *)realloc(content, content_len * sizeof(char)); + strcat(content, buffer); } - content_len += strlen(buffer); - content = (char *)realloc(content, content_len * sizeof(char)); - strcat(content, buffer); + /* Eventuel code brut */ + + if (snippet->show_code) + { + k = 0; + + if (snippet->info[i].instr != NULL) + { + get_asm_instr_offset_and_length(snippet->info[i].instr, &bin_offset, &bin_len); + + for (j = 0; j < bin_len; j++) + { + if ((j + 1) < bin_len) + k += snprintf(&bin_code[j * (2 + 1)], 4, "%02hhx ", exe_content[bin_offset + j]); + else + k += snprintf(&bin_code[j * (2 + 1)], 3, "%02hhx", exe_content[bin_offset + j]); + } + + } + + for (; k < max_bin_len; k++) + snprintf(&bin_code[k], 2, " "); + + if (snippet->show_vaddress) content_len += strlen("\t"); + content_len += strlen(bin_code); + content = (char *)realloc(content, content_len * sizeof(char)); + if (snippet->show_vaddress) strcat(content, "\t"); + strcat(content, bin_code); + + } /* Eventuelle instruction */ @@ -580,10 +686,11 @@ void gtk_snippet_build_content(GtkSnippet *snippet) { print_hinstruction(snippet->proc, snippet->format, snippet->info[i].instr, buffer, CONTENT_BUFFER_LEN, ASX_INTEL); - content_len += strlen("\t") + strlen(buffer); + if (snippet->show_vaddress || snippet->show_code) content_len += strlen("\t"); + content_len += strlen(buffer); content = (char *)realloc(content, content_len * sizeof(char)); - strcat(content, "\t"); + if (snippet->show_vaddress || snippet->show_code) strcat(content, "\t"); strcat(content, buffer); } @@ -592,10 +699,12 @@ void gtk_snippet_build_content(GtkSnippet *snippet) if (snippet->info[i].comment != NULL) { - content_len += strlen("\t; ") + strlen(snippet->info[i].comment) + strlen(""); + if (snippet->show_vaddress || snippet->show_code) content_len += strlen("\t"); + content_len += strlen("; ") + strlen(snippet->info[i].comment) + strlen(""); content = (char *)realloc(content, content_len * sizeof(char)); - strcat(content, "\t; "); + if (snippet->show_vaddress || snippet->show_code) strcat(content, "\t"); + strcat(content, "; "); strcat(content, snippet->info[i].comment); strcat(content, ""); @@ -607,6 +716,8 @@ void gtk_snippet_build_content(GtkSnippet *snippet) content = (char *)realloc(content, content_len * sizeof(char)); strcat(content, ""); + if (snippet->show_code) free(bin_code); + pango_layout_set_markup(snippet->layout, content, content_len - 1); pango_layout_get_pixel_size(snippet->layout, &width, &height); diff --git a/src/gtksnippet.h b/src/gtksnippet.h index 016787c..a4e2eb5 100644 --- a/src/gtksnippet.h +++ b/src/gtksnippet.h @@ -92,6 +92,9 @@ struct _GtkSnippet { AdressMode mode; /* Mode d'affichage */ + bool show_vaddress; /* Affichage des adresses ? */ + bool show_code; /* Affichage du code brut ? */ + PangoLayout *layout; /* Moteur de rendu du code ASM */ GdkGC *gc; /* Contexte graphique du rendu */ int line_height; /* Hauteur maximale des lignes */ @@ -121,6 +124,15 @@ GtkWidget * gtk_snippet_new(); void gtk_snippet_test(GtkSnippet *cpu); +/* Choisit d'afficher les adresses virtuelles ou non. */ +void gtk_snippet_show_vaddress(GtkSnippet *, gboolean); + +/* Choisit d'afficher le code brut ou non. */ +void gtk_snippet_show_code(GtkSnippet *, gboolean); + + + + /* Définit le format auquel le contenu est lié. */ void gtk_snippet_set_format(GtkSnippet *, const exe_format *); -- cgit v0.11.2-87-g4458