Add ChangeLog entries.
[official-gcc/constexpr.git] / lto-plugin / lto-plugin.c
blobd0266ffee6cd2c9ab3a749105d7bdf380590bcdf
1 /* LTO plugin for gold.
2 Copyright (C) 2009 Free Software Foundation, Inc.
3 Contributed by Rafael Avila de Espindola (espindola@google.com).
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.
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.
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/>. */
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.
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.
27 More information at http://gcc.gnu.org/wiki/whopr/driver.
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. */
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>
48 /* The presence of gelf.h is checked by the toplevel configure script. */
49 #include <gelf.h>
51 #include "plugin-api.h"
52 #include "../gcc/lto/common.h"
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. */
58 struct plugin_symtab
60 int nsyms;
61 uint32_t *slots;
62 struct ld_plugin_symbol *syms;
65 /* All that we have to remember about a file. */
67 struct plugin_file_info
69 char *name;
70 void *handle;
71 struct plugin_symtab symtab;
75 static char *arguments_file_name;
76 static ld_plugin_register_claim_file register_claim_file;
77 static ld_plugin_add_symbols add_symbols;
78 static ld_plugin_register_all_symbols_read register_all_symbols_read;
79 static ld_plugin_get_symbols get_symbols;
80 static ld_plugin_register_cleanup register_cleanup;
81 static ld_plugin_add_input_file add_input_file;
82 static ld_plugin_add_input_library add_input_library;
83 static ld_plugin_message message;
85 static struct plugin_file_info *claimed_files = NULL;
86 static unsigned int num_claimed_files = 0;
88 static char **output_files = NULL;
89 static unsigned int num_output_files = 0;
91 static char **lto_wrapper_argv;
92 static int lto_wrapper_num_args;
94 static char **pass_through_items = NULL;
95 static unsigned int num_pass_through_items;
97 static bool debug;
98 static bool nop;
99 static char *resolution_file = NULL;
101 static void
102 check (bool gate, enum ld_plugin_level level, const char *text)
104 if (gate)
105 return;
107 if (message)
108 message (level, text);
109 else
111 /* If there is no nicer way to inform the user, fallback to stderr. */
112 fprintf (stderr, "%s\n", text);
113 if (level == LDPL_FATAL)
114 abort ();
118 /* Parse an entry of the IL symbol table. The data to be parsed is pointed
119 by P and the result is written in ENTRY. The slot number is stored in SLOT.
120 Returns the address of the next entry. */
122 static char *
123 parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
125 unsigned char t;
126 enum ld_plugin_symbol_kind translate_kind[] =
128 LDPK_DEF,
129 LDPK_WEAKDEF,
130 LDPK_UNDEF,
131 LDPK_WEAKUNDEF,
132 LDPK_COMMON
135 enum ld_plugin_symbol_visibility translate_visibility[] =
137 LDPV_DEFAULT,
138 LDPV_PROTECTED,
139 LDPV_INTERNAL,
140 LDPV_HIDDEN
143 entry->name = xstrdup (p);
144 while (*p)
145 p++;
146 p++;
148 entry->version = NULL;
150 entry->comdat_key = p;
151 while (*p)
152 p++;
153 p++;
155 if (strlen (entry->comdat_key) == 0)
156 entry->comdat_key = NULL;
157 else
158 entry->comdat_key = xstrdup (entry->comdat_key);
160 t = *p;
161 check (t <= 4, LDPL_FATAL, "invalid symbol kind found");
162 entry->def = translate_kind[t];
163 p++;
165 t = *p;
166 check (t <= 3, LDPL_FATAL, "invalid symbol visibility found");
167 entry->visibility = translate_visibility[t];
168 p++;
170 entry->size = *(uint64_t *) p;
171 p += 8;
173 *slot = *(uint32_t *) p;
174 p += 4;
176 entry->resolution = LDPR_UNKNOWN;
178 return p;
181 /* Return the section in ELF that is named NAME. */
183 static Elf_Scn *
184 get_section (Elf *elf, const char *name)
186 Elf_Scn *section = 0;
187 GElf_Ehdr header;
188 GElf_Ehdr *t = gelf_getehdr (elf, &header);
189 if (t == NULL)
190 return NULL;
191 assert (t == &header);
193 while ((section = elf_nextscn(elf, section)) != 0)
195 GElf_Shdr shdr;
196 GElf_Shdr *tshdr = gelf_getshdr (section, &shdr);
197 const char *t;
198 assert (tshdr == &shdr);
199 t = elf_strptr (elf, header.e_shstrndx, shdr.sh_name);
200 assert (t != NULL);
201 if (strcmp (t, name) == 0)
202 return section;
204 return NULL;
207 /* Returns the IL symbol table of file ELF. */
209 static Elf_Data *
210 get_symtab (Elf *elf)
212 Elf_Data *data = 0;
213 Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
214 if (!section)
215 return NULL;
217 data = elf_getdata (section, data);
218 assert (data);
219 return data;
222 /* Translate the IL symbol table SYMTAB. Write the slots and symbols in OUT. */
224 static void
225 translate (Elf_Data *symtab, struct plugin_symtab *out)
227 uint32_t *slots = NULL;
228 char *data = symtab->d_buf;
229 char *end = data + symtab->d_size;
230 struct ld_plugin_symbol *syms = NULL;
231 int n = 0;
233 while (data < end)
235 n++;
236 syms = xrealloc (syms, n * sizeof (struct ld_plugin_symbol));
237 check (syms, LDPL_FATAL, "could not allocate memory");
238 slots = xrealloc (slots, n * sizeof (uint32_t));
239 check (slots, LDPL_FATAL, "could not allocate memory");
240 data = parse_table_entry (data, &syms[n - 1], &slots[n - 1]);
243 out->nsyms = n;
244 out->syms = syms;
245 out->slots = slots;
248 /* Free all memory that is no longer needed after writing the symbol
249 resolution. */
251 static void
252 free_1 (void)
254 unsigned int i;
255 for (i = 0; i < num_claimed_files; i++)
257 struct plugin_file_info *info = &claimed_files[i];
258 struct plugin_symtab *symtab = &info->symtab;
259 unsigned int j;
260 for (j = 0; j < symtab->nsyms; j++)
262 struct ld_plugin_symbol *s = &symtab->syms[j];
263 free (s->name);
264 if (s->comdat_key)
265 free (s->comdat_key);
267 free (symtab->syms);
268 symtab->syms = NULL;
272 /* Free all remaining memory. */
274 static void
275 free_2 (void)
277 unsigned int i;
278 for (i = 0; i < num_claimed_files; i++)
280 struct plugin_file_info *info = &claimed_files[i];
281 struct plugin_symtab *symtab = &info->symtab;
282 free (symtab->slots);
283 free (info->name);
286 for (i = 0; i < num_output_files; i++)
287 free (output_files[i]);
288 free (output_files);
290 free (claimed_files);
291 claimed_files = NULL;
292 num_claimed_files = 0;
294 if (arguments_file_name)
295 free (arguments_file_name);
296 arguments_file_name = NULL;
298 if (resolution_file)
300 free (resolution_file);
301 resolution_file = NULL;
305 /* Writes the relocations to disk. */
307 static void
308 write_resolution (void)
310 unsigned int i;
311 FILE *f;
313 f = fopen (resolution_file, "w");
314 check (f, LDPL_FATAL, "could not open file");
316 fprintf (f, "%d\n", num_claimed_files);
318 for (i = 0; i < num_claimed_files; i++)
320 struct plugin_file_info *info = &claimed_files[i];
321 struct plugin_symtab *symtab = &info->symtab;
322 struct ld_plugin_symbol *syms = symtab->syms;
323 unsigned j;
325 assert (syms);
326 get_symbols (info->handle, symtab->nsyms, syms);
328 fprintf (f, "%s %d\n", info->name, info->symtab.nsyms);
330 for (j = 0; j < info->symtab.nsyms; j++)
332 uint32_t slot = symtab->slots[j];
333 unsigned int resolution = syms[j].resolution;
334 fprintf (f, "%d %s %s\n", slot, lto_resolution_str[resolution], syms[j].name);
337 fclose (f);
340 /* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
341 stdout. */
343 static void
344 add_output_files (FILE *f)
346 for (;;)
348 const unsigned piece = 32;
349 char *buf, *s = xmalloc (piece);
350 size_t len;
352 buf = s;
353 cont:
354 if (!fgets (buf, piece, f))
355 break;
356 len = strlen (s);
357 if (s[len - 1] != '\n')
359 s = xrealloc (s, len + piece);
360 buf = s + len;
361 goto cont;
363 s[len - 1] = '\0';
365 num_output_files++;
366 output_files
367 = xrealloc (output_files, num_output_files * sizeof (char *));
368 output_files[num_output_files - 1] = s;
369 add_input_file (output_files[num_output_files - 1]);
373 /* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
374 argument list. */
376 static void
377 exec_lto_wrapper (char *argv[])
379 int t, i;
380 int status;
381 char *at_args;
382 FILE *args;
383 FILE *wrapper_output;
384 char *new_argv[3];
385 struct pex_obj *pex;
386 const char *errmsg;
388 /* Write argv to a file to avoid a command line that is too long. */
389 arguments_file_name = make_temp_file ("");
390 check (arguments_file_name, LDPL_FATAL,
391 "Failed to generate a temorary file name");
393 args = fopen (arguments_file_name, "w");
394 check (args, LDPL_FATAL, "could not open arguments file");
396 t = writeargv (&argv[1], args);
397 check (t == 0, LDPL_FATAL, "could not write arguments");
398 t = fclose (args);
399 check (t == 0, LDPL_FATAL, "could not close arguments file");
401 at_args = concat ("@", arguments_file_name, NULL);
402 check (at_args, LDPL_FATAL, "could not allocate");
404 for (i = 1; argv[i]; i++)
406 char *a = argv[i];
407 if (a[0] == '-' && a[1] == 'v' && a[2] == '\0')
409 for (i = 0; argv[i]; i++)
410 fprintf (stderr, "%s ", argv[i]);
411 fprintf (stderr, "\n");
412 break;
416 new_argv[0] = argv[0];
417 new_argv[1] = at_args;
418 new_argv[2] = NULL;
420 if (debug)
422 for (i = 0; new_argv[i]; i++)
423 fprintf (stderr, "%s ", new_argv[i]);
424 fprintf (stderr, "\n");
428 pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL);
429 check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper");
431 errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t);
432 check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper");
433 check (t == 0, LDPL_FATAL, "could not run lto-wrapper");
435 wrapper_output = pex_read_output (pex, 0);
436 check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output");
438 add_output_files (wrapper_output);
440 t = pex_get_status (pex, 1, &status);
441 check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status");
442 check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL,
443 "lto-wrapper failed");
445 pex_free (pex);
447 free (at_args);
450 /* Pass the original files back to the linker. */
452 static void
453 use_original_files (void)
455 unsigned i;
456 for (i = 0; i < num_claimed_files; i++)
458 struct plugin_file_info *info = &claimed_files[i];
459 add_input_file (info->name);
464 /* Called by the linker once all symbols have been read. */
466 static enum ld_plugin_status
467 all_symbols_read_handler (void)
469 unsigned i;
470 unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 2 + 1;
471 char **lto_argv;
472 const char **lto_arg_ptr;
473 if (num_claimed_files == 0)
474 return LDPS_OK;
476 if (nop)
478 use_original_files ();
479 return LDPS_OK;
482 lto_argv = (char **) xcalloc (sizeof (char *), num_lto_args);
483 lto_arg_ptr = (const char **) lto_argv;
484 assert (lto_wrapper_argv);
486 resolution_file = make_temp_file ("");
488 write_resolution ();
490 free_1 ();
492 for (i = 0; i < lto_wrapper_num_args; i++)
493 *lto_arg_ptr++ = lto_wrapper_argv[i];
495 *lto_arg_ptr++ = "-fresolution";
496 *lto_arg_ptr++ = resolution_file;
498 for (i = 0; i < num_claimed_files; i++)
500 struct plugin_file_info *info = &claimed_files[i];
502 *lto_arg_ptr++ = info->name;
505 *lto_arg_ptr++ = NULL;
506 exec_lto_wrapper (lto_argv);
508 free (lto_argv);
510 if (pass_through_items)
512 unsigned int i;
513 for (i = 0; i < num_pass_through_items; i++)
515 if (strncmp (pass_through_items[i], "-l", 2) == 0)
516 add_input_library (pass_through_items[i] + 2);
517 else
518 add_input_file (pass_through_items[i]);
519 free (pass_through_items[i]);
520 pass_through_items[i] = NULL;
522 free (pass_through_items);
523 pass_through_items = NULL;
526 return LDPS_OK;
529 /* Remove temporary files at the end of the link. */
531 static enum ld_plugin_status
532 cleanup_handler (void)
534 unsigned int i;
535 int t;
537 if (debug)
538 return LDPS_OK;
540 if (arguments_file_name)
542 t = unlink (arguments_file_name);
543 check (t == 0, LDPL_FATAL, "could not unlink arguments file");
546 if (resolution_file)
548 t = unlink (resolution_file);
549 check (t == 0, LDPL_FATAL, "could not unlink resolution file");
552 for (i = 0; i < num_output_files; i++)
554 t = unlink (output_files[i]);
555 check (t == 0, LDPL_FATAL, "could not unlink output file");
558 free_2 ();
559 return LDPS_OK;
562 /* Callback used by gold to check if the plugin will claim FILE. Writes
563 the result in CLAIMED. */
565 static enum ld_plugin_status
566 claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
568 enum ld_plugin_status status;
569 Elf *elf;
570 struct plugin_file_info lto_file;
571 Elf_Data *symtab;
573 if (file->offset != 0)
575 char *objname;
576 Elf *archive;
577 off_t offset;
578 /* We pass the offset of the actual file, not the archive header. */
579 int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
580 (int64_t) file->offset);
581 check (t >= 0, LDPL_FATAL, "asprintf failed");
582 lto_file.name = objname;
584 archive = elf_begin (file->fd, ELF_C_READ, NULL);
585 check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL,
586 "Not an archive and offset not 0");
588 /* elf_rand expects the offset to point to the ar header, not the
589 object itself. Subtract the size of the ar header (60 bytes).
590 We don't uses sizeof (struct ar_hd) to avoid including ar.h */
592 offset = file->offset - 60;
593 check (offset == elf_rand (archive, offset), LDPL_FATAL,
594 "could not seek in archive");
595 elf = elf_begin (file->fd, ELF_C_READ, archive);
596 check (elf != NULL, LDPL_FATAL, "could not find archive member");
597 elf_end (archive);
599 else
601 lto_file.name = xstrdup (file->name);
602 elf = elf_begin (file->fd, ELF_C_READ, NULL);
604 lto_file.handle = file->handle;
606 *claimed = 0;
608 if (!elf)
609 goto err;
611 symtab = get_symtab (elf);
612 if (!symtab)
613 goto err;
615 translate (symtab, &lto_file.symtab);
617 status = add_symbols (file->handle, lto_file.symtab.nsyms,
618 lto_file.symtab.syms);
619 check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
621 *claimed = 1;
622 num_claimed_files++;
623 claimed_files =
624 xrealloc (claimed_files,
625 num_claimed_files * sizeof (struct plugin_file_info));
626 claimed_files[num_claimed_files - 1] = lto_file;
628 goto cleanup;
630 err:
631 free (lto_file.name);
633 cleanup:
634 if (elf)
635 elf_end (elf);
637 return LDPS_OK;
640 /* Parse the plugin options. */
642 static void
643 process_option (const char *option)
645 if (strcmp (option, "-debug") == 0)
646 debug = 1;
647 else if (strcmp (option, "-nop") == 0)
648 nop = 1;
649 else if (!strncmp (option, "-pass-through=", strlen("-pass-through=")))
651 num_pass_through_items++;
652 pass_through_items = xrealloc (pass_through_items,
653 num_pass_through_items * sizeof (char *));
654 pass_through_items[num_pass_through_items - 1] =
655 xstrdup (option + strlen ("-pass-through="));
657 else
659 int size;
660 lto_wrapper_num_args += 1;
661 size = lto_wrapper_num_args * sizeof (char *);
662 lto_wrapper_argv = (char **) xrealloc (lto_wrapper_argv, size);
663 lto_wrapper_argv[lto_wrapper_num_args - 1] = xstrdup(option);
667 /* Called by gold after loading the plugin. TV is the transfer vector. */
669 enum ld_plugin_status
670 onload (struct ld_plugin_tv *tv)
672 struct ld_plugin_tv *p;
673 enum ld_plugin_status status;
675 unsigned version = elf_version (EV_CURRENT);
676 check (version != EV_NONE, LDPL_FATAL, "invalid ELF version");
678 p = tv;
679 while (p->tv_tag)
681 switch (p->tv_tag)
683 case LDPT_MESSAGE:
684 message = p->tv_u.tv_message;
685 break;
686 case LDPT_REGISTER_CLAIM_FILE_HOOK:
687 register_claim_file = p->tv_u.tv_register_claim_file;
688 break;
689 case LDPT_ADD_SYMBOLS:
690 add_symbols = p->tv_u.tv_add_symbols;
691 break;
692 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
693 register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
694 break;
695 case LDPT_GET_SYMBOLS:
696 get_symbols = p->tv_u.tv_get_symbols;
697 break;
698 case LDPT_REGISTER_CLEANUP_HOOK:
699 register_cleanup = p->tv_u.tv_register_cleanup;
700 break;
701 case LDPT_ADD_INPUT_FILE:
702 add_input_file = p->tv_u.tv_add_input_file;
703 break;
704 case LDPT_ADD_INPUT_LIBRARY:
705 add_input_library = p->tv_u.tv_add_input_library;
706 break;
707 case LDPT_OPTION:
708 process_option (p->tv_u.tv_string);
709 break;
710 default:
711 break;
713 p++;
716 check (register_claim_file, LDPL_FATAL, "register_claim_file not found");
717 check (add_symbols, LDPL_FATAL, "add_symbols not found");
718 status = register_claim_file (claim_file_handler);
719 check (status == LDPS_OK, LDPL_FATAL,
720 "could not register the claim_file callback");
722 if (register_cleanup)
724 status = register_cleanup (cleanup_handler);
725 check (status == LDPS_OK, LDPL_FATAL,
726 "could not register the cleanup callback");
729 if (register_all_symbols_read)
731 check (get_symbols, LDPL_FATAL, "get_symbols not found");
732 status = register_all_symbols_read (all_symbols_read_handler);
733 check (status == LDPS_OK, LDPL_FATAL,
734 "could not register the all_symbols_read callback");
737 return LDPS_OK;