[nemiver] fuzzy address search when looking from insns



commit b3214874acd8a2129d9f04d1c7183d3b5e9fb634
Author: Dodji Seketeli <dodji redhat com>
Date:   Mon Sep 6 13:44:47 2010 +0200

    fuzzy address search when looking from insns
    
    	* src/uicommon/nmv-source-editor.h (assembly_buf_addr_to_line):
    	Add a bool to approximate the address we were asked for, when
    	needed.
    	(scroll_to_address): Likewise.
    	* src/uicommon/nmv-source-editor.cc
    	(SourceEditor::Priv::get_smallest_range_containing_address):
    	Return range values even when the result is not
    	common::Range::VALUE_SEARCH_RESULT_EXACT. Add comment.
    	(assembly_buf_addr_to_line): Add a bool to approximate the address
    	we were asked for, when needed. Add comment.
    	(scroll_to_address): Likewise.
    	(move_where_marker_to_address): Likewise.
    	(remove_visual_breakpoint_from_address): Adapt to
    	assembly_buf_addr_to_line change.
    	(set_visual_breakpoint_at_address): Likewise.
    	(place_cursor_at_address): Likewise.
    	* src/persp/dbgperspective/nmv-dbg-perspective.cc (set_where):
    	Add a bool to approximate the address to set the
    	where pointer to in case the IP address isn't present in the
    	assembly.
    	(apply_decorations_to_asm): Likewise. Propagate the address
    	approximation request to set_where.
    	(switch_to_asm): Likewise. Use apply_decorations_to_asm directly instead of
    	apply_decoration. Propage the address approximation request.
    	(create_source_editor): Adapt to the change in
    	SourceEditor::assembly_buf_addr_to_line.
    	(on_breakpoint_go_to_source_action): Adapt to the change in
    	SourceEditor::scroll_to_address.
    	(on_debugger_asm_signal2, on_debugger_asm_signal3)
    	(on_debugger_asm_signal4): When we received the asm from the
    	engine, approximate the IP address when decorating or scrolling to
    	the instructions. This should hopefully prevent us -- in a robust
    	way -- from infinite recursion when the IP address is not present
    	in the asm. Why the IP address is not present in the asm will be
    	something to address in the engine. In the mean time we must be
    	liberal in what we accept.
    	(pump_asm_including_address): Pass the address by reference.

 src/persp/dbgperspective/nmv-dbg-perspective.cc |   74 +++++++++++++-------
 src/uicommon/nmv-source-editor.cc               |   85 +++++++++++++++++++----
 src/uicommon/nmv-source-editor.h                |    8 ++-
 3 files changed, 123 insertions(+), 44 deletions(-)
---
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 64c9f94..c68297c 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -544,10 +544,11 @@ public:
 
     void switch_to_asm (const common::DisassembleInfo &a_info,
                         const std::list<common::Asm> &a_asm,
-                        SourceEditor *a_editor);
+                        SourceEditor *a_editor,
+                        bool a_approximate_where = false);
 
     void pump_asm_including_address (SourceEditor *a_editor,
-                                     const Address a_address);
+                                     const Address &a_address);
 
     void switch_to_source_code ();
 
@@ -689,7 +690,8 @@ public:
     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);
+                                   bool a_scroll_to_where_marker = false,
+                                   bool a_approximate_where = false);
 
     IDebuggerSafePtr& debugger ();
 
@@ -780,7 +782,8 @@ public:
     bool set_where (SourceEditor *a_editor,
                     const Address &a_address,
                     bool a_do_scroll = true,
-                    bool a_try_hard = false);
+                    bool a_try_hard = false,
+                    bool a_approximate_where = false);
 
     void unset_where ();
 
@@ -1690,7 +1693,8 @@ DBGPerspective::on_breakpoint_go_to_source_action
                 break;
             case SourceEditor::BUFFER_TYPE_ASSEMBLY:
                 if (source_editor->scroll_to_address
-                    (a_breakpoint.address ()) == false)
+                    (a_breakpoint.address (),
+                     /*approximate=*/false) == false)
                     source_editor = 0;
                 break;
             case SourceEditor::BUFFER_TYPE_UNDEFINED:
