(root)/
binutils-2.41/
bfd/
plugin.c
       1  /* Plugin support for BFD.
       2     Copyright (C) 2009-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of BFD, the Binary File Descriptor library.
       5  
       6     This program is free software; you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3 of the License, or
       9     (at your option) any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program; if not, write to the Free Software
      18     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      19     MA 02110-1301, USA.  */
      20  
      21  #include "sysdep.h"
      22  #include "bfd.h"
      23  
      24  #if BFD_SUPPORTS_PLUGINS
      25  
      26  #include <assert.h>
      27  #ifdef HAVE_DLFCN_H
      28  #include <dlfcn.h>
      29  #elif defined (HAVE_WINDOWS_H)
      30  #include <windows.h>
      31  #else
      32  #error Unknown how to handle dynamic-load-libraries.
      33  #endif
      34  #include <stdarg.h>
      35  #include "plugin-api.h"
      36  #include "plugin.h"
      37  #include "libbfd.h"
      38  #include "libiberty.h"
      39  #include <dirent.h>
      40  
      41  #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
      42  
      43  #define RTLD_NOW 0      /* Dummy value.  */
      44  
      45  static void *
      46  dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
      47  {
      48    return LoadLibrary (file);
      49  }
      50  
      51  static void *
      52  dlsym (void *handle, const char *name)
      53  {
      54    return GetProcAddress (handle, name);
      55  }
      56  
      57  static int ATTRIBUTE_UNUSED
      58  dlclose (void *handle)
      59  {
      60    FreeLibrary (handle);
      61    return 0;
      62  }
      63  
      64  static const char *
      65  dlerror (void)
      66  {
      67    return "Unable to load DLL.";
      68  }
      69  
      70  #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)  */
      71  
      72  #define bfd_plugin_close_and_cleanup		      _bfd_generic_close_and_cleanup
      73  #define bfd_plugin_bfd_free_cached_info		      _bfd_generic_bfd_free_cached_info
      74  #define bfd_plugin_new_section_hook		      _bfd_generic_new_section_hook
      75  #define bfd_plugin_get_section_contents		      _bfd_generic_get_section_contents
      76  #define bfd_plugin_get_section_contents_in_window     _bfd_generic_get_section_contents_in_window
      77  #define bfd_plugin_bfd_copy_private_header_data	      _bfd_generic_bfd_copy_private_header_data
      78  #define bfd_plugin_bfd_merge_private_bfd_data	      _bfd_generic_bfd_merge_private_bfd_data
      79  #define bfd_plugin_bfd_copy_private_header_data	      _bfd_generic_bfd_copy_private_header_data
      80  #define bfd_plugin_bfd_set_private_flags	      _bfd_generic_bfd_set_private_flags
      81  #define bfd_plugin_core_file_matches_executable_p     generic_core_file_matches_executable_p
      82  #define bfd_plugin_bfd_is_local_label_name	      _bfd_nosymbols_bfd_is_local_label_name
      83  #define bfd_plugin_bfd_is_target_special_symbol	      _bfd_bool_bfd_asymbol_false
      84  #define bfd_plugin_get_lineno			      _bfd_nosymbols_get_lineno
      85  #define bfd_plugin_find_nearest_line		      _bfd_nosymbols_find_nearest_line
      86  #define bfd_plugin_find_nearest_line_with_alt	      _bfd_nosymbols_find_nearest_line_with_alt
      87  #define bfd_plugin_find_line			      _bfd_nosymbols_find_line
      88  #define bfd_plugin_find_inliner_info		      _bfd_nosymbols_find_inliner_info
      89  #define bfd_plugin_get_symbol_version_string	      _bfd_nosymbols_get_symbol_version_string
      90  #define bfd_plugin_bfd_make_debug_symbol	      _bfd_nosymbols_bfd_make_debug_symbol
      91  #define bfd_plugin_read_minisymbols		      _bfd_generic_read_minisymbols
      92  #define bfd_plugin_minisymbol_to_symbol		      _bfd_generic_minisymbol_to_symbol
      93  #define bfd_plugin_set_arch_mach		      bfd_default_set_arch_mach
      94  #define bfd_plugin_set_section_contents		      _bfd_generic_set_section_contents
      95  #define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
      96  #define bfd_plugin_bfd_relax_section		      bfd_generic_relax_section
      97  #define bfd_plugin_bfd_link_hash_table_create	      _bfd_generic_link_hash_table_create
      98  #define bfd_plugin_bfd_link_add_symbols		      _bfd_generic_link_add_symbols
      99  #define bfd_plugin_bfd_link_just_syms		      _bfd_generic_link_just_syms
     100  #define bfd_plugin_bfd_final_link		      _bfd_generic_final_link
     101  #define bfd_plugin_bfd_link_split_section	      _bfd_generic_link_split_section
     102  #define bfd_plugin_bfd_gc_sections		      bfd_generic_gc_sections
     103  #define bfd_plugin_bfd_lookup_section_flags	      bfd_generic_lookup_section_flags
     104  #define bfd_plugin_bfd_merge_sections		      bfd_generic_merge_sections
     105  #define bfd_plugin_bfd_is_group_section		      bfd_generic_is_group_section
     106  #define bfd_plugin_bfd_group_name		      bfd_generic_group_name
     107  #define bfd_plugin_bfd_discard_group		      bfd_generic_discard_group
     108  #define bfd_plugin_section_already_linked	      _bfd_generic_section_already_linked
     109  #define bfd_plugin_bfd_define_common_symbol	      bfd_generic_define_common_symbol
     110  #define bfd_plugin_bfd_link_hide_symbol		      _bfd_generic_link_hide_symbol
     111  #define bfd_plugin_bfd_define_start_stop	      bfd_generic_define_start_stop
     112  #define bfd_plugin_bfd_copy_link_hash_symbol_type     _bfd_generic_copy_link_hash_symbol_type
     113  #define bfd_plugin_bfd_link_check_relocs	      _bfd_generic_link_check_relocs
     114  
     115  static enum ld_plugin_status
     116  message (int level ATTRIBUTE_UNUSED,
     117  	 const char * format, ...)
     118  {
     119    va_list args;
     120    va_start (args, format);
     121    printf ("bfd plugin: ");
     122    vprintf (format, args);
     123    putchar ('\n');
     124    va_end (args);
     125    return LDPS_OK;
     126  }
     127  
     128  struct plugin_list_entry
     129  {
     130    /* These must be initialized for each IR object with LTO wrapper.  */
     131    ld_plugin_claim_file_handler claim_file;
     132    ld_plugin_claim_file_handler_v2 claim_file_v2;
     133    ld_plugin_all_symbols_read_handler all_symbols_read;
     134    ld_plugin_all_symbols_read_handler cleanup_handler;
     135    bool has_symbol_type;
     136  
     137    struct plugin_list_entry *next;
     138  
     139    /* These can be reused for all IR objects.  */
     140    const char *plugin_name;
     141  };
     142  
     143  static const char *plugin_program_name;
     144  
     145  void
     146  bfd_plugin_set_program_name (const char *program_name)
     147  {
     148    plugin_program_name = program_name;
     149  }
     150  
     151  static struct plugin_list_entry *plugin_list = NULL;
     152  static struct plugin_list_entry *current_plugin = NULL;
     153  
     154  /* Register a claim-file handler. */
     155  
     156  static enum ld_plugin_status
     157  register_claim_file (ld_plugin_claim_file_handler handler)
     158  {
     159    current_plugin->claim_file = handler;
     160    return LDPS_OK;
     161  }
     162  
     163  
     164  /* Register a claim-file handler, version 2. */
     165  
     166  static enum ld_plugin_status
     167  register_claim_file_v2 (ld_plugin_claim_file_handler_v2 handler)
     168  {
     169    current_plugin->claim_file_v2 = handler;
     170    return LDPS_OK;
     171  }
     172  
     173  static enum ld_plugin_status
     174  add_symbols (void * handle,
     175  	     int nsyms,
     176  	     const struct ld_plugin_symbol * syms)
     177  {
     178    bfd *abfd = handle;
     179    struct plugin_data_struct *plugin_data =
     180      bfd_alloc (abfd, sizeof (plugin_data_struct));
     181  
     182    if (!plugin_data)
     183      return LDPS_ERR;
     184  
     185    plugin_data->nsyms = nsyms;
     186    plugin_data->syms = syms;
     187  
     188    if (nsyms != 0)
     189      abfd->flags |= HAS_SYMS;
     190  
     191    abfd->tdata.plugin_data = plugin_data;
     192    return LDPS_OK;
     193  }
     194  
     195  static enum ld_plugin_status
     196  add_symbols_v2 (void *handle, int nsyms,
     197  		const struct ld_plugin_symbol *syms)
     198  {
     199    current_plugin->has_symbol_type = true;
     200    return add_symbols (handle, nsyms, syms);
     201  }
     202  
     203  int
     204  bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
     205  {
     206    bfd *iobfd;
     207    int fd;
     208  
     209    iobfd = ibfd;
     210    while (iobfd->my_archive
     211  	 && !bfd_is_thin_archive (iobfd->my_archive))
     212      iobfd = iobfd->my_archive;
     213    file->name = bfd_get_filename (iobfd);
     214  
     215    if (!iobfd->iostream && !bfd_open_file (iobfd))
     216      return 0;
     217  
     218    /* Reuse the archive plugin file descriptor.  */
     219    if (iobfd != ibfd)
     220      fd = iobfd->archive_plugin_fd;
     221    else
     222      fd = -1;
     223  
     224    if (fd < 0)
     225      {
     226        /* The plugin API expects that the file descriptor won't be closed
     227  	 and reused as done by the bfd file cache.  So open it again.
     228  	 dup isn't good enough.  plugin IO uses lseek/read while BFD uses
     229  	 fseek/fread.  It isn't wise to mix the unistd and stdio calls on
     230  	 the same underlying file descriptor.  */
     231        fd = open (file->name, O_RDONLY | O_BINARY);
     232        if (fd < 0)
     233  	{
     234  #ifndef EMFILE
     235  	  return 0;
     236  #else
     237  	  if (errno != EMFILE)
     238  	    return 0;
     239  
     240  #ifdef HAVE_GETRLIMIT
     241  	  struct rlimit lim;
     242  
     243  	  /* Complicated links involving lots of files and/or large
     244  	     archives can exhaust the number of file descriptors
     245  	     available to us.  If possible, try to allocate more
     246  	     descriptors.  */
     247  	  if (getrlimit (RLIMIT_NOFILE, & lim) == 0
     248  	      && lim.rlim_cur < lim.rlim_max)
     249  	    {
     250  	      lim.rlim_cur = lim.rlim_max;
     251  	      if (setrlimit (RLIMIT_NOFILE, &lim) == 0)
     252  		fd = open (file->name, O_RDONLY | O_BINARY);
     253  	    }
     254  
     255  	  if (fd < 0)
     256  #endif
     257  	    {
     258  	      _bfd_error_handler (_("plugin framework: out of file descriptors. Try using fewer objects/archives\n"));
     259  	      return 0;
     260  	    }
     261  #endif
     262  	}
     263      }
     264  
     265    if (iobfd == ibfd)
     266      {
     267        struct stat stat_buf;
     268  
     269        if (fstat (fd, &stat_buf))
     270  	{
     271  	  close (fd);
     272  	  return 0;
     273  	}
     274  
     275        file->offset = 0;
     276        file->filesize = stat_buf.st_size;
     277      }
     278    else
     279      {
     280        /* Cache the archive plugin file descriptor.  */
     281        iobfd->archive_plugin_fd = fd;
     282        iobfd->archive_plugin_fd_open_count++;
     283  
     284        file->offset = ibfd->origin;
     285        file->filesize = arelt_size (ibfd);
     286      }
     287  
     288    file->fd = fd;
     289    return 1;
     290  }
     291  
     292  /* Close the plugin file descriptor FD.  If ABFD isn't NULL, it is an
     293     archive member.   */
     294  
     295  void
     296  bfd_plugin_close_file_descriptor (bfd *abfd, int fd)
     297  {
     298    if (abfd == NULL)
     299      close (fd);
     300    else
     301      {
     302        while (abfd->my_archive
     303  	     && !bfd_is_thin_archive (abfd->my_archive))
     304  	abfd = abfd->my_archive;
     305  
     306        /* Close the file descriptor if there is no archive plugin file
     307  	 descriptor.  */
     308        if (abfd->archive_plugin_fd == -1)
     309  	{
     310  	  close (fd);
     311  	  return;
     312  	}
     313  
     314        abfd->archive_plugin_fd_open_count--;
     315        /* Dup the archive plugin file descriptor for later use, which
     316  	 will be closed by _bfd_archive_close_and_cleanup.  */
     317        if (abfd->archive_plugin_fd_open_count == 0)
     318  	{
     319  	  abfd->archive_plugin_fd = dup (fd);
     320  	  close (fd);
     321  	}
     322      }
     323  }
     324  
     325  static int
     326  try_claim (bfd *abfd)
     327  {
     328    int claimed = 0;
     329    struct ld_plugin_input_file file;
     330  
     331    file.handle = abfd;
     332    if (bfd_plugin_open_input (abfd, &file)
     333        && current_plugin->claim_file)
     334      {
     335        current_plugin->claim_file (&file, &claimed);
     336        bfd_plugin_close_file_descriptor ((abfd->my_archive != NULL
     337  					 ? abfd : NULL),
     338  					file.fd);
     339      }
     340  
     341    return claimed;
     342  }
     343  
     344  static bool
     345  try_load_plugin (const char *pname,
     346  		 struct plugin_list_entry *plugin_list_iter,
     347  		 bfd *abfd,
     348  		 bool build_list_p)
     349  {
     350    void *plugin_handle;
     351    struct ld_plugin_tv tv[6];
     352    int i;
     353    ld_plugin_onload onload;
     354    enum ld_plugin_status status;
     355    bool result = false;
     356  
     357    /* NB: Each object is independent.  Reuse the previous plugin from
     358       the last run will lead to wrong result.  */
     359    if (current_plugin)
     360      memset (current_plugin, 0,
     361  	    offsetof (struct plugin_list_entry, next));
     362  
     363    if (plugin_list_iter)
     364      pname = plugin_list_iter->plugin_name;
     365  
     366    plugin_handle = dlopen (pname, RTLD_NOW);
     367    if (!plugin_handle)
     368      {
     369        /* If we are building a list of viable plugins, then
     370  	 we do not bother the user with the details of any
     371  	 plugins that cannot be loaded.  */
     372        if (! build_list_p)
     373  	_bfd_error_handler ("Failed to load plugin '%s', reason: %s\n",
     374  			    pname, dlerror ());
     375        return false;
     376      }
     377  
     378    if (plugin_list_iter == NULL)
     379      {
     380        size_t length_plugin_name = strlen (pname) + 1;
     381        char *plugin_name = bfd_malloc (length_plugin_name);
     382  
     383        if (plugin_name == NULL)
     384  	goto short_circuit;
     385        plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
     386        if (plugin_list_iter == NULL)
     387  	{
     388  	  free (plugin_name);
     389  	  goto short_circuit;
     390  	}
     391        /* Make a copy of PNAME since PNAME from load_plugin () will be
     392  	 freed.  */
     393        memcpy (plugin_name, pname, length_plugin_name);
     394        memset (plugin_list_iter, 0, sizeof (*plugin_list_iter));
     395        plugin_list_iter->plugin_name = plugin_name;
     396        plugin_list_iter->next = plugin_list;
     397        plugin_list = plugin_list_iter;
     398      }
     399  
     400    current_plugin = plugin_list_iter;
     401    if (build_list_p)
     402      goto short_circuit;
     403  
     404    onload = dlsym (plugin_handle, "onload");
     405    if (!onload)
     406      goto short_circuit;
     407  
     408    i = 0;
     409    tv[i].tv_tag = LDPT_MESSAGE;
     410    tv[i].tv_u.tv_message = message;
     411  
     412    ++i;
     413    tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
     414    tv[i].tv_u.tv_register_claim_file = register_claim_file;
     415  
     416    ++i;
     417    tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK_V2;
     418    tv[i].tv_u.tv_register_claim_file_v2 = register_claim_file_v2;
     419  
     420    ++i;
     421    tv[i].tv_tag = LDPT_ADD_SYMBOLS;
     422    tv[i].tv_u.tv_add_symbols = add_symbols;
     423  
     424    ++i;
     425    tv[i].tv_tag = LDPT_ADD_SYMBOLS_V2;
     426    tv[i].tv_u.tv_add_symbols = add_symbols_v2;
     427  
     428    ++i;
     429    tv[i].tv_tag = LDPT_NULL;
     430    tv[i].tv_u.tv_val = 0;
     431  
     432    /* LTO plugin will call handler hooks to set up plugin handlers.  */
     433    status = (*onload)(tv);
     434  
     435    if (status != LDPS_OK)
     436      goto short_circuit;
     437  
     438    abfd->plugin_format = bfd_plugin_no;
     439  
     440    if (!current_plugin->claim_file)
     441      goto short_circuit;
     442  
     443    if (!try_claim (abfd))
     444      goto short_circuit;
     445  
     446    abfd->plugin_format = bfd_plugin_yes;
     447    result = true;
     448  
     449   short_circuit:
     450    dlclose (plugin_handle);
     451    return result;
     452  }
     453  
     454  /* There may be plugin libraries in lib/bfd-plugins.  */
     455  static int has_plugin_list = -1;
     456  
     457  static bfd_cleanup (*ld_plugin_object_p) (bfd *, bool);
     458  
     459  static const char *plugin_name;
     460  
     461  void
     462  bfd_plugin_set_plugin (const char *p)
     463  {
     464    plugin_name = p;
     465  }
     466  
     467  /* Return TRUE if a plugin library is used.  */
     468  
     469  bool
     470  bfd_plugin_specified_p (void)
     471  {
     472    return plugin_list != NULL;
     473  }
     474  
     475  /* Return TRUE if ABFD can be claimed by linker LTO plugin.  */
     476  
     477  bool
     478  bfd_link_plugin_object_p (bfd *abfd)
     479  {
     480    if (ld_plugin_object_p)
     481      return ld_plugin_object_p (abfd, false) != NULL;
     482    return false;
     483  }
     484  
     485  extern const bfd_target plugin_vec;
     486  
     487  /* Return TRUE if TARGET is a pointer to plugin_vec.  */
     488  
     489  bool
     490  bfd_plugin_target_p (const bfd_target *target)
     491  {
     492    return target == &plugin_vec;
     493  }
     494  
     495  /* Register OBJECT_P to be used by bfd_plugin_object_p.  */
     496  
     497  void
     498  register_ld_plugin_object_p (bfd_cleanup (*object_p) (bfd *, bool))
     499  {
     500    ld_plugin_object_p = object_p;
     501  }
     502  
     503  static void
     504  build_plugin_list (bfd *abfd)
     505  {
     506    /* The intent was to search ${libdir}/bfd-plugins for plugins, but
     507       unfortunately the original implementation wasn't precisely that
     508       when configuring binutils using --libdir.  Search in the proper
     509       path first, then the old one for backwards compatibility.  */
     510    static const char *path[]
     511      = { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" };
     512    struct stat last_st;
     513    unsigned int i;
     514  
     515    if (has_plugin_list >= 0)
     516      return;
     517  
     518    /* Try not to search the same dir twice, by looking at st_dev and
     519       st_ino for the dir.  If we are on a file system that always sets
     520       st_ino to zero or the actual st_ino is zero we might waste some
     521       time, but that doesn't matter too much.  */
     522    last_st.st_dev = 0;
     523    last_st.st_ino = 0;
     524    for (i = 0; i < sizeof (path) / sizeof (path[0]); i++)
     525      {
     526        char *plugin_dir = make_relative_prefix (plugin_program_name,
     527  					       BINDIR,
     528  					       path[i]);
     529        if (plugin_dir)
     530  	{
     531  	  struct stat st;
     532  	  DIR *d;
     533  
     534  	  if (stat (plugin_dir, &st) == 0
     535  	      && S_ISDIR (st.st_mode)
     536  	      && !(last_st.st_dev == st.st_dev
     537  		   && last_st.st_ino == st.st_ino
     538  		   && st.st_ino != 0)
     539  	      && (d = opendir (plugin_dir)) != NULL)
     540  	    {
     541  	      struct dirent *ent;
     542  
     543  	      last_st.st_dev = st.st_dev;
     544  	      last_st.st_ino = st.st_ino;
     545  	      while ((ent = readdir (d)) != NULL)
     546  		{
     547  		  char *full_name;
     548  
     549  		  full_name = concat (plugin_dir, "/", ent->d_name, NULL);
     550  		  if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
     551  		    (void) try_load_plugin (full_name, NULL, abfd, true);
     552  		  free (full_name);
     553  		}
     554  	      closedir (d);
     555  	    }
     556  	  free (plugin_dir);
     557  	}
     558      }
     559  
     560    has_plugin_list = plugin_list != NULL;
     561  }
     562  
     563  static bool
     564  load_plugin (bfd *abfd)
     565  {
     566    struct plugin_list_entry *plugin_list_iter;
     567  
     568    if (plugin_name)
     569      return try_load_plugin (plugin_name, plugin_list, abfd, false);
     570  
     571    if (plugin_program_name == NULL)
     572      return false;
     573  
     574    build_plugin_list (abfd);
     575  
     576    for (plugin_list_iter = plugin_list;
     577         plugin_list_iter;
     578         plugin_list_iter = plugin_list_iter->next)
     579      if (try_load_plugin (NULL, plugin_list_iter, abfd, false))
     580        return true;
     581  
     582    return false;
     583  }
     584  
     585  
     586  static bfd_cleanup
     587  bfd_plugin_object_p (bfd *abfd)
     588  {
     589    if (ld_plugin_object_p)
     590      return ld_plugin_object_p (abfd, false);
     591  
     592    if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd))
     593      return NULL;
     594  
     595    return abfd->plugin_format == bfd_plugin_yes ? _bfd_no_cleanup : NULL;
     596  }
     597  
     598  /* Copy any private info we understand from the input bfd
     599     to the output bfd.  */
     600  
     601  static bool
     602  bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
     603  				      bfd *obfd ATTRIBUTE_UNUSED)
     604  {
     605    BFD_ASSERT (0);
     606    return true;
     607  }
     608  
     609  /* Copy any private info we understand from the input section
     610     to the output section.  */
     611  
     612  static bool
     613  bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
     614  					  asection *isection ATTRIBUTE_UNUSED,
     615  					  bfd *obfd ATTRIBUTE_UNUSED,
     616  					  asection *osection ATTRIBUTE_UNUSED)
     617  {
     618    BFD_ASSERT (0);
     619    return true;
     620  }
     621  
     622  /* Copy any private info we understand from the input symbol
     623     to the output symbol.  */
     624  
     625  static bool
     626  bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
     627  					 asymbol *isymbol ATTRIBUTE_UNUSED,
     628  					 bfd *obfd ATTRIBUTE_UNUSED,
     629  					 asymbol *osymbol ATTRIBUTE_UNUSED)
     630  {
     631    BFD_ASSERT (0);
     632    return true;
     633  }
     634  
     635  static bool
     636  bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, void *ptr ATTRIBUTE_UNUSED)
     637  {
     638    BFD_ASSERT (0);
     639    return true;
     640  }
     641  
     642  static char *
     643  bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
     644  {
     645    BFD_ASSERT (0);
     646    return NULL;
     647  }
     648  
     649  static int
     650  bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
     651  {
     652    BFD_ASSERT (0);
     653    return 0;
     654  }
     655  
     656  static int
     657  bfd_plugin_core_file_pid (bfd *abfd ATTRIBUTE_UNUSED)
     658  {
     659    BFD_ASSERT (0);
     660    return 0;
     661  }
     662  
     663  static long
     664  bfd_plugin_get_symtab_upper_bound (bfd *abfd)
     665  {
     666    struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
     667    long nsyms = plugin_data->nsyms;
     668  
     669    BFD_ASSERT (nsyms >= 0);
     670  
     671    return ((nsyms + 1) * sizeof (asymbol *));
     672  }
     673  
     674  static flagword
     675  convert_flags (const struct ld_plugin_symbol *sym)
     676  {
     677   switch (sym->def)
     678     {
     679     case LDPK_DEF:
     680     case LDPK_COMMON:
     681     case LDPK_UNDEF:
     682       return BSF_GLOBAL;
     683  
     684     case LDPK_WEAKUNDEF:
     685     case LDPK_WEAKDEF:
     686       return BSF_GLOBAL | BSF_WEAK;
     687  
     688     default:
     689       BFD_ASSERT (0);
     690       return 0;
     691     }
     692  }
     693  
     694  static long
     695  bfd_plugin_canonicalize_symtab (bfd *abfd,
     696  				asymbol **alocation)
     697  {
     698    struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
     699    long nsyms = plugin_data->nsyms;
     700    const struct ld_plugin_symbol *syms = plugin_data->syms;
     701    static asection fake_text_section
     702      = BFD_FAKE_SECTION (fake_text_section, NULL, "plug", 0,
     703  			SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
     704    static asection fake_data_section
     705      = BFD_FAKE_SECTION (fake_data_section, NULL, "plug", 0,
     706  			SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS);
     707    static asection fake_bss_section
     708      = BFD_FAKE_SECTION (fake_bss_section, NULL, "plug", 0,
     709  			SEC_ALLOC);
     710    static asection fake_common_section
     711      = BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON);
     712    int i;
     713  
     714    for (i = 0; i < nsyms; i++)
     715      {
     716        asymbol *s = bfd_alloc (abfd, sizeof (asymbol));
     717  
     718        BFD_ASSERT (s);
     719        alocation[i] = s;
     720  
     721        s->the_bfd = abfd;
     722        s->name = syms[i].name;
     723        s->value = 0;
     724        s->flags = convert_flags (&syms[i]);
     725        switch (syms[i].def)
     726  	{
     727  	case LDPK_COMMON:
     728  	  s->section = &fake_common_section;
     729  	  break;
     730  	case LDPK_UNDEF:
     731  	case LDPK_WEAKUNDEF:
     732  	  s->section = bfd_und_section_ptr;
     733  	  break;
     734  	case LDPK_DEF:
     735  	case LDPK_WEAKDEF:
     736  	  if (current_plugin->has_symbol_type)
     737  	    switch (syms[i].symbol_type)
     738  	      {
     739  	      default:
     740  		/* FIXME: Should we issue an error here ?  */
     741  	      case LDST_UNKNOWN:
     742  		/* What is the best fake section for LDST_UNKNOWN?  */
     743  	      case LDST_FUNCTION:
     744  		s->section = &fake_text_section;
     745  		break;
     746  	      case LDST_VARIABLE:
     747  		if (syms[i].section_kind == LDSSK_BSS)
     748  		  s->section = &fake_bss_section;
     749  		else
     750  		  s->section = &fake_data_section;
     751  		break;
     752  	      }
     753  	  else
     754  	    s->section = &fake_text_section;
     755  	  break;
     756  	default:
     757  	  BFD_ASSERT (0);
     758  	}
     759  
     760        s->udata.p = (void *) &syms[i];
     761      }
     762  
     763    return nsyms;
     764  }
     765  
     766  static void
     767  bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
     768  			 void *afile ATTRIBUTE_UNUSED,
     769  			 asymbol *symbol ATTRIBUTE_UNUSED,
     770  			 bfd_print_symbol_type how ATTRIBUTE_UNUSED)
     771  {
     772    BFD_ASSERT (0);
     773  }
     774  
     775  static void
     776  bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
     777  			    asymbol *symbol,
     778  			    symbol_info *ret)
     779  {
     780    bfd_symbol_info (symbol, ret);
     781  }
     782  
     783  /* Make an empty symbol. */
     784  
     785  static asymbol *
     786  bfd_plugin_make_empty_symbol (bfd *abfd)
     787  {
     788    asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
     789    if (new_symbol == NULL)
     790      return new_symbol;
     791    new_symbol->the_bfd = abfd;
     792    return new_symbol;
     793  }
     794  
     795  static int
     796  bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
     797  			   struct bfd_link_info *info ATTRIBUTE_UNUSED)
     798  {
     799    BFD_ASSERT (0);
     800    return 0;
     801  }
     802  
     803  const bfd_target plugin_vec =
     804  {
     805    "plugin",			/* Name.  */
     806    bfd_target_unknown_flavour,
     807    BFD_ENDIAN_LITTLE,		/* Target byte order.  */
     808    BFD_ENDIAN_LITTLE,		/* Target headers byte order.  */
     809    (HAS_RELOC | EXEC_P |		/* Object flags.  */
     810     HAS_LINENO | HAS_DEBUG |
     811     HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
     812    (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
     813     | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
     814    0,				/* symbol_leading_char.  */
     815    '/',				/* ar_pad_char.  */
     816    15,				/* ar_max_namelen.  */
     817    255,				/* match priority.  */
     818    TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
     819  
     820    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
     821    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
     822    bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* data */
     823    bfd_getl64, bfd_getl_signed_64, bfd_putl64,
     824    bfd_getl32, bfd_getl_signed_32, bfd_putl32,
     825    bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* hdrs */
     826  
     827    {				/* bfd_check_format.  */
     828      _bfd_dummy_target,
     829      bfd_plugin_object_p,
     830      bfd_generic_archive_p,
     831      _bfd_dummy_target
     832    },
     833    {				/* bfd_set_format.  */
     834      _bfd_bool_bfd_false_error,
     835      _bfd_bool_bfd_false_error,
     836      _bfd_generic_mkarchive,
     837      _bfd_bool_bfd_false_error,
     838    },
     839    {				/* bfd_write_contents.  */
     840      _bfd_bool_bfd_false_error,
     841      _bfd_bool_bfd_false_error,
     842      _bfd_write_archive_contents,
     843      _bfd_bool_bfd_false_error,
     844    },
     845  
     846    BFD_JUMP_TABLE_GENERIC (bfd_plugin),
     847    BFD_JUMP_TABLE_COPY (bfd_plugin),
     848    BFD_JUMP_TABLE_CORE (bfd_plugin),
     849  #ifdef USE_64_BIT_ARCHIVE
     850    BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_64_bit),
     851  #else
     852    BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
     853  #endif
     854    BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
     855    BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
     856    BFD_JUMP_TABLE_WRITE (bfd_plugin),
     857    BFD_JUMP_TABLE_LINK (bfd_plugin),
     858    BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
     859  
     860    NULL,
     861  
     862    NULL				/* backend_data.  */
     863  };
     864  #endif /* BFD_SUPPORTS_PLUGINS */