[nemiver/asm-support] Support disassembly and switching to/from asm view
- From: Dodji Seketeli <dodji src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nemiver/asm-support] Support disassembly and switching to/from asm view
- Date: Sun, 11 Apr 2010 12:24:57 +0000 (UTC)
commit c06944c538dcebe65395b1ae67bde565b4809deb
Author: Dodji Seketeli <dodji redhat com>
Date: Sun Apr 11 14:02:50 2010 +0200
Support disassembly and switching to/from asm view
* src/dbgengine/nmv-i-debugger.h (IDebugger::Breakpoint):
make members m_address, m_function, m_expression and m_condition
use std::string instead of UString. It's un-necessary for these
to be in utf8. Update their accessors.
(IDebugger::Frame): Likewise for members m_function_name, and
m_args and m_library. Make m_address use the new type Address
instead of UString.
(IDebugger::Frame::has_empty_address): New function.
(IDebugger::set_breakpoint): New overload to set a bp at an
address.
* src/dbgengine/nmv-gdb-engine.h: Adjust.
* src/dbgengine/nmv-gdb-engine.cc: Adjust. All addresses are
typed with the Address type now.
(GDBEngine::set_breakpoint): New definition.
* src/dbgengine/nmv-gdbmi-parser.cc (GDBMIParser::parse_frame,
GDBMIParser::parse_call_stack, ):
Adjust to use Address instead of UString.
* src/persp/dbgperspective/nmv-call-stack.cc
(CallStack::Priv::append_frames_to_tree_view): Likewise.
* src/persp/dbgperspective/nmv-dbg-perspective.cc
(DBGPerspective::on_debugger_asm_signal1,
DBGPerspective::on_debugger_asm_signal2,
DBGPerspective::on_debugger_asm_signal3,
DBGPerspective::on_debugger_asm_signal4,
DBGPerspective::get_or_append_source_editor_from_path,
DBGPerspective::open_file_real,
DBGPerspective::pump_asm_including_address,
DBGPerspective::is_breakpoint_set_at_address,
DBGPerspective::breakpoint_and_frame_have_same_file,
DBGPerspective::get_frame_breakpoints_address_range,
DBGPerspective::disassemble_and_do,
DBGPerspective::disassemble_around_address_and_do,
DBGPerspective::apply_decorations,
DBGPerspective::apply_decorations_to_asm,
DBGPerspective::add_asm, write_asm_instr): New fns.
(DBGPerspective::bring_source_as_current,
DBGPerspective::load_disassembly,
DBGPerspective::get_breakpoint_number,
DBGPerspective::delete_breakpoint,
DBGPerspective::toggle_breakpoint,
DBGPerspective::append_visual_breakpoint,
DBGPerspective::set_where): New overloads. Often refactor
related overloads to re-use each others.
(DBGPerspective::get_asm_title): Renamed
DBGPerspective::get_disassembly_title.
(DBGPerspective::load_asm): Renamed
DBGPerspective::load_disassembly. Refactor to use
DBGPerspective::add_asm.
(DBGPerspective::open_asm): Renamed DBGPerspective::open_disassembly.
If the source editor was populated and the where pointer is set,
then bring the source editor to front.
(DBGPerspective::switch_to_asm): Renamed
DBGPerspective::switch_disassembly. Clear the decoration of the
previous source editor, before switching to the new one.
Do not set the current line and apply the decoration.
(DBGPerspective::switch_to_source_code):
(DBGPerspective::set_breakpoint): Use Address instead of
UString.
(DBGPerspective::apply_decorations_to_source): Renamed
DBGPerspective::apply_decoration_to_text. Make this to act only
on source code editor.
(DBGPerspective::on_switch_to_asm_action): Renamed
DBGPerspective::on_switch_to_disassembly_action.
(DBGPerspective::on_sv_markers_region_clicked_signal): Renamed
DBGPerspective::on_source_view_markers_region_clicked_signal.
Add a SourceEditor* parm to know which editor the source view
marker was clicked on. When the user clicks on the bp's margin,
set the breakpoint, wether we are in asm view or text view. In
assembly view, properly set the bp to the @ of the ligne
clicked. In source view, properly set the bp to the line # where
the user clicked.
(DBGPerspective::on_breakpoint_go_to_source_action): Re-factorize and
simply logic. Use the new
DBGPerspective::get_or_append_source_editor_from_path. Handle
source and asm buffers. If user wanted the source buffer and no
source could be found, fall back to disassembling instead.
(DBGPerspective::on_debugger_stopped_signal): Support updating
the "where pointer" in asm and source mode. If we couldn't set
the where pointer in source mode (probably b/c we couldn't find
the source file), then disassemble around the current IP value
and set the where pointer to the current IP value.
(DBGPerspective::on_frame_selected_signal): Support setting the
where pointer either on source or asm view.
(DBGPerspective::find_absolute_path): Also look for a file of
the same basename in the search directories before giving up.
(DBGPerspective::append_source_editor): When trying to add a
source editor with an empty file name to the notebook, use the
patch of the source editor as file name.
(DBGPerspective::get_current_source_editor): When the source
notebook is empty, try to open the source file corresponding to the
current frame.
(DBGPerspective::switch_to_source_code): Clear the decoration
of the old view before switching to the new one. When applying
decorations, scroll to the where marker.
(DBGPerspective::disassemble): Refactor and use the new
DBGPerspective::disassemble_and_do function
* src/persp/dbgperspective/nmv-dbg-perspective.h
(IDBGPerspective::load_asm): New fun.
* src/uicommon/nmv-source-editor.h (SourceEditor::BufferType):
New type.
Also declare the new member functions defined above.
* src/uicommon/nmv-source-editor.cc (struct Line2AddrFunc):
Remove.
(SourceEditor::Priv::get_buffer_type,
SourceEditor::Priv::get_markers,
SourceEditor::Priv::address_2_line,
SourceEditor::Priv::line_2_address,
SourceEditor::get_buffer_type,
SourceEditor::set_visual_breakpoint_at_address,
SourceEditor::scroll_to_address,
SourceEditor::get_assembly_address_range,
SourceEditor::move_where_marker_to_address,
SourceEditor::place_cursor_at_line,
SourceEditor::place_cursor_at_address): New fns.
(SourceEditor::Priv::NonAssemblyBufContext): Make this hold
source markers.
(SourceEditor::Priv::AssemblyBufContext): Likewise. Move
current_line and current_column here too. Add a current_address
too.
(SourceEditor::Priv::switch_to_assembly_source_buffer): If
called when we are already switched to asm buffer, don't barf.
(SourceEditor::Priv::switch_to_non_assembly_source_buffer):
Don't barf if called when we are already switched to source
buffer.
(SourceEditor::Priv::on_signal_insertion_moved): Protect with
try/catch.
(SourceEditor::Priv::update_line_col_info_from_iter,
SourceEditor::current_line): Handle both asm and source buffers.
(SourceEditor::move_where_marker_to_line,
SourceEditor::unset_where_marker,
SourceEditor::remove_visual_breakpoint_from_line
SourceEditor::clear_decorations,
SourceEditor::SourceEditor::is_visual_breakpoint_set_at_line): Remove
support for gsvmm 1.xx.
(SourceEditor::set_visual_breakpoint_at_line): Support gtk+ line
numbering scheme i.e, line nums starting at 0, instead of 1 like
GDB.
(SourceEditor::set_path, SourceEditor::get_path,
SourceEditor::get_file_name): Support this for asm
and source bufs.
(SourceEditor::assembly_buf_addr_to_line): Renamed
SourceEditor::assembly_buf_loc_to_line. Use
SourceEditor::Priv::assembly_buf_addr_to_line.
(SourceEditor::assembly_buf_line_to_addr): Renamed
SourceEditor::assembly_buf_line_to_loc. Use
SourceEditor::Priv::line_2_address.
* tests/test-disassemble.cc (on_stopped_signal): Adjust to
IDebugger::Frame::function yielding an std::string rather than
an UString.
(test_main): Call _exit to avoid a crash at exit.
* tests/test-gdbmi.cc b/tests/test-gdbmi.cc (tes_stack0): Use
the new IDebugger::Frame::has_empty_address function.
src/dbgengine/nmv-gdb-engine.cc | 31 +-
src/dbgengine/nmv-gdb-engine.h | 11 +-
src/dbgengine/nmv-gdbmi-parser.cc | 10 +-
src/dbgengine/nmv-i-debugger.h | 59 +-
src/persp/dbgperspective/nmv-call-stack.cc | 2 +-
src/persp/dbgperspective/nmv-dbg-perspective.cc | 1150 +++++++++++++++++------
src/persp/dbgperspective/nmv-dbg-perspective.h | 19 +-
src/uicommon/nmv-source-editor.cc | 610 ++++++++-----
src/uicommon/nmv-source-editor.h | 47 +-
tests/test-disassemble.cc | 9 +-
tests/test-gdbmi.cc | 2 +-
11 files changed, 1343 insertions(+), 607 deletions(-)
---
diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 20d9d7c..2d8fe0b 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -120,7 +120,7 @@ public:
IDebugger::State state;
int cur_frame_level;
int cur_thread_num;
- UString cur_frame_address;
+ Address cur_frame_address;
ILangTraitSafePtr lang_trait;
UString debugger_full_path;
GDBMIParser gdbmi_parser;
@@ -2779,7 +2779,7 @@ GDBEngine::set_current_frame_level (int a_level)
m_priv->cur_frame_level = a_level;
}
-const UString&
+const Address&
GDBEngine::get_current_frame_address () const
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -2789,7 +2789,7 @@ GDBEngine::get_current_frame_address () const
}
void
-GDBEngine::set_current_frame_address (const UString &a_address)
+GDBEngine::set_current_frame_address (const Address &a_address)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -3579,6 +3579,31 @@ GDBEngine::set_breakpoint (const UString &a_path,
queue_command (Command ("set-breakpoint", break_cmd, a_cookie));
}
+
+void
+GDBEngine::set_breakpoint (const Address &a_address,
+ const UString &a_condition,
+ unsigned a_ignore_count,
+ const UString &a_cookie)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ THROW_IF_FAIL (!a_address.empty ());
+
+ UString break_cmd ("-break-insert -f ");
+ if (!a_condition.empty ()) {
+ LOG_DD ("setting breakpoint with condition: " << a_condition);
+ break_cmd += " -c \"" + a_condition + "\"";
+ } else {
+ LOG_DD ("setting breakpoint without condition");
+ }
+
+ break_cmd += " -i " + UString::from_int (a_ignore_count);
+ break_cmd += " *" + (const string&) a_address;
+
+ queue_command (Command ("set-breakpoint", break_cmd, a_cookie));
+}
+
void
GDBEngine::enable_breakpoint (gint a_break_num,
const UString &a_cookie)
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index ca97f0b..cbeed92 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -300,9 +300,9 @@ public:
void set_current_frame_level (int);
- const UString& get_current_frame_address () const;
+ const Address & get_current_frame_address () const;
- void set_current_frame_address (const UString &a_address);
+ void set_current_frame_address (const Address &a_address);
void get_mi_thread_location (UString &a_str) const;
@@ -329,7 +329,12 @@ public:
void set_breakpoint (const UString &a_func_name,
const UString &a_condition,
unsigned a_ignore_count,
- const UString &a_cookie) ;
+ const UString &a_cookie);
+
+ void set_breakpoint (const Address &a_address,
+ const UString &a_condition,
+ unsigned a_ignore_count,
+ const UString &a_cookie);
void enable_breakpoint (gint a_break_num,
const UString &a_cookie="");
diff --git a/src/dbgengine/nmv-gdbmi-parser.cc b/src/dbgengine/nmv-gdbmi-parser.cc
index 8caa9b1..552b2f0 100644
--- a/src/dbgengine/nmv-gdbmi-parser.cc
+++ b/src/dbgengine/nmv-gdbmi-parser.cc
@@ -1537,9 +1537,9 @@ GDBMIParser::parse_frame (UString::size_type a_from,
if (name == "level") {
frame.level (atoi (value.c_str ()));
} else if (name == "addr") {
- frame.address (value);
+ frame.address (value.raw ());
} else if (name == "func") {
- frame.function_name (value);
+ frame.function_name (value.raw ());
} else if (name == "file") {
frame.file_name (value);
} else if (name == "fullname") {
@@ -2596,9 +2596,9 @@ GDBMIParser::parse_call_stack (const UString::size_type a_from,
THROW_IF_FAIL ((*frame_part_iter)->value ());
value = (*frame_part_iter)->value ()->get_string_content ();
if ((*frame_part_iter)->variable () == "addr") {
- frame.address (value);
+ frame.address (value.raw ());
} else if ((*frame_part_iter)->variable () == "func") {
- frame.function_name (value);
+ frame.function_name (value.raw ());
} else if ((*frame_part_iter)->variable () == "file") {
frame.file_name (value);
} else if ((*frame_part_iter)->variable () == "fullname") {
@@ -2609,7 +2609,7 @@ GDBMIParser::parse_call_stack (const UString::size_type a_from,
frame.level (atol (value.c_str ()));
}
}
- THROW_IF_FAIL (frame.address () != "");
+ THROW_IF_FAIL (frame.has_empty_address () != true);
stack.push_back (frame);
frame.clear ();
}
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index b526f78..49af67f 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -35,6 +35,7 @@
#include "common/nmv-ustring.h"
#include "common/nmv-dynamic-module.h"
#include "common/nmv-safe-ptr-utils.h"
+#include "common/nmv-address.h"
#include "nmv-i-conf-mgr.h"
NEMIVER_BEGIN_NAMESPACE (nemiver)
@@ -47,6 +48,7 @@ using nemiver::common::ObjectRef;
using nemiver::common::ObjectUnref;
using nemiver::common::UString;
using nemiver::common::Object;
+using nemiver::common::Address;
using std::vector;
using std::string;
using std::map;
@@ -89,12 +91,12 @@ public:
private:
int m_number;
bool m_enabled;
- UString m_address;
- UString m_function;
- UString m_expression;
+ string m_address;
+ string m_function;
+ string m_expression;
UString m_file_name;
UString m_file_full_name;
- UString m_condition;
+ string m_condition;
Type m_type;
int m_line;
int m_nb_times_hit;
@@ -114,14 +116,14 @@ public:
bool enabled () const {return m_enabled;}
void enabled (bool a_in) {m_enabled = a_in;}
- const UString& address () const {return m_address;}
- void address (const UString &a_in) {m_address = a_in;}
+ const string& address () const {return m_address;}
+ void address (const string &a_in) {m_address = a_in;}
- const UString& function () const {return m_function;}
- void function (const UString &a_in) {m_function = a_in;}
+ const string& function () const {return m_function;}
+ void function (const string &a_in) {m_function = a_in;}
- const UString& expression () const {return m_expression;}
- void expression (const UString &a_expr) {m_expression = a_expr;}
+ const string& expression () const {return m_expression;}
+ void expression (const string &a_expr) {m_expression = a_expr;}
const UString& file_name () const {return m_file_name;}
void file_name (const UString &a_in) {m_file_name = a_in;}
@@ -132,8 +134,8 @@ public:
int line () const {return m_line;}
void line (int a_in) {m_line = a_in;}
- const UString& condition () const {return m_condition;}
- void condition (const UString &a_cond) {m_condition = a_cond;}
+ const string& condition () const {return m_condition;}
+ void condition (const string &a_cond) {m_condition = a_cond;}
bool has_condition () const {return !m_condition.empty ();}
@@ -249,9 +251,9 @@ public:
/// \brief a function frame as seen by the debugger.
class Frame {
- UString m_address;
- UString m_function_name;
- map<UString, UString> m_args;
+ Address m_address;
+ string m_function_name;
+ map<string, string> m_args;
int m_level;
//present if the target has debugging info
UString m_file_name;
@@ -259,7 +261,7 @@ public:
UString m_file_full_name;
int m_line;
//present if the target doesn't have debugging info
- UString m_library;
+ string m_library;
public:
Frame () :
@@ -270,14 +272,18 @@ public:
/// \name accessors
/// @{
- const UString& address () const {return m_address;}
- void address (const UString &a_in) {m_address = a_in;}
+ const Address& address () const {return m_address;}
+ void address (const Address &a_in) {m_address = a_in;}
+ bool has_empty_address () const
+ {
+ return static_cast<std::string> (m_address).empty ();
+ }
- const UString& function_name () const {return m_function_name;}
- void function_name (const UString &a_in) {m_function_name = a_in;}
+ const string& function_name () const {return m_function_name;}
+ void function_name (const string &a_in) {m_function_name = a_in;}
- const map<UString, UString>& args () const {return m_args;}
- map<UString, UString>& args () {return m_args;}
+ const map<string, string>& args () const {return m_args;}
+ map<string, string>& args () {return m_args;}
int level () const {return m_level;}
void level (int a_level) {m_level = a_level;}
@@ -291,8 +297,8 @@ public:
int line () const {return m_line;}
void line (int a_in) {m_line = a_in;}
- const UString& library () const {return m_library;}
- void library (const UString &a_library) {m_library = a_library;}
+ const string& library () const {return m_library;}
+ void library (const string &a_library) {m_library = a_library;}
/// @}
@@ -1141,6 +1147,11 @@ public:
unsigned a_ignore_count = 0,
const UString &a_cookie = "") = 0;
+ virtual void set_breakpoint (const Address &a_address,
+ const UString &a_condition = "",
+ unsigned a_ignore_count = 0,
+ const UString &a_cookie = "") = 0;
+
virtual void enable_breakpoint (gint a_break_num,
const UString &a_cookie="") = 0;
diff --git a/src/persp/dbgperspective/nmv-call-stack.cc b/src/persp/dbgperspective/nmv-call-stack.cc
index ec56ef5..44d1eaf 100644
--- a/src/persp/dbgperspective/nmv-call-stack.cc
+++ b/src/persp/dbgperspective/nmv-call-stack.cc
@@ -665,7 +665,7 @@ struct CallStack::Priv {
+ UString::from_int (a_frames[i].line ());
} else {
(*store_iter)[columns ().location] =
- a_frames[i].address ();
+ static_cast<std::string> (a_frames[i].address ());
}
(*store_iter)[columns ().frame_index] = a_frames[i].level ();
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index e73a56e..bba43bd 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -64,6 +64,7 @@
#include "common/nmv-env.h"
#include "common/nmv-date-utils.h"
#include "common/nmv-str-utils.h"
+#include "common/nmv-address.h"
#include "nmv-sess-mgr.h"
#include "nmv-dbg-perspective.h"
#include "nmv-source-editor.h"
@@ -282,7 +283,7 @@ private:
void on_set_watchpoint_using_dialog_action ();
void on_refresh_locals_action ();
void on_disassemble_action (bool a_show_asm_in_new_tab);
- void on_switch_to_disassembly_action ();
+ void on_switch_to_asm_action ();
void on_toggle_breakpoint_action ();
void on_toggle_breakpoint_enabled_action ();
void on_inspect_variable_action ();
@@ -311,8 +312,9 @@ private:
const Glib::ustring &a_text,
int a_dont_know);
- void on_source_view_markers_region_clicked_signal
- (int a_line, bool a_dialog_requested);
+ void on_sv_markers_region_clicked_signal
+ (int a_line, bool a_dialog_requested,
+ SourceEditor *a_editor);
bool on_button_pressed_in_source_view_signal (GdkEventButton *a_event);
@@ -391,11 +393,28 @@ private:
(const UString &a_var_name,
const IDebugger::VariableSafePtr &a_var,
const UString &a_cooker);
- void on_debugger_disassembled_signal
+
+ void on_debugger_asm_signal1
(const IDebugger::DisassembleInfo &a_info,
const std::list<IDebugger::AsmInstr> &a_instrs,
bool a_show_asm_in_new_tab = true);
+ void on_debugger_asm_signal2
+ (const IDebugger::DisassembleInfo &info,
+ const std::list<IDebugger::AsmInstr> &instrs,
+ SourceEditor *editor);
+
+ void on_debugger_asm_signal3
+ (const IDebugger::DisassembleInfo &info,
+ const std::list<IDebugger::AsmInstr> &instrs,
+ SourceEditor *editor,
+ const IDebugger::Breakpoint &a_bp);
+
+ void on_debugger_asm_signal4
+ (const IDebugger::DisassembleInfo &info,
+ const std::list<IDebugger::AsmInstr> &instrs,
+ const Address &address);
+
void on_variable_created_for_tooltip_signal
(const IDebugger::VariableSafePtr);
void on_popup_var_insp_size_request (Gtk::Requisition*, Gtk::Widget *);
@@ -441,17 +460,20 @@ private:
SourceEditor* get_current_source_editor ();
ISessMgr* session_manager_ptr ();
UString get_current_file_path ();
- SourceEditor* get_source_editor_from_path (const UString &a_path,
- bool a_basename_only=false);
+ SourceEditor* get_source_editor_from_path (const UString& a_path,
+ bool a_basename_only = false);
SourceEditor* get_source_editor_from_path (const UString &a_path,
UString &a_actual_file_path,
bool a_basename_only=false);
+ SourceEditor* get_or_append_source_editor_from_path (const UString &a_path);
+
bool source_view_to_root_window_coordinates (int x, int y,
int &root_x,
int &root_y);
IWorkbench& workbench () const;
- void bring_source_as_current (const UString &a_path);
+ SourceEditor* bring_source_as_current (const UString &a_path);
+ void bring_source_as_current (SourceEditor *a_editor);
int get_n_pages ();
void popup_source_view_contextual_menu (GdkEventButton *a_event);
void record_and_save_new_session ();
@@ -489,7 +511,7 @@ public:
void edit_workbench_menu ();
SourceEditor* create_source_editor (Glib::RefPtr<SourceBuffer> &a_source_buf,
- bool a_disassembly_view,
+ bool a_asm_view,
const UString &a_path,
int a_current_line,
const UString &a_current_address);
@@ -506,12 +528,13 @@ public:
bool load_file (const UString &a_file,
Glib::RefPtr<SourceBuffer> &a_source_buffer);
- bool open_file (const UString &a_path,
- int current_line=-1);
+ bool open_file (const UString &a_path, int current_line=-1);
- bool open_file (const UString &a_path,
- int current_line,
- bool a_reload_visual_breakpoint);
+ SourceEditor* open_file_real (const UString &a_path, int current_line=-1);
+
+ SourceEditor* open_file_real (const UString &a_path,
+ int current_line,
+ bool a_reload_visual_breakpoint);
void close_current_file ();
@@ -522,17 +545,30 @@ public:
Gtk::Widget* load_menu (const UString &a_filename,
const UString &a_widget_name);
- const UString& get_disassembly_title ();
+ const UString& get_asm_title ();
+
+ bool load_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf);
+
+ bool add_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf,
+ bool a_append = true);
- bool load_disassembly (const IDebugger::DisassembleInfo &a_info,
- const std::list<IDebugger::AsmInstr> &a_asm,
- Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf);
+ SourceEditor* open_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ bool set_where = false);
- bool open_disassembly (const IDebugger::DisassembleInfo &a_info,
- const std::list<IDebugger::AsmInstr> &a_asm);
+ void switch_to_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm);
- void switch_to_disassembly (const IDebugger::DisassembleInfo &a_info,
- const std::list<IDebugger::AsmInstr> &a_asm);
+ void switch_to_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ SourceEditor *a_editor);
+
+ void pump_asm_including_address (SourceEditor *a_editor,
+ const Address a_address);
void switch_to_source_code ();
@@ -594,6 +630,7 @@ public:
const UString &a_cond);
void set_breakpoint (const UString &a_func_name,
const UString &a_cond);
+ void set_breakpoint (const Address &a_address);
void append_breakpoint (int a_bp_num,
const IDebugger::Breakpoint &a_breakpoint);
void append_breakpoints
@@ -603,23 +640,36 @@ public:
int a_linenum,
int &a_break_num,
bool &a_enabled);
+ bool get_breakpoint_number (const Address &a_address,
+ int &a_break_num);
bool delete_breakpoint ();
bool delete_breakpoint (int a_breakpoint_num);
bool delete_breakpoint (const UString &a_file_path,
int a_linenum);
+ bool delete_breakpoint (const Address &a_address);
bool is_breakpoint_set_at_line (const UString &a_file_path,
int a_linenum,
bool &a_enabled);
+ bool is_breakpoint_set_at_address (const Address &);
void toggle_breakpoint (const UString &a_file_path,
int a_linenum);
+ void toggle_breakpoint (const Address &a_address);
void set_breakpoint_using_dialog ();
void set_breakpoint_using_dialog (const UString &a_file_path,
const int a_line_num);
void set_breakpoint_using_dialog (const UString &a_function_name);
void set_breakpoint_from_dialog (SetBreakpointDialog &a_dialog);
void set_watchpoint_using_dialog ();
+ bool breakpoint_and_frame_have_same_file (const IDebugger::Breakpoint&,
+ const IDebugger::Frame&) const;
+
+ bool get_frame_breakpoints_address_range (const IDebugger::Frame&,
+ Range &) const;
void refresh_locals ();
void disassemble (bool a_show_asm_in_new_tab);
+ void disassemble_and_do (IDebugger::DisassSlot &a_what_to_do);
+ void disassemble_around_address_and_do (const Address &adress,
+ IDebugger::DisassSlot &what_to_do);
void inspect_variable ();
void inspect_variable (const UString &a_variable_name);
@@ -635,20 +685,25 @@ public:
UString& a_absolute_path);
bool ask_user_to_select_file (const UString &a_file_name,
UString& a_selected_file_path);
- bool append_visual_breakpoint (const UString &a_file_name,
- int a_linenum,
- UString &a_actual_file_name,
- bool enabled=true);
- bool append_visual_breakpoint (const UString &a_file_name,
- int a_linenum,
- bool enabled=true);
+ bool append_visual_breakpoint (SourceEditor *editor,
+ int linenum,
+ bool enabled = true);
+ bool append_visual_breakpoint (SourceEditor *editor,
+ const Address &address,
+ bool enabled = true);
void delete_visual_breakpoint (const UString &a_file_name, int a_linenum);
void delete_visual_breakpoint (int a_breaknum);
void choose_function_overload
(const vector<IDebugger::OverloadsChoiceEntry> &a_entries);
void remove_visual_decorations_from_text (const UString &a_file_path);
- bool apply_decorations_to_text (const UString &a_file_path);
+ bool apply_decorations (const UString &file_path);
+ bool apply_decorations (SourceEditor *editor,
+ bool scroll_to_where_marker = false);
+ bool apply_decorations_to_source (SourceEditor *a_editor,
+ bool scroll_to_where_marker = false);
+ bool apply_decorations_to_asm (SourceEditor *a_editor,
+ bool scroll_to_where_marker = false);
IDebuggerSafePtr& debugger ();
@@ -719,13 +774,25 @@ public:
#endif // WITH_MEMORYVIEW
void add_text_to_command_view (const UString &a_text,
- bool a_no_repeat=false);
+ bool a_no_repeat = false);
void add_text_to_target_output_view (const UString &a_text);
void add_text_to_log_view (const UString &a_text);
- void set_where (const UString &a_path, int line, bool a_do_scroll=true);
+ bool set_where (const UString &a_path,
+ const IDebugger::Frame &a_frame,
+ bool a_do_scroll = true,
+ bool a_try_hard = false);
+ bool set_where (const UString &a_path, int a_line,
+ bool a_do_scroll = true);
+ bool set_where (SourceEditor *a_editor,
+ int a_line,
+ bool a_do_scroll);
+ bool set_where (SourceEditor *a_editor,
+ const Address &a_address,
+ bool a_do_scroll = true,
+ bool a_try_hard = false);
void unset_where ();
@@ -1523,7 +1590,7 @@ DBGPerspective::on_disassemble_action (bool a_show_asm_in_new_tab)
}
void
-DBGPerspective::on_switch_to_disassembly_action ()
+DBGPerspective::on_switch_to_asm_action ()
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
NEMIVER_TRY
@@ -1622,28 +1689,39 @@ DBGPerspective::on_breakpoint_go_to_source_action
(const IDebugger::Breakpoint& a_breakpoint)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
- // FIXME: this should put the same effort into
- // finding the source file that
- // append_visual_breakpoint() does.
- // Maybe this should be abstracted out somehow
+
NEMIVER_TRY
+
UString file_path = a_breakpoint.file_full_name ();
- if (file_path == "") {
+ if (file_path.empty ())
file_path = a_breakpoint.file_name ();
- if (!find_file_in_source_dirs (file_path, file_path)) {
- UString message;
- message.printf (_("File path info is missing "
- "for breakpoint '%i'"), a_breakpoint.number ());
- display_warning (message);
- return;
- }
- }
- bring_source_as_current (file_path);
- SourceEditor *source_editor = get_source_editor_from_path (file_path);
- THROW_IF_FAIL (source_editor);
- source_editor->scroll_to_line (a_breakpoint.line ());
+ SourceEditor *source_editor =
+ get_or_append_source_editor_from_path (file_path);
+ bring_source_as_current (source_editor);
+ if (source_editor) {
+ SourceEditor::BufferType type = source_editor->get_buffer_type ();
+ switch (type) {
+ case SourceEditor::BUFFER_TYPE_SOURCE:
+ source_editor->scroll_to_line (a_breakpoint.line ());
+ break;
+ case SourceEditor::BUFFER_TYPE_ASSEMBLY:
+ source_editor->scroll_to_address (a_breakpoint.address ());
+ break;
+ case SourceEditor::BUFFER_TYPE_UNDEFINED:
+ break;
+ }
+ } else {
+ IDebugger::DisassSlot scroll_to_address;
+ scroll_to_address =
+ sigc::bind (sigc::mem_fun
+ (this,
+ &DBGPerspective::on_debugger_asm_signal4),
+ a_breakpoint.address ());
+ disassemble_around_address_and_do (a_breakpoint.address (),
+ scroll_to_address);
+ }
NEMIVER_CATCH
}
@@ -1812,22 +1890,39 @@ DBGPerspective::on_insert_in_command_view_signal
}
void
-DBGPerspective::on_source_view_markers_region_clicked_signal
- (int a_line,
- bool a_dialog_requested)
+DBGPerspective::on_sv_markers_region_clicked_signal (int a_line,
+ bool a_dialog_requested,
+ SourceEditor *a_editor)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
+
NEMIVER_TRY
- if (m_priv->debugger->get_state () != IDebugger::NOT_STARTED) {
- SourceEditor *cur_editor = get_current_source_editor ();
- THROW_IF_FAIL (cur_editor);
- UString path;
- cur_editor->get_path (path);
- if (a_dialog_requested) {
- set_breakpoint_using_dialog (path, a_line + 1);
- } else {
- toggle_breakpoint (path, a_line + 1 );
+ if (m_priv->debugger->get_state () == IDebugger::NOT_STARTED
+ || a_editor == 0)
+ return;
+
+ UString path;
+ a_editor->get_path (path);
+
+ if (a_dialog_requested) {
+ // FIXME: Handle assembly view mode.
+ set_breakpoint_using_dialog (path, a_line);
+ } else {
+ SourceEditor::BufferType type = a_editor->get_buffer_type ();
+ switch (type) {
+ case SourceEditor::BUFFER_TYPE_SOURCE:
+ toggle_breakpoint (path, a_line);
+ break;
+ case SourceEditor::BUFFER_TYPE_ASSEMBLY: {
+ Address address;
+ if (!a_editor->assembly_buf_line_to_addr (a_line, address))
+ return;
+ toggle_breakpoint (address);
+ }
+ break;
+ case SourceEditor::BUFFER_TYPE_UNDEFINED:
+ break;
}
}
@@ -2291,7 +2386,6 @@ DBGPerspective::on_debugger_breakpoints_set_signal
NEMIVER_CATCH
}
-
void
DBGPerspective::on_debugger_stopped_signal (IDebugger::StopReason a_reason,
bool a_has_frame,
@@ -2307,29 +2401,29 @@ DBGPerspective::on_debugger_stopped_signal (IDebugger::StopReason a_reason,
THROW_IF_FAIL (m_priv);
+ m_priv->current_frame = a_frame;
+
+ bool where_set = false;
UString file_path (a_frame.file_full_name ());
- if (a_has_frame
- && a_frame.file_full_name () == ""
- && a_frame.file_name () != "") {
+ if (a_has_frame && file_path.empty ()
+ && !a_frame.file_name ().empty ()) {
file_path = a_frame.file_name ();
if (!find_file_in_source_dirs (file_path, file_path)) {
UString message;
message.printf(_("Could not find file %s"), file_path.c_str ());
display_error (message);
- return;
}
}
- if (a_has_frame && file_path != "") {
- m_priv->current_frame = a_frame;
+ if (a_has_frame && !file_path.empty ()) {
m_priv->current_frame.file_name (file_path);
- set_where (file_path, a_frame.line ());
- } else if (a_has_frame &&
- a_frame.file_full_name () == ""
- && a_frame.file_name () == "") {
- UString message;
- message.printf(_("File path info is missing for function '%s'"),
- a_frame.function_name ().c_str ());
- LOG_ERROR (message);
+ where_set = set_where (file_path, a_frame,
+ /*do_scroll=*/true,
+ /*try_hard=*/true);
+ }
+
+ if (!where_set) {
+ SourceEditor *e = bring_source_as_current (file_path);
+ disassemble (e ? false : true);
}
if (m_priv->debugger_has_just_run) {
@@ -2422,7 +2516,7 @@ DBGPerspective::on_frame_selected_signal (int /* a_index */,
get_local_vars_inspector ().show_local_variables_of_current_function
(a_frame);
- set_where (file_path, a_frame.line ());
+ set_where (file_path, a_frame);
NEMIVER_CATCH
}
@@ -2559,17 +2653,72 @@ DBGPerspective::on_debugger_variable_value_signal
}
void
-DBGPerspective::on_debugger_disassembled_signal
+DBGPerspective::on_debugger_asm_signal1
(const IDebugger::DisassembleInfo &a_info,
const std::list<IDebugger::AsmInstr> &a_instrs,
bool a_show_asm_in_new_tab)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
- if (a_show_asm_in_new_tab)
- open_disassembly (a_info, a_instrs);
- else
- switch_to_disassembly (a_info, a_instrs);
+ NEMIVER_TRY
+
+ if (a_show_asm_in_new_tab) {
+ open_asm (a_info, a_instrs, /*set_where=*/true);
+ } else {
+ switch_to_asm (a_info, a_instrs);
+ }
+
+ NEMIVER_CATCH
+}
+
+void
+DBGPerspective::on_debugger_asm_signal2
+ (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_instrs,
+ SourceEditor *a_editor)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY
+
+ switch_to_asm (a_info, a_instrs, a_editor);
+
+ NEMIVER_CATCH
+}
+
+void
+DBGPerspective::on_debugger_asm_signal3
+ (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_instrs,
+ SourceEditor *a_editor,
+ const IDebugger::Breakpoint &a_bp)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY
+
+ switch_to_asm (a_info, a_instrs, a_editor);
+ append_visual_breakpoint (a_editor, a_bp.address (), a_bp.line ());
+
+ NEMIVER_CATCH
+}
+
+void
+DBGPerspective::on_debugger_asm_signal4
+ (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_instrs,
+ const Address &a_address)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY
+
+ SourceEditor* editor = open_asm (a_info, a_instrs, /*set_where=*/false);
+ THROW_IF_FAIL (editor);
+ bring_source_as_current (editor);
+ editor->scroll_to_address (a_address);
+
+ NEMIVER_CATCH
}
void
@@ -3830,6 +3979,13 @@ DBGPerspective::find_absolute_path (const UString& a_file_path,
if (find_file_in_source_dirs (a_file_path, a_absolute_path)) {
return true;
}
+ // Then look for a file of that basename in the search directories.
+ std::string basename =
+ Glib::path_get_basename (Glib::filename_from_utf8 (a_file_path));
+ if (basename != a_file_path
+ && find_file_in_source_dirs (basename, a_absolute_path)) {
+ return true;
+ }
return false;
}
@@ -3853,15 +4009,20 @@ void
DBGPerspective::append_source_editor (SourceEditor &a_sv,
const UString &a_path)
{
- if (a_path == "") {return;}
+ UString path = a_path;
+ if (path.empty ()) {
+ path = a_sv.get_path ();
+ if (path.empty ())
+ return;
+ }
- if (m_priv->path_2_pagenum_map.find (a_path)
+ if (m_priv->path_2_pagenum_map.find (path)
!= m_priv->path_2_pagenum_map.end ()) {
- THROW (UString ("File of '") + a_path + "' is already loaded");
+ THROW (UString ("File of '") + path + "' is already loaded");
}
UString basename = Glib::filename_to_utf8
- (Glib::path_get_basename (Glib::filename_from_utf8 (a_path)));
+ (Glib::path_get_basename (Glib::filename_from_utf8 (path)));
SafePtr<Gtk::Label> label (Gtk::manage
(new Gtk::Label (basename)));
@@ -3888,7 +4049,7 @@ DBGPerspective::append_source_editor (SourceEditor &a_sv,
close_button->signal_clicked ().connect
(sigc::mem_fun (*close_button, &SlotedButton::on_clicked));
UString message;
- message.printf (_("Close %s"), a_path.c_str ());
+ message.printf (_("Close %s"), path.c_str ());
close_button->set_tooltip_text (message);
SafePtr<Gtk::HBox> hbox (Gtk::manage (new Gtk::HBox ()));
@@ -3909,16 +4070,16 @@ DBGPerspective::append_source_editor (SourceEditor &a_sv,
m_priv->sourceviews_notebook->set_tab_reorderable (a_sv);
#endif
std::string base_name =
- Glib::path_get_basename (Glib::filename_from_utf8 (a_path));
+ Glib::path_get_basename (Glib::filename_from_utf8 (path));
THROW_IF_FAIL (base_name != "");
m_priv->basename_2_pagenum_map[Glib::filename_to_utf8 (base_name)] =
page_num;
m_priv->path_2_pagenum_map[a_path] = page_num;
m_priv->pagenum_2_source_editor_map[page_num] = &a_sv;
- m_priv->pagenum_2_path_map[page_num] = a_path;
+ m_priv->pagenum_2_path_map[page_num] = path;
- if (!do_monitor_file (a_path)) {
- LOG_ERROR ("Failed to start monitoring file: " << a_path);
+ if (!do_monitor_file (path)) {
+ LOG_ERROR ("Failed to start monitoring file: " << path);
}
hbox.release ();
@@ -3959,8 +4120,24 @@ DBGPerspective::get_current_source_editor ()
if (m_priv->sourceviews_notebook
&& !m_priv->sourceviews_notebook->get_n_pages ()) {
- LOG_ERROR ("Empty m_priv->sourceviews_notebook");
- return NULL;
+ // The source notebook is empty. If the current frame
+ // has file info, load the file, bring it to the front,
+ // apply decorations to it and return its editor.
+ if (m_priv->current_frame.has_empty_address ())
+ return NULL;
+ UString path = m_priv->current_frame.file_full_name ();
+ if (path.empty ())
+ path = m_priv->current_frame.file_name ();
+ if (path.empty ()) {
+ return 0;
+ }
+ if (!find_absolute_path_or_ask_user (path, path))
+ return 0;
+ SourceEditor *editor = open_file_real (path);
+ apply_decorations (editor,
+ /*scroll_to_where_marker=*/true);
+ bring_source_as_current (editor);
+ return editor;
}
LOG_DD ("current pagenum: "
@@ -4012,6 +4189,42 @@ DBGPerspective::get_source_editor_from_path (const UString &a_path,
a_basename_only);
}
+bool
+DBGPerspective::breakpoint_and_frame_have_same_file
+ (const IDebugger::Breakpoint &a_bp,
+ const IDebugger::Frame &a_frame) const
+{
+ if ((a_frame.file_full_name () == a_bp.file_full_name ()
+ && !a_frame.file_full_name ().empty ())
+ || (a_frame.file_name () == a_bp.file_name ()
+ && !a_frame.file_name ().empty ()))
+ return true;
+ return false;
+
+}
+
+bool
+DBGPerspective::get_frame_breakpoints_address_range
+ (const IDebugger::Frame &a_frame,
+ Range &a_range) const
+{
+
+ Range range = a_range;
+ bool result = false;
+ map<int, IDebugger::Breakpoint>::const_iterator it;
+ for (it = m_priv->breakpoints.begin ();
+ it != m_priv->breakpoints.end ();
+ ++it) {
+ if (breakpoint_and_frame_have_same_file (it->second, a_frame)) {
+ range.extend (str_utils::hexa_to_int (it->second.address ()));
+ result = true;
+ }
+ }
+ if (result)
+ a_range = range;
+ return result;
+}
+
/// Converts coordinates expressed in source view coordinates system into
/// coordinates expressed in the root window coordinate system.
/// \param a_x abscissa in source view coordinate system
@@ -4080,6 +4293,25 @@ DBGPerspective::get_source_editor_from_path (const UString &a_path,
return result;
}
+SourceEditor*
+DBGPerspective::get_or_append_source_editor_from_path (const UString &a_path)
+{
+ UString actual_file_path;
+
+ if (a_path.empty ())
+ return 0;
+
+ SourceEditor *source_editor =
+ get_source_editor_from_path (a_path, actual_file_path);
+ if (source_editor == 0) {
+ if (!find_absolute_path_or_ask_user (a_path, actual_file_path)) {
+ return 0;
+ }
+ source_editor = open_file_real (actual_file_path);
+ }
+ return source_editor;
+}
+
IWorkbench&
DBGPerspective::workbench () const
{
@@ -4089,48 +4321,151 @@ DBGPerspective::workbench () const
return *m_priv->workbench;
}
-void
+SourceEditor*
DBGPerspective::bring_source_as_current (const UString &a_path)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
LOG_DD ("file path: '" << a_path << "'");
+ if (a_path.empty ())
+ return 0;
+
SourceEditor *source_editor = get_source_editor_from_path (a_path);
if (!source_editor) {
- open_file (a_path, -1, true);
- }
- if (!source_editor) {
- source_editor = get_source_editor_from_path (a_path, true);
+ source_editor = open_file_real (a_path, -1, true);
+ THROW_IF_FAIL (source_editor);
}
- source_editor = get_source_editor_from_path (a_path);
- THROW_IF_FAIL (source_editor);
+ bring_source_as_current (source_editor);
+ return source_editor;
+}
+
+void
+DBGPerspective::bring_source_as_current (SourceEditor *a_editor)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ if (a_editor == 0)
+ return;
+
+ UString path = a_editor->get_path ();
map<UString, int>::iterator iter =
- m_priv->path_2_pagenum_map.find (a_path);
+ m_priv->path_2_pagenum_map.find (path);
THROW_IF_FAIL (iter != m_priv->path_2_pagenum_map.end ());
m_priv->sourceviews_notebook->set_current_page (iter->second);
}
-void
+// Set the graphical "where pointer" to either the source (or assembly)
+// location corresponding to a_frame.
+// \param a_path the path (uri) of the current source file.
+// \a_frame the frame to consider
+// \a_do_scroll if true, the source/asm editor is scrolled to the
+// location of the newly set where pointer.
+// \return true upon successful completion, false otherwise.
+bool
+DBGPerspective::set_where (const UString &a_path,
+ const IDebugger::Frame &a_frame,
+ bool a_do_scroll,
+ bool a_try_hard)
+{
+ SourceEditor *source_editor = bring_source_as_current (a_path);
+ if (!source_editor)
+ return false;
+
+ SourceEditor::BufferType type = source_editor->get_buffer_type ();
+ switch (type) {
+ case SourceEditor::BUFFER_TYPE_SOURCE:
+ return set_where (source_editor, a_frame.line (), a_do_scroll);
+ case SourceEditor::BUFFER_TYPE_ASSEMBLY:
+ return set_where (source_editor, a_frame.address (),
+ a_do_scroll, a_try_hard);
+ case SourceEditor::BUFFER_TYPE_UNDEFINED:
+ break;
+ }
+ return false;
+}
+
+// Set the graphical "where pointer" to the source line a_line.
+// \param a_path the path (uri) of the current source file.
+// \a_line the line number (starting from 1) to which the "where pointer"
+// is to be set.
+// \a_do_scroll if true, the source editor is scrolled to the
+// location of the newly set where pointer.
+// \return true upon successful completion, false otherwise.
+bool
DBGPerspective::set_where (const UString &a_path,
int a_line,
bool a_do_scroll)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
- bring_source_as_current (a_path);
- SourceEditor *source_editor = get_source_editor_from_path (a_path);
- if (!source_editor) {
- source_editor = get_source_editor_from_path (a_path, true);
- }
- THROW_IF_FAIL (source_editor);
- source_editor->move_where_marker_to_line (a_line, a_do_scroll);
+ SourceEditor *source_editor = bring_source_as_current (a_path);
+ return set_where (source_editor, a_line, a_do_scroll);
+}
+
+// Set the graphical "where pointer" to the source line a_line.
+// \param a_editor the source editor that contains the source to
+// consider.
+// \a_line the line number (starting from 1) to which the "where pointer"
+// is to be set.
+// \a_do_scroll if true, the source editor is scrolled to the
+// location of the newly set where pointer.
+// \return true upon successful completion, false otherwise.
+bool
+DBGPerspective::set_where (SourceEditor *a_editor,
+ int a_line,
+ bool a_do_scroll)
+{
+ if (!a_editor)
+ return false;
+
+ THROW_IF_FAIL (a_editor->get_buffer_type ()
+ == SourceEditor::BUFFER_TYPE_SOURCE);
+
+ a_editor->move_where_marker_to_line (a_line, a_do_scroll);
Gtk::TextBuffer::iterator iter =
- source_editor->source_view ()
- .get_buffer ()->get_iter_at_line (a_line-1);
+ a_editor->source_view ().get_buffer ()->get_iter_at_line (a_line - 1);
if (!iter) {
- return;
+ return false;
+ }
+ a_editor->source_view().get_buffer ()->place_cursor (iter);
+ return true;
+}
+
+// Set the graphical "where pointer" to the assembly address a_address.
+// \param a_editor the source editor that contains the source to
+// consider.
+// \a_address the assembly address to which the "where pointer"
+// is to be set.
+// \a_do_scroll if true, the source editor is scrolled to the
+// location of the newly set where pointer.
+// \return true upon successful completion, false otherwise.
+bool
+DBGPerspective::set_where (SourceEditor *a_editor,
+ const Address &a_address,
+ bool a_do_scroll,
+ bool a_try_hard)
+{
+ if (!a_editor)
+ return false;
+
+ THROW_IF_FAIL (a_editor->get_buffer_type ()
+ == SourceEditor::BUFFER_TYPE_ASSEMBLY);
+
+ // The IP points to the *next* instruction to execute. What we want
+ // is the current instruction executed. So lets get the line of the
+ // address that comes right before a_address.
+ if (!a_editor->move_where_marker_to_address (a_address, a_do_scroll)) {
+ if (a_try_hard) {
+ pump_asm_including_address (a_editor, a_address);
+ return true;
+ } else {
+ LOG_ERROR ("Fail to get line for address: "
+ << static_cast<string> (a_address));
+ return false;
+ }
}
- source_editor->source_view().get_buffer ()->place_cursor (iter);
+ a_editor->place_cursor_at_address (a_address);
+ return true;
}
void
@@ -5105,7 +5440,7 @@ DBGPerspective::load_file (const UString &a_path,
SourceEditor*
DBGPerspective::create_source_editor (Glib::RefPtr<SourceBuffer> &a_source_buf,
- bool a_disassembly_view,
+ bool a_asm_view,
const UString &a_path,
int a_current_line,
const UString &a_current_address)
@@ -5116,13 +5451,13 @@ DBGPerspective::create_source_editor (Glib::RefPtr<SourceBuffer> &a_source_buf,
Gtk::TextIter cur_line_iter;
int current_line = -1;
- if (a_disassembly_view) {
+ if (a_asm_view) {
source_editor = Gtk::manage (new SourceEditor (plugin_path (),
a_source_buf,
true));
if (!a_current_address.empty ()) {
- source_editor->assembly_buf_loc_to_line (a_current_address.raw (),
- current_line);
+ source_editor->assembly_buf_addr_to_line
+ (a_current_address.raw (), current_line);
}
} else {
source_editor = Gtk::manage (new SourceEditor (plugin_path (),
@@ -5174,9 +5509,10 @@ DBGPerspective::create_source_editor (Glib::RefPtr<SourceBuffer> &a_source_buf,
#endif // WITH_SOURCEVIEWMM2
source_editor->set_path (a_path);
source_editor->marker_region_got_clicked_signal ().connect
- (sigc::mem_fun
- (*this,
- &DBGPerspective::on_source_view_markers_region_clicked_signal));
+ (sigc::bind
+ (sigc::mem_fun (*this,
+ &DBGPerspective::on_sv_markers_region_clicked_signal),
+ source_editor));
m_priv->opened_file_action_group->set_sensitive (true);
@@ -5202,55 +5538,62 @@ DBGPerspective::open_file ()
dialog.get_filenames (paths);
list<UString>::const_iterator iter;
for (iter = paths.begin (); iter != paths.end (); ++iter) {
- open_file (*iter, -1, true);
+ open_file_real (*iter, -1, true);
}
bring_source_as_current (*(paths.begin()));
}
bool
-DBGPerspective::open_file (const UString &a_path,
- int a_current_line)
+DBGPerspective::open_file (const UString &a_path, int current_line)
+{
+ return open_file_real (a_path, current_line) ? true: false;
+}
+
+SourceEditor*
+DBGPerspective::open_file_real (const UString &a_path,
+ int a_current_line)
{
RETURN_VAL_IF_FAIL (m_priv, false);
if (a_path.empty ())
return false;
- if (get_source_editor_from_path (a_path)) {return true;}
+ SourceEditor *source_editor = 0;
+ if ((source_editor = get_source_editor_from_path (a_path)))
+ return source_editor;
NEMIVER_TRY
Glib::RefPtr<SourceBuffer> source_buffer;
if (!load_file (a_path, source_buffer)) {
- return false;
+ return 0;
}
- SourceEditor *source_editor =
- create_source_editor (source_buffer,
- /*a_disassembly_view=*/false,
- a_path,
- a_current_line,
- /*a_current_address=*/"");
+ source_editor = create_source_editor (source_buffer,
+ /*a_asm_view=*/false,
+ a_path,
+ a_current_line,
+ /*a_current_address=*/"");
THROW_IF_FAIL (source_editor);
source_editor->show_all ();
append_source_editor (*source_editor, a_path);
- NEMIVER_CATCH_AND_RETURN (false)
- return true;
+ NEMIVER_CATCH_AND_RETURN (0)
+ return source_editor;
}
-bool
-DBGPerspective::open_file (const UString &a_path,
- int current_line,
- bool a_reload_visual_breakpoint)
+SourceEditor*
+DBGPerspective::open_file_real (const UString &a_path,
+ int current_line,
+ bool a_reload_visual_breakpoint)
{
THROW_IF_FAIL (m_priv);
- bool res = open_file (a_path, current_line);
- if (res && a_reload_visual_breakpoint) {
- apply_decorations_to_text (a_path);
+ SourceEditor *editor = open_file_real (a_path, current_line);
+ if (editor && a_reload_visual_breakpoint) {
+ apply_decorations (editor);
}
- return res;
+ return editor;
}
void
@@ -5340,7 +5683,7 @@ DBGPerspective::close_file (const UString &a_path)
}
const UString&
-DBGPerspective::get_disassembly_title ()
+DBGPerspective::get_asm_title ()
{
static UString disass_title;
if (disass_title.empty ()) {
@@ -5350,9 +5693,9 @@ DBGPerspective::get_disassembly_title ()
}
bool
-DBGPerspective::load_disassembly (const IDebugger::DisassembleInfo &/*a_info*/,
- const std::list<IDebugger::AsmInstr> &a_asm,
- Glib::RefPtr<SourceBuffer> &a_source_buffer)
+DBGPerspective::load_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ Glib::RefPtr<SourceBuffer> &a_source_buffer)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -5365,99 +5708,187 @@ DBGPerspective::load_disassembly (const IDebugger::DisassembleInfo &/*a_info*/,
}
THROW_IF_FAIL (a_source_buffer);
- std::list<IDebugger::AsmInstr>::const_iterator it;
- for (it = a_asm.begin (); it != a_asm.end (); ++it) {
- ostringstream os;
- a_source_buffer->insert (a_source_buffer->end (),
- it->address ());
- a_source_buffer->insert (a_source_buffer->end (),
- " ");
- os << "<" << it->function ();
- if (!it->offset ().empty () && it->offset () != "0")
- os << "+" << it->offset ();
- os << ">: ";
- os << it->instruction ();
- os << std::endl;
- a_source_buffer->insert (a_source_buffer->end (),
- os.str ());
+ add_asm (a_info, a_asm, a_source_buffer, /*append=*/ true);
+
+ NEMIVER_CATCH_AND_RETURN (false)
+ return true;
+}
+
+static void
+write_asm_instr (std::ostringstream &a_os,
+ const IDebugger::AsmInstr &a_instr)
+{
+ a_os << a_instr.address ();
+ a_os << " ";
+ a_os << "<" << a_instr.function ();
+ if (!a_instr.offset ().empty () && a_instr.offset () != "0")
+ a_os << "+" << a_instr.offset ();
+ a_os << ">: ";
+ a_os << a_instr.instruction ();
+}
+
+bool
+DBGPerspective::add_asm (const IDebugger::DisassembleInfo &/*a_info*/,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ Glib::RefPtr<SourceBuffer> &a_buf,
+ bool a_append)
+{
+ if (!a_buf)
+ return false;
+
+ std::list<IDebugger::AsmInstr>::const_iterator it = a_asm.begin ();
+ if (it == a_asm.end ())
+ return true;
+
+ // Write the first asm instruction into a string stream.
+ std::ostringstream first_os, endl_os;
+ write_asm_instr (first_os, *it);
+ endl_os << std::endl;
+
+ // Figure out where to insert the asm instrs, depending on a_append
+ // (either prepend or append it)
+ // Also, if a_buf is not empty and we are going to append asm
+ // instrs, make sure to add an "end line" before appending our asm
+ // instrs.
+ Gtk::TextBuffer::iterator insert_it;
+ if (a_append) {
+ insert_it = a_buf->end ();
+ if (a_buf->get_char_count () != 0)
+ insert_it = a_buf->insert (insert_it, endl_os.str ());
+ } else {
+ insert_it = a_buf->begin ();
}
+ // Really insert the the first asm instrs.
+ insert_it = a_buf->insert (insert_it, first_os.str ());
+ // Append the remaing asm instrs. Make sure to add an "end of line"
+ // before each asm instr.
+ for (++it; it != a_asm.end (); ++it) {
+ ostringstream os;
+ write_asm_instr (os, *it);
+ insert_it = a_buf->insert (insert_it, endl_os.str ());
+ insert_it = a_buf->insert (insert_it, os.str ());
+ }
return true;
- NEMIVER_CATCH_AND_RETURN (false)
}
-// If new disassembly dedicated tab was already present in the perspective,
-// create a new one, otherwise, reuse the one that was already present.
+// If no asm dedicated tab was already present in the perspective,
+// create a new one, otherwise reuse the one that was already present.
// Then load the assembly insns a_asm described by a_info into the
-// source buffer of the disassembly tab.
+// source buffer of the asm tab.
// Return true upon successful completion, false otherwise.
-bool
-DBGPerspective::open_disassembly (const IDebugger::DisassembleInfo &a_info,
- const std::list<IDebugger::AsmInstr> &a_asm)
+SourceEditor*
+DBGPerspective::open_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ bool a_set_where)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
+ SourceEditor *source_editor = 0;
NEMIVER_TRY
Glib::RefPtr<SourceBuffer> source_buffer;
- SourceEditor *source_editor =
- get_source_editor_from_path (get_disassembly_title ());
+ source_editor = get_source_editor_from_path (get_asm_title ());
if (source_editor) {
source_buffer = source_editor->source_view ().get_source_buffer ();
source_buffer->erase (source_buffer->begin (), source_buffer->end ());
}
- if (!load_disassembly (a_info, a_asm, source_buffer)) {
- return false;
+ if (load_asm (a_info, a_asm, source_buffer) == 0) {
+ return 0;
}
if (!source_editor) {
source_editor =
create_source_editor (source_buffer,
- /*a_disassembly_view=*/true,
- get_disassembly_title (),
- -1,
+ /*a_asm_view=*/true,
+ get_asm_title (),
+ /*curren_line=*/-1,
/*a_current_address=*/"");
THROW_IF_FAIL (source_editor);
source_editor->show_all ();
- append_source_editor (*source_editor, get_disassembly_title ());
+ append_source_editor (*source_editor, get_asm_title ());
}
- NEMIVER_CATCH_AND_RETURN (false);
+ NEMIVER_CATCH_AND_RETURN (0);
- return true;
+ if (source_editor && a_set_where) {
+ bring_source_as_current (source_editor);
+ if (!m_priv->current_frame.has_empty_address ())
+ set_where (source_editor, m_priv->current_frame.address (),
+ /*do_scroll=*/true, /*try_hard=*/true);
+ }
+
+ return source_editor;
}
// Get the source editor of the source file being currently debugged,
-// switch it into the disassembly mode and load the asm insns
+// switch it into the asm mode and load the asm insns
// represented by a_info and a_asm into its source buffer.
// \param a_info descriptor of the assembly instructions
// \param a_asm a list of asm instructions.
void
-DBGPerspective::switch_to_disassembly
- (const IDebugger::DisassembleInfo &a_info,
- const std::list<IDebugger::AsmInstr> &a_asm)
+DBGPerspective::switch_to_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm)
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
SourceEditor *source_editor = get_current_source_editor ();
- if (source_editor == 0)
+ switch_to_asm (a_info, a_asm, source_editor);
+}
+
+// Switch a_source_editor into the asm mode and load the asm insns
+// represented by a_info and a_asm into its source buffer.
+// \param a_info descriptor of the assembly instructions
+// \param a_asm a list of asm instructions.
+void
+DBGPerspective::switch_to_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ SourceEditor *a_source_editor)
+{
+ if (!a_source_editor)
return;
+ a_source_editor->clear_decorations ();
+
Glib::RefPtr<SourceBuffer> asm_buf;
- if ((asm_buf = source_editor->get_assembly_source_buffer ()) == 0) {
+ if ((asm_buf = a_source_editor->get_assembly_source_buffer ()) == 0) {
setup_buffer_mime_and_lang (asm_buf, "test/x-asm");
- source_editor->register_assembly_source_buffer (asm_buf);
- asm_buf = source_editor->get_assembly_source_buffer ();
+ a_source_editor->register_assembly_source_buffer (asm_buf);
+ asm_buf = a_source_editor->get_assembly_source_buffer ();
RETURN_IF_FAIL (asm_buf);
}
- if (!load_disassembly (a_info, a_asm, asm_buf)) {
+ if (!load_asm (a_info, a_asm, asm_buf)) {
LOG_ERROR ("failed to load asm");
return;
}
- if (!source_editor->switch_to_assembly_source_buffer ()) {
+ if (!a_source_editor->switch_to_assembly_source_buffer ()) {
LOG_ERROR ("Could not switch the current view to asm");
+ return;
}
+ a_source_editor->current_line (-1);
+ apply_decorations (a_source_editor,
+ /*scroll_to_where_marker=*/true);
+}
+
+void
+DBGPerspective::pump_asm_including_address (SourceEditor *a_editor,
+ const Address a_address)
+{
+ Range r;
+
+ if (!a_editor
+ || !a_editor->get_assembly_address_range (r)
+ || r.contains (a_address))
+ return;
+
+ r.extend (a_address);
+ IDebugger::DisassSlot slot =
+ sigc::bind (sigc::mem_fun (this,
+ &DBGPerspective::on_debugger_asm_signal2),
+ a_editor);
+
+ disassemble_and_do (slot);
}
// Get the source editor of the source file being currently debugged,
@@ -5469,6 +5900,9 @@ DBGPerspective::switch_to_source_code ()
SourceEditor *source_editor = get_current_source_editor ();
if (source_editor == 0)
return;
+
+ source_editor->clear_decorations ();
+
Glib::RefPtr<SourceBuffer> source_buf;
UString source_path;
if ((source_buf = source_editor->get_non_assembly_source_buffer ()) == 0) {
@@ -5477,7 +5911,7 @@ DBGPerspective::switch_to_source_code ()
// the source code corresponding to the current frame. For that,
// we'll hope to have proper debug info for the binary being
// debugged, and the source code available on disk.
- if (m_priv->current_frame.address ().empty ()) {
+ if (m_priv->current_frame.has_empty_address ()) {
LOG_DD ("No current instruction pointer");
return;
}
@@ -5498,8 +5932,8 @@ DBGPerspective::switch_to_source_code ()
source_editor->register_non_assembly_source_buffer (source_buf);
}
source_editor->switch_to_non_assembly_source_buffer ();
- source_editor->get_path (source_path);
- apply_decorations_to_text (source_path);
+ apply_decorations (source_editor,
+ /*scroll_to_where_marker=*/true);
}
Gtk::Widget*
@@ -5595,10 +6029,10 @@ DBGPerspective::reload_file (const UString &a_path)
int current_column = editor->current_column ();
if (!load_file (a_path, buffer))
return false;
- editor->source_view ().set_source_buffer (buffer);
+ editor->register_non_assembly_source_buffer (buffer);
editor->current_line (current_line);
editor->current_column (current_column);
- apply_decorations_to_text (a_path);
+ apply_decorations (a_path);
return true;
}
@@ -6338,6 +6772,22 @@ DBGPerspective::get_breakpoint_number (const UString &a_file_name,
}
bool
+DBGPerspective::get_breakpoint_number (const Address &a_address,
+ int &a_break_num)
+{
+ map<int, IDebugger::Breakpoint>::const_iterator iter;
+ for (iter = m_priv->breakpoints.begin ();
+ iter != m_priv->breakpoints.end ();
+ ++iter) {
+ if (a_address == iter->second.address ()) {
+ a_break_num = iter->second.number ();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
DBGPerspective::delete_breakpoint ()
{
SourceEditor *source_editor = get_current_source_editor ();
@@ -6372,15 +6822,6 @@ DBGPerspective::delete_breakpoint (int a_breakpoint_num)
return true;
}
-bool
-DBGPerspective::append_visual_breakpoint (const UString &a_file_name,
- int a_linenum, bool enabled)
-{
- UString actual_file_path;
- return append_visual_breakpoint (a_file_name, a_linenum,
- actual_file_path, enabled);
-}
-
// Popup a dialog asking the user to select the file a_file_name.
// \param a_file_name the name of the file we want the user to select.
// \param a_selected_file_path the path to the file the user actually
@@ -6414,61 +6855,27 @@ DBGPerspective::ask_user_to_select_file (const UString &a_file_name,
}
bool
-DBGPerspective::append_visual_breakpoint (const UString &a_file_name,
+DBGPerspective::append_visual_breakpoint (SourceEditor *a_editor,
int a_linenum,
- UString &a_actual_file_path,
- bool enabled)
+ bool a_enabled)
{
- if (a_file_name.empty()) {
- LOG_ERROR_DD ("a_file_name is empty");
- return false;
- }
- THROW_IF_FAIL(m_priv);
LOG_FUNCTION_SCOPE_NORMAL_DD
- LOG_DD ("a_file_name: " << a_file_name);
- LOG_DD ("a_linenum: " << (int)a_linenum);
-
- if (a_linenum < 0) {a_linenum = 0;}
+ if (a_editor == 0)
+ return false;
+ return a_editor->set_visual_breakpoint_at_line (a_linenum, a_enabled);
+}
- UString actual_file_path;
- SourceEditor *source_editor =
- get_source_editor_from_path (a_file_name,
- actual_file_path);
- if (source_editor == 0) {
- if (!find_absolute_path (a_file_name, actual_file_path)) {
- if (ask_user_to_select_file (a_file_name, actual_file_path)) {
- UString parent_dir =
- Glib::filename_to_utf8
- (Glib::path_get_dirname (actual_file_path));
- m_priv->search_paths.push_back (parent_dir);
- }
- }
- open_file (actual_file_path);
- source_editor = get_source_editor_from_path (a_file_name,
- actual_file_path);
- }
- // if that didn't work, look for an opened source editor
- // that matches the base name
- if (source_editor == 0) {
- source_editor = get_source_editor_from_path (a_file_name,
- actual_file_path,
- /*basename_only=*/true);
- }
+bool
+DBGPerspective::append_visual_breakpoint (SourceEditor *a_editor,
+ const Address &a_address,
+ bool a_enabled)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD
- // finally, if none of these things worked, display an error
- if (!source_editor) {
- LOG_ERROR ("Could not find source editor for file: '"
- << a_file_name
- << "'");
+ if (a_editor == 0)
return false;
- } else {
- LOG_DD ("setting actual visual bp in the source editor");
- source_editor->set_visual_breakpoint_at_line (a_linenum, enabled);
- }
-
- a_actual_file_path = actual_file_path;
- return true;
+ return a_editor->set_visual_breakpoint_at_address (a_address, a_enabled);
}
void
@@ -6545,39 +6952,122 @@ DBGPerspective::remove_visual_decorations_from_text
}
bool
-DBGPerspective::apply_decorations_to_text (const UString &a_file_path)
+DBGPerspective::apply_decorations (const UString &a_file_path)
{
SourceEditor *editor = get_source_editor_from_path (a_file_path);
RETURN_VAL_IF_FAIL (editor, false);
- map<int, IDebugger::BreakPoint>::const_iterator it;
+ return apply_decorations (editor);
+}
+
+bool
+DBGPerspective::apply_decorations (SourceEditor *a_editor,
+ bool a_scroll_to_where_marker)
+{
+ bool result = false;
+ if (a_editor == 0)
+ return result;
+
+ SourceEditor::BufferType type = a_editor->get_buffer_type ();
+ switch (type) {
+ case SourceEditor::BUFFER_TYPE_SOURCE:
+ result = apply_decorations_to_source (a_editor,
+ a_scroll_to_where_marker);
+ break;
+ case SourceEditor::BUFFER_TYPE_ASSEMBLY:
+ result = apply_decorations_to_asm (a_editor,
+ a_scroll_to_where_marker);
+ break;
+ case SourceEditor::BUFFER_TYPE_UNDEFINED:
+ break;
+ }
+ return result;
+}
+
+bool
+DBGPerspective::apply_decorations_to_source (SourceEditor *a_editor,
+ bool a_scroll_to_where_marker)
+{
+ if (a_editor == 0)
+ return false;
+
+ THROW_IF_FAIL (a_editor->get_buffer_type ()
+ == SourceEditor::BUFFER_TYPE_SOURCE);
+
+ map<int, IDebugger::Breakpoint>::const_iterator it;
for (it = m_priv->breakpoints.begin ();
it != m_priv->breakpoints.end ();
++it) {
- if (a_file_path == it->second.file_full_name ()) {
- append_visual_breakpoint (a_file_path, it->second.line () - 1);
+ if (a_editor->get_path () == it->second.file_full_name ()) {
+ append_visual_breakpoint (a_editor,
+ it->second.line (),
+ it->second.enabled ());
}
}
- //scroll to the line that was precedently selected
- //or to the one pointed to by the current line marker
- bool scroll_to_where_marker = false;
- int cur_line = editor->current_line ();
- if (cur_line > 0) {
+
+ // If we don't want to scroll to the "where marker",
+ // the scroll to the line that was precedently selected
+ int cur_line;
+ if (!a_scroll_to_where_marker
+ && (cur_line = a_editor->current_line ()) > 0) {
LOG_DD ("scroll to cur_line: " << (int)cur_line);
Gtk::TextBuffer::iterator iter =
- editor->source_view().get_buffer ()->get_iter_at_line (cur_line);
+ a_editor->source_view ().get_buffer ()->get_iter_at_line (cur_line);
if (iter)
- editor->source_view ().get_buffer ()->place_cursor (iter);
- editor->scroll_to_line (cur_line);
- scroll_to_where_marker=false;
- } else {
- scroll_to_where_marker=true;
+ a_editor->source_view ().get_buffer ()->place_cursor (iter);
+ a_editor->scroll_to_line (cur_line);
}
- if (m_priv->current_frame.file_name () == a_file_path) {
- set_where (m_priv->current_frame.file_name (),
+
+ if (m_priv->current_frame.file_name () == a_editor->get_path ())
+ set_where (a_editor,
m_priv->current_frame.line (),
- scroll_to_where_marker);
+ /*a_scroll_to_where_marker=*/true);
+ return true;
+}
+
+bool
+DBGPerspective::apply_decorations_to_asm (SourceEditor *a_editor,
+ bool a_scroll_to_where_marker)
+{
+ if (a_editor == 0)
+ return false;
+
+ THROW_IF_FAIL (a_editor->get_buffer_type ()
+ == SourceEditor::BUFFER_TYPE_ASSEMBLY);
+
+ map<int, IDebugger::Breakpoint>::const_iterator it;
+ for (it = m_priv->breakpoints.begin ();
+ it != m_priv->breakpoints.end ();
+ ++it) {
+ if (a_editor->get_path () == it->second.file_full_name ()) {
+ Address addr = it->second.address ();
+ if (!append_visual_breakpoint (a_editor, addr,
+ it->second.enabled ())) {
+ LOG_ERROR ("Could'nt find line for address: "
+ << static_cast<string> (addr)
+ << " for file: "
+ << a_editor->get_path ());
+ }
+ }
+ }
+ // If we don't want to scroll to the "where marker", then scroll to
+ // the line that was precedently selected
+ int cur_line;
+ if (!a_scroll_to_where_marker
+ && (cur_line = a_editor->current_line ()) > 0) {
+ LOG_DD ("scroll to cur_line: " << cur_line);
+ Gtk::TextBuffer::iterator iter =
+ a_editor->source_view ().get_buffer ()->get_iter_at_line (cur_line);
+ if (iter)
+ a_editor->source_view ().get_buffer ()->place_cursor (iter);
+ a_editor->scroll_to_line (cur_line);
}
+
+ if (m_priv->current_frame.file_name () == a_editor->get_path ())
+ set_where (a_editor,
+ m_priv->current_frame.address (),
+ a_scroll_to_where_marker,
+ /*try_hard=*/true);
return true;
}
@@ -6585,27 +7075,47 @@ bool
DBGPerspective::delete_breakpoint (const UString &a_file_name,
int a_line_num)
{
- int breakpoint_number=0;
- bool enabled=false;
+ int breakpoint_number = 0;
+ bool enabled = false;
if (!get_breakpoint_number (a_file_name, a_line_num,
- breakpoint_number, enabled)) {
+ breakpoint_number, enabled))
+ return false;
+
+ if (breakpoint_number < 1)
return false;
- }
- if (breakpoint_number < 1) {return false;}
return delete_breakpoint (breakpoint_number);
}
bool
+DBGPerspective::delete_breakpoint (const Address &a_address)
+{
+ int bp_num = 0;
+ if (!get_breakpoint_number (a_address, bp_num))
+ return false;
+ if (bp_num < 1)
+ return false;
+ return delete_breakpoint (bp_num);
+}
+
+bool
DBGPerspective::is_breakpoint_set_at_line (const UString &a_file_path,
int a_line_num,
bool &a_enabled)
{
- int break_num=0;
+ int break_num = 0;
if (get_breakpoint_number (a_file_path, a_line_num,
- break_num, a_enabled)) {
+ break_num, a_enabled))
+ return true;
+ return false;
+}
+
+bool
+DBGPerspective::is_breakpoint_set_at_address (const Address &a_address)
+{
+ int break_num = 0;
+ if (get_breakpoint_number (a_address, break_num))
return true;
- }
return false;
}
@@ -6627,6 +7137,16 @@ DBGPerspective::toggle_breakpoint (const UString &a_file_path,
}
void
+DBGPerspective::toggle_breakpoint (const Address &a_address)
+{
+ if (is_breakpoint_set_at_address (a_address)) {
+ delete_breakpoint (a_address);
+ } else {
+ set_breakpoint (a_address);
+ }
+}
+
+void
DBGPerspective::toggle_breakpoint ()
{
SourceEditor *source_editor = get_current_source_editor ();
@@ -6815,37 +7335,75 @@ DBGPerspective::disassemble (bool a_show_asm_in_new_tab)
{
THROW_IF_FAIL (m_priv);
+ IDebugger::DisassSlot slot;
+
+ if (a_show_asm_in_new_tab)
+ slot =
+ sigc::bind (sigc::mem_fun (this,
+ &DBGPerspective::on_debugger_asm_signal1),
+ true);
+ else
+ slot =
+ sigc::bind (sigc::mem_fun (this,
+ &DBGPerspective::on_debugger_asm_signal1),
+ false);
+
+ disassemble_and_do (slot);
+}
+
+void
+DBGPerspective::disassemble_and_do (IDebugger::DisassSlot &a_what_to_do)
+{
// If we don't have the current instruction pointer (IP), there is
// nothing we can do.
if (!debugger ()->is_attached_to_target ()
- || m_priv->current_frame.address ().empty ()) {
+ || m_priv->current_frame.has_empty_address ()) {
LOG_DD ("No current instruction pointer");
return;
}
- sigc::slot<void,
- const IDebugger::DisassembleInfo,
- const std::list<IDebugger::AsmInstr>& > s;
- if (a_show_asm_in_new_tab)
- s = sigc::bind (sigc::mem_fun (this,
- &DBGPerspective::on_debugger_disassembled_signal),
- true);
+ Range addr_range (m_priv->current_frame.address (),
+ m_priv->current_frame.address ());
+ get_frame_breakpoints_address_range (m_priv->current_frame, addr_range);
- else
- s = sigc::bind
- (sigc::mem_fun
- (this,
- &DBGPerspective::on_debugger_disassembled_signal),
- false);
-
- debugger ()->disassemble
- (0 /* Start @ to disassemble */,
- true /* Start @ is relative to current IP */,
- NUM_INSTR_TO_DISASSEMBLE * sizeof (void *),
- true /* End @ is relative to current IP */,
- s);
+ THROW_IF_FAIL (addr_range.min () != 0
+ && addr_range.max () != 0);
+
+ debugger ()->disassemble (/*start_addr=*/addr_range.min (),
+ /*start_addr_relative_to_pc=*/false,
+ /*end_addr=*/addr_range.max () + 20,
+ /*end_addr_relative_to_pc=*/false,
+ a_what_to_do);
+}
+
+void
+DBGPerspective::disassemble_around_address_and_do
+ (const Address &a_address,
+ IDebugger::DisassSlot &a_what_to_do)
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ if (!debugger ()->is_attached_to_target ()
+ || a_address.empty ()) {
+ LOG_DD ("No current instruction pointer");
+ return;
+ }
+
+ if (a_address.empty ())
+ return;
+
+ Range addr_range (a_address, a_address);
+ THROW_IF_FAIL (addr_range.min () != 0
+ && addr_range.max () != 0);
+
+ debugger ()->disassemble (/*start_addr=*/addr_range.min (),
+ /*start_addr_relative_to_pc=*/false,
+ /*end_addr=*/addr_range.max () + 20,
+ /*end_addr_relative_to_pc=*/false,
+ a_what_to_do);
}
+
void
DBGPerspective::toggle_breakpoint_enabled ()
{
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.h b/src/persp/dbgperspective/nmv-dbg-perspective.h
index 6e3a488..f74e3d2 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.h
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.h
@@ -37,6 +37,7 @@ namespace gtksourceview {
NEMIVER_BEGIN_NAMESPACE (nemiver)
+class SourceEditor;
class NEMIVER_API IDBGPerspective : public IPerspective {
//non copyable
IDBGPerspective (const IPerspective&);
@@ -72,10 +73,9 @@ public:
virtual void close_file (const UString &a_uri) = 0;
- virtual bool load_disassembly
- (const IDebugger::DisassembleInfo &a_info,
- const std::list<IDebugger::AsmInstr> &a_asm,
- Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf) = 0;
+ virtual bool load_asm (const IDebugger::DisassembleInfo &a_info,
+ const std::list<IDebugger::AsmInstr> &a_asm,
+ Glib::RefPtr<gtksourceview::SourceBuffer> &a_buf) = 0;
virtual Gtk::Widget* load_menu (const UString &a_filename,
const UString &a_widget_name) = 0;
@@ -145,15 +145,6 @@ public:
virtual bool delete_breakpoint (const UString &a_file_uri,
int a_linenum) = 0;
- virtual bool append_visual_breakpoint (const UString &a_file_name,
- int a_linenum,
- bool enabled=true) = 0;
-
- virtual void delete_visual_breakpoint (const UString &a_file_name,
- int a_linenum) = 0;
-
- virtual void delete_visual_breakpoint (int a_breaknum) = 0;
-
virtual IDebuggerSafePtr& debugger () = 0;
virtual void add_text_to_command_view (const UString &a_text,
@@ -163,7 +154,7 @@ public:
virtual void add_text_to_log_view (const UString &a_text) = 0;
- virtual void set_where (const UString &a_uri,
+ virtual bool set_where (const UString &a_uri,
int line,
bool a_do_scroll=true) = 0;
diff --git a/src/uicommon/nmv-source-editor.cc b/src/uicommon/nmv-source-editor.cc
index 624129c..d728c4b 100644
--- a/src/uicommon/nmv-source-editor.cc
+++ b/src/uicommon/nmv-source-editor.cc
@@ -28,11 +28,7 @@
#include <gtkmm/table.h>
#include <gtkmm/label.h>
#include <gtkmm/scrolledwindow.h>
-#ifdef WITH_SOURCEVIEWMM2
#include <gtksourceviewmm/sourcemark.h>
-#else
-#include <gtksourceviewmm/sourcemarker.h>
-#endif // WITH_SOURCEVIEWMM2
#include <gtksourceviewmm/sourceiter.h>
#include "common/nmv-exception.h"
#include "common/nmv-sequence.h"
@@ -42,15 +38,12 @@
using namespace std;
using namespace nemiver::common;
-#ifdef WITH_SOURCEVIEWMM2
using gtksourceview::SourceMark;
-#else
-using gtksourceview::SourceMarker;
-#endif // WITH_SOURCEVIEWMM2
using gtksourceview::SourceIter;
using gtksourceview::SearchFlags;
-namespace nemiver {
+namespace nemiver
+{
const char* BREAKPOINT_ENABLED_CATEGORY = "breakpoint-enabled-category";
const char* BREAKPOINT_DISABLED_CATEGORY = "breakpoint-disabled-category";
@@ -58,7 +51,8 @@ const char* WHERE_CATEGORY = "line-pointer-category";
const char* WHERE_MARK = "where-marker";
-class SourceView : public gtksourceview::SourceView {
+class SourceView : public gtksourceview::SourceView
+{
sigc::signal<void, int, bool> m_marker_region_got_clicked_signal;
@@ -115,7 +109,7 @@ public:
THROW_IF_FAIL (iter);
LOG_DD ("got clicked on line: " << iter.get_line ());
- marker_region_got_clicked_signal ().emit (iter.get_line (),
+ marker_region_got_clicked_signal ().emit (iter.get_line () + 1,
false/*no dialog requested*/);
}
@@ -137,49 +131,22 @@ public:
};//end class Sourceview
-struct Line2AddrFunc : std::binary_function<Glib::RefPtr<SourceBuffer>,
- int,
- Address>
-{
- int m_line;
- Line2AddrFunc () :
- m_line (-1)
- {
- }
- Address operator () (Glib::RefPtr<SourceBuffer> a_buf, int a_line);
-};
-
-struct Addr2LineFunc : public std::binary_function<Glib::RefPtr<SourceBuffer>,
- const Address&, int>
-{
- int m_line;
- Addr2LineFunc () :
- m_line (-1)
- {
- }
- int operator () (Glib::RefPtr<SourceBuffer> a_buf, const Address &addr);
-};
-
-
struct SourceEditor::Priv {
Sequence sequence;
-#ifdef WITH_SOURCEVIEWMM2
- std::map<int, Glib::RefPtr<gtksourceview::SourceMark> > markers;
-#else
- std::map<int, Glib::RefPtr<gtksourceview::SourceMarker> > markers;
-#endif // WITH_SOURCEVIEWMM2
UString root_dir;
nemiver::SourceView *source_view;
Gtk::Label *line_col_label;
Gtk::HBox *status_box;
+ enum SourceEditor::BufferType buffer_type;
+ UString path;
struct NonAssemblyBufContext {
Glib::RefPtr<SourceBuffer> buffer;
+ std::map<int, Glib::RefPtr<gtksourceview::SourceMark> > markers;
int current_column;
int current_line;
- sigc::signal<void, gint, gint> signal_insertion_moved;
+ sigc::signal<void, int, int> signal_insertion_moved;
sigc::signal<void, int, bool> marker_region_got_clicked_signal;
- UString path;
NonAssemblyBufContext (Glib::RefPtr<SourceBuffer> a_buf,
int a_cur_col, int a_cur_line) :
@@ -204,16 +171,22 @@ struct SourceEditor::Priv {
struct AssemblyBufContext {
Glib::RefPtr<SourceBuffer> buffer;
- Line2AddrFunc line_to_locus_func;
- Addr2LineFunc locus_to_line_func;
+ std::map<int, Glib::RefPtr<gtksourceview::SourceMark> > markers;
+ int current_line;
+ int current_column;
+ Address current_address;
- AssemblyBufContext ()
+ AssemblyBufContext () :
+ current_line (-1),
+ current_column (-1)
{
}
AssemblyBufContext
(Glib::RefPtr<SourceBuffer> a_buf) :
- buffer (a_buf)
+ buffer (a_buf),
+ current_line (-1),
+ current_column (-1)
{
}
} asm_ctxt;
@@ -222,80 +195,190 @@ struct SourceEditor::Priv {
insertion_changed_signal;
- void register_assembly_source_buffer
- (Glib::RefPtr<SourceBuffer> &a_buf)
+ void
+ register_assembly_source_buffer (Glib::RefPtr<SourceBuffer> &a_buf)
{
asm_ctxt.buffer = a_buf;
+ source_view->set_source_buffer (a_buf);
}
- void register_non_assembly_source_buffer
- (Glib::RefPtr<SourceBuffer> &a_buf)
+ void
+ register_non_assembly_source_buffer (Glib::RefPtr<SourceBuffer> &a_buf)
{
non_asm_ctxt.buffer = a_buf;
+ source_view->set_source_buffer (a_buf);
}
- bool switch_to_assembly_source_buffer ()
+ bool
+ switch_to_assembly_source_buffer ()
{
RETURN_VAL_IF_FAIL (source_view, false);
- if (asm_ctxt.buffer
- && (source_view->get_source_buffer ()
- != asm_ctxt.buffer)) {
- source_view->set_source_buffer (asm_ctxt.buffer);
+ if (asm_ctxt.buffer) {
+ if (source_view->get_source_buffer ()
+ != asm_ctxt.buffer)
+ source_view->set_source_buffer (asm_ctxt.buffer);
return true;
}
return false;
}
- bool switch_to_non_assembly_source_buffer ()
+ bool
+ switch_to_non_assembly_source_buffer ()
{
RETURN_VAL_IF_FAIL (source_view, false);
- if (asm_ctxt.buffer
- && (source_view->get_source_buffer ()
- != non_asm_ctxt.buffer)) {
- source_view->set_source_buffer (non_asm_ctxt.buffer);
+ if (asm_ctxt.buffer) {
+ if (source_view->get_source_buffer ()
+ != non_asm_ctxt.buffer) {
+ source_view->set_source_buffer (non_asm_ctxt.buffer);
+ // Reset the "current line" that was selected previously.
+ non_asm_ctxt.current_line = -1;
+ }
return true;
}
return false;
}
+ SourceEditor::BufferType
+ get_buffer_type () const
+ {
+ Glib::RefPtr<SourceBuffer> buf = source_view->get_source_buffer ();
+ if (buf == non_asm_ctxt.buffer)
+ return BUFFER_TYPE_SOURCE;
+ else if (buf == asm_ctxt.buffer)
+ return BUFFER_TYPE_ASSEMBLY;
+ else
+ return BUFFER_TYPE_UNDEFINED;
+ }
+
+ std::map<int, Glib::RefPtr<gtksourceview::SourceMark> >*
+ get_markers ()
+ {
+ SourceEditor::BufferType t = get_buffer_type ();
+ switch (t) {
+ case SourceEditor::BUFFER_TYPE_SOURCE:
+ return &non_asm_ctxt.markers;
+ case SourceEditor::BUFFER_TYPE_ASSEMBLY:
+ return &asm_ctxt.markers;
+ case SourceEditor::BUFFER_TYPE_UNDEFINED:
+ return 0;
+ }
+ return 0;
+ }
+
+ bool
+ address_2_line (Glib::RefPtr<SourceBuffer> a_buf,
+ const Address an_addr,
+ int &a_line) const
+ {
+ Address prev_address;
+ return address_2_line (a_buf, an_addr, a_line, prev_address);
+ }
+
+ bool
+ address_2_line (Glib::RefPtr<SourceBuffer> a_buf,
+ const Address an_addr,
+ int &a_line,
+ Address &a_prev_addr) const
+ {
+ if (!a_buf)
+ return false;
+
+ Gtk::TextBuffer::iterator it = a_buf->begin ();
+ size_t i;
+ std::string addr, prev_addr;
+ while (!it.is_end ()) {
+ // We must always be at the beginning of a line here.
+ THROW_IF_FAIL (it.starts_line ());
+ prev_addr = addr;
+ addr.clear ();
+ for (i = 0;
+ !isspace (it.get_char ()) && it.ends_line () != true
+ && i < an_addr.string_size ();
+ ++it, ++i) {
+ addr += it.get_char ();
+ }
+ bool match = (addr == static_cast<std::string> (an_addr));
+ if (match) {
+ a_line = it.get_line () + 1;
+ a_prev_addr = prev_addr;
+ return true;
+ } else {
+ // Go to next line.
+ it.forward_line ();
+ }
+ }
+ return false;
+ }
+
+ bool
+ line_2_address (Glib::RefPtr<SourceBuffer> a_buf,
+ int a_line,
+ Address &an_address) const
+ {
+ if (!a_buf)
+ return false;
+
+ std::string addr;
+ for (Gtk::TextBuffer::iterator it = a_buf->get_iter_at_line (a_line - 1);
+ !it.ends_line ();
+ ++it) {
+ char c = (char) it.get_char ();
+ if (isspace (c))
+ break;
+ addr += c;
+ }
+ if (addr.empty ())
+ return false;
+
+ an_address = addr;
+ return true;
+ }
+
//**************
//<signal slots>
//**************
- void on_marker_region_got_clicked (int a_line, bool a_dialog_requested)
+ void
+ on_marker_region_got_clicked (int a_line, bool a_dialog_requested)
{
non_asm_ctxt.marker_region_got_clicked_signal.emit
- (a_line, a_dialog_requested);
+ (a_line, a_dialog_requested);
}
- void on_mark_set_signal (const Gtk::TextBuffer::iterator &a_iter,
- const Glib::RefPtr<Gtk::TextBuffer::Mark> &a_mark)
+ void
+ on_mark_set_signal (const Gtk::TextBuffer::iterator &a_iter,
+ const Glib::RefPtr<Gtk::TextBuffer::Mark> &a_mark)
{
if (a_mark->get_name () == "insert") {
update_line_col_info_from_iter (a_iter);
}
}
- void on_signal_insert (const Gtk::TextBuffer::iterator &a_iter,
- const Glib::ustring &a_text,
- int a_unknown)
+ void
+ on_signal_insert (const Gtk::TextBuffer::iterator &a_iter,
+ const Glib::ustring &a_text,
+ int a_unknown)
{
if (a_text == "" || a_unknown) {}
update_line_col_info_from_iter (a_iter);
}
- void on_signal_insertion_moved (gint a_line, gint a_col)
+ void
+ on_signal_insertion_moved (int a_line, int a_col)
{
- if (a_line || a_col) {}
+ NEMIVER_TRY
+
non_asm_ctxt.current_line = a_line;
non_asm_ctxt.current_column = a_col;
update_line_col_label ();
+
+ NEMIVER_CATCH
}
- void on_signal_mark_set
- (const Gtk::TextBuffer::iterator &a_iter,
- const Glib::RefPtr<Gtk::TextBuffer::Mark > &a_mark)
+ void
+ on_signal_mark_set (const Gtk::TextBuffer::iterator &a_iter,
+ const Glib::RefPtr<Gtk::TextBuffer::Mark > &a_mark)
{
NEMIVER_TRY
THROW_IF_FAIL (source_view);
@@ -312,7 +395,8 @@ struct SourceEditor::Priv {
//</signal slots>
//**************
- void init_signals ()
+ void
+ init_signals ()
{
source_view->marker_region_got_clicked_signal ().connect
(sigc::mem_fun (*this,
@@ -328,18 +412,30 @@ struct SourceEditor::Priv {
(sigc::mem_fun (*this, &SourceEditor::Priv::on_signal_mark_set));
}
- void update_line_col_info_from_iter (const Gtk::TextBuffer::iterator &a_iter)
+ void
+ update_line_col_info_from_iter (const Gtk::TextBuffer::iterator &a_iter)
{
- non_asm_ctxt.current_line = a_iter.get_line () + 1;
- non_asm_ctxt.current_column = get_column_from_iter (a_iter);
- non_asm_ctxt.signal_insertion_moved.emit
- (non_asm_ctxt.current_line,
- non_asm_ctxt.current_column);
+ SourceEditor::BufferType t = get_buffer_type ();
+ if (t == SourceEditor::BUFFER_TYPE_SOURCE) {
+ non_asm_ctxt.current_line = a_iter.get_line () + 1;
+ non_asm_ctxt.current_column = get_column_from_iter (a_iter);
+ non_asm_ctxt.signal_insertion_moved.emit
+ (non_asm_ctxt.current_line,
+ non_asm_ctxt.current_column);
+ } else if (t == SourceEditor::BUFFER_TYPE_ASSEMBLY) {
+ asm_ctxt.current_line = a_iter.get_line () + 1;
+ asm_ctxt.current_column = get_column_from_iter (a_iter);
+ line_2_address (asm_ctxt.buffer,
+ asm_ctxt.current_line,
+ asm_ctxt.current_address);
+ }
+
}
- void update_line_col_label ()
+ void
+ update_line_col_label ()
{
- gint line_count = 0;
+ int line_count = 0;
if (source_view && source_view->get_buffer ()) {
line_count = source_view->get_buffer ()->get_line_count ();
}
@@ -350,12 +446,14 @@ struct SourceEditor::Priv {
line_col_label->set_text (message);
}
- gint get_column_from_iter (const Gtk::TextBuffer::iterator &a_iter)
+ int
+ get_column_from_iter (const Gtk::TextBuffer::iterator &a_iter)
{
return a_iter.get_line_offset () + 1;
}
- bool get_absolute_resource_path (const UString &a_relative_path,
+ bool
+ get_absolute_resource_path (const UString &a_relative_path,
string &a_absolute_path)
{
bool result (false);
@@ -373,7 +471,8 @@ struct SourceEditor::Priv {
return result;
}
- void register_breakpoint_marker_type (const UString &a_name,
+ void
+ register_breakpoint_marker_type (const UString &a_name,
const UString &a_image)
{
string path;
@@ -384,15 +483,12 @@ struct SourceEditor::Priv {
Glib::RefPtr<Gdk::Pixbuf> bm_pixbuf =
Gdk::Pixbuf::create_from_file (path);
-#ifdef WITH_SOURCEVIEWMM2
source_view->set_mark_category_pixbuf (a_name, bm_pixbuf);
source_view->set_mark_category_priority (a_name, 0);
-#else
- source_view->set_marker_pixbuf (a_name, bm_pixbuf);
-#endif // WITH_SOURCEVIEWMM2
}
- void init ()
+ void
+ init ()
{
status_box->pack_end (*line_col_label,
Gtk::PACK_SHRINK, 6 /* padding */);
@@ -426,7 +522,7 @@ struct SourceEditor::Priv {
source_view (Gtk::manage (new SourceView (a_buf))),
line_col_label (Gtk::manage (new Gtk::Label)),
status_box (Gtk::manage (new Gtk::HBox)),
- non_asm_ctxt (a_buf, -1, -1)
+ non_asm_ctxt (-1, -1)
{
if (a_assembly) {
asm_ctxt.buffer = a_buf;
@@ -441,7 +537,7 @@ struct SourceEditor::Priv {
root_dir (a_root_dir),
source_view (Gtk::manage (new SourceView (a_buf))),
status_box (Gtk::manage (new Gtk::HBox)),
- asm_ctxt (a_buf)
+ non_asm_ctxt (a_buf, -1, -1)
{
init ();
}
@@ -466,15 +562,10 @@ SourceEditor::init ()
THROW ("could not get path to line-pointer.png");
}
Glib::RefPtr<Gdk::Pixbuf> lp_pixbuf = Gdk::Pixbuf::create_from_file (path);
-#ifdef WITH_SOURCEVIEWMM2
source_view ().set_mark_category_pixbuf (WHERE_CATEGORY, lp_pixbuf);
// show this on top
source_view ().set_mark_category_priority (WHERE_CATEGORY, 100);
source_view ().set_show_line_marks (true);
-#else
- source_view ().set_marker_pixbuf (WHERE_CATEGORY, lp_pixbuf);
- source_view ().set_show_line_markers (true);
-#endif // WITH_SOURCEVIEWMM2
}
SourceEditor::SourceEditor ()
@@ -503,32 +594,42 @@ SourceEditor::source_view () const
return *m_priv->source_view;
}
-gint
+int
SourceEditor::current_line () const
{
- return m_priv->non_asm_ctxt.current_line;
+ BufferType type = get_buffer_type ();
+ if (type == BUFFER_TYPE_SOURCE)
+ return m_priv->non_asm_ctxt.current_line;
+ else if (type == BUFFER_TYPE_ASSEMBLY)
+ return m_priv->asm_ctxt.current_line;
+ else
+ return -1;
}
void
-SourceEditor::current_line (gint &a_line)
+SourceEditor::current_line (int a_line)
{
- m_priv->non_asm_ctxt.current_line = a_line;
+ BufferType type = get_buffer_type ();
+ if (type == BUFFER_TYPE_SOURCE)
+ m_priv->non_asm_ctxt.current_line = a_line;
+ else if (type == BUFFER_TYPE_ASSEMBLY)
+ m_priv->asm_ctxt.current_line = a_line;
}
-gint
+int
SourceEditor::current_column () const
{
return m_priv->non_asm_ctxt.current_column;
}
void
-SourceEditor::current_column (gint &a_col)
+SourceEditor::current_column (int &a_col)
{
LOG_DD ("current colnum " << (int) a_col);
m_priv->non_asm_ctxt.current_column = a_col;
}
-void
+bool
SourceEditor::move_where_marker_to_line (int a_line, bool a_do_scroll)
{
LOG_DD ("a_line: " << a_line);
@@ -539,66 +640,50 @@ SourceEditor::move_where_marker_to_line (int a_line, bool a_do_scroll)
source_view ().get_source_buffer ()->get_iter_at_line (a_line - 1);
THROW_IF_FAIL (line_iter);
-#ifdef WITH_SOURCEVIEWMM2
Glib::RefPtr<Gtk::TextMark> where_marker =
source_view ().get_source_buffer ()->get_mark (WHERE_MARK);
-#else
- Glib::RefPtr<gtksourceview::SourceMarker> where_marker =
- source_view ().get_source_buffer ()->get_marker (WHERE_MARK);
-#endif // WITH_SOURCEVIEWMM2
if (!where_marker) {
-#ifdef WITH_SOURCEVIEWMM2
Glib::RefPtr<Gtk::TextMark> where_marker =
source_view ().get_source_buffer ()->create_source_mark
-#else
- Glib::RefPtr<gtksourceview::SourceMarker> where_marker =
- source_view ().get_source_buffer ()->create_marker
-#endif // WITH_SOURCEVIEWMM2
(WHERE_MARK,
WHERE_CATEGORY,
line_iter);
THROW_IF_FAIL (where_marker);
} else {
-#ifdef WITH_SOURCEVIEWMM2
source_view ().get_source_buffer ()->move_mark (where_marker,
line_iter);
-#else
- source_view ().get_source_buffer ()->move_marker (where_marker,
- line_iter);
-#endif // WITH_SOURCEVIEWMM2
}
if (a_do_scroll) {
scroll_to_line (a_line);
}
-
+ return true;
}
void
SourceEditor::unset_where_marker ()
{
-#ifdef WITH_SOURCEVIEWMM2
Glib::RefPtr<Gtk::TextMark> where_marker =
source_view ().get_source_buffer ()->get_mark (WHERE_MARK);
-#else
- Glib::RefPtr<gtksourceview::SourceMarker> where_marker =
- source_view ().get_source_buffer ()->get_marker (WHERE_MARK);
-#endif // WITH_SOURCEVIEWMM2
if (where_marker && !where_marker->get_deleted ()) {
-#ifdef WITH_SOURCEVIEWMM2
source_view ().get_source_buffer ()->delete_mark (where_marker);
-#else
- source_view ().get_source_buffer ()->delete_marker (where_marker);
-#endif // WITH_SOURCEVIEWMM2
}
}
-void
+bool
SourceEditor::set_visual_breakpoint_at_line (int a_line, bool enabled)
{
LOG_FUNCTION_SCOPE_NORMAL_DD
+
LOG_DD ("a_line: " << (int)a_line << "enabled: " << (int) enabled);
+ // GTK+ Considers that line numbers (in Gtk::TextBuffer) start at 0,
+ // where as in Nemiver (mostly due to GDB), we consider that they
+ // starts at 1. So adjust a_line accordingly.
+ if (a_line <= 0)
+ return false;
+ --a_line;
+
UString marker_type;
if (enabled) {
marker_type = BREAKPOINT_ENABLED_CATEGORY;
@@ -607,82 +692,65 @@ SourceEditor::set_visual_breakpoint_at_line (int a_line, bool enabled)
}
std::map<int,
-#ifdef WITH_SOURCEVIEWMM2
- Glib::RefPtr<gtksourceview::SourceMark> >::iterator mark_iter =
-#else
- Glib::RefPtr<gtksourceview::SourceMarker> >::iterator mark_iter =
-#endif // WITH_SOURCEVIEWMM2
- m_priv->markers.find (a_line);
- if (mark_iter != m_priv->markers.end ()) {
+ Glib::RefPtr<gtksourceview::SourceMark> > *markers;
+ if ((markers = m_priv->get_markers ()) == 0)
+ return false;
+
+
+ Glib::RefPtr<SourceBuffer> buf = source_view ().get_source_buffer ();
+ std::map<int, Glib::RefPtr<gtksourceview::SourceMark> >::iterator mark_iter;
+ mark_iter = markers->find (a_line);
+ if (mark_iter != markers->end ()) {
if (!mark_iter->second->get_deleted ()) {
LOG_DD ("deleting marker");
-#ifdef WITH_SOURCEVIEWMM2
- source_view ().get_source_buffer ()->delete_mark
-#else
- source_view ().get_source_buffer ()->delete_marker
-#endif // WITH_SOURCEVIEWMM2
- (mark_iter->second);
+ buf->delete_mark (mark_iter->second);
+ markers->erase (a_line);
}
- m_priv->markers.erase (a_line);
}
// marker doesn't yet exist, so create one of the correct type
- Gtk::TextIter iter =
- source_view ().get_source_buffer ()->get_iter_at_line (a_line);
+ Gtk::TextIter iter = buf->get_iter_at_line (a_line);
LOG_DD ("a_line: " << a_line);
THROW_IF_FAIL (iter);
UString marker_name = UString::from_int (a_line);
LOG_DD ("creating marker of type: " << marker_type);
-#ifdef WITH_SOURCEVIEWMM2
- Glib::RefPtr<gtksourceview::SourceMark> marker =
- source_view ().get_source_buffer ()->create_source_mark
-#else
- Glib::RefPtr<gtksourceview::SourceMarker> marker =
- source_view ().get_source_buffer ()->create_marker
-#endif // WITH_SOURCEVIEWMM2
- (marker_name, marker_type, iter);
- m_priv->markers[a_line] = marker;
+ Glib::RefPtr<gtksourceview::SourceMark> marker;
+ marker = buf->create_source_mark (marker_name, marker_type, iter);
+ (*markers)[a_line] = marker;
+ return true;
}
void
SourceEditor::remove_visual_breakpoint_from_line (int a_line)
{
-#ifdef WITH_SOURCEVIEWMM2
+ std::map<int, Glib::RefPtr<gtksourceview::SourceMark> > *markers;
+
+ if ((markers = m_priv->get_markers ()) == 0)
+ return;
+
std::map<int, Glib::RefPtr<gtksourceview::SourceMark> >::iterator iter;
-#else
- std::map<int, Glib::RefPtr<gtksourceview::SourceMarker> >::iterator iter;
-#endif // WITH_SOURCEVIEWMM2
- iter = m_priv->markers.find (a_line);
- if (iter == m_priv->markers.end ()) {
+ iter = markers->find (a_line);
+ if (iter == markers->end ()) {
return;
}
if (!iter->second->get_deleted ())
-#ifdef WITH_SOURCEVIEWMM2
source_view ().get_source_buffer ()->delete_mark (iter->second);
-#else
- source_view ().get_source_buffer ()->delete_marker (iter->second);
-#endif // WITH_SOURCEVIEWMM2
- m_priv->markers.erase (iter);
+ markers->erase (iter);
}
void
SourceEditor::clear_decorations ()
{
-#ifdef WITH_SOURCEVIEWMM2
+ std::map<int, Glib::RefPtr<gtksourceview::SourceMark> > *markers;
+ if ((markers = m_priv->get_markers ()) == 0)
+ return;
std::map<int, Glib::RefPtr<gtksourceview::SourceMark> >::iterator it;
-#else
- std::map<int, Glib::RefPtr<gtksourceview::SourceMarker> >::iterator it;
-#endif // WITH_SOURCEVIEWMM2
// Clear breakpoint markers
- for (it = m_priv->markers.begin (); it != m_priv->markers.end (); ++it) {
+ for (it = markers->begin (); it != markers->end (); ++it) {
if (!it->second->get_deleted ()) {
-#ifdef WITH_SOURCEVIEWMM2
source_view ().get_source_buffer ()->delete_mark (it->second);
-#else
- source_view ().get_source_buffer ()->delete_marker (it->second);
-#endif // WITH_SOURCEVIEWMM2
- m_priv->markers.erase (it);
+ markers->erase (it);
}
}
@@ -692,13 +760,12 @@ SourceEditor::clear_decorations ()
bool
SourceEditor::is_visual_breakpoint_set_at_line (int a_line) const
{
-#ifdef WITH_SOURCEVIEWMM2
+ std::map<int, Glib::RefPtr<gtksourceview::SourceMark> > *markers;
std::map<int, Glib::RefPtr<gtksourceview::SourceMark> >::iterator iter;
-#else
- std::map<int, Glib::RefPtr<gtksourceview::SourceMarker> >::iterator iter;
-#endif // WITH_SOURCEVIEWMM2
- iter = m_priv->markers.find (a_line);
- if (iter == m_priv->markers.end ()) {
+ if ((markers = m_priv->get_markers ()) == 0)
+ return false;
+ iter = markers->find (a_line);
+ if (iter == markers->end ()) {
return false;
}
return true;
@@ -722,14 +789,15 @@ struct ScrollToLine {
bool do_scroll ()
{
if (!m_source_view) {return false;}
- Gtk::TextIter iter = m_source_view->get_buffer ()->get_iter_at_line (m_line);
+ Gtk::TextIter iter =
+ m_source_view->get_buffer ()->get_iter_at_line (m_line);
if (!iter) {return false;}
m_source_view->scroll_to (iter, 0.1);
return false;
}
};
-void
+bool
SourceEditor::scroll_to_line (int a_line)
{
static ScrollToLine s_scroll_functor;
@@ -737,6 +805,7 @@ SourceEditor::scroll_to_line (int a_line)
s_scroll_functor.m_source_view = m_priv->source_view;
Glib::signal_idle ().connect (sigc::mem_fun (s_scroll_functor,
&ScrollToLine::do_scroll));
+ return true;
}
void
@@ -756,20 +825,26 @@ SourceEditor::scroll_to_iter (Gtk::TextIter &a_iter)
void
SourceEditor::set_path (const UString &a_path)
{
- m_priv->non_asm_ctxt.path = a_path;
+ m_priv->path = a_path;
}
void
SourceEditor::get_path (UString &a_path) const
{
- a_path = m_priv->non_asm_ctxt.path;
+ a_path = m_priv->path;
+}
+
+const UString&
+SourceEditor::get_path () const
+{
+ return m_priv->path;
}
void
SourceEditor::get_file_name (UString &a_file_name)
{
string path;
- path = Glib::locale_from_utf8 (m_priv->non_asm_ctxt.path);
+ path = Glib::locale_from_utf8 (get_path ());
path = Glib::path_get_basename (path);
a_file_name = Glib::locale_to_utf8 (path);
}
@@ -927,10 +1002,6 @@ SourceEditor::do_search (const UString &a_str,
/// Registers a assembly source buffer
/// \param a_buf the assembly source buffer
-/// \param a_line_to_locus_func a unary function that converts a line
-/// number into a meaningful location for this source buffer.
-/// \param a_locus_to_line_func a unary function that converst a
-/// meaningful location into a line buffer.
void
SourceEditor::register_assembly_source_buffer
(Glib::RefPtr<SourceBuffer> &a_buf)
@@ -938,6 +1009,12 @@ SourceEditor::register_assembly_source_buffer
m_priv->register_assembly_source_buffer (a_buf);
}
+SourceEditor::BufferType
+SourceEditor::get_buffer_type () const
+{
+ return m_priv->get_buffer_type ();
+}
+
/// Registers a normal (non-assembly) source buffer.
/// \param a_buf the source buffer to register.
void
@@ -956,6 +1033,26 @@ SourceEditor::get_assembly_source_buffer () const
return m_priv->asm_ctxt.buffer;
}
+bool
+SourceEditor::set_visual_breakpoint_at_address (const Address &a_address,
+ bool a_enabled)
+{
+ int line = -1;
+ if (!assembly_buf_addr_to_line (a_address, line))
+ return false;
+ return set_visual_breakpoint_at_line (line, a_enabled);
+
+}
+
+bool
+SourceEditor::scroll_to_address (const Address &a_address)
+{
+ int line = -1;
+ if (!assembly_buf_addr_to_line (a_address, line))
+ return false;
+ return scroll_to_line (line);
+}
+
/// Get the non-assembly source buffer that was registered, or a NULL
/// pointer if no one was registered before.
/// \return a smart pointer to the source buffer.
@@ -994,84 +1091,113 @@ SourceEditor::switch_to_non_assembly_source_buffer ()
}
bool
-SourceEditor::assembly_buf_loc_to_line (const Address &a_addr, int &a_line)
+SourceEditor::assembly_buf_addr_to_line (const Address &a_addr, int &a_line) const
{
Glib::RefPtr<SourceBuffer> buf = get_assembly_source_buffer ();
RETURN_VAL_IF_FAIL (buf, false);
- a_line = m_priv->asm_ctxt.locus_to_line_func (buf, a_addr);
- return true;
+ return m_priv->address_2_line (buf, a_addr, a_line);
}
bool
-SourceEditor::assembly_buf_line_to_loc (int a_line, Address &a_address)
+SourceEditor::assembly_buf_addr_to_line_previous (const Address &a_addr,
+ int &a_prev_line) const
+{
+ Address prev_addr;
+ return assembly_buf_addr_to_line_previous (a_addr, a_prev_line, prev_addr);
+}
+
+bool
+SourceEditor::assembly_buf_addr_to_line_previous (const Address &a_addr,
+ int &a_prev_line,
+ Address &a_prev_address) const
{
Glib::RefPtr<SourceBuffer> buf = get_assembly_source_buffer ();
RETURN_VAL_IF_FAIL (buf, false);
- a_address = m_priv->asm_ctxt.line_to_locus_func (buf, a_line);
- return true;
+ int line = 0;
+ bool ok = m_priv->address_2_line (buf, a_addr,
+ line,
+ a_prev_address);
+ if (ok) {
+ THROW_IF_FAIL (line > 0);
+ a_prev_line = line - 1;
+ }
+ return ok;
}
-sigc::signal<void, int, bool>&
-SourceEditor::marker_region_got_clicked_signal () const
+bool
+SourceEditor::assembly_buf_line_to_addr (int a_line, Address &a_address) const
{
- return m_priv->non_asm_ctxt.marker_region_got_clicked_signal;
+ Glib::RefPtr<SourceBuffer> buf = get_assembly_source_buffer ();
+ RETURN_VAL_IF_FAIL (buf, false);
+ return m_priv->line_2_address (buf, a_line, a_address);
}
-sigc::signal<void, const Gtk::TextBuffer::iterator&>&
-SourceEditor::insertion_changed_signal () const
+bool
+SourceEditor::get_assembly_address_range (Range &a) const
{
- return m_priv->insertion_changed_signal;
+ Glib::RefPtr<SourceBuffer> buf = get_assembly_source_buffer ();
+ if (!buf)
+ return false;
+ Address addr;
+ if (!m_priv->line_2_address (buf, 1, addr))
+ return false;
+ Range range;
+ range.min (addr);
+ if (!m_priv->line_2_address (buf, buf->get_line_count (), addr))
+ return false;
+ range.max (addr);
+ a = range;
+ return true;
}
-Address
-Line2AddrFunc::operator () (Glib::RefPtr<SourceBuffer> a_buf,
- int a_line)
+bool
+SourceEditor::move_where_marker_to_address (const Address &a_address,
+ bool a_do_scroll)
{
- THROW_IF_FAIL (a_buf);
-
- std::string addr;
- m_line = a_line;
- Gtk::TextBuffer::iterator it = a_buf->get_iter_at_line (m_line);
- while (true) {
- gunichar c = *it;
- if (isspace (c) || it.is_end ())
- break;
- addr += c;
- ++it;
+ int line = -1;
+ if (!assembly_buf_addr_to_line (a_address, line)) {
+ return false;
}
- Address result = addr;
- return result;
+ return move_where_marker_to_line (line, a_do_scroll);
}
-int
-Addr2LineFunc::operator () (Glib::RefPtr<SourceBuffer> a_buf,
- const Address &an_addr)
+bool
+SourceEditor::place_cursor_at_line (size_t a_line)
{
- THROW_IF_FAIL (a_buf);
-
- int wrap = 0;
+ if (a_line == 0)
+ return false;
+ --a_line;
+ Gtk::TextBuffer::iterator iter =
+ source_view ().get_buffer ()->get_iter_at_line (a_line);
+ if (!iter) {
+ return false;
+ }
+ source_view().get_buffer ()->place_cursor (iter);
+ return true;
+}
- if (m_line < 0)
- m_line = 0;
- else
- wrap = 1;
+bool
+SourceEditor::place_cursor_at_address (const Address &a_address)
+{
+ if (get_buffer_type () != BUFFER_TYPE_ASSEMBLY)
+ return false;
+ int line = -1;
+ if (!assembly_buf_addr_to_line (a_address, line))
+ return false;
+ return place_cursor_at_line (line);
- Gtk::TextBuffer::iterator it = a_buf->get_iter_at_line (m_line);
- const std::string &addr = an_addr;
+}
- do {
- bool match = true;
- for (std::string::size_type i = 0; i < addr.size (); ++i, ++it) {
- if (it.get_char () != (gunichar) addr[i]) {
- match = false;
- break;
- }
- }
- if (match)
- return it.get_line ();
- } while (wrap--);
+sigc::signal<void, int, bool>&
+SourceEditor::marker_region_got_clicked_signal () const
+{
+ return m_priv->non_asm_ctxt.marker_region_got_clicked_signal;
+}
- return -1;
+sigc::signal<void, const Gtk::TextBuffer::iterator&>&
+SourceEditor::insertion_changed_signal () const
+{
+ return m_priv->insertion_changed_signal;
}
}//end namespace nemiver
diff --git a/src/uicommon/nmv-source-editor.h b/src/uicommon/nmv-source-editor.h
index a9c59bf..371b3c2 100644
--- a/src/uicommon/nmv-source-editor.h
+++ b/src/uicommon/nmv-source-editor.h
@@ -1,4 +1,4 @@
-//Author: Dodji Seketeli
+// Author: Dodji Seketeli
/*
*This file is part of the Nemiver project
*
@@ -32,6 +32,7 @@
#include "common/nmv-safe-ptr-utils.h"
#include "common/nmv-ustring.h"
#include "common/nmv-address.h"
+#include "common/nmv-range.h"
using gtksourceview::SourceView;
using gtksourceview::SourceBuffer;
@@ -62,25 +63,33 @@ class SourceEditor : public VBox {
public:
+ enum BufferType {
+ BUFFER_TYPE_UNDEFINED,
+ BUFFER_TYPE_SOURCE,
+ BUFFER_TYPE_ASSEMBLY
+ };
+
+
explicit SourceEditor (const UString &a_root_dir,
Glib::RefPtr<SourceBuffer> &a_buf,
bool a_composite = false);
virtual ~SourceEditor ();
SourceView& source_view () const;
- gint current_line () const;
- void current_line (gint &a_line);
- gint current_column () const;
- void current_column (gint &a_col);
- void move_where_marker_to_line (int a_line, bool a_do_scroll=true);
+ int current_line () const;
+ void current_line (int a_line);
+ int current_column () const;
+ void current_column (int &a_col);
+ bool move_where_marker_to_line (int a_line, bool a_do_scroll = true);
void unset_where_marker ();
- void set_visual_breakpoint_at_line (int a_line, bool enabled=true);
+ bool set_visual_breakpoint_at_line (int a_line, bool enabled = true);
void remove_visual_breakpoint_from_line (int a_line);
void clear_decorations ();
bool is_visual_breakpoint_set_at_line (int a_line) const;
- void scroll_to_line (int a_line);
+ bool scroll_to_line (int a_line);
void scroll_to_iter (Gtk::TextIter &a_iter);
void set_path (const UString &a_path);
void get_path (UString &a_path) const;
+ const UString& get_path () const;
void get_file_name (UString &a_file_name);
bool get_word_at_position (int a_x,
int a_y,
@@ -96,12 +105,12 @@ public:
bool a_search_backwards=false,
bool a_clear_selection=false);
- /// \name Composite Source buffer handling.
+ /// \name Assembly source buffer handling.
/// @{
/// A assembly buffer is a buffer which content doesn't come
/// directly from a file. It as been composed in memory. We use
- /// assemyb buffers to represent the assembly view of a text file
+ /// assembly buffers to represent the assembly view of a text file
/// being debugged.
/// Unlike non-assembly buffers, meaningful locations inside the buffer
/// are not necessarily line numbers.
@@ -111,6 +120,8 @@ public:
/// line number, because the underlying SourceBuffer implementation
/// relies on line numbers anyhow.
+ BufferType get_buffer_type () const;
+
void register_assembly_source_buffer
(Glib::RefPtr<SourceBuffer> &a_buf);
@@ -125,9 +136,21 @@ public:
bool switch_to_non_assembly_source_buffer ();
- bool assembly_buf_loc_to_line (const Address &, int &);
+ bool assembly_buf_addr_to_line (const Address&, int&) const;
+ bool assembly_buf_addr_to_line_previous (const Address&, int&) const;
+ bool assembly_buf_addr_to_line_previous (const Address&,
+ int&,
+ Address&) const;
+ bool assembly_buf_line_to_addr (int, Address &) const;
+ bool get_assembly_address_range (common::Range &a) const;
+ bool move_where_marker_to_address (const Address &address,
+ bool do_scroll);
+ bool place_cursor_at_line (size_t);
+ bool place_cursor_at_address (const Address &);
+ bool set_visual_breakpoint_at_address (const Address &a_address,
+ bool enabled = true);
+ bool scroll_to_address (const Address &a_address);
- bool assembly_buf_line_to_loc (int, Address &);
/// @}
/// \name signals
diff --git a/tests/test-disassemble.cc b/tests/test-disassemble.cc
index fe256ed..e28de7d 100644
--- a/tests/test-disassemble.cc
+++ b/tests/test-disassemble.cc
@@ -37,7 +37,7 @@ using namespace nemiver::common;
using namespace std;
Glib::RefPtr<Glib::MainLoop> loop =
- Glib::MainLoop::create (Glib::MainContext::get_default ()) ;
+ Glib::MainLoop::create (Glib::MainContext::get_default ()) ;
IDebuggerSafePtr debugger;
static const char *PROG_TO_DEBUG = "./fooprog";
@@ -114,7 +114,7 @@ on_stopped_signal (IDebugger::StopReason a_reason,
return;
BOOST_REQUIRE (a_has_frame);
- MESSAGE ("current frame: '" << a_frame.function_name ().raw () << "'");
+ MESSAGE ("current frame: '" << a_frame.function_name () << "'");
if (a_frame.function_name () != "main")
return;
@@ -176,10 +176,7 @@ test_main (int, char**)
NEMIVER_CATCH_AND_RETURN_NOX (-1);
- debugger.reset ();
- loop.reset ();
-
- return 0;
+ _exit (0);
}
diff --git a/tests/test-gdbmi.cc b/tests/test-gdbmi.cc
index 42156a8..9d10de0 100644
--- a/tests/test-gdbmi.cc
+++ b/tests/test-gdbmi.cc
@@ -393,7 +393,7 @@ test_stack0 ()
BOOST_REQUIRE (call_stack[i].level () >= 0
&& call_stack[i].level () == (int) i);
BOOST_REQUIRE (!call_stack[i].function_name ().empty ());
- BOOST_REQUIRE (!call_stack[i].address ().empty ());
+ BOOST_REQUIRE (!call_stack[i].has_empty_address ());
BOOST_REQUIRE (!call_stack[i].file_name ().empty ());
BOOST_REQUIRE (!call_stack[i].file_full_name ().empty ());
BOOST_REQUIRE (call_stack[i].line ());
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]