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