[PATCH] Lock bfd_stat and bfd_get_mtime

Andrew Burgess aburgess@redhat.com
Thu Dec 12 13:27:38 GMT 2024


Tom Tromey <tom@tromey.com> writes:

> PR gdb/31713 points out some races when using the background DWARF
> reader.
>
> This particular patch fixes some of these, namely the ones when using
> the sim.  In this case, the 'load' command calls reopen_exec_file,
> which calls bfd_stat, which introduces a race.
>
> BFD only locks globals -- concurrent use of a single BFD must be
> handled by the application.  To this end, this patch adds locked
> wrappers for bfd_stat and bfd_get_mtime.
>
> I couldn't reproduce these data races but the original reporter tested
> the patch and confirms that it helps.

Thanks.  This looks good.

Approved-By: Andrew Burgess <aburgess@redhat.com>

Thanks,
Andrew


>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31713
> ---
>  gdb/corefile.c  |  6 +++---
>  gdb/exec.c      |  2 +-
>  gdb/gdb_bfd.c   | 26 ++++++++++++++++++++++++++
>  gdb/gdb_bfd.h   | 11 +++++++++++
>  gdb/machoread.c |  3 ++-
>  gdb/objfiles.c  |  2 +-
>  gdb/symfile.c   |  6 +++---
>  7 files changed, 47 insertions(+), 9 deletions(-)
>
> diff --git a/gdb/corefile.c b/gdb/corefile.c
> index f6ec3cd5ca1..be0f1075488 100644
> --- a/gdb/corefile.c
> +++ b/gdb/corefile.c
> @@ -51,7 +51,7 @@ reopen_exec_file (void)
>  
>    /* If the timestamp of the exec file has changed, reopen it.  */
>    struct stat st;
> -  int res = bfd_stat (exec_bfd, &st);
> +  int res = gdb_bfd_stat (exec_bfd, &st);
>  
>    if (res == 0
>        && current_program_space->ebfd_mtime != 0
> @@ -70,8 +70,8 @@ validate_files (void)
>        if (!core_file_matches_executable_p (current_program_space->core_bfd (),
>  					   current_program_space->exec_bfd ()))
>  	warning (_("core file may not match specified executable file."));
> -      else if (bfd_get_mtime (current_program_space->exec_bfd ())
> -	       > bfd_get_mtime (current_program_space->core_bfd ()))
> +      else if (gdb_bfd_get_mtime (current_program_space->exec_bfd ())
> +	       > gdb_bfd_get_mtime (current_program_space->core_bfd ()))
>  	warning (_("exec file is newer than core file."));
>      }
>  }
> diff --git a/gdb/exec.c b/gdb/exec.c
> index 82d9266b7e3..73280ad59e7 100644
> --- a/gdb/exec.c
> +++ b/gdb/exec.c
> @@ -483,7 +483,7 @@ exec_file_attach (const char *filename, int from_tty)
>  	= build_section_table (current_program_space->exec_bfd ());
>  
>        current_program_space->ebfd_mtime
> -	= bfd_get_mtime (current_program_space->exec_bfd ());
> +	= gdb_bfd_get_mtime (current_program_space->exec_bfd ());
>  
>        validate_files ();
>  
> diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
> index 330d9182803..e0171871b76 100644
> --- a/gdb/gdb_bfd.c
> +++ b/gdb/gdb_bfd.c
> @@ -1140,6 +1140,32 @@ gdb_bfd_get_full_section_contents (bfd *abfd, asection *section,
>  				   section_size);
>  }
>  
> +/* See gdb_bfd.h.  */
> +
> +int
> +gdb_bfd_stat (bfd *abfd, struct stat *sbuf)
> +{
> +#if CXX_STD_THREAD
> +  gdb_bfd_data *gdata = (gdb_bfd_data *) bfd_usrdata (abfd);
> +  std::lock_guard<std::mutex> guard (gdata->per_bfd_mutex);
> +#endif
> +
> +  return bfd_stat (abfd, sbuf);
> +}
> +
> +/* See gdb_bfd.h.  */
> +
> +long
> +gdb_bfd_get_mtime (bfd *abfd)
> +{
> +#if CXX_STD_THREAD
> +  gdb_bfd_data *gdata = (gdb_bfd_data *) bfd_usrdata (abfd);
> +  std::lock_guard<std::mutex> guard (gdata->per_bfd_mutex);
> +#endif
> +
> +  return bfd_get_mtime (abfd);
> +}
> +
>  #define AMBIGUOUS_MESS1	".\nMatching formats:"
>  #define AMBIGUOUS_MESS2	\
>    ".\nUse \"set gnutarget format-name\" to specify the format."
> diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
> index 331570d769c..a93d9aa92e8 100644
> --- a/gdb/gdb_bfd.h
> +++ b/gdb/gdb_bfd.h
> @@ -251,6 +251,17 @@ gdb_bfd_sections (const gdb_bfd_ref_ptr &abfd)
>    return gdb_bfd_section_range (abfd->sections);
>  };
>  
> +/* A wrapper for bfd_stat that acquires the per-BFD lock on ABFD.  */
> +
> +extern int gdb_bfd_stat (bfd *abfd, struct stat *sbuf)
> +  ATTRIBUTE_WARN_UNUSED_RESULT;
> +
> +/* A wrapper for bfd_get_mtime that acquires the per-BFD lock on
> +   ABFD.  */
> +
> +extern long gdb_bfd_get_mtime (bfd *abfd)
> +  ATTRIBUTE_WARN_UNUSED_RESULT;
> +
>  /* A wrapper for bfd_errmsg to produce a more helpful error message
>     in the case of bfd_error_file_ambiguously recognized.
>     MATCHING, if non-NULL, is the corresponding argument to
> diff --git a/gdb/machoread.c b/gdb/machoread.c
> index ef6cf660629..ac764c09496 100644
> --- a/gdb/machoread.c
> +++ b/gdb/machoread.c
> @@ -434,7 +434,8 @@ macho_add_oso_symfile (oso_el *oso, const gdb_bfd_ref_ptr &abfd,
>        return;
>      }
>  
> -  if (abfd->my_archive == NULL && oso->mtime != bfd_get_mtime (abfd.get ()))
> +  if (abfd->my_archive == nullptr
> +      && oso->mtime != gdb_bfd_get_mtime (abfd.get ()))
>      {
>        warning (_("`%s': file time stamp mismatch."), oso->name);
>        return;
> diff --git a/gdb/objfiles.c b/gdb/objfiles.c
> index 555195dc61f..db9a704f333 100644
> --- a/gdb/objfiles.c
> +++ b/gdb/objfiles.c
> @@ -337,7 +337,7 @@ objfile::objfile (gdb_bfd_ref_ptr bfd_, program_space *pspace,
>  
>    if (obfd != nullptr)
>      {
> -      mtime = bfd_get_mtime (obfd.get ());
> +      mtime = gdb_bfd_get_mtime (obfd.get ());
>  
>        /* Build section table.  */
>        build_objfile_section_table (this);
> diff --git a/gdb/symfile.c b/gdb/symfile.c
> index 4386cdce5e7..aa3076555c9 100644
> --- a/gdb/symfile.c
> +++ b/gdb/symfile.c
> @@ -1267,9 +1267,9 @@ separate_debug_file_exists (const std::string &name, unsigned long crc,
>       numbers will never set st_ino to zero, this is merely an
>       optimization, so we do not need to worry about false negatives.  */
>  
> -  if (bfd_stat (abfd.get (), &abfd_stat) == 0
> +  if (gdb_bfd_stat (abfd.get (), &abfd_stat) == 0
>        && abfd_stat.st_ino != 0
> -      && bfd_stat (parent_objfile->obfd.get (), &parent_stat) == 0)
> +      && gdb_bfd_stat (parent_objfile->obfd.get (), &parent_stat) == 0)
>      {
>        if (abfd_stat.st_dev == parent_stat.st_dev
>  	  && abfd_stat.st_ino == parent_stat.st_ino)
> @@ -2488,7 +2488,7 @@ reread_symbols (int from_tty)
>  	continue;
>  
>        struct stat new_statbuf;
> -      int res = bfd_stat (objfile->obfd.get (), &new_statbuf);
> +      int res = gdb_bfd_stat (objfile->obfd.get (), &new_statbuf);
>        if (res != 0)
>  	{
>  	  /* If this object is from an archive (what you usually create
> -- 
> 2.46.1



More information about the Gdb-patches mailing list