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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [lto-plugin/] [lto-plugin.c] - Blame information for rev 743

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 743 jeremybenn
/* LTO plugin for gold and/or GNU ld.
2
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3
   Contributed by Rafael Avila de Espindola (espindola@google.com).
4
 
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 3, or (at your option)
8
any later version.
9
 
10
This program is distributed in the hope that it will be useful, but
11
WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
General Public License for more details.
14
 
15
You should have received a copy of the GNU General Public License
16
along with this program; see the file COPYING3.  If not see
17
<http://www.gnu.org/licenses/>.  */
18
 
19
/* The plugin has only one external function: onload. Gold passes it an array of
20
   function that the plugin uses to communicate back to gold.
21
 
22
   With the functions provided by gold, the plugin can be notified when
23
   gold first analyzes a file and pass a symbol table back to gold. The plugin
24
   is also notified when all symbols have been read and it is time to generate
25
   machine code for the necessary symbols.
26
 
27
   More information at http://gcc.gnu.org/wiki/whopr/driver.
28
 
29
   This plugin should be passed the lto-wrapper options and will forward them.
30
   It also has 2 options of its own:
31
   -debug: Print the command line used to run lto-wrapper.
32
   -nop: Instead of running lto-wrapper, pass the original to the plugin. This
33
   only works if the input files are hybrid.  */
34
 
35
#ifdef HAVE_CONFIG_H
36
#include "config.h"
37
#endif
38
#if HAVE_STDINT_H
39
#include <stdint.h>
40
#endif
41
#include <assert.h>
42
#include <string.h>
43
#include <stdlib.h>
44
#include <stdio.h>
45
#include <inttypes.h>
46
#include <sys/stat.h>
47
#include <unistd.h>
48
#include <fcntl.h>
49
#include <sys/types.h>
50
#ifdef HAVE_SYS_WAIT_H
51
#include <sys/wait.h>
52
#endif
53
#ifndef WIFEXITED
54
#define WIFEXITED(S) (((S) & 0xff) == 0)
55
#endif
56
#ifndef WEXITSTATUS
57
#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
58
#endif
59
#include <libiberty.h>
60
#include <hashtab.h>
61
#include "../gcc/lto/common.h"
62
#include "simple-object.h"
63
#include "plugin-api.h"
64
 
65
/* We need to use I64 instead of ll width-specifier on native Windows.
66
   The reason for this is that older MS-runtimes don't support the ll.  */
67
#ifdef __MINGW32__
68
#define PRI_LL "I64"
69
#else
70
#define PRI_LL "ll"
71
#endif
72
 
73
/* Handle opening elf files on hosts, such as Windows, that may use
74
   text file handling that will break binary access.  */
75
#ifndef O_BINARY
76
# define O_BINARY 0
77
#endif
78
 
79
/* Segment name for LTO sections.  This is only used for Mach-O.
80
   FIXME: This needs to be kept in sync with darwin.c.  */
81
 
82
#define LTO_SEGMENT_NAME "__GNU_LTO"
83
 
84
/* LTO magic section name.  */
85
 
86
#define LTO_SECTION_PREFIX      ".gnu.lto_.symtab"
87
#define LTO_SECTION_PREFIX_LEN  (sizeof (LTO_SECTION_PREFIX) - 1)
88
 
89
/* The part of the symbol table the plugin has to keep track of. Note that we
90
   must keep SYMS until all_symbols_read is called to give the linker time to
91
   copy the symbol information.
92
   The id must be 64bit to minimze collisions. */
93
 
94
struct sym_aux
95
{
96
  uint32_t slot;
97
  unsigned long long id;
98
  unsigned next_conflict;
99
};
100
 
101
struct plugin_symtab
102
{
103
  int nsyms;
104
  struct sym_aux *aux;
105
  struct ld_plugin_symbol *syms;
106
  unsigned long long id;
107
};
108
 
109
/* Encapsulates object file data during symbol scan.  */
110
struct plugin_objfile
111
{
112
  int found;
113
  simple_object_read *objfile;
114
  struct plugin_symtab *out;
115
  const struct ld_plugin_input_file *file;
116
};
117
 
118
/* All that we have to remember about a file. */
119
 
120
struct plugin_file_info
121
{
122
  char *name;
123
  void *handle;
124
  struct plugin_symtab symtab;
125
  struct plugin_symtab conflicts;
126
};
127
 
128
/* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
129
   stdio file streams, we do simple label translation here.  */
130
 
