static htab_t gdb_bfd_cache;
+/* When true gdb will reuse an existing bfd object if the filename,
+ modification time, and file size all match. */
+
+static int bfd_sharing = 1;
+static void
+show_bfd_sharing (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("BFD sharing is %s.\n"), value);
+}
+
+/* When non-zero debugging of the bfd caches is enabled. */
+
+static unsigned int debug_bfd_cache;
+static void
+show_bfd_cache_debug (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("BFD cache debugging is %s.\n"), value);
+}
+
/* The type of an object being looked up in gdb_bfd_cache. We use
htab's capability of storing one kind of object (BFD in this case)
and using a different sort of object for searching. */
gdb_assert (is_target_filename (filename));
- fd = target_fileio_open ((struct inferior *) inferior,
- filename + strlen (TARGET_SYSROOT_PREFIX),
- FILEIO_O_RDONLY, 0,
- &target_errno);
+ fd = target_fileio_open_warn_if_slow ((struct inferior *) inferior,
+ filename
+ + strlen (TARGET_SYSROOT_PREFIX),
+ FILEIO_O_RDONLY, 0,
+ &target_errno);
if (fd == -1)
{
errno = fileio_errno_to_host (target_errno);
pos = 0;
while (nbytes > pos)
{
+ QUIT;
+
bytes = target_fileio_pread (fd, (gdb_byte *) buf + pos,
nbytes - pos, offset + pos,
&target_errno);
opening the BFD may fail; and this would violate hashtab
invariants. */
abfd = htab_find_with_hash (gdb_bfd_cache, &search, hash);
- if (abfd != NULL)
+ if (bfd_sharing && abfd != NULL)
{
+ if (debug_bfd_cache)
+ fprintf_unfiltered (gdb_stdlog,
+ "Reusing cached bfd %s for %s\n",
+ host_address_to_string (abfd),
+ bfd_get_filename (abfd));
close (fd);
gdb_bfd_ref (abfd);
return abfd;
if (abfd == NULL)
return NULL;
- slot = htab_find_slot_with_hash (gdb_bfd_cache, &search, hash, INSERT);
- gdb_assert (!*slot);
- *slot = abfd;
+ if (debug_bfd_cache)
+ fprintf_unfiltered (gdb_stdlog,
+ "Creating new bfd %s for %s\n",
+ host_address_to_string (abfd),
+ bfd_get_filename (abfd));
+
+ if (bfd_sharing)
+ {
+ slot = htab_find_slot_with_hash (gdb_bfd_cache, &search, hash, INSERT);
+ gdb_assert (!*slot);
+ *slot = abfd;
+ }
gdb_bfd_ref (abfd);
return abfd;
gdata = bfd_usrdata (abfd);
+ if (debug_bfd_cache)
+ fprintf_unfiltered (gdb_stdlog,
+ "Increase reference count on bfd %s (%s)\n",
+ host_address_to_string (abfd),
+ bfd_get_filename (abfd));
+
if (gdata != NULL)
{
gdata->refc += 1;
gdata->refc -= 1;
if (gdata->refc > 0)
- return;
+ {
+ if (debug_bfd_cache)
+ fprintf_unfiltered (gdb_stdlog,
+ "Decrease reference count on bfd %s (%s)\n",
+ host_address_to_string (abfd),
+ bfd_get_filename (abfd));
+ return;
+ }
+
+ if (debug_bfd_cache)
+ fprintf_unfiltered (gdb_stdlog,
+ "Delete final reference count on bfd %s (%s)\n",
+ host_address_to_string (abfd),
+ bfd_get_filename (abfd));
archive_bfd = gdata->archive_bfd;
search.filename = bfd_get_filename (abfd);
add_cmd ("bfds", class_maintenance, maintenance_info_bfds, _("\
List the BFDs that are currently open."),
&maintenanceinfolist);
+
+ add_setshow_boolean_cmd ("bfd-sharing", no_class,
+ &bfd_sharing, _("\
+Set whether gdb will share bfds that appear to be the same file."), _("\
+Show whether gdb will share bfds that appear to be the same file."), _("\
+When enabled gdb will reuse existing bfds rather than reopening the\n\
+same file. To decide if two files are the same then gdb compares the\n\
+filename, file size, file modification time, and file inode."),
+ NULL,
+ &show_bfd_sharing,
+ &maintenance_set_cmdlist,
+ &maintenance_show_cmdlist);
+
+ add_setshow_zuinteger_cmd ("bfd-cache", class_maintenance,
+ &debug_bfd_cache, _("\
+Set bfd cache debugging."), _("\
+Show bfd cache debugging."), _("\
+When non-zero, bfd cache specific debugging is enabled."),
+ NULL,
+ &show_bfd_cache_debug,
+ &setdebuglist, &showdebuglist);
}