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