Avoid testsuite errors when no cross compiler is available.
[deliverable/binutils-gdb.git] / ld / plugin.c
CommitLineData
5d3236ee
DK
1/* Plugin control for the GNU linker.
2 Copyright 2010 Free Software Foundation, Inc.
3
4 This file is part of the GNU Binutils.
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 "libiberty.h"
23#include "bfd.h"
24#include "bfdlink.h"
25#include "bfdver.h"
26#include "ld.h"
27#include "ldmain.h"
28#include "ldmisc.h"
29#include "ldexp.h"
30#include "ldlang.h"
31#include "ldfile.h"
32#include "plugin.h"
33#include "plugin-api.h"
34#include "elf-bfd.h"
35
36/* The suffix to append to the name of the real (claimed) object file
37 when generating a dummy BFD to hold the IR symbols sent from the
38 plugin. */
39#define IRONLY_SUFFIX ".ironly\004"
40
41/* This is sizeof an array of chars, not sizeof a const char *. We
42 also have to avoid inadvertently counting the trailing NUL. */
43#define IRONLY_SUFFIX_LEN (sizeof (IRONLY_SUFFIX) - 1)
44
45/* Stores a single argument passed to a plugin. */
46typedef struct plugin_arg
47{
48 struct plugin_arg *next;
49 const char *arg;
50} plugin_arg_t;
51
52/* Holds all details of a single plugin. */
53typedef struct plugin
54{
55 /* Next on the list of plugins, or NULL at end of chain. */
56 struct plugin *next;
57 /* The argument string given to --plugin. */
58 const char *name;
59 /* The shared library handle returned by dlopen. */
60 void *dlhandle;
61 /* The list of argument string given to --plugin-opt. */
62 plugin_arg_t *args;
63 /* Number of args in the list, for convenience. */
64 size_t n_args;
65 /* The plugin's event handlers. */
66 ld_plugin_claim_file_handler claim_file_handler;
67 ld_plugin_all_symbols_read_handler all_symbols_read_handler;
68 ld_plugin_cleanup_handler cleanup_handler;
69 /* TRUE if the cleanup handlers have been called. */
70 bfd_boolean cleanup_done;
71} plugin_t;
72
73/* The master list of all plugins. */
74static plugin_t *plugins_list = NULL;
75
76/* We keep a tail pointer for easy linking on the end. */
77static plugin_t **plugins_tail_chain_ptr = &plugins_list;
78
79/* The last plugin added to the list, for receiving args. */
80static plugin_t *last_plugin = NULL;
81
82/* The tail of the arg chain of the last plugin added to the list. */
83static plugin_arg_t **last_plugin_args_tail_chain_ptr = NULL;
84
85/* The plugin which is currently having a callback executed. */
86static plugin_t *called_plugin = NULL;
87
88/* Last plugin to cause an error, if any. */
89static const char *error_plugin = NULL;
90
91/* A hash table that records symbols referenced by non-IR files. Used
92 at get_symbols time to determine whether any prevailing defs from
93 IR files are referenced only from other IR files, so tthat we can
94 we can distinguish the LDPR_PREVAILING_DEF and LDPR_PREVAILING_DEF_IRONLY
95 cases when establishing symbol resolutions. */
96static struct bfd_hash_table *non_ironly_hash = NULL;
97
98/* Set at all symbols read time, to avoid recursively offering the plugin
99 its own newly-added input files and libs to claim. */
100static bfd_boolean no_more_claiming = FALSE;
101
102/* If the --allow-multiple-definition command-line option is active, we
103 have to disable it so that BFD always calls our hook, and simulate the
104 effect (when not resolving IR vs. real symbols) ourselves by ensuring
105 TRUE is returned from the hook. */
106static bfd_boolean plugin_cached_allow_multiple_defs = FALSE;
107
108/* List of tags to set in the constant leading part of the tv array. */
109static const enum ld_plugin_tag tv_header_tags[] =
110{
111 LDPT_MESSAGE,
112 LDPT_API_VERSION,
113 LDPT_GNU_LD_VERSION,
114 LDPT_LINKER_OUTPUT,
115 LDPT_OUTPUT_NAME,
116 LDPT_REGISTER_CLAIM_FILE_HOOK,
117 LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
118 LDPT_REGISTER_CLEANUP_HOOK,
119 LDPT_ADD_SYMBOLS,
120 LDPT_GET_INPUT_FILE,
121 LDPT_RELEASE_INPUT_FILE,
122 LDPT_GET_SYMBOLS,
123 LDPT_ADD_INPUT_FILE,
124 LDPT_ADD_INPUT_LIBRARY,
125 LDPT_SET_EXTRA_LIBRARY_PATH
126};
127
128/* How many entries in the constant leading part of the tv array. */
129static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
130
131/* Helper function for exiting with error status. */
132static int
133set_plugin_error (const char *plugin)
134{
135 error_plugin = plugin;
136 return -1;
137}
138
139/* Test if an error occurred. */
140static bfd_boolean
141plugin_error_p (void)
142{
143 return error_plugin != NULL;
144}
145
146/* Return name of plugin which caused an error if any. */
147const char *plugin_error_plugin (void)
148{
149 return error_plugin ? error_plugin : _("<no plugin>");
150}
151
152/* Handle -plugin arg: find and load plugin, or return error. */
153int plugin_opt_plugin (const char *plugin)
154{
155 plugin_t *newplug;
156
157 newplug = xmalloc (sizeof *newplug);
158 memset (newplug, 0, sizeof *newplug);
159 newplug->name = plugin;
160 newplug->dlhandle = dlopen (plugin, RTLD_NOW);
161 if (!newplug->dlhandle)
162 return set_plugin_error (plugin);
163
164 /* Chain on end, so when we run list it is in command-line order. */
165 *plugins_tail_chain_ptr = newplug;
166 plugins_tail_chain_ptr = &newplug->next;
167
168 /* Record it as current plugin for receiving args. */
169 last_plugin = newplug;
170 last_plugin_args_tail_chain_ptr = &newplug->args;
171 return 0;
172}
173
174/* Accumulate option arguments for last-loaded plugin, or return
175 error if none. */
176int plugin_opt_plugin_arg (const char *arg)
177{
178 plugin_arg_t *newarg;
179
180 if (!last_plugin)
181 return set_plugin_error (_("<no plugin>"));
182
183 newarg = xmalloc (sizeof *newarg);
184 newarg->arg = arg;
185 newarg->next = NULL;
186
187 /* Chain on end to preserve command-line order. */
188 *last_plugin_args_tail_chain_ptr = newarg;
189 last_plugin_args_tail_chain_ptr = &newarg->next;
190 last_plugin->n_args++;
191 return 0;
192}
193
194/* Create a dummy BFD. */
195bfd *
196plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
197{
198 asection *sec;
199 bfd *abfd = bfd_create (
200 concat (name, IRONLY_SUFFIX, (const char *)NULL),
201 srctemplate);
202 bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
203 bfd_make_writable (abfd);
204 /* Create a minimal set of sections to own the symbols. */
205 sec = bfd_make_section_old_way (abfd, ".text");
206 bfd_set_section_flags (abfd, sec,
207 SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
208 | SEC_ALLOC | SEC_LOAD | SEC_KEEP);
209 sec->output_section = sec;
210 sec->output_offset = 0;
211 return abfd;
212}
213
214/* Check if the BFD is an IR dummy. */
215bfd_boolean
216is_ir_dummy_bfd (const bfd *abfd)
217{
218 size_t namlen = strlen (abfd->filename);
219 if (namlen < IRONLY_SUFFIX_LEN)
220 return FALSE;
221 return !strcmp (abfd->filename + namlen - IRONLY_SUFFIX_LEN, IRONLY_SUFFIX);
222}
223
224/* Helpers to convert between BFD and GOLD symbol formats. */
225static enum ld_plugin_status
226asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
227 const struct ld_plugin_symbol *ldsym)
228{
229 flagword flags = BSF_NO_FLAGS;
230 struct bfd_section *section;
231
232 asym->the_bfd = abfd;
233 asym->name = ldsym->version
234 ? concat (ldsym->name, "@", ldsym->version, NULL)
235 : ldsym->name;
236 asym->value = 0;
237 switch (ldsym->def)
238 {
239 case LDPK_WEAKDEF:
240 flags = BSF_WEAK;
241 /* FALLTHRU */
242 case LDPK_DEF:
243 flags |= BSF_GLOBAL;
244 section = bfd_get_section_by_name (abfd, ".text");
245 break;
246
247 case LDPK_WEAKUNDEF:
248 flags = BSF_WEAK;
249 /* FALLTHRU */
250 case LDPK_UNDEF:
251 section = bfd_und_section_ptr;
252 break;
253
254 case LDPK_COMMON:
255 flags = BSF_GLOBAL;
256 section = bfd_com_section_ptr;
257 asym->value = ldsym->size;
258 break;
259
260 default:
261 return LDPS_ERR;
262 }
263 asym->flags = flags;
264 asym->section = section;
265
266 /* Visibility only applies on ELF targets. */
267 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
268 {
269 elf_symbol_type *elfsym = elf_symbol_from (abfd, asym);
270 if (!elfsym)
271 einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!"), asym->name);
272 elfsym->internal_elf_sym.st_other &= ~3;
273 elfsym->internal_elf_sym.st_other |= ldsym->visibility;
274 }
275
276 return LDPS_OK;
277}
278
279/* Register a claim-file handler. */
280static enum ld_plugin_status
281register_claim_file (ld_plugin_claim_file_handler handler)
282{
283 ASSERT (called_plugin);
284 called_plugin->claim_file_handler = handler;
285 return LDPS_OK;
286}
287
288/* Register an all-symbols-read handler. */
289static enum ld_plugin_status
290register_all_symbols_read (ld_plugin_all_symbols_read_handler handler)
291{
292 ASSERT (called_plugin);
293 called_plugin->all_symbols_read_handler = handler;
294 return LDPS_OK;
295}
296
297/* Register a cleanup handler. */
298static enum ld_plugin_status
299register_cleanup (ld_plugin_cleanup_handler handler)
300{
301 ASSERT (called_plugin);
302 called_plugin->cleanup_handler = handler;
303 return LDPS_OK;
304}
305
306/* Add symbols from a plugin-claimed input file. */
307static enum ld_plugin_status
308add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
309{
310 asymbol **symptrs;
311 bfd *abfd = handle;
312 int n;
313 ASSERT (called_plugin);
314 symptrs = xmalloc (nsyms * sizeof *symptrs);
315 for (n = 0; n < nsyms; n++)
316 {
317 enum ld_plugin_status rv;
318 asymbol *bfdsym = bfd_make_empty_symbol (abfd);
319 symptrs[n] = bfdsym;
320 rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);
321 if (rv != LDPS_OK)
322 return rv;
323 }
324 bfd_set_symtab (abfd, symptrs, nsyms);
325 return LDPS_OK;
326}
327
328/* Get the input file information with an open (possibly re-opened)
329 file descriptor. */
330static enum ld_plugin_status
331get_input_file (const void *handle, struct ld_plugin_input_file *file)
332{
333 ASSERT (called_plugin);
334 handle = handle;
335 file = file;
336 return LDPS_ERR;
337}
338
339/* Release the input file. */
340static enum ld_plugin_status
341release_input_file (const void *handle)
342{
343 ASSERT (called_plugin);
344 handle = handle;
345 return LDPS_ERR;
346}
347
348/* Get the symbol resolution info for a plugin-claimed input file. */
349static enum ld_plugin_status
350get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
351{
352 const bfd *abfd = handle;
353 int n;
354 ASSERT (called_plugin);
355 for (n = 0; n < nsyms; n++)
356 {
357 struct bfd_link_hash_entry *blhe;
358 bfd_boolean ironly;
359
360 blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
361 FALSE, FALSE, TRUE);
362 if (!blhe)
363 {
364 syms[n].resolution = LDPR_UNKNOWN;
365 continue;
366 }
367
368 /* Determine resolution from blhe type and symbol's original type. */
369 if (blhe->type == bfd_link_hash_undefined
370 || blhe->type == bfd_link_hash_undefweak)
371 {
372 syms[n].resolution = LDPR_UNDEF;
373 continue;
374 }
375 if (blhe->type != bfd_link_hash_defined
376 && blhe->type != bfd_link_hash_defweak
377 && blhe->type != bfd_link_hash_common)
378 {
379 /* We should not have a new, indirect or warning symbol here. */
380 einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)",
381 called_plugin->name, blhe->type);
382 }
383
384 /* We need to know if the sym is referenced from non-IR files. */
385 ironly = !bfd_hash_lookup (non_ironly_hash, syms[n].name, FALSE, FALSE);
386
387 /* If it was originally undefined or common, then it has been
388 resolved; determine how. */
389 if (syms[n].def == LDPK_UNDEF || syms[n].def == LDPK_WEAKUNDEF
390 || syms[n].def == LDPK_COMMON)
391 {
392 asection *owner_sec = (syms[n].def == LDPK_COMMON)
393 ? blhe->u.c.p->section
394 : blhe->u.def.section;
395 if (owner_sec->owner == link_info.output_bfd)
396 syms[n].resolution = LDPR_RESOLVED_EXEC;
397 else if (owner_sec->owner == abfd)
398 syms[n].resolution = (ironly)
399 ? LDPR_PREVAILING_DEF_IRONLY
400 : LDPR_PREVAILING_DEF;
401 else if (is_ir_dummy_bfd (owner_sec->owner))
402 syms[n].resolution = LDPR_RESOLVED_IR;
403 else if (owner_sec->owner->flags & DYNAMIC)
404 syms[n].resolution = LDPR_RESOLVED_DYN;
405 else
406 syms[n].resolution = LDPR_RESOLVED_EXEC;
407 continue;
408 }
409
410 /* Was originally def, or weakdef. Does it prevail? If the
411 owner is the original dummy bfd that supplied it, then this
412 is the definition that has prevailed. */
413 if (blhe->u.def.section->owner == link_info.output_bfd)
414 syms[n].resolution = LDPR_PREEMPTED_REG;
415 else if (blhe->u.def.section->owner == abfd)
416 {
417 syms[n].resolution = (ironly)
418 ? LDPR_PREVAILING_DEF_IRONLY
419 : LDPR_PREVAILING_DEF;
420 continue;
421 }
422
423 /* Was originally def, weakdef, or common, but has been pre-empted. */
424 syms[n].resolution = is_ir_dummy_bfd (blhe->u.def.section->owner)
425 ? LDPR_PREEMPTED_IR
426 : LDPR_PREEMPTED_REG;
427 }
428 return LDPS_OK;
429}
430
431/* Add a new (real) input file generated by a plugin. */
432static enum ld_plugin_status
433add_input_file (const char *pathname)
434{
435 ASSERT (called_plugin);
436 if (!lang_add_input_file (pathname, lang_input_file_is_file_enum, NULL))
437 return LDPS_ERR;
438 return LDPS_OK;
439}
440
441/* Add a new (real) library required by a plugin. */
442static enum ld_plugin_status
443add_input_library (const char *pathname)
444{
445 ASSERT (called_plugin);
446 if (!lang_add_input_file (pathname, lang_input_file_is_l_enum, NULL))
447 return LDPS_ERR;
448 return LDPS_OK;
449}
450
451/* Set the extra library path to be used by libraries added via
452 add_input_library. */
453static enum ld_plugin_status
454set_extra_library_path (const char *path)
455{
456 ASSERT (called_plugin);
457 ldfile_add_library_path (path, FALSE);
458 return LDPS_OK;
459}
460
461/* Issue a diagnostic message from a plugin. */
462static enum ld_plugin_status
463message (int level, const char *format, ...)
464{
465 va_list args;
466 va_start (args, format);
467
468 switch (level)
469 {
470 case LDPL_INFO:
471 vfinfo (stdout, format, args, FALSE);
472 break;
473 case LDPL_WARNING:
474 vfinfo (stdout, format, args, TRUE);
475 break;
476 case LDPL_FATAL:
477 case LDPL_ERROR:
478 default:
479 {
480 char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%F" : "%X",
481 format, NULL));
482 vfinfo (stderr, newfmt, args, TRUE);
483 }
484 break;
485 }
486
487 va_end (args);
488 return LDPS_OK;
489}
490
491/* Helper to size leading part of tv array and set it up. */
492static size_t
493set_tv_header (struct ld_plugin_tv *tv)
494{
495 size_t i;
496
497 /* Version info. */
498 static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL);
499 static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100;
500
501 if (!tv)
502 return tv_header_size;
503
504 for (i = 0; i < tv_header_size; i++)
505 {
506 tv[i].tv_tag = tv_header_tags[i];
507#define TVU(x) tv[i].tv_u.tv_ ## x
508 switch (tv[i].tv_tag)
509 {
510 case LDPT_MESSAGE:
511 TVU(message) = message;
512 break;
513 case LDPT_API_VERSION:
514 TVU(val) = LD_PLUGIN_API_VERSION;
515 break;
516 case LDPT_GNU_LD_VERSION:
517 TVU(val) = major * 100 + minor;
518 break;
519 case LDPT_LINKER_OUTPUT:
520 TVU(val) = link_info.relocatable ? LDPO_REL
521 : (link_info.shared ? LDPO_DYN : LDPO_EXEC);
522 break;
523 case LDPT_OUTPUT_NAME:
524 TVU(string) = output_filename;
525 break;
526 case LDPT_REGISTER_CLAIM_FILE_HOOK:
527 TVU(register_claim_file) = register_claim_file;
528 break;
529 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
530 TVU(register_all_symbols_read) = register_all_symbols_read;
531 break;
532 case LDPT_REGISTER_CLEANUP_HOOK:
533 TVU(register_cleanup) = register_cleanup;
534 break;
535 case LDPT_ADD_SYMBOLS:
536 TVU(add_symbols) = add_symbols;
537 break;
538 case LDPT_GET_INPUT_FILE:
539 TVU(get_input_file) = get_input_file;
540 break;
541 case LDPT_RELEASE_INPUT_FILE:
542 TVU(release_input_file) = release_input_file;
543 break;
544 case LDPT_GET_SYMBOLS:
545 TVU(get_symbols) = get_symbols;
546 break;
547 case LDPT_ADD_INPUT_FILE:
548 TVU(add_input_file) = add_input_file;
549 break;
550 case LDPT_ADD_INPUT_LIBRARY:
551 TVU(add_input_library) = add_input_library;
552 break;
553 case LDPT_SET_EXTRA_LIBRARY_PATH:
554 TVU(set_extra_library_path) = set_extra_library_path;
555 break;
556 default:
557 /* Added a new entry to the array without adding
558 a new case to set up its value is a bug. */
559 FAIL ();
560 }
561#undef TVU
562 }
563 return tv_header_size;
564}
565
566/* Append the per-plugin args list and trailing LDPT_NULL to tv. */
567static void
568set_tv_plugin_args (plugin_t *plugin, struct ld_plugin_tv *tv)
569{
570 plugin_arg_t *arg = plugin->args;
571 while (arg)
572 {
573 tv->tv_tag = LDPT_OPTION;
574 tv->tv_u.tv_string = arg->arg;
575 arg = arg->next;
576 tv++;
577 }
578 tv->tv_tag = LDPT_NULL;
579 tv->tv_u.tv_val = 0;
580}
581
582/* Load up and initialise all plugins after argument parsing. */
583int plugin_load_plugins (void)
584{
585 struct ld_plugin_tv *my_tv;
586 unsigned int max_args = 0;
587 plugin_t *curplug = plugins_list;
588
589 /* If there are no plugins, we need do nothing this run. */
590 if (!curplug)
591 return 0;
592
593 /* First pass over plugins to find max # args needed so that we
594 can size and allocate the tv array. */
595 while (curplug)
596 {
597 if (curplug->n_args > max_args)
598 max_args = curplug->n_args;
599 curplug = curplug->next;
600 }
601
602 /* Allocate tv array and initialise constant part. */
603 my_tv = xmalloc ((max_args + 1 + tv_header_size) * sizeof *my_tv);
604 set_tv_header (my_tv);
605
606 /* Pass over plugins again, activating them. */
607 curplug = plugins_list;
608 while (curplug)
609 {
610 enum ld_plugin_status rv;
611 ld_plugin_onload onloadfn = dlsym (curplug->dlhandle, "onload");
612 if (!onloadfn)
613 onloadfn = dlsym (curplug->dlhandle, "_onload");
614 if (!onloadfn)
615 return set_plugin_error (curplug->name);
616 set_tv_plugin_args (curplug, &my_tv[tv_header_size]);
617 called_plugin = curplug;
618 rv = (*onloadfn) (my_tv);
619 called_plugin = NULL;
620 if (rv != LDPS_OK)
621 return set_plugin_error (curplug->name);
622 curplug = curplug->next;
623 }
624
625 /* Since plugin(s) inited ok, assume they're going to want symbol
626 resolutions, which needs us to track which symbols are referenced
627 by non-IR files using the linker's notice callback. */
628 link_info.notice_all = TRUE;
629
630 return 0;
631}
632
633/* Call 'claim file' hook for all plugins. */
634int
635plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
636{
637 plugin_t *curplug = plugins_list;
638 *claimed = FALSE;
639 if (no_more_claiming)
640 return 0;
641 while (curplug && !*claimed)
642 {
643 if (curplug->claim_file_handler)
644 {
645 enum ld_plugin_status rv;
646 called_plugin = curplug;
647 rv = (*curplug->claim_file_handler) (file, claimed);
648 called_plugin = NULL;
649 if (rv != LDPS_OK)
650 set_plugin_error (curplug->name);
651 }
652 curplug = curplug->next;
653 }
654 return plugin_error_p () ? -1 : 0;
655}
656
657/* Call 'all symbols read' hook for all plugins. */
658int
659plugin_call_all_symbols_read (void)
660{
661 plugin_t *curplug = plugins_list;
662
663 /* Disable any further file-claiming. */
664 no_more_claiming = TRUE;
665
666 /* If --allow-multiple-definition is in effect, we need to disable it,
667 as the plugin infrastructure relies on the multiple_definition
668 callback to swap out the dummy IR-only BFDs for new real ones
669 when it starts opening the files added during this callback. */
670 plugin_cached_allow_multiple_defs = link_info.allow_multiple_definition;
671 link_info.allow_multiple_definition = FALSE;
672
673 while (curplug)
674 {
675 if (curplug->all_symbols_read_handler)
676 {
677 enum ld_plugin_status rv;
678 called_plugin = curplug;
679 rv = (*curplug->all_symbols_read_handler) ();
680 called_plugin = NULL;
681 if (rv != LDPS_OK)
682 set_plugin_error (curplug->name);
683 }
684 curplug = curplug->next;
685 }
686 return plugin_error_p () ? -1 : 0;
687}
688
689/* Call 'cleanup' hook for all plugins. */
690int
691plugin_call_cleanup (void)
692{
693 plugin_t *curplug = plugins_list;
694 while (curplug)
695 {
696 if (curplug->cleanup_handler && !curplug->cleanup_done)
697 {
698 enum ld_plugin_status rv;
699 curplug->cleanup_done = TRUE;
700 called_plugin = curplug;
701 rv = (*curplug->cleanup_handler) ();
702 called_plugin = NULL;
703 if (rv != LDPS_OK)
704 set_plugin_error (curplug->name);
705 dlclose (curplug->dlhandle);
706 }
707 curplug = curplug->next;
708 }
709 return plugin_error_p () ? -1 : 0;
710}
711
712/* Lazily init the non_ironly hash table. */
713static void
714init_non_ironly_hash (void)
715{
716 if (non_ironly_hash == NULL)
717 {
718 non_ironly_hash =
719 (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
720 if (!bfd_hash_table_init_n (non_ironly_hash,
721 bfd_hash_newfunc,
722 sizeof (struct bfd_hash_entry),
723 61))
724 einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
725 }
726}
727
728/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
729 and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
730 the linker adds them to the linker hash table. If we see a symbol
731 being referenced from a non-IR file, we add it to the non_ironly hash
732 table. If we can't find it there at get_symbols time, we know that
733 it was referenced only by IR files. We have to notice_all symbols,
734 because we won't necessarily know until later which ones will be
735 contributed by IR files. */
736bfd_boolean
737plugin_notice (struct bfd_link_info *info ATTRIBUTE_UNUSED,
738 const char *name, bfd *abfd,
739 asection *section, bfd_vma value ATTRIBUTE_UNUSED)
740{
741 bfd_boolean is_ref = bfd_is_und_section (section);
742 bfd_boolean is_dummy = is_ir_dummy_bfd (abfd);
743 init_non_ironly_hash ();
744 /* We only care about refs, not defs, indicated by section pointing
745 to the undefined section (according to the bfd linker notice callback
746 interface definition). */
747 if (is_ref && !is_dummy)
748 {
749 /* This is a ref from a non-IR file, so note the ref'd symbol
750 in the non-IR-only hash. */
751 if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
752 einfo (_("%P%X: %s: hash table failure adding symbol %s"),
753 abfd->filename, name);
754 }
755 else if (!is_ref && is_dummy)
756 {
757 /* No further processing since this is a def from an IR dummy BFD. */
758 return FALSE;
759 }
760
761 /* Continue with cref/nocrossref/trace-sym processing. */
762 return TRUE;
763}
764
765/* When we add new object files to the link at all symbols read time,
766 these contain the real code and symbols generated from the IR files,
767 and so duplicate all the definitions already supplied by the dummy
768 IR-only BFDs that we created at claim files time. We use the linker's
769 multiple-definitions callback hook to fix up the clash, discarding
770 the symbol from the IR-only BFD in favour of the symbol from the
771 real BFD. We return true if this was not-really-a-clash because
772 we've fixed it up, or anyway if --allow-multiple-definition was in
773 effect (before we disabled it to ensure we got called back). */
774bfd_boolean
775plugin_multiple_definition (struct bfd_link_info *info, const char *name,
776 bfd *obfd, asection *osec ATTRIBUTE_UNUSED,
777 bfd_vma oval ATTRIBUTE_UNUSED,
778 bfd *nbfd, asection *nsec, bfd_vma nval)
779{
780 if (is_ir_dummy_bfd (obfd))
781 {
782 struct bfd_link_hash_entry *blhe = bfd_link_hash_lookup (info->hash,
783 name, FALSE, FALSE, FALSE);
784 if (!blhe)
785 einfo (_("%P%X: %s: can't find IR symbol '%s'"), nbfd->filename,
786 name);
787 else if (blhe->type != bfd_link_hash_defined)
788 einfo (_("%P%x: %s: bad IR symbol type %d"), name, blhe->type);
789 /* Replace it with new details. */
790 blhe->u.def.section = nsec;
791 blhe->u.def.value = nval;
792 return TRUE;
793 }
794 return plugin_cached_allow_multiple_defs;
795}
This page took 0.049579 seconds and 4 git commands to generate.