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 241

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

powered by: WebSVN 2.1.0

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