@@ -2628,11 +2632,12 @@ DBGPerspective::on_debugger_asm_signal2
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
-    NEMIVER_TRY
-
-    switch_to_asm (a_info, a_instrs, a_editor);
+    NEMIVER_TRY;
 
-    NEMIVER_CATCH
+    switch_to_asm (a_info, a_instrs, a_editor,
+                   /*a_approximate_where=*/ true);
+    
+    NEMIVER_CATCH;
 }
 
 void
@@ -2644,12 +2649,14 @@ DBGPerspective::on_debugger_asm_signal3
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
-    NEMIVER_TRY
+    NEMIVER_TRY;
 
-    switch_to_asm (a_info, a_instrs, a_editor);
-    append_visual_breakpoint (a_editor, a_bp.address (), a_bp.line ());
+    switch_to_asm (a_info, a_instrs, a_editor,
+                   /*a_approximate_where=*/true);
+    append_visual_breakpoint (a_editor, a_bp.address (),
+                              a_bp.line ());
 
-    NEMIVER_CATCH
+    NEMIVER_CATCH;
 }
 
 void
@@ -2665,7 +2672,8 @@ DBGPerspective::on_debugger_asm_signal4
     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);
+    editor->scroll_to_address (a_address,
+                               /*approximate=*/true);
 
     NEMIVER_CATCH
 }
