OSDN Git Service

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