/* Plugin support for BFD.
- Copyright (C) 2009-2020 Free Software Foundation, Inc.
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
ld_plugin_claim_file_handler claim_file;
ld_plugin_all_symbols_read_handler all_symbols_read;
ld_plugin_all_symbols_read_handler cleanup_handler;
- bfd_boolean has_symbol_type;
+ bool has_symbol_type;
struct plugin_list_entry *next;
add_symbols_v2 (void *handle, int nsyms,
const struct ld_plugin_symbol *syms)
{
- current_plugin->has_symbol_type = TRUE;
+ current_plugin->has_symbol_type = true;
return add_symbols (handle, nsyms, syms);
}
bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
{
bfd *iobfd;
+ int fd;
iobfd = ibfd;
while (iobfd->my_archive
if (!iobfd->iostream && !bfd_open_file (iobfd))
return 0;
- /* The plugin API expects that the file descriptor won't be closed
- and reused as done by the bfd file cache. So open it again.
- dup isn't good enough. plugin IO uses lseek/read while BFD uses
- fseek/fread. It isn't wise to mix the unistd and stdio calls on
- the same underlying file descriptor. */
- file->fd = open (file->name, O_RDONLY | O_BINARY);
- if (file->fd < 0)
- return 0;
+ /* Reuse the archive plugin file descriptor. */
+ if (iobfd != ibfd)
+ fd = iobfd->archive_plugin_fd;
+ else
+ fd = -1;
+
+ if (fd < 0)
+ {
+ /* The plugin API expects that the file descriptor won't be closed
+ and reused as done by the bfd file cache. So open it again.
+ dup isn't good enough. plugin IO uses lseek/read while BFD uses
+ fseek/fread. It isn't wise to mix the unistd and stdio calls on
+ the same underlying file descriptor. */
+ fd = open (file->name, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ {
+#ifndef EMFILE
+ return 0;
+#else
+ if (errno != EMFILE)
+ return 0;
+
+#ifdef HAVE_GETRLIMIT
+ struct rlimit lim;
+
+ /* Complicated links involving lots of files and/or large
+ archives can exhaust the number of file descriptors
+ available to us. If possible, try to allocate more
+ descriptors. */
+ if (getrlimit (RLIMIT_NOFILE, & lim) == 0
+ && lim.rlim_cur < lim.rlim_max)
+ {
+ lim.rlim_cur = lim.rlim_max;
+ if (setrlimit (RLIMIT_NOFILE, &lim) == 0)
+ fd = open (file->name, O_RDONLY | O_BINARY);
+ }
+
+ if (fd < 0)
+#endif
+ {
+ _bfd_error_handler (_("plugin framework: out of file descriptors. Try using fewer objects/archives\n"));
+ return 0;
+ }
+#endif
+ }
+ }
if (iobfd == ibfd)
{
struct stat stat_buf;
- if (fstat (file->fd, &stat_buf))
+ if (fstat (fd, &stat_buf))
{
- close(file->fd);
+ close (fd);
return 0;
}
}
else
{
+ /* Cache the archive plugin file descriptor. */
+ iobfd->archive_plugin_fd = fd;
+ iobfd->archive_plugin_fd_open_count++;
+
file->offset = ibfd->origin;
file->filesize = arelt_size (ibfd);
}
+
+ file->fd = fd;
return 1;
}
+/* Close the plugin file descriptor FD. If ABFD isn't NULL, it is an
+ archive member. */
+
+void
+bfd_plugin_close_file_descriptor (bfd *abfd, int fd)
+{
+ if (abfd == NULL)
+ close (fd);
+ else
+ {
+ while (abfd->my_archive
+ && !bfd_is_thin_archive (abfd->my_archive))
+ abfd = abfd->my_archive;
+
+ /* Close the file descriptor if there is no archive plugin file
+ descriptor. */
+ if (abfd->archive_plugin_fd == -1)
+ {
+ close (fd);
+ return;
+ }
+
+ abfd->archive_plugin_fd_open_count--;
+ /* Dup the archive plugin file descriptor for later use, which
+ will be closed by _bfd_archive_close_and_cleanup. */
+ if (abfd->archive_plugin_fd_open_count == 0)
+ {
+ abfd->archive_plugin_fd = dup (fd);
+ close (fd);
+ }
+ }
+}
+
static int
try_claim (bfd *abfd)
{
&& current_plugin->claim_file)
{
current_plugin->claim_file (&file, &claimed);
- close (file.fd);
+ bfd_plugin_close_file_descriptor ((abfd->my_archive != NULL
+ ? abfd : NULL),
+ file.fd);
}
return claimed;
}
-static bfd_boolean
-try_load_plugin (const char * pname,
- struct plugin_list_entry * plugin_list_iter,
- bfd * abfd,
- bfd_boolean build_list_p)
+static bool
+try_load_plugin (const char *pname,
+ struct plugin_list_entry *plugin_list_iter,
+ bfd *abfd,
+ bool build_list_p)
{
void *plugin_handle;
struct ld_plugin_tv tv[5];
int i;
ld_plugin_onload onload;
enum ld_plugin_status status;
- bfd_boolean result = FALSE;
+ bool result = false;
/* NB: Each object is independent. Reuse the previous plugin from
the last run will lead to wrong result. */
if (! build_list_p)
_bfd_error_handler ("Failed to load plugin '%s', reason: %s\n",
pname, dlerror ());
- return FALSE;
+ return false;
}
if (plugin_list_iter == NULL)
goto short_circuit;
abfd->plugin_format = bfd_plugin_yes;
- result = TRUE;
+ result = true;
short_circuit:
dlclose (plugin_handle);
/* Return TRUE if a plugin library is used. */
-bfd_boolean
+bool
bfd_plugin_specified_p (void)
{
return plugin_list != NULL;
/* Return TRUE if ABFD can be claimed by linker LTO plugin. */
-bfd_boolean
+bool
bfd_link_plugin_object_p (bfd *abfd)
{
if (ld_plugin_object_p)
return ld_plugin_object_p (abfd) != NULL;
- return FALSE;
+ return false;
}
extern const bfd_target plugin_vec;
/* Return TRUE if TARGET is a pointer to plugin_vec. */
-bfd_boolean
+bool
bfd_plugin_target_p (const bfd_target *target)
{
return target == &plugin_vec;
full_name = concat (plugin_dir, "/", ent->d_name, NULL);
if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
- (void) try_load_plugin (full_name, NULL, abfd, TRUE);
+ (void) try_load_plugin (full_name, NULL, abfd, true);
free (full_name);
}
closedir (d);
has_plugin_list = plugin_list != NULL;
}
-static bfd_boolean
+static bool
load_plugin (bfd *abfd)
{
struct plugin_list_entry *plugin_list_iter;
if (plugin_name)
- return try_load_plugin (plugin_name, plugin_list, abfd, FALSE);
+ return try_load_plugin (plugin_name, plugin_list, abfd, false);
if (plugin_program_name == NULL)
- return FALSE;
+ return false;
build_plugin_list (abfd);
for (plugin_list_iter = plugin_list;
plugin_list_iter;
plugin_list_iter = plugin_list_iter->next)
- if (try_load_plugin (NULL, plugin_list_iter, abfd,FALSE))
- return TRUE;
+ if (try_load_plugin (NULL, plugin_list_iter, abfd, false))
+ return true;
- return FALSE;
+ return false;
}
/* Copy any private info we understand from the input bfd
to the output bfd. */
-static bfd_boolean
+static bool
bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
bfd *obfd ATTRIBUTE_UNUSED)
{
BFD_ASSERT (0);
- return TRUE;
+ return true;
}
/* Copy any private info we understand from the input section
to the output section. */
-static bfd_boolean
+static bool
bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
asection *isection ATTRIBUTE_UNUSED,
bfd *obfd ATTRIBUTE_UNUSED,
asection *osection ATTRIBUTE_UNUSED)
{
BFD_ASSERT (0);
- return TRUE;
+ return true;
}
/* Copy any private info we understand from the input symbol
to the output symbol. */
-static bfd_boolean
+static bool
bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
asymbol *isymbol ATTRIBUTE_UNUSED,
bfd *obfd ATTRIBUTE_UNUSED,
asymbol *osymbol ATTRIBUTE_UNUSED)
{
BFD_ASSERT (0);
- return TRUE;
+ return true;
}
-static bfd_boolean
+static bool
bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, PTR ptr ATTRIBUTE_UNUSED)
{
BFD_ASSERT (0);
- return TRUE;
+ return true;
}
static char *
'/', /* ar_pad_char. */
15, /* ar_max_namelen. */
255, /* match priority. */
+ TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
bfd_getl32, bfd_getl_signed_32, bfd_putl32,