131
enum symbol_style
132
{
133
  ss_none,      /* No underscore prefix. */
134
  ss_win32,     /* Underscore prefix any symbol not beginning with '@'.  */
135
  ss_uscore,    /* Underscore prefix all symbols.  */
136
};
137
 
138
static char *arguments_file_name;
139
static ld_plugin_register_claim_file register_claim_file;
140
static ld_plugin_register_all_symbols_read register_all_symbols_read;
141
static ld_plugin_get_symbols get_symbols, get_symbols_v2;
142
static ld_plugin_register_cleanup register_cleanup;
143
static ld_plugin_add_input_file add_input_file;
144
static ld_plugin_add_input_library add_input_library;
145
static ld_plugin_message message;
146
static ld_plugin_add_symbols add_symbols;
147
 
148
static struct plugin_file_info *claimed_files = NULL;
149
static unsigned int num_claimed_files = 0;
150
 
151
static char **output_files = NULL;
152
static unsigned int num_output_files = 0;
153
 
154
static char **lto_wrapper_argv;
155
static int lto_wrapper_num_args;
156
 
157
static char **pass_through_items = NULL;
158
static unsigned int num_pass_through_items;
159
 
160
static char debug;
161
static char nop;
162
static char *resolution_file = NULL;
163
 
164
/* The version of gold being used, or -1 if not gold.  The number is
165
   MAJOR * 100 + MINOR.  */
166
static int gold_version = -1;
167
 
168
/* Not used by default, but can be overridden at runtime
169
   by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
170
   (in fact, only first letter of style arg is checked.)  */
171
static enum symbol_style sym_style = ss_none;
172
 
173
static void
174
check_1 (int gate, enum ld_plugin_level level, const char *text)
175
{
176
  if (gate)
177
    return;
178
 
179
  if (message)
180
    message (level, text);
181
  else
182
    {
183
      /* If there is no nicer way to inform the user, fallback to stderr. */
184
      fprintf (stderr, "%s\n", text);
185
      if (level == LDPL_FATAL)
186
        abort ();
187
    }
188
}
189
 
190
/* This little wrapper allows check to be called with a non-integer
191
   first argument, such as a pointer that must be non-NULL.  We can't
192
   use c99 bool type to coerce it into range, so we explicitly test.  */
193
#define check(GATE, LEVEL, TEXT) check_1 (((GATE) != 0), (LEVEL), (TEXT))
194
 
195
/* Parse an entry of the IL symbol table. The data to be parsed is pointed
196
   by P and the result is written in ENTRY. The slot number is stored in SLOT.
197
   Returns the address of the next entry. */
198
 
199
static char *
200
parse_table_entry (char *p, struct ld_plugin_symbol *entry,
201
                   struct sym_aux *aux)
202
{
203
  unsigned char t;
204
  enum ld_plugin_symbol_kind translate_kind[] =
205
    {
206
      LDPK_DEF,
207
      LDPK_WEAKDEF,
208
      LDPK_UNDEF,
209
      LDPK_WEAKUNDEF,
210
      LDPK_COMMON
211
    };
212
 
213
  enum ld_plugin_symbol_visibility translate_visibility[] =
214
    {
215
      LDPV_DEFAULT,
216
      LDPV_PROTECTED,
217
      LDPV_INTERNAL,
218
      LDPV_HIDDEN
219
    };
220
 
221
  switch (sym_style)
222
    {
223
    case ss_win32:
224
      if (p[0] == '@')
225
        {
226
    /* cf. Duff's device.  */
227
    case ss_none:
228
          entry->name = xstrdup (p);
229
          break;
230
        }
231
    /* FALL-THROUGH.  */
232
    case ss_uscore:
233
      entry->name = concat ("_", p, NULL);
234
      break;
235
    default:
236
      check (0, LDPL_FATAL, "invalid symbol style requested");
237
      break;
238
    }
239
  while (*p)
240
    p++;
241
  p++;
242
 
243
  entry->version = NULL;
244
 
245
  entry->comdat_key = p;
246
  while (*p)
247
    p++;
248
  p++;
249
 
250
  if (strlen (entry->comdat_key) == 0)
251
    entry->comdat_key = NULL;
252
  else
253
    entry->comdat_key = xstrdup (entry->comdat_key);
254
 
255
  t = *p;
256
  check (t <= 4, LDPL_FATAL, "invalid symbol kind found");
257
  entry->def = translate_kind[t];
258
  p++;
259
 
260
  t = *p;
261
  check (t <= 3, LDPL_FATAL, "invalid symbol visibility found");
262
  entry->visibility = translate_visibility[t];
263
  p++;
264
 
265
  memcpy (&entry->size, p, sizeof (uint64_t));
266
  p += 8;
267
 
268
  memcpy (&aux->slot, p, sizeof (uint32_t));
269
  p += 4;
270
 
271
  entry->resolution = LDPR_UNKNOWN;
272
 
273
  aux->next_conflict = -1;
274
 
275
  return p;
276
}
277
 
