OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [ld/] [plugin.c] - Blame information for rev 162

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 khays
/* Plugin control for the GNU linker.
2
   Copyright 2010, 2011 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
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
36
#include <windows.h>
37
#endif
38
 
39
/* Report plugin symbols.  */
40
bfd_boolean report_plugin_symbols;
41
 
42
/* The suffix to append to the name of the real (claimed) object file
43
   when generating a dummy BFD to hold the IR symbols sent from the
44
   plugin.  For cosmetic use only; appears in maps, crefs etc.  */
45
#define IRONLY_SUFFIX " (symbol from plugin)"
46
 
47
/* Stores a single argument passed to a plugin.  */
48
typedef struct plugin_arg
49
{
50
  struct plugin_arg *next;
51
  const char *arg;
52
} plugin_arg_t;
53
 
54
/* Holds all details of a single plugin.  */
55
typedef struct plugin
56
{
57
  /* Next on the list of plugins, or NULL at end of chain.  */
58
  struct plugin *next;
59
  /* The argument string given to --plugin.  */
60
  const char *name;
61
  /* The shared library handle returned by dlopen.  */
62
  void *dlhandle;
63
  /* The list of argument string given to --plugin-opt.  */
64
  plugin_arg_t *args;
65
  /* Number of args in the list, for convenience.  */
66
  size_t n_args;
67
  /* The plugin's event handlers.  */
68
  ld_plugin_claim_file_handler claim_file_handler;
69
  ld_plugin_all_symbols_read_handler all_symbols_read_handler;
70
  ld_plugin_cleanup_handler cleanup_handler;
71
  /* TRUE if the cleanup handlers have been called.  */
72
  bfd_boolean cleanup_done;
73
} plugin_t;
74
 
75
/* The master list of all plugins.  */
76
static plugin_t *plugins_list = NULL;
77
 
78
/* We keep a tail pointer for easy linking on the end.  */
79
static plugin_t **plugins_tail_chain_ptr = &plugins_list;
80
 
81
/* The last plugin added to the list, for receiving args.  */
82
static plugin_t *last_plugin = NULL;
83
 
84
/* The tail of the arg chain of the last plugin added to the list.  */
85
static plugin_arg_t **last_plugin_args_tail_chain_ptr = NULL;
86
 
87
/* The plugin which is currently having a callback executed.  */
88
static plugin_t *called_plugin = NULL;
89
 
90
/* Last plugin to cause an error, if any.  */
91
static const char *error_plugin = NULL;
92
 
93
/* State of linker "notice" interface before we poked at it.  */
94
static bfd_boolean orig_notice_all;
95
 
96
/* Original linker callbacks, and the plugin version.  */
97
static const struct bfd_link_callbacks *orig_callbacks;
98
static struct bfd_link_callbacks plugin_callbacks;
99
 
100
/* Set at all symbols read time, to avoid recursively offering the plugin
101
   its own newly-added input files and libs to claim.  */
102
bfd_boolean no_more_claiming = FALSE;
103
 
104
/* List of tags to set in the constant leading part of the tv array. */
105
static const enum ld_plugin_tag tv_header_tags[] =
106
{
107
  LDPT_MESSAGE,
108
  LDPT_API_VERSION,
109
  LDPT_GNU_LD_VERSION,
110
  LDPT_LINKER_OUTPUT,
111
  LDPT_OUTPUT_NAME,
112
  LDPT_REGISTER_CLAIM_FILE_HOOK,
113
  LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
114
  LDPT_REGISTER_CLEANUP_HOOK,
115
  LDPT_ADD_SYMBOLS,
116
  LDPT_GET_INPUT_FILE,
117
  LDPT_RELEASE_INPUT_FILE,
118
  LDPT_GET_SYMBOLS,
119
  LDPT_ADD_INPUT_FILE,
120
  LDPT_ADD_INPUT_LIBRARY,
121
  LDPT_SET_EXTRA_LIBRARY_PATH
122
};
123
 
124
/* How many entries in the constant leading part of the tv array.  */
125
static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
126
 
127
/* Forward references.  */
128
static bfd_boolean plugin_notice (struct bfd_link_info *,
129
                                  struct bfd_link_hash_entry *, bfd *,
130
                                  asection *, bfd_vma, flagword, const char *);
131
 
132
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
133
 
134
#define RTLD_NOW 0      /* Dummy value.  */
135
 
