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 154

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
          /* Create sections to own the symbols.  */
243
          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
      section = bfd_get_section_by_name (abfd, ".text");
288
      break;
289
 
290
    case LDPK_WEAKUNDEF:
291
      flags = BSF_WEAK;
292
      /* FALLTHRU */
293
    case LDPK_UNDEF:
294
      section = bfd_und_section_ptr;
295
      break;
296
 
297
    case LDPK_COMMON:
298
      flags = BSF_GLOBAL;
299
      section = bfd_com_section_ptr;
300
      asym->value = ldsym->size;
301
      /* For ELF targets, set alignment of common symbol to 1.  */
302
      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
303
        {
304
          ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
305
          ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
306
        }
307
      break;
308
 
309
    default:
310
      return LDPS_ERR;
311
    }
312
  asym->flags = flags;
313
  asym->section = section;
314
 
315
  /* Visibility only applies on ELF targets.  */
316
  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
317
    {
318
      elf_symbol_type *elfsym = elf_symbol_from (abfd, asym);
319
      unsigned char visibility;
320
 
321
      if (!elfsym)
322
        einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name);
323
      switch (ldsym->visibility)
324
        {
325
        default:
326
          einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"),
327
                 ldsym->visibility);
328
        case LDPV_DEFAULT:
329
          visibility = STV_DEFAULT;
330
          break;
331
        case LDPV_PROTECTED:
332
          visibility = STV_PROTECTED;
333
          break;
334
        case LDPV_INTERNAL:
335
          visibility = STV_INTERNAL;
336
          break;
337
        case LDPV_HIDDEN:
338
          visibility = STV_HIDDEN;
339
          break;
340
        }
341
      elfsym->internal_elf_sym.st_other
342
        = (visibility | (elfsym->internal_elf_sym.st_other
343
                         & ~ELF_ST_VISIBILITY (-1)));
344
    }
345
 
346
  return LDPS_OK;
347
}
348
 
349
/* Register a claim-file handler.  */
350
static enum ld_plugin_status
351
register_claim_file (ld_plugin_claim_file_handler handler)
352
{
353
  ASSERT (called_plugin);
354
  called_plugin->claim_file_handler = handler;
355
  return LDPS_OK;
356
}
357
 
358
/* Register an all-symbols-read handler.  */
359
static enum ld_plugin_status
360
register_all_symbols_read (ld_plugin_all_symbols_read_handler handler)
361
{
362
  ASSERT (called_plugin);
363
  called_plugin->all_symbols_read_handler = handler;
364
  return LDPS_OK;
365
}
366
 
367
/* Register a cleanup handler.  */
368
static enum ld_plugin_status
369
register_cleanup (ld_plugin_cleanup_handler handler)
370
{
371
  ASSERT (called_plugin);
372
  called_plugin->cleanup_handler = handler;
373
  return LDPS_OK;
374
}
375
 
376
/* Add symbols from a plugin-claimed input file.  */
377
static enum ld_plugin_status
378
add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
379
{
380
  asymbol **symptrs;
381
  bfd *abfd = handle;
382
  int n;
383
  ASSERT (called_plugin);
384
  symptrs = xmalloc (nsyms * sizeof *symptrs);
385
  for (n = 0; n < nsyms; n++)
386
    {
387
      enum ld_plugin_status rv;
388
      asymbol *bfdsym = bfd_make_empty_symbol (abfd);
389
      symptrs[n] = bfdsym;
390
      rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);
391
      if (rv != LDPS_OK)
392
        return rv;
393
    }
394
  bfd_set_symtab (abfd, symptrs, nsyms);
395
  return LDPS_OK;
396
}
397
 
398
/* Get the input file information with an open (possibly re-opened)
399
   file descriptor.  */
400
static enum ld_plugin_status
401
get_input_file (const void *handle, struct ld_plugin_input_file *file)
402
{
403
  ASSERT (called_plugin);
404
  handle = handle;
405
  file = file;
406
  return LDPS_ERR;
407
}
408
 
409
/* Release the input file.  */
410
static enum ld_plugin_status
411
release_input_file (const void *handle)
412
{
413
  ASSERT (called_plugin);
414
  handle = handle;
415
  return LDPS_ERR;
416
}
417
 
