Integrate adding files with the file manager
[anjuta-git-plugin.git] / plugins / debug-manager / disassemble.c
blob8060732142991d32003624683f0e5e107fc98a3d
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 <gnome.h>
36 #include "disassemble.h"
38 #include "sparse_buffer.h"
39 #include "sparse_view.h"
41 #include "plugin.h"
42 #include "queue.h"
44 /* Constants
45 *---------------------------------------------------------------------------*/
47 enum {DMA_DISASSEMBLY_BUFFER_BLOCK_SIZE = 256,
48 DMA_DISASSEMBLY_SKIP_BEGINNING_LINE = 4,
49 DMA_DISASSEMBLY_TAB_LENGTH = 4,
50 DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH = 8,
51 DMA_DISASSEMBLY_PAGE_DISTANCE = 4 * 60,
52 DMA_DISASSEMBLY_VALID_ADDRESS = 0,
53 DMA_DISASSEMBLY_KNOW_ADDRESS = -1,
54 DMA_DISASSEMBLY_UNKNOWN_ADDRESS = -2};
56 enum {DMA_DISASSEMBLY_KEEP_ALL,
57 DMA_DISASSEMBLY_SKIP_BEGINNING};
59 /* Types
60 *---------------------------------------------------------------------------*/
62 typedef struct _DmaDisassemblyLine DmaDisassemblyLine;
63 typedef struct _DmaDisassemblyBufferNode DmaDisassemblyBufferNode;
65 typedef struct _DmaDisassemblyBuffer DmaDisassemblyBuffer;
66 typedef struct _DmaDisassemblyBufferClass DmaDisassemblyBufferClass;
68 typedef struct _DmaDisassemblyView DmaDisassemblyView;
69 typedef struct _DmaDisassemblyViewClass DmaDisassemblyViewClass;
71 struct _DmaDisassemble
73 DmaDebuggerQueue *debugger;
74 DebugManagerPlugin *plugin;
75 GtkWidget *window;
76 GtkWidget *menu;
77 DmaSparseBuffer* buffer;
78 DmaSparseView* view;
81 /* Disassembly buffer object
82 *---------------------------------------------------------------------------*/
84 struct _DmaDisassemblyBuffer
86 DmaSparseBuffer parent;
87 DmaDebuggerQueue *debugger;
88 gboolean pending;
91 struct _DmaDisassemblyBufferClass
93 DmaSparseBufferClass parent;
96 struct _DmaDisassemblyLine
98 gulong address;
99 gchar* text;
102 struct _DmaDisassemblyBufferNode
104 DmaSparseBufferNode parent;
105 guint size;
107 DmaDisassemblyLine data[];
110 #define DMA_DISASSEMBLY_BUFFER_TYPE (dma_disassembly_buffer_get_type ())
111 #define DMA_DISASSEMBLY_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DMA_DISASSEMBLY_BUFFER_TYPE, DmaDisassemblyBuffer))
112 #define DMA_DISASSEMBLY_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DMA_DISASSEMBLY_BUFFER_TYPE, DmaDisassemblyBufferClass))
113 #define IS_DMA_DISASSEMBLY_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DMA_DISASSEMBLY_BUFFER_TYPE))
114 #define IS_DMA_DISASSEMBLY_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DMA_DISASSEMBLY_BUFFER_TYPE))
115 #define GET_DMA_DISASSEMBLY_BUFFER_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DMA_DISASSEMBLY_BUFFER_TYPE, DmaDisassemblyBufferClass))
117 static DmaSparseBufferClass *parent_buffer_class = NULL;
119 static GType dma_disassembly_buffer_get_type (void);
121 /* Disassembly iterator function
122 *---------------------------------------------------------------------------*/
125 * Iterator can be divided in 3 cases:
126 * 1. Iterator on valid address:
127 * node != NULL
128 * base = address
129 * offset = 0
130 * line = line number in node
131 * 2. Iterator on know address:
132 * base = address
133 * offset = 0
134 * line = -1
135 * 3. Iterator on unknown address:
136 * base = address (often known)
137 * offset != 0 (could be 0 too)
138 * line = -2
139 *---------------------------------------------------------------------------*/
141 static gulong
142 dma_disassembly_get_address (DmaSparseIter *iter)
144 return iter->base + iter->offset;
147 static gboolean
148 dma_disassembly_iter_refresh (DmaSparseIter *iter)
150 /* Call this after updating node according to base */
151 gint line = -1;
152 DmaDisassemblyBufferNode *node = (DmaDisassemblyBufferNode *)iter->node;
154 if (iter->node != NULL)
156 /* Find line corresponding to base */
157 if ((iter->node->lower <= iter->base) && (iter->base <= iter->node->upper))
159 /* Iterator in current node */
160 if ((iter->line >= 0) && (iter->line < ((DmaDisassemblyBufferNode *)iter->node)->size)
161 && (((DmaDisassemblyBufferNode *)iter->node)->data[iter->line].address == iter->base))
163 /* Already get the right node */
164 line = iter->line;
166 else
168 /* Search for correct line */
170 if (iter->offset >= 0)
172 for (line = 0; line < node->size; line++)
174 if (node->data[line].address >= iter->base) break;
177 else
179 for (line = node->size - 1; line >= 0; line--)
181 if (node->data[line].address <= iter->base) break;
185 if (node->data[line].address == iter->base)
187 iter->line = line;
189 else if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
191 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
195 else if (iter->base == iter->node->upper + 1)
197 line = node->size;
198 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
200 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
203 else
205 /* Invalid base address */
206 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
208 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
212 else
214 /* Invalid base address */
215 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
217 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
221 /* Try to reduce offset */
222 if (line != -1)
224 if (iter->offset > 0)
226 /* Need to go upper if possible */
227 guint up = (DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH + iter->offset - 1)/ DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
229 for (;;)
231 gint len = node->size - line;
233 if (up < len)
235 iter->node = (DmaSparseBufferNode *)node;
236 iter->line = line + up;
237 iter->base = node->data[iter->line].address;
238 iter->offset = 0;
240 return TRUE;
243 if (iter->node->upper == dma_sparse_buffer_get_upper (iter->buffer))
245 gboolean move = iter->line != node->size - 1;
247 iter->node = (DmaSparseBufferNode *)node;
248 iter->line = node->size - 1;
249 iter->base = node->data[iter->line].address;
250 iter->offset = 0;
252 return move;
255 up -= len;
257 if ((node->parent.next == NULL) || (node->parent.upper != node->parent.next->lower - 1))
259 /* No following node */
261 iter->node = (DmaSparseBufferNode *)node;
262 iter->base = node->parent.upper + 1;
263 iter->offset = up * DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
265 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
267 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
270 break;
273 node = (DmaDisassemblyBufferNode *)node->parent.next;
274 line = 0;
277 else if (iter->offset < 0)
279 /* Need to go down if possible */
280 gint down = (- iter->offset) / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
282 for (;;)
284 guint len = line;
286 if (down <= len)
288 iter->node = (DmaSparseBufferNode *)node;
289 iter->line = line - down;
290 iter->base = node->data[iter->line].address;
291 iter->offset = 0;
293 return TRUE;
296 if (iter->node->lower == dma_sparse_buffer_get_lower (iter->buffer))
298 gboolean move = iter->line != 0;
300 iter->node = (DmaSparseBufferNode *)node;
301 iter->line = 0;
302 iter->base = node->data[0].address;
303 iter->offset = 0;
305 return move;
308 down -= len;
310 if ((node->parent.prev == NULL) || (node->parent.lower != node->parent.prev->upper + 1))
312 /* No following node */
314 iter->node = (DmaSparseBufferNode *)node;
315 iter->base = node->parent.lower;
316 iter->offset = -down * DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
317 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
319 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
321 break;
324 node = (DmaDisassemblyBufferNode *)node->parent.prev;
325 line = node->size;
330 /* Round offset */
331 if (iter->offset < 0)
333 gulong address;
334 gboolean move = TRUE;
336 address = iter->offset + iter->base;
337 if ((address < dma_sparse_buffer_get_lower (iter->buffer)) || (address > iter->base))
339 address = dma_sparse_buffer_get_lower (iter->buffer);
340 move = FALSE;
342 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
343 iter->offset = address - iter->base;
345 return move;
347 else if ((iter->offset > 0) || (iter->line == DMA_DISASSEMBLY_UNKNOWN_ADDRESS))
349 gulong address;
350 gboolean move = TRUE;
352 address = iter->offset + iter->base;
353 if ((address > dma_sparse_buffer_get_upper (iter->buffer)) || (address < iter->base))
355 address = dma_sparse_buffer_get_upper (iter->buffer);
356 move = FALSE;
358 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
359 iter->offset = address - iter->base;
361 return move;
364 /* return FALSE if iterator reach the lower or upper limit */
365 return TRUE;
368 static gboolean
369 dma_disassembly_iter_backward_line (DmaSparseIter *iter)
371 iter->offset -= DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
372 return dma_disassembly_iter_refresh (iter);
375 static gboolean
376 dma_disassembly_iter_forward_line (DmaSparseIter *iter)
378 iter->offset += DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
379 return dma_disassembly_iter_refresh (iter);
383 static void
384 dma_disassembly_iter_round (DmaSparseIter *iter, gboolean round_up)
386 iter->offset += round_up ? 1 : -1;
387 dma_disassembly_iter_refresh (iter);
390 static void
391 on_disassemble (const IAnjutaDebuggerInstructionDisassembly *block, DmaSparseBufferTransport *trans, GError *err)
393 DmaDisassemblyBufferNode *node;
394 DmaDisassemblyBuffer *buffer = (DmaDisassemblyBuffer *)trans->buffer;
395 DmaSparseBufferNode *next;
396 guint i;
397 char *dst;
399 DEBUG_PRINT ("on disassemble %p", block);
401 if ((err != NULL) && !g_error_matches (err, IANJUTA_DEBUGGER_ERROR, IANJUTA_DEBUGGER_UNABLE_TO_ACCESS_MEMORY))
404 /* Command has been cancelled */
405 dma_sparse_buffer_free_transport (trans);
407 return;
410 /* Find following block */
411 DEBUG_PRINT("trans %p buffer %p trans->buffer %p trans->start %lu", trans, buffer, trans == NULL ? NULL : trans->buffer, trans == NULL ? 0 : trans->start);
412 next = dma_sparse_buffer_lookup (DMA_SPARSE_BUFFER (buffer), trans->start + trans->length - 1);
413 if ((next != NULL) && (next->upper <= trans->start)) next = NULL;
415 if (err != NULL)
417 gulong address = trans->start;
418 gint len;
420 /* Create a dummy node */
421 len = (trans->length + DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH - 1) / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
422 node = (DmaDisassemblyBufferNode *)g_malloc0 (sizeof(DmaDisassemblyBufferNode) + sizeof(DmaDisassemblyLine) * len);
423 node->parent.lower = address;
424 for (i = 0; i < len; i++)
426 if ((next != NULL) && (address >= next->lower)) break;
427 node->data[i].address = address;
428 node->data[i].text = "????????";
429 address += DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
430 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
432 node->size = i;
433 if ((next != NULL) && (address >= next->lower))
435 address = next->lower -1;
437 else
439 address = trans->start + trans->length - 1;
441 node->parent.upper = address;
443 else
445 guint size = 0;
446 guint line = 0;
448 /* Compute size of all data */
449 /* use size -1 because last block has no data (NULL) */
450 for (i = trans->tag == DMA_DISASSEMBLY_KEEP_ALL ? 0 : 4; i < block->size - 1; i++)
452 if (block->data[i].label)
454 size += strlen(block->data[i].label) + 2;
455 line++;
457 size += strlen(block->data[i].text) + 1 + DMA_DISASSEMBLY_TAB_LENGTH;
458 line++;
461 node = (DmaDisassemblyBufferNode *)g_malloc0 (sizeof(DmaDisassemblyBufferNode) + sizeof(DmaDisassemblyLine) * line + size);
463 /* Copy all data */
464 dst = (gchar *)&(node->data[line]);
465 line = 0;
466 for (i = trans->tag == DMA_DISASSEMBLY_KEEP_ALL ? 0 : DMA_DISASSEMBLY_SKIP_BEGINNING_LINE; i < block->size - 1; i++)
468 gsize len;
470 if ((next != NULL) && (block->data[i].address == next->lower)) break;
472 /* Add label if exist */
473 if (block->data[i].label != NULL)
475 len = strlen(block->data[i].label);
477 node->data[line].address = block->data[i].address;
478 node->data[line].text = dst;
480 memcpy(dst, block->data[i].label, len);
481 dst[len] = ':';
482 dst[len + 1] = '\0';
484 dst += len + 2;
485 line++;
488 /* Add disassembled instruction */
489 len = strlen(block->data[i].text) + 1;
491 node->data[line].address = block->data[i].address;
492 node->data[line].text = dst;
494 memset (dst, ' ', DMA_DISASSEMBLY_TAB_LENGTH);
495 memcpy (dst + DMA_DISASSEMBLY_TAB_LENGTH, block->data[i].text, len);
496 dst += len + DMA_DISASSEMBLY_TAB_LENGTH;
497 line++;
500 /* fill last block */
501 node->size = line;
502 node->parent.lower = node->data[0].address;
503 node->parent.upper = block->data[i].address - 1;
507 dma_sparse_buffer_insert (DMA_SPARSE_BUFFER (buffer), (DmaSparseBufferNode *)node);
508 dma_sparse_buffer_free_transport (trans);
509 dma_sparse_buffer_changed (DMA_SPARSE_BUFFER (buffer));
512 static void
513 dma_disassembly_buffer_insert_line (DmaSparseIter *iter, GtkTextIter *dst)
515 DmaDisassemblyBuffer * dis = (DmaDisassemblyBuffer *)iter->buffer;
516 GtkTextBuffer *buffer = gtk_text_iter_get_buffer (dst);
518 if (dis->debugger != NULL)
520 dma_sparse_iter_refresh (iter);
521 if (iter->line < DMA_DISASSEMBLY_VALID_ADDRESS)
523 if (iter->buffer->pending == NULL)
525 DmaSparseIter end;
526 DmaSparseBufferTransport *trans;
527 gint i, j;
528 gulong start_adr;
529 gulong end_adr;
530 gint margin;
532 /* If following line is define, get a block stopping here */
533 dma_sparse_iter_copy (&end, iter);
534 margin = 0;
535 for (j = 0; j < DMA_DISASSEMBLY_BUFFER_BLOCK_SIZE / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH; j++)
537 if (!dma_disassembly_iter_forward_line (&end))
539 end.offset = 0;
540 end.base = dma_sparse_buffer_get_upper (end.buffer);
541 break;
543 if (margin > DMA_DISASSEMBLY_SKIP_BEGINNING_LINE) break;
544 if ((margin != 0) || (end.line >= DMA_DISASSEMBLY_VALID_ADDRESS)) margin++;
546 i = j;
547 if (iter->line == DMA_DISASSEMBLY_UNKNOWN_ADDRESS)
549 for (i = j; i < DMA_DISASSEMBLY_BUFFER_BLOCK_SIZE / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH; i++)
551 if (!dma_disassembly_iter_backward_line (iter)) break;
552 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS) break;
555 start_adr = dma_sparse_iter_get_address (iter);
556 end_adr = dma_sparse_iter_get_address (&end);
557 trans = dma_sparse_buffer_alloc_transport (DMA_SPARSE_BUFFER (dis), i, 0);
558 trans->tag = i != j ? DMA_DISASSEMBLY_SKIP_BEGINNING : DMA_DISASSEMBLY_KEEP_ALL;
559 trans->start = start_adr;
560 trans->length = end_adr - start_adr;
561 if (end_adr == dma_sparse_buffer_get_upper (DMA_SPARSE_BUFFER (dis)))
563 trans->length++;
565 DEBUG_PRINT("get disassemble %lx %lx %ld trans %p buffer %p", start_adr, end_adr, trans->length, trans, trans->buffer);
566 dma_queue_disassemble (dis->debugger, start_adr, end_adr + 1 - start_adr, (IAnjutaDebuggerCallback)on_disassemble, trans);
569 else
571 /* Fill with known data */
572 gtk_text_buffer_insert (buffer, dst, ((DmaDisassemblyBufferNode *)(iter->node))->data[iter->line].text, -1);
574 return;
578 /* Fill with unknow data */
579 gtk_text_buffer_insert (buffer, dst, "??", 2);
582 static void
583 dma_disassembly_buffer_class_init (DmaDisassemblyBufferClass *klass)
585 DmaSparseBufferClass* buffer_class;
587 g_return_if_fail (klass != NULL);
589 parent_buffer_class = (DmaSparseBufferClass*) g_type_class_peek_parent (klass);
591 buffer_class = DMA_SPARSE_BUFFER_CLASS (klass);
593 buffer_class->refresh_iter = dma_disassembly_iter_refresh;
594 buffer_class->round_iter = dma_disassembly_iter_round;
595 buffer_class->insert_line = dma_disassembly_buffer_insert_line;
596 buffer_class->forward_line = dma_disassembly_iter_forward_line;
597 buffer_class->backward_line = dma_disassembly_iter_backward_line;
598 buffer_class->get_address = dma_disassembly_get_address;
601 static GType
602 dma_disassembly_buffer_get_type (void)
604 static GType type = 0;
606 if (!type)
608 static const GTypeInfo type_info =
610 sizeof (DmaDisassemblyBufferClass),
611 (GBaseInitFunc) NULL,
612 (GBaseFinalizeFunc) NULL,
613 (GClassInitFunc) dma_disassembly_buffer_class_init,
614 (GClassFinalizeFunc) NULL,
615 NULL, /* class_data */
616 sizeof (DmaDisassemblyBuffer),
617 0, /* n_preallocs */
618 (GInstanceInitFunc) NULL,
619 NULL /* value_table */
622 type = g_type_register_static (DMA_SPARSE_BUFFER_TYPE,
623 "DmaDisassemblyBuffer", &type_info, 0);
626 return type;
630 static DmaDisassemblyBuffer*
631 dma_disassembly_buffer_new (DmaDebuggerQueue *debugger, gulong lower, gulong upper)
633 DmaDisassemblyBuffer *buffer;
635 buffer = g_object_new (DMA_DISASSEMBLY_BUFFER_TYPE, NULL);
636 g_assert (buffer != NULL);
638 buffer->debugger = debugger;
640 DMA_SPARSE_BUFFER (buffer)->lower = lower;
641 DMA_SPARSE_BUFFER (buffer)->upper = upper;
643 return buffer;
646 /* Disassembly view object
647 *---------------------------------------------------------------------------*/
649 struct _DmaDisassemblyView
651 DmaSparseView parent;
652 DmaDebuggerQueue *debugger;
653 gboolean pending;
656 struct _DmaDisassemblyViewClass
658 DmaSparseViewClass parent;
661 #define DMA_DISASSEMBLY_VIEW_TYPE (dma_disassembly_view_get_type ())
662 #define DMA_DISASSEMBLY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyView))
663 #define DMA_DISASSEMBLY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyViewClass))
664 #define IS_DMA_DISASSEMBLY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DMA_DISASSEMBLY_VIEW_TYPE))
665 #define IS_DMA_DISASSEMBLY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DMA_DISASSEMBLY_VIEW_TYPE))
666 #define GET_DMA_DISASSEMBLY_VIEW_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyViewClass))
668 static DmaSparseViewClass *parent_class = NULL;
670 static GType dma_disassembly_view_get_type (void);
672 /* instance_init is the constructor. All functions should work after this
673 * call. */
675 static void
676 dma_disassembly_view_instance_init (DmaSparseView *view)
678 gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
681 /* class_init intialize the class itself not the instance */
683 static void
684 dma_disassembly_view_class_init (DmaDisassemblyViewClass *klass)
686 DmaSparseViewClass* view_class;
688 g_return_if_fail (klass != NULL);
690 parent_class = (DmaSparseViewClass*) g_type_class_peek_parent (klass);
692 view_class = DMA_SPARSE_VIEW_CLASS (klass);
695 static GType
696 dma_disassembly_view_get_type (void)
698 static GType type = 0;
700 if (!type)
702 static const GTypeInfo type_info =
704 sizeof (DmaDisassemblyViewClass),
705 (GBaseInitFunc) NULL,
706 (GBaseFinalizeFunc) NULL,
707 (GClassInitFunc) dma_disassembly_view_class_init,
708 (GClassFinalizeFunc) NULL,
709 NULL, /* class_data */
710 sizeof (DmaDisassemblyView),
711 0, /* n_preallocs */
712 (GInstanceInitFunc) dma_disassembly_view_instance_init,
713 NULL /* value_table */
716 type = g_type_register_static (DMA_SPARSE_VIEW_TYPE,
717 "DmaDisassemblyView", &type_info, 0);
720 return type;
724 static DmaDisassemblyView*
725 dma_disassembly_view_new_with_buffer (DmaDebuggerQueue *debugger, DmaSparseBuffer *buffer)
727 DmaDisassemblyView *view;
729 view = g_object_new (DMA_DISASSEMBLY_VIEW_TYPE, NULL);
730 g_assert (view != NULL);
732 view->debugger = debugger;
734 dma_sparse_view_set_sparse_buffer (DMA_SPARSE_VIEW(view), buffer);
736 return view;
739 /* Private functions
740 *---------------------------------------------------------------------------*/
742 static void
743 on_disassembly_buffer_changed (DmaDisassemblyBuffer *buffer, DmaSparseView *view)
745 dma_sparse_view_refresh (view);
748 static void
749 on_breakpoint_changed (DmaDisassemble *self, IAnjutaDebuggerBreakpointItem *bp)
751 g_return_if_fail (bp != NULL);
753 dma_sparse_view_unmark (self->view, bp->address, IANJUTA_MARKABLE_BREAKPOINT_DISABLED);
754 dma_sparse_view_unmark (self->view, bp->address, IANJUTA_MARKABLE_BREAKPOINT_ENABLED);
755 if (!(bp->type & IANJUTA_DEBUGGER_BREAKPOINT_REMOVED))
757 dma_sparse_view_mark (self->view, bp->address, bp->enable ? IANJUTA_MARKABLE_BREAKPOINT_ENABLED : IANJUTA_MARKABLE_BREAKPOINT_DISABLED);
761 static void
762 destroy_disassemble_gui (DmaDisassemble *self)
764 /* Destroy menu */
765 if (self->menu != NULL)
767 gtk_widget_destroy (self->menu);
768 self->menu = NULL;
771 if (self->window != NULL)
773 gtk_widget_destroy (self->window);
774 self->window = NULL;
775 self->view = NULL;
778 /* Destroy buffer */
779 if (self->buffer)
781 dma_sparse_buffer_free (DMA_SPARSE_BUFFER (self->buffer));
782 self->buffer = NULL;
786 static void
787 on_program_running (DmaDisassemble *self)
789 dma_sparse_view_delete_all_markers (self->view, IANJUTA_MARKABLE_PROGRAM_COUNTER);
792 static void
793 on_program_moved (DmaDisassemble *self, guint pid, guint tid, gulong address, const gchar* file, guint line)
795 dma_sparse_view_delete_all_markers (self->view, IANJUTA_MARKABLE_PROGRAM_COUNTER);
797 if (address != 0)
799 dma_sparse_view_mark (self->view, address, IANJUTA_MARKABLE_PROGRAM_COUNTER);
800 dma_sparse_view_goto (self->view, address);
804 static void
805 on_location_changed (DmaDisassemble *self, gulong address, GFile* file, guint line)
807 dma_sparse_view_goto (self->view, address);
810 static void
811 on_program_unloaded (DmaDisassemble *self)
813 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_unloaded), self);
814 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_breakpoint_changed), self);
815 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_running), self);
816 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_moved), self);
817 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_location_changed), self);
819 dma_sparse_view_delete_all_markers (self->view, IANJUTA_MARKABLE_PROGRAM_COUNTER);
821 destroy_disassemble_gui (self);
824 static gboolean
825 create_disassemble_gui (DmaDisassemble *self)
827 GtkWidget *dataview;
829 g_return_val_if_fail (self->buffer == NULL, FALSE);
830 g_return_val_if_fail (self->window == NULL, FALSE);
832 /* Create buffer */
833 self->buffer = DMA_SPARSE_BUFFER (dma_disassembly_buffer_new (self->debugger, 0x00000000U,0xFFFFFFFFU));
834 if (self->buffer == NULL) return FALSE;
836 dataview = GTK_WIDGET (dma_disassembly_view_new_with_buffer (self->debugger, self->buffer));
837 self->view = DMA_SPARSE_VIEW (dataview);
838 DMA_DISASSEMBLY_VIEW (dataview)->pending = FALSE;
839 g_signal_connect (G_OBJECT (self->buffer), "changed", G_CALLBACK (on_disassembly_buffer_changed), self->view);
841 /* Add disassembly window */
842 self->window = gtk_scrolled_window_new (NULL, NULL);
843 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->window),
844 GTK_POLICY_AUTOMATIC,
845 GTK_POLICY_AUTOMATIC);
846 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self->window),
847 GTK_SHADOW_IN);
848 gtk_container_add (GTK_CONTAINER (self->window), GTK_WIDGET (dataview));
850 anjuta_shell_add_widget (ANJUTA_PLUGIN (self->plugin)->shell,
851 self->window,
852 "AnjutaDebuggerDisassemble", _("Disassembly"),
853 NULL, ANJUTA_SHELL_PLACEMENT_LEFT,
854 NULL);
856 return TRUE;
859 static void
860 on_program_loaded (DmaDisassemble *self)
862 if (!dma_debugger_queue_is_supported (self->debugger, HAS_INSTRUCTION)) return;
864 if (!create_disassemble_gui (self)) return;
866 /* Connect signals */
867 g_signal_connect_swapped (self->plugin, "program-unloaded", G_CALLBACK (on_program_unloaded), self);
868 g_signal_connect_swapped (self->plugin, "breakpoint-changed", G_CALLBACK (on_breakpoint_changed), self);
869 g_signal_connect_swapped (self->plugin, "program-running", G_CALLBACK (on_program_running), self);
870 g_signal_connect_swapped (self->plugin, "program-moved", G_CALLBACK (on_program_moved), self);
871 g_signal_connect_swapped (self->plugin, "location-changed", G_CALLBACK (on_location_changed), self);
874 /* Public functions
875 *---------------------------------------------------------------------------*/
877 gboolean
878 dma_disassemble_is_focus (DmaDisassemble *self)
880 return gtk_widget_is_focus (GTK_WIDGET(self->view));
883 guint
884 dma_disassemble_get_current_address (DmaDisassemble *self)
886 return dma_sparse_view_get_location (self->view);
889 /* Constructor & Destructor
890 *---------------------------------------------------------------------------*/
892 DmaDisassemble*
893 dma_disassemble_new(DebugManagerPlugin *plugin)
895 DmaDisassemble* self;
897 self = g_new0 (DmaDisassemble, 1);
899 self->plugin = plugin;
900 self->debugger = dma_debug_manager_get_queue (plugin);;
902 g_signal_connect_swapped (self->plugin, "program-loaded", G_CALLBACK (on_program_loaded), self);
904 return self;
907 void
908 dma_disassemble_free(DmaDisassemble* self)
910 g_return_if_fail (self != NULL);
912 g_signal_handlers_disconnect_matched (self->plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
914 destroy_disassemble_gui (self);
916 g_free(self);