136
static void *
137
dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
138
{
139
  return LoadLibrary (file);
140
}
141
 
142
static void *
143
dlsym (void *handle, const char *name)
144
{
145
  return GetProcAddress (handle, name);
146
}
147
 
148
static int
149
dlclose (void *handle)
150
{
151
  FreeLibrary (handle);
152
  return 0;
153
}
154
 
155
#endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)  */
156
 
157
/* Helper function for exiting with error status.  */
158
static int
159
set_plugin_error (const char *plugin)
160
{
161
  error_plugin = plugin;
162
  return -1;
163
}
164
 
165
/* Test if an error occurred.  */
166
static bfd_boolean
167
plugin_error_p (void)
168
{
169
  return error_plugin != NULL;
170
}
171
 
172
/* Return name of plugin which caused an error if any.  */
173
const char *
174
plugin_error_plugin (void)
175
{
176
  return error_plugin ? error_plugin : _("<no plugin>");
177
}
178
 
179
/* Handle -plugin arg: find and load plugin, or return error.  */
180
int
181
plugin_opt_plugin (const char *plugin)
182
{
183
  plugin_t *newplug;
184
 
185
  newplug = xmalloc (sizeof *newplug);
186
  memset (newplug, 0, sizeof *newplug);
187
  newplug->name = plugin;
188
  newplug->dlhandle = dlopen (plugin, RTLD_NOW);
189
  if (!newplug->dlhandle)
190
    return set_plugin_error (plugin);
191
 
192
  /* Chain on end, so when we run list it is in command-line order.  */
193
  *plugins_tail_chain_ptr = newplug;
194
  plugins_tail_chain_ptr = &newplug->next;
195
 
196
  /* Record it as current plugin for receiving args.  */
197
  last_plugin = newplug;
198
  last_plugin_args_tail_chain_ptr = &newplug->args;
199
  return 0;
200
}
201
 
202
/* Accumulate option arguments for last-loaded plugin, or return
203
   error if none.  */
204
int
205
plugin_opt_plugin_arg (const char *arg)
206
{
207
  plugin_arg_t *newarg;
208
 
209
  if (!last_plugin)
210
    return set_plugin_error (_("<no plugin>"));
211
 
212
  newarg = xmalloc (sizeof *newarg);
213
  newarg->arg = arg;
214
  newarg->next = NULL;
215
 
216
  /* Chain on end to preserve command-line order.  */
217
  *last_plugin_args_tail_chain_ptr = newarg;
218
  last_plugin_args_tail_chain_ptr = &newarg->next;
219
  last_plugin->n_args++;
220
  return 0;
221
}
222
 
223
/* Create a dummy BFD.  */
224
bfd *
225
plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
226
{
227
  bfd *abfd;
228
 
229
  bfd_use_reserved_id = 1;
230
  abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL),
231
                     srctemplate);
232
  if (abfd != NULL)
233
    {
234
      abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
235
      bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
236
      bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
237
      if (bfd_make_writable (abfd)
238
          && bfd_copy_private_bfd_data (srctemplate, abfd))
239
        {
240
          flagword flags;
241
 
242 157 khays
          /* Create section to own the symbols.  */
243 145 khays
          flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
244
                   | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
245
          if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
246
            return abfd;
247
        }
248
    }
249
  einfo (_("could not create dummy IR bfd: %F%E\n"));
250
  return NULL;
251
}
252
 
253
/* Check if the BFD passed in is an IR dummy object file.  */
254
static bfd_boolean
255
is_ir_dummy_bfd (const bfd *abfd)
256
{
257
  /* ABFD can sometimes legitimately be NULL, e.g. when called from one
258
     of the linker callbacks for a symbol in the *ABS* or *UND* sections.
259
     Likewise, the usrdata field may be NULL if ABFD was added by the
260
     backend without a corresponding input statement, as happens e.g.
261
     when processing DT_NEEDED dependencies.  */
262
  return (abfd
263
          && abfd->usrdata
264
          && ((lang_input_statement_type *)(abfd->usrdata))->claimed);
265
}
266
 
267
/* Helpers to convert between BFD and GOLD symbol formats.  */
268
static enum ld_plugin_status
269
asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
270
                            const struct ld_plugin_symbol *ldsym)
271
{
272
  flagword flags = BSF_NO_FLAGS;
273
  struct bfd_section *section;
274
 
275
  asym->the_bfd = abfd;
276
  asym->name = (ldsym->version
277
                ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL)
278
                : ldsym->name);