@@ -4461,7 +4469,8 @@ bool
 DBGPerspective::set_where (SourceEditor *a_editor,
                            const Address &a_address,
                            bool a_do_scroll,
-                           bool a_try_hard)
+                           bool a_try_hard,
+                           bool a_approximate)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
@@ -4476,7 +4485,8 @@ DBGPerspective::set_where (SourceEditor *a_editor,
     // 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_editor->move_where_marker_to_address (a_address, a_do_scroll,
+                                                 a_approximate)) {
         if (a_try_hard) {
             pump_asm_including_address (a_editor, a_address);
             return true;
@@ -5279,6 +5289,7 @@ DBGPerspective::create_source_editor (Glib::RefPtr<SourceBuffer> &a_source_buf,
         if (!a_current_address.empty ()) {
             source_editor->assembly_buf_addr_to_line
                                 (Address (a_current_address.raw ()),
+                                 /*approximate=*/false,
                                  current_line);
         }
     } else {
@@ -5542,14 +5553,22 @@ DBGPerspective::switch_to_asm (const common::DisassembleInfo &a_info,
     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.
+/// 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.
+/// \param a_source_editor the source editor to switch into asm mode.
+/// \param a_approximate_where if true and if the current instruction
+/// pointer's address is missing from the list of asm instructions,
+/// try set the where marker to the closest address that comes right
+/// after the instruction pointer's address. Otherwise, try to
+/// disassemble and pump in more asm instructions whose addresses will
+/// likely contain the one of the instruction pointer.
 void
 DBGPerspective::switch_to_asm (const common::DisassembleInfo &a_info,
                                const std::list<common::Asm> &a_asm,
-                               SourceEditor *a_source_editor)
+                               SourceEditor *a_source_editor,
+                               bool a_approximate_where)
 {
     if (!a_source_editor)
         return;
@@ -5576,13 +5595,14 @@ DBGPerspective::switch_to_asm (const common::DisassembleInfo &a_info,
         return;
     }
     a_source_editor->current_line (-1);
-    apply_decorations (a_source_editor,
-                       /*scroll_to_where_marker=*/true);
+    apply_decorations_to_asm (a_source_editor,
+                              /*scroll_to_where_marker=*/true,
+                              a_approximate_where);
 }
 
 void
 DBGPerspective::pump_asm_including_address (SourceEditor *a_editor,
-                                            const Address a_address)
+                                            const Address &a_address)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
@@ -6739,7 +6759,8 @@ DBGPerspective::apply_decorations_to_source (SourceEditor *a_editor,
 
 bool
 DBGPerspective::apply_decorations_to_asm (SourceEditor *a_editor,
-                                          bool a_scroll_to_where_marker)
+                                          bool a_scroll_to_where_marker,
+                                          bool a_approximate_where)
 {
     if (a_editor == 0)
         return false;
@@ -6787,7 +6808,8 @@ DBGPerspective::apply_decorations_to_asm (SourceEditor *a_editor,
         set_where (a_editor,
                    m_priv->current_frame.address (),
                    a_scroll_to_where_marker,
-                   /*try_hard=*/true);
+                   /*try_hard=*/true,
+                   a_approximate_where);
     return true;
 }
 
diff --git a/src/uicommon/nmv-source-editor.cc b/src/uicommon/nmv-source-editor.cc
index fe8ca21..b471b19 100644
--- a/src/uicommon/nmv-source-editor.cc
+++ b/src/uicommon/nmv-source-editor.cc
@@ -332,9 +332,27 @@ struct SourceEditor::Priv {
         return 0;
     }
 
-    typedef std::pair<Address, int> AddrLine;
+    typedef std::pair<Address, size_t> AddrLine;
     typedef std::pair<AddrLine, AddrLine> AddrLineRange;
 
+    /// Return the smallest range of address/line pair enclosing the
+    /// instruction whose address is an_addr.
+    /// \param a_buf the buffer to look into.
+    /// \param an_addr the address of the instruction to look for.
+    /// \param a_range output parameter. the range found.
+    /// This range either encloses
+    /// an_addr if such a range is found, or is the range (possibly
+    /// reduced to a single value) that comes after or before an_addr
+    /// if no enclosing range is found in the buffer for an_addr.
+    /// \return Range::VALUE_SEARCH_RESULT_EXACT If an instruction which
+    /// address is an_addr is found; Range::VALUE_SEARCH_RESULT_BEFORE
+    /// if an_addr is smaller than all the addresses of a_buf. In
+    /// that case, the smaller address of a_buf is returned into
+    /// a_range; Range::VALUE_SEARCH_RESULT_AFTER if an_addr is higher
+    /// than all addresses found in the buffer. In that case the
+    /// higher address found in a_buf is returned into a_range;
+    /// Range::VALUE_SEARCH_RESULT_NONE when no address has been found
+    /// in the buffer.
     common::Range::ValueSearchResult
     get_smallest_range_containing_address (Glib::RefPtr<SourceBuffer> a_buf,
                                            const Address &an_addr,
@@ -374,6 +392,9 @@ struct SourceEditor::Priv {
                     // an_addr without having ever seen an @ that is
                     // lower than an_addr.  That means all the @s of
                     // the buffer are greater than an_addr.
+                    a_range.first.first = addr;
+                    a_range.first.second = it.get_line () + 1;
+                    a_range.second = a_range.first;
                     return common::Range::VALUE_SEARCH_RESULT_BEFORE;
                 } else {
                     // So the previous @ we saw was lower than
@@ -401,18 +422,32 @@ struct SourceEditor::Priv {
         }
 
         if (!lower_bound.first.empty ()) {
-            if (upper_bound.first.empty ())
+            if (upper_bound.first.empty ()) {
+                a_range.first.first = lower_bound.first;
+                a_range.second = a_range.first;
                 return common::Range::VALUE_SEARCH_RESULT_AFTER;
-            else
+            } else {
                 THROW ("unreachable");
+            }
         }
          
         return common::Range::VALUE_SEARCH_RESULT_NONE;
     }
 
+    /// Return the number of the line in a_buf that contains an asm
+    /// instruction of whose address is an_addr.
+    /// \param a_buf the buffer to search into
+    /// \param an_addr the address of the instruction to look for.
+    /// \param a_approximate if true and if an_addr hasn't been found
+    /// in the buffer, return the line that matches the closes address
+    /// found.
+    /// \param a_line output parameter. Is set to the line found, iff
+    /// the function returns true. Otherwise this parameter is not touched.
+    /// \return true upon successful completion, false otherwise.
     bool
     address_2_line (Glib::RefPtr<SourceBuffer> a_buf,
 		    const Address an_addr,
+                    bool a_approximate,
 		    int &a_line) const
     {
         if (!a_buf)
@@ -422,9 +457,15 @@ struct SourceEditor::Priv {
         common::Range::ValueSearchResult s =
             get_smallest_range_containing_address (a_buf, an_addr, range);
 
-        if (s == common::Range::VALUE_SEARCH_RESULT_EXACT
-            || s == common::Range::VALUE_SEARCH_RESULT_WITHIN) {
-            a_line = range.second.second;
+        if (s == common::Range::VALUE_SEARCH_RESULT_EXACT) {
+            a_line = range.first.second;
+            return true;
+        }
+
+        if (a_approximate
+            && (s == common::Range::VALUE_SEARCH_RESULT_WITHIN
+                || s == common::Range::VALUE_SEARCH_RESULT_BEFORE)) {
+            a_line = range.first.second;
             return true;
         }
         return false;
@@ -1495,7 +1536,7 @@ 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))
+    if (!assembly_buf_addr_to_line (a_address, false, line))
         return false;
     return set_visual_breakpoint_at_line (line, a_enabled);
 
@@ -1510,16 +1551,21 @@ bool
 SourceEditor::remove_visual_breakpoint_from_address (const Address &a_address)
 {
     int line = -1;
-    if (!assembly_buf_addr_to_line (a_address, line))
+    if (!assembly_buf_addr_to_line (a_address, false, line))
         return false;
     return remove_visual_breakpoint_from_line (line);
 }
 
+/// Scroll the instruction which address is specified.
+/// \param a_address the instruction which address to scroll to.
+/// \param a_approximate if true and if the a_address hasn't been
+/// found in the buffer, scroll to the closes address found.
 bool
-SourceEditor::scroll_to_address (const Address &a_address)
+SourceEditor::scroll_to_address (const Address &a_address,
+                                 bool a_approximate)
 {
     int line = -1;
-    if (!assembly_buf_addr_to_line (a_address, line))
+    if (!assembly_buf_addr_to_line (a_address, a_approximate, line))
         return false;
     return scroll_to_line (line);
 }
@@ -1561,11 +1607,19 @@ SourceEditor::switch_to_non_assembly_source_buffer ()
     return false;
 }
 
+/// Give the source line number at which an asm instruction of a given
+/// address is.
+/// \param a_address the address of the asm instruction to look for.
+/// \param a_approximate if true and if the a_addr hasn't been found
+/// in the the buffer, then return the closest address
+/// found. Otherwise, pretend the we haven't found the address.
 bool
-SourceEditor::assembly_buf_addr_to_line (const Address &a_addr, int &a_line) const
+SourceEditor::assembly_buf_addr_to_line (const Address &a_addr,
+                                         bool a_approximate,
+                                         int &a_line) const
 {
     Glib::RefPtr<SourceBuffer> buf = get_assembly_source_buffer ();
-    return m_priv->address_2_line (buf, a_addr, a_line);
+    return m_priv->address_2_line (buf, a_addr, a_approximate, a_line);
 }
 
 bool
@@ -1592,10 +1646,11 @@ SourceEditor::get_assembly_address_range (Range &a) const
 
 bool
 SourceEditor::move_where_marker_to_address (const Address &a_address,
-                                            bool a_do_scroll)
+                                            bool a_do_scroll,
+                                            bool a_approximate)
 {
     int line = -1;
-    if (!assembly_buf_addr_to_line (a_address, line)) {
+    if (!assembly_buf_addr_to_line (a_address, a_approximate, line)) {
         return false;
     }
     return move_where_marker_to_line (line, a_do_scroll);
@@ -1622,7 +1677,7 @@ 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))
+    if (!assembly_buf_addr_to_line (a_address, false, line))
         return false;
     return place_cursor_at_line (line);
 
diff --git a/src/uicommon/nmv-source-editor.h b/src/uicommon/nmv-source-editor.h
index 0c3f2c9..a8453bd 100644
--- a/src/uicommon/nmv-source-editor.h
+++ b/src/uicommon/nmv-source-editor.h
@@ -153,17 +153,19 @@ public:
 
     bool switch_to_non_assembly_source_buffer ();
 
-    bool assembly_buf_addr_to_line (const Address&, int&) const;
+    bool assembly_buf_addr_to_line (const Address&, bool, int&) 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 do_scroll,
+				       bool a_approximate);
     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 remove_visual_breakpoint_from_address (const Address &);
-    bool scroll_to_address (const Address &a_address);
+    bool scroll_to_address (const Address &a_address,
+			    bool a_approximate);
 
     static bool add_asm (const common::DisassembleInfo &/*a_info*/,
 			 const std::list<common::Asm> &a_asm,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]