Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / plugin.c
index 064e2731282fc43f2698a098614af937d8f6db50..3931d2750b1ec93a84ebadd0f70e4d11a6ba882b 100644 (file)
@@ -1,6 +1,5 @@
 /* Plugin support for BFD.
 /* Plugin support for BFD.
-   Copyright 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 
    This file is part of BFD, the Binary File Descriptor library.
 
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
    MA 02110-1301, USA.  */
 
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
    MA 02110-1301, USA.  */
 
-#include "config.h"
+#include "sysdep.h"
 #include "bfd.h"
 
 #if BFD_SUPPORTS_PLUGINS
 
 #include <assert.h>
 #include "bfd.h"
 
 #if BFD_SUPPORTS_PLUGINS
 
 #include <assert.h>
+#ifdef HAVE_DLFCN_H
 #include <dlfcn.h>
 #include <dlfcn.h>
+#elif defined (HAVE_WINDOWS_H)
+#include <windows.h>
+#else
+#error Unknown how to handle dynamic-load-libraries.
+#endif
 #include <stdarg.h>
 #include "plugin-api.h"
 #include <stdarg.h>
 #include "plugin-api.h"
-#include "sysdep.h"
 #include "plugin.h"
 #include "libbfd.h"
 #include "libiberty.h"
 #include <dirent.h>
 
 #include "plugin.h"
 #include "libbfd.h"
 #include "libiberty.h"
 #include <dirent.h>
 
+#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
+
+#define RTLD_NOW 0      /* Dummy value.  */
+
+static void *
+dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
+{
+  return LoadLibrary (file);
+}
+
+static void *
+dlsym (void *handle, const char *name)
+{
+  return GetProcAddress (handle, name);
+}
+
+static int ATTRIBUTE_UNUSED
+dlclose (void *handle)
+{
+  FreeLibrary (handle);
+  return 0;
+}
+
+static const char *
+dlerror (void)
+{
+  return "Unable to load DLL.";
+}
+
+#endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)  */
+
 #define bfd_plugin_close_and_cleanup                  _bfd_generic_close_and_cleanup
 #define bfd_plugin_bfd_free_cached_info               _bfd_generic_bfd_free_cached_info
 #define bfd_plugin_new_section_hook                   _bfd_generic_new_section_hook
 #define bfd_plugin_close_and_cleanup                  _bfd_generic_close_and_cleanup
 #define bfd_plugin_bfd_free_cached_info               _bfd_generic_bfd_free_cached_info
 #define bfd_plugin_new_section_hook                   _bfd_generic_new_section_hook
@@ -48,7 +83,9 @@
 #define bfd_plugin_bfd_is_target_special_symbol       ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
 #define bfd_plugin_get_lineno                         _bfd_nosymbols_get_lineno
 #define bfd_plugin_find_nearest_line                  _bfd_nosymbols_find_nearest_line
 #define bfd_plugin_bfd_is_target_special_symbol       ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
 #define bfd_plugin_get_lineno                         _bfd_nosymbols_get_lineno
 #define bfd_plugin_find_nearest_line                  _bfd_nosymbols_find_nearest_line
+#define bfd_plugin_find_line                          _bfd_nosymbols_find_line
 #define bfd_plugin_find_inliner_info                  _bfd_nosymbols_find_inliner_info
 #define bfd_plugin_find_inliner_info                  _bfd_nosymbols_find_inliner_info
+#define bfd_plugin_get_symbol_version_string         _bfd_nosymbols_get_symbol_version_string
 #define bfd_plugin_bfd_make_debug_symbol              _bfd_nosymbols_bfd_make_debug_symbol
 #define bfd_plugin_read_minisymbols                   _bfd_generic_read_minisymbols
 #define bfd_plugin_minisymbol_to_symbol               _bfd_generic_minisymbol_to_symbol
 #define bfd_plugin_bfd_make_debug_symbol              _bfd_nosymbols_bfd_make_debug_symbol
 #define bfd_plugin_read_minisymbols                   _bfd_generic_read_minisymbols
 #define bfd_plugin_minisymbol_to_symbol               _bfd_generic_minisymbol_to_symbol
