[PATCH] 697992 - fail to restart a program wrapped in libtool shell script



Hello,

This bug happens when the user is debugging a program that is wrapped
in a libtool shell script.  That is, she does:

 nemiver foo

but foo is a libtool wrapper script, rather than the real binary.  These
beasts are usually generated by libtool when you use it e.g, coupled
with autoconf and automake.

In that case, Nemiver issues the command:

 libtool --mode=execute gdb foo

Libtool then spawns a GDB process with the path to the real binary
wrapped by the foo shell script.  That might be someting like:

    .libs/lt-foo.

Now when the user modifies the source code of foo, and then type
'make' again, it happens that the autotools machinery removes the
.libs/lt-foo binary.  So when the user asks for the a restart of the
foo in Nemiver, the debugger tries asks GDB to restart .libs/lt-foo,
and then gets lost as the .libs/lt-foo got removed.

I believe the Right Thing To Do ™ in that case is for Nemiver to issue
a:

 libtool --mode=execute gdb foo

again.

This is in essence what this patch does.

Tested on my Fedora 18 and applied to master.

        * src/dbgengine/nmv-gdb-engine.cc (GDBEngine::load_program):  When
        asked about a forced re-load, always launch a new GDB.  This
        allows to re-ask libtool to launch the gdb for us, on libtool
        wrapper scripts.  Add logs for this case.
        * src/persp/dbgperspective/nmv-dbg-perspective.cc
        (DBGPerspective::Priv::last_prog_path_requested): New data member.
        (DBGPerspective::restart_local_inferior): Re-launch a debugger
        engine upon re-starts of a libtool wrapper.  Make sure to ask the
        restart on the libtool wrapper, not on the its underlying binary
        that might have been wiped out by a re-build.
        (DBGPerspective::execute_program): Likewise, make sure to ask the
        restart on the libtool wrapper, not on the its underlying binary
        that might have been wiped out by a re-build.  Also, set the new
        DBGPerspective::Priv::last_prog_path_requested data member to the
        path to of the program which the user wants to debug.
---
 src/dbgengine/nmv-gdb-engine.cc                 |  5 +++-
 src/persp/dbgperspective/nmv-dbg-perspective.cc | 32 +++++++++++++++++++++----
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 3286a12..7a05690 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -3195,7 +3195,10 @@ GDBEngine::load_program (const UString &a_prog,
     THROW_IF_FAIL (!a_prog.empty ());
     vector<UString> argv (a_argv);
 
-    if (!m_priv->is_gdb_running ()) {
+    bool is_gdb_running = m_priv->is_gdb_running();
+    LOG_DD ("force: " << a_force << ", is_gdb_running: " << is_gdb_running);
+    if (a_force || !is_gdb_running) {
+        LOG_DD("Launching a fresh GDB");
         vector<UString> gdb_opts;
 
         // Read the tty attributes before we launch the target so that
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index bb9861d..d9760a9 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -53,6 +53,7 @@
 #include "common/nmv-str-utils.h"
 #include "common/nmv-address.h"
 #include "common/nmv-loc.h"
+#include "common/nmv-proc-utils.h"
 #include "nmv-sess-mgr.h"
 #include "nmv-dbg-perspective.h"
 #include "nmv-source-editor.h"
@@ -857,6 +858,15 @@ struct DBGPerspective::Priv {
     // A Flag to know if the debugging
     // engine died or not.
     bool debugger_engine_alive;
+    // The path to the program the user requested a debugging session
+    // for.
+    UString last_prog_path_requested;
+    // The path to the binary that is actually being debugged.  This
+    // can be different from last_prog_path_requested above, e.g, when
+    // the user asked to debug a libtool wrapper shell script.  In
+    // that case, this data member eventually contains the path to the
+    // real underlying binary referred to by the libtool wrapper shell
+    // script.
     UString prog_path;
     vector<UString> prog_args;
     UString prog_cwd;
@@ -5900,8 +5910,21 @@ DBGPerspective::restart_local_inferior ()
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
     THROW_IF_FAIL (!is_connected_to_remote_target ());
-    
-    if (debugger ()->is_attached_to_target ()
+
+    if (// If the program the user asked is a libtool wrapper shell
+        // script, then the real program we are debugging is at a
+        // different path from the (libtool shell script) path
+        // requested by the user.  So we cannot just ask the debugger
+        // to re-run the binary it's current running, as libtool can
+        // have changed changed the path to the underlying real
+        // binary.  This can happen, e.g, when the user re-compiled
+        // the program she is debugging and then asks for a re-start
+        // of the inferior in Nemiver.  In that case, libtool might
+        // have changed the real binary path name.
+        !is_libtool_executable_wrapper(m_priv->last_prog_path_requested)
+        // If we are not attached to the target, there is not debugger
+        // engine to ask a re-run to ...
+        && debugger ()->is_attached_to_target ()
         // Make sure we are restarting the program we were running
         // right before. We need to make sure because the user can
         // have changed the path to the inferior and ask for a
@@ -5914,7 +5937,7 @@ DBGPerspective::restart_local_inferior ()
              (*this, &DBGPerspective::on_debugger_inferior_re_run_signal));
     } else {
         vector<IDebugger::Breakpoint> bps;
-        execute_program (m_priv->prog_path, m_priv->prog_args,
+        execute_program (m_priv->last_prog_path_requested, m_priv->prog_args,
                          m_priv->env_variables, m_priv->prog_cwd,
                          bps,
                          true /* be aware we are restarting the same inferior*/,
@@ -6029,7 +6052,7 @@ DBGPerspective::execute_program
     // In that case, we might want to keep things like breakpoints etc,
     // around.
     bool is_new_program = a_restarting
-        ? (prog != m_priv->prog_path)
+        ? (prog != m_priv->last_prog_path_requested)
         : true;
     LOG_DD ("is new prog: " << is_new_program);
 
@@ -6097,6 +6120,7 @@ DBGPerspective::execute_program
     if (a_break_in_main_run)
         run_real (a_restarting);
 
+    m_priv->last_prog_path_requested = prog;
     m_priv->prog_path = prog;
     m_priv->prog_args = a_args;
     m_priv->prog_cwd = a_cwd;
-- 
                Dodji


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