aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog10
-rw-r--r--gdb/gdb_bfd.c34
-rw-r--r--gdb/gdb_bfd.h9
-rw-r--r--gdb/solib-darwin.c32
4 files changed, 68 insertions, 17 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 41b687a..632f6cf 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2012-11-28 Tom Tromey <tromey@redhat.com>
+
+ PR gdb/14290:
+ * solib-darwin.c (gdb_bfd_mach_o_fat_extract): New function.
+ (darwin_solib_get_all_image_info_addr_at_init, darwin_bfd_open):
+ Use it.
+ * gdb_bfd.h (gdb_bfd_mark_parent): Declare.
+ * gdb_bfd.c (gdb_bfd_mark_parent): New function.
+ (gdb_bfd_openr_next_archived_file): Use it.
+
2012-11-28 Markus Metzger <markus.t.metzger@intel.com>
* configure.ac: Check for linux/perf_event.h.
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 2bcc4b4..f0e349b 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -499,24 +499,34 @@ gdb_bfd_openr_iovec (const char *filename, const char *target,
/* See gdb_bfd.h. */
+void
+gdb_bfd_mark_parent (bfd *child, bfd *parent)
+{
+ struct gdb_bfd_data *gdata;
+
+ gdb_bfd_ref (child);
+ /* No need to stash the filename here, because we also keep a
+ reference on the parent archive. */
+
+ gdata = bfd_usrdata (child);
+ if (gdata->archive_bfd == NULL)
+ {
+ gdata->archive_bfd = parent;
+ gdb_bfd_ref (parent);
+ }
+ else
+ gdb_assert (gdata->archive_bfd == parent);
+}
+
+/* See gdb_bfd.h. */
+
bfd *
gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
{
bfd *result = bfd_openr_next_archived_file (archive, previous);
if (result)
- {
- struct gdb_bfd_data *gdata;
-
- gdb_bfd_ref (result);
- /* No need to stash the filename here, because we also keep a
- reference on the parent archive. */
-
- gdata = bfd_usrdata (result);
- gdb_assert (gdata->archive_bfd == NULL || gdata->archive_bfd == archive);
- gdata->archive_bfd = archive;
- gdb_bfd_ref (archive);
- }
+ gdb_bfd_mark_parent (result, archive);
return result;
}
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index 5fd361c..bb70b27 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -50,6 +50,15 @@ void gdb_bfd_ref (struct bfd *abfd);
void gdb_bfd_unref (struct bfd *abfd);
+/* Mark the CHILD BFD as being a member of PARENT. Also, increment
+ the reference count of CHILD. Calling this function ensures that
+ as along as CHILD remains alive, PARENT will as well. Both CHILD
+ and PARENT must be non-NULL. This can be called more than once
+ with the same arguments; but it is not allowed to call it for a
+ single CHILD with different values for PARENT. */
+
+void gdb_bfd_mark_parent (bfd *child, bfd *parent);
+
/* Try to read or map the contents of the section SECT. If
successful, the section data is returned and *SIZE is set to the
size of the section data; this may not be the same as the size
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 4ea0722..735d1c3 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -348,6 +348,27 @@ darwin_special_symbol_handling (void)
{
}
+/* A wrapper for bfd_mach_o_fat_extract that handles reference
+ counting properly. This will either return NULL, or return a new
+ reference to a BFD. */
+
+static bfd *
+gdb_bfd_mach_o_fat_extract (bfd *abfd, bfd_format format,
+ const bfd_arch_info_type *arch)
+{
+ bfd *result = bfd_mach_o_fat_extract (abfd, format, arch);
+
+ if (result == NULL)
+ return NULL;
+
+ if (result == abfd)
+ gdb_bfd_ref (result);
+ else
+ gdb_bfd_mark_parent (result, abfd);
+
+ return result;
+}
+
/* Extract dyld_all_image_addr when the process was just created, assuming the
current PC is at the entry of the dynamic linker. */
@@ -377,12 +398,11 @@ darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info)
bfd *sub;
make_cleanup_bfd_unref (dyld_bfd);
- sub = bfd_mach_o_fat_extract (dyld_bfd, bfd_object,
- gdbarch_bfd_arch_info (target_gdbarch ()));
+ sub = gdb_bfd_mach_o_fat_extract (dyld_bfd, bfd_object,
+ gdbarch_bfd_arch_info (target_gdbarch ()));
if (sub)
{
dyld_bfd = sub;
- gdb_bfd_ref (sub);
make_cleanup_bfd_unref (sub);
}
else
@@ -514,14 +534,16 @@ darwin_bfd_open (char *pathname)
/* Open bfd for shared library. */
abfd = solib_bfd_fopen (found_pathname, found_file);
- res = bfd_mach_o_fat_extract (abfd, bfd_object,
- gdbarch_bfd_arch_info (target_gdbarch ()));
+ res = gdb_bfd_mach_o_fat_extract (abfd, bfd_object,
+ gdbarch_bfd_arch_info (target_gdbarch ()));
if (!res)
{
make_cleanup_bfd_unref (abfd);
error (_("`%s': not a shared-library: %s"),
bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
}
+
+ gdb_bfd_unref (abfd);
return res;
}