RFA: attach to a PID using a different exec

Michael Snyder msnyder@vmware.com
Fri Nov 14 00:54:00 GMT 2008


No way should we do this without asking.
It's just as possible that the first file was the one
the user wanted, and the one attached to was a mistake.

Tom Tromey wrote:
> 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"



More information about the Gdb-patches mailing list