From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7746 invoked by alias); 13 Nov 2008 19:19:02 -0000 Received: (qmail 7599 invoked by uid 22791); 13 Nov 2008 19:19:01 -0000 X-Spam-Check-By: sourceware.org Received: from mx2.redhat.com (HELO mx2.redhat.com) (66.187.237.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 13 Nov 2008 19:18:25 +0000 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id mADJINYf030748 for ; Thu, 13 Nov 2008 14:18:23 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id mADJIMb6004064; Thu, 13 Nov 2008 14:18:22 -0500 Received: from opsy.redhat.com (vpn-13-92.rdu.redhat.com [10.11.13.92]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id mADJILrD005011; Thu, 13 Nov 2008 14:18:21 -0500 Received: by opsy.redhat.com (Postfix, from userid 500) id B22843786E3; Thu, 13 Nov 2008 12:18:20 -0700 (MST) To: gdb-patches@sourceware.org Subject: RFA: attach to a PID using a different exec From: Tom Tromey Reply-To: tromey@redhat.com X-Attribution: Tom Date: Thu, 13 Nov 2008 22:32:00 -0000 Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-11/txt/msg00293.txt.bz2 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 * infcmd.c (attach_command_post_wait): Compare current exec file with target's exec file. 2008-11-13 Tom Tromey * 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"