@@ -57,7 +94,6 @@
 #define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
 #define bfd_plugin_bfd_relax_section                  bfd_generic_relax_section
 #define bfd_plugin_bfd_link_hash_table_create         _bfd_generic_link_hash_table_create
 #define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
 #define bfd_plugin_bfd_relax_section                  bfd_generic_relax_section
 #define bfd_plugin_bfd_link_hash_table_create         _bfd_generic_link_hash_table_create
-#define bfd_plugin_bfd_link_hash_table_free           _bfd_generic_link_hash_table_free
 #define bfd_plugin_bfd_link_add_symbols               _bfd_generic_link_add_symbols
 #define bfd_plugin_bfd_link_just_syms                 _bfd_generic_link_just_syms
 #define bfd_plugin_bfd_final_link                     _bfd_generic_final_link
 #define bfd_plugin_bfd_link_add_symbols               _bfd_generic_link_add_symbols
 #define bfd_plugin_bfd_link_just_syms                 _bfd_generic_link_just_syms
 #define bfd_plugin_bfd_final_link                     _bfd_generic_final_link
 #define bfd_plugin_section_already_linked             _bfd_generic_section_already_linked
 #define bfd_plugin_bfd_define_common_symbol           bfd_generic_define_common_symbol
 #define bfd_plugin_bfd_copy_link_hash_symbol_type     _bfd_generic_copy_link_hash_symbol_type
 #define bfd_plugin_section_already_linked             _bfd_generic_section_already_linked
 #define bfd_plugin_bfd_define_common_symbol           bfd_generic_define_common_symbol
 #define bfd_plugin_bfd_copy_link_hash_symbol_type     _bfd_generic_copy_link_hash_symbol_type