278
/* Translate the IL symbol table located between DATA and END. Append the
279
   slots and symbols to OUT. */
280
 
281
static void
282
translate (char *data, char *end, struct plugin_symtab *out)
283
{
284
  struct sym_aux *aux;
285
  struct ld_plugin_symbol *syms = NULL;
286
  int n, len;
287
 
288
  /* This overestimates the output buffer sizes, but at least
289
     the algorithm is O(1) now. */
290
 
291
  len = (end - data)/8 + out->nsyms + 1;
292
  syms = xrealloc (out->syms, len * sizeof (struct ld_plugin_symbol));
293
  aux = xrealloc (out->aux, len * sizeof (struct sym_aux));
294
 
295
  for (n = out->nsyms; data < end; n++)
296
    {
297
      aux[n].id = out->id;
298
      data = parse_table_entry (data, &syms[n], &aux[n]);
299
    }
300
 
301
  assert(n < len);
302
 
303
  out->nsyms = n;
304
  out->syms = syms;
305
  out->aux = aux;
306
}
307
 
308
/* Free all memory that is no longer needed after writing the symbol
309
   resolution. */
310
 
311
static void
312
free_1 (void)
313
{
314
  unsigned int i;
315
  for (i = 0; i < num_claimed_files; i++)
316
    {
317
      struct plugin_file_info *info = &claimed_files[i];
318
      struct plugin_symtab *symtab = &info->symtab;
319
      unsigned int j;
320
      for (j = 0; j < symtab->nsyms; j++)
321
        {
322
          struct ld_plugin_symbol *s = &symtab->syms[j];
323
          free (s->name);
324
          free (s->comdat_key);
325
        }
326
      free (symtab->syms);
327
      symtab->syms = NULL;
328
    }
329
}
330
 
331
/* Free all remaining memory. */
332
 
333
static void
334
free_2 (void)
335
{
336
  unsigned int i;
337
  for (i = 0; i < num_claimed_files; i++)
338
    {
339
      struct plugin_file_info *info = &claimed_files[i];
340
      struct plugin_symtab *symtab = &info->symtab;
341
      free (symtab->aux);
342
      free (info->name);
343
    }
344
 
345
  for (i = 0; i < num_output_files; i++)
346
    free (output_files[i]);
347
  free (output_files);
348
 
349
  free (claimed_files);
350
  claimed_files = NULL;
351
  num_claimed_files = 0;
352
 
353
  free (arguments_file_name);
354
  arguments_file_name = NULL;
355
}
356
 
357
/* Dump SYMTAB to resolution file F. */
358
 
359
static void
360
dump_symtab (FILE *f, struct plugin_symtab *symtab)
361
{
362
  unsigned j;
363
 
364
  for (j = 0; j < symtab->nsyms; j++)
365
    {
366
      uint32_t slot = symtab->aux[j].slot;
367
      unsigned int resolution = symtab->syms[j].resolution;
368
 
369
      assert (resolution != LDPR_UNKNOWN);
370
 
371
      fprintf (f, "%u %" PRI_LL "x %s %s\n",
372
               (unsigned int) slot, symtab->aux[j].id,
373
               lto_resolution_str[resolution],
374
               symtab->syms[j].name);
375
    }
376
}
377
 
378
/* Finish the conflicts' resolution information after the linker resolved
379
   the original symbols */
380
 
381
static void
382
finish_conflict_resolution (struct plugin_symtab *symtab,
383
                           struct plugin_symtab *conflicts)