279
  asym->value = 0;
280
  switch (ldsym->def)
281
    {
282
    case LDPK_WEAKDEF:
283
      flags = BSF_WEAK;
284
      /* FALLTHRU */
285
    case LDPK_DEF:
286
      flags |= BSF_GLOBAL;
287 157 khays
      if (ldsym->comdat_key)
288
        {
289
          char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key,
290
                               (const char *) NULL);
291
          section = bfd_get_section_by_name (abfd, name);
292
          if (section != NULL)
293
            free (name);
294
          else
295
            {
296
              flagword sflags;
297
 
298
              sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
299
                        | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE
300
                        | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD);
301
              section = bfd_make_section_anyway_with_flags (abfd, name, sflags);
302
              if (section == NULL)
303
                return LDPS_ERR;
304
            }
305
        }
306
      else
307
        section = bfd_get_section_by_name (abfd, ".text");
308 145 khays
      break;
309
 
310
    case LDPK_WEAKUNDEF:
311
      flags = BSF_WEAK;
312
      /* FALLTHRU */
313
    case LDPK_UNDEF:
314
      section = bfd_und_section_ptr;
315
      break;
316
 
317
    case LDPK_COMMON:
318
      flags = BSF_GLOBAL;
319
      section = bfd_com_section_ptr;
320
      asym->value = ldsym->size;
321
      /* For ELF targets, set alignment of common symbol to 1.  */
322
      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
323
        {
324
          ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
325
          ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
326
        }
327
      break;
328
 
329
    default:
330
      return LDPS_ERR;
331
    }
332
  asym->flags = flags;
333
  asym->section = section;
334
 
335
  /* Visibility only applies on ELF targets.  */
336
  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
337
    {
338
      elf_symbol_type *elfsym = elf_symbol_from (abfd, asym);
339
      unsigned char visibility;
340
 
341
      if (!elfsym)
342
        einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name);
343
      switch (ldsym->visibility)
344
        {
345
        default:
346
          einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"),
347
                 ldsym->visibility);
348
        case LDPV_DEFAULT:
349
          visibility = STV_DEFAULT;
350
          break;
351
        case LDPV_PROTECTED:
352
          visibility = STV_PROTECTED;
353
          break;
354
        case LDPV_INTERNAL:
355
          visibility = STV_INTERNAL;
356
          break;
357
        case LDPV_HIDDEN:
358
          visibility = STV_HIDDEN;
359
          break;
360
        }
361
      elfsym->internal_elf_sym.st_other
362
        = (visibility | (elfsym->internal_elf_sym.st_other
363
                         & ~ELF_ST_VISIBILITY (-1)));
364
    }
365
 
366
  return LDPS_OK;
367
}
368
 
369
/* Register a claim-file handler.  */
370
static enum ld_plugin_status
371
register_claim_file (ld_plugin_claim_file_handler handler)
372
{
373
  ASSERT (called_plugin);
374
  called_plugin->claim_file_handler = handler;
375
  return LDPS_OK;
376
}
377
 
378
/* Register an all-symbols-read handler.  */
379
static enum ld_plugin_status
380
register_all_symbols_read (ld_plugin_all_symbols_read_handler handler)
381
{
382
  ASSERT (called_plugin);
383
  called_plugin->all_symbols_read_handler = handler;
384
  return LDPS_OK;
385
}
386
 
387
/* Register a cleanup handler.  */
388
static enum ld_plugin_status
389
register_cleanup (ld_plugin_cleanup_handler handler)
390
{
391
  ASSERT (called_plugin);
392
  called_plugin->cleanup_handler = handler;
393
  return LDPS_OK;
394
}
395
 
396
/* Add symbols from a plugin-claimed input file.  */
397
static enum ld_plugin_status
398
add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
399
{
400
  asymbol **symptrs;
401
  bfd *abfd = handle;
402
  int n;
403 157 khays
 
404 145 khays
  ASSERT (called_plugin);
405
  symptrs = xmalloc (nsyms * sizeof *symptrs);
406
  for (n = 0; n < nsyms; n++)
407
    {
408
      enum ld_plugin_status rv;
409 157 khays
      asymbol *bfdsym;
410
 
411
      bfdsym = bfd_make_empty_symbol (abfd);
412 145 khays
      symptrs[n] = bfdsym;
413
      rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);
414
      if (rv != LDPS_OK)
415
        return rv;
416
    }
