Re: [PATCH] Make only user-specified executable filenames sticky

Don Breazeal
2015-05-11T17:14:11Z

On 5/6/2015 3:26 AM, Gary Benson wrote:
> Hi all,
>
> In GDB some executable files are supplied by the user (e.g. using a
> "file" command) and some are determined by GDB (e.g. while processing
> an "attach" command). GDB will not attempt to determine a filename if
> one has been set. This causes problems if you attach to one process
> and then attach to another: GDB will not attempt to discover the main
> executable on the second attach. If the two processes have different
> main executable files then the symbols will now be wrong.
>
> This commit updates GDB to keep track of which executable filenames
> were supplied by the user. When GDB might attempt to determine an
> executable filename and one is already set, filenames determined by
> GDB may be overridden but user-supplied filenames will not.
>
> Built and regtested on RHEL6.6 x86_64.
>
> Is this ok to commit?
>
> Cheers,
> Gary
>
>
> gdb/ChangeLog:
>
> * progspace.h (struct program_space)
> <pspace_user_supplied_exec_file_p>: New field.
> * exec.h (user_supplied_exec_file_p): New macro.
> * exec.c (exec_close): Clear user_supplied_exec_file_p.
> (exec_file_locate_attach): Remove get_exec_file check.
> (exec_file_command): Set user_supplied_exec_file_p.
> * inferior.c (add_inferior_command): Likewise.
> * main.c (captured_main): Likewise.
> * infcmd.c (attach_command_post_wait): Always try and
> locate main executable if !user_supplied_exec_file_p.
> * remote.c (remote_add_inferior): Likewise.
> ---
> gdb/ChangeLog | 14 ++++++++++++++
> gdb/exec.c | 7 ++-----
> gdb/exec.h | 2 ++
> gdb/infcmd.c | 12 +++++++-----
> gdb/inferior.c | 1 +
> gdb/main.c | 16 +++++++++++-----
> gdb/progspace.h | 7 +++++++
> gdb/remote.c | 7 ++++---
> 8 files changed, 48 insertions(+), 18 deletions(-)
>
> diff --git a/gdb/exec.c b/gdb/exec.c
> index 8a4ab6f..278df83 100644
> --- a/gdb/exec.c
> +++ b/gdb/exec.c
> @@ -102,6 +102,7 @@ exec_close (void)
>
> xfree (exec_filename);
> exec_filename = NULL;
> + user_supplied_exec_file_p = 0;
> }
> }
>
> @@ -142,11 +143,6 @@ exec_file_locate_attach (int pid, int from_tty)
> {
> char *exec_file, *full_exec_path = NULL;
>
> - /* Do nothing if we already have an executable filename. */
> - exec_file = (char *) get_exec_file (0);
> - if (exec_file != NULL)
> - return;
> -
> /* Try to determine a filename from the process itself. */
> exec_file = target_pid_to_exec_file (pid);
> if (exec_file == NULL)
> @@ -376,6 +372,7 @@ exec_file_command (char *args, int from_tty)
> filename = tilde_expand (*argv);
> make_cleanup (xfree, filename);
> exec_file_attach (filename, from_tty);
> + user_supplied_exec_file_p = 1;
>
> do_cleanups (cleanups);
> }
> diff --git a/gdb/exec.h b/gdb/exec.h
> index c7f3b56..3794aba 100644
> --- a/gdb/exec.h
> +++ b/gdb/exec.h
> @@ -32,6 +32,8 @@ struct objfile;
> #define exec_bfd current_program_space->ebfd
> #define exec_bfd_mtime current_program_space->ebfd_mtime
> #define exec_filename current_program_space->pspace_exec_filename
> +#define user_supplied_exec_file_p \
> + current_program_space->pspace_user_supplied_exec_file_p
>
> /* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
> Returns 0 if OK, 1 on error. */
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 7e2484b..491cbb6 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -2467,15 +2467,17 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
> inferior = current_inferior ();
> inferior->control.stop_soon = NO_STOP_QUIETLY;
>
> - /* If no exec file is yet known, try to determine it from the
> - process itself. */
> - if (get_exec_file (0) == NULL)
> - exec_file_locate_attach (ptid_get_pid (inferior_ptid), from_tty);
> - else
> + if (user_supplied_exec_file_p)
> {
> reopen_exec_file ();
> reread_symbols ();
> }
> + else
> + {
> + /* Attempt to open the file that was executed to create this
> + inferior. */
> + exec_file_locate_attach (ptid_get_pid (inferior_ptid), from_tty);
> + }
>
> /* Take any necessary post-attaching actions for this platform. */
> target_post_attach (ptid_get_pid (inferior_ptid));
> diff --git a/gdb/inferior.c b/gdb/inferior.c
> index ba320b5..87b2133 100644
> --- a/gdb/inferior.c
> +++ b/gdb/inferior.c
> @@ -889,6 +889,7 @@ add_inferior_command (char *args, int from_tty)
>
> exec_file_attach (exec, from_tty);
> symbol_file_add_main (exec, from_tty);
> + user_supplied_exec_file_p = 1;
> }
> }
>
> diff --git a/gdb/main.c b/gdb/main.c
> index 477fd68..9d8a196 100644
> --- a/gdb/main.c
> +++ b/gdb/main.c
> @@ -1051,14 +1051,20 @@ captured_main (void *data)
> catch_command_errors returns non-zero on success! */
> if (catch_command_errors_const (exec_file_attach, execarg,
> !batch_flag))
> - catch_command_errors_const (symbol_file_add_main, symarg,
> - !batch_flag);
> + {
> + user_supplied_exec_file_p = 1;
> +
> + catch_command_errors_const (symbol_file_add_main, symarg,
> + !batch_flag);
> + }
> }
> else
> {
> - if (execarg != NULL)
> - catch_command_errors_const (exec_file_attach, execarg,
> - !batch_flag);
> + if (execarg != NULL
> + && catch_command_errors_const (exec_file_attach, execarg,
> + !batch_flag))
> + user_supplied_exec_file_p = 1;
> +
> if (symarg != NULL)
> catch_command_errors_const (symbol_file_add_main, symarg,
> !batch_flag);
> diff --git a/gdb/progspace.h b/gdb/progspace.h
> index f960093..f8c39b6 100644
> --- a/gdb/progspace.h
> +++ b/gdb/progspace.h
> @@ -154,6 +154,13 @@ struct program_space
> It needs to be freed by xfree. It is not NULL iff EBFD is not NULL. */
> char *pspace_exec_filename;
>
> + /* Nonzero if pspace_exec_filename was supplied by the user,
> + either at startup (on the command-line) or via a "file"
> + an "add-inferior -exec" command. Zero if
> + pspace_exec_filename is unset or was discovered by GDB
> + somehow. */
> + int pspace_user_supplied_exec_file_p;
> +
> /* The address space attached to this program space. More than one
> program space may be bound to the same address space. In the
> traditional unix-like debugging scenario, this will usually
> diff --git a/gdb/remote.c b/gdb/remote.c
> index 099ddbb..b2f1bba 100644
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -1556,9 +1556,10 @@ remote_add_inferior (int fake_pid_p, int pid, int attached,
> inf->attach_flag = attached;
> inf->fake_pid_p = fake_pid_p;
>
> - /* If no main executable is currently open then attempt to
> - open the file that was executed to create this inferior. */
> - if (try_open_exec && !fake_pid_p && get_exec_file (0) == NULL)
> + /* If the user did not explicitly specify an executable file
> + then attempt to open the file that was executed to create
> + this inferior. */
> + if (try_open_exec && !fake_pid_p && !user_supplied_exec_file_p)
> exec_file_locate_attach (pid, 1);
>
> return inf;
>

I realize that I am coming late to this discussion, sorry about that.

How does this interact with follow-exec-mode? If follow-exec-mode is
'new' and the program execs, then 'run' will use the original executable
file. But if follow-exec-mode is 'same' and the program execs, then
'run' will use the executable file that was active after the exec call.

In the follow-exec-mode == 'same' instance, is the assumption that the
exec'd executable file takes on the same 'user-supplied' attribute as
the initial executable, since it is using the original inferior?

If so, is there a scenario where:
* the user supplies the exec file name
* the program execs, so the exec file name is now different
* then the user tries to do an attach (without an exec file name) to a
process running the original exec file, and gets the wrong exec file name?

Thanks
-Don