384
{
385
  int i, j;
386
 
387
  if (conflicts->nsyms == 0)
388
    return;
389
 
390
  for (i = 0; i < symtab->nsyms; i++)
391
    {
392
      int resolution = LDPR_UNKNOWN;
393
 
394
      if (symtab->aux[i].next_conflict == -1)
395
        continue;
396
 
397
      switch (symtab->syms[i].def)
398
        {
399
        case LDPK_DEF:
400
        case LDPK_COMMON: /* ??? */
401
          resolution = LDPR_RESOLVED_IR;
402
          break;
403
        case LDPK_WEAKDEF:
404
          resolution = LDPR_PREEMPTED_IR;
405
          break;
406
        case LDPK_UNDEF:
407
        case LDPK_WEAKUNDEF:
408
          resolution = symtab->syms[i].resolution;
409
          break;
410
        default:
411
          assert (0);
412
        }
413
 
414
      assert (resolution != LDPR_UNKNOWN);
415
 
416
      for (j = symtab->aux[i].next_conflict;
417
           j != -1;
418
           j = conflicts->aux[j].next_conflict)
419
        conflicts->syms[j].resolution = resolution;
420
    }
421
}
422
 
423
/* Free symbol table SYMTAB. */
424
 
425
static void
426
free_symtab (struct plugin_symtab *symtab)
427
{
428
  free (symtab->syms);
429
  symtab->syms = NULL;
430
  free (symtab->aux);
431
  symtab->aux = NULL;
432
}
433
 
434
/*  Writes the relocations to disk. */
435
 
436
static void
437
write_resolution (void)
438
{
439
  unsigned int i;
440
  FILE *f;
441
 
442
  check (resolution_file, LDPL_FATAL, "resolution file not specified");
443
  f = fopen (resolution_file, "w");
444
  check (f, LDPL_FATAL, "could not open file");
445
 
446
  fprintf (f, "%d\n", num_claimed_files);
447
 
448
  for (i = 0; i < num_claimed_files; i++)
449
    {
450
      struct plugin_file_info *info = &claimed_files[i];
451
      struct plugin_symtab *symtab = &info->symtab;
452
      struct ld_plugin_symbol *syms = symtab->syms;
453
 
454
      /* Version 2 of API supports IRONLY_EXP resolution that is
455
         accepted by GCC-4.7 and newer.  */
456
      if (get_symbols_v2)
457
        get_symbols_v2 (info->handle, symtab->nsyms, syms);
458
      else
459
        get_symbols (info->handle, symtab->nsyms, syms);
460
 
461
      finish_conflict_resolution (symtab, &info->conflicts);
462
 
463
      fprintf (f, "%s %d\n", info->name, symtab->nsyms + info->conflicts.nsyms);
464
      dump_symtab (f, symtab);
465
      if (info->conflicts.nsyms)
466
        {
467
          dump_symtab (f, &info->conflicts);
468
          free_symtab (&info->conflicts);
469
        }
470
    }
471
  fclose (f);
472
}
473
 
474
/* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
475
   stdout. */
476
 
477
static void
478
add_output_files (FILE *f)
479
{
480
  for (;;)
481
    {
482
      const unsigned piece = 32;
483
      char *buf, *s = xmalloc (piece);
484
      size_t len;
485
 
486
      buf = s;
487
cont:
488
      if (!fgets (buf, piece, f))
489
        {
490
          free (s);
491
          break;
492
        }
493
      len = strlen (s);
494
      if (s[len - 1] != '\n')
495
        {
496
          s = xrealloc (s, len + piece);
497
          buf = s + len;
498
          goto cont;
499
        }
500
      s[len - 1] = '\0';
501
 
502
      num_output_files++;
503
      output_files
504
        = xrealloc (output_files, num_output_files * sizeof (char *));
505
      output_files[num_output_files - 1] = s;
506
      add_input_file (output_files[num_output_files - 1]);
507
    }
508
}
509
 
510
/* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
511
   argument list. */
512
 
