OSDN Git Service

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