417
  bfd_set_symtab (abfd, symptrs, nsyms);
418
  return LDPS_OK;
419
}
420
 
421
/* Get the input file information with an open (possibly re-opened)
422
   file descriptor.  */
423
static enum ld_plugin_status
424
get_input_file (const void *handle, struct ld_plugin_input_file *file)
425
{
426
  ASSERT (called_plugin);
427
  handle = handle;
428
  file = file;
429
  return LDPS_ERR;
430
}
431
 
432
/* Release the input file.  */
433
static enum ld_plugin_status
434
release_input_file (const void *handle)
435
{
436
  ASSERT (called_plugin);
437
  handle = handle;
438
  return LDPS_ERR;
439
}
440
 
441
/* Return TRUE if a defined symbol might be reachable from outside the
442
   universe of claimed objects.  */
443
static inline bfd_boolean
444
is_visible_from_outside (struct ld_plugin_symbol *lsym, asection *section,
445
                         struct bfd_link_hash_entry *blhe)
446
{
447
  struct bfd_sym_chain *sym;
448
 
449
  /* Section's owner may be NULL if it is the absolute
450
     section, fortunately is_ir_dummy_bfd handles that.  */
451
  if (!is_ir_dummy_bfd (section->owner))
452
    return TRUE;
453
  if (link_info.relocatable)
454
    return TRUE;
455
  if (link_info.export_dynamic || link_info.shared)
456
    {
457
      /* Only ELF symbols really have visibility.  */
458
      if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
459
        {
460
          struct elf_link_hash_entry *el = (struct elf_link_hash_entry *)blhe;
461
          int vis = ELF_ST_VISIBILITY (el->other);
462
          return vis == STV_DEFAULT || vis == STV_PROTECTED;
463
        }
464
      /* On non-ELF targets, we can safely make inferences by considering
465
         what visibility the plugin would have liked to apply when it first
466
         sent us the symbol.  During ELF symbol processing, visibility only
467
         ever becomes more restrictive, not less, when symbols are merged,
468
         so this is a conservative estimate; it may give false positives,
469
         declaring something visible from outside when it in fact would
470
         not have been, but this will only lead to missed optimisation
471
         opportunities during LTRANS at worst; it will not give false
472
         negatives, which can lead to the disastrous conclusion that the
473
         related symbol is IRONLY.  (See GCC PR46319 for an example.)  */
474
      return (lsym->visibility == LDPV_DEFAULT
475
              || lsym->visibility == LDPV_PROTECTED);
476
    }
477
 
478
  for (sym = &entry_symbol; sym != NULL; sym = sym->next)
479
    if (sym->name
480
        && strcmp (sym->name, blhe->root.string) == 0)
481
      return TRUE;
482
 
483
  return FALSE;
484
}
485
 
486
/* Get the symbol resolution info for a plugin-claimed input file.  */
487
static enum ld_plugin_status
488
get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
489
{
490
  const bfd *abfd = handle;
491
  int n;
492
  ASSERT (called_plugin);
493
  for (n = 0; n < nsyms; n++)
494
    {
495
      struct bfd_link_hash_entry *blhe;
496
      bfd_boolean ironly;
497
      asection *owner_sec;
498
      if (syms[n].def != LDPK_UNDEF)
499
        blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
500
                                     FALSE, FALSE, TRUE);
501
      else
502
        blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info,
503
                                             syms[n].name, FALSE, FALSE, TRUE);
504
      if (!blhe)
505
        {
506
          syms[n].resolution = LDPR_UNKNOWN;
507
          goto report_symbol;
508
        }
509
 
510
      /* Determine resolution from blhe type and symbol's original type.  */
511
      if (blhe->type == bfd_link_hash_undefined
512
          || blhe->type == bfd_link_hash_undefweak)
513
        {
514
          syms[n].resolution = LDPR_UNDEF;
515
          goto report_symbol;
516
        }
517
      if (blhe->type != bfd_link_hash_defined
518
          && blhe->type != bfd_link_hash_defweak
519
          && blhe->type != bfd_link_hash_common)
520
        {
521
          /* We should not have a new, indirect or warning symbol here.  */
522
          einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)\n",
523
                 called_plugin->name, blhe->type);
524
        }
525
 
526
      /* Find out which section owns the symbol.  Since it's not undef,
527
         it must have an owner; if it's not a common symbol, both defs
528
         and weakdefs keep it in the same place. */