513
static void
514
exec_lto_wrapper (char *argv[])
515
{
516
  int t, i;
517
  int status;
518
  char *at_args;
519
  FILE *args;
520
  FILE *wrapper_output;
521
  char *new_argv[3];
522
  struct pex_obj *pex;
523
  const char *errmsg;
524
 
525
  /* Write argv to a file to avoid a command line that is too long. */
526
  arguments_file_name = make_temp_file ("");
527
  check (arguments_file_name, LDPL_FATAL,
528
         "Failed to generate a temorary file name");
529
 
530
  args = fopen (arguments_file_name, "w");
531
  check (args, LDPL_FATAL, "could not open arguments file");
532
 
533
  t = writeargv (&argv[1], args);
534
  check (t == 0, LDPL_FATAL, "could not write arguments");
535
  t = fclose (args);
536
  check (t == 0, LDPL_FATAL, "could not close arguments file");
537
 
538
  at_args = concat ("@", arguments_file_name, NULL);
539
  check (at_args, LDPL_FATAL, "could not allocate");
540
 
541
  for (i = 1; argv[i]; i++)
542
    {
543
      char *a = argv[i];
544
      if (a[0] == '-' && a[1] == 'v' && a[2] == '\0')
545
        {
546
          for (i = 0; argv[i]; i++)
547
            fprintf (stderr, "%s ", argv[i]);
548
          fprintf (stderr, "\n");
549
          break;
550
        }
551
    }
552
 
553
  new_argv[0] = argv[0];
554
  new_argv[1] = at_args;
555
  new_argv[2] = NULL;
556
 
557
  if (debug)
558
    {
559
      for (i = 0; new_argv[i]; i++)
560
        fprintf (stderr, "%s ", new_argv[i]);
561
      fprintf (stderr, "\n");
562
    }
563
 
564
 
565
  pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL);
566
  check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper");
567
 
568
  errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t);
569
  check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper");
570
  check (t == 0, LDPL_FATAL, "could not run lto-wrapper");
571
 
572
  wrapper_output = pex_read_output (pex, 0);
573
  check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output");
574
 
575
  add_output_files (wrapper_output);
576
 
577
  t = pex_get_status (pex, 1, &status);
578
  check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status");
579
  check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL,
580
         "lto-wrapper failed");
581
 
582
  pex_free (pex);
583
 
584
  free (at_args);
585
}
586
 
587
/* Pass the original files back to the linker. */
588
 
589
static void
590
use_original_files (void)
591
{
592
  unsigned i;
593
  for (i = 0; i < num_claimed_files; i++)
594
    {
595
      struct plugin_file_info *info = &claimed_files[i];
596
      add_input_file (info->name);
597
    }
598
}
599
 
600
 
601
/* Called by the linker once all symbols have been read. */
602
 
603
static enum ld_plugin_status
604
all_symbols_read_handler (void)
605
{
606
  unsigned i;
607
  unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 1;
608
  char **lto_argv;
609
  const char **lto_arg_ptr;
610
  if (num_claimed_files == 0)
611
    return LDPS_OK;
612
 
613
  if (nop)
614
    {
615
      use_original_files ();
616
      return LDPS_OK;
617
    }
618
 
619
  lto_argv = (char **) xcalloc (sizeof (char *), num_lto_args);
620
  lto_arg_ptr = (const char **) lto_argv;
621
  assert (lto_wrapper_argv);
622
 
623
  write_resolution ();
624
 
625
  free_1 ();
626
 
627
  for (i = 0; i < lto_wrapper_num_args; i++)
628
    *lto_arg_ptr++ = lto_wrapper_argv[i];
629
 
630
  for (i = 0; i < num_claimed_files; i++)
631
    {
632
      struct plugin_file_info *info = &claimed_files[i];
633
 
634
      *lto_arg_ptr++ = info->name;
635
    }
636
 
637
  *lto_arg_ptr++ = NULL;
638
  exec_lto_wrapper (lto_argv);
639
 
640
  free (lto_argv);
641
 
642
  /* --pass-through is not needed when using gold 1.11 or later.  */
643
  if (pass_through_items && gold_version < 111)
644
    {
645
      unsigned int i;
646
      for (i = 0; i < num_pass_through_items; i++)
647
        {
648
          if (strncmp (pass_through_items[i], "-l", 2) == 0)
649
            add_input_library (pass_through_items[i] + 2);
650
          else
651
            add_input_file (pass_through_items[i]);
652
          free (pass_through_items[i]);
653
          pass_through_items[i] = NULL;
654
        }
655
      free (pass_through_items);
656
      pass_through_items = NULL;
657
    }
658
 
659
  return LDPS_OK;
660
}
661
 
662
/* Remove temporary files at the end of the link. */
663
 
664
static enum ld_plugin_status
665
cleanup_handler (void)
666
{
667
  unsigned int i;
668
  int t;
669
 
670
  if (debug)
671
    return LDPS_OK;
672
 
673
  if (arguments_file_name)
674
    {
675
      t = unlink (arguments_file_name);
676
      check (t == 0, LDPL_FATAL, "could not unlink arguments file");
677
    }
678
 
679
  for (i = 0; i < num_output_files; i++)
680
    {
681
      t = unlink (output_files[i]);
682
      check (t == 0, LDPL_FATAL, "could not unlink output file");
683
    }
684
 
685
  free_2 ();
686
  return LDPS_OK;
687
}
688
 
