Coverage Report

Created: 2026-03-10 08:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/bfd/plugin.c
Line
Count
Source
1
/* Plugin support for BFD.
2
   Copyright (C) 2009-2026 Free Software Foundation, Inc.
3
4
   This file is part of BFD, the Binary File Descriptor library.
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.  */
20
21
#include "sysdep.h"
22
#include "bfd.h"
23
24
#if BFD_SUPPORTS_PLUGINS
25
26
#include <assert.h>
27
#ifdef HAVE_DLFCN_H
28
#include <dlfcn.h>
29
#elif defined (HAVE_WINDOWS_H)
30
#include <windows.h>
31
#else
32
#error Unknown how to handle dynamic-load-libraries.
33
#endif
34
#include <stdarg.h>
35
#include "plugin-api.h"
36
#include "plugin.h"
37
#include "libbfd.h"
38
#include "libiberty.h"
39
#include <dirent.h>
40
41
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
42
43
#define RTLD_NOW 0      /* Dummy value.  */
44
45
static void *
46
dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
47
{
48
  return LoadLibrary (file);
49
}
50
51
static void *
52
dlsym (void *handle, const char *name)
53
{
54
  return GetProcAddress (handle, name);
55
}
56
57
static int ATTRIBUTE_UNUSED
58
dlclose (void *handle)
59
{
60
  FreeLibrary (handle);
61
  return 0;
62
}
63
64
static const char *
65
dlerror (void)
66
{
67
  return "Unable to load DLL.";
68
}
69
70
#endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)  */
71
72
#define bfd_plugin_close_and_cleanup          _bfd_generic_close_and_cleanup
73
#define bfd_plugin_bfd_free_cached_info         _bfd_generic_bfd_free_cached_info
74
#define bfd_plugin_new_section_hook         _bfd_generic_new_section_hook
75
#define bfd_plugin_get_section_contents         _bfd_generic_get_section_contents
76
#define bfd_plugin_bfd_merge_private_bfd_data       _bfd_generic_bfd_merge_private_bfd_data
77
#define bfd_plugin_bfd_copy_private_header_data       _bfd_generic_bfd_copy_private_header_data
78
#define bfd_plugin_bfd_set_private_flags        _bfd_generic_bfd_set_private_flags
79
#define bfd_plugin_core_file_matches_executable_p     generic_core_file_matches_executable_p
80
#define bfd_plugin_bfd_is_local_label_name        _bfd_nosymbols_bfd_is_local_label_name
81
#define bfd_plugin_bfd_is_target_special_symbol       _bfd_bool_bfd_asymbol_false
82
#define bfd_plugin_get_lineno           _bfd_nosymbols_get_lineno
83
#define bfd_plugin_find_nearest_line          _bfd_nosymbols_find_nearest_line
84
#define bfd_plugin_find_nearest_line_with_alt       _bfd_nosymbols_find_nearest_line_with_alt
85
#define bfd_plugin_find_line            _bfd_nosymbols_find_line
86
#define bfd_plugin_find_inliner_info          _bfd_nosymbols_find_inliner_info
87
#define bfd_plugin_get_symbol_version_string        _bfd_nosymbols_get_symbol_version_string
88
#define bfd_plugin_bfd_make_debug_symbol        _bfd_nosymbols_bfd_make_debug_symbol
89
#define bfd_plugin_read_minisymbols         _bfd_generic_read_minisymbols
90
#define bfd_plugin_minisymbol_to_symbol         _bfd_generic_minisymbol_to_symbol
91
#define bfd_plugin_set_arch_mach          bfd_default_set_arch_mach
92
#define bfd_plugin_set_section_contents         _bfd_generic_set_section_contents
93
#define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
94
#define bfd_plugin_bfd_relax_section          bfd_generic_relax_section
95
#define bfd_plugin_bfd_link_hash_table_create       _bfd_generic_link_hash_table_create
96
#define bfd_plugin_bfd_link_add_symbols         _bfd_generic_link_add_symbols
97
#define bfd_plugin_bfd_link_just_syms         _bfd_generic_link_just_syms
98
#define bfd_plugin_bfd_final_link         _bfd_generic_final_link
99
#define bfd_plugin_bfd_link_split_section       _bfd_generic_link_split_section
100
#define bfd_plugin_bfd_gc_sections          bfd_generic_gc_sections
101
#define bfd_plugin_bfd_lookup_section_flags       bfd_generic_lookup_section_flags
102
#define bfd_plugin_bfd_is_group_section         bfd_generic_is_group_section
103
#define bfd_plugin_bfd_group_name         bfd_generic_group_name
104
#define bfd_plugin_bfd_discard_group          bfd_generic_discard_group
105
#define bfd_plugin_section_already_linked       _bfd_generic_section_already_linked
106
#define bfd_plugin_bfd_define_common_symbol       bfd_generic_define_common_symbol
107
#define bfd_plugin_bfd_link_hide_symbol         _bfd_generic_link_hide_symbol
108
#define bfd_plugin_bfd_define_start_stop        bfd_generic_define_start_stop
109
#define bfd_plugin_bfd_copy_link_hash_symbol_type     _bfd_generic_copy_link_hash_symbol_type
110
#define bfd_plugin_bfd_link_check_relocs        _bfd_generic_link_check_relocs
111
112
static enum ld_plugin_status
113
message (int level ATTRIBUTE_UNUSED,
114
   const char * format, ...)