418
/* Return TRUE if a defined symbol might be reachable from outside the
419
   universe of claimed objects.  */
420
static inline bfd_boolean
421
is_visible_from_outside (struct ld_plugin_symbol *lsym, asection *section,
422
                         struct bfd_link_hash_entry *blhe)
423
{
424
  struct bfd_sym_chain *sym;
425
 
426
  /* Section's owner may be NULL if it is the absolute
427
     section, fortunately is_ir_dummy_bfd handles that.  */
428
  if (!is_ir_dummy_bfd (section->owner))
429
    return TRUE;
430
  if (link_info.relocatable)
431
    return TRUE;
432
  if (link_info.export_dynamic || link_info.shared)
433
    {
434
      /* Only ELF symbols really have visibility.  */
435
      if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
436
        {
437
          struct elf_link_hash_entry *el = (struct elf_link_hash_entry *)blhe;
438
          int vis = ELF_ST_VISIBILITY (el->other);
439
          return vis == STV_DEFAULT || vis == STV_PROTECTED;
440
        }
441
      /* On non-ELF targets, we can safely make inferences by considering
442
         what visibility the plugin would have liked to apply when it first
443
         sent us the symbol.  During ELF symbol processing, visibility only
444
         ever becomes more restrictive, not less, when symbols are merged,
445
         so this is a conservative estimate; it may give false positives,
446
         declaring something visible from outside when it in fact would
447
         not have been, but this will only lead to missed optimisation
448
         opportunities during LTRANS at worst; it will not give false
449
         negatives, which can lead to the disastrous conclusion that the
450
         related symbol is IRONLY.  (See GCC PR46319 for an example.)  */
451
      return (lsym->visibility == LDPV_DEFAULT
452
              || lsym->visibility == LDPV_PROTECTED);
453
    }
454
 
455
  for (sym = &entry_symbol; sym != NULL; sym = sym->next)
456
    if (sym->name
457
        && strcmp (sym->name, blhe->root.string) == 0)
458
      return TRUE;
459
 
460
  return FALSE;
461
}
462
 
463
/* Get the symbol resolution info for a plugin-claimed input file.  */
464
static enum ld_plugin_status
465
get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
466
{
467
  const bfd *abfd = handle;
468
  int n;
469
  ASSERT (called_plugin);
470
  for (n = 0; n < nsyms; n++)
471
    {
472
      struct bfd_link_hash_entry *blhe;
473
      bfd_boolean ironly;
474
      asection *owner_sec;
475
      if (syms[n].def != LDPK_UNDEF)
476
        blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
477
                                     FALSE, FALSE, TRUE);
478
      else
479
        blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info,
480
                                             syms[n].name, FALSE, FALSE, TRUE);
481
      if (!blhe)
482
        {
483
          syms[n].resolution = LDPR_UNKNOWN;
484
          goto report_symbol;
485
        }
486
 
487
      /* Determine resolution from blhe type and symbol's original type.  */
488
      if (blhe->type == bfd_link_hash_undefined
489
          || blhe->type == bfd_link_hash_undefweak)
490
        {
491
          syms[n].resolution = LDPR_UNDEF;
492
          goto report_symbol;
493
        }
494
      if (blhe->type != bfd_link_hash_defined
495
          && blhe->type != bfd_link_hash_defweak
496
          && blhe->type != bfd_link_hash_common)
497
        {
498
          /* We should not have a new, indirect or warning symbol here.  */
499
          einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)\n",
500
                 called_plugin->name, blhe->type);
501
        }
502
 
503
      /* Find out which section owns the symbol.  Since it's not undef,
504
         it must have an owner; if it's not a common symbol, both defs
505
         and weakdefs keep it in the same place. */
506
      owner_sec = (blhe->type == bfd_link_hash_common
507
                   ? blhe->u.c.p->section
508
                   : blhe->u.def.section);
509
 
510
      /* We need to know if the sym is referenced from non-IR files.  Or
511
         even potentially-referenced, perhaps in a future final link if
512
         this is a partial one, perhaps dynamically at load-time if the
513
         symbol is externally visible.  */
514
      ironly = !(blhe->non_ir_ref
515
                 || is_visible_from_outside (&syms[n], owner_sec, blhe));
516
 