689
#define SWAP(type, a, b) \
690
  do { type tmp_; tmp_ = (a); (a) = (b); (b) = tmp_; } while(0)
691
 
692
/* Compare two hash table entries */
693
 
694
static int eq_sym (const void *a, const void *b)
695
{
696
  const struct ld_plugin_symbol *as = (const struct ld_plugin_symbol *)a;
697
  const struct ld_plugin_symbol *bs = (const struct ld_plugin_symbol *)b;
698
 
699
  return !strcmp (as->name, bs->name);
700
}
701
 
702
/* Hash a symbol */
703
 
704
static hashval_t hash_sym (const void *a)
705
{
706
  const struct ld_plugin_symbol *as = (const struct ld_plugin_symbol *)a;
707
 
708
  return htab_hash_string (as->name);
709
}
710
 
711
/* Determine how strong a symbol is */
712
 
713
static int symbol_strength (struct ld_plugin_symbol *s)
714
{
715
  switch (s->def)
716
    {
717
    case LDPK_UNDEF:
718
    case LDPK_WEAKUNDEF:
719
      return 0;
720
    case LDPK_WEAKDEF:
721
      return 1;
722
    default:
723
      return 2;
724
    }
725
}
726
 
727
/* In the ld -r case we can get dups in the LTO symbol tables, where
728
   the same symbol can have different resolutions (e.g. undefined and defined).
729
 
730
   We have to keep that in the LTO symbol tables, but the dups confuse
731
   gold and then finally gcc by supplying incorrect resolutions.
732
 
733
   Problem is that the main gold symbol table doesn't know about subids
734
   and does not distingush the same symbols in different states.
735
 
736
   So we drop duplicates from the linker visible symbol table
737
   and keep them in a private table. Then later do own symbol
738
   resolution for the duplicated based on the results for the
739
   originals.
740
 
741
   Then when writing out the resolution file readd the dropped symbols.
742
 
743
   XXX how to handle common? */
744
 
745
static void
746
resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
747
{
748
  htab_t symtab = htab_create (t->nsyms, hash_sym, eq_sym, NULL);
749
  int i;
750
  int out;
751
  int outlen;
752
 
753
  outlen = t->nsyms;
754
  conflicts->syms = xmalloc (sizeof (struct ld_plugin_symbol) * outlen);
755
  conflicts->aux = xmalloc (sizeof (struct sym_aux) * outlen);
756
 
757
  /* Move all duplicate symbols into the auxillary conflicts table. */
758
  out = 0;
759
  for (i = 0; i < t->nsyms; i++)
760
    {
761
      struct ld_plugin_symbol *s = &t->syms[i];
762
      struct sym_aux *aux = &t->aux[i];
763
      void **slot;
764
 
765
      slot = htab_find_slot (symtab, s, INSERT);
766
      if (*slot != NULL)
767
        {
768
          int cnf;
769
          struct ld_plugin_symbol *orig = (struct ld_plugin_symbol *)*slot;
770
          struct sym_aux *orig_aux = &t->aux[orig - t->syms];
771
 
772
          /* Always let the linker resolve the strongest symbol */
773
          if (symbol_strength (orig) < symbol_strength (s))
774
            {
775
              SWAP (struct ld_plugin_symbol, *orig, *s);
776
              SWAP (uint32_t, orig_aux->slot, aux->slot);
777
              SWAP (unsigned long long, orig_aux->id, aux->id);
778
              /* Don't swap conflict chain pointer */
779
            }
780
 
781
          /* Move current symbol into the conflicts table */
782
          cnf = conflicts->nsyms++;
783
          conflicts->syms[cnf] = *s;
784
          conflicts->aux[cnf] = *aux;
785
          aux = &conflicts->aux[cnf];
786
 
787
          /* Update conflicts chain of the original symbol */
788
          aux->next_conflict = orig_aux->next_conflict;
789
          orig_aux->next_conflict = cnf;
790
 
791
          continue;
792
        }
793
 
794
      /* Remove previous duplicates in the main table */
795
      if (out < i)
796
        {
797
          t->syms[out] = *s;
798
          t->aux[out] = *aux;
799
        }
800
 
801
      /* Put original into the hash table */
802
      *slot = &t->syms[out];
803
      out++;
804
    }
805
 
806
  assert (conflicts->nsyms <= outlen);
807
  assert (conflicts->nsyms + out == t->nsyms);
808
 
809
  t->nsyms = out;
810
  htab_delete (symtab);
811
}
812
 