115
0
{
116
0
  va_list args;
117
0
  va_start (args, format);
118
0
  printf ("bfd plugin: ");
119
0
  vprintf (format, args);
120
0
  putchar ('\n');
121
0
  va_end (args);
122
0
  return LDPS_OK;
123
0
}
124
125
struct plugin_list_entry
126
{
127
  /* These must be initialized for each IR object with LTO wrapper.  */
128
  ld_plugin_claim_file_handler claim_file;
129
  ld_plugin_claim_file_handler_v2 claim_file_v2;
130
  ld_plugin_all_symbols_read_handler all_symbols_read;
131
  ld_plugin_all_symbols_read_handler cleanup_handler;
132
  bool has_symbol_type;
133
134
  struct plugin_list_entry *next;
135
136
  /* These can be reused for all IR objects.  */
137
  const char *plugin_name;
138
};
139
140
struct plugin_data_struct
141
{
142
  int nsyms;
143
  const struct ld_plugin_symbol *syms;
144
  int object_only_nsyms;
145
  asymbol **object_only_syms;
146
};
147
148
static const char *plugin_program_name;
149
150
void
151
bfd_plugin_set_program_name (const char *program_name)
152
0
{
153
0
  plugin_program_name = program_name;
154
0
}
155
156
static struct plugin_list_entry *plugin_list = NULL;
157
static struct plugin_list_entry *current_plugin = NULL;
158
159
/* Register a claim-file handler. */
160
161
static enum ld_plugin_status
162
register_claim_file (ld_plugin_claim_file_handler handler)
163
0
{
164
0
  current_plugin->claim_file = handler;
165
0
  return LDPS_OK;
166
0
}
167
168
static asection bfd_plugin_fake_text_section
169
  = BFD_FAKE_SECTION (bfd_plugin_fake_text_section, NULL, "plug", 0,
170
          SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS);
171
static asection bfd_plugin_fake_data_section
172
  = BFD_FAKE_SECTION (bfd_plugin_fake_data_section, NULL, "plug", 0,
173
          SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS);
174
static asection bfd_plugin_fake_bss_section
175
  = BFD_FAKE_SECTION (bfd_plugin_fake_bss_section, NULL, "plug", 0,
176
          SEC_ALLOC);
177
static asection bfd_plugin_fake_common_section
178
  = BFD_FAKE_SECTION (bfd_plugin_fake_common_section, NULL, NULL,
179
          0, SEC_IS_COMMON);
