xref: /netbsd-src/external/gpl3/gdb/dist/bfd/plugin.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /* Plugin support for BFD.
2    Copyright (C) 2009-2022 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_all_symbols_read_handler all_symbols_read;
133   ld_plugin_all_symbols_read_handler cleanup_handler;
134   bool has_symbol_type;
135 
136   struct plugin_list_entry *next;
137 
138   /* These can be reused for all IR objects.  */
139   const char *plugin_name;
140 };
141 
142 static const char *plugin_program_name;
143 
144 void
145 bfd_plugin_set_program_name (const char *program_name)
146 {
147   plugin_program_name = program_name;
148 }
149 
150 static struct plugin_list_entry *plugin_list = NULL;
151 static struct plugin_list_entry *current_plugin = NULL;
152 
153 /* Register a claim-file handler. */
154 
155 static enum ld_plugin_status
156 register_claim_file (ld_plugin_claim_file_handler handler)
157 {
158   current_plugin->claim_file = handler;
159   return LDPS_OK;
160 }
161 
162 static enum ld_plugin_status
163 add_symbols (void * handle,
164 	     int nsyms,
165 	     const struct ld_plugin_symbol * syms)
166 {
167   bfd *abfd = handle;
168   struct plugin_data_struct *plugin_data =
169     bfd_alloc (abfd, sizeof (plugin_data_struct));
170 
171   if (!plugin_data)
172     return LDPS_ERR;
173 
174   plugin_data->nsyms = nsyms;
175   plugin_data->syms = syms;
176 
177   if (nsyms != 0)
178     abfd->flags |= HAS_SYMS;
179 
180   abfd->tdata.plugin_data = plugin_data;
181   return LDPS_OK;
182 }
183 
184 static enum ld_plugin_status
185 add_symbols_v2 (void *handle, int nsyms,
186 		const struct ld_plugin_symbol *syms)
187 {
188   current_plugin->has_symbol_type = true;
189   return add_symbols (handle, nsyms, syms);
190 }
191 
192 int
193 bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
194 {
195   bfd *iobfd;
196   int fd;
197 
198   iobfd = ibfd;
199   while (iobfd->my_archive
200 	 && !bfd_is_thin_archive (iobfd->my_archive))
201     iobfd = iobfd->my_archive;
202   file->name = bfd_get_filename (iobfd);
203 
204   if (!iobfd->iostream && !bfd_open_file (iobfd))
205     return 0;
206 
207   /* Reuse the archive plugin file descriptor.  */
208   if (iobfd != ibfd)
209     fd = iobfd->archive_plugin_fd;
210   else
211     fd = -1;
212 
213   if (fd < 0)
214     {
215       /* The plugin API expects that the file descriptor won't be closed
216 	 and reused as done by the bfd file cache.  So open it again.
217 	 dup isn't good enough.  plugin IO uses lseek/read while BFD uses
218 	 fseek/fread.  It isn't wise to mix the unistd and stdio calls on
219 	 the same underlying file descriptor.  */
220       fd = open (file->name, O_RDONLY | O_BINARY);
221       if (fd < 0)
222 	{
223 #ifndef EMFILE
224 	  return 0;
225 #else
226 	  if (errno != EMFILE)
227 	    return 0;
228 
229 #ifdef HAVE_GETRLIMIT
230 	  struct rlimit lim;
231 
232 	  /* Complicated links involving lots of files and/or large
233 	     archives can exhaust the number of file descriptors
234 	     available to us.  If possible, try to allocate more
235 	     descriptors.  */
236 	  if (getrlimit (RLIMIT_NOFILE, & lim) == 0
237 	      && lim.rlim_cur < lim.rlim_max)
238 	    {
239 	      lim.rlim_cur = lim.rlim_max;
240 	      if (setrlimit (RLIMIT_NOFILE, &lim) == 0)
241 		fd = open (file->name, O_RDONLY | O_BINARY);
242 	    }
243 
244 	  if (fd < 0)
245 #endif
246 	    {
247 	      _bfd_error_handler (_("plugin framework: out of file descriptors. Try using fewer objects/archives\n"));
248 	      return 0;
249 	    }
250 #endif
251 	}
252     }
253 
254   if (iobfd == ibfd)
255     {
256       struct stat stat_buf;
257 
258       if (fstat (fd, &stat_buf))
259 	{
260 	  close (fd);
261 	  return 0;
262 	}
263 
264       file->offset = 0;
265       file->filesize = stat_buf.st_size;
266     }
267   else
268     {
269       /* Cache the archive plugin file descriptor.  */
270       iobfd->archive_plugin_fd = fd;
271       iobfd->archive_plugin_fd_open_count++;
272 
273       file->offset = ibfd->origin;
274       file->filesize = arelt_size (ibfd);
275     }
276 
277   file->fd = fd;
278   return 1;
279 }
280 
281 /* Close the plugin file descriptor FD.  If ABFD isn't NULL, it is an
282    archive member.   */
283 
284 void
285 bfd_plugin_close_file_descriptor (bfd *abfd, int fd)
286 {
287   if (abfd == NULL)
288     close (fd);
289   else
290     {
291       while (abfd->my_archive
292 	     && !bfd_is_thin_archive (abfd->my_archive))
293 	abfd = abfd->my_archive;
294 
295       /* Close the file descriptor if there is no archive plugin file
296 	 descriptor.  */
297       if (abfd->archive_plugin_fd == -1)
298 	{
299 	  close (fd);
300 	  return;
301 	}
302 
303       abfd->archive_plugin_fd_open_count--;
304       /* Dup the archive plugin file descriptor for later use, which
305 	 will be closed by _bfd_archive_close_and_cleanup.  */
306       if (abfd->archive_plugin_fd_open_count == 0)
307 	{
308 	  abfd->archive_plugin_fd = dup (fd);
309 	  close (fd);
310 	}
311     }
312 }
313 
314 static int
315 try_claim (bfd *abfd)
316 {
317   int claimed = 0;
318   struct ld_plugin_input_file file;
319 
320   file.handle = abfd;
321   if (bfd_plugin_open_input (abfd, &file)
322       && current_plugin->claim_file)
323     {
324       current_plugin->claim_file (&file, &claimed);
325       bfd_plugin_close_file_descriptor ((abfd->my_archive != NULL
326 					 ? abfd : NULL),
327 					file.fd);
328     }
329 
330   return claimed;
331 }
332 
333 static bool
334 try_load_plugin (const char *pname,
335 		 struct plugin_list_entry *plugin_list_iter,
336 		 bfd *abfd,
337 		 bool build_list_p)
338 {
339   void *plugin_handle;
340   struct ld_plugin_tv tv[5];
341   int i;
342   ld_plugin_onload onload;
343   enum ld_plugin_status status;
344   bool result = false;
345 
346   /* NB: Each object is independent.  Reuse the previous plugin from
347      the last run will lead to wrong result.  */
348   if (current_plugin)
349     memset (current_plugin, 0,
350 	    offsetof (struct plugin_list_entry, next));
351 
352   if (plugin_list_iter)
353     pname = plugin_list_iter->plugin_name;
354 
355   plugin_handle = dlopen (pname, RTLD_NOW);
356   if (!plugin_handle)
357     {
358       /* If we are building a list of viable plugins, then
359 	 we do not bother the user with the details of any
360 	 plugins that cannot be loaded.  */
361       if (! build_list_p)
362 	_bfd_error_handler ("Failed to load plugin '%s', reason: %s\n",
363 			    pname, dlerror ());
364       return false;
365     }
366 
367   if (plugin_list_iter == NULL)
368     {
369       size_t length_plugin_name = strlen (pname) + 1;
370       char *plugin_name = bfd_malloc (length_plugin_name);
371 
372       if (plugin_name == NULL)
373 	goto short_circuit;
374       plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
375       if (plugin_list_iter == NULL)
376 	{
377 	  free (plugin_name);
378 	  goto short_circuit;
379 	}
380       /* Make a copy of PNAME since PNAME from load_plugin () will be
381 	 freed.  */
382       memcpy (plugin_name, pname, length_plugin_name);
383       memset (plugin_list_iter, 0, sizeof (*plugin_list_iter));
384       plugin_list_iter->plugin_name = plugin_name;
385       plugin_list_iter->next = plugin_list;
386       plugin_list = plugin_list_iter;
387     }
388 
389   current_plugin = plugin_list_iter;
390   if (build_list_p)
391     goto short_circuit;
392 
393   onload = dlsym (plugin_handle, "onload");
394   if (!onload)
395     goto short_circuit;
396 
397   i = 0;
398   tv[i].tv_tag = LDPT_MESSAGE;
399   tv[i].tv_u.tv_message = message;
400 
401   ++i;
402   tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
403   tv[i].tv_u.tv_register_claim_file = register_claim_file;
404 
405   ++i;
406   tv[i].tv_tag = LDPT_ADD_SYMBOLS;
407   tv[i].tv_u.tv_add_symbols = add_symbols;
408 
409   ++i;
410   tv[i].tv_tag = LDPT_ADD_SYMBOLS_V2;
411   tv[i].tv_u.tv_add_symbols = add_symbols_v2;
412 
413   ++i;
414   tv[i].tv_tag = LDPT_NULL;
415   tv[i].tv_u.tv_val = 0;
416 
417   /* LTO plugin will call handler hooks to set up plugin handlers.  */
418   status = (*onload)(tv);
419 
420   if (status != LDPS_OK)
421     goto short_circuit;
422 
423   abfd->plugin_format = bfd_plugin_no;
424 
425   if (!current_plugin->claim_file)
426     goto short_circuit;
427 
428   if (!try_claim (abfd))
429     goto short_circuit;
430 
431   abfd->plugin_format = bfd_plugin_yes;
432   result = true;
433 
434  short_circuit:
435   dlclose (plugin_handle);
436   return result;
437 }
438 
439 /* There may be plugin libraries in lib/bfd-plugins.  */
440 static int has_plugin_list = -1;
441 
442 static bfd_cleanup (*ld_plugin_object_p) (bfd *);
443 
444 static const char *plugin_name;
445 
446 void
447 bfd_plugin_set_plugin (const char *p)
448 {
449   plugin_name = p;
450 }
451 
452 /* Return TRUE if a plugin library is used.  */
453 
454 bool
455 bfd_plugin_specified_p (void)
456 {
457   return plugin_list != NULL;
458 }
459 
460 /* Return TRUE if ABFD can be claimed by linker LTO plugin.  */
461 
462 bool
463 bfd_link_plugin_object_p (bfd *abfd)
464 {
465   if (ld_plugin_object_p)
466     return ld_plugin_object_p (abfd) != NULL;
467   return false;
468 }
469 
470 extern const bfd_target plugin_vec;
471 
472 /* Return TRUE if TARGET is a pointer to plugin_vec.  */
473 
474 bool
475 bfd_plugin_target_p (const bfd_target *target)
476 {
477   return target == &plugin_vec;
478 }
479 
480 /* Register OBJECT_P to be used by bfd_plugin_object_p.  */
481 
482 void
483 register_ld_plugin_object_p (bfd_cleanup (*object_p) (bfd *))
484 {
485   ld_plugin_object_p = object_p;
486 }
487 
488 static void
489 build_plugin_list (bfd *abfd)
490 {
491   /* The intent was to search ${libdir}/bfd-plugins for plugins, but
492      unfortunately the original implementation wasn't precisely that
493      when configuring binutils using --libdir.  Search in the proper
494      path first, then the old one for backwards compatibility.  */
495   static const char *path[]
496     = { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" };
497   struct stat last_st;
498   unsigned int i;
499 
500   if (has_plugin_list >= 0)
501     return;
502 
503   /* Try not to search the same dir twice, by looking at st_dev and
504      st_ino for the dir.  If we are on a file system that always sets
505      st_ino to zero or the actual st_ino is zero we might waste some
506      time, but that doesn't matter too much.  */
507   last_st.st_dev = 0;
508   last_st.st_ino = 0;
509   for (i = 0; i < sizeof (path) / sizeof (path[0]); i++)
510     {
511       char *plugin_dir = make_relative_prefix (plugin_program_name,
512 					       BINDIR,
513 					       path[i]);
514       if (plugin_dir)
515 	{
516 	  struct stat st;
517 	  DIR *d;
518 
519 	  if (stat (plugin_dir, &st) == 0
520 	      && S_ISDIR (st.st_mode)
521 	      && !(last_st.st_dev == st.st_dev
522 		   && last_st.st_ino == st.st_ino
523 		   && st.st_ino != 0)
524 	      && (d = opendir (plugin_dir)) != NULL)
525 	    {
526 	      struct dirent *ent;
527 
528 	      last_st.st_dev = st.st_dev;
529 	      last_st.st_ino = st.st_ino;
530 	      while ((ent = readdir (d)) != NULL)
531 		{
532 		  char *full_name;
533 
534 		  full_name = concat (plugin_dir, "/", ent->d_name, NULL);
535 		  if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
536 		    (void) try_load_plugin (full_name, NULL, abfd, true);
537 		  free (full_name);
538 		}
539 	      closedir (d);
540 	    }
541 	  free (plugin_dir);
542 	}
543     }
544 
545   has_plugin_list = plugin_list != NULL;
546 }
547 
548 static bool
549 load_plugin (bfd *abfd)
550 {
551   struct plugin_list_entry *plugin_list_iter;
552 
553   if (plugin_name)
554     return try_load_plugin (plugin_name, plugin_list, abfd, false);
555 
556   if (plugin_program_name == NULL)
557     return false;
558 
559   build_plugin_list (abfd);
560 
561   for (plugin_list_iter = plugin_list;
562        plugin_list_iter;
563        plugin_list_iter = plugin_list_iter->next)
564     if (try_load_plugin (NULL, plugin_list_iter, abfd, false))
565       return true;
566 
567   return false;
568 }
569 
570 
571 static bfd_cleanup
572 bfd_plugin_object_p (bfd *abfd)
573 {
574   if (ld_plugin_object_p)
575     return ld_plugin_object_p (abfd);
576 
577   if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd))
578     return NULL;
579 
580   return abfd->plugin_format == bfd_plugin_yes ? _bfd_no_cleanup : NULL;
581 }
582 
583 /* Copy any private info we understand from the input bfd
584    to the output bfd.  */
585 
586 static bool
587 bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
588 				      bfd *obfd ATTRIBUTE_UNUSED)
589 {
590   BFD_ASSERT (0);
591   return true;
592 }
593 
594 /* Copy any private info we understand from the input section
595    to the output section.  */
596 
597 static bool
598 bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
599 					  asection *isection ATTRIBUTE_UNUSED,
600 					  bfd *obfd ATTRIBUTE_UNUSED,
601 					  asection *osection ATTRIBUTE_UNUSED)
602 {
603   BFD_ASSERT (0);
604   return true;
605 }
606 
607 /* Copy any private info we understand from the input symbol
608    to the output symbol.  */
609 
610 static bool
611 bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
612 					 asymbol *isymbol ATTRIBUTE_UNUSED,
613 					 bfd *obfd ATTRIBUTE_UNUSED,
614 					 asymbol *osymbol ATTRIBUTE_UNUSED)
615 {
616   BFD_ASSERT (0);
617   return true;
618 }
619 
620 static bool
621 bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, void *ptr ATTRIBUTE_UNUSED)
622 {
623   BFD_ASSERT (0);
624   return true;
625 }
626 
627 static char *
628 bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
629 {
630   BFD_ASSERT (0);
631   return NULL;
632 }
633 
634 static int
635 bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
636 {
637   BFD_ASSERT (0);
638   return 0;
639 }
640 
641 static int
642 bfd_plugin_core_file_pid (bfd *abfd ATTRIBUTE_UNUSED)
643 {
644   BFD_ASSERT (0);
645   return 0;
646 }
647 
648 static long
649 bfd_plugin_get_symtab_upper_bound (bfd *abfd)
650 {
651   struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
652   long nsyms = plugin_data->nsyms;
653 
654   BFD_ASSERT (nsyms >= 0);
655 
656   return ((nsyms + 1) * sizeof (asymbol *));
657 }
658 
659 static flagword
660 convert_flags (const struct ld_plugin_symbol *sym)
661 {
662  switch (sym->def)
663    {
664    case LDPK_DEF:
665    case LDPK_COMMON:
666    case LDPK_UNDEF:
667      return BSF_GLOBAL;
668 
669    case LDPK_WEAKUNDEF:
670    case LDPK_WEAKDEF:
671      return BSF_GLOBAL | BSF_WEAK;
672 
673    default:
674      BFD_ASSERT (0);
675      return 0;
676    }
677 }
678 
679 static long
680 bfd_plugin_canonicalize_symtab (bfd *abfd,
681 				asymbol **alocation)
682 {
683   struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
684   long nsyms = plugin_data->nsyms;
685   const struct ld_plugin_symbol *syms = plugin_data->syms;
686   static asection fake_text_section
687     = BFD_FAKE_SECTION (fake_text_section, NULL, "plug", 0,
688 			SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
689   static asection fake_data_section
690     = BFD_FAKE_SECTION (fake_data_section, NULL, "plug", 0,
691 			SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS);
692   static asection fake_bss_section
693     = BFD_FAKE_SECTION (fake_bss_section, NULL, "plug", 0,
694 			SEC_ALLOC);
695   static asection fake_common_section
696     = BFD_FAKE_SECTION (fake_common_section, NULL, "plug", 0, SEC_IS_COMMON);
697   int i;
698 
699   for (i = 0; i < nsyms; i++)
700     {
701       asymbol *s = bfd_alloc (abfd, sizeof (asymbol));
702 
703       BFD_ASSERT (s);
704       alocation[i] = s;
705 
706       s->the_bfd = abfd;
707       s->name = syms[i].name;
708       s->value = 0;
709       s->flags = convert_flags (&syms[i]);
710       switch (syms[i].def)
711 	{
712 	case LDPK_COMMON:
713 	  s->section = &fake_common_section;
714 	  break;
715 	case LDPK_UNDEF:
716 	case LDPK_WEAKUNDEF:
717 	  s->section = bfd_und_section_ptr;
718 	  break;
719 	case LDPK_DEF:
720 	case LDPK_WEAKDEF:
721 	  if (current_plugin->has_symbol_type)
722 	    switch (syms[i].symbol_type)
723 	      {
724 	      default:
725 		/* FIXME: Should we issue an error here ?  */
726 	      case LDST_UNKNOWN:
727 		/* What is the best fake section for LDST_UNKNOWN?  */
728 	      case LDST_FUNCTION:
729 		s->section = &fake_text_section;
730 		break;
731 	      case LDST_VARIABLE:
732 		if (syms[i].section_kind == LDSSK_BSS)
733 		  s->section = &fake_bss_section;
734 		else
735 		  s->section = &fake_data_section;
736 		break;
737 	      }
738 	  else
739 	    s->section = &fake_text_section;
740 	  break;
741 	default:
742 	  BFD_ASSERT (0);
743 	}
744 
745       s->udata.p = (void *) &syms[i];
746     }
747 
748   return nsyms;
749 }
750 
751 static void
752 bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
753 			 void *afile ATTRIBUTE_UNUSED,
754 			 asymbol *symbol ATTRIBUTE_UNUSED,
755 			 bfd_print_symbol_type how ATTRIBUTE_UNUSED)
756 {
757   BFD_ASSERT (0);
758 }
759 
760 static void
761 bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
762 			    asymbol *symbol,
763 			    symbol_info *ret)
764 {
765   bfd_symbol_info (symbol, ret);
766 }
767 
768 /* Make an empty symbol. */
769 
770 static asymbol *
771 bfd_plugin_make_empty_symbol (bfd *abfd)
772 {
773   asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
774   if (new_symbol == NULL)
775     return new_symbol;
776   new_symbol->the_bfd = abfd;
777   return new_symbol;
778 }
779 
780 static int
781 bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
782 			   struct bfd_link_info *info ATTRIBUTE_UNUSED)
783 {
784   BFD_ASSERT (0);
785   return 0;
786 }
787 
788 const bfd_target plugin_vec =
789 {
790   "plugin",			/* Name.  */
791   bfd_target_unknown_flavour,
792   BFD_ENDIAN_LITTLE,		/* Target byte order.  */
793   BFD_ENDIAN_LITTLE,		/* Target headers byte order.  */
794   (HAS_RELOC | EXEC_P |		/* Object flags.  */
795    HAS_LINENO | HAS_DEBUG |
796    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
797   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
798    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
799   0,				/* symbol_leading_char.  */
800   '/',				/* ar_pad_char.  */
801   15,				/* ar_max_namelen.  */
802   255,				/* match priority.  */
803   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
804 
805   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
806   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
807   bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* data */
808   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
809   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
810   bfd_getl16, bfd_getl_signed_16, bfd_putl16,	/* hdrs */
811 
812   {				/* bfd_check_format.  */
813     _bfd_dummy_target,
814     bfd_plugin_object_p,
815     bfd_generic_archive_p,
816     _bfd_dummy_target
817   },
818   {				/* bfd_set_format.  */
819     _bfd_bool_bfd_false_error,
820     _bfd_bool_bfd_false_error,
821     _bfd_generic_mkarchive,
822     _bfd_bool_bfd_false_error,
823   },
824   {				/* bfd_write_contents.  */
825     _bfd_bool_bfd_false_error,
826     _bfd_bool_bfd_false_error,
827     _bfd_write_archive_contents,
828     _bfd_bool_bfd_false_error,
829   },
830 
831   BFD_JUMP_TABLE_GENERIC (bfd_plugin),
832   BFD_JUMP_TABLE_COPY (bfd_plugin),
833   BFD_JUMP_TABLE_CORE (bfd_plugin),
834 #ifdef USE_64_BIT_ARCHIVE
835   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_64_bit),
836 #else
837   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
838 #endif
839   BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
840   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
841   BFD_JUMP_TABLE_WRITE (bfd_plugin),
842   BFD_JUMP_TABLE_LINK (bfd_plugin),
843   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
844 
845   NULL,
846 
847   NULL				/* backend_data.  */
848 };
849 #endif /* BFD_SUPPORTS_PLUGINS */
850