517
      /* If it was originally undefined or common, then it has been
518
         resolved; determine how.  */
519
      if (syms[n].def == LDPK_UNDEF
520
          || syms[n].def == LDPK_WEAKUNDEF
521
          || syms[n].def == LDPK_COMMON)
522
        {
523
          if (owner_sec->owner == link_info.output_bfd)
524
            syms[n].resolution = LDPR_RESOLVED_EXEC;
525
          else if (owner_sec->owner == abfd)
526
            syms[n].resolution = (ironly
527
                                  ? LDPR_PREVAILING_DEF_IRONLY
528
                                  : LDPR_PREVAILING_DEF);
529
          else if (is_ir_dummy_bfd (owner_sec->owner))
530
            syms[n].resolution = LDPR_RESOLVED_IR;
531
          else if (owner_sec->owner != NULL
532
                   && (owner_sec->owner->flags & DYNAMIC) != 0)
533
            syms[n].resolution =  LDPR_RESOLVED_DYN;
534
          else
535
            syms[n].resolution = LDPR_RESOLVED_EXEC;
536
          goto report_symbol;
537
        }
538
 
539
      /* Was originally def, or weakdef.  Does it prevail?  If the
540
         owner is the original dummy bfd that supplied it, then this
541
         is the definition that has prevailed.  */
542
      if (owner_sec->owner == link_info.output_bfd)
543
        syms[n].resolution = LDPR_PREEMPTED_REG;
544
      else if (owner_sec->owner == abfd)
545
        {
546
          syms[n].resolution = (ironly
547
                                ? LDPR_PREVAILING_DEF_IRONLY
548
                                : LDPR_PREVAILING_DEF);
549
          goto report_symbol;
550
        }
551
 
552
      /* Was originally def, weakdef, or common, but has been pre-empted.  */
553
      syms[n].resolution = (is_ir_dummy_bfd (owner_sec->owner)
554
                            ? LDPR_PREEMPTED_IR
555
                            : LDPR_PREEMPTED_REG);
556
 
557
    report_symbol:
558
      if (report_plugin_symbols)
559
        einfo (_("%P: %B: symbol `%s' "
560
                 "definition: %d, visibility: %d, resolution: %d\n"),
561
               abfd, syms[n].name,
562
               syms[n].def, syms[n].visibility, syms[n].resolution);
563
    }
564
  return LDPS_OK;
565
}
566
 
567
/* Add a new (real) input file generated by a plugin.  */
568
static enum ld_plugin_status
569
add_input_file (const char *pathname)
570
{
571
  ASSERT (called_plugin);
572
  if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
573
                            NULL))
574
    return LDPS_ERR;
575
  return LDPS_OK;
576
}
577
 
578
/* Add a new (real) library required by a plugin.  */
579
static enum ld_plugin_status
580
add_input_library (const char *pathname)
581
{
582
  ASSERT (called_plugin);
583
  if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
584
                            NULL))
585
    return LDPS_ERR;
586
  return LDPS_OK;
587
}
588
 
589
/* Set the extra library path to be used by libraries added via
590
   add_input_library.  */
591
static enum ld_plugin_status
592
set_extra_library_path (const char *path)
593
{
594
  ASSERT (called_plugin);
595
  ldfile_add_library_path (xstrdup (path), FALSE);
596
  return LDPS_OK;
597
}
598
 
599
/* Issue a diagnostic message from a plugin.  */
600
static enum ld_plugin_status
601
message (int level, const char *format, ...)
602
{
603
  va_list args;
604
  va_start (args, format);
605
 
606
  switch (level)
607
    {
608
    case LDPL_INFO:
609
      vfinfo (stdout, format, args, FALSE);
610
      putchar ('\n');
611
      break;
612
    case LDPL_WARNING:
613
      vfinfo (stdout, format, args, TRUE);
614
      putchar ('\n');
615
      break;
616
    case LDPL_FATAL:
617
    case LDPL_ERROR:
618
    default:
619
      {
620
        char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ",
621
                                 format, "\n", (const char *) NULL));
622
        fflush (stdout);
623
        vfinfo (stderr, newfmt, args, TRUE);
624
        fflush (stderr);
625
      }
626
      break;
627
    }
628
 
629
  va_end (args);
630
  return LDPS_OK;
631
}
632
 
