Add the PR number for the ETIME/DTIME documentation change.
[official-gcc.git] / lto-plugin / lto-plugin.c
blobae484a9efab2271267192677ce95cbbdd7bc653c
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 <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>
49 /* The presence of gelf.h is checked by the toplevel configure script. */
50 #include <gelf.h>
52 #include "plugin-api.h"
53 #include "../gcc/lto/common.h"
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. */
59 struct plugin_symtab
61 int nsyms;
62 uint32_t *slots;
63 struct ld_plugin_symbol *syms;
66 /* All that we have to remember about a file. */
68 struct plugin_file_info
70 char *name;
71 void *handle;
72 struct plugin_symtab symtab;
73 unsigned char temp;
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;
86 static struct plugin_file_info *claimed_files = NULL;
87 static unsigned int num_claimed_files = 0;
89 static char **output_files = NULL;
90 static unsigned int num_output_files = 0;
92 static char **lto_wrapper_argv;
93 static int lto_wrapper_num_args;
95 static char **pass_through_items = NULL;
96 static unsigned int num_pass_through_items;
98 static bool debug;
99 static bool nop;
100 static char *resolution_file = NULL;
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. */
106 static char *
107 parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
109 unsigned char t;
110 enum ld_plugin_symbol_kind translate_kind[] =
112 LDPK_DEF,
113 LDPK_WEAKDEF,
114 LDPK_UNDEF,
115 LDPK_WEAKUNDEF,
116 LDPK_COMMON
119 enum ld_plugin_symbol_visibility translate_visibility[] =
121 LDPV_DEFAULT,
122 LDPV_PROTECTED,
123 LDPV_INTERNAL,
124 LDPV_HIDDEN
127 entry->name = strdup (p);
128 while (*p)
129 p++;
130 p++;
132 entry->version = NULL;
134 entry->comdat_key = p;
135 while (*p)
136 p++;
137 p++;
139 if (strlen (entry->comdat_key) == 0)
140 entry->comdat_key = NULL;
141 else
142 entry->comdat_key = strdup (entry->comdat_key);
144 t = *p;
145 assert (t <= 4);
146 entry->def = translate_kind[t];
147 p++;
149 t = *p;
150 assert (t <= 3);
151 entry->visibility = translate_visibility[t];
152 p++;
154 entry->size = *(uint64_t *) p;
155 p += 8;
157 *slot = *(uint32_t *) p;
158 p += 4;
160 entry->resolution = LDPR_UNKNOWN;
162 return p;
165 /* Return the section in ELF that is named NAME. */
167 static Elf_Scn *
168 get_section (Elf *elf, const char *name)
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);
177 while ((section = elf_nextscn(elf, section)) != 0)
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;
188 return NULL;
191 /* Returns the IL symbol table of file ELF. */
193 static Elf_Data *
194 get_symtab (Elf *elf)
196 Elf_Data *data = 0;
197 Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
198 if (!section)
199 return NULL;
201 data = elf_getdata (section, data);
202 assert (data);
203 return data;
206 /* Translate the IL symbol table SYMTAB. Write the slots and symbols in OUT. */
208 static void
209 translate (Elf_Data *symtab, struct plugin_symtab *out)
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;
217 while (data < end)
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]);
227 out->nsyms = n;
228 out->syms = syms;
229 out->slots = slots;
232 /* Free all memory that is no longer needed after writing the symbol
233 resolution. */
235 static void
236 free_1 (void)
238 unsigned int i;
239 for (i = 0; i < num_claimed_files; i++)
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++)
246 struct ld_plugin_symbol *s = &symtab->syms[j];
247 free (s->name);
248 if (s->comdat_key)
249 free (s->comdat_key);
251 free (symtab->syms);
252 symtab->syms = NULL;
256 /* Free all remaining memory. */
258 static void
259 free_2 (void)
261 unsigned int i;
262 for (i = 0; i < num_claimed_files; i++)
264 struct plugin_file_info *info = &claimed_files[i];
265 struct plugin_symtab *symtab = &info->symtab;
266 free (symtab->slots);
267 free (info->name);
270 for (i = 0; i < num_output_files; i++)
271 free (output_files[i]);
272 free (output_files);
274 free (claimed_files);
275 claimed_files = NULL;
276 num_claimed_files = 0;
278 free (temp_obj_dir_name);
279 temp_obj_dir_name = NULL;
281 if (resolution_file)
283 free (resolution_file);
284 resolution_file = NULL;
288 /* Writes the relocations to disk. */
290 static void
291 write_resolution (void)
293 unsigned int i;
294 FILE *f;
296 if (!resolution_file)
297 return;
299 f = fopen (resolution_file, "w");
300 assert (f);
302 fprintf (f, "%d\n", num_claimed_files);
304 for (i = 0; i < num_claimed_files; i++)
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;
311 assert (syms);
312 get_symbols (info->handle, symtab->nsyms, syms);
314 fprintf (f, "%s %d\n", info->name, info->symtab.nsyms);
316 for (j = 0; j < info->symtab.nsyms; j++)
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]);
323 fclose (f);
326 /* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
327 stdout. */
329 static void
330 add_output_files (FILE *f)
332 char fname[1000]; /* FIXME: Is this big enough? */
334 for (;;)
336 size_t len;
337 char *s = fgets (fname, sizeof (fname), f);
338 if (!s)
339 break;
341 len = strlen (s);
342 assert (s[len - 1] == '\n');
343 s[len - 1] = '\0';
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]);
352 /* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
353 argument list. */
355 static void
356 exec_lto_wrapper (char *argv[])
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;
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);
372 args_name = at_args + 1;
373 args = fopen (args_name, "w");
374 assert (args);
376 t = writeargv (&argv[1], args);
377 assert (t == 0);
378 t = fclose (args);
379 assert (t == 0);
381 new_argv[0] = argv[0];
382 new_argv[1] = at_args;
383 new_argv[2] = NULL;
385 if (debug)
387 int i;
388 for (i = 0; new_argv[i]; i++)
389 fprintf (stderr, "%s ", new_argv[i]);
390 fprintf (stderr, "\n");
394 pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL);
395 assert (pex != NULL);
397 errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t);
398 assert (errmsg == NULL);
399 assert (t == 0);
401 wrapper_output = pex_read_output (pex, 0);
402 assert (wrapper_output);
404 add_output_files (wrapper_output);
406 t = pex_get_status (pex, 1, &status);
407 assert (t == 1);
408 assert (WIFEXITED (status) && WEXITSTATUS (status) == 0);
410 pex_free (pex);
412 t = unlink (args_name);
413 assert (t == 0);
414 free (at_args);
417 /* Pass the original files back to the linker. */
419 static void
420 use_original_files (void)
422 unsigned i;
423 for (i = 0; i < num_claimed_files; i++)
425 struct plugin_file_info *info = &claimed_files[i];
426 add_input_file (info->name);
431 /* Called by the linker once all symbols have been read. */
433 static enum ld_plugin_status
434 all_symbols_read_handler (void)
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;
443 if (nop)
445 use_original_files ();
446 return LDPS_OK;
449 lto_argv = (char **) calloc (sizeof (char *), num_lto_args);
450 lto_arg_ptr = (const char **) lto_argv;
451 assert (lto_wrapper_argv);
453 write_resolution ();
455 free_1 ();
457 for (i = 0; i < lto_wrapper_num_args; i++)
458 *lto_arg_ptr++ = lto_wrapper_argv[i];
460 for (i = 0; i < num_claimed_files; i++)
462 struct plugin_file_info *info = &claimed_files[i];
464 *lto_arg_ptr++ = info->name;
467 *lto_arg_ptr++ = NULL;
468 exec_lto_wrapper (lto_argv);
470 free (lto_argv);
472 if (pass_through_items)
474 unsigned int i;
475 for (i = 0; i < num_pass_through_items; i++)
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;
484 free (pass_through_items);
485 pass_through_items = NULL;
488 return LDPS_OK;
491 /* Remove temporary files at the end of the link. */
493 static enum ld_plugin_status
494 cleanup_handler (void)
496 int t;
497 unsigned i;
499 for (i = 0; i < num_claimed_files; i++)
501 struct plugin_file_info *info = &claimed_files[i];
502 if (info->temp)
504 t = unlink (info->name);
505 assert (t == 0);
508 t = rmdir (temp_obj_dir_name);
509 assert (t == 0);
511 free_2 ();
512 return LDPS_OK;
515 /* Callback used by gold to check if the plugin will claim FILE. Writes
516 the result in CLAIMED. */
518 static enum ld_plugin_status
519 claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
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;
527 if (file->offset != 0)
529 /* FIXME lto: lto1 should know how to handle archives. */
530 int fd;
531 off_t size = file->filesize;
532 off_t offset;
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++;
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)
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;
555 lto_file.name = objname;
556 lto_file_fd = fd;
557 lto_file.handle = file->handle;
558 lto_file.temp = 1;
560 else
562 lto_file.name = strdup (file->name);
563 lto_file_fd = file->fd;
564 lto_file.handle = file->handle;
565 lto_file.temp = 0;
567 elf = elf_begin (lto_file_fd, ELF_C_READ, NULL);
569 *claimed = 0;
571 if (!elf)
572 goto err;
574 symtab = get_symtab (elf);
575 if (!symtab)
576 goto err;
578 translate (symtab, &lto_file.symtab);
580 status = add_symbols (file->handle, lto_file.symtab.nsyms,
581 lto_file.symtab.syms);
582 assert (status == LDPS_OK);
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;
591 goto cleanup;
593 err:
594 if (file->offset != 0)
596 int t = unlink (lto_file.name);
597 assert (t == 0);
599 free (lto_file.name);
601 cleanup:
602 if (elf)
603 elf_end (elf);
605 return LDPS_OK;
608 /* Parse the plugin options. */
610 static void
611 process_option (const char *option)
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=")))
619 resolution_file = strdup (option + strlen("-resolution="));
621 else if (!strncmp (option, "-pass-through=", strlen("-pass-through=")))
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="));
629 else
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);
639 /* Called by gold after loading the plugin. TV is the transfer vector. */
641 enum ld_plugin_status
642 onload (struct ld_plugin_tv *tv)
644 struct ld_plugin_tv *p;
645 enum ld_plugin_status status;
646 char *t;
648 unsigned version = elf_version (EV_CURRENT);
649 assert (version != EV_NONE);
651 p = tv;
652 while (p->tv_tag)
654 switch (p->tv_tag)
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;
683 p++;
686 assert (register_claim_file);
687 assert (add_symbols);
688 status = register_claim_file (claim_file_handler);
689 assert (status == LDPS_OK);
691 if (register_cleanup)
693 status = register_cleanup (cleanup_handler);
694 assert (status == LDPS_OK);
697 if (register_all_symbols_read)
699 assert (get_symbols);
700 status = register_all_symbols_read (all_symbols_read_handler);
701 assert (status == LDPS_OK);
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;