180
181
/* Get symbols from object only section.  */
182
183
static void
184
bfd_plugin_get_symbols_in_object_only (bfd *abfd)
185
0
{
186
0
  struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
187
0
  const char *object_only_file;
188
0
  bfd *nbfd;
189
0
  long storage;
190
0
  long object_only_nsyms, added_nsyms, i;
191
0
  asymbol **object_only_syms, **added_syms;
192
193
0
  plugin_data->object_only_syms = NULL;
194
0
  plugin_data->object_only_nsyms = 0;
195
196
0
  if (abfd->sections == NULL && abfd->my_archive == NULL)
197
0
    {
198
0
      nbfd = bfd_openr (abfd->filename, NULL);
199
0
      if (nbfd == NULL)
200
0
  {
201
0
    (*_bfd_error_handler)
202
0
      (_("%s: failed to open to extract object only section: %s"),
203
0
       abfd->filename, bfd_errmsg (bfd_get_error ()));
204
0
    return;
205
0
  }
206
      /* Prevent this recursive call into bfd_check_format from
207
   attempting to load the plugin again while it is running.  */
208
0
      nbfd->plugin_format = bfd_plugin_no;
209
0
      if (!bfd_check_format (nbfd, bfd_object))
210
0
  {
211
    /* There is no object only section if it isn't a bfd_object
212
       file.  */
213
0
    bfd_close (nbfd);
214
0
    return;
215
0
  }
216
217
      /* Copy LTO type derived from input sections.  */
218
0
      abfd->lto_type = nbfd->lto_type;
219
0
    }
220
0
  else
221
0
    {
222
0
      BFD_ASSERT (abfd->plugin_format == bfd_plugin_no);
223
0
      if (!bfd_check_format (abfd, bfd_object))
224
0
  {
225
0
    (*_bfd_error_handler)
226
0
      (_("%pB: invalid file to extract object only section: %s"),
227
0
       abfd, bfd_errmsg (bfd_get_error ()));
228
0
    return;
229
0
  }
230
0
      nbfd = abfd;
231
0
    }
232
233
0
  if (nbfd->lto_type == lto_mixed_object
234
0
      && (nbfd->flags & HAS_SYMS) != 0)
235
0
    {
236
0
      object_only_file = bfd_extract_object_only_section (nbfd);
237
0
      if (object_only_file == NULL)
238
0
  (*_bfd_error_handler)
239
0
    (_("%pB: failed to extract object only section: %s"),
240
0
     abfd, bfd_errmsg (bfd_get_error ()));
241
0
    }
242
0
  else
243
0
    object_only_file = NULL;
244
245
  /* Close the new bfd we just opened.  */
246
0
  if (nbfd != abfd)
247
0
    bfd_close (nbfd);
248
249
  /* Return if there is no object only section or there is no
250
     symbol in object only section.  */
251
0
  if (!object_only_file)
252
0
    return;
253
254
  /* Open the file containing object only section.  */
255
0
  nbfd = bfd_openr (object_only_file, NULL);
256
  /* Prevent this recursive call into bfd_check_format from
257
     attempting to load the plugin again while it is running.  */
258
0
  nbfd->plugin_format = bfd_plugin_no;
259
0
  if (!bfd_check_format (nbfd, bfd_object))
260
0
    {
261
0
      (*_bfd_error_handler)
262
0
  (_("%pB: failed to open object only section: %s"),
263
0
   abfd, bfd_errmsg (bfd_get_error ()));
264
0
      goto quit;
265
0
    }
266
267
0
  storage = bfd_get_symtab_upper_bound (nbfd);
268
0
  if (storage <= 0)
269
0
    {
270
0
      if (storage < 0)
271
0
  (*_bfd_error_handler)
272
0
    (_("%pB: failed to get symbol table in object only section: %s"),
273
0
     abfd, bfd_errmsg (bfd_get_error ()));
274
275
0
      goto quit;
276
0
    }
277
278
0
  object_only_syms = (asymbol **) bfd_malloc (storage);
279
0
  object_only_nsyms = bfd_canonicalize_symtab (nbfd, object_only_syms);
280
281
  /* FIXME: We waste some spaces if not all symbols are copied.  */
282
0
  added_syms = (asymbol **) bfd_alloc (abfd, storage);
283
0
  added_nsyms = 0;
284
285
  /* Copy only global symbols from object only section.  */
286
0
  for (i = 0; i < object_only_nsyms; i++)
287
0
    {
288
0
      asection *sec = object_only_syms[i]->section;
289
0
      flagword flags = object_only_syms[i]->flags;
290
0
      asymbol *s;
291
292
0
      if (bfd_is_com_section (sec))
293
0
  sec = &bfd_plugin_fake_common_section;
294
0
      else if (bfd_is_und_section (sec))
295
0
  ;
296
0
      else if ((flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0)
297
0
  {
298
0
    if ((sec->flags & SEC_CODE) != 0)
299
0
      sec = &bfd_plugin_fake_text_section;
300
0
    else if ((sec->flags & SEC_LOAD) != 0)
301
0
      sec = &bfd_plugin_fake_data_section;
302
0
    else
303
0
      sec = &bfd_plugin_fake_bss_section;
304
0
  }
305
0
      else
306
0
  continue;
307
308
0
      s = bfd_alloc (abfd, sizeof (asymbol));
309
0
      BFD_ASSERT (s);
310
0
      added_syms[added_nsyms++] = s;
311
312
0
      s->section = sec;
313
0
      s->the_bfd = abfd;
314
0
      s->name = xstrdup (object_only_syms[i]->name);
315
0
      s->value = 0;
316
0
      s->flags = flags;
317
0
      s->udata.p = NULL;
318
0
    }
319
320
0
  plugin_data->object_only_syms = added_syms;
321
0
  plugin_data->object_only_nsyms = added_nsyms;
322
323
0
  free (object_only_syms);
324
325
0
quit:
326
  /* Close and remove the object only section file.  */
327
0
  bfd_close (nbfd);
328
0
  unlink (object_only_file);
329
0
}
330
331
/* Register a claim-file handler, version 2. */
332
333
static enum ld_plugin_status
334
register_claim_file_v2 (ld_plugin_claim_file_handler_v2 handler)
335
0
{
336
0
  current_plugin->claim_file_v2 = handler;
337
0
  return LDPS_OK;
338
0
}
339
340
static enum ld_plugin_status
341
add_symbols (void * handle,
342
       int nsyms,
343
       const struct ld_plugin_symbol * syms)
344
0
{
345
0
  bfd *abfd = handle;
346
0
  struct plugin_data_struct *plugin_data = bfd_alloc (abfd,
347
0
                  sizeof (*plugin_data));
348
0
  if (!plugin_data)
349
0
    return LDPS_ERR;
350
351
0
  plugin_data->nsyms = nsyms;
352
0
  plugin_data->syms = syms;
353
354
0
  abfd->tdata.plugin_data = plugin_data;
355
356
0
  bfd_plugin_get_symbols_in_object_only (abfd);
357
358
0
  if ((nsyms + plugin_data->object_only_nsyms) != 0)
359
0
    abfd->flags |= HAS_SYMS;
360
361
0
  return LDPS_OK;
362
0
}
363
364
static enum ld_plugin_status
365
add_symbols_v2 (void *handle, int nsyms,
366
    const struct ld_plugin_symbol *syms)
367
0
{
368
0
  current_plugin->has_symbol_type = true;
369
0
  return add_symbols (handle, nsyms, syms);
370
0
}
371
372
int
373
bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
374
0
{
375
0
  bfd *iobfd;
376
0
  int fd;
377
378
0
  iobfd = ibfd;
379
0
  while (iobfd->my_archive
380
0
   && iobfd->my_archive->iovec == iobfd->iovec
381
0
   && !bfd_is_thin_archive (iobfd->my_archive))
382
0
    iobfd = iobfd->my_archive;
383
0
  file->name = bfd_get_filename (iobfd);
384
385
0
  if (!iobfd->iostream && !bfd_open_file (iobfd))
386
0
    return 0;
387
388
  /* Reuse the archive plugin file descriptor.  */
389
0
  if (iobfd != ibfd)
390
0
    fd = iobfd->archive_plugin_fd;
391
0
  else
392
0
    fd = -1;
393
394
0
  if (fd < 0)
395
0
    {
396
      /* The plugin API expects that the file descriptor won't be closed
397
   and reused as done by the bfd file cache.  So open it again.
398
   dup isn't good enough.  plugin IO uses lseek/read while BFD uses
399
   fseek/fread.  It isn't wise to mix the unistd and stdio calls on
400
   the same underlying file descriptor.  */
401
0
      fd = open (file->name, O_RDONLY | O_BINARY);
402
0
      if (fd < 0)
403
0
  {
404
#ifndef EMFILE
405
    return 0;
406
#else
407
0
    if (errno != EMFILE)
408
0
      return 0;
409
410
0
#ifdef HAVE_GETRLIMIT
411
0
    struct rlimit lim;
412
413
    /* Complicated links involving lots of files and/or large
414
       archives can exhaust the number of file descriptors
415
       available to us.  If possible, try to allocate more
416
       descriptors.  */
417
0
    if (getrlimit (RLIMIT_NOFILE, & lim) == 0
418
0
        && lim.rlim_cur < lim.rlim_max)
419
0
      {
420
0
        lim.rlim_cur = lim.rlim_max;
421
0
        if (setrlimit (RLIMIT_NOFILE, &lim) == 0)
422
0
    fd = open (file->name, O_RDONLY | O_BINARY);
423
0
      }
424
425
0
    if (fd < 0)
426
0
#endif
427
0
      {
428
0
        _bfd_error_handler (_("plugin framework: out of file descriptors. Try using fewer objects/archives\n"));
429
0
        return 0;
430
0
      }
431
0
#endif
432
0
  }
433
0
    }
434
435
0
  if (iobfd == ibfd)
436
0
    {
437
0
      struct stat stat_buf;
438
439
0
      if (fstat (fd, &stat_buf))
440
0
  {
441
0
    close (fd);
442
0
    return 0;
443
0
  }
444
445
0
      file->offset = 0;
446
0
      file->filesize = stat_buf.st_size;
447
0
    }
448
0
  else
449
0
    {
450
      /* Cache the archive plugin file descriptor.  */
451
0
      iobfd->archive_plugin_fd = fd;
452
0
      iobfd->archive_plugin_fd_open_count++;
453
454
0
      file->offset = ibfd->origin;
455
0
      file->filesize = arelt_size (ibfd);
456
0
    }
457
458
0
  file->fd = fd;
459
0
  return 1;
460
0
}
461
462
/* Close the plugin file descriptor FD.  If ABFD isn't NULL, it is an
463
   archive member.   */
464
465
void
466
bfd_plugin_close_file_descriptor (bfd *abfd, int fd)
467
0
{
468
0
  if (abfd == NULL)
469
0
    close (fd);
470
0
  else
471
0
    {
472
0
      while (abfd->my_archive
473
0
       && abfd->my_archive->iovec == abfd->iovec
474
0
       && !bfd_is_thin_archive (abfd->my_archive))
475
0
  abfd = abfd->my_archive;
476
477
      /* Close the file descriptor if there is no archive plugin file
478
   descriptor.  */
479
0
      if (abfd->archive_plugin_fd == -1)
480
0
  {
481
0
    close (fd);
482
0
    return;
483
0
  }
484
485
0
      abfd->archive_plugin_fd_open_count--;
486
      /* Dup the archive plugin file descriptor for later use, which
487
   will be closed by _bfd_archive_close_and_cleanup.  */
488
0
      if (abfd->archive_plugin_fd_open_count == 0)
489
0
  {
490
0
    abfd->archive_plugin_fd = dup (fd);
491
0
    close (fd);
492
0
  }
493
0
    }
494
0
}
495
496
static int
497
try_claim (bfd *abfd)
498
0
{
499
0
  int claimed = 0;
500
0
  struct ld_plugin_input_file file;
501
502
0
  file.handle = abfd;
503
0
  if (bfd_plugin_open_input (abfd, &file))
504
0
    {
505
0
      bool claim_file_called = false;
506
0
      if (current_plugin->claim_file_v2)
507
0
  {
508
0
    current_plugin->claim_file_v2 (&file, &claimed, false);
509
0
    claim_file_called = true;
510
0
  }
511
0
      else if (current_plugin->claim_file)
512
0
  {
513
0
    current_plugin->claim_file (&file, &claimed);
514
0
    claim_file_called = true;
515
0
  }
516
0
      if (claim_file_called)
517
0
  bfd_plugin_close_file_descriptor ((abfd->my_archive != NULL
518
0
             ? abfd : NULL),
519
0
            file.fd);
520
0
    }
521
522
0
  return claimed;
523
0
}
524
525
static bool
526
try_load_plugin (const char *pname,
527
     struct plugin_list_entry *plugin_list_iter,
528
     bfd *abfd,
529
     bool build_list_p)
530
0
{
531
0
  void *plugin_handle;
532
0
  struct ld_plugin_tv tv[6];
533
0
  int i;
534
0
  ld_plugin_onload onload;
535
0
  enum ld_plugin_status status;
536
0
  bool result = false;
537
538
  /* NB: Each object is independent.  Reuse the previous plugin from
539
     the last run will lead to wrong result.  */
540
0
  if (current_plugin)
541
0
    memset (current_plugin, 0,
542
0
      offsetof (struct plugin_list_entry, next));
543
544
0
  if (plugin_list_iter)
545
0
    pname = plugin_list_iter->plugin_name;
546
547
0
  plugin_handle = dlopen (pname, RTLD_NOW);
548
0
  if (!plugin_handle)
549
0
    {
550
      /* If we are building a list of viable plugins, then
551
   we do not bother the user with the details of any
552
   plugins that cannot be loaded.  */
553
0
      if (! build_list_p)
554
0
  _bfd_error_handler ("Failed to load plugin '%s', reason: %s\n",
555
0
          pname, dlerror ());
556
0
      return false;
557
0
    }
558
559
0
  if (plugin_list_iter == NULL)
560
0
    {
561
0
      size_t length_plugin_name = strlen (pname) + 1;
562
0
      char *plugin_name = bfd_malloc (length_plugin_name);
563
564
0
      if (plugin_name == NULL)
565
0
  goto short_circuit;
566
0
      plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
567
0
      if (plugin_list_iter == NULL)
568
0
  {
569
0
    free (plugin_name);
570
0
    goto short_circuit;
571
0
  }
572
      /* Make a copy of PNAME since PNAME from load_plugin () will be
573
   freed.  */
574
0
      memcpy (plugin_name, pname, length_plugin_name);
575
0
      memset (plugin_list_iter, 0, sizeof (*plugin_list_iter));
576
0
      plugin_list_iter->plugin_name = plugin_name;
577
0
      plugin_list_iter->next = plugin_list;
578
0
      plugin_list = plugin_list_iter;
579
0
    }
580
581
0
  current_plugin = plugin_list_iter;
582
0
  if (build_list_p)
583
0
    goto short_circuit;
584
585
0
  onload = dlsym (plugin_handle, "onload");
586
0
  if (!onload)
587
0
    goto short_circuit;
588
589
0
  i = 0;
590
0
  tv[i].tv_tag = LDPT_MESSAGE;
591
0
  tv[i].tv_u.tv_message = message;
592
593
0
  ++i;
594
0
  tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
595
0
  tv[i].tv_u.tv_register_claim_file = register_claim_file;
596
597
0
  ++i;
598
0
  tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK_V2;
599
0
  tv[i].tv_u.tv_register_claim_file_v2 = register_claim_file_v2;
600
601
0
  ++i;
602
0
  tv[i].tv_tag = LDPT_ADD_SYMBOLS;
603
0
  tv[i].tv_u.tv_add_symbols = add_symbols;
604
605
0
  ++i;
606
0
  tv[i].tv_tag = LDPT_ADD_SYMBOLS_V2;
607
0
  tv[i].tv_u.tv_add_symbols = add_symbols_v2;
608
609
0
  ++i;
610
0
  tv[i].tv_tag = LDPT_NULL;
611
0
  tv[i].tv_u.tv_val = 0;
612
613
  /* LTO plugin will call handler hooks to set up plugin handlers.  */
614
0
  status = (*onload)(tv);
615
616
0
  if (status != LDPS_OK)
617
0
    goto short_circuit;
618
619
  /* Setting bfd_plugin_no here prevents recursive calls into
620
     bfd_check_format from within the plugin (unless the plugin opens
621
     another bfd.)  Attempting to load the plugin again while it is
622
     running is *not* a good idea.  */
623
0
  abfd->plugin_format = bfd_plugin_no;
624
625
0
  if (!current_plugin->claim_file)
626
0
    goto short_circuit;
627
628
0
  if (!try_claim (abfd))
629
0
    goto short_circuit;
630
631
0
  abfd->plugin_format = bfd_plugin_yes;
632
0
  result = true;
633
634
0
 short_circuit:
635
0
  dlclose (plugin_handle);
636
0
  return result;
637
0
}
638
639
/* There may be plugin libraries in lib/bfd-plugins.  */
640
static int has_plugin_list = -1;
641
642
static bfd_cleanup (*ld_plugin_object_p) (bfd *, bool);
643
644
static const char *plugin_name;
645
646
void
647
bfd_plugin_set_plugin (const char *p)
648
0
{
649
0
  plugin_name = p;
650
0
}
651
652
/* Return TRUE if ABFD can be claimed by linker LTO plugin.  */
653
654
bool
655
bfd_link_plugin_object_p (bfd *abfd)
656
0
{
657
0
  if (ld_plugin_object_p)
658
0
    return ld_plugin_object_p (abfd, false) != NULL;
659
0
  return false;
660
0
}
661
662
/* Register OBJECT_P to be used by bfd_plugin_object_p.  */
663
664
void
665
register_ld_plugin_object_p (bfd_cleanup (*object_p) (bfd *, bool))
666
0
{
667
0
  ld_plugin_object_p = object_p;
668
0
}
669
670
static void
671
build_plugin_list (bfd *abfd)
672
0
{
673
  /* The intent was to search ${libdir}/bfd-plugins for plugins, but
674
     unfortunately the original implementation wasn't precisely that
675
     when configuring binutils using --libdir.  Search in the proper
676
     path first, then the old one for backwards compatibility.  */
677
0
  static const char *path[]
678
0
    = { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" };
679
0
  struct stat last_st;
680
0
  unsigned int i;
681
682
0
  if (has_plugin_list >= 0)
683
0
    return;
684
685
  /* Try not to search the same dir twice, by looking at st_dev and
686
     st_ino for the dir.  If we are on a file system that always sets
687
     st_ino to zero or the actual st_ino is zero we might waste some
688
     time, but that doesn't matter too much.  */
689
0
  last_st.st_dev = 0;
690
0
  last_st.st_ino = 0;
691
0
  for (i = 0; i < sizeof (path) / sizeof (path[0]); i++)
692
0
    {
693
0
      char *plugin_dir = make_relative_prefix (plugin_program_name,
694
0
                 BINDIR,
695
0
                 path[i]);
696
0
      if (plugin_dir)
697
0
  {
698
0
    struct stat st;
699
0
    DIR *d;
700
701
0
    if (stat (plugin_dir, &st) == 0
702
0
        && S_ISDIR (st.st_mode)
703
0
        && !(last_st.st_dev == st.st_dev
704
0
       && last_st.st_ino == st.st_ino
705
0
       && st.st_ino != 0)
706
0
        && (d = opendir (plugin_dir)) != NULL)
707
0
      {
708
0
        struct dirent *ent;
709
710
0
        last_st.st_dev = st.st_dev;
711
0
        last_st.st_ino = st.st_ino;
712
0
        while ((ent = readdir (d)) != NULL)
713
0
    {
714
0
      char *full_name;
715
716
0
      full_name = concat (plugin_dir, "/", ent->d_name, NULL);
717
0
      if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
718
0
        (void) try_load_plugin (full_name, NULL, abfd, true);
719
0
      free (full_name);
720
0
    }
721
0
        closedir (d);
722
0
      }
723
0
    free (plugin_dir);
724
0
  }
725
0
    }
726
727
0
  has_plugin_list = plugin_list != NULL;
728
0
}
729
730
static bool
731
load_plugin (bfd *abfd)
732
151k
{
733
151k
  struct plugin_list_entry *plugin_list_iter;
734
735
151k
  if (plugin_name)
736
0
    return try_load_plugin (plugin_name, plugin_list, abfd, false);
737
738
151k
  if (plugin_program_name == NULL)
739
151k
    return false;
740
741
0
  build_plugin_list (abfd);
742
743
0
  for (plugin_list_iter = plugin_list;
744
0
       plugin_list_iter;
745
0
       plugin_list_iter = plugin_list_iter->next)
746
0
    if (try_load_plugin (NULL, plugin_list_iter, abfd, false))
747
0
      return true;
748
749
0
  return false;
750
0
}
751
752
753
static bfd_cleanup
754
bfd_plugin_object_p (bfd *abfd)
755
151k
{
756
  /* Since ld_plugin_object_p is called only for linker command-line input
757
     objects, pass true to ld_plugin_object_p so that the same input IR
758
     file won't be included twice if the LDPT_REGISTER_CLAIM_FILE_HOOK_V2
759
     isn't used.  */
760
151k
  if (ld_plugin_object_p)
761
0
    return ld_plugin_object_p (abfd, true);
762
763
151k
  if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd))
764
151k
    return NULL;
765
766
0
  return abfd->plugin_format == bfd_plugin_yes ? _bfd_no_cleanup : NULL;
767
151k
}
768
769
/* Copy any private info we understand from the input bfd
770
   to the output bfd.  */