529
      owner_sec = (blhe->type == bfd_link_hash_common
530
                   ? blhe->u.c.p->section
531
                   : blhe->u.def.section);
532
 
533
      /* We need to know if the sym is referenced from non-IR files.  Or
534
         even potentially-referenced, perhaps in a future final link if
535
         this is a partial one, perhaps dynamically at load-time if the
536
         symbol is externally visible.  */
537
      ironly = !(blhe->non_ir_ref
538
                 || is_visible_from_outside (&syms[n], owner_sec, blhe));
539
 
540
      /* If it was originally undefined or common, then it has been
541
         resolved; determine how.  */
542
      if (syms[n].def == LDPK_UNDEF
543
          || syms[n].def == LDPK_WEAKUNDEF
544
          || syms[n].def == LDPK_COMMON)
545
        {
546
          if (owner_sec->owner == link_info.output_bfd)
547
            syms[n].resolution = LDPR_RESOLVED_EXEC;
548
          else if (owner_sec->owner == abfd)
549
            syms[n].resolution = (ironly
550
                                  ? LDPR_PREVAILING_DEF_IRONLY
551
                                  : LDPR_PREVAILING_DEF);
552
          else if (is_ir_dummy_bfd (owner_sec->owner))
553
            syms[n].resolution = LDPR_RESOLVED_IR;
554
          else if (owner_sec->owner != NULL
555
                   && (owner_sec->owner->flags & DYNAMIC) != 0)
556
            syms[n].resolution =  LDPR_RESOLVED_DYN;
557
          else
558
            syms[n].resolution = LDPR_RESOLVED_EXEC;
559
          goto report_symbol;
560
        }
561
 
562
      /* Was originally def, or weakdef.  Does it prevail?  If the
563
         owner is the original dummy bfd that supplied it, then this
564
         is the definition that has prevailed.  */
565
      if (owner_sec->owner == link_info.output_bfd)
566
        syms[n].resolution = LDPR_PREEMPTED_REG;
567
      else if (owner_sec->owner == abfd)
568
        {
569
          syms[n].resolution = (ironly
570
                                ? LDPR_PREVAILING_DEF_IRONLY
571
                                : LDPR_PREVAILING_DEF);
572
          goto report_symbol;
573
        }
574
 
575
      /* Was originally def, weakdef, or common, but has been pre-empted.  */
576
      syms[n].resolution = (is_ir_dummy_bfd (owner_sec->owner)
577
                            ? LDPR_PREEMPTED_IR
578
                            : LDPR_PREEMPTED_REG);
579
 
580
    report_symbol:
581
      if (report_plugin_symbols)
582
        einfo (_("%P: %B: symbol `%s' "
583
                 "definition: %d, visibility: %d, resolution: %d\n"),
584
               abfd, syms[n].name,
585
               syms[n].def, syms[n].visibility, syms[n].resolution);
586
    }
587
  return LDPS_OK;
588
}
589
 
590
/* Add a new (real) input file generated by a plugin.  */
591
static enum ld_plugin_status
592
add_input_file (const char *pathname)
593
{
594
  ASSERT (called_plugin);
595
  if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
596
                            NULL))
597
    return LDPS_ERR;
598
  return LDPS_OK;
599
}
600
 
601
/* Add a new (real) library required by a plugin.  */
602
static enum ld_plugin_status
603
add_input_library (const char *pathname)
604
{
605
  ASSERT (called_plugin);
606
  if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
607
                            NULL))
608
    return LDPS_ERR;
609
  return LDPS_OK;
610
}
611
 
612
/* Set the extra library path to be used by libraries added via
613
   add_input_library.  */
614
static enum ld_plugin_status
615
set_extra_library_path (const char *path)
616
{
617
  ASSERT (called_plugin);
618
  ldfile_add_library_path (xstrdup (path), FALSE);
619
  return LDPS_OK;
620
}
621
 
622
/* Issue a diagnostic message from a plugin.  */
623
static enum ld_plugin_status
624
message (int level, const char *format, ...)
625
{
626
  va_list args;
627
  va_start (args, format);
628
 
629
  switch (level)
630
    {
631
    case LDPL_INFO:
632
      vfinfo (stdout, format, args, FALSE);
633
      putchar ('\n');
634
      break;
635
    case LDPL_WARNING:
636
      vfinfo (stdout, format, args, TRUE);
637
      putchar ('\n');
638
      break;
639
    case LDPL_FATAL:
640
    case LDPL_ERROR:
641
    default:
642
      {
643
        char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ",
644
                                 format, "\n", (const char *) NULL));
645
        fflush (stdout);
646
        vfinfo (stderr, newfmt, args, TRUE);
647
        fflush (stderr);
648
      }
