lto-plugin.c revision 1.1.1.1
1/* LTO plugin for gold.
2   Copyright (C) 2009 Free Software Foundation, Inc.
3   Contributed by Rafael Avila de Espindola (espindola@google.com).
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 3, or (at your option)
8any later version.
9
10This program is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along 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#include <assert.h>
36#include <string.h>
37#include <stdlib.h>
38#include <stdio.h>
39#include <inttypes.h>
40#include <sys/stat.h>
41#include <unistd.h>
42#include <fcntl.h>
43#include <sys/types.h>
44#include <sys/wait.h>
45#include <stdbool.h>
46#include <libiberty.h>
47
48/* The presence of gelf.h is checked by the toplevel configure script.  */
49#include <gelf.h>
50
51#include "plugin-api.h"
52#include "../gcc/lto/common.h"
53
54/* The part of the symbol table the plugin has to keep track of. Note that we
55   must keep SYMS until all_symbols_read is called to give the linker time to
56   copy the symbol information. */
57
58struct plugin_symtab
59{
60  int nsyms;
61  uint32_t *slots;
62  struct ld_plugin_symbol *syms;
63};
64
65/* All that we have to remember about a file. */
66
67struct plugin_file_info
68{
69  char *name;
70  void *handle;
71  struct plugin_symtab symtab;
72};
73
74
75static char *arguments_file_name;
76static ld_plugin_register_claim_file register_claim_file;
77static ld_plugin_add_symbols add_symbols;
78static ld_plugin_register_all_symbols_read register_all_symbols_read;
79static ld_plugin_get_symbols get_symbols;
80static ld_plugin_register_cleanup register_cleanup;
81static ld_plugin_add_input_file add_input_file;
82static ld_plugin_add_input_library add_input_library;
83static ld_plugin_message message;
84
85static struct plugin_file_info *claimed_files = NULL;
86static unsigned int num_claimed_files = 0;
87
88static char **output_files = NULL;
89static unsigned int num_output_files = 0;
90
91static char **lto_wrapper_argv;
92static int lto_wrapper_num_args;
93
94static char **pass_through_items = NULL;
95static unsigned int num_pass_through_items;
96
97static bool debug;
98static bool nop;
99static char *resolution_file = NULL;
100
101static void
102check (bool gate, enum ld_plugin_level level, const char *text)
103{
104  if (gate)
105    return;
106
107  if (message)
108    message (level, text);
109  else
110    {
111      /* If there is no nicer way to inform the user, fallback to stderr. */
112      fprintf (stderr, "%s\n", text);
113      if (level == LDPL_FATAL)
114	abort ();
115    }
116}
117
118/* Parse an entry of the IL symbol table. The data to be parsed is pointed
119   by P and the result is written in ENTRY. The slot number is stored in SLOT.
120   Returns the address of the next entry. */
121
122static char *
123parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
124{
125  unsigned char t;
126  enum ld_plugin_symbol_kind translate_kind[] =
127    {
128      LDPK_DEF,
129      LDPK_WEAKDEF,
130      LDPK_UNDEF,
131      LDPK_WEAKUNDEF,
132      LDPK_COMMON
133    };
134
135  enum ld_plugin_symbol_visibility translate_visibility[] =
136    {
137      LDPV_DEFAULT,
138      LDPV_PROTECTED,
139      LDPV_INTERNAL,
140      LDPV_HIDDEN
141    };
142
143  entry->name = strdup (p);
144  while (*p)
145    p++;
146  p++;
147
148  entry->version = NULL;
149
150  entry->comdat_key = p;
151  while (*p)
152    p++;
153  p++;
154
155  if (strlen (entry->comdat_key) == 0)
156    entry->comdat_key = NULL;
157  else
158    entry->comdat_key = strdup (entry->comdat_key);
159
160  t = *p;
161  check (t <= 4, LDPL_FATAL, "invalid symbol kind found");
162  entry->def = translate_kind[t];
163  p++;
164
165  t = *p;
166  check (t <= 3, LDPL_FATAL, "invalid symbol visibility found");
167  entry->visibility = translate_visibility[t];
168  p++;
169
170  entry->size = *(uint64_t *) p;
171  p += 8;
172
173  *slot = *(uint32_t *) p;
174  p += 4;
175
176  entry->resolution = LDPR_UNKNOWN;
177
178  return p;
179}
180
181/* Return the section in ELF that is named NAME. */
182
183static Elf_Scn *
184get_section (Elf *elf, const char *name)
185{
186  Elf_Scn *section = 0;
187  GElf_Ehdr header;
188  GElf_Ehdr *t = gelf_getehdr (elf, &header);
189  if (t == NULL)
190    return NULL;
191  assert (t == &header);
192
193  while ((section = elf_nextscn(elf, section)) != 0)
194    {
195      GElf_Shdr shdr;
196      GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
197      const char *t;
198      assert (tshdr == &shdr);
199      t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name);
200      assert (t != NULL);
201      if (strcmp (t, name) == 0)
202	return section;
203    }
204  return NULL;
205}
206
207/* Returns the IL symbol table of file ELF. */
208
209static Elf_Data *
210get_symtab (Elf *elf)
211{
212  Elf_Data *data = 0;
213  Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
214  if (!section)
215    return NULL;
216
217  data = elf_getdata (section, data);
218  assert (data);
219  return data;
220}
221
222/* Translate the IL symbol table SYMTAB. Write the slots and symbols in OUT. */
223
224static void
225translate (Elf_Data *symtab, struct plugin_symtab *out)
226{
227  uint32_t *slots = NULL;
228  char *data = symtab->d_buf;
229  char *end = data + symtab->d_size;
230  struct ld_plugin_symbol *syms = NULL;
231  int n = 0;
232
233  while (data < end)
234    {
235      n++;
236      syms = realloc (syms, n * sizeof (struct ld_plugin_symbol));
237      check (syms, LDPL_FATAL, "could not allocate memory");
238      slots = realloc (slots, n * sizeof (uint32_t));
239      check (slots, LDPL_FATAL, "could not allocate memory");
240      data = parse_table_entry (data, &syms[n - 1], &slots[n - 1]);
241    }
242
243  out->nsyms = n;
244  out->syms = syms;
245  out->slots = slots;
246}
247
248/* Free all memory that is no longer needed after writing the symbol
249   resolution. */
250
251static void
252free_1 (void)
253{
254  unsigned int i;
255  for (i = 0; i < num_claimed_files; i++)
256    {
257      struct plugin_file_info *info = &claimed_files[i];
258      struct plugin_symtab *symtab = &info->symtab;
259      unsigned int j;
260      for (j = 0; j < symtab->nsyms; j++)
261	{
262	  struct ld_plugin_symbol *s = &symtab->syms[j];
263	  free (s->name);
264	  if (s->comdat_key)
265	    free (s->comdat_key);
266	}
267      free (symtab->syms);
268      symtab->syms = NULL;
269    }
270}
271
272/* Free all remaining memory. */
273
274static void
275free_2 (void)
276{
277  unsigned int i;
278  for (i = 0; i < num_claimed_files; i++)
279    {
280      struct plugin_file_info *info = &claimed_files[i];
281      struct plugin_symtab *symtab = &info->symtab;
282      free (symtab->slots);
283      free (info->name);
284    }
285
286  for (i = 0; i < num_output_files; i++)
287    free (output_files[i]);
288  free (output_files);
289
290  free (claimed_files);
291  claimed_files = NULL;
292  num_claimed_files = 0;
293
294  if (arguments_file_name)
295    free (arguments_file_name);
296  arguments_file_name = NULL;
297
298  if (resolution_file)
299    {
300      free (resolution_file);
301      resolution_file = NULL;
302    }
303}
304
305/*  Writes the relocations to disk. */
306
307static void
308write_resolution (void)
309{
310  unsigned int i;
311  FILE *f;
312
313  f = fopen (resolution_file, "w");
314  check (f, LDPL_FATAL, "could not open file");
315
316  fprintf (f, "%d\n", num_claimed_files);
317
318  for (i = 0; i < num_claimed_files; i++)
319    {
320      struct plugin_file_info *info = &claimed_files[i];
321      struct plugin_symtab *symtab = &info->symtab;
322      struct ld_plugin_symbol *syms = symtab->syms;
323      unsigned j;
324
325      get_symbols (info->handle, symtab->nsyms, syms);
326
327      fprintf (f, "%s %d\n", info->name, info->symtab.nsyms);
328
329      for (j = 0; j < info->symtab.nsyms; j++)
330	{
331	  uint32_t slot = symtab->slots[j];
332	  unsigned int resolution = syms[j].resolution;
333	  fprintf (f, "%d %s %s\n", slot, lto_resolution_str[resolution], syms[j].name);
334	}
335    }
336  fclose (f);
337}
338
339/* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
340   stdout. */
341
342static void
343add_output_files (FILE *f)
344{
345  char fname[1000]; /* FIXME: Remove this restriction. */
346
347  for (;;)
348    {
349      size_t len;
350      char *s = fgets (fname, sizeof (fname), f);
351      if (!s)
352	break;
353
354      len = strlen (s);
355      check (s[len - 1] == '\n', LDPL_FATAL, "file name too long");
356      s[len - 1] = '\0';
357
358      num_output_files++;
359      output_files = realloc (output_files, num_output_files * sizeof (char *));
360      output_files[num_output_files - 1] = strdup (s);
361      add_input_file (output_files[num_output_files - 1]);
362    }
363}
364
365/* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
366   argument list. */
367
368static void
369exec_lto_wrapper (char *argv[])
370{
371  int t, i;
372  int status;
373  char *at_args;
374  FILE *args;
375  FILE *wrapper_output;
376  char *new_argv[3];
377  struct pex_obj *pex;
378  const char *errmsg;
379
380  /* Write argv to a file to avoid a command line that is too long. */
381  arguments_file_name = make_temp_file ("");
382  check (arguments_file_name, LDPL_FATAL,
383         "Failed to generate a temorary file name");
384
385  args = fopen (arguments_file_name, "w");
386  check (args, LDPL_FATAL, "could not open arguments file");
387
388  t = writeargv (&argv[1], args);
389  check (t == 0, LDPL_FATAL, "could not write arguments");
390  t = fclose (args);
391  check (t == 0, LDPL_FATAL, "could not close arguments file");
392
393  at_args = concat ("@", arguments_file_name, NULL);
394  check (at_args, LDPL_FATAL, "could not allocate");
395
396  for (i = 1; argv[i]; i++)
397    {
398      char *a = argv[i];
399      if (a[0] == '-' && a[1] == 'v' && a[2] == '\0')
400	{
401	  for (i = 0; argv[i]; i++)
402	    fprintf (stderr, "%s ", argv[i]);
403	  fprintf (stderr, "\n");
404	  break;
405	}
406    }
407
408  new_argv[0] = argv[0];
409  new_argv[1] = at_args;
410  new_argv[2] = NULL;
411
412  if (debug)
413    {
414      for (i = 0; new_argv[i]; i++)
415	fprintf (stderr, "%s ", new_argv[i]);
416      fprintf (stderr, "\n");
417    }
418
419
420  pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL);
421  check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper");
422
423  errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t);
424  check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper");
425  check (t == 0, LDPL_FATAL, "could not run lto-wrapper");
426
427  wrapper_output = pex_read_output (pex, 0);
428  check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output");
429
430  add_output_files (wrapper_output);
431
432  t = pex_get_status (pex, 1, &status);
433  check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status");
434  check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL,
435         "lto-wrapper failed");
436
437  pex_free (pex);
438
439  free (at_args);
440}
441
442/* Pass the original files back to the linker. */
443
444static void
445use_original_files (void)
446{
447  unsigned i;
448  for (i = 0; i < num_claimed_files; i++)
449    {
450      struct plugin_file_info *info = &claimed_files[i];
451      add_input_file (info->name);
452    }
453}
454
455
456/* Called by the linker once all symbols have been read. */
457
458static enum ld_plugin_status
459all_symbols_read_handler (void)
460{
461  unsigned i;
462  unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 2 + 1;
463  char **lto_argv;
464  const char **lto_arg_ptr;
465  if (num_claimed_files == 0)
466    return LDPS_OK;
467
468  if (nop)
469    {
470      use_original_files ();
471      return LDPS_OK;
472    }
473
474  lto_argv = (char **) calloc (sizeof (char *), num_lto_args);
475  lto_arg_ptr = (const char **) lto_argv;
476  assert (lto_wrapper_argv);
477
478  resolution_file = make_temp_file ("");
479
480  write_resolution ();
481
482  free_1 ();
483
484  for (i = 0; i < lto_wrapper_num_args; i++)
485    *lto_arg_ptr++ = lto_wrapper_argv[i];
486
487  *lto_arg_ptr++ = "-fresolution";
488  *lto_arg_ptr++ = resolution_file;
489
490  for (i = 0; i < num_claimed_files; i++)
491    {
492      struct plugin_file_info *info = &claimed_files[i];
493
494      *lto_arg_ptr++ = info->name;
495    }
496
497  *lto_arg_ptr++ = NULL;
498  exec_lto_wrapper (lto_argv);
499
500  free (lto_argv);
501
502  if (pass_through_items)
503    {
504      unsigned int i;
505      for (i = 0; i < num_pass_through_items; i++)
506        {
507          if (strncmp (pass_through_items[i], "-l", 2) == 0)
508            add_input_library (pass_through_items[i] + 2);
509          else
510            add_input_file (pass_through_items[i]);
511          free (pass_through_items[i]);
512          pass_through_items[i] = NULL;
513        }
514      free (pass_through_items);
515      pass_through_items = NULL;
516    }
517
518  return LDPS_OK;
519}
520
521/* Remove temporary files at the end of the link. */
522
523static enum ld_plugin_status
524cleanup_handler (void)
525{
526  unsigned int i;
527  int t;
528
529  if (debug)
530    return LDPS_OK;
531
532  if (arguments_file_name)
533    {
534      t = unlink (arguments_file_name);
535      check (t == 0, LDPL_FATAL, "could not unlink arguments file");
536    }
537
538  if (resolution_file)
539    {
540      t = unlink (resolution_file);
541      check (t == 0, LDPL_FATAL, "could not unlink resolution file");
542    }
543
544  for (i = 0; i < num_output_files; i++)
545    {
546      t = unlink (output_files[i]);
547      check (t == 0, LDPL_FATAL, "could not unlink output file");
548    }
549
550  free_2 ();
551  return LDPS_OK;
552}
553
554/* Callback used by gold to check if the plugin will claim FILE. Writes
555   the result in CLAIMED. */
556
557static enum ld_plugin_status
558claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
559{
560  enum ld_plugin_status status;
561  Elf *elf;
562  struct plugin_file_info lto_file;
563  Elf_Data *symtab;
564
565  if (file->offset != 0)
566    {
567      char *objname;
568      Elf *archive;
569      off_t offset;
570      /* We pass the offset of the actual file, not the archive header. */
571      int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
572                        (int64_t) file->offset);
573      check (t >= 0, LDPL_FATAL, "asprintf failed");
574      lto_file.name = objname;
575
576      archive = elf_begin (file->fd, ELF_C_READ, NULL);
577      check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL,
578             "Not an archive and offset not 0");
579
580      /* elf_rand expects the offset to point to the ar header, not the
581         object itself. Subtract the size of the ar header (60 bytes).
582         We don't uses sizeof (struct ar_hd) to avoid including ar.h */
583
584      offset = file->offset - 60;
585      check (offset == elf_rand (archive, offset), LDPL_FATAL,
586             "could not seek in archive");
587      elf = elf_begin (file->fd, ELF_C_READ, archive);
588      check (elf != NULL, LDPL_FATAL, "could not find archive member");
589      elf_end (archive);
590    }
591  else
592    {
593      lto_file.name = strdup (file->name);
594      elf = elf_begin (file->fd, ELF_C_READ, NULL);
595    }
596  lto_file.handle = file->handle;
597
598  *claimed = 0;
599
600  if (!elf)
601    goto err;
602
603  symtab = get_symtab (elf);
604  if (!symtab)
605    goto err;
606
607  translate (symtab, &lto_file.symtab);
608
609  status = add_symbols (file->handle, lto_file.symtab.nsyms,
610			lto_file.symtab.syms);
611  check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
612
613  *claimed = 1;
614  num_claimed_files++;
615  claimed_files =
616    realloc (claimed_files,
617	     num_claimed_files * sizeof (struct plugin_file_info));
618  claimed_files[num_claimed_files - 1] = lto_file;
619
620  goto cleanup;
621
622 err:
623  free (lto_file.name);
624
625 cleanup:
626  if (elf)
627    elf_end (elf);
628
629  return LDPS_OK;
630}
631
632/* Parse the plugin options. */
633
634static void
635process_option (const char *option)
636{
637  if (strcmp (option, "-debug") == 0)
638    debug = 1;
639  else if (strcmp (option, "-nop") == 0)
640    nop = 1;
641  else if (!strncmp (option, "-pass-through=", strlen("-pass-through=")))
642    {
643      num_pass_through_items++;
644      pass_through_items = realloc (pass_through_items,
645                                    num_pass_through_items * sizeof (char *));
646      pass_through_items[num_pass_through_items - 1] =
647          strdup (option + strlen ("-pass-through="));
648    }
649  else
650    {
651      int size;
652      lto_wrapper_num_args += 1;
653      size = lto_wrapper_num_args * sizeof (char *);
654      lto_wrapper_argv = (char **) realloc (lto_wrapper_argv, size);
655      lto_wrapper_argv[lto_wrapper_num_args - 1] = strdup(option);
656    }
657}
658
659/* Called by gold after loading the plugin. TV is the transfer vector. */
660
661enum ld_plugin_status
662onload (struct ld_plugin_tv *tv)
663{
664  struct ld_plugin_tv *p;
665  enum ld_plugin_status status;
666
667  unsigned version = elf_version (EV_CURRENT);
668  check (version != EV_NONE, LDPL_FATAL, "invalid ELF version");
669
670  p = tv;
671  while (p->tv_tag)
672    {
673      switch (p->tv_tag)
674	{
675        case LDPT_MESSAGE:
676          message = p->tv_u.tv_message;
677          break;
678	case LDPT_REGISTER_CLAIM_FILE_HOOK:
679	  register_claim_file = p->tv_u.tv_register_claim_file;
680	  break;
681	case LDPT_ADD_SYMBOLS:
682	  add_symbols = p->tv_u.tv_add_symbols;
683	  break;
684	case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
685	  register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
686	  break;
687	case LDPT_GET_SYMBOLS:
688	  get_symbols = p->tv_u.tv_get_symbols;
689	  break;
690	case LDPT_REGISTER_CLEANUP_HOOK:
691	  register_cleanup = p->tv_u.tv_register_cleanup;
692	  break;
693	case LDPT_ADD_INPUT_FILE:
694	  add_input_file = p->tv_u.tv_add_input_file;
695	  break;
696	case LDPT_ADD_INPUT_LIBRARY:
697	  add_input_library = p->tv_u.tv_add_input_library;
698	  break;
699	case LDPT_OPTION:
700	  process_option (p->tv_u.tv_string);
701	  break;
702	default:
703	  break;
704	}
705      p++;
706    }
707
708  check (register_claim_file, LDPL_FATAL, "register_claim_file not found");
709  check (add_symbols, LDPL_FATAL, "add_symbols not found");
710  status = register_claim_file (claim_file_handler);
711  check (status == LDPS_OK, LDPL_FATAL,
712	 "could not register the claim_file callback");
713
714  if (register_cleanup)
715    {
716      status = register_cleanup (cleanup_handler);
717      check (status == LDPS_OK, LDPL_FATAL,
718	     "could not register the cleanup callback");
719    }
720
721  if (register_all_symbols_read)
722    {
723      check (get_symbols, LDPL_FATAL, "get_symbols not found");
724      status = register_all_symbols_read (all_symbols_read_handler);
725      check (status == LDPS_OK, LDPL_FATAL,
726	     "could not register the all_symbols_read callback");
727    }
728
729  return LDPS_OK;
730}
731