813
/* Process one section of an object file.  */
814
 
815
static int
816
process_symtab (void *data, const char *name, off_t offset, off_t length)
817
{
818
  struct plugin_objfile *obj = (struct plugin_objfile *)data;
819
  char *s;
820
  char *secdata;
821
 
822
  if (strncmp (name, LTO_SECTION_PREFIX, LTO_SECTION_PREFIX_LEN) != 0)
823
    return 1;
824
 
825
  s = strrchr (name, '.');
826
  if (s)
827
    sscanf (s, ".%" PRI_LL "x", &obj->out->id);
828
  secdata = xmalloc (length);
829
  offset += obj->file->offset;
830
  if (offset != lseek (obj->file->fd, offset, SEEK_SET)
831
        || length != read (obj->file->fd, secdata, length))
832
    {
833
      if (message)
834
        message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
835
      /* Force claim_file_handler to abandon this file.  */
836
      obj->found = 0;
837
      free (secdata);
838
      return 0;
839
    }
840
 
841
  translate (secdata, secdata + length, obj->out);
842
  obj->found++;
843
  free (secdata);
844
  return 1;
845
}
846
 
847
/* Callback used by gold to check if the plugin will claim FILE. Writes
848
   the result in CLAIMED. */
849
 
850
static enum ld_plugin_status
851
claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
852
{
853
  enum ld_plugin_status status;
854
  struct plugin_objfile obj;
855
  struct plugin_file_info lto_file;
856
  int err;
857
  const char *errmsg;
858
 
859
  memset (&lto_file, 0, sizeof (struct plugin_file_info));
860
 
861
  if (file->offset != 0)
862
    {
863
      char *objname;
864
      /* We pass the offset of the actual file, not the archive header.
865
         Can't use PRIx64, because that's C99, so we have to print the
866
         64-bit hex int as two 32-bit ones. */
867
      int lo, hi, t;
868
      lo = file->offset & 0xffffffff;
869
      hi = ((int64_t)file->offset >> 32) & 0xffffffff;
870
      t = hi ? asprintf (&objname, "%s@0x%x%08x", file->name, lo, hi)
871
             : asprintf (&objname, "%s@0x%x", file->name, lo);
872
      check (t >= 0, LDPL_FATAL, "asprintf failed");
873
      lto_file.name = objname;
874
    }
875
  else
876
    {
877
      lto_file.name = xstrdup (file->name);
878
    }
879
  lto_file.handle = file->handle;
880
 
881
  *claimed = 0;
882
  obj.file = file;
883
  obj.found = 0;
884
  obj.out = &lto_file.symtab;
885
  errmsg = NULL;
886
  obj.objfile = simple_object_start_read (file->fd, file->offset, LTO_SEGMENT_NAME,
887
                        &errmsg, &err);
888
  /* No file, but also no error code means unrecognized format; just skip it.  */
889
  if (!obj.objfile && !err)
890
    goto err;
891
 
892
  if (obj.objfile)
893
    errmsg = simple_object_find_sections (obj.objfile, process_symtab, &obj, &err);
894
 
895
  if (!obj.objfile || errmsg)
896
    {
897
      if (err && message)
898
        message (LDPL_FATAL, "%s: %s: %s", file->name, errmsg,
899
                xstrerror (err));
900
      else if (message)
901
        message (LDPL_FATAL, "%s: %s", file->name, errmsg);
902
      goto err;
903
    }
904
 
905
  if (obj.found == 0)
906
    goto err;
907
 
908
  if (obj.found > 1)
909
    resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
910
 
911
  status = add_symbols (file->handle, lto_file.symtab.nsyms,
912
                        lto_file.symtab.syms);
913
  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
914
 
915
  *claimed = 1;
916
  num_claimed_files++;
917
  claimed_files =
918
    xrealloc (claimed_files,
919
              num_claimed_files * sizeof (struct plugin_file_info));
920
  claimed_files[num_claimed_files - 1] = lto_file;
921
 
922
  goto cleanup;
923
 
924
 err:
925
  free (lto_file.name);
926
 
927
 cleanup:
928
  if (obj.objfile)
929
    simple_object_release_read (obj.objfile);
930
 
931
  return LDPS_OK;
932
}
933
 
934
/* Parse the plugin options. */
935
 