771
772
static bool
773
bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
774
              bfd *obfd ATTRIBUTE_UNUSED)
775
0
{
776
0
  BFD_ASSERT (0);
777
0
  return true;
778
0
}
779
780
/* Copy any private info we understand from the input section
781
   to the output section.  */
782
783
static bool
784
bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
785
            asection *isection ATTRIBUTE_UNUSED,
786
            bfd *obfd ATTRIBUTE_UNUSED,
787
            asection *osection ATTRIBUTE_UNUSED,
788
            struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
789
0
{
790
0
  BFD_ASSERT (0);
791
0
  return true;
792
0
}
793
794
/* Copy any private info we understand from the input symbol
795
   to the output symbol.  */
796
797
static bool
798
bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
799
           asymbol **isymbol ATTRIBUTE_UNUSED,
800
           bfd *obfd ATTRIBUTE_UNUSED,
801
           asymbol **osymbol ATTRIBUTE_UNUSED)
802
0
{
803
0
  BFD_ASSERT (0);
804
0
  return true;
805
0
}
806
807
static bool
808
bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, void *ptr ATTRIBUTE_UNUSED)
809
0
{
810
0
  BFD_ASSERT (0);
811
0
  return true;
812
0
}
813
814
static char *
815
bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
816
0
{
817
0
  BFD_ASSERT (0);
818
0
  return NULL;
819
0
}
820
821
static int
822
bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
823
0
{
824
0
  BFD_ASSERT (0);
825
0
  return 0;
826
0
}
827
828
static int
829
bfd_plugin_core_file_pid (bfd *abfd ATTRIBUTE_UNUSED)
830
0
{
831
0
  BFD_ASSERT (0);
832
0
  return 0;
833
0
}
834
835
static long
836
bfd_plugin_get_symtab_upper_bound (bfd *abfd)
837
0
{
838
0
  struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
839
  /* Add symbols from object only section.  */
840
0
  long nsyms = plugin_data->nsyms + plugin_data->object_only_nsyms;
841
842
0
  BFD_ASSERT (nsyms >= 0);
843
844
0
  return ((nsyms + 1) * sizeof (asymbol *));
845
0
}
846
847
static flagword
848
convert_flags (const struct ld_plugin_symbol *sym)
849
0
{
850
0
 switch (sym->def)
851
0
   {
852
0
   case LDPK_DEF:
853
0
   case LDPK_COMMON:
854
0
   case LDPK_UNDEF:
855
0
     return BSF_GLOBAL;
856
857
0
   case LDPK_WEAKUNDEF:
858
0
   case LDPK_WEAKDEF:
859
0
     return BSF_GLOBAL | BSF_WEAK;
860
861
0
   default:
862
0
     BFD_ASSERT (0);
863
0
     return 0;
864
0
   }
865
0
}
866
867
static long
868
bfd_plugin_canonicalize_symtab (bfd *abfd,
869
        asymbol **alocation)
