]> git.ipfire.org Git - thirdparty/gcc.git/blame - lto-plugin/lto-plugin.c
Daily bump.
[thirdparty/gcc.git] / lto-plugin / lto-plugin.c
CommitLineData
d7f09764
DN
1/* LTO plugin for gold.
2 Copyright (C) 2009 Free Software Foundation, Inc.
3 Contributed by Rafael Avila de Espindola (espindola@google.com).
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 3, or (at your option)
8any later version.
9
10This program is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along 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>
d7f09764
DN
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>
47
48/* The presence of gelf.h is checked by the toplevel configure script. */
49#include <gelf.h>
50
51#include "plugin-api.h"
52#include "../gcc/lto/common.h"
53
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. */
57
58struct plugin_symtab
59{
60 int nsyms;
61 uint32_t *slots;
62 struct ld_plugin_symbol *syms;
63};
64
65/* All that we have to remember about a file. */
66
67struct plugin_file_info
68{
69 char *name;
70 void *handle;
71 struct plugin_symtab symtab;
d7f09764
DN
72};
73
74
94086ef6 75static char *arguments_file_name;
d7f09764
DN
76static ld_plugin_register_claim_file register_claim_file;
77static ld_plugin_add_symbols add_symbols;
78static ld_plugin_register_all_symbols_read register_all_symbols_read;
79static ld_plugin_get_symbols get_symbols;
80static ld_plugin_register_cleanup register_cleanup;
81static ld_plugin_add_input_file add_input_file;
d520c7fb 82static ld_plugin_add_input_library add_input_library;
33662270 83static ld_plugin_message message;
d7f09764
DN
84
85static struct plugin_file_info *claimed_files = NULL;
86static unsigned int num_claimed_files = 0;
87
88static char **output_files = NULL;
89static unsigned int num_output_files = 0;
90
91static char **lto_wrapper_argv;
92static int lto_wrapper_num_args;
93
94static char **pass_through_items = NULL;
95static unsigned int num_pass_through_items;
96
97static bool debug;
98static bool nop;
b10071c5 99static char *resolution_file = NULL;
d7f09764 100
33662270
RAE
101static void
102check (bool gate, enum ld_plugin_level level, const char *text)
103{
104 if (gate)
105 return;
106
107 if (message)
108 message (level, text);
109 else
110 {
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 ();
115 }
116}
117
d7f09764
DN
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. */
121
122static char *
123parse_table_entry (char *p, struct ld_plugin_symbol *entry, uint32_t *slot)
124{
125 unsigned char t;
126 enum ld_plugin_symbol_kind translate_kind[] =
127 {
128 LDPK_DEF,
129 LDPK_WEAKDEF,
130 LDPK_UNDEF,
131 LDPK_WEAKUNDEF,
132 LDPK_COMMON
133 };
134
135 enum ld_plugin_symbol_visibility translate_visibility[] =
136 {
137 LDPV_DEFAULT,
138 LDPV_PROTECTED,
139 LDPV_INTERNAL,
140 LDPV_HIDDEN
141 };
142
143 entry->name = strdup (p);
144 while (*p)
145 p++;
146 p++;
147
148 entry->version = NULL;
149
150 entry->comdat_key = p;
151 while (*p)
152 p++;
153 p++;
154
155 if (strlen (entry->comdat_key) == 0)
156 entry->comdat_key = NULL;
157 else
158 entry->comdat_key = strdup (entry->comdat_key);
159
160 t = *p;
33662270 161 check (t <= 4, LDPL_FATAL, "invalid symbol kind found");
d7f09764
DN
162 entry->def = translate_kind[t];
163 p++;
164
165 t = *p;
33662270 166 check (t <= 3, LDPL_FATAL, "invalid symbol visibility found");
d7f09764
DN
167 entry->visibility = translate_visibility[t];
168 p++;
169
170 entry->size = *(uint64_t *) p;
171 p += 8;
172
173 *slot = *(uint32_t *) p;
174 p += 4;
175
176 entry->resolution = LDPR_UNKNOWN;
177
178 return p;
179}
180
181/* Return the section in ELF that is named NAME. */
182
183static Elf_Scn *
184get_section (Elf *elf, const char *name)
185{
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);
192
193 while ((section = elf_nextscn(elf, section)) != 0)
194 {
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;
203 }
204 return NULL;
205}
206
207/* Returns the IL symbol table of file ELF. */
208
209static Elf_Data *
210get_symtab (Elf *elf)
211{
212 Elf_Data *data = 0;
213 Elf_Scn *section = get_section (elf, ".gnu.lto_.symtab");
214 if (!section)
215 return NULL;
216
217 data = elf_getdata (section, data);
218 assert (data);
219 return data;
220}
221
222/* Translate the IL symbol table SYMTAB. Write the slots and symbols in OUT. */
223
224static void
225translate (Elf_Data *symtab, struct plugin_symtab *out)
226{
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;
232
233 while (data < end)
234 {
235 n++;
236 syms = realloc (syms, n * sizeof (struct ld_plugin_symbol));
33662270 237 check (syms, LDPL_FATAL, "could not allocate memory");
d7f09764 238 slots = realloc (slots, n * sizeof (uint32_t));
33662270 239 check (slots, LDPL_FATAL, "could not allocate memory");
d7f09764
DN
240 data = parse_table_entry (data, &syms[n - 1], &slots[n - 1]);
241 }
242
243 out->nsyms = n;
244 out->syms = syms;
245 out->slots = slots;
246}
247
b10071c5
RAE
248/* Free all memory that is no longer needed after writing the symbol
249 resolution. */
d7f09764
DN
250
251static void
252free_1 (void)
253{
254 unsigned int i;
255 for (i = 0; i < num_claimed_files; i++)
256 {
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++)
261 {
262 struct ld_plugin_symbol *s = &symtab->syms[j];
263 free (s->name);
264 if (s->comdat_key)
265 free (s->comdat_key);
266 }
267 free (symtab->syms);
268 symtab->syms = NULL;
269 }
270}
271
272/* Free all remaining memory. */
273
274static void
275free_2 (void)
276{
277 unsigned int i;
278 for (i = 0; i < num_claimed_files; i++)
279 {
280 struct plugin_file_info *info = &claimed_files[i];
281 struct plugin_symtab *symtab = &info->symtab;
282 free (symtab->slots);
283 free (info->name);
284 }
285
286 for (i = 0; i < num_output_files; i++)
287 free (output_files[i]);
288 free (output_files);
289
290 free (claimed_files);
291 claimed_files = NULL;
292 num_claimed_files = 0;
293
94086ef6
RAE
294 if (arguments_file_name)
295 free (arguments_file_name);
296 arguments_file_name = NULL;
b10071c5
RAE
297
298 if (resolution_file)
299 {
300 free (resolution_file);
301 resolution_file = NULL;
302 }
d7f09764
DN
303}
304
305/* Writes the relocations to disk. */
306
307static void
308write_resolution (void)
309{
310 unsigned int i;
311 FILE *f;
d7f09764 312
b10071c5 313 f = fopen (resolution_file, "w");
33662270 314 check (f, LDPL_FATAL, "could not open file");
d7f09764
DN
315
316 fprintf (f, "%d\n", num_claimed_files);
317
318 for (i = 0; i < num_claimed_files; i++)
319 {
320 struct plugin_file_info *info = &claimed_files[i];
321 struct plugin_symtab *symtab = &info->symtab;
b10071c5 322 struct ld_plugin_symbol *syms = symtab->syms;
d7f09764
DN
323 unsigned j;
324
325 assert (syms);
326 get_symbols (info->handle, symtab->nsyms, syms);
327
328 fprintf (f, "%s %d\n", info->name, info->symtab.nsyms);
329
330 for (j = 0; j < info->symtab.nsyms; j++)
331 {
332 uint32_t slot = symtab->slots[j];
333 unsigned int resolution = syms[j].resolution;
06bd7f56 334 fprintf (f, "%d %s %s\n", slot, lto_resolution_str[resolution], syms[j].name);
d7f09764 335 }
d7f09764
DN
336 }
337 fclose (f);
338}
339
340/* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
341 stdout. */
342
343static void
344add_output_files (FILE *f)
345{
33662270 346 char fname[1000]; /* FIXME: Remove this restriction. */
d7f09764
DN
347
348 for (;;)
349 {
350 size_t len;
351 char *s = fgets (fname, sizeof (fname), f);
352 if (!s)
353 break;
354
355 len = strlen (s);
33662270 356 check (s[len - 1] == '\n', LDPL_FATAL, "file name too long");
d7f09764
DN
357 s[len - 1] = '\0';
358
359 num_output_files++;
360 output_files = realloc (output_files, num_output_files * sizeof (char *));
361 output_files[num_output_files - 1] = strdup (s);
362 add_input_file (output_files[num_output_files - 1]);
363 }
364}
365
366/* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
367 argument list. */
368
369static void
370exec_lto_wrapper (char *argv[])
371{
372 int t;
373 int status;
374 char *at_args;
d7f09764
DN
375 FILE *args;
376 FILE *wrapper_output;
377 char *new_argv[3];
378 struct pex_obj *pex;
379 const char *errmsg;
380
381 /* Write argv to a file to avoid a command line that is too long. */
94086ef6
RAE
382 arguments_file_name = make_temp_file ("");
383 check (arguments_file_name, LDPL_FATAL,
384 "Failed to generate a temorary file name");
d7f09764 385
94086ef6 386 args = fopen (arguments_file_name, "w");
33662270 387 check (args, LDPL_FATAL, "could not open arguments file");
d7f09764
DN
388
389 t = writeargv (&argv[1], args);
33662270 390 check (t == 0, LDPL_FATAL, "could not write arguments");
d7f09764 391 t = fclose (args);
33662270 392 check (t == 0, LDPL_FATAL, "could not close arguments file");
d7f09764 393
94086ef6
RAE
394 at_args = concat ("@", arguments_file_name, NULL);
395 check (at_args, LDPL_FATAL, "could not allocate");
396
d7f09764
DN
397 new_argv[0] = argv[0];
398 new_argv[1] = at_args;
399 new_argv[2] = NULL;
400
401 if (debug)
402 {
403 int i;
404 for (i = 0; new_argv[i]; i++)
405 fprintf (stderr, "%s ", new_argv[i]);
406 fprintf (stderr, "\n");
407 }
408
409
410 pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL);
33662270 411 check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper");
d7f09764
DN
412
413 errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t);
33662270
RAE
414 check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper");
415 check (t == 0, LDPL_FATAL, "could not run lto-wrapper");
d7f09764
DN
416
417 wrapper_output = pex_read_output (pex, 0);
33662270 418 check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output");
d7f09764
DN
419
420 add_output_files (wrapper_output);
421
422 t = pex_get_status (pex, 1, &status);
33662270
RAE
423 check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status");
424 check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL,
425 "lto-wrapper failed");
d7f09764
DN
426
427 pex_free (pex);
428
d7f09764
DN
429 free (at_args);
430}
431
432/* Pass the original files back to the linker. */
433
434static void
435use_original_files (void)
436{
437 unsigned i;
438 for (i = 0; i < num_claimed_files; i++)
439 {
440 struct plugin_file_info *info = &claimed_files[i];
441 add_input_file (info->name);
442 }
443}
444
445
446/* Called by the linker once all symbols have been read. */
447
448static enum ld_plugin_status
449all_symbols_read_handler (void)
450{
451 unsigned i;
06bd7f56 452 unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 2 + 1;
d7f09764
DN
453 char **lto_argv;
454 const char **lto_arg_ptr;
455 if (num_claimed_files == 0)
456 return LDPS_OK;
457
d7f09764
DN
458 if (nop)
459 {
460 use_original_files ();
461 return LDPS_OK;
462 }
463
464 lto_argv = (char **) calloc (sizeof (char *), num_lto_args);
465 lto_arg_ptr = (const char **) lto_argv;
466 assert (lto_wrapper_argv);
467
06bd7f56
RAE
468 resolution_file = make_temp_file ("");
469
d7f09764
DN
470 write_resolution ();
471
b10071c5
RAE
472 free_1 ();
473
d7f09764
DN
474 for (i = 0; i < lto_wrapper_num_args; i++)
475 *lto_arg_ptr++ = lto_wrapper_argv[i];
476
06bd7f56
RAE
477 *lto_arg_ptr++ = "-fresolution";
478 *lto_arg_ptr++ = resolution_file;
479
d7f09764
DN
480 for (i = 0; i < num_claimed_files; i++)
481 {
482 struct plugin_file_info *info = &claimed_files[i];
483
484 *lto_arg_ptr++ = info->name;
485 }
486
487 *lto_arg_ptr++ = NULL;
488 exec_lto_wrapper (lto_argv);
489
490 free (lto_argv);
491
492 if (pass_through_items)
493 {
494 unsigned int i;
495 for (i = 0; i < num_pass_through_items; i++)
496 {
d520c7fb
RAE
497 if (strncmp (pass_through_items[i], "-l", 2) == 0)
498 add_input_library (pass_through_items[i] + 2);
499 else
500 add_input_file (pass_through_items[i]);
d7f09764
DN
501 free (pass_through_items[i]);
502 pass_through_items[i] = NULL;
503 }
504 free (pass_through_items);
505 pass_through_items = NULL;
506 }
507
508 return LDPS_OK;
509}
510
511/* Remove temporary files at the end of the link. */
512
513static enum ld_plugin_status
514cleanup_handler (void)
515{
516 int t;
d7f09764 517
1cddcdca
RAE
518 if (debug)
519 return LDPS_OK;
520
94086ef6 521 if (arguments_file_name)
33662270 522 {
94086ef6 523 t = unlink (arguments_file_name);
aff4273c 524 check (t == 0, LDPL_FATAL, "could not unlink arguments file");
33662270 525 }
d7f09764 526
06bd7f56
RAE
527 if (resolution_file)
528 {
529 t = unlink (resolution_file);
530 check (t == 0, LDPL_FATAL, "could not unlink resolution file");
531 }
532
d7f09764
DN
533 free_2 ();
534 return LDPS_OK;
535}
536
537/* Callback used by gold to check if the plugin will claim FILE. Writes
538 the result in CLAIMED. */
539
540static enum ld_plugin_status
541claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
542{
543 enum ld_plugin_status status;
544 Elf *elf;
545 struct plugin_file_info lto_file;
546 Elf_Data *symtab;
d7f09764
DN
547
548 if (file->offset != 0)
549 {
d7f09764 550 char *objname;
7e9dc421
RG
551 Elf *archive;
552 off_t offset;
553 /* We pass the offset of the actual file, not the archive header. */
92fa7608 554 int t = asprintf (&objname, "%s@0x%" PRIx64, file->name,
7e9dc421 555 (int64_t) file->offset);
33662270 556 check (t >= 0, LDPL_FATAL, "asprintf failed");
d7f09764 557 lto_file.name = objname;
7e9dc421
RG
558
559 archive = elf_begin (file->fd, ELF_C_READ, NULL);
560 check (elf_kind (archive) == ELF_K_AR, LDPL_FATAL,
561 "Not an archive and offset not 0");
562
563 /* elf_rand expects the offset to point to the ar header, not the
564 object itself. Subtract the size of the ar header (60 bytes).
565 We don't uses sizeof (struct ar_hd) to avoid including ar.h */
566
567 offset = file->offset - 60;
568 check (offset == elf_rand (archive, offset), LDPL_FATAL,
569 "could not seek in archive");
570 elf = elf_begin (file->fd, ELF_C_READ, archive);
571 check (elf != NULL, LDPL_FATAL, "could not find archive member");
572 elf_end (archive);
d7f09764
DN
573 }
574 else
575 {
576 lto_file.name = strdup (file->name);
7e9dc421 577 elf = elf_begin (file->fd, ELF_C_READ, NULL);
d7f09764 578 }
7e9dc421 579 lto_file.handle = file->handle;
d7f09764
DN
580
581 *claimed = 0;
582
583 if (!elf)
584 goto err;
585
586 symtab = get_symtab (elf);
587 if (!symtab)
588 goto err;
589
590 translate (symtab, &lto_file.symtab);
591
592 status = add_symbols (file->handle, lto_file.symtab.nsyms,
593 lto_file.symtab.syms);
33662270 594 check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
d7f09764
DN
595
596 *claimed = 1;
597 num_claimed_files++;
598 claimed_files =
599 realloc (claimed_files,
600 num_claimed_files * sizeof (struct plugin_file_info));
601 claimed_files[num_claimed_files - 1] = lto_file;
602
603 goto cleanup;
604
605 err:
d7f09764
DN
606 free (lto_file.name);
607
608 cleanup:
609 if (elf)
610 elf_end (elf);
611
612 return LDPS_OK;
613}
614
615/* Parse the plugin options. */
616
617static void
618process_option (const char *option)
619{
620 if (strcmp (option, "-debug") == 0)
621 debug = 1;
622 else if (strcmp (option, "-nop") == 0)
623 nop = 1;
624 else if (!strncmp (option, "-pass-through=", strlen("-pass-through=")))
625 {
626 num_pass_through_items++;
d520c7fb
RAE
627 pass_through_items = realloc (pass_through_items,
628 num_pass_through_items * sizeof (char *));
629 pass_through_items[num_pass_through_items - 1] =
630 strdup (option + strlen ("-pass-through="));
d7f09764
DN
631 }
632 else
633 {
634 int size;
635 lto_wrapper_num_args += 1;
636 size = lto_wrapper_num_args * sizeof (char *);
637 lto_wrapper_argv = (char **) realloc (lto_wrapper_argv, size);
638 lto_wrapper_argv[lto_wrapper_num_args - 1] = strdup(option);
639 }
640}
641
642/* Called by gold after loading the plugin. TV is the transfer vector. */
643
644enum ld_plugin_status
645onload (struct ld_plugin_tv *tv)
646{
647 struct ld_plugin_tv *p;
648 enum ld_plugin_status status;
d7f09764
DN
649
650 unsigned version = elf_version (EV_CURRENT);
33662270 651 check (version != EV_NONE, LDPL_FATAL, "invalid ELF version");
d7f09764
DN
652
653 p = tv;
654 while (p->tv_tag)
655 {
656 switch (p->tv_tag)
657 {
33662270
RAE
658 case LDPT_MESSAGE:
659 message = p->tv_u.tv_message;
660 break;
d7f09764
DN
661 case LDPT_REGISTER_CLAIM_FILE_HOOK:
662 register_claim_file = p->tv_u.tv_register_claim_file;
663 break;
664 case LDPT_ADD_SYMBOLS:
665 add_symbols = p->tv_u.tv_add_symbols;
666 break;
667 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
668 register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
669 break;
670 case LDPT_GET_SYMBOLS:
671 get_symbols = p->tv_u.tv_get_symbols;
672 break;
673 case LDPT_REGISTER_CLEANUP_HOOK:
674 register_cleanup = p->tv_u.tv_register_cleanup;
675 break;
676 case LDPT_ADD_INPUT_FILE:
677 add_input_file = p->tv_u.tv_add_input_file;
678 break;
d520c7fb
RAE
679 case LDPT_ADD_INPUT_LIBRARY:
680 add_input_library = p->tv_u.tv_add_input_library;
681 break;
d7f09764
DN
682 case LDPT_OPTION:
683 process_option (p->tv_u.tv_string);
684 break;
685 default:
686 break;
687 }
688 p++;
689 }
690
33662270
RAE
691 check (register_claim_file, LDPL_FATAL, "register_claim_file not found");
692 check (add_symbols, LDPL_FATAL, "add_symbols not found");
d7f09764 693 status = register_claim_file (claim_file_handler);
33662270
RAE
694 check (status == LDPS_OK, LDPL_FATAL,
695 "could not register the claim_file callback");
d7f09764
DN
696
697 if (register_cleanup)
698 {
699 status = register_cleanup (cleanup_handler);
33662270
RAE
700 check (status == LDPS_OK, LDPL_FATAL,
701 "could not register the cleanup callback");
d7f09764
DN
702 }
703
704 if (register_all_symbols_read)
705 {
33662270 706 check (get_symbols, LDPL_FATAL, "get_symbols not found");
d7f09764 707 status = register_all_symbols_read (all_symbols_read_handler);
33662270
RAE
708 check (status == LDPS_OK, LDPL_FATAL,
709 "could not register the all_symbols_read callback");
d7f09764
DN
710 }
711
d7f09764
DN
712 return LDPS_OK;
713}