lto-plugin.c (add_input_library): New.
[official-gcc.git] / lto-plugin / lto-plugin.c
blob71b4961496cc20051f4a155c93480db0a79d3809
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;
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. */
105 static char *
106 parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
108 unsigned char t;
109 enum ld_plugin_symbol_kind translate_kind[] =
111 LDPK_DEF,
112 LDPK_WEAKDEF,
113 LDPK_UNDEF,
114 LDPK_WEAKUNDEF,
115 LDPK_COMMON
118 enum ld_plugin_symbol_visibility translate_visibility[] =
120 LDPV_DEFAULT,
121 LDPV_PROTECTED,
122 LDPV_INTERNAL,
123 LDPV_HIDDEN
126 entry->name = strdup (p);
127 while (*p)
128 p++;
129 p++;
131 entry->version = NULL;
133 entry->comdat_key = p;
134 while (*p)
135 p++;
136 p++;
138 if (strlen (entry->comdat_key) == 0)
139 entry->comdat_key = NULL;
140 else
141 entry->comdat_key = strdup (entry->comdat_key);
143 t = *p;
144 assert (t <= 4);
145 entry->def = translate_kind[t];
146 p++;
148 t = *p;
149 assert (t <= 3);
150 entry->visibility = translate_visibility[t];
151 p++;
153 entry->size = *(uint64_t *) p;
154 p += 8;
156 *slot = *(uint32_t *) p;
157 p += 4;
159 entry->resolution = LDPR_UNKNOWN;
161 return p;
164 /* Return the section in ELF that is named NAME. */
166 static Elf_Scn *
167 get_section (Elf *elf, const char *name)
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);
176 while ((section = elf_nextscn(elf, section)) != 0)
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;
187 return NULL;
190 /* Returns the IL symbol table of file ELF. */
192 static Elf_Data *
193 get_symtab (Elf *elf)
195 Elf_Data *data = 0;
196 Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
197 if (!section)
198 return NULL;
200 data = elf_getdata (section, data);
201 assert (data);
202 return data;
205 /* Translate the IL symbol table SYMTAB. Write the slots and symbols in OUT. */
207 static void
208 translate (Elf_Data *symtab, struct plugin_symtab *out)
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;
216 while (data < end)
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]);
226 out->nsyms = n;
227 out->syms = syms;
228 out->slots = slots;
231 /* Free all memory that is no longer needed at the beginning of all_symbols_read. */
233 static void
234 free_1 (void)
236 unsigned int i;
237 for (i = 0; i < num_claimed_files; i++)
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++)
244 struct ld_plugin_symbol *s = &symtab->syms[j];
245 free (s->name);
246 if (s->comdat_key)
247 free (s->comdat_key);
249 free (symtab->syms);
250 symtab->syms = NULL;
254 /* Free all remaining memory. */
256 static void
257 free_2 (void)
259 unsigned int i;
260 for (i = 0; i < num_claimed_files; i++)
262 struct plugin_file_info *info = &claimed_files[i];
263 struct plugin_symtab *symtab = &info->symtab;
264 free (symtab->slots);
265 free (info->name);
268 for (i = 0; i < num_output_files; i++)
269 free (output_files[i]);
270 free (output_files);
272 free (claimed_files);
273 claimed_files = NULL;
274 num_claimed_files = 0;
276 free (temp_obj_dir_name);
277 temp_obj_dir_name = NULL;
280 /* Writes the relocations to disk. */
282 static void
283 write_resolution (void)
285 unsigned int i;
286 FILE *f;
287 /* FIXME: Disabled for now since we are not using the resolution file. */
288 return;
291 /* FIXME: This should be a temporary file. */
292 f = fopen ("resolution", "w");
294 fprintf (f, "%d\n", num_claimed_files);
296 for (i = 0; i < num_claimed_files; i++)
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;
304 assert (syms);
305 get_symbols (info->handle, symtab->nsyms, syms);
307 fprintf (f, "%s %d\n", info->name, info->symtab.nsyms);
309 for (j = 0; j < info->symtab.nsyms; j++)
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]);
315 free (syms);
317 fclose (f);
320 /* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
321 stdout. */
323 static void
324 add_output_files (FILE *f)
326 char fname[1000]; /* FIXME: Is this big enough? */
328 for (;;)
330 size_t len;
331 char *s = fgets (fname, sizeof (fname), f);
332 if (!s)
333 break;
335 len = strlen (s);
336 assert (s[len - 1] == '\n');
337 s[len - 1] = '\0';
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]);
346 /* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
347 argument list. */
349 static void
350 exec_lto_wrapper (char *argv[])
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;
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);
366 args_name = at_args + 1;
367 args = fopen (args_name, "w");
368 assert (args);
370 t = writeargv (&argv[1], args);
371 assert (t == 0);
372 t = fclose (args);
373 assert (t == 0);
375 new_argv[0] = argv[0];
376 new_argv[1] = at_args;
377 new_argv[2] = NULL;
379 if (debug)
381 int i;
382 for (i = 0; new_argv[i]; i++)
383 fprintf (stderr, "%s ", new_argv[i]);
384 fprintf (stderr, "\n");
388 pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL);
389 assert (pex != NULL);
391 errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t);
392 assert (errmsg == NULL);
393 assert (t == 0);
395 wrapper_output = pex_read_output (pex, 0);
396 assert (wrapper_output);
398 add_output_files (wrapper_output);
400 t = pex_get_status (pex, 1, &status);
401 assert (t == 1);
402 assert (WIFEXITED (status) && WEXITSTATUS (status) == 0);
404 pex_free (pex);
406 t = unlink (args_name);
407 assert (t == 0);
408 free (at_args);
411 /* Pass the original files back to the linker. */
413 static void
414 use_original_files (void)
416 unsigned i;
417 for (i = 0; i < num_claimed_files; i++)
419 struct plugin_file_info *info = &claimed_files[i];
420 add_input_file (info->name);
425 /* Called by the linker once all symbols have been read. */
427 static enum ld_plugin_status
428 all_symbols_read_handler (void)
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;
437 free_1 ();
439 if (nop)
441 use_original_files ();
442 return LDPS_OK;
445 lto_argv = (char **) calloc (sizeof (char *), num_lto_args);
446 lto_arg_ptr = (const char **) lto_argv;
447 assert (lto_wrapper_argv);
449 write_resolution ();
451 for (i = 0; i < lto_wrapper_num_args; i++)
452 *lto_arg_ptr++ = lto_wrapper_argv[i];
454 for (i = 0; i < num_claimed_files; i++)
456 struct plugin_file_info *info = &claimed_files[i];
458 *lto_arg_ptr++ = info->name;
461 *lto_arg_ptr++ = NULL;
462 exec_lto_wrapper (lto_argv);
464 free (lto_argv);
466 if (pass_through_items)
468 unsigned int i;
469 for (i = 0; i < num_pass_through_items; i++)
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;
478 free (pass_through_items);
479 pass_through_items = NULL;
482 return LDPS_OK;
485 /* Remove temporary files at the end of the link. */
487 static enum ld_plugin_status
488 cleanup_handler (void)
490 int t;
491 unsigned i;
493 for (i = 0; i < num_claimed_files; i++)
495 struct plugin_file_info *info = &claimed_files[i];
496 if (info->temp)
498 t = unlink (info->name);
499 assert (t == 0);
502 t = rmdir (temp_obj_dir_name);
503 assert (t == 0);
505 free_2 ();
506 return LDPS_OK;
509 /* Callback used by gold to check if the plugin will claim FILE. Writes
510 the result in CLAIMED. */
512 static enum ld_plugin_status
513 claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
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;
521 if (file->offset != 0)
523 /* FIXME lto: lto1 should know how to handle archives. */
524 int fd;
525 off_t size = file->filesize;
526 off_t offset;
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++;
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)
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;
549 lto_file.name = objname;
550 lto_file_fd = fd;
551 lto_file.handle = file->handle;
552 lto_file.temp = 1;
554 else
556 lto_file.name = strdup (file->name);
557 lto_file_fd = file->fd;
558 lto_file.handle = file->handle;
559 lto_file.temp = 0;
561 elf = elf_begin (lto_file_fd, ELF_C_READ, NULL);
563 *claimed = 0;
565 if (!elf)
566 goto err;
568 symtab = get_symtab (elf);
569 if (!symtab)
570 goto err;
572 translate (symtab, &lto_file.symtab);
574 status = add_symbols (file->handle, lto_file.symtab.nsyms,
575 lto_file.symtab.syms);
576 assert (status == LDPS_OK);
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;
585 goto cleanup;
587 err:
588 if (file->offset != 0)
590 int t = unlink (lto_file.name);
591 assert (t == 0);
593 free (lto_file.name);
595 cleanup:
596 if (elf)
597 elf_end (elf);
599 return LDPS_OK;
602 /* Parse the plugin options. */
604 static void
605 process_option (const char *option)
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=")))
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="));
619 else
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);
629 /* Called by gold after loading the plugin. TV is the transfer vector. */
631 enum ld_plugin_status
632 onload (struct ld_plugin_tv *tv)
634 struct ld_plugin_tv *p;
635 enum ld_plugin_status status;
636 char *t;
638 unsigned version = elf_version (EV_CURRENT);
639 assert (version != EV_NONE);
641 p = tv;
642 while (p->tv_tag)
644 switch (p->tv_tag)
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;
673 p++;
676 assert (register_claim_file);
677 assert (add_symbols);
678 status = register_claim_file (claim_file_handler);
679 assert (status == LDPS_OK);
681 if (register_cleanup)
683 status = register_cleanup (cleanup_handler);
684 assert (status == LDPS_OK);
687 if (register_all_symbols_read)
689 assert (get_symbols);
690 status = register_all_symbols_read (all_symbols_read_handler);
691 assert (status == LDPS_OK);
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;