870
0
{
871
0
  struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
872
0
  long nsyms = plugin_data->nsyms;
873
0
  const struct ld_plugin_symbol *syms = plugin_data->syms;
874
0
  int i, j;
875
876
0
  for (i = 0; i < nsyms; i++)
877
0
    {
878
0
      asymbol *s = bfd_alloc (abfd, sizeof (asymbol));
879
880
0
      BFD_ASSERT (s);
881
0
      alocation[i] = s;
882
883
0
      s->the_bfd = abfd;
884
0
      s->name = syms[i].name;
885
0
      s->value = 0;
886
0
      s->flags = convert_flags (&syms[i]);
887
0
      s->udata.p = NULL;
888
0
      switch (syms[i].def)
889
0
  {
890
0
  case LDPK_COMMON:
891
0
    s->section = &bfd_plugin_fake_common_section;
892
0
    break;
893
0
  case LDPK_UNDEF:
894
0
  case LDPK_WEAKUNDEF:
895
0
    s->section = bfd_und_section_ptr;
896
0
    break;
897
0
  case LDPK_DEF:
898
0
  case LDPK_WEAKDEF:
899
0
    if (current_plugin->has_symbol_type)
900
0
      switch (syms[i].symbol_type)
901
0
        {
902
0
        default:
903
    /* FIXME: Should we issue an error here ?  */
904
0
        case LDST_UNKNOWN:
905
    /* What is the best fake section for LDST_UNKNOWN?  */
906
0
        case LDST_FUNCTION:
907
0
    s->section = &bfd_plugin_fake_text_section;
908
0
    break;
909
0
        case LDST_VARIABLE:
910
0
    if (syms[i].section_kind == LDSSK_BSS)
911
0
      s->section = &bfd_plugin_fake_bss_section;
912
0
    else
913
0
      s->section = &bfd_plugin_fake_data_section;
914
0
    break;
915
0
        }
916
0
    else
917
0
      s->section = &bfd_plugin_fake_text_section;
918
0
    break;
919
0
  default:
920
0
    BFD_ASSERT (0);
921
0
  }
922
0
    }
923
924
  /* Copy symbols from object only section.  */
925
0
  nsyms += plugin_data->object_only_nsyms;
926
0
  for (j = 0; j < plugin_data->object_only_nsyms; j++, i++)
927
0
    alocation[i] = plugin_data->object_only_syms[j];
928
929
0
  return nsyms;
930
0
}
931
932
static void
933
bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
934
       void *afile ATTRIBUTE_UNUSED,
