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