aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/dwarf2/read.c3
-rw-r--r--gdb/gdb_bfd.c58
-rw-r--r--gdb/gdb_bfd.h5
-rw-r--r--gdb/main.c3
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 */
diff --git a/gdb/main.c b/gdb/main.c
index 688db76..67c7a52 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -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