[binutils-gdb] gdb: call target_follow_exec when "set follow-exec-mode" is "same"

Simon Marchi simark@sourceware.org
Thu May 13 19:29:58 GMT 2021


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2af87c859fe450d4a3a841cf19637a91d53c9486

commit 2af87c859fe450d4a3a841cf19637a91d53c9486
Author: Simon Marchi <simon.marchi@efficios.com>
Date:   Thu May 13 15:27:55 2021 -0400

    gdb: call target_follow_exec when "set follow-exec-mode" is "same"
    
    target_follow_exec is currently only called in the "follow-exec-mode ==
    new" branch of follow_exec, not the "follow-exec-mode == same" branch.
    I think it would make sense to call it regardless of the mode to let
    targets do some necessary handling.
    
    This is needed in the context of rocm-gdb [1], where a target is pushed
    on top of the linux-nat target.  On exec, it needs to do some
    bookkeeping, close some file descriptors / handles that were related to
    the process pre-exec and open some new ones for the process post-exec.
    
    However, by looking at the only in-tree implementation of
    target_ops::follow_exec, remote_target::follow_exec, I found that it
    would be useful for the extended-remote target too, to align its
    behavior with native debugging (although I think that behavior is not
    very user-friendly, see PR 27745 [2]).
    
    Using two programs, one (let's call it "execer") that execs the other
    (let's call it "execee"), with native:
    
        $ ./gdb -q -nx --data-directory=data-directory ./execer
        Reading symbols from ./execer...
        (gdb) r
        Starting program: /home/simark/build/binutils-gdb/gdb/execer
        I am execer
        process 1495622 is executing new program: /home/simark/build/binutils-gdb/gdb/execee
        I am execee
        [Inferior 1 (process 1495622) exited normally]
        (gdb) r
        Starting program: /home/simark/build/binutils-gdb/gdb/execee
        I am execee
        [Inferior 1 (process 1495626) exited normally]
    
    And now with gdbserver (some irrelevant output lines removed for brevity):
    
        $ ./gdbserver --once --multi :1234
        ...
    
        $ ./gdb -q -nx --data-directory=data-directory ./execer -ex "set remote exec-file /home/simark/build/binutils-gdb/gdb/execer" -ex "tar ext :1234"
        Reading symbols from ./execer...
        Remote debugging using :1234
        (gdb) r
        Starting program: /home/simark/build/binutils-gdb/gdb/execer
        process 1495724 is executing new program: /home/simark/build/binutils-gdb/gdb/execee
        [Inferior 1 (process 1495724) exited normally]
        (gdb) r
        `target:/home/simark/build/binutils-gdb/gdb/execee' has disappeared; keeping its symbols.
        Starting program: target:/home/simark/build/binutils-gdb/gdb/execee
        warning: Build ID mismatch between current exec-file target:/home/simark/build/binutils-gdb/gdb/execee
        and automatically determined exec-file target:/home/simark/build/binutils-gdb/gdb/execer
        exec-file-mismatch handling is currently "ask"
        Reading /home/simark/build/binutils-gdb/gdb/execer from remote target...
        Load new symbol table from "target:/home/simark/build/binutils-gdb/gdb/execer"? (y or n)
    
    When handling the exec, GDB updates the exec-file of the inferior to be
    the execee.  This means that a subsequent "run" will run the execee, not
    the original executable (execer).
    
    remote_target::follow_exec is meant to update the "remote exec-file",
    which is the file on the remote system that will be executed if you
    "run" the inferior, to the execee as well.  However, this is not called
    when follow-exec-mode is same, because target_follow_exec is not called
    in this branch.  As a result, GDB thinks the inferior is executing
    execee but the remote side is really executing execer, hence the
    mismatch message.
    
    By calling target_follow_exec in the "same" branch of the follow_exec
    function, we ensure that everybody agrees, and we get the same behavior
    with the extended-remote target as we get with the native target, the
    execee is executed on the second run:
    
        $ ./gdbserver --once --multi :1234
        ...
    
        $ ./gdb -q -nx --data-directory=data-directory ./execer -ex "set remote exec-file /home/simark/build/binutils-gdb/gdb/execer" -ex "tar ext :1234"
        Reading symbols from ./execer...
        Remote debugging using :1234
        (gdb) r
        Starting program: /home/simark/build/binutils-gdb/gdb/execer
        process 1501445 is executing new program: /home/simark/build/binutils-gdb/gdb/execee
        [Inferior 1 (process 1501445) exited normally]
        (gdb) r
        `target:/home/simark/build/binutils-gdb/gdb/execee' has disappeared; keeping its symbols.
        Starting program: target:/home/simark/build/binutils-gdb/gdb/execee
        [Inferior 1 (process 1501447) exited normally]
        (gdb)
    
    This scenario is tested in gdb.base/foll-exec-mode.exp, and in fact this
    patch fixes the test for me when using
    --target_board=native-extended-gdbserver.
    
    gdb/ChangeLog:
    
            * infrun.c (follow_exec): Call target_follow_fork when
            follow-exec-mode is same.
            * target.h (target_follow_fork): Improve doc.
    
    [1] https://github.com/ROCm-Developer-Tools/ROCgdb
    [2] https://sourceware.org/bugzilla/show_bug.cgi?id=27745
    
    Change-Id: I4ee84a875e39bf3f8eaf3e6789a4bfe23a2a430e

Diff:
---
 gdb/ChangeLog | 6 ++++++
 gdb/infrun.c  | 1 +
 gdb/target.h  | 7 +++++--
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index de66783dd26..f0ae77e1218 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2021-05-13  Simon Marchi  <simon.marchi@efficios.com>
+
+	* infrun.c (follow_exec): Call target_follow_fork when
+	follow-exec-mode is same.
+	* target.h (target_follow_fork): Improve doc.
+
 2021-05-13  Simon Marchi  <simon.marchi@polymtl.ca>
 
 	* cli/cli-decode.h (struct cmd_list_element) <pre_show_hook>:
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 90bab8d984f..3e386aa587c 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1198,6 +1198,7 @@ follow_exec (ptid_t ptid, const char *exec_file_target)
 	 around (its description is later cleared/refetched on
 	 restart).  */
       target_clear_description ();
+      target_follow_exec (inf, exec_file_target);
     }
 
   gdb_assert (current_program_space == inf->pspace);
diff --git a/gdb/target.h b/gdb/target.h
index 48bf734279a..b80cf88db81 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -1714,8 +1714,11 @@ extern int target_remove_vfork_catchpoint (int pid);
 
 void target_follow_fork (bool follow_child, bool detach_fork);
 
-/* Handle the target-specific bookkeeping required when the inferior
-   makes an exec call.  INF is the exec'd inferior.  */
+/* Handle the target-specific bookkeeping required when the inferior makes an
+   exec call.  The current inferior is the inferior that has executed the exec
+   call.  INF is the inferior in which execution continues post-exec.  It is the
+   same inferior as the current one if "follow-exec-mode" is "same" but is a new
+   one if "follow-exec-mode" is "new".  */
 
 void target_follow_exec (struct inferior *inf, const char *execd_pathname);


More information about the Gdb-cvs mailing list