OSDN Git Service

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