935
       asymbol *symbol ATTRIBUTE_UNUSED,
936
       bfd_print_symbol_type how ATTRIBUTE_UNUSED)
937
0
{
938
0
  BFD_ASSERT (0);
939
0
}
940
941
static void
942
bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
943
          asymbol *symbol,
944
          symbol_info *ret)
945
0
{
946
0
  bfd_symbol_info (symbol, ret);
947
0
}
948
949
/* Make an empty symbol. */
950
951
static asymbol *
952
bfd_plugin_make_empty_symbol (bfd *abfd)
953
0
{
954
0
  asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
955
0
  if (new_symbol == NULL)
956
0
    return new_symbol;
957
0
  new_symbol->the_bfd = abfd;
958
0
  return new_symbol;
959
0
}
960
961
static int
962
bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
963
         struct bfd_link_info *info ATTRIBUTE_UNUSED)
964
0
{
965
0
  BFD_ASSERT (0);
966
0
  return 0;
967
0
}
968
969
const bfd_target plugin_vec =
970
{
971
  "plugin",     /* Name.  */
972
  bfd_target_unknown_flavour,
973
  BFD_ENDIAN_LITTLE,    /* Target byte order.  */
974
  BFD_ENDIAN_LITTLE,    /* Target headers byte order.  */
975
  (HAS_RELOC | EXEC_P |   /* Object flags.  */
976
   HAS_LINENO | HAS_DEBUG |
977
   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
978
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
979
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
980
  0,        /* symbol_leading_char.  */
981
  '/',        /* ar_pad_char.  */
982
  15,       /* ar_max_namelen.  */
983
  255,        /* match priority.  */
984
  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
985
  TARGET_MERGE_SECTIONS,
986
987
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
988
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
989
  bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
990
  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
991
  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
992
  bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
993
994
  {       /* bfd_check_format.  */
995
    _bfd_dummy_target,
996
    bfd_plugin_object_p,
997
    _bfd_dummy_target,
998
    _bfd_dummy_target
999
  },
1000
  {       /* bfd_set_format.  */
1001
    _bfd_bool_bfd_false_error,
1002
    _bfd_bool_bfd_false_error,
1003
    _bfd_bool_bfd_false_error,
1004
    _bfd_bool_bfd_false_error,
1005
  },
1006
  {       /* bfd_write_contents.  */
1007
    _bfd_bool_bfd_false_error,
1008
    _bfd_bool_bfd_false_error,
1009
    _bfd_bool_bfd_false_error,
1010
    _bfd_bool_bfd_false_error,
1011
  },
1012
1013
  BFD_JUMP_TABLE_GENERIC (bfd_plugin),
1014
  BFD_JUMP_TABLE_COPY (bfd_plugin),
1015
  BFD_JUMP_TABLE_CORE (bfd_plugin),
1016
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1017
  BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
1018
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1019
  BFD_JUMP_TABLE_WRITE (bfd_plugin),
1020
  BFD_JUMP_TABLE_LINK (bfd_plugin),
1021
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1022
1023
  NULL,
1024
1025
  NULL        /* backend_data.  */
1026
};
1027
#endif /* BFD_SUPPORTS_PLUGINS */