summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2012-11-22 19:51:17 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2012-11-22 19:51:17 (GMT)
commit3669bdaf8552f53baa5cfb2b0d360959eea61236 (patch)
tree94c5c5a74de1438c99320d4159b1f3de56961edf
parent29b390b5ed9f5c1a89db6d1e8d93d7126051b9a7 (diff)
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
-rw-r--r--ChangeLog14
-rw-r--r--plugins/androhelpers/try_n_catch.c297
-rw-r--r--src/glibext/gbufferline.c10
-rw-r--r--src/glibext/gbufferline.h1
-rw-r--r--src/glibext/gbuffersegment.c3
-rw-r--r--src/glibext/gcodebuffer.c175
-rw-r--r--src/glibext/gcodebuffer.h6
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 <nocbos@gmail.com>
+
+ * 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 <nocbos@gmail.com>
* 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 <malloc.h>
+#include <stdio.h>
#include <format/dex/dex-int.h>
@@ -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);