From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
To: Pedro Alves <palves@redhat.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH v2 3/3] Make exec-file-mismatch compare build IDs
Date: Mon, 18 May 2020 16:21:42 +0200 [thread overview]
Message-ID: <1925ad2ac77a84fa40389ad801e42a8241ab8b13.camel@skynet.be> (raw)
In-Reply-To: <dc364cbb-25ad-484d-3f72-081f8fd0b2b3@redhat.com>
Patch looks nice to me.
Just one small comment: the call
add_setshow_enum_cmd ("exec-file-mismatch", class_support,
still references exec-file name in the help doc string.
The help doc should better reference the build ID, or alternatively
be generic by removing "name".
Thanks
Philippe
On Mon, 2020-05-18 at 14:55 +0100, Pedro Alves via Gdb-patches wrote:
> On 5/17/20 7:04 PM, Pedro Alves via Gdb-patches wrote:
> > The patch makes GDB first try exec-file-mismatch validation via build
> > IDs, and then if that isn't possible, fallback to validating using the
> > old method of comparing filenames. I'd argue that we should remove
> > the filename validation for causing too many false positives, though.
>
> I've argued about that yesterday over at gdb@, in this thread:
> https://sourceware.org/pipermail/gdb/2020-May/048544.html
>
> Here's an updated version that removes the filename comparison.
> I've kept the structure of the code the same, in case we
> add some form of fallback later on.
>
> From 771c3a52fd88c351bd4e93491f591f9b942ce217 Mon Sep 17 00:00:00 2001
> From: Pedro Alves <palves@redhat.com>
> Date: Mon, 18 May 2020 14:49:34 +0100
> Subject: [PATCH] Make exec-file-mismatch compare build IDs
>
> The patch makes GDB do exec-file-mismatch validation by comparing
> build IDs instead of the current method of comparing filenames.
>
> Currently, the exec-file-mismatch feature simply compares filenames to
> decide whether the exec file loaded in gdb and the exec file the
> target reports is running match. This causes false positives when
> remote debugging, because it'll often be the case that the paths in
> the host and the target won't match. And of course misses the case of
> the files having the same name but being actually different files
> (e.g., different builds).
>
> This also broke many testcases when running against gdbserver, causing
> tests to be skipped like (here native-extended-gdbserver):
>
> (gdb) run
> Starting program: /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/argv0-symlink/argv0-symlink-filelink
> warning: Mismatch between current exec-file /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/argv0-symlink/argv0-symlink-filelink
> and automatically determined exec-file /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/argv0-symlink/argv0-symlink
> exec-file-mismatch handling is currently "ask"
> Load new symbol table from "/home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/argv0-symlink/argv0-symlink"? (y or n) UNTESTED: gdb.base/argv0-symlink.exp: could not run to main
>
> or to fail like (here native-gdbserver):
>
> (gdb) spawn /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/../../gdbserver/gdbserver --once localhost:2346 /home/pedro/gdb/binutils-gdb/build/gdb/te
> stsuite/outputs/gdb.btrace/buffer-size/skip_btrace_tests-19968.x
> Process /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.btrace/buffer-size/skip_btrace_tests-19968.x created; pid = 20040
> Listening on port 2346
> target remote localhost:2346
> Remote debugging using localhost:2346
> warning: Mismatch between current exec-file /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/temp/19968/skip_btrace_tests-19968.x
> and automatically determined exec-file /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.btrace/buffer-size/skip_btrace_tests-19968.x
> exec-file-mismatch handling is currently "ask"
> Load new symbol table from "/home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.btrace/buffer-size/skip_btrace_tests-19968.x"? (y or n) Quit
> (gdb) UNSUPPORTED: gdb.btrace/buffer-size.exp: target does not support record-btrace
>
> The former case is about GDB not realizing the two files are the same,
> because one of the them is a symlink to the other. The latter case is
> about GDB realizing that one file is a copy of the other.
>
> Over the years, the toolchain has settled on build ID matching being
> the canonical method to match core dumps to executables, and
> executables with no debug info to their debug info.
>
> This patch makes us use build IDs to match the running image of a
> binary with its version loaded in gdb, which may or may not have debug
> info. This is very much like the core dump/executable matching.
>
> The change to gdb_bfd_open is necessary to get rid of the "transfers
> from remote targets can be slow" warning when we open the remote file
> to read its build ID:
>
> (gdb) r
> Starting program: /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/break/break
> Reading /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/argv0-symlink/argv0-symlink from remote target...
> warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> warning: Mismatch between current exec-file /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/break/break
> and automatically determined exec-file /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/argv0-symlink/argv0-symlink
> exec-file-mismatch handling is currently "ask"
> Load new symbol table from "/home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/argv0-symlink/argv0-symlink"? (y or n)
>
> While trying this out, I was worried that bfd would read a lot of
> stuff from the binary in order to extract the build ID, making it
> potentially slow, but turns out we don't read all that much. Maybe a
> couple hundred bytes, and most of it seemingly is the read-ahead
> cache. So I'm not worried about that. Otherwise I'd consider whether
> a new qXfer:buildid:read would be better. But I'm happy that we
> seemingly don't need to worry about it.
>
> gdb/ChangeLog:
> yyyy-mm-dd Pedro Alves <palves@redhat.com>
>
> * NEWS (set exec-file-mismatch): Adjust entry.
> * exec.c: Include "build-id.h".
> (validate_exec_file): Try to match build IDs instead of filenames.
> * gdb_bfd.c (struct gdb_bfd_open_closure): New.
> (gdb_bfd_iovec_fileio_open): Adjust to use gdb_bfd_open_closure
> and pass down 'warn_if_slow'.
> (gdb_bfd_open): Add 'warn_if_slow' parameter. Use
> gdb_bfd_open_closure to pass it down.
> * gdb_bfd.h (gdb_bfd_open): Add 'warn_if_slow' parameter.
>
> gdb/doc/ChangeLog:
> yyyy-mm-dd Pedro Alves <palves@redhat.com>
>
> * gdb.texinfo (Attach): Update exec-file-mismatch description to
> mention build IDs.
> (Separate Debug Files): Add "build id" anchor.
> ---
> gdb/doc/gdb.texinfo | 21 +++++++++++----------
> gdb/NEWS | 15 +++++++--------
> gdb/exec.c | 49 ++++++++++++++++++++++++++++++++++++++++++-------
> gdb/gdb_bfd.c | 23 ++++++++++++++++-------
> gdb/gdb_bfd.h | 6 ++++--
> 5 files changed, 80 insertions(+), 34 deletions(-)
>
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 8f3301259af..64181628495 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -2909,22 +2909,22 @@ the @code{file} command to load the program. @xref{Files, ,Commands to
> Specify Files}.
>
> @anchor{set exec-file-mismatch}
> -If the debugger can determine the name of the executable file running
> -in the process it is attaching to, and this file name does not match
> -the name of the current exec-file loaded by @value{GDBN}, the option
> -@code{exec-file-mismatch} specifies how to handle the mismatch.
> +If the debugger can determine that the executable file running in the
> +process it is attaching to does not match the current exec-file loaded
> +by @value{GDBN}, the option @code{exec-file-mismatch} specifies how to
> +handle the mismatch. @value{GDBN} tries to compare the files by
> +comparing their build IDs (@pxref{build ID}), if available.
>
> @table @code
> @kindex exec-file-mismatch
> @cindex set exec-file-mismatch
> @item set exec-file-mismatch @samp{ask|warn|off}
>
> -Whether to detect mismatch between the name of the current executable
> -file loaded by @value{GDBN} and the name of the executable file used to
> -start the process. If @samp{ask}, the default, display a warning
> -and ask the user whether to load the process executable file; if
> -@samp{warn}, just display a warning; if @samp{off}, don't attempt to
> -detect a mismatch.
> +Whether to detect mismatch between the current executable file loaded
> +by @value{GDBN} and the executable file used to start the process. If
> +@samp{ask}, the default, display a warning and ask the user whether to
> +load the process executable file; if @samp{warn}, just display a
> +warning; if @samp{off}, don't attempt to detect a mismatch.
>
> @cindex show exec-file-mismatch
> @item show exec-file-mismatch
> @@ -20874,6 +20874,7 @@ checksum for the debug file, which @value{GDBN} uses to validate that
> the executable and the debug file came from the same build.
>
> @item
> +@anchor{build ID}
> The executable contains a @dfn{build ID}, a unique bit string that is
> also present in the corresponding debug info file. (This is supported
> only on some operating systems, when using the ELF or PE file formats
> diff --git a/gdb/NEWS b/gdb/NEWS
> index a059fc7aa0e..2a9c8b8ee19 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -54,14 +54,13 @@
>
> set exec-file-mismatch -- Set exec-file-mismatch handling (ask|warn|off).
> show exec-file-mismatch -- Show exec-file-mismatch handling (ask|warn|off).
> - Set or show the option 'exec-file-mismatch'. When GDB attaches to
> - a running process and can determine the name of the executable file
> - the process runs, this new option indicates whether to detect mismatch
> - between the name of the current executable file loaded by GDB
> - and the name of the executable file used to start the process.
> - If 'ask', the default, display a warning and ask the user
> - whether to load the process executable file; if 'warn', just display
> - a warning; if 'off', don't attempt to detect a mismatch.
> + Set or show the option 'exec-file-mismatch'. When GDB attaches to a
> + running process, this new option indicates whether to detect
> + a mismatch between the current executable file loaded by GDB and the
> + executable file used to start the process. If 'ask', the default,
> + display a warning and ask the user whether to load the process
> + executable file; if 'warn', just display a warning; if 'off', don't
> + attempt to detect a mismatch.
>
> tui new-layout NAME WINDOW WEIGHT [WINDOW WEIGHT]...
> Define a new TUI layout, specifying its name and the windows that
> diff --git a/gdb/exec.c b/gdb/exec.c
> index a2added5e22..8b89828ddda 100644
> --- a/gdb/exec.c
> +++ b/gdb/exec.c
> @@ -37,6 +37,7 @@
> #include "gdb_bfd.h"
> #include "gcore.h"
> #include "source.h"
> +#include "build-id.h"
>
> #include <fcntl.h>
> #include "readline/tilde.h"
> @@ -247,20 +248,54 @@ validate_exec_file (int from_tty)
> struct inferior *inf = current_inferior ();
> /* Try to determine a filename from the process itself. */
> const char *pid_exec_file = target_pid_to_exec_file (inf->pid);
> + bool build_id_mismatch = false;
>
> - /* If wee cannot validate the exec file, return. */
> + /* If we cannot validate the exec file, return. */
> if (current_exec_file == NULL || pid_exec_file == NULL)
> return;
>
> - std::string exec_file_target (pid_exec_file);
> + /* Try validating via build-id, if available. This is the most
> + reliable check. */
> + const bfd_build_id *exec_file_build_id = build_id_bfd_get (exec_bfd);
> + if (exec_file_build_id != nullptr)
> + {
> + /* Prepend the target prefix, to force gdb_bfd_open to open the
> + file on the remote file system (if indeed remote). */
> + std::string target_pid_exec_file
> + = std::string (TARGET_SYSROOT_PREFIX) + pid_exec_file;
> +
> + gdb_bfd_ref_ptr abfd (gdb_bfd_open (target_pid_exec_file.c_str (),
> + gnutarget, -1, false));
> + if (abfd != nullptr)
> + {
> + const bfd_build_id *target_exec_file_build_id
> + = build_id_bfd_get (abfd.get ());
>
> - /* In case the exec file is not local, exec_file_target has to point at
> - the target file system. */
> - if (is_target_filename (current_exec_file) && !target_filesystem_is_local ())
> - exec_file_target = TARGET_SYSROOT_PREFIX + exec_file_target;
> + if (target_exec_file_build_id != nullptr)
> + {
> + if (exec_file_build_id->size == target_exec_file_build_id->size
> + && memcmp (exec_file_build_id->data,
> + target_exec_file_build_id->data,
> + exec_file_build_id->size) == 0)
> + {
> + /* Match. */
> + return;
> + }
> + else
> + build_id_mismatch = true;
> + }
> + }
> + }
>
> - if (exec_file_target != current_exec_file)
> + if (build_id_mismatch)
> {
> + std::string exec_file_target (pid_exec_file);
> +
> + /* In case the exec file is not local, exec_file_target has to point at
> + the target file system. */
> + if (is_target_filename (current_exec_file) && !target_filesystem_is_local ())
> + exec_file_target = TARGET_SYSROOT_PREFIX + exec_file_target;
> +
> warning
> (_("Mismatch between current exec-file %ps\n"
> "and automatically determined exec-file %ps\n"
> diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
> index 61872a0bf3d..25e0178a8b8 100644
> --- a/gdb/gdb_bfd.c
> +++ b/gdb/gdb_bfd.c
> @@ -271,22 +271,29 @@ fileio_errno_to_host (int errnum)
> return -1;
> }
>
> +/* bfd_openr_iovec OPEN_CLOSURE data for gdb_bfd_open. */
> +struct gdb_bfd_open_closure
> +{
> + inferior *inf;
> + bool warn_if_slow;
> +};
> +
> /* Wrapper for target_fileio_open suitable for passing as the
> - OPEN_FUNC argument to gdb_bfd_openr_iovec. The supplied
> - OPEN_CLOSURE is unused. */
> + OPEN_FUNC argument to gdb_bfd_openr_iovec. */
>
> static void *
> -gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *inferior)
> +gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *open_closure)
> {
> const char *filename = bfd_get_filename (abfd);
> int fd, target_errno;
> int *stream;
> + gdb_bfd_open_closure *oclosure = (gdb_bfd_open_closure *) open_closure;
>
> gdb_assert (is_target_filename (filename));
>
> - fd = target_fileio_open ((struct inferior *) inferior,
> + fd = target_fileio_open (oclosure->inf,
> filename + strlen (TARGET_SYSROOT_PREFIX),
> - FILEIO_O_RDONLY, 0, true,
> + FILEIO_O_RDONLY, 0, oclosure->warn_if_slow,
> &target_errno);
> if (fd == -1)
> {
> @@ -378,7 +385,8 @@ gdb_bfd_iovec_fileio_fstat (struct bfd *abfd, void *stream,
> /* See gdb_bfd.h. */
>
> gdb_bfd_ref_ptr
> -gdb_bfd_open (const char *name, const char *target, int fd)
> +gdb_bfd_open (const char *name, const char *target, int fd,
> + bool warn_if_slow)
> {
> hashval_t hash;
> void **slot;
> @@ -392,9 +400,10 @@ gdb_bfd_open (const char *name, const char *target, int fd)
> {
> gdb_assert (fd == -1);
>
> + gdb_bfd_open_closure open_closure { current_inferior (), warn_if_slow };
> return gdb_bfd_openr_iovec (name, target,
> gdb_bfd_iovec_fileio_open,
> - current_inferior (),
> + &open_closure,
> gdb_bfd_iovec_fileio_pread,
> gdb_bfd_iovec_fileio_close,
> gdb_bfd_iovec_fileio_fstat);
> diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
> index 532520e0f7d..a941b79fe73 100644
> --- a/gdb/gdb_bfd.h
> +++ b/gdb/gdb_bfd.h
> @@ -78,10 +78,12 @@ typedef gdb::ref_ptr<struct bfd, gdb_bfd_ref_policy> gdb_bfd_ref_ptr;
> If the BFD was not accessed using target fileio operations then the
> filename associated with the BFD and accessible with
> bfd_get_filename will not be exactly NAME but rather NAME with
> - TARGET_SYSROOT_PREFIX stripped. */
> + TARGET_SYSROOT_PREFIX stripped. If WARN_IF_SLOW is true, print a
> + warning message if the file is being accessed over a link that may
> + be slow. */
>
> gdb_bfd_ref_ptr gdb_bfd_open (const char *name, const char *target,
> - int fd = -1);
> + int fd = -1, bool warn_if_slow = true);
>
> /* Mark the CHILD BFD as being a member of PARENT. Also, increment
> the reference count of CHILD. Calling this function ensures that
>
> base-commit: 7cfd74cfc6e14034779e6cc048c68877b7a08f88
> prerequisite-patch-id: b945b532dec51eb5ae7fdb9b8fe9007deca8d276
> prerequisite-patch-id: 6730601601e24970f31193c533a7c257c7e1c48c
next prev parent reply other threads:[~2020-05-18 14:21 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-17 18:04 [PATCH 0/3] " Pedro Alves
2020-05-17 18:04 ` [PATCH 1/3] Default gdb_bfd_open's fd parameter to -1 Pedro Alves
2020-05-17 18:04 ` [PATCH 2/3] Eliminate target_fileio_open_warn_if_slow Pedro Alves
2020-05-17 18:04 ` [PATCH 3/3] Make exec-file-mismatch compare build IDs Pedro Alves
2020-05-17 18:25 ` Eli Zaretskii
2020-05-18 13:52 ` Pedro Alves
2020-05-18 13:55 ` [PATCH v2 " Pedro Alves
2020-05-18 14:21 ` Philippe Waroquiers [this message]
2020-05-19 15:43 ` Pedro Alves
2020-05-19 16:04 ` Tom Tromey
2020-05-19 17:44 ` Pedro Alves
2020-05-21 13:32 ` Philippe Waroquiers
2020-05-21 14:02 ` Pedro Alves
2020-05-21 14:23 ` Philippe Waroquiers
2020-05-21 14:27 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1925ad2ac77a84fa40389ad801e42a8241ab8b13.camel@skynet.be \
--to=philippe.waroquiers@skynet.be \
--cc=gdb-patches@sourceware.org \
--cc=palves@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).