936
static void
937
process_option (const char *option)
938
{
939
  if (strcmp (option, "-debug") == 0)
940
    debug = 1;
941
  else if (strcmp (option, "-nop") == 0)
942
    nop = 1;
943
  else if (!strncmp (option, "-pass-through=", strlen("-pass-through=")))
944
    {
945
      num_pass_through_items++;
946
      pass_through_items = xrealloc (pass_through_items,
947
                                     num_pass_through_items * sizeof (char *));
948
      pass_through_items[num_pass_through_items - 1] =
949
          xstrdup (option + strlen ("-pass-through="));
950
    }
951
  else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
952
    {
953
      switch (option[sizeof ("-sym-style=") - 1])
954
        {
955
        case 'w':
956
          sym_style = ss_win32;
957
          break;
958
        case 'u':
959
          sym_style = ss_uscore;
960
          break;
961
        default:
962
          sym_style = ss_none;
963
          break;
964
        }
965
    }
966
  else
967
    {
968
      int size;
969
      char *opt = xstrdup (option);
970
      lto_wrapper_num_args += 1;
971
      size = lto_wrapper_num_args * sizeof (char *);
972
      lto_wrapper_argv = (char **) xrealloc (lto_wrapper_argv, size);
973
      lto_wrapper_argv[lto_wrapper_num_args - 1] = opt;
974
      if (strncmp (option, "-fresolution=", sizeof ("-fresolution=") - 1) == 0)
975
        resolution_file = opt + sizeof ("-fresolution=") - 1;
976
    }
977
}
978
 
979
/* Called by gold after loading the plugin. TV is the transfer vector. */
980
 
981
enum ld_plugin_status
982
onload (struct ld_plugin_tv *tv)
983
{
984
  struct ld_plugin_tv *p;
985
  enum ld_plugin_status status;
986
 
987
  p = tv;
988
  while (p->tv_tag)
989
    {
990
      switch (p->tv_tag)
991
        {
992
        case LDPT_MESSAGE:
993
          message = p->tv_u.tv_message;
994
          break;
995
        case LDPT_REGISTER_CLAIM_FILE_HOOK:
996
          register_claim_file = p->tv_u.tv_register_claim_file;
997
          break;
998
        case LDPT_ADD_SYMBOLS:
999
          add_symbols = p->tv_u.tv_add_symbols;
1000
          break;
1001
        case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
1002
          register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
1003
          break;
1004
        case LDPT_GET_SYMBOLS_V2:
1005
          get_symbols_v2 = p->tv_u.tv_get_symbols;
1006
          break;
1007
        case LDPT_GET_SYMBOLS:
1008
          get_symbols = p->tv_u.tv_get_symbols;
1009
          break;
1010
        case LDPT_REGISTER_CLEANUP_HOOK:
1011
          register_cleanup = p->tv_u.tv_register_cleanup;
1012
          break;
1013
        case LDPT_ADD_INPUT_FILE:
1014
          add_input_file = p->tv_u.tv_add_input_file;
1015
          break;
1016
        case LDPT_ADD_INPUT_LIBRARY:
1017
          add_input_library = p->tv_u.tv_add_input_library;
1018
          break;
1019
        case LDPT_OPTION:
1020
          process_option (p->tv_u.tv_string);
1021
          break;
1022
        case LDPT_GOLD_VERSION:
1023
          gold_version = p->tv_u.tv_val;
1024
          break;
1025
        default:
1026
          break;
1027
        }
1028
      p++;
1029
    }
1030
 
1031
  check (register_claim_file, LDPL_FATAL, "register_claim_file not found");
1032
  check (add_symbols, LDPL_FATAL, "add_symbols not found");
1033
  status = register_claim_file (claim_file_handler);
1034
  check (status == LDPS_OK, LDPL_FATAL,
1035
         "could not register the claim_file callback");
1036
 
1037
  if (register_cleanup)
1038
    {
1039
      status = register_cleanup (cleanup_handler);
1040
      check (status == LDPS_OK, LDPL_FATAL,
1041
             "could not register the cleanup callback");
1042
    }
1043
 
1044
  if (register_all_symbols_read)
1045
    {
1046
      check (get_symbols, LDPL_FATAL, "get_symbols not found");
1047
      status = register_all_symbols_read (all_symbols_read_handler);
1048
      check (status == LDPS_OK, LDPL_FATAL,
1049
             "could not register the all_symbols_read callback");
1050
    }
1051
 
1052
  return LDPS_OK;
1053
}

powered by: WebSVN 2.1.0

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