Added byline
[anjuta.git] / plugins / debug-manager / disassemble.c
blob027652ced362de1c48a6d8327f9255a5294f0afa
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 disassemble.c
4 Copyright (C) 2006 Sebastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 /*#define DEBUG*/
26 #include <libanjuta/anjuta-debug.h>
28 #include <libanjuta/interfaces/ianjuta-markable.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <string.h>
35 #include "disassemble.h"
37 #include "sparse_buffer.h"
38 #include "sparse_view.h"
40 #include "plugin.h"
41 #include "queue.h"
43 /* Constants
44 *---------------------------------------------------------------------------*/
46 enum {DMA_DISASSEMBLY_BUFFER_BLOCK_SIZE = 256,
47 DMA_DISASSEMBLY_SKIP_BEGINNING_LINE = 4,
48 DMA_DISASSEMBLY_TAB_LENGTH = 4,
49 DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH = 8,
50 DMA_DISASSEMBLY_PAGE_DISTANCE = 4 * 60,
51 DMA_DISASSEMBLY_VALID_ADDRESS = 0,
52 DMA_DISASSEMBLY_KNOW_ADDRESS = -1,
53 DMA_DISASSEMBLY_UNKNOWN_ADDRESS = -2};
55 enum {DMA_DISASSEMBLY_KEEP_ALL,
56 DMA_DISASSEMBLY_SKIP_BEGINNING};
58 /* Types
59 *---------------------------------------------------------------------------*/
61 typedef struct _DmaDisassemblyLine DmaDisassemblyLine;
62 typedef struct _DmaDisassemblyBufferNode DmaDisassemblyBufferNode;
64 typedef struct _DmaDisassemblyBuffer DmaDisassemblyBuffer;
65 typedef struct _DmaDisassemblyBufferClass DmaDisassemblyBufferClass;
67 typedef struct _DmaDisassemblyView DmaDisassemblyView;
68 typedef struct _DmaDisassemblyViewClass DmaDisassemblyViewClass;
70 struct _DmaDisassemble
72 DmaDebuggerQueue *debugger;
73 DebugManagerPlugin *plugin;
74 GtkWidget *window;
75 GtkWidget *menu;
76 DmaSparseBuffer* buffer;
77 DmaSparseView* view;
80 /* Disassembly buffer object
81 *---------------------------------------------------------------------------*/
83 struct _DmaDisassemblyBuffer
85 DmaSparseBuffer parent;
86 DmaDebuggerQueue *debugger;
87 gboolean pending;
90 struct _DmaDisassemblyBufferClass
92 DmaSparseBufferClass parent;
95 struct _DmaDisassemblyLine
97 gulong address;
98 gchar* text;
101 struct _DmaDisassemblyBufferNode
103 DmaSparseBufferNode parent;
104 guint size;
106 DmaDisassemblyLine data[];
109 #define DMA_DISASSEMBLY_BUFFER_TYPE (dma_disassembly_buffer_get_type ())
110 #define DMA_DISASSEMBLY_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DMA_DISASSEMBLY_BUFFER_TYPE, DmaDisassemblyBuffer))
111 #define DMA_DISASSEMBLY_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DMA_DISASSEMBLY_BUFFER_TYPE, DmaDisassemblyBufferClass))
112 #define IS_DMA_DISASSEMBLY_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DMA_DISASSEMBLY_BUFFER_TYPE))
113 #define IS_DMA_DISASSEMBLY_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DMA_DISASSEMBLY_BUFFER_TYPE))
114 #define GET_DMA_DISASSEMBLY_BUFFER_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DMA_DISASSEMBLY_BUFFER_TYPE, DmaDisassemblyBufferClass))
116 static DmaSparseBufferClass *parent_buffer_class = NULL;
118 static GType dma_disassembly_buffer_get_type (void);
120 /* Disassembly iterator function
121 *---------------------------------------------------------------------------*/
124 * Iterator can be divided in 3 cases:
125 * 1. Iterator on valid address:
126 * node != NULL
127 * base = address
128 * offset = 0
129 * line = line number in node
130 * 2. Iterator on know address:
131 * base = address
132 * offset = 0
133 * line = -1
134 * 3. Iterator on unknown address:
135 * base = address (often known)
136 * offset != 0 (could be 0 too)
137 * line = -2
138 *---------------------------------------------------------------------------*/
140 static gulong
141 dma_disassembly_get_address (DmaSparseIter *iter)
143 return iter->base + iter->offset;
146 static gboolean
147 dma_disassembly_iter_refresh (DmaSparseIter *iter)
149 /* Call this after updating node according to base */
150 gint line = -1;
151 DmaDisassemblyBufferNode *node = (DmaDisassemblyBufferNode *)iter->node;
153 if (iter->node != NULL)
155 /* Find line corresponding to base */
156 if ((iter->node->lower <= iter->base) && (iter->base <= iter->node->upper))
158 /* Iterator in current node */
159 if ((iter->line >= 0) && (iter->line < ((DmaDisassemblyBufferNode *)iter->node)->size)
160 && (((DmaDisassemblyBufferNode *)iter->node)->data[iter->line].address == iter->base))
162 /* Already get the right node */
163 line = iter->line;
165 else
167 /* Search for correct line */
169 if (iter->offset >= 0)
171 for (line = 0; line < node->size; line++)
173 if (node->data[line].address >= iter->base) break;
176 else
178 for (line = node->size - 1; line >= 0; line--)
180 if (node->data[line].address <= iter->base) break;
184 if (node->data[line].address == iter->base)
186 iter->line = line;
188 else if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
190 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
194 else if (iter->base == iter->node->upper + 1)
196 line = node->size;
197 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
199 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
202 else
204 /* Invalid base address */
205 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
207 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
211 else
213 /* Invalid base address */
214 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
216 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
220 /* Try to reduce offset */
221 if (line != -1)
223 if (iter->offset > 0)
225 /* Need to go upper if possible */
226 guint up = (DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH + iter->offset - 1)/ DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
228 for (;;)
230 gint len = node->size - line;
232 if (up < len)
234 iter->node = (DmaSparseBufferNode *)node;
235 iter->line = line + up;
236 iter->base = node->data[iter->line].address;
237 iter->offset = 0;
239 return TRUE;
242 if (iter->node->upper == dma_sparse_buffer_get_upper (iter->buffer))
244 gboolean move = iter->line != node->size - 1;
246 iter->node = (DmaSparseBufferNode *)node;
247 iter->line = node->size - 1;
248 iter->base = node->data[iter->line].address;
249 iter->offset = 0;
251 return move;
254 up -= len;
256 if ((node->parent.next == NULL) || (node->parent.upper != node->parent.next->lower - 1))
258 /* No following node */
260 iter->node = (DmaSparseBufferNode *)node;
261 iter->base = node->parent.upper + 1;
262 iter->offset = up * DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
264 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
266 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
269 break;
272 node = (DmaDisassemblyBufferNode *)node->parent.next;
273 line = 0;
276 else if (iter->offset < 0)
278 /* Need to go down if possible */
279 gint down = (- iter->offset) / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
281 for (;;)
283 guint len = line;
285 if (down <= len)
287 iter->node = (DmaSparseBufferNode *)node;
288 iter->line = line - down;
289 iter->base = node->data[iter->line].address;
290 iter->offset = 0;
292 return TRUE;
295 if (iter->node->lower == dma_sparse_buffer_get_lower (iter->buffer))
297 gboolean move = iter->line != 0;
299 iter->node = (DmaSparseBufferNode *)node;
300 iter->line = 0;
301 iter->base = node->data[0].address;
302 iter->offset = 0;
304 return move;
307 down -= len;
309 if ((node->parent.prev == NULL) || (node->parent.lower != node->parent.prev->upper + 1))
311 /* No following node */
313 iter->node = (DmaSparseBufferNode *)node;
314 iter->base = node->parent.lower;
315 iter->offset = -down * DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
316 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
318 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
320 break;
323 node = (DmaDisassemblyBufferNode *)node->parent.prev;
324 line = node->size;
329 /* Round offset */
330 if (iter->offset < 0)
332 gulong address;
333 gboolean move = TRUE;
335 address = iter->offset + iter->base;
336 if ((address < dma_sparse_buffer_get_lower (iter->buffer)) || (address > iter->base))
338 address = dma_sparse_buffer_get_lower (iter->buffer);
339 move = FALSE;
341 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
342 iter->offset = address - iter->base;
344 return move;
346 else if ((iter->offset > 0) || (iter->line == DMA_DISASSEMBLY_UNKNOWN_ADDRESS))
348 gulong address;
349 gboolean move = TRUE;
351 address = iter->offset + iter->base;
352 if ((address > dma_sparse_buffer_get_upper (iter->buffer)) || (address < iter->base))
354 address = dma_sparse_buffer_get_upper (iter->buffer);
355 move = FALSE;
357 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
358 iter->offset = address - iter->base;
360 return move;
363 /* return FALSE if iterator reach the lower or upper limit */
364 return TRUE;
367 static gboolean
368 dma_disassembly_iter_backward_line (DmaSparseIter *iter)
370 iter->offset -= DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
371 return dma_disassembly_iter_refresh (iter);
374 static gboolean
375 dma_disassembly_iter_forward_line (DmaSparseIter *iter)
377 iter->offset += DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
378 return dma_disassembly_iter_refresh (iter);
382 static void
383 dma_disassembly_iter_round (DmaSparseIter *iter, gboolean round_up)
385 iter->offset += round_up ? 1 : -1;
386 dma_disassembly_iter_refresh (iter);
389 static void
390 on_disassemble (const IAnjutaDebuggerInstructionDisassembly *block, DmaSparseBufferTransport *trans, GError *err)
392 DmaDisassemblyBufferNode *node;
393 DmaDisassemblyBuffer *buffer = (DmaDisassemblyBuffer *)trans->buffer;
394 DmaSparseBufferNode *next;
395 guint i;
396 char *dst;
398 DEBUG_PRINT ("on disassemble %p", block);
400 if ((err != NULL) && !g_error_matches (err, IANJUTA_DEBUGGER_ERROR, IANJUTA_DEBUGGER_UNABLE_TO_ACCESS_MEMORY))
403 /* Command has been cancelled */
404 dma_sparse_buffer_free_transport (trans);
406 return;
409 /* Find following block */
410 DEBUG_PRINT("trans %p buffer %p trans->buffer %p trans->start %lu", trans, buffer, trans == NULL ? NULL : trans->buffer, trans == NULL ? 0 : trans->start);
411 next = dma_sparse_buffer_lookup (DMA_SPARSE_BUFFER (buffer), trans->start + trans->length - 1);
412 if ((next != NULL) && (next->upper <= trans->start)) next = NULL;
414 if (err != NULL)
416 gulong address = trans->start;
417 gint len;
419 /* Create a dummy node */
420 len = (trans->length + DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH - 1) / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
421 node = (DmaDisassemblyBufferNode *)g_malloc0 (sizeof(DmaDisassemblyBufferNode) + sizeof(DmaDisassemblyLine) * len);
422 node->parent.lower = address;
423 for (i = 0; i < len; i++)
425 if ((next != NULL) && (address >= next->lower)) break;
426 node->data[i].address = address;
427 node->data[i].text = "????????";
428 address += DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
429 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
431 node->size = i;
432 if ((next != NULL) && (address >= next->lower))
434 address = next->lower -1;
436 else
438 address = trans->start + trans->length - 1;
440 node->parent.upper = address;
442 else
444 guint size = 0;
445 guint line = 0;
447 /* Compute size of all data */
448 /* use size -1 because last block has no data (NULL) */
449 for (i = trans->tag == DMA_DISASSEMBLY_KEEP_ALL ? 0 : 4; i < block->size - 1; i++)
451 if (block->data[i].label)
453 size += strlen(block->data[i].label) + 2;
454 line++;
456 size += strlen(block->data[i].text) + 1 + DMA_DISASSEMBLY_TAB_LENGTH;
457 line++;
460 node = (DmaDisassemblyBufferNode *)g_malloc0 (sizeof(DmaDisassemblyBufferNode) + sizeof(DmaDisassemblyLine) * line + size);
462 /* Copy all data */
463 dst = (gchar *)&(node->data[line]);
464 line = 0;
465 for (i = trans->tag == DMA_DISASSEMBLY_KEEP_ALL ? 0 : DMA_DISASSEMBLY_SKIP_BEGINNING_LINE; i < block->size - 1; i++)
467 gsize len;
469 if ((next != NULL) && (block->data[i].address == next->lower)) break;
471 /* Add label if exist */
472 if (block->data[i].label != NULL)
474 len = strlen(block->data[i].label);
476 node->data[line].address = block->data[i].address;
477 node->data[line].text = dst;
479 memcpy(dst, block->data[i].label, len);
480 dst[len] = ':';
481 dst[len + 1] = '\0';
483 dst += len + 2;
484 line++;
487 /* Add disassembled instruction */
488 len = strlen(block->data[i].text) + 1;
490 node->data[line].address = block->data[i].address;
491 node->data[line].text = dst;
493 memset (dst, ' ', DMA_DISASSEMBLY_TAB_LENGTH);
494 memcpy (dst + DMA_DISASSEMBLY_TAB_LENGTH, block->data[i].text, len);
495 dst += len + DMA_DISASSEMBLY_TAB_LENGTH;
496 line++;
499 /* fill last block */
500 node->size = line;
501 node->parent.lower = node->data[0].address;
502 node->parent.upper = block->data[i].address - 1;
506 dma_sparse_buffer_insert (DMA_SPARSE_BUFFER (buffer), (DmaSparseBufferNode *)node);
507 dma_sparse_buffer_free_transport (trans);
508 dma_sparse_buffer_changed (DMA_SPARSE_BUFFER (buffer));
511 static void
512 dma_disassembly_buffer_insert_line (DmaSparseIter *iter, GtkTextIter *dst)
514 DmaDisassemblyBuffer * dis = (DmaDisassemblyBuffer *)iter->buffer;
515 GtkTextBuffer *buffer = gtk_text_iter_get_buffer (dst);
517 if (dis->debugger != NULL)
519 dma_sparse_iter_refresh (iter);
520 if (iter->line < DMA_DISASSEMBLY_VALID_ADDRESS)
522 if (iter->buffer->pending == NULL)
524 DmaSparseIter end;
525 DmaSparseBufferTransport *trans;
526 gint i, j;
527 gulong start_adr;
528 gulong end_adr;
529 gint margin;
531 /* If following line is define, get a block stopping here */
532 dma_sparse_iter_copy (&end, iter);
533 margin = 0;
534 for (j = 0; j < DMA_DISASSEMBLY_BUFFER_BLOCK_SIZE / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH; j++)
536 if (!dma_disassembly_iter_forward_line (&end))
538 end.offset = 0;
539 end.base = dma_sparse_buffer_get_upper (end.buffer);
540 break;
542 if (margin > DMA_DISASSEMBLY_SKIP_BEGINNING_LINE) break;
543 if ((margin != 0) || (end.line >= DMA_DISASSEMBLY_VALID_ADDRESS)) margin++;
545 i = j;
546 if (iter->line == DMA_DISASSEMBLY_UNKNOWN_ADDRESS)
548 for (i = j; i < DMA_DISASSEMBLY_BUFFER_BLOCK_SIZE / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH; i++)
550 if (!dma_disassembly_iter_backward_line (iter)) break;
551 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS) break;
554 start_adr = dma_sparse_iter_get_address (iter);
555 end_adr = dma_sparse_iter_get_address (&end);
556 trans = dma_sparse_buffer_alloc_transport (DMA_SPARSE_BUFFER (dis), i, 0);
557 trans->tag = i != j ? DMA_DISASSEMBLY_SKIP_BEGINNING : DMA_DISASSEMBLY_KEEP_ALL;
558 trans->start = start_adr;
559 trans->length = end_adr - start_adr;
560 if (end_adr == dma_sparse_buffer_get_upper (DMA_SPARSE_BUFFER (dis)))
562 trans->length++;
564 DEBUG_PRINT("get disassemble %lx %lx %ld trans %p buffer %p", start_adr, end_adr, trans->length, trans, trans->buffer);
565 dma_queue_disassemble (dis->debugger, start_adr, end_adr + 1 - start_adr, (IAnjutaDebuggerCallback)on_disassemble, trans);
568 else
570 /* Fill with known data */
571 gtk_text_buffer_insert (buffer, dst, ((DmaDisassemblyBufferNode *)(iter->node))->data[iter->line].text, -1);
573 return;
577 /* Fill with unknow data */
578 gtk_text_buffer_insert (buffer, dst, "??", 2);
581 static void
582 dma_disassembly_buffer_class_init (DmaDisassemblyBufferClass *klass)
584 DmaSparseBufferClass* buffer_class;
586 g_return_if_fail (klass != NULL);
588 parent_buffer_class = (DmaSparseBufferClass*) g_type_class_peek_parent (klass);
590 buffer_class = DMA_SPARSE_BUFFER_CLASS (klass);
592 buffer_class->refresh_iter = dma_disassembly_iter_refresh;
593 buffer_class->round_iter = dma_disassembly_iter_round;
594 buffer_class->insert_line = dma_disassembly_buffer_insert_line;
595 buffer_class->forward_line = dma_disassembly_iter_forward_line;
596 buffer_class->backward_line = dma_disassembly_iter_backward_line;
597 buffer_class->get_address = dma_disassembly_get_address;
600 static GType
601 dma_disassembly_buffer_get_type (void)
603 static GType type = 0;
605 if (!type)
607 static const GTypeInfo type_info =
609 sizeof (DmaDisassemblyBufferClass),
610 (GBaseInitFunc) NULL,
611 (GBaseFinalizeFunc) NULL,
612 (GClassInitFunc) dma_disassembly_buffer_class_init,
613 (GClassFinalizeFunc) NULL,
614 NULL, /* class_data */
615 sizeof (DmaDisassemblyBuffer),
616 0, /* n_preallocs */
617 (GInstanceInitFunc) NULL,
618 NULL /* value_table */
621 type = g_type_register_static (DMA_SPARSE_BUFFER_TYPE,
622 "DmaDisassemblyBuffer", &type_info, 0);
625 return type;
629 static DmaDisassemblyBuffer*
630 dma_disassembly_buffer_new (DmaDebuggerQueue *debugger, gulong lower, gulong upper)
632 DmaDisassemblyBuffer *buffer;
634 buffer = g_object_new (DMA_DISASSEMBLY_BUFFER_TYPE, NULL);
635 g_assert (buffer != NULL);
637 buffer->debugger = debugger;
639 DMA_SPARSE_BUFFER (buffer)->lower = lower;
640 DMA_SPARSE_BUFFER (buffer)->upper = upper;
642 return buffer;
645 /* Disassembly view object
646 *---------------------------------------------------------------------------*/
648 struct _DmaDisassemblyView
650 DmaSparseView parent;
651 DmaDebuggerQueue *debugger;
652 gboolean pending;
655 struct _DmaDisassemblyViewClass
657 DmaSparseViewClass parent;
660 #define DMA_DISASSEMBLY_VIEW_TYPE (dma_disassembly_view_get_type ())
661 #define DMA_DISASSEMBLY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyView))
662 #define DMA_DISASSEMBLY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyViewClass))
663 #define IS_DMA_DISASSEMBLY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DMA_DISASSEMBLY_VIEW_TYPE))
664 #define IS_DMA_DISASSEMBLY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DMA_DISASSEMBLY_VIEW_TYPE))
665 #define GET_DMA_DISASSEMBLY_VIEW_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyViewClass))
667 static DmaSparseViewClass *parent_class = NULL;
669 static GType dma_disassembly_view_get_type (void);
671 /* instance_init is the constructor. All functions should work after this
672 * call. */
674 static void
675 dma_disassembly_view_instance_init (DmaSparseView *view)
677 gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
680 /* class_init intialize the class itself not the instance */
682 static void
683 dma_disassembly_view_class_init (DmaDisassemblyViewClass *klass)
685 g_return_if_fail (klass != NULL);
687 parent_class = (DmaSparseViewClass*) g_type_class_peek_parent (klass);
690 static GType
691 dma_disassembly_view_get_type (void)
693 static GType type = 0;
695 if (!type)
697 static const GTypeInfo type_info =
699 sizeof (DmaDisassemblyViewClass),
700 (GBaseInitFunc) NULL,
701 (GBaseFinalizeFunc) NULL,
702 (GClassInitFunc) dma_disassembly_view_class_init,
703 (GClassFinalizeFunc) NULL,
704 NULL, /* class_data */
705 sizeof (DmaDisassemblyView),
706 0, /* n_preallocs */
707 (GInstanceInitFunc) dma_disassembly_view_instance_init,
708 NULL /* value_table */
711 type = g_type_register_static (DMA_SPARSE_VIEW_TYPE,
712 "DmaDisassemblyView", &type_info, 0);
715 return type;
719 static DmaDisassemblyView*
720 dma_disassembly_view_new_with_buffer (DmaDebuggerQueue *debugger, DmaSparseBuffer *buffer)
722 DmaDisassemblyView *view;
724 view = g_object_new (DMA_DISASSEMBLY_VIEW_TYPE, "buffer", buffer, NULL);
725 g_assert (view != NULL);
727 view->debugger = debugger;
729 return view;
732 /* Private functions
733 *---------------------------------------------------------------------------*/
735 static void
736 on_disassembly_buffer_changed (DmaDisassemblyBuffer *buffer, DmaSparseView *view)
738 dma_sparse_view_refresh (view);
741 static void
742 on_breakpoint_changed (DmaDisassemble *self, IAnjutaDebuggerBreakpointItem *bp)
744 g_return_if_fail (bp != NULL);
746 dma_sparse_view_unmark (self->view, bp->address, IANJUTA_MARKABLE_BREAKPOINT_DISABLED);
747 dma_sparse_view_unmark (self->view, bp->address, IANJUTA_MARKABLE_BREAKPOINT_ENABLED);
748 if (!(bp->type & IANJUTA_DEBUGGER_BREAKPOINT_REMOVED))
750 dma_sparse_view_mark (self->view, bp->address, bp->enable ? IANJUTA_MARKABLE_BREAKPOINT_ENABLED : IANJUTA_MARKABLE_BREAKPOINT_DISABLED);
754 static void
755 destroy_disassemble_gui (DmaDisassemble *self)
757 /* Destroy menu */
758 if (self->menu != NULL)
760 gtk_widget_destroy (self->menu);
761 self->menu = NULL;
764 if (self->window != NULL)
766 gtk_widget_destroy (self->window);
767 self->window = NULL;
768 self->view = NULL;
771 /* Destroy buffer */
772 if (self->buffer)
774 dma_sparse_buffer_free (DMA_SPARSE_BUFFER (self->buffer));
775 self->buffer = NULL;
779 static void
780 on_program_running (DmaDisassemble *self)
782 dma_sparse_view_delete_all_markers (self->view, IANJUTA_MARKABLE_PROGRAM_COUNTER);
785 static void
786 on_program_moved (DmaDisassemble *self, guint pid, guint tid, gulong address, const gchar* file, guint line)
788 dma_sparse_view_delete_all_markers (self->view, IANJUTA_MARKABLE_PROGRAM_COUNTER);
790 if (address != 0)
792 dma_sparse_view_mark (self->view, address, IANJUTA_MARKABLE_PROGRAM_COUNTER);
793 dma_sparse_view_goto (self->view, address);
797 static void
798 on_location_changed (DmaDisassemble *self, gulong address, GFile* file, guint line)
800 dma_sparse_view_goto (self->view, address);
803 static void
804 on_program_unloaded (DmaDisassemble *self)
806 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_unloaded), self);
807 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_breakpoint_changed), self);
808 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_running), self);
809 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_moved), self);
810 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_location_changed), self);
812 dma_sparse_view_delete_all_markers (self->view, IANJUTA_MARKABLE_PROGRAM_COUNTER);
814 destroy_disassemble_gui (self);
817 static gboolean
818 create_disassemble_gui (DmaDisassemble *self)
820 GtkWidget *dataview;
822 g_return_val_if_fail (self->buffer == NULL, FALSE);
823 g_return_val_if_fail (self->window == NULL, FALSE);
825 /* Create buffer */
826 self->buffer = DMA_SPARSE_BUFFER (dma_disassembly_buffer_new (self->debugger, 0x00000000U,0xFFFFFFFFU));
827 if (self->buffer == NULL) return FALSE;
829 dataview = GTK_WIDGET (dma_disassembly_view_new_with_buffer (self->debugger, self->buffer));
830 self->view = DMA_SPARSE_VIEW (dataview);
831 DMA_DISASSEMBLY_VIEW (dataview)->pending = FALSE;
832 g_signal_connect (G_OBJECT (self->buffer), "changed", G_CALLBACK (on_disassembly_buffer_changed), self->view);
834 /* Add disassembly window */
835 self->window = gtk_scrolled_window_new (NULL, NULL);
836 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->window),
837 GTK_POLICY_AUTOMATIC,
838 GTK_POLICY_AUTOMATIC);
839 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self->window),
840 GTK_SHADOW_IN);
841 gtk_container_add (GTK_CONTAINER (self->window), GTK_WIDGET (dataview));
843 gtk_widget_show_all (self->window);
844 anjuta_shell_add_widget (ANJUTA_PLUGIN (self->plugin)->shell,
845 self->window,
846 "AnjutaDebuggerDisassemble", _("Disassembly"),
847 "debugger-disassembly", ANJUTA_SHELL_PLACEMENT_NONE,
848 NULL);
850 return TRUE;
853 static void
854 on_program_loaded (DmaDisassemble *self)
856 if (!dma_debugger_queue_is_supported (self->debugger, HAS_INSTRUCTION)) return;
858 if (!create_disassemble_gui (self)) return;
860 /* Connect signals */
861 g_signal_connect_swapped (self->plugin, "program-unloaded", G_CALLBACK (on_program_unloaded), self);
862 g_signal_connect_swapped (self->plugin, "breakpoint-changed", G_CALLBACK (on_breakpoint_changed), self);
863 g_signal_connect_swapped (self->plugin, "program-running", G_CALLBACK (on_program_running), self);
864 g_signal_connect_swapped (self->plugin, "program-moved", G_CALLBACK (on_program_moved), self);
865 g_signal_connect_swapped (self->plugin, "location-changed", G_CALLBACK (on_location_changed), self);
868 /* Public functions
869 *---------------------------------------------------------------------------*/
871 gboolean
872 dma_disassemble_is_focus (DmaDisassemble *self)
874 return gtk_widget_is_focus (GTK_WIDGET(self->view));
877 guint
878 dma_disassemble_get_current_address (DmaDisassemble *self)
880 return dma_sparse_view_get_location (self->view);
883 /* Constructor & Destructor
884 *---------------------------------------------------------------------------*/
886 DmaDisassemble*
887 dma_disassemble_new(DebugManagerPlugin *plugin)
889 DmaDisassemble* self;
891 self = g_new0 (DmaDisassemble, 1);
893 self->plugin = plugin;
894 self->debugger = dma_debug_manager_get_queue (plugin);;
896 g_signal_connect_swapped (self->plugin, "program-loaded", G_CALLBACK (on_program_loaded), self);
898 return self;
901 void
902 dma_disassemble_free(DmaDisassemble* self)
904 g_return_if_fail (self != NULL);
906 g_signal_handlers_disconnect_matched (self->plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
908 destroy_disassemble_gui (self);
910 g_free(self);