633
/* Helper to size leading part of tv array and set it up. */
634
static size_t
635
set_tv_header (struct ld_plugin_tv *tv)
636
{
637
  size_t i;
638
 
639
  /* Version info.  */
640
  static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL);
641
  static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100;
642
 
643
  if (!tv)
644
    return tv_header_size;
645
 
646
  for (i = 0; i < tv_header_size; i++)
647
    {
648
      tv[i].tv_tag = tv_header_tags[i];
649
#define TVU(x) tv[i].tv_u.tv_ ## x
650
      switch (tv[i].tv_tag)
651
        {
652
        case LDPT_MESSAGE:
653
          TVU(message) = message;
654
          break;
655
        case LDPT_API_VERSION:
656
          TVU(val) = LD_PLUGIN_API_VERSION;
657
          break;
658
        case LDPT_GNU_LD_VERSION:
659
          TVU(val) = major * 100 + minor;
660
          break;
661
        case LDPT_LINKER_OUTPUT:
662
          TVU(val) = (link_info.relocatable
663
                      ? LDPO_REL
664
                      : (link_info.shared ? LDPO_DYN : LDPO_EXEC));
665
          break;
666
        case LDPT_OUTPUT_NAME:
667
          TVU(string) = output_filename;
668
          break;
669
        case LDPT_REGISTER_CLAIM_FILE_HOOK:
670
          TVU(register_claim_file) = register_claim_file;
671
          break;
672
        case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
673
          TVU(register_all_symbols_read) = register_all_symbols_read;
674
          break;
675
        case LDPT_REGISTER_CLEANUP_HOOK:
676
          TVU(register_cleanup) = register_cleanup;
677
          break;
678
        case LDPT_ADD_SYMBOLS:
679
          TVU(add_symbols) = add_symbols;
680
          break;
681
        case LDPT_GET_INPUT_FILE:
682
          TVU(get_input_file) = get_input_file;
683
          break;
684
        case LDPT_RELEASE_INPUT_FILE:
685
          TVU(release_input_file) = release_input_file;
686
          break;
687
        case LDPT_GET_SYMBOLS:
688
          TVU(get_symbols) = get_symbols;
689
          break;
690
        case LDPT_ADD_INPUT_FILE:
691
          TVU(add_input_file) = add_input_file;
692
          break;
693
        case LDPT_ADD_INPUT_LIBRARY:
694
          TVU(add_input_library) = add_input_library;
695
          break;
696
        case LDPT_SET_EXTRA_LIBRARY_PATH:
697
          TVU(set_extra_library_path) = set_extra_library_path;
698
          break;
699
        default:
700
          /* Added a new entry to the array without adding
701
             a new case to set up its value is a bug.  */
702
          FAIL ();
703
        }
704
#undef TVU
705
    }
706
  return tv_header_size;
707
}
708
 
709
/* Append the per-plugin args list and trailing LDPT_NULL to tv.  */
710
static void
711
set_tv_plugin_args (plugin_t *plugin, struct ld_plugin_tv *tv)
712
{
713
  plugin_arg_t *arg = plugin->args;
714
  while (arg)
715
    {
716
      tv->tv_tag = LDPT_OPTION;
717
      tv->tv_u.tv_string = arg->arg;
718
      arg = arg->next;
719
      tv++;
720
    }
721
  tv->tv_tag = LDPT_NULL;
722
  tv->tv_u.tv_val = 0;
723
}
724
 
725
/* Return true if any plugins are active this run.  Only valid
726
   after options have been processed.  */
727
bfd_boolean
728
plugin_active_plugins_p (void)
729
{
730
  return plugins_list != NULL;
731
}
732
 