+#define bfd_plugin_bfd_link_check_relocs              _bfd_generic_link_check_relocs
 
 static enum ld_plugin_status
 message (int level ATTRIBUTE_UNUSED,
 
 static enum ld_plugin_status
 message (int level ATTRIBUTE_UNUSED,
@@ -101,7 +138,7 @@ add_symbols (void * handle,
 {
   bfd *abfd = handle;
   struct plugin_data_struct *plugin_data =
 {
   bfd *abfd = handle;
   struct plugin_data_struct *plugin_data =
-    bfd_alloc (abfd, sizeof (plugin_data_struct));;
+    bfd_alloc (abfd, sizeof (plugin_data_struct));
 
   plugin_data->nsyms = nsyms;
   plugin_data->syms = syms;
 
   plugin_data->nsyms = nsyms;
   plugin_data->syms = syms;
@@ -121,16 +158,63 @@ bfd_plugin_set_program_name (const char *program_name)
   plugin_program_name = program_name;
 }
 
   plugin_program_name = program_name;
 }
 
+int
+bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
+{
+  bfd *iobfd;
+
+  iobfd = ibfd;
+  if (ibfd->my_archive && !bfd_is_thin_archive (ibfd->my_archive))
+    iobfd = ibfd->my_archive;
+  file->name = iobfd->filename;
+
+  if (!iobfd->iostream && !bfd_open_file (iobfd))
+    return 0;
+
+  file->fd = fileno ((FILE *) iobfd->iostream);
+
+  if (iobfd == ibfd)
+    {
+      struct stat stat_buf;
+      if (fstat (file->fd, &stat_buf))
+        return 0;
+      file->offset = 0;
+      file->filesize = stat_buf.st_size;
+    }
+  else
+    {
+      file->offset = ibfd->origin;
+      file->filesize = arelt_size (ibfd);
+    }
+  return 1;
+}
+
+static int
+try_claim (bfd *abfd)
+{
+  int claimed = 0;
+  struct ld_plugin_input_file file;
+
+  if (!bfd_plugin_open_input (abfd, &file))
+    return 0;
+  file.handle = abfd;
+  off_t cur_offset = lseek (file.fd, 0, SEEK_CUR);
+  claim_file (&file, &claimed);
+  lseek (file.fd, cur_offset, SEEK_SET);
+  return claimed;
+}
+
 static int
 static int
-try_load_plugin (const char *pname)
+try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
 {
 {
-  static void *plugin_handle;
-  int tv_size = 4;
-  struct ld_plugin_tv tv[tv_size];
+  void *plugin_handle;
+  struct ld_plugin_tv tv[4];
   int i;
   ld_plugin_onload onload;
   enum ld_plugin_status status;
 
   int i;
   ld_plugin_onload onload;
   enum ld_plugin_status status;
 
+  *has_plugin_p = 0;
+
   plugin_handle = dlopen (pname, RTLD_NOW);
   if (!plugin_handle)
     {
   plugin_handle = dlopen (pname, RTLD_NOW);
   if (!plugin_handle)
     {
@@ -163,26 +247,77 @@ try_load_plugin (const char *pname)
   if (status != LDPS_OK)
     goto err;
 
   if (status != LDPS_OK)
     goto err;
 
+  *has_plugin_p = 1;
+
+  abfd->plugin_format = bfd_plugin_no;
+
   if (!claim_file)
     goto err;
 
   if (!claim_file)
     goto err;
 
+  if (!try_claim (abfd))
+    goto err;
+
+  abfd->plugin_format = bfd_plugin_yes;
+
   return 1;
 
  err:
   return 1;
 
  err:
-  plugin_handle = NULL;
   return 0;
 }
 
   return 0;
 }
 
+/* There may be plugin libraries in lib/bfd-plugins.  */
+
+static int has_plugin = -1;
+
+static const bfd_target *(*ld_plugin_object_p) (bfd *);
+
 static const char *plugin_name;
 
 void
 bfd_plugin_set_plugin (const char *p)
 {
   plugin_name = p;
 static const char *plugin_name;
 
 void
 bfd_plugin_set_plugin (const char *p)
 {
   plugin_name = p;
+  has_plugin = p != NULL;
+}
+
+/* Return TRUE if a plugin library is used.  */
+
+bfd_boolean
+bfd_plugin_specified_p (void)
+{
+  return has_plugin > 0;
+}
+
+/* Return TRUE if ABFD can be claimed by linker LTO plugin.  */
+
+bfd_boolean
+bfd_link_plugin_object_p (bfd *abfd)
+{
+  if (ld_plugin_object_p)
+    return ld_plugin_object_p (abfd) != NULL;
+  return FALSE;
+}
+
+extern const bfd_target plugin_vec;
+
+/* Return TRUE if TARGET is a pointer to plugin_vec.  */
+
+bfd_boolean
+bfd_plugin_target_p (const bfd_target *target)
+{
+  return target == &plugin_vec;
+}
+
+/* Register OBJECT_P to be used by bfd_plugin_object_p.  */
+
+void
+register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *))
+{
+  ld_plugin_object_p = object_p;
 }
 
 static int
 }
 
 static int
-load_plugin (void)
+load_plugin (bfd *abfd)
 {
   char *plugin_dir;
   char *p;
 {
   char *plugin_dir;
   char *p;
@@ -190,11 +325,14 @@ load_plugin (void)
   struct dirent *ent;
   int found = 0;
 
   struct dirent *ent;
   int found = 0;
 
+  if (!has_plugin)
+    return found;
+
   if (plugin_name)
   if (plugin_name)
-    return try_load_plugin (plugin_name);
+    return try_load_plugin (plugin_name, abfd, &has_plugin);
 
   if (plugin_program_name == NULL)
 
   if (plugin_program_name == NULL)
-    return 0;
+    return found;
 
   plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
   p = make_relative_prefix (plugin_program_name,
 
   plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
   p = make_relative_prefix (plugin_program_name,
@@ -211,10 +349,13 @@ load_plugin (void)
     {
       char *full_name;
       struct stat s;
     {
       char *full_name;
       struct stat s;
+      int valid_plugin;
 
       full_name = concat (p, "/", ent->d_name, NULL);
       if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode))
 
       full_name = concat (p, "/", ent->d_name, NULL);
       if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode))
-       found = try_load_plugin (full_name);
+       found = try_load_plugin (full_name, abfd, &valid_plugin);
+      if (has_plugin <= 0)
+       has_plugin = valid_plugin;
       free (full_name);
       if (found)
        break;
       free (full_name);
       if (found)
        break;
@@ -232,56 +373,13 @@ load_plugin (void)
 static const bfd_target *
 bfd_plugin_object_p (bfd *abfd)
 {
 static const bfd_target *
 bfd_plugin_object_p (bfd *abfd)
 {
-  int claimed = 0;
-  struct ld_plugin_input_file file;
-  bfd *iobfd;
-  static int have_loaded = 0;
-  static int have_plugin = 0;
-
-  if (!have_loaded)
-    {
-      have_loaded = 1;
-      have_plugin = load_plugin ();
-    }
-  if (!have_plugin)
-    return NULL;
-
-  file.name = abfd->filename;
-
-  if (abfd->my_archive)
-    {
-      iobfd = abfd->my_archive;
-      file.offset = abfd->origin;
-      file.filesize = arelt_size (abfd);
-    }
-  else
-    {
-      iobfd = abfd;
-      file.offset = 0;
-      file.filesize = 0;
-    }
-
-  if (!iobfd->iostream && !bfd_open_file (iobfd))
-    return NULL;
-
-  file.fd = fileno ((FILE *) iobfd->iostream);
+  if (ld_plugin_object_p)
+    return ld_plugin_object_p (abfd);
 
 
-  if (!abfd->my_archive)
-    {
-      struct stat stat_buf;
-      if (fstat (file.fd, &stat_buf))
-        return NULL;
-      file.filesize = stat_buf.st_size;
-    }
-
-  file.handle = abfd;
-  off_t cur_offset = lseek(file.fd, 0, SEEK_CUR);
-  claim_file (&file, &claimed);
-  lseek(file.fd, cur_offset, SEEK_SET);
-  if (!claimed)
+  if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd))
     return NULL;
 
     return NULL;
 
-  return abfd->xvec;
+  return abfd->plugin_format == bfd_plugin_yes ? abfd->xvec : NULL;
 }
 
 /* Copy any private info we understand from the input bfd
 }
 
 /* Copy any private info we understand from the input bfd
@@ -364,7 +462,7 @@ static flagword
 convert_flags (const struct ld_plugin_symbol *sym)
 {
  switch (sym->def)
 convert_flags (const struct ld_plugin_symbol *sym)
 {
  switch (sym->def)
-   { 
+   {
    case LDPK_DEF:
    case LDPK_COMMON:
    case LDPK_UNDEF:
    case LDPK_DEF:
    case LDPK_COMMON:
    case LDPK_UNDEF:
@@ -396,7 +494,7 @@ bfd_plugin_canonicalize_symtab (bfd *abfd,
 
   for (i = 0; i < nsyms; i++)
     {
 
   for (i = 0; i < nsyms; i++)
     {
-      asymbol *s = bfd_alloc (abfd, sizeof (asymbol)); 
+      asymbol *s = bfd_alloc (abfd, sizeof (asymbol));
 
       BFD_ASSERT (s);
       alocation[i] = s;
 
       BFD_ASSERT (s);
       alocation[i] = s;
@@ -479,7 +577,7 @@ const bfd_target plugin_vec =
   0,                           /* symbol_leading_char.  */
   '/',                         /* ar_pad_char.  */
   15,                          /* ar_max_namelen.  */
   0,                           /* symbol_leading_char.  */
   '/',                         /* ar_pad_char.  */
   15,                          /* ar_max_namelen.  */
-  0,                           /* match priority.  */
+  255,                         /* match priority.  */
 
   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
 
   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
@@ -510,7 +608,11 @@ const bfd_target plugin_vec =
   BFD_JUMP_TABLE_GENERIC (bfd_plugin),
   BFD_JUMP_TABLE_COPY (bfd_plugin),
   BFD_JUMP_TABLE_CORE (bfd_plugin),
   BFD_JUMP_TABLE_GENERIC (bfd_plugin),
   BFD_JUMP_TABLE_COPY (bfd_plugin),
   BFD_JUMP_TABLE_CORE (bfd_plugin),
+#ifdef USE_64_BIT_ARCHIVE
+  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_64_bit),
+#else
   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+#endif
   BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
   BFD_JUMP_TABLE_WRITE (bfd_plugin),
   BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
   BFD_JUMP_TABLE_WRITE (bfd_plugin),
This page took 0.028805 seconds and 4 git commands to generate.