Added byline
[anjuta.git] / plugins / debug-manager / plugin.c
blob5ae284469ce0e8825ba6ce54128b5ee0464cee83
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 plugin.c
4 Copyright (C) 2004 Naba Kumar
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 #include <config.h>
23 /*#define DEBUG*/
25 #include "plugin.h"
27 #include "breakpoints.h"
28 #include "stack_trace.h"
29 #include "info.h"
30 #include "memory.h"
31 #include "disassemble.h"
32 #include "signals.h"
33 #include "sharedlib.h"
34 #include "registers.h"
35 #include "utilities.h"
36 #include "start.h"
37 #include "queue.h"
38 #include "variable.h"
40 #include <glib/gi18n.h>
41 #include <libanjuta/anjuta-shell.h>
42 #include <libanjuta/anjuta-debug.h>
43 #include <libanjuta/anjuta-status.h>
44 #include <libanjuta/interfaces/ianjuta-file.h>
45 #include <libanjuta/interfaces/ianjuta-editor.h>
46 #include <libanjuta/interfaces/ianjuta-indicable.h>
47 #include <libanjuta/interfaces/ianjuta-markable.h>
48 #include <libanjuta/interfaces/ianjuta-debug-manager.h>
49 #include <libanjuta/interfaces/ianjuta-project-manager.h>
50 #include <libanjuta/interfaces/ianjuta-document-manager.h>
51 #include <libanjuta/interfaces/ianjuta-message-manager.h>
53 #include <gio/gio.h>
55 /* Contants defintion
56 *---------------------------------------------------------------------------*/
58 #define ICON_FILE "anjuta-debug-manager-plugin-48.png"
59 #define UI_FILE PACKAGE_DATA_DIR "/ui/anjuta-debug-manager.xml"
61 /* Plugin type
62 *---------------------------------------------------------------------------*/
64 struct _DebugManagerPlugin
66 AnjutaPlugin parent;
68 /* Debugger queue */
69 DmaDebuggerQueue *queue;
71 /* Menu item */
72 gint uiid;
73 GtkActionGroup *start_group;
74 GtkActionGroup *loaded_group;
75 GtkActionGroup *stopped_group;
76 GtkActionGroup *running_group;
77 GtkAction *run_stop_action;
79 /* Project */
80 gchar *project_root_uri;
81 guint project_watch_id;
83 /* Editor */
84 IAnjutaEditor *current_editor;
85 guint editor_watch_id;
86 IAnjutaEditor *pc_editor;
87 guint pc_line;
88 gulong pc_address;
89 gboolean busy;
91 /* Debugger components */
92 BreakpointsDBase *breakpoints;
93 DmaStart *start;
94 StackTrace *stack;
95 CpuRegisters *registers;
96 Sharedlibs *sharedlibs;
97 Signals *signals;
98 DmaMemory *memory;
99 DmaDisassemble *disassemble;
100 DmaVariableDBase *variable;
103 GtkWidget *user_command_dialog;
105 /* Logging view */
106 IAnjutaMessageView* view;
109 struct _DebugManagerPluginClass
111 AnjutaPluginClass parent_class;
114 /* Private functions
115 *---------------------------------------------------------------------------*/
117 static void
118 register_stock_icons (AnjutaPlugin *plugin)
120 static gboolean registered = FALSE;
122 if (registered)
123 return;
124 registered = TRUE;
126 /* Register stock icons */
127 BEGIN_REGISTER_ICON (plugin)
128 REGISTER_ICON (ICON_FILE, "debugger-icon");
129 REGISTER_ICON ("stack.png", "gdb-stack-icon");
130 REGISTER_ICON ("locals.png", "gdb-locals-icon");
131 REGISTER_ICON_FULL ("anjuta-watch", "gdb-watch-icon");
132 REGISTER_ICON_FULL ("anjuta-breakpoint-toggle", ANJUTA_STOCK_BREAKPOINT_TOGGLE);
133 REGISTER_ICON_FULL ("anjuta-breakpoint-clear", ANJUTA_STOCK_BREAKPOINT_CLEAR);
134 /* We have no -24 version for the next two */
135 REGISTER_ICON ("anjuta-breakpoint-disabled-16.png", ANJUTA_STOCK_BREAKPOINT_DISABLED);
136 REGISTER_ICON ("anjuta-breakpoint-enabled-16.png", ANJUTA_STOCK_BREAKPOINT_ENABLED);
137 REGISTER_ICON_FULL ("anjuta-attach", "debugger-attach");
138 REGISTER_ICON_FULL ("anjuta-step-into", "debugger-step-into");
139 REGISTER_ICON_FULL ("anjuta-step-out", "debugger-step-out");
140 REGISTER_ICON_FULL ("anjuta-step-over", "debugger-step-over");
141 REGISTER_ICON_FULL ("anjuta-run-to-cursor", "debugger-run-to-cursor");
142 REGISTER_ICON_FULL ("anjuta-memory", "debugger-memory");
143 REGISTER_ICON_FULL ("anjuta-disassembly", "debugger-disassembly");
144 END_REGISTER_ICON
147 /* Program counter functions
148 *---------------------------------------------------------------------------*/
150 static void
151 show_program_counter_in_editor(DebugManagerPlugin *self)
153 IAnjutaEditor *editor = self->current_editor;
155 if ((editor != NULL) && (self->pc_editor == editor))
157 if (IANJUTA_IS_MARKABLE (editor))
159 ianjuta_markable_mark(IANJUTA_MARKABLE (editor), self->pc_line, IANJUTA_MARKABLE_PROGRAM_COUNTER, NULL, NULL);
161 if (IANJUTA_IS_INDICABLE(editor))
163 IAnjutaIterable *begin =
164 ianjuta_editor_get_line_begin_position(editor, self->pc_line, NULL);
165 IAnjutaIterable *end =
166 ianjuta_editor_get_line_end_position(editor, self->pc_line, NULL);
168 ianjuta_indicable_set(IANJUTA_INDICABLE(editor), begin, end,
169 IANJUTA_INDICABLE_IMPORTANT, NULL);
170 g_object_unref (begin);
171 g_object_unref (end);
176 static void
177 hide_program_counter_in_editor(DebugManagerPlugin *self)
179 IAnjutaEditor *editor = self->current_editor;
181 if ((editor != NULL) && (self->pc_editor == editor))
183 if (IANJUTA_IS_MARKABLE (editor))
185 ianjuta_markable_delete_all_markers (IANJUTA_MARKABLE (editor), IANJUTA_MARKABLE_PROGRAM_COUNTER, NULL);
187 if (IANJUTA_IS_INDICABLE(editor))
189 ianjuta_indicable_clear(IANJUTA_INDICABLE(editor), NULL);
194 static void
195 set_program_counter(DebugManagerPlugin *self, const gchar* filename, guint line, gulong address)
197 IAnjutaDocumentManager *docman = NULL;
198 GFile* file;
200 /* Remove previous marker */
201 hide_program_counter_in_editor (self);
202 if (self->pc_editor != NULL)
204 g_object_remove_weak_pointer (G_OBJECT (self->pc_editor), (gpointer *)(gpointer)&self->pc_editor);
205 self->pc_editor = NULL;
207 self->pc_address = address;
209 if (filename != NULL)
211 file = g_file_new_for_path (filename);
212 docman = anjuta_shell_get_interface (ANJUTA_PLUGIN (self)->shell, IAnjutaDocumentManager, NULL);
213 if (docman)
215 IAnjutaEditor* editor;
217 editor = ianjuta_document_manager_goto_file_line(docman, file, line, NULL);
219 if (editor != NULL)
221 self->pc_editor = editor;
222 g_object_add_weak_pointer (G_OBJECT (editor), (gpointer)(gpointer)&self->pc_editor);
223 self->pc_line = line;
224 show_program_counter_in_editor (self);
227 g_object_unref (file);
231 static void
232 value_added_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
233 const GValue *value, gpointer user_data)
235 DebugManagerPlugin *dm_plugin;
236 const gchar *root_uri;
238 dm_plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
240 if (dm_plugin->project_root_uri)
241 g_free (dm_plugin->project_root_uri);
242 dm_plugin->project_root_uri = NULL;
244 root_uri = g_value_get_string (value);
245 if (root_uri)
247 dm_plugin->project_root_uri = g_strdup (root_uri);
251 static void
252 value_removed_project_root_uri (AnjutaPlugin *plugin, const gchar *name,
253 gpointer user_data)
255 DebugManagerPlugin *dm_plugin;
257 dm_plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
259 if (dm_plugin->project_root_uri)
260 g_free (dm_plugin->project_root_uri);
261 dm_plugin->project_root_uri = NULL;
264 static void
265 value_added_current_editor (AnjutaPlugin *plugin, const char *name,
266 const GValue *value, gpointer data)
268 GObject *editor;
269 DebugManagerPlugin *self;
271 self = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
273 editor = g_value_get_object (value);
274 DEBUG_PRINT("add value current editor %p", editor);
276 if (self->current_editor)
277 g_object_remove_weak_pointer (G_OBJECT (self->current_editor), (gpointer *)(gpointer)&self->current_editor);
279 if (!IANJUTA_IS_EDITOR(editor))
281 self->current_editor = NULL;
282 return;
285 self->current_editor = IANJUTA_EDITOR (editor);
286 g_object_add_weak_pointer (G_OBJECT (self->current_editor), (gpointer *)(gpointer)&self->current_editor);
288 /* Restore program counter marker */
289 show_program_counter_in_editor (self);
291 /* connect signal to enable/disable breakpoints on double clicking the line marks gutter */
292 /* firstly, find the handler of previously connected signal */
293 /* secondly, connect signal if a handler wasn't found for the signal */
294 guint signal_id = g_signal_lookup( "line-marks-gutter-clicked", IANJUTA_TYPE_EDITOR);
295 glong handler_id = g_signal_handler_find( (gpointer)self->current_editor,
296 G_SIGNAL_MATCH_ID,
297 signal_id,
298 0, NULL, NULL, NULL );
301 DEBUG_PRINT("current editor %p, breapoints db %p", self->current_editor, self->breakpoints);
303 if(!handler_id) {
304 g_signal_connect (
305 self->current_editor,
306 "line-marks-gutter-clicked",
307 G_CALLBACK (breakpoint_toggle_handler),
308 self->breakpoints
314 static void
315 value_removed_current_editor (AnjutaPlugin *plugin,
316 const char *name, gpointer data)
318 DebugManagerPlugin *self = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
320 DEBUG_PRINT("remove value current editor %p", self->current_editor);
321 if (self->current_editor)
323 hide_program_counter_in_editor (self);
325 g_object_remove_weak_pointer (G_OBJECT (self->current_editor), (gpointer *)(gpointer)&self->current_editor);
327 self->current_editor = NULL;
330 static void
331 enable_log_view (DebugManagerPlugin *this, gboolean enable)
333 if (enable)
335 if (this->view == NULL)
337 IAnjutaMessageManager* man;
339 man = anjuta_shell_get_interface (ANJUTA_PLUGIN (this)->shell, IAnjutaMessageManager, NULL);
340 this->view = ianjuta_message_manager_add_view (man, _("Debugger Log"), ICON_FILE, NULL);
341 if (this->view != NULL)
343 /*g_signal_connect (G_OBJECT (this->view), "buffer_flushed", G_CALLBACK (on_message_buffer_flushed), this);*/
344 g_object_add_weak_pointer (G_OBJECT (this->view), (gpointer *)(gpointer)&this->view);
345 dma_queue_enable_log (this->queue, this->view);
348 else
350 ianjuta_message_view_clear (this->view, NULL);
353 else
355 if (this->view != NULL)
357 IAnjutaMessageManager* man;
359 man = anjuta_shell_get_interface (ANJUTA_PLUGIN (this)->shell, IAnjutaMessageManager, NULL);
360 ianjuta_message_manager_remove_view (man, this->view, NULL);
361 this->view = NULL;
363 if (this->queue != NULL)
365 dma_queue_disable_log (this->queue);
370 static void
371 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
372 AnjutaSession *session, DebugManagerPlugin *plugin)
374 if (phase == ANJUTA_SESSION_PHASE_FIRST)
375 enable_log_view (plugin, FALSE);
376 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
377 return;
379 /* Close debugger when session changed */
380 if (plugin->queue)
382 dma_queue_abort (plugin->queue);
386 /* State functions
387 *---------------------------------------------------------------------------*/
389 /* Called when the debugger is started but no program is loaded */
391 static void
392 dma_plugin_debugger_started (DebugManagerPlugin *this)
394 GtkAction *action;
395 AnjutaStatus* status;
397 DEBUG_PRINT ("%s", "DMA: dma_plugin_debugger_started");
399 /* Update ui */
400 action = gtk_action_group_get_action (this->start_group, "ActionDebuggerStop");
401 gtk_action_set_sensitive (action, TRUE);
402 gtk_action_group_set_visible (this->loaded_group, TRUE);
403 gtk_action_group_set_sensitive (this->loaded_group, FALSE);
404 gtk_action_group_set_visible (this->stopped_group, TRUE);
405 gtk_action_group_set_sensitive (this->stopped_group, FALSE);
406 gtk_action_group_set_visible (this->running_group, TRUE);
407 gtk_action_group_set_sensitive (this->running_group, FALSE);
409 status = anjuta_shell_get_status(ANJUTA_PLUGIN (this)->shell, NULL);
410 anjuta_status_set_default (status, _("Debugger"), _("Started"));
413 /* Called when a program is loaded */
415 static void
416 dma_plugin_program_loaded (DebugManagerPlugin *this)
418 AnjutaStatus* status;
420 DEBUG_PRINT ("%s", "DMA: dma_plugin_program_loaded");
422 /* Update ui */
423 gtk_action_group_set_sensitive (this->loaded_group, TRUE);
424 gtk_action_group_set_sensitive (this->stopped_group, FALSE);
425 gtk_action_group_set_sensitive (this->running_group, FALSE);
427 gtk_action_set_sensitive (this->run_stop_action, FALSE);
429 status = anjuta_shell_get_status(ANJUTA_PLUGIN (this)->shell, NULL);
430 anjuta_status_set_default (status, _("Debugger"), _("Loaded"));
433 /* Called when the program is running */
435 static void
436 dma_plugin_program_running (DebugManagerPlugin *this)
438 AnjutaStatus* status;
440 DEBUG_PRINT ("%s", "DMA: dma_plugin_program_running");
442 /* Update ui */
443 gtk_action_group_set_sensitive (this->loaded_group, TRUE);
444 gtk_action_group_set_sensitive (this->stopped_group, FALSE);
445 gtk_action_group_set_sensitive (this->running_group, TRUE);
447 gtk_action_set_sensitive (this->run_stop_action, TRUE);
448 gtk_action_set_stock_id (this->run_stop_action, GTK_STOCK_MEDIA_PAUSE);
449 gtk_action_set_label (this->run_stop_action, _("Pa_use Program"));
450 gtk_action_set_tooltip (this->run_stop_action, _("Pauses the execution of the program"));
452 status = anjuta_shell_get_status(ANJUTA_PLUGIN (this)->shell, NULL);
453 anjuta_status_set_default (status, _("Debugger"), _("Running…"));
455 set_program_counter(this, NULL, 0, 0);
458 /* Called when the program is stopped */
460 static void
461 dma_plugin_program_stopped (DebugManagerPlugin *this)
463 AnjutaStatus* status;
465 DEBUG_PRINT ("%s", "DMA: dma_plugin_program_broken");
467 /* Update ui */
468 gtk_action_group_set_sensitive (this->loaded_group, TRUE);
469 gtk_action_group_set_sensitive (this->stopped_group, TRUE);
470 gtk_action_group_set_sensitive (this->running_group, FALSE);
472 gtk_action_set_sensitive (this->run_stop_action, TRUE);
473 gtk_action_set_stock_id (this->run_stop_action, GTK_STOCK_MEDIA_PLAY);
474 gtk_action_set_label (this->run_stop_action, _("Run/_Continue"));
475 gtk_action_set_tooltip (this->run_stop_action, _("Continue the execution of the program"));
477 status = anjuta_shell_get_status(ANJUTA_PLUGIN (this)->shell, NULL);
478 anjuta_status_set_default (status, _("Debugger"), _("Stopped"));
481 /* Called when the program postion change */
483 static void
484 dma_plugin_program_moved (DebugManagerPlugin *this, guint pid, guint tid, gulong address, const gchar* file, guint line)
486 DEBUG_PRINT ("DMA: dma_plugin_program_moved %s %d %lx", file, line, address);
488 set_program_counter (this, file, line, address);
491 /* Called when a program is unloaded */
492 static void
493 dma_plugin_program_unload (DebugManagerPlugin *this)
495 AnjutaStatus* status;
497 DEBUG_PRINT ("%s", "DMA: dma_plugin_program_unload");
499 /* Update ui */
500 gtk_action_group_set_visible (this->start_group, TRUE);
501 gtk_action_group_set_sensitive (this->start_group, TRUE);
502 gtk_action_group_set_visible (this->loaded_group, TRUE);
503 gtk_action_group_set_sensitive (this->loaded_group, FALSE);
504 gtk_action_group_set_visible (this->stopped_group, TRUE);
505 gtk_action_group_set_sensitive (this->stopped_group, FALSE);
506 gtk_action_group_set_visible (this->running_group, TRUE);
507 gtk_action_group_set_sensitive (this->running_group, FALSE);
509 status = anjuta_shell_get_status(ANJUTA_PLUGIN (this)->shell, NULL);
510 anjuta_status_set_default (status, _("Debugger"), _("Unloaded"));
513 /* Called when the debugger is stopped */
515 static void
516 dma_plugin_debugger_stopped (DebugManagerPlugin *self, GError *err)
518 GtkAction *action;
519 AnjutaStatus* state;
521 DEBUG_PRINT ("%s", "DMA: dma_plugin_debugger_stopped");
523 dma_plugin_program_unload (self);
525 /* Update ui */
526 gtk_action_group_set_visible (self->start_group, TRUE);
527 gtk_action_group_set_sensitive (self->start_group, TRUE);
528 action = gtk_action_group_get_action (self->start_group, "ActionDebuggerStop");
529 gtk_action_set_sensitive (action, FALSE);
530 gtk_action_group_set_visible (self->loaded_group, TRUE);
531 gtk_action_group_set_sensitive (self->loaded_group, FALSE);
532 gtk_action_group_set_visible (self->stopped_group, TRUE);
533 gtk_action_group_set_sensitive (self->stopped_group, FALSE);
534 gtk_action_group_set_visible (self->running_group, TRUE);
535 gtk_action_group_set_sensitive (self->running_group, FALSE);
537 /* clear indicator */
538 set_program_counter (self, NULL, 0, 0);
540 state = anjuta_shell_get_status(ANJUTA_PLUGIN (self)->shell, NULL);
541 anjuta_status_set_default (state, _("Debugger"), NULL);
543 /* Remove user command dialog if existing */
544 if (self->user_command_dialog) gtk_widget_destroy (GTK_WIDGET (self->user_command_dialog));
546 /* Display a warning if debugger stop unexpectedly */
547 if (err != NULL)
549 GtkWindow *parent = GTK_WINDOW (ANJUTA_PLUGIN(self)->shell);
550 anjuta_util_dialog_error (parent, _("Debugger terminated with error %d: %s\n"), err->code, err->message);
555 static void
556 dma_plugin_signal_received (DebugManagerPlugin *self, const gchar *name, const gchar *description)
558 GtkWindow *parent = GTK_WINDOW (ANJUTA_PLUGIN (self)->shell);
560 /* Skip SIGINT signal */
561 if (strcmp(name, "SIGINT") != 0)
563 anjuta_util_dialog_warning (parent, _("Program has received signal: %s\n"), description);
567 /* Called when the user want to go to another location */
569 static void
570 dma_plugin_location_changed (DebugManagerPlugin *self, gulong address, const gchar *uri, guint line)
572 /* Go to location in editor */
573 if (uri != NULL)
575 IAnjutaDocumentManager *docman;
576 docman = anjuta_shell_get_interface (ANJUTA_PLUGIN(self)->shell, IAnjutaDocumentManager, NULL);
577 if (docman)
579 GFile *file = g_file_new_for_uri (uri);
580 ianjuta_document_manager_goto_file_line (docman, file, line, NULL);
581 g_object_unref (file);
586 /* Start/Stop menu functions
587 *---------------------------------------------------------------------------*/
589 static void
590 on_start_debug_activate (GtkAction* action, DebugManagerPlugin* this)
592 enable_log_view (this, TRUE);
593 dma_run_target (this->start, NULL);
596 static void
597 on_attach_to_project_action_activate (GtkAction* action, DebugManagerPlugin* this)
599 enable_log_view (this, TRUE);
600 dma_attach_to_process (this->start);
603 static void
604 on_start_remote_debug_action_activate (GtkAction* action, DebugManagerPlugin* this)
606 /* Returns true if user clicked "Connect" */
607 enable_log_view (this, TRUE);
608 dma_run_remote_target (this->start, NULL, NULL);
611 static void
612 on_debugger_stop_activate (GtkAction* action, DebugManagerPlugin* plugin)
614 if (plugin->start)
616 dma_quit_debugger (plugin->start);
620 static void
621 on_add_source_activate (GtkAction* action, DebugManagerPlugin* this)
623 dma_add_source_path (this->start);
626 /* Execute call back
627 *---------------------------------------------------------------------------*/
629 static void
630 on_run_continue_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
632 if (plugin->queue)
633 dma_queue_run (plugin->queue);
636 static void
637 on_continue_suspend_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
639 if (plugin->queue)
641 if (gtk_action_group_get_sensitive (plugin->running_group))
643 dma_queue_interrupt (plugin->queue);
645 else
647 dma_queue_run (plugin->queue);
652 static void
653 on_step_in_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
655 if (plugin->queue)
657 if ((plugin->disassemble != NULL) && (dma_disassemble_is_focus (plugin->disassemble)))
659 dma_queue_stepi_in (plugin->queue);
661 else
663 dma_queue_step_in (plugin->queue);
668 static void
669 on_step_over_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
671 if (plugin->queue)
673 if ((plugin->disassemble != NULL) && (dma_disassemble_is_focus (plugin->disassemble)))
675 dma_queue_stepi_over (plugin->queue);
677 else
679 dma_queue_step_over (plugin->queue);
684 static void
685 on_step_out_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
687 if (plugin->queue)
688 dma_queue_step_out (plugin->queue);
691 static void
692 on_run_to_cursor_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
694 if (plugin->queue)
696 if ((plugin->disassemble != NULL) && (dma_disassemble_is_focus (plugin->disassemble)))
698 gulong address;
700 address = dma_disassemble_get_current_address (plugin->disassemble);
701 dma_queue_run_to_address (plugin->queue, address);
703 else
705 IAnjutaEditor *editor;
706 GFile* file;
707 gchar *filename;
708 gint line;
710 editor = dma_get_current_editor (ANJUTA_PLUGIN (plugin));
711 if (editor == NULL)
712 return;
713 file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
714 if (file == NULL)
715 return;
717 filename = g_file_get_path (file);
719 line = ianjuta_editor_get_lineno (editor, NULL);
720 dma_queue_run_to (plugin->queue, filename, line);
721 g_free (filename);
722 g_object_unref (file);
727 static void
728 on_run_from_cursor_action_activate (GtkAction* action, DebugManagerPlugin* plugin)
730 if (plugin->queue)
732 if ((plugin->disassemble != NULL) && (dma_disassemble_is_focus (plugin->disassemble)))
734 gulong address;
736 address = dma_disassemble_get_current_address (plugin->disassemble);
737 dma_queue_run_from_address (plugin->queue, address);
739 else
741 IAnjutaEditor *editor;
742 GFile* file;
743 gchar *filename;
744 gint line;
746 editor = dma_get_current_editor (ANJUTA_PLUGIN (plugin));
747 if (editor == NULL)
748 return;
749 file = ianjuta_file_get_file (IANJUTA_FILE (editor), NULL);
750 if (file == NULL)
751 return;
753 filename = g_file_get_path (file);
755 line = ianjuta_editor_get_lineno (editor, NULL);
756 dma_queue_run_from (plugin->queue, filename, line);
757 g_free (filename);
758 g_object_unref (file);
763 static void
764 on_debugger_interrupt_activate (GtkAction* action, DebugManagerPlugin* plugin)
766 if (plugin->queue)
767 dma_queue_interrupt (plugin->queue);
770 /* Custom command
771 *---------------------------------------------------------------------------*/
773 static void
774 on_debugger_command_entry_activate (GtkEntry *entry, DebugManagerPlugin *plugin)
776 const gchar *command;
778 command = gtk_entry_get_text (GTK_ENTRY (entry));
779 if (command && strlen (command))
780 dma_queue_send_command (plugin->queue, command);
781 gtk_entry_set_text (entry, "");
784 static void
785 on_debugger_custom_command_activate (GtkAction * action, DebugManagerPlugin *plugin)
787 if (plugin->user_command_dialog == NULL)
789 GtkBuilder *bxml;
790 GtkWidget *entry;
792 bxml = anjuta_util_builder_new (GLADE_FILE, NULL);
793 if (!bxml) return;
794 anjuta_util_builder_get_objects (bxml,
795 "debugger_command_dialog", &plugin->user_command_dialog,
796 "debugger_command_entry", &entry,
797 NULL);
798 g_object_unref (bxml);
800 gtk_window_set_transient_for (GTK_WINDOW (plugin->user_command_dialog), GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell));
802 g_object_add_weak_pointer (G_OBJECT (plugin->user_command_dialog), (gpointer *)&plugin->user_command_dialog);
804 g_signal_connect_swapped (plugin->user_command_dialog, "response",
805 G_CALLBACK (gtk_widget_destroy),
806 plugin->user_command_dialog);
807 g_signal_connect (entry, "activate",
808 G_CALLBACK (on_debugger_command_entry_activate),
809 plugin);
811 gtk_widget_show_all (GTK_WIDGET (plugin->user_command_dialog));
813 else
815 gtk_window_present (GTK_WINDOW (plugin->user_command_dialog));
819 /* Other informations
820 *---------------------------------------------------------------------------*/
822 /*static void
823 on_info_memory_activate (GtkAction * action, DebugManagerPlugin *plugin)
825 GtkWidget *win_memory;
827 win_memory = memory_info_new (plugin->debugger,
828 GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell),
829 NULL);
830 gtk_widget_show(win_memory);
833 static void
834 on_debugger_sharedlibs_activate (GtkAction * action, DebugManagerPlugin *plugin)
836 sharedlibs_show (plugin->sharedlibs);
839 static void
840 on_debugger_signals_activate (GtkAction * action, DebugManagerPlugin *plugin)
842 signals_show (plugin->signals);
845 /* Actions table
846 *---------------------------------------------------------------------------*/
848 static GtkActionEntry actions_start[] =
851 "ActionMenuDebug", /* Action name */
852 NULL, /* Stock icon, if any */
853 N_("_Debug"), /* Display label */
854 NULL, /* short-cut */
855 NULL, /* Tooltip */
856 NULL /* action callback */
859 "ActionMenuStart",
860 "debugger-icon",
861 N_("_Start Debugger"),
862 NULL,
863 NULL,
864 NULL
867 "ActionDebuggerRunTarget",
868 NULL,
869 N_("_Debug Program"),
870 "<shift>F12",
871 N_("Start debugger and load the program"),
872 G_CALLBACK (on_start_debug_activate)
875 "ActionDebuggerAttachProcess",
876 "debugger-attach",
877 N_("_Debug Process…"),
878 NULL,
879 N_("Start debugger and attach to a running program"),
880 G_CALLBACK (on_attach_to_project_action_activate)
883 "ActionDebuggerDebugRemote",
884 "debugger-remote-target",
885 N_("Debug _Remote Target…"),
886 NULL,
887 N_("Connect to a remote debugging target"),
888 G_CALLBACK (on_start_remote_debug_action_activate),
891 "ActionDebuggerStop",
892 GTK_STOCK_STOP,
893 N_("Stop Debugger"),
894 NULL,
895 N_("Say goodbye to the debugger"),
896 G_CALLBACK (on_debugger_stop_activate)
899 "ActionDebuggerAddSource",
900 NULL,
901 N_("Add source paths…"),
902 NULL,
903 N_("Add additional source paths"),
904 G_CALLBACK (on_add_source_activate)
908 static GtkActionEntry actions_loaded[] =
911 "ActionGdbCommand", /* Action name */
912 NULL, /* Stock icon, if any */
913 N_("Debugger Command…"), /* Display label */
914 NULL, /* short-cut */
915 N_("Custom debugger command"), /* Tooltip */
916 G_CALLBACK (on_debugger_custom_command_activate) /* action callback */
919 "ActionMenuGdbInformation",
920 NULL,
921 N_("_Info"),
922 NULL,
923 NULL,
924 NULL
927 "ActionGdbViewSharedlibs",
928 NULL,
929 N_("Shared Libraries"),
930 NULL,
931 N_("Show shared library mappings"),
932 G_CALLBACK (on_debugger_sharedlibs_activate)
935 "ActionGdbViewSignals",
936 NULL,
937 N_("Kernel Signals"),
938 NULL,
939 N_("Show kernel signals"),
940 G_CALLBACK (on_debugger_signals_activate)
943 "ActionDebuggerContinueSuspend",
944 GTK_STOCK_MEDIA_PLAY,
945 N_("_Continue/Suspend"),
946 "F4",
947 N_("Continue or suspend the execution of the program"),
948 G_CALLBACK (on_continue_suspend_action_activate)
952 static GtkActionEntry actions_stopped[] =
955 "ActionDebuggerRunContinue", /* Action name */
956 GTK_STOCK_MEDIA_PLAY, /* Stock icon, if any */
957 N_("Run/_Continue"), /* Display label */
958 "F4", /* short-cut */
959 N_("Continue the execution of the program"), /* Tooltip */
960 G_CALLBACK (on_run_continue_action_activate) /* action callback */
963 "ActionDebuggerStepIn",
964 "debugger-step-into",
965 N_("Step _In"),
966 "F5",
967 N_("Single step into function"),
968 G_CALLBACK (on_step_in_action_activate)
971 "ActionDebuggerStepOver",
972 "debugger-step-over",
973 N_("Step O_ver"),
974 "F6",
975 N_("Single step over function"),
976 G_CALLBACK (on_step_over_action_activate)
979 "ActionDebuggerStepOut",
980 "debugger-step-out",
981 N_("Step _Out"),
982 "<shift>F5",
983 N_("Single step out of function"),
984 G_CALLBACK (on_step_out_action_activate)
987 "ActionDebuggerRunToPosition",
988 "debugger-run-to-cursor",
989 N_("_Run to Cursor"),
990 "F8",
991 N_("Run to the cursor"),
992 G_CALLBACK (on_run_to_cursor_action_activate)
995 "ActionDebuggerRunFromPosition",
996 "debugger-run-from-cursor",
997 N_("_Run from Cursor"),
998 NULL,
999 N_("Run from the cursor"),
1000 G_CALLBACK (on_run_from_cursor_action_activate)
1003 "ActionGdbCommand",
1004 NULL,
1005 N_("Debugger Command…"),
1006 NULL,
1007 N_("Custom debugger command"),
1008 G_CALLBACK (on_debugger_custom_command_activate)
1011 "ActionMenuGdbInformation",
1012 NULL,
1013 N_("_Info"),
1014 NULL,
1015 NULL,
1016 NULL
1019 "ActionGdbViewSharedlibs",
1020 NULL,
1021 N_("Shared Libraries"),
1022 NULL,
1023 N_("Show shared library mappings"),
1024 G_CALLBACK (on_debugger_sharedlibs_activate)
1027 "ActionGdbViewSignals",
1028 NULL,
1029 N_("Kernel Signals"),
1030 NULL,
1031 N_("Show kernel signals"),
1032 G_CALLBACK (on_debugger_signals_activate)
1036 static GtkActionEntry actions_running[] =
1039 "ActionGdbPauseProgram", /* Action name */
1040 GTK_STOCK_MEDIA_PAUSE, /* Stock icon, if any */
1041 N_("Pa_use Program"), /* Display label */
1042 NULL, /* short-cut */
1043 N_("Pauses the execution of the program"), /* Tooltip */
1044 G_CALLBACK (on_debugger_interrupt_activate) /* action callback */
1048 /* AnjutaPlugin functions
1049 *---------------------------------------------------------------------------*/
1051 static gboolean
1052 dma_plugin_activate (AnjutaPlugin* plugin)
1054 DebugManagerPlugin *this;
1055 static gboolean initialized = FALSE;
1056 AnjutaUI *ui;
1058 DEBUG_PRINT ("%s", "DebugManagerPlugin: Activating Debug Manager plugin…");
1059 this = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
1061 if (!initialized)
1063 initialized = TRUE;
1064 register_stock_icons (ANJUTA_PLUGIN (plugin));
1067 /* Load debugger */
1068 this->queue = dma_debugger_queue_new (plugin);
1069 g_signal_connect (this, "debugger-started", G_CALLBACK (dma_plugin_debugger_started), this);
1070 g_signal_connect (this, "debugger-stopped", G_CALLBACK (dma_plugin_debugger_stopped), this);
1071 g_signal_connect (this, "program-loaded", G_CALLBACK (dma_plugin_program_loaded), this);
1072 g_signal_connect (this, "program-running", G_CALLBACK (dma_plugin_program_running), this);
1073 g_signal_connect (this, "program-stopped", G_CALLBACK (dma_plugin_program_stopped), this);
1074 g_signal_connect (this, "program-exited", G_CALLBACK (dma_plugin_program_loaded), this);
1075 g_signal_connect (this, "program-moved", G_CALLBACK (dma_plugin_program_moved), this);
1076 g_signal_connect (this, "signal-received", G_CALLBACK (dma_plugin_signal_received), this);
1077 g_signal_connect (this, "location-changed", G_CALLBACK (dma_plugin_location_changed), this);
1079 /* Add all our debug manager actions */
1080 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL);
1081 this->start_group =
1082 anjuta_ui_add_action_group_entries (ui, "ActionGroupDebugStart",
1083 _("Debugger operations"),
1084 actions_start,
1085 G_N_ELEMENTS (actions_start),
1086 GETTEXT_PACKAGE, TRUE, this);
1087 this->loaded_group =
1088 anjuta_ui_add_action_group_entries (ui, "ActionGroupDebugLoaded",
1089 _("Debugger operations"),
1090 actions_loaded,
1091 G_N_ELEMENTS (actions_loaded),
1092 GETTEXT_PACKAGE, TRUE, this);
1093 this->stopped_group =
1094 anjuta_ui_add_action_group_entries (ui, "ActionGroupDebugStopped",
1095 _("Debugger operations"),
1096 actions_stopped,
1097 G_N_ELEMENTS (actions_stopped),
1098 GETTEXT_PACKAGE, TRUE, this);
1099 this->running_group =
1100 anjuta_ui_add_action_group_entries (ui, "ActionGroupDebugRunning",
1101 _("Debugger operations"),
1102 actions_running,
1103 G_N_ELEMENTS (actions_running),
1104 GETTEXT_PACKAGE, TRUE, this);
1105 this->uiid = anjuta_ui_merge (ui, UI_FILE);
1107 /* Get run_stop_action */
1108 this->run_stop_action = anjuta_ui_get_action (ui, "ActionGroupDebugLoaded", "ActionDebuggerContinueSuspend");
1110 /* Variable */
1111 this->variable = dma_variable_dbase_new (this);
1113 /* Stack trace */
1114 this->stack = stack_trace_new (this);
1116 /* Create breakpoints list */
1117 this->breakpoints = breakpoints_dbase_new (this);
1119 /* Register list */
1120 this->registers = cpu_registers_new (this);
1122 /* Memory window */
1123 this->memory = dma_memory_new (this);
1125 /* Disassembly window */
1126 this->disassemble = dma_disassemble_new (this);
1128 /* Start debugger part */
1129 this->start = dma_start_new (this);
1131 /* Shared libraries part */
1132 this->sharedlibs = sharedlibs_new (this);
1134 /* Signal part */
1135 this->signals = signals_new (this);
1137 dma_plugin_debugger_stopped (this, 0);
1139 /* Add watches */
1140 this->project_watch_id =
1141 anjuta_plugin_add_watch (plugin, IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
1142 value_added_project_root_uri,
1143 value_removed_project_root_uri, NULL);
1144 this->editor_watch_id =
1145 anjuta_plugin_add_watch (plugin, IANJUTA_DOCUMENT_MANAGER_CURRENT_DOCUMENT,
1146 value_added_current_editor,
1147 value_removed_current_editor, NULL);
1149 /* Connect to save session */
1150 g_signal_connect (G_OBJECT (plugin->shell), "save_session",
1151 G_CALLBACK (on_session_save), plugin);
1153 return TRUE;
1156 static gboolean
1157 dma_plugin_deactivate (AnjutaPlugin* plugin)
1159 DebugManagerPlugin *this;
1160 AnjutaUI *ui;
1162 DEBUG_PRINT ("%s", "DebugManagerPlugin: Deactivating Debug Manager plugin…");
1164 this = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
1166 /* Stop debugger */
1167 dma_plugin_debugger_stopped (this, 0);
1169 g_signal_handlers_disconnect_by_func (plugin->shell, G_CALLBACK (on_session_save), plugin);
1170 g_signal_handlers_disconnect_matched (plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, plugin);
1172 anjuta_plugin_remove_watch (plugin, this->project_watch_id, FALSE);
1173 anjuta_plugin_remove_watch (plugin, this->editor_watch_id, FALSE);
1175 dma_debugger_queue_free (this->queue);
1176 this->queue = NULL;
1178 ui = anjuta_shell_get_ui (plugin->shell, NULL);
1179 anjuta_ui_unmerge (ui, this->uiid);
1181 dma_variable_dbase_free (this->variable);
1182 this->variable = NULL;
1184 breakpoints_dbase_destroy (this->breakpoints);
1185 this->breakpoints = NULL;
1187 stack_trace_free (this->stack);
1188 this->stack = NULL;
1190 cpu_registers_free (this->registers);
1191 this->registers = NULL;
1193 dma_memory_free (this->memory);
1194 this->memory = NULL;
1196 dma_disassemble_free (this->disassemble);
1197 this->disassemble = NULL;
1199 dma_start_free (this->start);
1200 this->start = NULL;
1202 sharedlibs_free (this->sharedlibs);
1203 this->sharedlibs = NULL;
1205 signals_free (this->signals);
1206 this->signals = NULL;
1208 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (this)->shell, NULL);
1209 anjuta_ui_remove_action_group (ui, this->start_group);
1210 anjuta_ui_remove_action_group (ui, this->loaded_group);
1211 anjuta_ui_remove_action_group (ui, this->stopped_group);
1212 anjuta_ui_remove_action_group (ui, this->running_group);
1214 if (this->view != NULL)
1216 g_object_remove_weak_pointer (G_OBJECT (this->view), (gpointer*)(gpointer)&this->view);
1217 this->view = NULL;
1220 return TRUE;
1223 /* Public functions
1224 *---------------------------------------------------------------------------*/
1226 DmaDebuggerQueue*
1227 dma_debug_manager_get_queue (DebugManagerPlugin *self)
1229 return self->queue;
1232 /* GObject functions
1233 *---------------------------------------------------------------------------*/
1235 /* Used in dispose and finalize */
1236 static gpointer parent_class;
1238 /* instance_init is the constructor. All functions should work after this
1239 * call. */
1241 static void
1242 dma_plugin_instance_init (GObject* obj)
1244 DebugManagerPlugin *plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (obj);
1246 plugin->uiid = 0;
1248 plugin->project_root_uri = NULL;
1249 plugin->queue = NULL;
1250 plugin->current_editor = NULL;
1251 plugin->pc_editor = NULL;
1252 plugin->editor_watch_id = 0;
1253 plugin->project_watch_id = 0;
1254 plugin->breakpoints = NULL;
1255 plugin->registers = NULL;
1256 plugin->signals = NULL;
1257 plugin->sharedlibs = NULL;
1258 plugin->view = NULL;
1260 plugin->user_command_dialog = NULL;
1262 /* plugin->uri = NULL; */
1265 /* dispose is the first destruction step. It is used to unref object created
1266 * with instance_init in order to break reference counting cycles. This
1267 * function could be called several times. All function should still work
1268 * after this call. It has to called its parents.*/
1270 static void
1271 dma_plugin_dispose (GObject* obj)
1273 DebugManagerPlugin *plugin = ANJUTA_PLUGIN_DEBUG_MANAGER (obj);
1275 if (plugin->user_command_dialog != NULL) gtk_widget_destroy (GTK_WIDGET (plugin->user_command_dialog));
1277 G_OBJECT_CLASS (parent_class)->dispose (obj);
1280 /* finalize is the last destruction step. It must free all memory allocated
1281 * with instance_init. It is called only one time just before releasing all
1282 * memory */
1284 static void
1285 dma_plugin_finalize (GObject* obj)
1287 DebugManagerPlugin *self = ANJUTA_PLUGIN_DEBUG_MANAGER (obj);
1289 if (self->pc_editor != NULL)
1291 g_object_remove_weak_pointer (G_OBJECT (self->pc_editor), (gpointer *)(gpointer)&self->pc_editor);
1293 if (self->current_editor != NULL)
1295 g_object_remove_weak_pointer (G_OBJECT (self->current_editor), (gpointer *)(gpointer)&self->current_editor);
1298 G_OBJECT_CLASS (parent_class)->finalize (obj);
1301 /* class_init intialize the class itself not the instance */
1303 static void
1304 dma_plugin_class_init (GObjectClass* klass)
1306 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
1308 parent_class = g_type_class_peek_parent (klass);
1310 plugin_class->activate = dma_plugin_activate;
1311 plugin_class->deactivate = dma_plugin_deactivate;
1312 klass->dispose = dma_plugin_dispose;
1313 klass->finalize = dma_plugin_finalize;
1316 /* Implementation of IAnjutaDebugManager interface
1317 *---------------------------------------------------------------------------*/
1319 static gboolean
1320 idebug_manager_start (IAnjutaDebugManager *plugin, const gchar *uri, GError **err)
1322 DebugManagerPlugin *self = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
1324 return dma_run_target (self->start, uri);
1327 static gboolean
1328 idebug_manager_start_remote (IAnjutaDebugManager *plugin, const gchar *server, const gchar *uri, GError **err)
1330 DebugManagerPlugin *self = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
1332 return dma_run_remote_target (self->start, server, uri);
1335 static gboolean
1336 idebug_manager_quit (IAnjutaDebugManager *plugin, GError **err)
1338 DebugManagerPlugin *self = ANJUTA_PLUGIN_DEBUG_MANAGER (plugin);
1340 return dma_quit_debugger (self->start);
1343 static void
1344 idebug_manager_iface_init (IAnjutaDebugManagerIface *iface)
1346 iface->start = idebug_manager_start;
1347 iface->start_remote = idebug_manager_start_remote;
1348 iface->quit = idebug_manager_quit;
1351 ANJUTA_PLUGIN_BEGIN (DebugManagerPlugin, dma_plugin);
1352 ANJUTA_PLUGIN_ADD_INTERFACE(idebug_manager, IANJUTA_TYPE_DEBUG_MANAGER);
1353 ANJUTA_PLUGIN_END;
1355 ANJUTA_SIMPLE_PLUGIN (DebugManagerPlugin, dma_plugin);