649
      break;
650
    }
651
 
652
  va_end (args);
653
  return LDPS_OK;
654
}
655
 
656
/* Helper to size leading part of tv array and set it up. */
657
static size_t
658
set_tv_header (struct ld_plugin_tv *tv)
659
{
660
  size_t i;
661
 
662
  /* Version info.  */
663
  static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL);
664
  static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100;
665
 
666
  if (!tv)
667
    return tv_header_size;
668
 
669
  for (i = 0; i < tv_header_size; i++)
670
    {
671
      tv[i].tv_tag = tv_header_tags[i];
672
#define TVU(x) tv[i].tv_u.tv_ ## x
673
      switch (tv[i].tv_tag)
674
        {
675
        case LDPT_MESSAGE:
676
          TVU(message) = message;
677
          break;
678
        case LDPT_API_VERSION:
679
          TVU(val) = LD_PLUGIN_API_VERSION;
680
          break;
681
        case LDPT_GNU_LD_VERSION:
682
          TVU(val) = major * 100 + minor;
683
          break;
684
        case LDPT_LINKER_OUTPUT:
685
          TVU(val) = (link_info.relocatable
686
                      ? LDPO_REL
687
                      : (link_info.shared ? LDPO_DYN : LDPO_EXEC));
688
          break;
689
        case LDPT_OUTPUT_NAME:
690
          TVU(string) = output_filename;
691
          break;
692
        case LDPT_REGISTER_CLAIM_FILE_HOOK:
693
          TVU(register_claim_file) = register_claim_file;
694
          break;
695
        case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
696
          TVU(register_all_symbols_read) = register_all_symbols_read;
697
          break;
698
        case LDPT_REGISTER_CLEANUP_HOOK:
699
          TVU(register_cleanup) = register_cleanup;
700
          break;
701
        case LDPT_ADD_SYMBOLS:
702
          TVU(add_symbols) = add_symbols;
703
          break;
704
        case LDPT_GET_INPUT_FILE:
705
          TVU(get_input_file) = get_input_file;
706
          break;
707
        case LDPT_RELEASE_INPUT_FILE:
708
          TVU(release_input_file) = release_input_file;
709
          break;
710
        case LDPT_GET_SYMBOLS:
711
          TVU(get_symbols) = get_symbols;
712
          break;
713
        case LDPT_ADD_INPUT_FILE:
714
          TVU(add_input_file) = add_input_file;
715
          break;
716
        case LDPT_ADD_INPUT_LIBRARY:
717
          TVU(add_input_library) = add_input_library;
718
          break;
719
        case LDPT_SET_EXTRA_LIBRARY_PATH:
720
          TVU(set_extra_library_path) = set_extra_library_path;
721
          break;
722
        default:
723
          /* Added a new entry to the array without adding
724
             a new case to set up its value is a bug.  */
725
          FAIL ();
726
        }
727
#undef TVU
728
    }
729
  return tv_header_size;
730
}
731
 
732
/* Append the per-plugin args list and trailing LDPT_NULL to tv.  */
733
static void
734
set_tv_plugin_args (plugin_t *plugin, struct ld_plugin_tv *tv)
735
{
736
  plugin_arg_t *arg = plugin->args;
737
  while (arg)
738
    {
739
      tv->tv_tag = LDPT_OPTION;
740
      tv->tv_u.tv_string = arg->arg;
741
      arg = arg->next;
742
      tv++;
743
    }
744
  tv->tv_tag = LDPT_NULL;
745
  tv->tv_u.tv_val = 0;
746
}
747
 
748
/* Return true if any plugins are active this run.  Only valid
749
   after options have been processed.  */
750
bfd_boolean
751
plugin_active_plugins_p (void)
752
{
753
  return plugins_list != NULL;
754
}
755
 
