OSDN Git Service

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