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
This commit is contained in:
Simon Marchi 2021-05-13 15:27:55 -04:00 committed by Simon Marchi
parent bab9eb490b
commit 2af87c859f
3 changed files with 12 additions and 2 deletions

View file

@ -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>:

View file

@ -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);

View file

@ -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);