Don't convert GOTPCREL relocation against large section
[deliverable/binutils-gdb.git] / bfd / plugin.c
index 49395e8cb7cf5ec0c205bb93e45e91a8bd3e535e..fd7bac04ece081d124abf3b13597def9cfc13865 100644 (file)
@@ -1,6 +1,5 @@
 /* Plugin support for BFD.
 /* Plugin support for BFD.
-   Copyright 2009
-   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 <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
@@ -44,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
 #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_split_section             _bfd_generic_link_split_section
 #define bfd_plugin_bfd_gc_sections                    bfd_generic_gc_sections
 #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_split_section             _bfd_generic_link_split_section
 #define bfd_plugin_bfd_gc_sections                    bfd_generic_gc_sections
+#define bfd_plugin_bfd_lookup_section_flags           bfd_generic_lookup_section_flags
 #define bfd_plugin_bfd_merge_sections                 bfd_generic_merge_sections
 #define bfd_plugin_bfd_is_group_section               bfd_generic_is_group_section
 #define bfd_plugin_bfd_discard_group                  bfd_generic_discard_group
 #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_merge_sections                 bfd_generic_merge_sections
 #define bfd_plugin_bfd_is_group_section               bfd_generic_is_group_section
 #define bfd_plugin_bfd_discard_group                  bfd_generic_discard_group
 #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,
@@ -73,6 +116,7 @@ message (int level ATTRIBUTE_UNUSED,
   va_start (args, format);
   printf ("bfd plugin: ");
   vprintf (format, args);
   va_start (args, format);
   printf ("bfd plugin: ");
   vprintf (format, args);
+  putchar ('\n');
   va_end (args);
   return LDPS_OK;
 }
   va_end (args);
   return LDPS_OK;
 }
@@ -94,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;
@@ -106,18 +150,70 @@ add_symbols (void * handle,
   return LDPS_OK;
 }
 
   return LDPS_OK;
 }
 
-extern char *program_name __attribute__ ((weak));
+static const char *plugin_program_name;
+
+void
+bfd_plugin_set_program_name (const char *program_name)
+{
+  plugin_program_name = program_name;
+}
 
 static int
 
 static int
-try_load_plugin (const char *pname)
+try_claim (bfd *abfd)
 {
 {
-  static void *plugin_handle;
-  int tv_size = 4;
-  struct ld_plugin_tv tv[tv_size];
+  int claimed = 0;
+  struct ld_plugin_input_file file;
+  bfd *iobfd;
+
+  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 0;
+
+  file.fd = fileno ((FILE *) iobfd->iostream);
+
+  if (!abfd->my_archive)
+    {
+      struct stat stat_buf;
+      if (fstat (file.fd, &stat_buf))
+        return 0;
+      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)
+    return 0;
+
+  return 1;
+}
+
+static int
+try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
+{
+  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)
     {
@@ -150,26 +246,67 @@ 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;
+}
+
+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;
@@ -177,14 +314,17 @@ 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 (!program_name)
-    return 0;
+  if (plugin_program_name == NULL)
+    return found;
 
   plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
 
   plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
-  p = make_relative_prefix (program_name,
+  p = make_relative_prefix (plugin_program_name,
                            BINDIR,
                            plugin_dir);
   free (plugin_dir);
                            BINDIR,
                            plugin_dir);
   free (plugin_dir);
@@ -197,11 +337,14 @@ load_plugin (void)
   while ((ent = readdir (d)))
     {
       char *full_name;
   while ((ent = readdir (d)))
     {
       char *full_name;
-      if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
-       continue;
+      struct stat s;
+      int valid_plugin;
 
       full_name = concat (p, "/", ent->d_name, NULL);
 
       full_name = concat (p, "/", ent->d_name, NULL);
-      found = try_load_plugin (full_name);
+      if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode))
+       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;
@@ -219,35 +362,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;
-  int t = load_plugin ();
-  struct ld_plugin_input_file file;
-  if (!t)
-    return NULL;
+  if (ld_plugin_object_p)
+    return ld_plugin_object_p (abfd);
 
 
-  file.name = abfd->filename;
-
-  if (abfd->iostream)
-    {
-      file.fd = fileno (abfd->iostream);
-      file.offset = 0;
-      file.filesize = 0; /*FIXME*/
-    }
-  else
-    {
-      bfd *archive = abfd->my_archive;
-      BFD_ASSERT (archive);
-      file.fd = fileno (archive->iostream);
-      file.offset = abfd->origin;
-      file.filesize = arelt_size (abfd);
-
-    }
-  file.handle = abfd;
-  claim_file (&file, &claimed);
-  if (!claimed)
+  if (abfd->plugin_format == bfd_plugin_uknown && !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
@@ -308,6 +429,13 @@ bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
   return 0;
 }
 
   return 0;
 }
 
+static int
+bfd_plugin_core_file_pid (bfd *abfd ATTRIBUTE_UNUSED)
+{
+  BFD_ASSERT (0);
+  return 0;
+}
+
 static long
 bfd_plugin_get_symtab_upper_bound (bfd *abfd)
 {
 static long
 bfd_plugin_get_symtab_upper_bound (bfd *abfd)
 {
@@ -323,7 +451,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:
@@ -355,7 +483,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;
@@ -409,11 +537,11 @@ bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
 static asymbol *
 bfd_plugin_make_empty_symbol (bfd *abfd)
 {
 static asymbol *
 bfd_plugin_make_empty_symbol (bfd *abfd)
 {
-  asymbol *new = bfd_zalloc (abfd, sizeof (asymbol));
-  if (new == NULL)
-    return new;
-  new->the_bfd = abfd;
-  return new;
+  asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
+  if (new_symbol == NULL)
+    return new_symbol;
+  new_symbol->the_bfd = abfd;
+  return new_symbol;
 }
 
 static int
 }
 
 static int
@@ -424,13 +552,6 @@ bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
   return 0;
 }
 
   return 0;
 }
 
-static bfd_boolean
-bfd_plugin_mkobject (bfd *abfd ATTRIBUTE_UNUSED)
-{
-  BFD_ASSERT (0);
-  return 0;
-}
-
 const bfd_target plugin_vec =
 {
   "plugin",                    /* Name.  */
 const bfd_target plugin_vec =
 {
   "plugin",                    /* Name.  */
@@ -445,6 +566,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.  */
+  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,
@@ -461,7 +583,7 @@ const bfd_target plugin_vec =
   },
   {                            /* bfd_set_format.  */
     bfd_false,
   },
   {                            /* bfd_set_format.  */
     bfd_false,
-    bfd_plugin_mkobject,
+    bfd_false,
     _bfd_generic_mkarchive,
     bfd_false,
   },
     _bfd_generic_mkarchive,
     bfd_false,
   },
@@ -486,3 +608,4 @@ const bfd_target plugin_vec =
 
   NULL                         /* backend_data.  */
 };
 
   NULL                         /* backend_data.  */
 };
+#endif /* BFD_SUPPORTS_PLUGIN */
This page took 0.029643 seconds and 4 git commands to generate.