diff options
-rw-r--r-- | gdb/dwarf2/read.c | 3 | ||||
-rw-r--r-- | gdb/gdb_bfd.c | 58 | ||||
-rw-r--r-- | gdb/gdb_bfd.h | 5 | ||||
-rw-r--r-- | gdb/main.c | 3 |
4 files changed, 65 insertions, 4 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 45f79de..a0fddbe 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -3920,8 +3920,7 @@ static struct dwo_unit * lookup_dwo_unit (dwarf2_cu *cu, die_info *comp_unit_die, const char *dwo_name) { #if CXX_STD_THREAD - /* We need a lock here both to handle the DWO hash table, and BFD, - which is not thread-safe. */ + /* We need a lock here both to handle the DWO hash table. */ static std::mutex dwo_lock; std::lock_guard<std::mutex> guard (dwo_lock); diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c index 1c496c4..9f7d0f6 100644 --- a/gdb/gdb_bfd.c +++ b/gdb/gdb_bfd.c @@ -35,6 +35,36 @@ #include "cli/cli-style.h" #include <unordered_map> +#if CXX_STD_THREAD + +#include <mutex> + +/* Lock held when doing BFD operations. A recursive mutex is used + because we use this mutex internally and also for BFD, just to make + life a bit simpler, and we may sometimes hold it while calling into + BFD. */ +static std::recursive_mutex gdb_bfd_mutex; + +/* BFD locking function. */ + +static bool +gdb_bfd_lock (void *ignore) +{ + gdb_bfd_mutex.lock (); + return true; +} + +/* BFD unlocking function. */ + +static bool +gdb_bfd_unlock (void *ignore) +{ + gdb_bfd_mutex.unlock (); + return true; +} + +#endif /* CXX_STD_THREAD */ + /* An object of this type is stored in the section's user data when mapping a section. */ @@ -498,6 +528,10 @@ gdb_bfd_open (const char *name, const char *target, int fd, name += strlen (TARGET_SYSROOT_PREFIX); } +#if CXX_STD_THREAD + std::lock_guard<std::recursive_mutex> guard (gdb_bfd_mutex); +#endif + if (gdb_bfd_cache == NULL) gdb_bfd_cache = htab_create_alloc (1, hash_bfd, eq_bfd, NULL, xcalloc, xfree); @@ -625,6 +659,10 @@ gdb_bfd_ref (struct bfd *abfd) if (abfd == NULL) return; +#if CXX_STD_THREAD + std::lock_guard<std::recursive_mutex> guard (gdb_bfd_mutex); +#endif + gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd); bfd_cache_debug_printf ("Increase reference count on bfd %s (%s)", @@ -654,6 +692,10 @@ gdb_bfd_unref (struct bfd *abfd) if (abfd == NULL) return; +#if CXX_STD_THREAD + std::lock_guard<std::recursive_mutex> guard (gdb_bfd_mutex); +#endif + gdata = (struct gdb_bfd_data *) bfd_usrdata (abfd); gdb_assert (gdata->refc >= 1); @@ -1171,6 +1213,22 @@ gdb_bfd_error_handler (const char *fmt, va_list ap) (*default_bfd_error_handler) (fmt, ap); } +/* See gdb_bfd.h. */ + +void +gdb_bfd_init () +{ + if (bfd_init () == BFD_INIT_MAGIC) + { +#if CXX_STD_THREAD + if (bfd_thread_init (gdb_bfd_lock, gdb_bfd_unlock, nullptr)) +#endif + return; + } + + error (_("fatal error: libbfd ABI mismatch")); +} + void _initialize_gdb_bfd (); void _initialize_gdb_bfd () diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h index eeb782e..3de9cd9 100644 --- a/gdb/gdb_bfd.h +++ b/gdb/gdb_bfd.h @@ -258,4 +258,9 @@ gdb_bfd_sections (const gdb_bfd_ref_ptr &abfd) extern std::string gdb_bfd_errmsg (bfd_error_type error_tag, char **matching); +/* A wrapper for bfd_init that also handles setting up for + multi-threading. */ + +extern void gdb_bfd_init (); + #endif /* GDB_BFD_H */ @@ -699,8 +699,7 @@ captured_main_1 (struct captured_main_args *context) auto temp_uiout = std::make_unique<cli_ui_out> (gdb_stdout); current_uiout = temp_uiout.get (); - if (bfd_init () != BFD_INIT_MAGIC) - error (_("fatal error: libbfd ABI mismatch")); + gdb_bfd_init (); #ifdef __MINGW32__ /* On Windows, argv[0] is not necessarily set to absolute form when |