733
/* Load up and initialise all plugins after argument parsing.  */
734
int
735
plugin_load_plugins (void)
736
{
737
  struct ld_plugin_tv *my_tv;
738
  unsigned int max_args = 0;
739
  plugin_t *curplug = plugins_list;
740
 
741
  /* If there are no plugins, we need do nothing this run.  */
742
  if (!curplug)
743
    return 0;
744
 
745
  /* First pass over plugins to find max # args needed so that we
746
     can size and allocate the tv array.  */
747
  while (curplug)
748
    {
749
      if (curplug->n_args > max_args)
750
        max_args = curplug->n_args;
751
      curplug = curplug->next;
752
    }
753
 
754
  /* Allocate tv array and initialise constant part.  */
755
  my_tv = xmalloc ((max_args + 1 + tv_header_size) * sizeof *my_tv);
756
  set_tv_header (my_tv);
757
 
758
  /* Pass over plugins again, activating them.  */
759
  curplug = plugins_list;
760
  while (curplug)
761
    {
762
      enum ld_plugin_status rv;
763
      ld_plugin_onload onloadfn = dlsym (curplug->dlhandle, "onload");
764
      if (!onloadfn)
765
        onloadfn = dlsym (curplug->dlhandle, "_onload");
766
      if (!onloadfn)
767
        return set_plugin_error (curplug->name);
768
      set_tv_plugin_args (curplug, &my_tv[tv_header_size]);
769
      called_plugin = curplug;
770
      rv = (*onloadfn) (my_tv);
771
      called_plugin = NULL;
772
      if (rv != LDPS_OK)
773
        return set_plugin_error (curplug->name);
774
      curplug = curplug->next;
775
    }
776
 
777
  /* Since plugin(s) inited ok, assume they're going to want symbol
778
     resolutions, which needs us to track which symbols are referenced
779
     by non-IR files using the linker's notice callback.  */
780
  orig_notice_all = link_info.notice_all;
781
  orig_callbacks = link_info.callbacks;
782
  plugin_callbacks = *orig_callbacks;
783
  plugin_callbacks.notice = &plugin_notice;
784
  link_info.notice_all = TRUE;
785
  link_info.callbacks = &plugin_callbacks;
786
 
787
  return 0;
788
}
789
 
790
/* Call 'claim file' hook for all plugins.  */
791
static int
792
plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
793
{
794
  plugin_t *curplug = plugins_list;
795
  *claimed = FALSE;
796
  if (no_more_claiming)
797
    return 0;
798
  while (curplug && !*claimed)
799
    {
800
      if (curplug->claim_file_handler)
801
        {
802
          enum ld_plugin_status rv;
803
          called_plugin = curplug;
804
          rv = (*curplug->claim_file_handler) (file, claimed);
805
          called_plugin = NULL;
806
          if (rv != LDPS_OK)
807
            set_plugin_error (curplug->name);
808
        }
809
      curplug = curplug->next;
810
    }
811
  return plugin_error_p () ? -1 : 0;
812
}
813
 
814
void
815
plugin_maybe_claim (struct ld_plugin_input_file *file,
816
                    lang_input_statement_type *entry)
817
{
818
  int claimed = 0;
819
 
820
  /* We create a dummy BFD, initially empty, to house whatever symbols
821
     the plugin may want to add.  */
822
  file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
823
                                          entry->the_bfd);
824
  if (plugin_call_claim_file (file, &claimed))
825
    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
826
           plugin_error_plugin ());
827
  /* fd belongs to us, not the plugin; but we don't need it.  */
828
  close (file->fd);
829
  if (claimed)
830
    {
831
      /* Discard the real file's BFD and substitute the dummy one.  */
832
 
833
      /* BFD archive handling caches elements so we can't call
834
         bfd_close for archives.  */
835
      if (entry->the_bfd->my_archive == NULL)
836
        bfd_close (entry->the_bfd);
837
      entry->the_bfd = file->handle;
838
      entry->claimed = TRUE;
839
      bfd_make_readable (entry->the_bfd);
840
    }
841
  else
842
    {
843
      /* If plugin didn't claim the file, we don't need the dummy bfd.
844
         Can't avoid speculatively creating it, alas.  */
845
      bfd_close_all_done (file->handle);
846
      entry->claimed = FALSE;
847
    }
848
}
849
 
850
/* Call 'all symbols read' hook for all plugins.  */
851
int
852
plugin_call_all_symbols_read (void)
853
{
854
  plugin_t *curplug = plugins_list;
855
 
856
  /* Disable any further file-claiming.  */
857
  no_more_claiming = TRUE;
858
 
859
  while (curplug)
860
    {
861
      if (curplug->all_symbols_read_handler)
862
        {
863
          enum ld_plugin_status rv;
864
          called_plugin = curplug;
865
          rv = (*curplug->all_symbols_read_handler) ();
866
          called_plugin = NULL;
867
          if (rv != LDPS_OK)
868
            set_plugin_error (curplug->name);
869
        }
870
      curplug = curplug->next;
871
    }
872
  return plugin_error_p () ? -1 : 0;
873
}
874
 
