OSDN Git Service

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