This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: attach to a PID using a different exec


Sometimes I will start gdb like "gdb /some/path/to/gdb" and then
"attach PID" -- where PID is actually running "/some/other/gdb".
That is, the current exec file and the attached process disagree.

Right now this usually yields an error along the lines of:
"Cannot access memory at address 0x2e".

This patch changes gdb to look at the target's notion of the exec
file, and then switch to it if it differs from the current exec.

I looked a little and didn't see an existing "are these two files 'the
same'" predicate in gdb, so I just compare the real paths.

Built and regtested on x86-64 (compile farm).
New test included -- it fails before the patch and passes after it.

Please review.

thanks,
Tom

2008-11-13  Tom Tromey  <tromey@redhat.com>

	* infcmd.c (attach_command_post_wait): Compare current exec file
	with target's exec file.

2008-11-13  Tom Tromey  <tromey@redhat.com>

	* gdb.base/attach.exp (do_attach_tests): Test attaching to a PID
	using a different exec file.

diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index b3af31f..2efdd14 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2114,37 +2114,63 @@ proceed_after_attach (int pid)
 static void
 attach_command_post_wait (char *args, int from_tty, int async_exec)
 {
-  char *exec_file;
-  char *full_exec_path = NULL;
+  char *exec_file, *targ_exec_file;
+  char *full_targ_exec_path = NULL;
   struct inferior *inferior;
+  int must_attach;
 
   inferior = current_inferior ();
   inferior->stop_soon = NO_STOP_QUIETLY;
 
-  /* If no exec file is yet known, try to determine it from the
-     process itself.  */
+  /* Figure out what to do about the exec.  There are four cases to
+     consider -- we may or may not have a current exec file, and the
+     target may or may not be able to determine the exec file of the
+     attached process.  */
   exec_file = (char *) get_exec_file (0);
-  if (!exec_file)
+
+  /* Get the target's notion of the current exec.  */
+  targ_exec_file = target_pid_to_exec_file (PIDGET (inferior_ptid));
+  if (targ_exec_file)
     {
-      exec_file = target_pid_to_exec_file (PIDGET (inferior_ptid));
-      if (exec_file)
+      /* It's possible we don't have a full path, but rather just a
+	 filename.  Some targets, such as HP-UX, don't provide the
+	 full path, sigh.
+
+	 Attempt to qualify the filename against the source path.
+	 (If that fails, we'll just fall back on the original
+	 filename.  Not much more we can do...)
+      */
+      if (!source_full_path_of (targ_exec_file, &full_targ_exec_path))
+	full_targ_exec_path = xstrdup (targ_exec_file);
+    }
+
+  must_attach = 0;
+  /* If the target knows the exec, check to see if it matches our
+     current exec.  */
+  if (full_targ_exec_path)
+    {
+      /* If we don't have a current exec, just go with what the target
+	 reported.  */
+      if (!exec_file)
+	must_attach = 1;
+      else
 	{
-	  /* It's possible we don't have a full path, but rather just a
-	     filename.  Some targets, such as HP-UX, don't provide the
-	     full path, sigh.
-
-	     Attempt to qualify the filename against the source path.
-	     (If that fails, we'll just fall back on the original
-	     filename.  Not much more we can do...)
-	   */
-	  if (!source_full_path_of (exec_file, &full_exec_path))
-	    full_exec_path = savestring (exec_file, strlen (exec_file));
-
-	  exec_file_attach (full_exec_path, from_tty);
-	  symbol_file_add_main (full_exec_path, from_tty);
+	  char *real_path = gdb_realpath (exec_file);
+	  char *targ_real_path = gdb_realpath (full_targ_exec_path);
+	  must_attach = strcmp (real_path, targ_real_path) != 0;
+	  if (!must_attach)
+	    xfree (full_targ_exec_path);
+	  xfree (real_path);
+	  xfree (targ_real_path);
 	}
     }
-  else
+
+  if (must_attach)
+    {
+      exec_file_attach (full_targ_exec_path, from_tty);
+      symbol_file_add_main (full_targ_exec_path, from_tty);
+    }
+  else if (exec_file)
     {
       reopen_exec_file ();
       reread_symbols ();
@@ -2163,7 +2189,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
       /* The user requested an `attach&', so be sure to leave threads
 	 that didn't get a signal running.  */
 
-      /* Immediatelly resume all suspended threads of this inferior,
+      /* Immediately resume all suspended threads of this inferior,
 	 and this inferior only.  This should have no effect on
 	 already running threads.  If a thread has been stopped with a
 	 signal, leave it be.  */
diff --git a/gdb/testsuite/gdb.base/attach.exp b/gdb/testsuite/gdb.base/attach.exp
index 4529715..fd59c0f 100644
--- a/gdb/testsuite/gdb.base/attach.exp
+++ b/gdb/testsuite/gdb.base/attach.exp
@@ -48,6 +48,7 @@ set srcfile2 ${testfile}2.c
 set binfile  ${objdir}/${subdir}/${testfile}
 set binfile2 ${objdir}/${subdir}/${testfile}2
 set escapedbinfile  [string_to_regexp ${objdir}/${subdir}/${testfile}]
+set escapedbinfile2 [string_to_regexp ${objdir}/${subdir}/${testfile}2]
 
 #execute_anywhere "rm -f ${binfile} ${binfile2}"
 remote_exec build "rm -f ${binfile} ${binfile2}"
@@ -75,8 +76,8 @@ if [get_compiler_info ${binfile}] {
 
 proc do_attach_tests {} {
     global gdb_prompt
-    global binfile
-    global escapedbinfile
+    global binfile binfile2
+    global escapedbinfile escapedbinfile2
     global srcfile
     global testfile
     global objdir
@@ -313,7 +314,53 @@ proc do_attach_tests {} {
 	"Attaching to process $testpid.*Reading symbols from $escapedbinfile.*main.*at .*" \
 	"attach when process' a.out not in cwd"
 
-    set test "after attach3, exit"
+    # Detach the process.
+   
+    gdb_test "detach" \
+	"Detaching from program: .*$escapedbinfile, process $testpid" \
+	"before attach4, detach"
+
+    # Wait a bit for gdb to finish detaching
+    
+    exec sleep 5
+
+    # Use symbols from one file, then attach to a process executing
+    # from another file.
+    gdb_test "file $binfile2" \
+	"Reading symbols from $escapedbinfile2\.\.\.*done." \
+	"attach4, select binfile2" \
+	"Load new symbol table from .*? .y or n. " \
+	"y"
+
+    set test "attach to PID using different exec"
+    send_gdb "attach $testpid\n"
+    gdb_expect {
+	-re "Attaching to program.*, process $testpid.*Load new symbol table from \"$escapedbinfile\".*y or n. $" {
+	    send_gdb "y\n"
+	    gdb_expect {
+		-re "main.*at.*$srcfile:.*$gdb_prompt $" {
+		    pass "$test"
+		}
+		-re "$gdb_prompt $" {
+		    fail "$test"
+		}
+		timeout {
+		    fail "$test (timeout)"
+		}
+	    }
+	}
+	-re "Attaching to program.*, process $testpid.*Cannot access memory at .*$" {
+	    fail "$test"
+	}
+	-re "Attaching to program.*, process $testpid.*$gdb_prompt $" {
+	    fail "$test"
+	}
+	timeout {
+	    fail "$test (timeout)"
+	}
+    }
+
+    set test "after attach4, exit"
     gdb_test_multiple "kill" "$test" {
 	-re "Kill the program being debugged.*y or n. $" {
 	    gdb_test "y" "" "$test"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]