From 3669bdaf8552f53baa5cfb2b0d360959eea61236 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 22 Nov 2012 19:51:17 +0000 Subject: Rewritten parts of the Android plugin to insert indications about exceptions. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@288 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 14 ++ plugins/androhelpers/try_n_catch.c | 297 ++++++++++++++++++++++++------------- src/glibext/gbufferline.c | 10 ++ src/glibext/gbufferline.h | 1 + src/glibext/gbuffersegment.c | 3 + src/glibext/gcodebuffer.c | 175 ++++++++++++++++++---- src/glibext/gcodebuffer.h | 6 + 7 files changed, 369 insertions(+), 137 deletions(-) diff --git a/ChangeLog b/ChangeLog index f5e628d..e1d758a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +12-11-22 Cyrille Bagard + + * plugins/androhelpers/try_n_catch.c: + Rewrite parts of the Android plugin to insert indications about exceptions. + + * src/glibext/gbufferline.c: + * src/glibext/gbufferline.h: + * src/glibext/gbuffersegment.c: + Introduce a new style for code indications. + + * src/glibext/gcodebuffer.c: + * src/glibext/gcodebuffer.h: + Add a function to complete in order to insert line at given addresses. + 12-11-20 Cyrille Bagard * src/gui/panels/glance.c: diff --git a/plugins/androhelpers/try_n_catch.c b/plugins/androhelpers/try_n_catch.c index fc7b2bb..7db0f70 100644 --- a/plugins/androhelpers/try_n_catch.c +++ b/plugins/androhelpers/try_n_catch.c @@ -25,6 +25,7 @@ #include +#include #include @@ -36,6 +37,7 @@ /* Mémorisation d'un lien vers un gestionnaire */ typedef struct _caught_exception { + vmpa_t addr; /* Adresse du code de gestion */ GArchInstruction *instr; /* Première instruction visée */ char *desc; /* Nom de l'exception */ @@ -46,14 +48,17 @@ typedef struct _caught_exception /* Valide la zone couverte par le gestionnaire d'exceptions. */ static bool check_covered_area(const try_item *, const GBinRoutine *); -/* Construit une liste pointant sur les différentes gestions. */ -static caught_exception *build_destinations_list(GLoadedBinary *, const try_item *, const encoded_catch_handler_list *, const GBinRoutine *, size_t *); - /* Rattache les gestionnaires d'exception à leur code couvert. */ -static void attach_caught_code(GLoadedBinary *, const try_item *, const encoded_catch_handler_list *, const GBinRoutine *); +static void attach_caught_code(const GLoadedBinary *, const GBinRoutine *, const try_item *, const caught_exception *, size_t); + +/* Insère des indications dans le texte humainement lisible. */ +static void mark_exception_handlers(const GLoadedBinary *, uleb128_t, caught_exception **, size_t *); + +/* Construit des listes pointant sur les différentes gestions. */ +static caught_exception **build_all_destinations_list(const GLoadedBinary *, const GBinRoutine *, const encoded_catch_handler_list *, size_t **); /* Recherche et met en avant tous les gestionnaires d'exception. */ -static void look_for_exception_handlers(GLoadedBinary *, const GDexFormat *, GDexMethod *); +static void look_for_exception_handlers(const GLoadedBinary *, const GDexFormat *, GDexMethod *); @@ -88,169 +93,210 @@ static bool check_covered_area(const try_item *try, const GBinRoutine *routine) /****************************************************************************** * * -* Paramètres : binary = représentation binaire à traiter. * -* try = informations sur la gestion à consulter. * -* hlist = liste de tous les gestionnaires en place. * -* routine = routine associée, pour l'accès au instructions. * -* count = quantité de destinations trouvées. [OUT] * +* Paramètres : binary = représentation binaire à traiter. * +* routine = routine associée, pour l'accès au instructions. * +* try = informations sur la gestion à consulter. * +* handlers = arrivées des liens vers les gestionnaires. * +* count = nombre de ces arrivées. * * * -* Description : Construit une liste pointant sur les différentes gestions. * +* Description : Rattache les gestionnaires d'exception à leur code couvert. * * * -* Retour : Adresse des codes à lier systématiquement. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static caught_exception *build_destinations_list(GLoadedBinary *binary, const try_item *try, const encoded_catch_handler_list *hlist, const GBinRoutine *routine, size_t *count) +static void attach_caught_code(const GLoadedBinary *binary, const GBinRoutine *routine, const try_item *try, const caught_exception *handlers, size_t count) { - caught_exception *result; /* Liste à retourner */ - GDexFormat *format; /* Format du binaire chargé */ - vmpa_t start; /* Début du code de la routine */ + vmpa_t start; /* Début de la zone couverte */ + vmpa_t end; /* Début de la zone couverte */ GArchInstruction *instrs; /* Instructions Dalvik */ - uleb128_t index; /* Indice du bon gestionnaire */ - encoded_catch_handler *handlers; /* Groupe de gestionnaires */ - leb128_t max; /* Quantité d'exception */ - leb128_t i; /* Boucle de parcours */ - vmpa_t handler_addr; /* Adresse du code de gestion */ - GDataType *type; /* Type de l'exception */ - - format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); + GArchInstruction *first; /* Première instruction */ + GArchInstruction *next; /* Dernière instruction + 1 */ + GArchInstruction *prev; /* Instruction à détacher */ + GArchInstruction *iter; /* Boucle de parcours */ + size_t i; /* Boucle de parcours */ start = g_binary_routine_get_address(routine); + start += try->start_addr * sizeof(uint16_t); + + end = start + try->insn_count * sizeof(uint16_t); instrs = g_loaded_binary_get_instructions(binary); - instrs = g_arch_instruction_find_by_address(instrs, start, true); + first = g_arch_instruction_find_by_address(instrs, start, true); + next = g_arch_instruction_find_by_address(instrs, end, true); - for (index = 0; index < hlist->size; index++) - if (try->handler_off == hlist->list[index].offset) - break; + /* Si des détachements sont nécessaires... */ - if (index == hlist->size) + if (!g_arch_instruction_has_sources(first)) { - *count = 0; - return NULL; + prev = g_arch_instruction_get_prev_iter(instrs, first); + g_arch_instruction_link_with(prev, first, ILT_EXEC_FLOW); } - handlers = &hlist->list[index]; - max = leb128_abs(handlers->size); - - *count = max + (handlers->size < 0 ? 1 : 0); - result = (caught_exception *)calloc(*count, sizeof(caught_exception)); + if (!g_arch_instruction_has_sources(next)) + { + prev = g_arch_instruction_get_prev_iter(instrs, next); + g_arch_instruction_link_with(prev, next, ILT_EXEC_FLOW); + } - *count = 0; + /* Rattachements ? */ - for (i = 0; i < max; i++) + if (handlers != NULL) { - handler_addr = start + handlers->handlers[i].addr * sizeof(uint16_t); - result[*count].instr = g_arch_instruction_find_by_address(instrs, handler_addr, true); - - if (result[*count].instr == NULL) - continue; + for (iter = first; + iter != NULL; + iter = g_arch_instruction_get_next_iter(instrs, iter, end)) + { + if (!g_arch_instruction_has_destinations(iter)) + continue; - type = get_type_from_dex_pool(format, handlers->handlers[i].type_idx); - result[*count].desc = g_data_type_to_string(type); + for (i = 0; i < count; i++) + g_arch_instruction_link_with(iter, handlers[i].instr, ILT_CATCH_EXCEPTION); - (*count)++; + } } - if (handlers->size < 0) - { - handler_addr = start + handlers->catch_all_addr * sizeof(uint16_t); - result[*count].instr = g_arch_instruction_find_by_address(instrs, handler_addr, true); +} - if (result[*count].instr != NULL) + +/****************************************************************************** +* * +* Paramètres : binary = représentation binaire à traiter. * +* size = nombre de groupe à parcourir. * +* handlers = ensemble des groupes de gestionnaires. * +* count = liste des quantités de gestionnaires groupés. * +* * +* Description : Insère des indications dans le texte humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mark_exception_handlers(const GLoadedBinary *binary, uleb128_t size, caught_exception **handlers, size_t *count) +{ + GCodeBuffer *buffer; /* Contenu textuel à modifier */ + uleb128_t i; /* Boucle de parcours #1 */ + size_t j; /* Boucle de parcours #2 */ + GBufferLine *line; /* Nouvelle ligne à compléter */ + size_t len; /* Taille de la description */ + char *fulldesc; /* Description complète */ + + buffer = g_loaded_binary_get_disassembled_buffer(binary); + + for (i = 0; i < size; i++) + for (j = 0; j < count[i]; j++) { - result[*count].desc = strdup(_("default")); - (*count)++; - } + line = g_code_buffer_insert_at(buffer, handlers[i][j].addr, true); + g_buffer_line_start_merge_at(line, BLC_ASSEMBLY_HEAD); - } + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, "; ", 2, RTT_INDICATION); - return result; + len = strlen(_("Handler for caught '%s'")) + strlen(handlers[i][j].desc); + fulldesc = (char *)calloc(len + 1, sizeof(char)); + snprintf(fulldesc, len + 1, _("Handler for caught '%s'"), handlers[i][j].desc); + + g_buffer_line_insert_text(line, BLC_ASSEMBLY_HEAD, fulldesc, len, RTT_INDICATION); + + free(fulldesc); + + } } /****************************************************************************** * * -* Paramètres : binary = représentation binaire à traiter. * -* try = informations sur la gestion à consulter. * -* handlers = liste de tous les gestionnaires en place. * -* routine = routine associée, pour l'accès au instructions. * +* Paramètres : binary = représentation binaire à traiter. * +* routine = routine associée, pour l'accès au instructions. * +* hlist = liste de tous les gestionnaires en place. * +* count = quantité de destinations trouvées. [OUT] * * * -* Description : Rattache les gestionnaires d'exception à leur code couvert. * +* Description : Construit des listes pointant sur les différentes gestions. * * * -* Retour : - * +* Retour : Adresses des codes à lier systématiquement. * * * * Remarques : - * * * ******************************************************************************/ -static void attach_caught_code(GLoadedBinary *binary, const try_item *try, const encoded_catch_handler_list *handlers, const GBinRoutine *routine) +static caught_exception **build_all_destinations_list(const GLoadedBinary *binary, const GBinRoutine *routine, const encoded_catch_handler_list *hlist, size_t **count) { - vmpa_t start; /* Début de la zone couverte */ - vmpa_t end; /* Début de la zone couverte */ + caught_exception **result; /* Liste de listes à retourner */ + GDexFormat *format; /* Format du binaire chargé */ + vmpa_t start; /* Début du code de la routine */ GArchInstruction *instrs; /* Instructions Dalvik */ - GArchInstruction *first; /* Première instruction */ - GArchInstruction *next; /* Dernière instruction + 1 */ - GArchInstruction *prev; /* Instruction à détacher */ - GArchInstruction *iter; /* Boucle de parcours */ - size_t dests_count; /* Nombre de points d'arrivée */ - caught_exception *dests; /* Points d'arrivée */ - size_t i; /* Boucle de parcours */ + uleb128_t i; /* Boucle de parcours #1 */ + encoded_catch_handler *handlers; /* Groupe de gestionnaires */ + leb128_t max; /* Quantité d'exception */ + leb128_t j; /* Boucle de parcours #2 */ + caught_exception *excep; /* Raccourci confortable */ + GDataType *type; /* Type de l'exception */ - start = g_binary_routine_get_address(routine); - start += try->start_addr * sizeof(uint16_t); + format = G_DEX_FORMAT(g_loaded_binary_get_format(binary)); - end = start + try->insn_count * sizeof(uint16_t); + start = g_binary_routine_get_address(routine); instrs = g_loaded_binary_get_instructions(binary); - first = g_arch_instruction_find_by_address(instrs, start, true); - next = g_arch_instruction_find_by_address(instrs, end, true); + instrs = g_arch_instruction_find_by_address(instrs, start, true); - /* Si des détachements sont nécessaires... */ + /* Création d'un espace mémoire pour les listes */ - if (!g_arch_instruction_has_sources(first)) - { - prev = g_arch_instruction_get_prev_iter(instrs, first); - g_arch_instruction_link_with(prev, first, ILT_EXEC_FLOW); - } + result = (caught_exception **)calloc(hlist->size, sizeof(caught_exception *)); + *count = (size_t *)calloc(hlist->size, sizeof(size_t)); - if (!g_arch_instruction_has_sources(next)) + /* Parcours de chaque groupe de gestionnaires */ + + for (i = 0; i < hlist->size; i++) { - prev = g_arch_instruction_get_prev_iter(instrs, next); - g_arch_instruction_link_with(prev, next, ILT_EXEC_FLOW); - } + handlers = &hlist->list[i]; + max = leb128_abs(handlers->size); - /* Détermination du code des exceptions */ - dests = build_destinations_list(binary, try, handlers, routine, &dests_count); + (*count)[i] = max + (handlers->size < 0 ? 1 : 0); + result[i] = (caught_exception *)calloc((*count)[i], sizeof(caught_exception)); - if (dests != NULL) - { - /* Rattachements */ - for (iter = first; - iter != NULL; - iter = g_arch_instruction_get_next_iter(instrs, iter, end)) + (*count)[i] = 0; + + for (j = 0; j < max; j++) { - if (!g_arch_instruction_has_destinations(iter)) + excep = &result[i][(*count)[i]]; + + excep->addr = start + handlers->handlers[j].addr * sizeof(uint16_t); + excep->instr = g_arch_instruction_find_by_address(instrs, excep->addr, true); + + if (excep->instr == NULL) continue; - for (i = 0; i < dests_count; i++) - g_arch_instruction_link_with(iter, dests[i].instr, ILT_CATCH_EXCEPTION); + type = get_type_from_dex_pool(format, handlers->handlers[j].type_idx); + excep->desc = g_data_type_to_string(type); + + (*count)[i]++; } - /* Libération de la mémoire utilisée */ + if (handlers->size < 0) + { + excep = &result[i][(*count)[i]]; - for (i = 0; i < dests_count; i++) - free(dests[i].desc); + excep->addr = start + handlers->catch_all_addr * sizeof(uint16_t); + excep->instr = g_arch_instruction_find_by_address(instrs, excep->addr, true); - free(dests); + if (excep->instr != NULL) + { + excep->desc = strdup(_("default")); + (*count)[i]++; + } + + } } + return result; + } @@ -268,11 +314,17 @@ static void attach_caught_code(GLoadedBinary *binary, const try_item *try, const * * ******************************************************************************/ -static void look_for_exception_handlers(GLoadedBinary *binary, const GDexFormat *format, GDexMethod *method) +static void look_for_exception_handlers(const GLoadedBinary *binary, const GDexFormat *format, GDexMethod *method) { const code_item *body; /* Description du corps */ GBinRoutine *routine; /* Abstraction globale */ - uint16_t i; /* Boucle de parcours */ + encoded_catch_handler_list *hlist; /* Confort vers la liste brute */ + caught_exception **handlers; /* Interprétation des gestions */ + size_t *count; /* Tailles des groupes */ + uint16_t i; /* Boucle de parcours #1 */ + try_item *try; /* Raccourci vers une zone */ + uleb128_t index; /* Indice du bon gestionnaire */ + size_t j; /* Boucle de parcours #2 */ body = g_dex_method_get_dex_body(method); @@ -281,15 +333,48 @@ static void look_for_exception_handlers(GLoadedBinary *binary, const GDexFormat routine = g_dex_method_get_routine(method); + hlist = body->handlers; + handlers = build_all_destinations_list(binary, routine, hlist, &count); + + /* Pour chaque zone couverte... */ + for (i = 0; i < body->tries_size; i++) { - if (!check_covered_area(&body->tries[i], routine)) + try = &body->tries[i]; + + if (!check_covered_area(try, routine)) continue; - attach_caught_code(binary, &body->tries[i], body->handlers, routine); + for (index = 0; index < hlist->size; index++) + if (try->handler_off == hlist->list[index].offset) + break; + + if (index == hlist->size) + continue; + + attach_caught_code(binary, routine, try, handlers[index], count[index]); + + } + + /* Ajout des précisions */ + + mark_exception_handlers(binary, hlist->size, handlers, count); + + /* Libération de la mémoire utilisée */ + + for (index = 0; index < hlist->size; index++) + { + for (j = 0; j < count[index]; j++) + free(handlers[index][j].desc); + + if (handlers[index] != NULL) + free(handlers[index]); } + if (handlers != NULL) free(handlers); + if (count != NULL) free(count); + } diff --git a/src/glibext/gbufferline.c b/src/glibext/gbufferline.c index ce3e19f..c8ff5f2 100644 --- a/src/glibext/gbufferline.c +++ b/src/glibext/gbufferline.c @@ -345,6 +345,16 @@ static void g_buffer_line_class_init(GBufferLineClass *class) attrib = pango_attr_foreground_new(14335, 45311, 23551); pango_attr_list_insert(class->attribs[RTT_COMMENT], attrib); + /* RTT_INDICATION */ + + class->attribs[RTT_INDICATION] = pango_attr_list_new(); + + attrib = pango_attr_foreground_new(33410, 33410, 33410); + pango_attr_list_insert(class->attribs[RTT_INDICATION], attrib); + + attrib = pango_attr_style_new(PANGO_STYLE_ITALIC); + pango_attr_list_insert(class->attribs[RTT_INDICATION], attrib); + /* RTT_RAW_CODE */ class->attribs[RTT_RAW_CODE] = pango_attr_list_new(); diff --git a/src/glibext/gbufferline.h b/src/glibext/gbufferline.h index 3cc992b..670df99 100644 --- a/src/glibext/gbufferline.h +++ b/src/glibext/gbufferline.h @@ -71,6 +71,7 @@ typedef enum _RenderingTagType RTT_RAW, /* Contenu brut */ RTT_COMMENT, /* Commentaire */ + RTT_INDICATION, /* Aide à la lecture */ RTT_RAW_CODE, /* Code binaire brut */ RTT_INSTRUCTION, /* Code binaire brut */ diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c index 5125631..9510fa2 100644 --- a/src/glibext/gbuffersegment.c +++ b/src/glibext/gbuffersegment.c @@ -231,6 +231,9 @@ static void g_buffer_segment_prepare(GBufferSegment *segment, PangoContext *cont attrib = pango_attr_iterator_get(iterator, PANGO_ATTR_WEIGHT); must_use_pango |= (attrib != NULL); + attrib = pango_attr_iterator_get(iterator, PANGO_ATTR_STYLE); + must_use_pango |= (attrib != NULL); + pango_attr_iterator_destroy(iterator); if (must_use_pango) diff --git a/src/glibext/gcodebuffer.c b/src/glibext/gcodebuffer.c index aec3303..4ffc15a 100644 --- a/src/glibext/gcodebuffer.c +++ b/src/glibext/gcodebuffer.c @@ -121,6 +121,9 @@ static void g_code_buffer_class_init(GCodeBufferClass *); static void g_code_buffer_init(GCodeBuffer *); /* Convertit une adresse en indice de ligne. */ +static size_t _g_code_buffer_get_index_from_address(GCodeBuffer *, vmpa_t); + +/* Convertit une adresse en indice de ligne. */ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *, vmpa_t); @@ -292,15 +295,16 @@ static void g_buffer_scan_process(GBufferScan *scan, GtkExtStatusBar *statusbar) id = gtk_extended_status_bar_push(statusbar, scan->message, true); - for (i = first; i <= last; i++) - { - if (!scan->process(scan->buffer, lines[i], scan->user_data)) - break; + if (scan->buffer->used > 0) + for (i = first; i <= last; i++) + { + if (!scan->process(scan->buffer, lines[i], scan->user_data)) + break; - gtk_extended_status_bar_update_activity(statusbar, id, - (i - first) * 1.0 / (last - first)); + gtk_extended_status_bar_update_activity(statusbar, id, + (i - first) * 1.0 / (last - first)); - } + } /* TODO : unlock scan->buffer->lines */ @@ -380,6 +384,7 @@ GCodeBuffer *g_code_buffer_new(void) } + /****************************************************************************** * * * Paramètres : buffer = composant GTK à mettre à jour. * @@ -393,17 +398,48 @@ GCodeBuffer *g_code_buffer_new(void) * * ******************************************************************************/ -static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, vmpa_t addr) +static size_t _g_code_buffer_get_index_from_address(GCodeBuffer *buffer, vmpa_t addr) { size_t result; /* Indice à retourner */ if (addr == VMPA_MAX) return (buffer->used > 0 ? buffer->used - 1 : 0); + /* TODO : coder un parcours plus optimal ! */ + for (result = 0; result < buffer->used; result++) if (g_buffer_line_get_address(buffer->lines[result]) == addr) break; + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : buffer = composant GTK à mettre à jour. * +* addr = adresse où va se situer la ligne. * +* * +* Description : Convertit une adresse en indice de ligne. * +* * +* Retour : Indice de l'adresse trouvée, ou 0 en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, vmpa_t addr) +{ + size_t result; /* Indice à retourner */ + + result = _g_code_buffer_get_index_from_address(buffer, addr); + + /** + * Par commodités, on évite certaines instructions en cas d'échec dans les + * fonctions d'appels : la condition des boucles utilisant l'indice retourné (0) + * fait son office directement ! + */ if (result == buffer->used) result = 0; @@ -419,7 +455,7 @@ static size_t g_code_buffer_get_index_from_address(GCodeBuffer *buffer, vmpa_t a * * * Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. * * * -* Retour : - * +* Retour : Nouvelle ligne vierge à écrire. * * * * Remarques : - * * * @@ -451,6 +487,82 @@ GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, vmpa_t addr) /****************************************************************************** * * * Paramètres : buffer = composant GTK à mettre à jour. * +* addr = adresse où va se situer la ligne. * +* before = emplacement de l'insertion. * +* * +* Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. * +* * +* Retour : Nouvelle ligne vierge à écrire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_code_buffer_insert_at(GCodeBuffer *buffer, vmpa_t addr, bool before) +{ + GBufferLine *result; /* Instance à retourner */ + size_t index; /* Indice de la ligne visée */ + + index = _g_code_buffer_get_index_from_address(buffer, addr); + if (index == buffer->used) return NULL; + + if (buffer->used == buffer->count) + { + buffer->count += LINE_ALLOC_BULK; + buffer->lines = (GBufferLine **)realloc(buffer->lines, + buffer->count * sizeof(GBufferLine *)); + } + + if (before) + { + memmove(&buffer->lines[index + 1], &buffer->lines[index], + sizeof(GBufferLine *) * (buffer->used - index)); + + buffer->used++; + + result = g_buffer_line_new(addr); + buffer->lines[index] = result; + + } + + + else + /* FIXME */ + ; + + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : buffer = composant GTK à mettre à jour. * +* line = point d'insertion. * +* * +* Description : Ajoute une nouvelle ligne à un tampon pour code désassemblé. * +* * +* Retour : Nouvelle ligne vierge à écrire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GBufferLine *g_code_buffer_insert_after(GCodeBuffer *buffer, GBufferLine *line) +{ + + /* FIXME */ + + return NULL; + + +} + + +/****************************************************************************** +* * +* Paramètres : buffer = composant GTK à mettre à jour. * * addr = adresse où retrouver la ligne recherchée. * * * * Description : Retrouve une ligne au sein d'un tampon avec une adresse. * @@ -464,15 +576,14 @@ GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *buffer, vmpa_t addr) GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *buffer, vmpa_t addr) { GBufferLine *result; /* Instance à retourner */ - size_t i; /* Boucle de parcours */ + size_t index; /* Indice de la ligne visée */ - result = NULL; + index = _g_code_buffer_get_index_from_address(buffer, addr); - /* TODO : coder un parcours plus optimal ! */ - - for (i = 0; i < buffer->used && result == NULL; i++) - if (g_buffer_line_get_address(buffer->lines[i]) == addr) - result = buffer->lines[i]; + if (index == buffer->used) + result = NULL; + else + result = buffer->lines[index]; return result; @@ -749,12 +860,13 @@ static void g_buffer_view_compute_required_widths(GBufferView *view) view->left_margin = 2 * view->line_height; view->left_text = 2.5 * view->line_height; - for (i = first; i <= last; i++) - for (j = 0; j < BLC_COUNT; j++) - { - width = g_buffer_line_get_width(lines[i], j); - view->max_widths[j] = MAX(view->max_widths[j], width); - } + if (view->buffer->used > 0) + for (i = first; i <= last; i++) + for (j = 0; j < BLC_COUNT; j++) + { + width = g_buffer_line_get_width(lines[i], j); + view->max_widths[j] = MAX(view->max_widths[j], width); + } } @@ -1086,19 +1198,20 @@ bool g_buffer_view_get_address_coordinates(GBufferView *view, vmpa_t addr, gint first = g_code_buffer_get_index_from_address(view->buffer, view->start); last = g_code_buffer_get_index_from_address(view->buffer, view->end); - for (i = first; i <= last; i++) - { - current = g_buffer_line_get_address(view->buffer->lines[i]); + if (view->buffer->used > 0) + for (i = first; i <= last; i++) + { + current = g_buffer_line_get_address(view->buffer->lines[i]); - if (current == addr) - break; + if (current == addr) + break; - if (current > addr) - return false; + if (current > addr) + return false; - *y += lheight; + *y += lheight; - } + } return (current == addr); diff --git a/src/glibext/gcodebuffer.h b/src/glibext/gcodebuffer.h index b92f38b..725bd1f 100644 --- a/src/glibext/gcodebuffer.h +++ b/src/glibext/gcodebuffer.h @@ -62,6 +62,12 @@ GCodeBuffer *g_code_buffer_new(void); /* Ajoute une nouvelle ligne à un tampon pour code désassemblé. */ GBufferLine *g_code_buffer_append_new_line(GCodeBuffer *, vmpa_t); +/* Ajoute une nouvelle ligne à un tampon pour code désassemblé. */ +GBufferLine *g_code_buffer_insert_at(GCodeBuffer *, vmpa_t, bool); + +/* Ajoute une nouvelle ligne à un tampon pour code désassemblé. */ +GBufferLine *g_code_buffer_insert_after(GCodeBuffer *, GBufferLine *); + /* Retrouve une ligne au sein d'un tampon avec une adresse. */ GBufferLine *g_code_buffer_find_line_by_addr(const GCodeBuffer *, vmpa_t); -- cgit v0.11.2-87-g4458