756
/* Load up and initialise all plugins after argument parsing.  */
757
int
758
plugin_load_plugins (void)
759
{
760
  struct ld_plugin_tv *my_tv;
761
  unsigned int max_args = 0;
762
  plugin_t *curplug = plugins_list;
763
 
764
  /* If there are no plugins, we need do nothing this run.  */
765
  if (!curplug)
766
    return 0;
767
 
768
  /* First pass over plugins to find max # args needed so that we
769
     can size and allocate the tv array.  */
770
  while (curplug)
771
    {
772
      if (curplug->n_args > max_args)
773
        max_args = curplug->n_args;
774
      curplug = curplug->next;
775
    }
776
 
777
  /* Allocate tv array and initialise constant part.  */
778
  my_tv = xmalloc ((max_args + 1 + tv_header_size) * sizeof *my_tv);
779
  set_tv_header (my_tv);
780
 
781
  /* Pass over plugins again, activating them.  */
782
  curplug = plugins_list;
783
  while (curplug)
784
    {
785
      enum ld_plugin_status rv;
786
      ld_plugin_onload onloadfn = dlsym (curplug->dlhandle, "onload");
787
      if (!onloadfn)
788
        onloadfn = dlsym (curplug->dlhandle, "_onload");
789
      if (!onloadfn)
790
        return set_plugin_error (curplug->name);
791
      set_tv_plugin_args (curplug, &my_tv[tv_header_size]);
792
      called_plugin = curplug;
793
      rv = (*onloadfn) (my_tv);
794
      called_plugin = NULL;
795
      if (rv != LDPS_OK)
796
        return set_plugin_error (curplug->name);
797
      curplug = curplug->next;
798
    }
799
 
800
  /* Since plugin(s) inited ok, assume they're going to want symbol
801
     resolutions, which needs us to track which symbols are referenced
802
     by non-IR files using the linker's notice callback.  */
803
  orig_notice_all = link_info.notice_all;
804
  orig_callbacks = link_info.callbacks;
805
  plugin_callbacks = *orig_callbacks;
806
  plugin_callbacks.notice = &plugin_notice;
807
  link_info.notice_all = TRUE;
808
  link_info.callbacks = &plugin_callbacks;
809
 
810
  return 0;
811
}
812
 
813
/* Call 'claim file' hook for all plugins.  */
814
static int
815
plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
816
{
817
  plugin_t *curplug = plugins_list;
818
  *claimed = FALSE;
819
  if (no_more_claiming)
820
    return 0;
821
  while (curplug && !*claimed)
822
    {
823
      if (curplug->claim_file_handler)
824
        {
825
          enum ld_plugin_status rv;
826
          called_plugin = curplug;
827
          rv = (*curplug->claim_file_handler) (file, claimed);
828
          called_plugin = NULL;
829
          if (rv != LDPS_OK)
830
            set_plugin_error (curplug->name);
831
        }
832
      curplug = curplug->next;
833
    }
834
  return plugin_error_p () ? -1 : 0;
835
}
836
 
837
void
838
plugin_maybe_claim (struct ld_plugin_input_file *file,
839
                    lang_input_statement_type *entry)
840
{
841
  int claimed = 0;
842
 
843
  /* We create a dummy BFD, initially empty, to house whatever symbols
844
     the plugin may want to add.  */
845
  file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
846
                                          entry->the_bfd);
847
  if (plugin_call_claim_file (file, &claimed))
848
    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
849
           plugin_error_plugin ());
850
  /* fd belongs to us, not the plugin; but we don't need it.  */
851
  close (file->fd);
852
  if (claimed)
853
    {
854
      /* Discard the real file's BFD and substitute the dummy one.  */
855
 
856
      /* BFD archive handling caches elements so we can't call
857
         bfd_close for archives.  */
858
      if (entry->the_bfd->my_archive == NULL)
859
        bfd_close (entry->the_bfd);
860
      entry->the_bfd = file->handle;
861
      entry->claimed = TRUE;
862
      bfd_make_readable (entry->the_bfd);
863
    }
864
  else
865
    {
866
      /* If plugin didn't claim the file, we don't need the dummy bfd.
867
         Can't avoid speculatively creating it, alas.  */
868
      bfd_close_all_done (file->handle);
869
      entry->claimed = FALSE;
870
    }
871
}
872
 
