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