* configure.in: Bumped version to 2.1.4 (RC1 for 2.2.0).
[anjuta-git-plugin.git] / plugins / debug-manager / disassemble.c
blobce39c7c1c58dba4c62cab6f58820b8ee9f9d9f16
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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"
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 IAnjutaDebugger *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 IAnjutaDebugger *debugger;
87 gboolean pending;
90 struct _DmaDisassemblyBufferClass
92 DmaSparseBufferClass parent;
95 struct _DmaDisassemblyLine
97 guint 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 DEBUG_PRINT("iter_refresh iter->node %p (%x, %d), base %lx offset %ld", iter->node, iter->node != NULL ? iter->node->lower : 0, iter->node != NULL ? ((DmaDisassemblyBufferNode *)iter->node)->size : 0, iter->base, iter->offset);
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 DEBUG_PRINT("iter_refresh offset iter->node %p, base %lx offset %ld line %d line %d", iter->node, iter->base, iter->offset, iter->line, line);
223 if (line != -1)
225 if (iter->offset > 0)
227 /* Need to go upper if possible */
228 guint up = (DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH + iter->offset - 1)/ DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
230 for (;;)
232 gint len = node->size - line;
234 if (up < len)
236 iter->node = (DmaSparseBufferNode *)node;
237 iter->line = line + up;
238 iter->base = node->data[iter->line].address;
239 iter->offset = 0;
241 return TRUE;
244 if (iter->node->upper == dma_sparse_buffer_get_upper (iter->buffer))
246 gboolean move = iter->line != node->size - 1;
248 iter->node = (DmaSparseBufferNode *)node;
249 iter->line = node->size - 1;
250 iter->base = node->data[iter->line].address;
251 iter->offset = 0;
253 return move;
256 up -= len;
258 if ((node->parent.next == NULL) || (node->parent.upper != node->parent.next->lower - 1))
260 /* No following node */
262 iter->node = (DmaSparseBufferNode *)node;
263 iter->base = node->parent.upper + 1;
264 iter->offset = up * DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
266 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
268 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
271 break;
274 node = (DmaDisassemblyBufferNode *)node->parent.next;
275 line = 0;
278 else if (iter->offset < 0)
280 /* Need to go down if possible */
281 gint down = (- iter->offset) / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
283 for (;;)
285 guint len = line;
287 if (down <= len)
289 iter->node = (DmaSparseBufferNode *)node;
290 iter->line = line - down;
291 iter->base = node->data[iter->line].address;
292 iter->offset = 0;
294 return TRUE;
297 if (iter->node->lower == dma_sparse_buffer_get_lower (iter->buffer))
299 gboolean move = iter->line != 0;
301 iter->node = (DmaSparseBufferNode *)node;
302 iter->line = 0;
303 iter->base = node->data[0].address;
304 iter->offset = 0;
306 return move;
309 down -= len;
311 if ((node->parent.prev == NULL) || (node->parent.lower != node->parent.prev->upper + 1))
313 /* No following node */
315 iter->node = (DmaSparseBufferNode *)node;
316 iter->base = node->parent.lower;
317 iter->offset = -down * DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
318 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS)
320 iter->line = iter->offset == 0 ? DMA_DISASSEMBLY_KNOW_ADDRESS : DMA_DISASSEMBLY_UNKNOWN_ADDRESS;
322 break;
325 node = (DmaDisassemblyBufferNode *)node->parent.prev;
326 line = node->size;
331 /* Round offset */
332 DEBUG_PRINT("iter_refresh round iter->node %p, base %lx offset %ld line %d line %d", iter->node, iter->base, iter->offset, iter->line, line);
333 if (iter->offset < 0)
335 gulong address;
336 gboolean move = TRUE;
338 address = iter->offset + iter->base;
339 if ((address < dma_sparse_buffer_get_lower (iter->buffer)) || (address > iter->base))
341 address = dma_sparse_buffer_get_lower (iter->buffer);
342 move = FALSE;
344 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
345 iter->offset = address - iter->base;
347 return move;
349 else if ((iter->offset > 0) || (iter->line == DMA_DISASSEMBLY_UNKNOWN_ADDRESS))
351 gulong address;
352 gboolean move = TRUE;
354 address = iter->offset + iter->base;
355 if ((address > dma_sparse_buffer_get_upper (iter->buffer)) || (address < iter->base))
357 address = dma_sparse_buffer_get_upper (iter->buffer);
358 move = FALSE;
360 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
361 iter->offset = address - iter->base;
363 return move;
366 /* return FALSE if iterator reach the lower or upper limit */
367 return TRUE;
370 static gboolean
371 dma_disassembly_iter_backward_line (DmaSparseIter *iter)
373 iter->offset -= DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
374 return dma_disassembly_iter_refresh (iter);
377 static gboolean
378 dma_disassembly_iter_forward_line (DmaSparseIter *iter)
380 iter->offset += DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
381 return dma_disassembly_iter_refresh (iter);
385 static void
386 dma_disassembly_iter_round (DmaSparseIter *iter, gboolean round_up)
388 iter->offset += round_up ? 1 : -1;
389 dma_disassembly_iter_refresh (iter);
392 static void
393 on_disassemble (const IAnjutaDebuggerDisassembly *block, DmaSparseBufferTransport *trans, GError *err)
395 DmaDisassemblyBufferNode *node;
396 DmaDisassemblyBuffer *buffer = (DmaDisassemblyBuffer *)trans->buffer;
397 DmaSparseBufferNode *next;
398 guint i;
399 char *dst;
401 DEBUG_PRINT ("on disassemble %p", block);
403 if ((err != NULL) && !g_error_matches (err, IANJUTA_DEBUGGER_ERROR, IANJUTA_DEBUGGER_UNABLE_TO_ACCESS_MEMORY))
406 /* Command has been cancelled */
407 dma_sparse_buffer_free_transport (trans);
409 return;
412 /* Find following block */
413 next = dma_sparse_buffer_lookup (DMA_SPARSE_BUFFER (buffer), trans->start + trans->length - 1);
414 if ((next != NULL) && (next->upper <= trans->start)) next = NULL;
416 if (err != NULL)
418 gulong address = trans->start;
419 gint len;
421 DEBUG_PRINT ("Create a dummy disassembly node");
423 /* Create a dummy node */
424 len = (trans->length + DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH - 1) / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
425 node = (DmaDisassemblyBufferNode *)g_malloc0 (sizeof(DmaDisassemblyBufferNode) + sizeof(DmaDisassemblyLine) * len);
426 node->parent.lower = address;
427 for (i = 0; i < len; i++)
429 if ((next != NULL) && (address >= next->lower)) break;
430 node->data[i].address = address;
431 node->data[i].text = "????????";
432 address += DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
433 address -= address % DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH;
435 node->size = i;
436 if ((next != NULL) && (address >= next->lower))
438 address = next->lower -1;
440 else
442 address = trans->start + trans->length - 1;
444 node->parent.upper = address;
446 else
448 guint size = 0;
449 guint line = 0;
451 DEBUG_PRINT ("on disassemble size %d", block->size);
452 /* Compute size of all data */
453 /* use size -1 because last block has no data (NULL) */
454 for (i = trans->tag == DMA_DISASSEMBLY_KEEP_ALL ? 0 : 4; i < block->size - 1; i++)
456 if (block->data[i].label)
458 size += strlen(block->data[i].label) + 2;
459 line++;
461 size += strlen(block->data[i].text) + 1 + DMA_DISASSEMBLY_TAB_LENGTH;
462 line++;
465 node = (DmaDisassemblyBufferNode *)g_malloc0 (sizeof(DmaDisassemblyBufferNode) + sizeof(DmaDisassemblyLine) * line + size);
467 /* Copy all data */
468 dst = (gchar *)&(node->data[line]);
469 line = 0;
470 for (i = trans->tag == DMA_DISASSEMBLY_KEEP_ALL ? 0 : DMA_DISASSEMBLY_SKIP_BEGINNING_LINE; i < block->size - 1; i++)
472 gsize len;
474 if ((next != NULL) && (block->data[i].address == next->lower)) break;
476 /* Add label if exist */
477 if (block->data[i].label != NULL)
479 len = strlen(block->data[i].label);
481 node->data[line].address = block->data[i].address;
482 node->data[line].text = dst;
484 memcpy(dst, block->data[i].label, len);
485 dst[len] = ':';
486 dst[len + 1] = '\0';
488 dst += len + 2;
489 line++;
492 /* Add disassembled instruction */
493 len = strlen(block->data[i].text) + 1;
495 node->data[line].address = block->data[i].address;
496 node->data[line].text = dst;
498 memset (dst, ' ', DMA_DISASSEMBLY_TAB_LENGTH);
499 memcpy (dst + DMA_DISASSEMBLY_TAB_LENGTH, block->data[i].text, len);
500 dst += len + DMA_DISASSEMBLY_TAB_LENGTH;
501 line++;
504 /* fill last block */
505 node->size = line;
506 node->parent.lower = node->data[0].address;
507 node->parent.upper = block->data[i].address - 1;
511 dma_sparse_buffer_insert (DMA_SPARSE_BUFFER (buffer), (DmaSparseBufferNode *)node);
512 dma_sparse_buffer_free_transport (trans);
513 dma_sparse_buffer_changed (DMA_SPARSE_BUFFER (buffer));
516 static void
517 dma_disassembly_buffer_insert_line (DmaSparseIter *iter, GtkTextIter *dst)
519 DmaDisassemblyBuffer * dis = (DmaDisassemblyBuffer *)iter->buffer;
520 GtkTextBuffer *buffer = gtk_text_iter_get_buffer (dst);
522 if (dis->debugger != NULL)
524 dma_sparse_iter_refresh (iter);
525 if (iter->line < DMA_DISASSEMBLY_VALID_ADDRESS)
527 if (iter->buffer->pending == NULL)
529 DmaSparseIter end;
530 DmaSparseBufferTransport *trans;
531 gint i, j;
532 gulong start_adr;
533 gulong end_adr;
534 gint margin;
536 DEBUG_PRINT("no data at address %lx + %ld", iter->base, iter->offset);
538 /* If following line is define, get a block stopping here */
539 dma_sparse_iter_copy (&end, iter);
540 margin = 0;
541 for (j = 0; j < DMA_DISASSEMBLY_BUFFER_BLOCK_SIZE / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH; j++)
543 if (!dma_disassembly_iter_forward_line (&end))
545 end.offset = 0;
546 end.base = dma_sparse_buffer_get_upper (end.buffer);
547 break;
549 if (margin > DMA_DISASSEMBLY_SKIP_BEGINNING_LINE) break;
550 if ((margin != 0) || (end.line >= DMA_DISASSEMBLY_VALID_ADDRESS)) margin++;
552 i = j;
553 if (iter->line == DMA_DISASSEMBLY_UNKNOWN_ADDRESS)
555 for (i = j; i < DMA_DISASSEMBLY_BUFFER_BLOCK_SIZE / DMA_DISASSEMBLY_DEFAULT_LINE_LENGTH; i++)
557 if (!dma_disassembly_iter_backward_line (iter)) break;
558 if (iter->line >= DMA_DISASSEMBLY_VALID_ADDRESS) break;
561 start_adr = dma_sparse_iter_get_address (iter);
562 end_adr = dma_sparse_iter_get_address (&end);
563 trans = dma_sparse_buffer_alloc_transport (DMA_SPARSE_BUFFER (dis), i, 0);
564 trans->tag = i != j ? DMA_DISASSEMBLY_SKIP_BEGINNING : DMA_DISASSEMBLY_KEEP_ALL;
565 trans->start = start_adr;
566 trans->length = end_adr - start_adr;
567 if (end_adr == dma_sparse_buffer_get_upper (DMA_SPARSE_BUFFER (dis)))
569 trans->length++;
571 DEBUG_PRINT("get disassemble %lx %lx %ld", start_adr, end_adr, trans->length);
572 ianjuta_cpu_debugger_disassemble ((IAnjutaCpuDebugger *)dis->debugger, start_adr, end_adr + 1 - start_adr, (IAnjutaDebuggerCallback)on_disassemble, trans, NULL);
575 else
577 /* Fill with known data */
578 gtk_text_buffer_insert (buffer, dst, ((DmaDisassemblyBufferNode *)(iter->node))->data[iter->line].text, -1);
580 return;
584 /* Fill with unknow data */
585 gtk_text_buffer_insert (buffer, dst, "??", 2);
588 static void
589 dma_disassembly_buffer_class_init (DmaDisassemblyBufferClass *klass)
591 DmaSparseBufferClass* buffer_class;
593 g_return_if_fail (klass != NULL);
595 parent_buffer_class = (DmaSparseBufferClass*) g_type_class_peek_parent (klass);
597 buffer_class = DMA_SPARSE_BUFFER_CLASS (klass);
599 buffer_class->refresh_iter = dma_disassembly_iter_refresh;
600 buffer_class->round_iter = dma_disassembly_iter_round;
601 buffer_class->insert_line = dma_disassembly_buffer_insert_line;
602 buffer_class->forward_line = dma_disassembly_iter_forward_line;
603 buffer_class->backward_line = dma_disassembly_iter_backward_line;
604 buffer_class->get_address = dma_disassembly_get_address;
607 static GType
608 dma_disassembly_buffer_get_type (void)
610 static GType type = 0;
612 if (!type)
614 static const GTypeInfo type_info =
616 sizeof (DmaDisassemblyBufferClass),
617 (GBaseInitFunc) NULL,
618 (GBaseFinalizeFunc) NULL,
619 (GClassInitFunc) dma_disassembly_buffer_class_init,
620 (GClassFinalizeFunc) NULL,
621 NULL, /* class_data */
622 sizeof (DmaDisassemblyBuffer),
623 0, /* n_preallocs */
624 (GInstanceInitFunc) NULL,
625 NULL /* value_table */
628 type = g_type_register_static (DMA_SPARSE_BUFFER_TYPE,
629 "DmaDisassemblyBuffer", &type_info, 0);
632 return type;
636 static DmaDisassemblyBuffer*
637 dma_disassembly_buffer_new (IAnjutaDebugger *debugger, gulong lower, gulong upper)
639 DmaDisassemblyBuffer *buffer;
641 buffer = g_object_new (DMA_DISASSEMBLY_BUFFER_TYPE, NULL);
642 g_assert (buffer != NULL);
644 buffer->debugger = debugger;
646 DMA_SPARSE_BUFFER (buffer)->lower = lower;
647 DMA_SPARSE_BUFFER (buffer)->upper = upper;
649 return buffer;
652 static void
653 dma_disassembly_buffer_free (DmaDisassemblyBuffer *buffer)
655 g_object_unref (buffer);
659 /* Disassembly view object
660 *---------------------------------------------------------------------------*/
662 struct _DmaDisassemblyView
664 DmaSparseView parent;
665 IAnjutaDebugger *debugger;
666 gboolean pending;
669 struct _DmaDisassemblyViewClass
671 DmaSparseViewClass parent;
674 #define DMA_DISASSEMBLY_VIEW_TYPE (dma_disassembly_view_get_type ())
675 #define DMA_DISASSEMBLY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyView))
676 #define DMA_DISASSEMBLY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyViewClass))
677 #define IS_DMA_DISASSEMBLY_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DMA_DISASSEMBLY_VIEW_TYPE))
678 #define IS_DMA_DISASSEMBLY_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DMA_DISASSEMBLY_VIEW_TYPE))
679 #define GET_DMA_DISASSEMBLY_VIEW_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DMA_DISASSEMBLY_VIEW_TYPE, DmaDisassemblyViewClass))
681 static DmaSparseViewClass *parent_class = NULL;
683 static GType dma_disassembly_view_get_type (void);
685 static void
686 dma_disassembly_view_class_init (DmaDisassemblyViewClass *klass)
688 DmaSparseViewClass* view_class;
690 g_return_if_fail (klass != NULL);
692 parent_class = (DmaSparseViewClass*) g_type_class_peek_parent (klass);
694 view_class = DMA_SPARSE_VIEW_CLASS (klass);
697 static GType
698 dma_disassembly_view_get_type (void)
700 static GType type = 0;
702 if (!type)
704 static const GTypeInfo type_info =
706 sizeof (DmaDisassemblyViewClass),
707 (GBaseInitFunc) NULL,
708 (GBaseFinalizeFunc) NULL,
709 (GClassInitFunc) dma_disassembly_view_class_init,
710 (GClassFinalizeFunc) NULL,
711 NULL, /* class_data */
712 sizeof (DmaDisassemblyView),
713 0, /* n_preallocs */
714 (GInstanceInitFunc) NULL,
715 NULL /* value_table */
718 type = g_type_register_static (DMA_SPARSE_VIEW_TYPE,
719 "DmaDisassemblyView", &type_info, 0);
722 return type;
726 static DmaDisassemblyView*
727 dma_disassembly_view_new_with_buffer (IAnjutaDebugger *debugger, DmaSparseBuffer *buffer)
729 DmaDisassemblyView *view;
731 view = g_object_new (DMA_DISASSEMBLY_VIEW_TYPE, NULL);
732 g_assert (view != NULL);
734 view->debugger = debugger;
736 dma_sparse_view_set_sparse_buffer (DMA_SPARSE_VIEW(view), buffer);
738 return view;
741 static void
742 dma_disassembly_view_free (DmaDisassemblyView *view)
744 g_object_unref (view);
747 /* Private functions
748 *---------------------------------------------------------------------------*/
750 static void
751 on_disassembly_buffer_changed (DmaDisassemblyBuffer *buffer, DmaSparseView *view)
753 dma_sparse_view_refresh (view);
756 static void
757 on_breakpoint_changed (DmaDisassemble *self, IAnjutaDebuggerBreakpoint *bp)
759 g_return_if_fail (bp != NULL);
761 dma_disassemble_unmark (self, bp->address, IANJUTA_MARKABLE_BREAKPOINT_DISABLED);
762 dma_disassemble_unmark (self, bp->address, IANJUTA_MARKABLE_BREAKPOINT_ENABLED);
763 if (bp->type != IANJUTA_DEBUGGER_BREAK_REMOVED)
765 dma_disassemble_mark (self, bp->address, bp->enable ? IANJUTA_MARKABLE_BREAKPOINT_ENABLED : IANJUTA_MARKABLE_BREAKPOINT_DISABLED);
769 static GtkWidget*
770 create_disassemble_gui (DmaDisassemble *self)
772 GtkWidget *dataview;
774 dataview = GTK_WIDGET (dma_disassembly_view_new_with_buffer (self->debugger, self->buffer));
776 /* Add register window */
777 self->window = gtk_scrolled_window_new (NULL, NULL);
778 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->window),
779 GTK_POLICY_AUTOMATIC,
780 GTK_POLICY_AUTOMATIC);
781 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self->window),
782 GTK_SHADOW_IN);
783 gtk_container_add (GTK_CONTAINER (self->window), GTK_WIDGET (dataview));
785 anjuta_shell_add_widget (ANJUTA_PLUGIN (self->plugin)->shell,
786 self->window,
787 "AnjutaDebuggerDisassemble", _("Disassembly"),
788 NULL, ANJUTA_SHELL_PLACEMENT_LEFT,
789 NULL);
792 DMA_DISASSEMBLY_VIEW (dataview)->pending = FALSE;
794 return dataview;
797 static void
798 on_debugger_started (DmaDisassemble *self)
800 self->buffer = DMA_SPARSE_BUFFER (dma_disassembly_buffer_new (self->debugger, 0x00000000U,0xFFFFFFFFU));
802 self->view = DMA_SPARSE_VIEW (create_disassemble_gui (self));
804 g_signal_connect_swapped (self->plugin, "breakpoint-changed", G_CALLBACK (on_breakpoint_changed), self);
806 g_signal_connect (G_OBJECT (self->buffer),
807 "changed",
808 G_CALLBACK (on_disassembly_buffer_changed),
809 self->view);
812 static void
813 destroy_disassemble_gui (DmaDisassemble *self)
815 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_breakpoint_changed), self);
817 /* Destroy menu */
818 if (self->menu != NULL)
820 gtk_widget_destroy (self->menu);
821 self->menu = NULL;
824 if (self->window != NULL)
826 gtk_widget_destroy (self->window);
827 self->window = NULL;
828 self->view = NULL;
832 static void
833 on_debugger_stopped (DmaDisassemble *self)
835 g_signal_handlers_disconnect_by_func (self->buffer,
836 on_disassembly_buffer_changed,
837 self->view);
839 dma_sparse_buffer_free (DMA_SPARSE_BUFFER (self->buffer));
840 self->buffer = NULL;
842 destroy_disassemble_gui (self);
845 /* Public functions
846 *---------------------------------------------------------------------------*/
848 void
849 dma_disassemble_mark (DmaDisassemble *self, guint address, gint marker)
851 g_return_if_fail (self != NULL);
852 g_return_if_fail (self->view != NULL);
854 dma_sparse_view_mark (self->view, address, marker);
857 void
858 dma_disassemble_unmark (DmaDisassemble *self, guint address, gint marker)
860 g_return_if_fail (self != NULL);
861 g_return_if_fail (self->view != NULL);
863 dma_sparse_view_unmark (self->view, address, marker);
866 void
867 dma_disassemble_clear_all_mark (DmaDisassemble *self, gint marker)
869 g_return_if_fail (self != NULL);
870 /* Accept to clear mark without a view, used at initialization */
871 if (self->view != NULL)
872 dma_sparse_view_delete_all_markers (self->view, marker);
875 void
876 dma_disassemble_goto_address (DmaDisassemble *self, guint address)
878 g_return_if_fail (self != NULL);
879 g_return_if_fail (self->view != NULL);
881 dma_sparse_view_goto (self->view, address);
884 /* Constructor & Destructor
885 *---------------------------------------------------------------------------*/
887 DmaDisassemble*
888 dma_disassemble_new(AnjutaPlugin *plugin, IAnjutaDebugger *debugger)
890 DmaDisassemble* self;
892 self = g_new0 (DmaDisassemble, 1);
894 self->debugger = debugger;
895 if (debugger != NULL) g_object_ref (debugger);
896 self->plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
897 self->buffer = NULL;
898 self->view = NULL;
900 g_signal_connect_swapped (self->debugger, "debugger-started", G_CALLBACK (on_debugger_started), self);
901 g_signal_connect_swapped (self->debugger, "debugger-stopped", G_CALLBACK (on_debugger_stopped), self);
903 return self;
906 void
907 dma_disassemble_free(DmaDisassemble* self)
909 g_return_if_fail (self != NULL);
911 destroy_disassemble_gui (self);
913 if (self->debugger != NULL) g_object_unref (self->debugger);
915 g_free(self);