873
/* Call 'all symbols read' hook for all plugins.  */
874
int
875
plugin_call_all_symbols_read (void)
876
{
877
  plugin_t *curplug = plugins_list;
878
 
879
  /* Disable any further file-claiming.  */
880
  no_more_claiming = TRUE;
881
 
882
  while (curplug)
883
    {
884
      if (curplug->all_symbols_read_handler)
885
        {
886
          enum ld_plugin_status rv;
887
          called_plugin = curplug;
888
          rv = (*curplug->all_symbols_read_handler) ();
889
          called_plugin = NULL;
890
          if (rv != LDPS_OK)
891
            set_plugin_error (curplug->name);
892
        }
893
      curplug = curplug->next;
894
    }
895
  return plugin_error_p () ? -1 : 0;
896
}
897
 
898
/* Call 'cleanup' hook for all plugins at exit.  */
899
void
900
plugin_call_cleanup (void)
901
{
902
  plugin_t *curplug = plugins_list;
903
  while (curplug)
904
    {
905
      if (curplug->cleanup_handler && !curplug->cleanup_done)
906
        {
907
          enum ld_plugin_status rv;
908
          curplug->cleanup_done = TRUE;
909
          called_plugin = curplug;
910
          rv = (*curplug->cleanup_handler) ();
911
          called_plugin = NULL;
912
          if (rv != LDPS_OK)
913
            set_plugin_error (curplug->name);
914
          dlclose (curplug->dlhandle);
915
        }
916
      curplug = curplug->next;
917
    }
918
  if (plugin_error_p ())
919
    info_msg (_("%P: %s: error in plugin cleanup (ignored)\n"),
920
              plugin_error_plugin ());
921
}
922
 
923
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
924
   and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
925
   the linker adds them to the linker hash table.  Mark those
926
   referenced from a non-IR file with non_ir_ref.  We have to
927
   notice_all symbols, because we won't necessarily know until later
928
   which ones will be contributed by IR files.  */
929
static bfd_boolean
930
plugin_notice (struct bfd_link_info *info,
931
               struct bfd_link_hash_entry *h,
932
               bfd *abfd,
933
               asection *section,
934
               bfd_vma value,
935
               flagword flags,
936
               const char *string)
937
{
938
  if (h != NULL)
939
    {
940
      bfd *sym_bfd;
941
 
942
      /* No further processing if this def/ref is from an IR dummy BFD.  */
943
      if (is_ir_dummy_bfd (abfd))
944
        return TRUE;
945
 
946
      /* Making an indirect symbol counts as a reference unless this
947
         is a brand new symbol.  */
948
      if (bfd_is_ind_section (section)
949
          || (flags & BSF_INDIRECT) != 0)
950
        {
951
          if (h->type != bfd_link_hash_new)
952
            {
953
              struct bfd_link_hash_entry *inh;
954
 
955
              h->non_ir_ref = TRUE;
956
              inh = bfd_wrapped_link_hash_lookup (abfd, info, string, FALSE,
957
                                                  FALSE, FALSE);
958
              if (inh != NULL)
959
                inh->non_ir_ref = TRUE;
960
            }
961
        }
962
 
963
      /* Nothing to do here for warning symbols.  */
964
      else if ((flags & BSF_WARNING) != 0)
965
        ;
966
 
967
      /* Nothing to do here for constructor symbols.  */
968
      else if ((flags & BSF_CONSTRUCTOR) != 0)
969
        ;
970
 
971
      /* If this is a ref, set non_ir_ref.  */
972
      else if (bfd_is_und_section (section))
973
        h->non_ir_ref = TRUE;
974
 
975
      /* Otherwise, it must be a new def.  Ensure any symbol defined
976
         in an IR dummy BFD takes on a new value from a real BFD.
977
         Weak symbols are not normally overridden by a new weak
978
         definition, and strong symbols will normally cause multiple
979
         definition errors.  Avoid this by making the symbol appear
980
         to be undefined.  */
981
      else if (((h->type == bfd_link_hash_defweak
982
                 || h->type == bfd_link_hash_defined)
983
                && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
984
               || (h->type == bfd_link_hash_common
985
                   && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
986
        {
987
          h->type = bfd_link_hash_undefweak;
988
          h->u.undef.abfd = sym_bfd;
989
        }
990
    }
991
 
992
  /* Continue with cref/nocrossref/trace-sym processing.  */
993
  if (h == NULL
994
      || orig_notice_all
995
      || (info->notice_hash != NULL
996
          && bfd_hash_lookup (info->notice_hash, h->root.string,
997
                              FALSE, FALSE) != NULL))
998
    return (*orig_callbacks->notice) (info, h,
999
                                      abfd, section, value, flags, string);
1000
  return TRUE;
1001
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.