875
/* Call 'cleanup' hook for all plugins at exit.  */
876
void
877
plugin_call_cleanup (void)
878
{
879
  plugin_t *curplug = plugins_list;
880
  while (curplug)
881
    {
882
      if (curplug->cleanup_handler && !curplug->cleanup_done)
883
        {
884
          enum ld_plugin_status rv;
885
          curplug->cleanup_done = TRUE;
886
          called_plugin = curplug;
887
          rv = (*curplug->cleanup_handler) ();
888
          called_plugin = NULL;
889
          if (rv != LDPS_OK)
890
            set_plugin_error (curplug->name);
891
          dlclose (curplug->dlhandle);
892
        }
893
      curplug = curplug->next;
894
    }
895
  if (plugin_error_p ())
896
    info_msg (_("%P: %s: error in plugin cleanup (ignored)\n"),
897
              plugin_error_plugin ());
898
}
899
 
900
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
901
   and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
902
   the linker adds them to the linker hash table.  Mark those
903
   referenced from a non-IR file with non_ir_ref.  We have to
904
   notice_all symbols, because we won't necessarily know until later
905
   which ones will be contributed by IR files.  */
906
static bfd_boolean
907
plugin_notice (struct bfd_link_info *info,
908
               struct bfd_link_hash_entry *h,
909
               bfd *abfd,
910
               asection *section,
911
               bfd_vma value,
912
               flagword flags,
913
               const char *string)
914
{
915
  if (h != NULL)
916
    {
917
      bfd *sym_bfd;
918
 
919
      /* No further processing if this def/ref is from an IR dummy BFD.  */
920
      if (is_ir_dummy_bfd (abfd))
921
        return TRUE;
922
 
923
      /* Making an indirect symbol counts as a reference unless this
924
         is a brand new symbol.  */
925
      if (bfd_is_ind_section (section)
926
          || (flags & BSF_INDIRECT) != 0)
927
        {
928
          if (h->type != bfd_link_hash_new)
929
            {
930
              struct bfd_link_hash_entry *inh;
931
 
932
              h->non_ir_ref = TRUE;
933
              inh = bfd_wrapped_link_hash_lookup (abfd, info, string, FALSE,
934
                                                  FALSE, FALSE);
935
              if (inh != NULL)
936
                inh->non_ir_ref = TRUE;
937
            }
938
        }
939
 
940
      /* Nothing to do here for warning symbols.  */
941
      else if ((flags & BSF_WARNING) != 0)
942
        ;
943
 
944
      /* Nothing to do here for constructor symbols.  */
945
      else if ((flags & BSF_CONSTRUCTOR) != 0)
946
        ;
947
 
948
      /* If this is a ref, set non_ir_ref.  */
949
      else if (bfd_is_und_section (section))
950
        h->non_ir_ref = TRUE;
951
 
952
      /* Otherwise, it must be a new def.  Ensure any symbol defined
953
         in an IR dummy BFD takes on a new value from a real BFD.
954
         Weak symbols are not normally overridden by a new weak
955
         definition, and strong symbols will normally cause multiple
956
         definition errors.  Avoid this by making the symbol appear
957
         to be undefined.  */
958
      else if (((h->type == bfd_link_hash_defweak
959
                 || h->type == bfd_link_hash_defined)
960
                && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
961
               || (h->type == bfd_link_hash_common
962
                   && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
963
        {
964
          h->type = bfd_link_hash_undefweak;
965
          h->u.undef.abfd = sym_bfd;
966
        }
967
    }
968
 
969
  /* Continue with cref/nocrossref/trace-sym processing.  */
970
  if (h == NULL
971
      || orig_notice_all
972
      || (info->notice_hash != NULL
973
          && bfd_hash_lookup (info->notice_hash, h->root.string,
974
                              FALSE, FALSE) != NULL))
975
    return (*orig_callbacks->notice) (info, h,
976
                                      abfd, section, value, flags, string);
977
  return TRUE;
978
}

powered by: WebSVN 2.1.0

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