xref: /netbsd-src/external/gpl3/gcc.old/dist/lto-plugin/lto-plugin.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /* LTO plugin for gold.
2    Copyright (C) 2009 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 #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 
58 struct 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 
67 struct plugin_file_info
68 {
69   char *name;
70   void *handle;
71   struct plugin_symtab symtab;
72 };
73 
74 
75 static char *arguments_file_name;
76 static ld_plugin_register_claim_file register_claim_file;
77 static ld_plugin_add_symbols add_symbols;
78 static ld_plugin_register_all_symbols_read register_all_symbols_read;
79 static ld_plugin_get_symbols get_symbols;
80 static ld_plugin_register_cleanup register_cleanup;
81 static ld_plugin_add_input_file add_input_file;
82 static ld_plugin_add_input_library add_input_library;
83 static ld_plugin_message message;
84 
85 static struct plugin_file_info *claimed_files = NULL;
86 static unsigned int num_claimed_files = 0;
87 
88 static char **output_files = NULL;
89 static unsigned int num_output_files = 0;
90 
91 static char **lto_wrapper_argv;
92 static int lto_wrapper_num_args;
93 
94 static char **pass_through_items = NULL;
95 static unsigned int num_pass_through_items;
96 
97 static bool debug;
98 static bool nop;
99 static char *resolution_file = NULL;
100 
101 static void
102 check (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 
122 static char *
123 parse_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 
183 static Elf_Scn *
184 get_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 
209 static Elf_Data *
210 get_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 
224 static void
225 translate (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 
251 static void
252 free_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 
274 static void
275 free_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 
307 static void
308 write_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 
342 static void
343 add_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 
368 static void
369 exec_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 
444 static void
445 use_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 
458 static enum ld_plugin_status
459 all_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 
523 static enum ld_plugin_status
524 cleanup_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 
557 static enum ld_plugin_status
558 claim_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 
634 static void
635 process_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 
661 enum ld_plugin_status
662 onload (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