1/* LTO plugin for linkers like gold, GNU ld or mold.
2 Copyright (C) 2009-2024 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. A linker passes it an array of
20 function that the plugin uses to communicate back to the linker.
21
22 With the functions provided by the linker, the plugin can be notified when
23 the linker first analyzes a file and pass a symbol table back to the linker. 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 options at his 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 -linker-output-known: Do not determine linker output
35 -linker-output-auto-nolto-rel: Switch from rel to nolto-rel mode without
36 warning. This is used on systems like VxWorks (kernel) where the link is
37 always partial and repeated incremental linking is generally not used.
38 -sym-style={none,win32,underscore|uscore}
39 -pass-through */
40
41#ifdef HAVE_CONFIG_H
42#include "config.h"
43#endif
44#if HAVE_STDINT_H
45#include <stdint.h>
46#endif
47#include <stdbool.h>
48#include <assert.h>
49#include <errno.h>
50#include <string.h>
51#include <stdlib.h>
52#include <stdio.h>
53#include <inttypes.h>
54#include <sys/stat.h>
55#include <unistd.h>
56#include <fcntl.h>
57#include <sys/types.h>
58#if HAVE_PTHREAD_LOCKING
59#include <pthread.h>
60#endif
61#ifdef HAVE_SYS_WAIT_H
62#include <sys/wait.h>
63#endif
64#ifndef WIFEXITED
65#define WIFEXITED(S) (((S) & 0xff) == 0)
66#endif
67#ifndef WEXITSTATUS
68#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
69#endif
70#include <libiberty.h>
71#include <hashtab.h>
72#include "../gcc/lto/common.h"
73#include "simple-object.h"
74#include "plugin-api.h"
75
76/* We need to use I64 instead of ll width-specifier on native Windows.
77 The reason for this is that older MS-runtimes don't support the ll. */
78#ifdef __MINGW32__
79#define PRI_LL "I64"
80#else
81#define PRI_LL "ll"
82#endif
83
84/* Handle opening elf files on hosts, such as Windows, that may use
85 text file handling that will break binary access. */
86#ifndef O_BINARY
87# define O_BINARY 0
88#endif
89
90/* Segment name for LTO sections. This is only used for Mach-O.
91 FIXME: This needs to be kept in sync with darwin.c. */
92
93#define LTO_SEGMENT_NAME "__GNU_LTO"
94
95/* Return true if STR string starts with PREFIX. */
96
97static inline bool
98startswith (const char *str, const char *prefix)
99{
100 return strncmp (s1: str, s2: prefix, n: strlen (s: prefix)) == 0;
101}
102
103/* The part of the symbol table the plugin has to keep track of. Note that we
104 must keep SYMS until all_symbols_read is called to give the linker time to
105 copy the symbol information.
106 The id must be 64bit to minimze collisions. */
107
108struct sym_aux
109{
110 uint32_t slot;
111 unsigned long long id;
112 unsigned next_conflict;
113};
114
115struct plugin_symtab
116{
117 int nsyms;
118 int last_sym;
119 struct sym_aux *aux;
120 struct ld_plugin_symbol *syms;
121 unsigned long long id;
122};
123
124/* Encapsulates object file data during symbol scan. */
125struct plugin_objfile
126{
127 int found;
128 bool offload;
129 simple_object_read *objfile;
130 struct plugin_symtab *out;
131 const struct ld_plugin_input_file *file;
132};
133
134/* All that we have to remember about a file. */
135
136struct plugin_file_info
137{
138 char *name;
139 void *handle;
140 struct plugin_symtab symtab;
141 struct plugin_symtab conflicts;
142 bool skip_file;
143};
144
145/* List item with name of the file with offloading. */
146
147struct plugin_offload_file
148{
149 char *name;
150 struct plugin_offload_file *next;
151};
152
153/* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
154 stdio file streams, we do simple label translation here. */
155
156enum symbol_style
157{
158 ss_none, /* No underscore prefix. */
159 ss_win32, /* Underscore prefix any symbol not beginning with '@'. */
160 ss_uscore, /* Underscore prefix all symbols. */
161};
162
163#if HAVE_PTHREAD_LOCKING
164/* Plug-in mutex. */
165static pthread_mutex_t plugin_lock;
166
167#define LOCK_SECTION pthread_mutex_lock (&plugin_lock)
168#define UNLOCK_SECTION pthread_mutex_unlock (&plugin_lock)
169#else
170#define LOCK_SECTION
171#define UNLOCK_SECTION
172#endif
173
174static char *arguments_file_name;
175static ld_plugin_register_claim_file register_claim_file;
176static ld_plugin_register_claim_file_v2 register_claim_file_v2;
177static ld_plugin_register_all_symbols_read register_all_symbols_read;
178static ld_plugin_get_symbols get_symbols, get_symbols_v2, get_symbols_v3;
179static ld_plugin_register_cleanup register_cleanup;
180static ld_plugin_add_input_file add_input_file;
181static ld_plugin_add_input_library add_input_library;
182static ld_plugin_message message;
183static ld_plugin_add_symbols add_symbols, add_symbols_v2;
184static ld_plugin_get_api_version get_api_version;
185
186/* By default, use version LAPI_V0 if there is not negotiation. */
187static enum linker_api_version api_version = LAPI_V0;
188
189static struct plugin_file_info *claimed_files = NULL;
190static unsigned int num_claimed_files = 0;
191static unsigned int non_claimed_files = 0;
192
193/* List of files with offloading. */
194static struct plugin_offload_file *offload_files;
195/* Last file in the list. */
196static struct plugin_offload_file *offload_files_last;
197/* Last non-archive file in the list. */
198static struct plugin_offload_file *offload_files_last_obj;
199/* Last LTO file in the list. */
200static struct plugin_offload_file *offload_files_last_lto;
201/* Total number of files with offloading. */
202static unsigned num_offload_files;
203
204static char **output_files = NULL;
205static unsigned int num_output_files = 0;
206
207static char **lto_wrapper_argv;
208static int lto_wrapper_num_args;
209
210static char **pass_through_items = NULL;
211static unsigned int num_pass_through_items;
212
213static char *ltrans_objects = NULL;
214
215static bool debug;
216static bool save_temps;
217static bool verbose;
218static char nop;
219static char *resolution_file = NULL;
220static enum ld_plugin_output_file_type linker_output;
221static bool linker_output_set;
222static bool linker_output_known;
223static bool linker_output_auto_nolto_rel;
224static const char *link_output_name = NULL;
225
226/* This indicates link_output_name already contains the dot of the
227 suffix, so we can skip it in extensions. */
228static bool skip_in_suffix = false;
229
230/* The version of gold being used, or -1 if not gold. The number is
231 MAJOR * 100 + MINOR. */
232static int gold_version = -1;
233
234/* Not used by default, but can be overridden at runtime
235 by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
236 (in fact, only first letter of style arg is checked.) */
237static enum symbol_style sym_style = ss_none;
238
239static void
240check_1 (int gate, enum ld_plugin_level level, const char *text)
241{
242 if (gate)
243 return;
244
245 if (message)
246 message (level, text);
247 else
248 {
249 /* If there is no nicer way to inform the user, fallback to stderr. */
250 fprintf (stderr, format: "%s\n", text);
251 if (level == LDPL_FATAL)
252 abort ();
253 }
254}
255
256/* This little wrapper allows check to be called with a non-integer
257 first argument, such as a pointer that must be non-NULL. We can't
258 use c99 bool type to coerce it into range, so we explicitly test. */
259#define check(GATE, LEVEL, TEXT) check_1 (((GATE) != 0), (LEVEL), (TEXT))
260
261/* Parse an entry of the IL symbol table. The data to be parsed is pointed
262 by P and the result is written in ENTRY. The slot number is stored in SLOT.
263 Returns the address of the next entry. */
264
265static char *
266parse_table_entry (char *p, struct ld_plugin_symbol *entry,
267 struct sym_aux *aux)
268{
269 unsigned char t;
270 enum ld_plugin_symbol_kind translate_kind[] =
271 {
272 LDPK_DEF,
273 LDPK_WEAKDEF,
274 LDPK_UNDEF,
275 LDPK_WEAKUNDEF,
276 LDPK_COMMON
277 };
278
279 enum ld_plugin_symbol_visibility translate_visibility[] =
280 {
281 LDPV_DEFAULT,
282 LDPV_PROTECTED,
283 LDPV_INTERNAL,
284 LDPV_HIDDEN
285 };
286
287 switch (sym_style)
288 {
289 case ss_win32:
290 if (p[0] == '@')
291 {
292 /* cf. Duff's device. */
293 case ss_none:
294 entry->name = xstrdup (p);
295 break;
296 }
297 /* FALL-THROUGH. */
298 case ss_uscore:
299 entry->name = concat ("_", p, NULL);
300 break;
301 default:
302 check (0, LDPL_FATAL, "invalid symbol style requested");
303 break;
304 }
305 while (*p)
306 p++;
307 p++;
308
309 entry->version = NULL;
310
311 entry->comdat_key = p;
312 while (*p)
313 p++;
314 p++;
315
316 if (strlen (s: entry->comdat_key) == 0)
317 entry->comdat_key = NULL;
318 else
319 entry->comdat_key = xstrdup (entry->comdat_key);
320
321 entry->unused = entry->section_kind = entry->symbol_type = 0;
322
323 t = *p;
324 check (t <= 4, LDPL_FATAL, "invalid symbol kind found");
325 entry->def = translate_kind[t];
326 p++;
327
328 t = *p;
329 check (t <= 3, LDPL_FATAL, "invalid symbol visibility found");
330 entry->visibility = translate_visibility[t];
331 p++;
332
333 memcpy (dest: &entry->size, src: p, n: sizeof (uint64_t));
334 p += 8;
335
336 memcpy (dest: &aux->slot, src: p, n: sizeof (uint32_t));
337 p += 4;
338
339 entry->resolution = LDPR_UNKNOWN;
340
341 aux->next_conflict = -1;
342
343 return p;
344}
345
346/* Parse an entry of the IL symbol table. The data to be parsed is pointed
347 by P and the result is written in ENTRY. The slot number is stored in SLOT.
348 Returns the address of the next entry. */
349
350static char *
351parse_table_entry_extension (char *p, struct ld_plugin_symbol *entry)
352{
353 unsigned char t;
354 enum ld_plugin_symbol_type symbol_types[] =
355 {
356 LDST_UNKNOWN,
357 LDST_FUNCTION,
358 LDST_VARIABLE,
359 };
360
361 t = *p;
362 check (t <= 2, LDPL_FATAL, "invalid symbol type found");
363 entry->symbol_type = symbol_types[t];
364 p++;
365 entry->section_kind = *p;
366 p++;
367
368 return p;
369}
370
371
372/* Translate the IL symbol table located between DATA and END. Append the
373 slots and symbols to OUT. */
374
375static void
376translate (char *data, char *end, struct plugin_symtab *out)
377{
378 struct sym_aux *aux;
379 struct ld_plugin_symbol *syms = NULL;
380 int n, len;
381
382 /* This overestimates the output buffer sizes, but at least
383 the algorithm is O(1) now. */
384
385 len = (end - data)/8 + out->nsyms + 1;
386 syms = xrealloc (out->syms, len * sizeof (struct ld_plugin_symbol));
387 aux = xrealloc (out->aux, len * sizeof (struct sym_aux));
388
389 for (n = out->nsyms; data < end; n++)
390 {
391 aux[n].id = out->id;
392 data = parse_table_entry (p: data, entry: &syms[n], aux: &aux[n]);
393 }
394
395 assert(n < len);
396
397 out->nsyms = n;
398 out->syms = syms;
399 out->aux = aux;
400}
401
402static void
403parse_symtab_extension (char *data, char *end, struct plugin_symtab *out)
404{
405 unsigned long i;
406 unsigned char version;
407
408 if (data >= end)
409 /* FIXME: Issue an error ? */
410 return;
411
412 version = *data;
413 data++;
414
415 if (version != 1)
416 return;
417
418 /* Version 1 contains the following data per entry:
419 - symbol_type
420 - section_kind
421 . */
422
423 unsigned long nsyms = (end - data) / 2;
424
425 for (i = 0; i < nsyms; i++)
426 data = parse_table_entry_extension (p: data, entry: out->syms + i + out->last_sym);
427
428 out->last_sym += nsyms;
429}
430
431/* Free all memory that is no longer needed after writing the symbol
432 resolution. */
433
434static void
435free_1 (struct plugin_file_info *files, unsigned num_files)
436{
437 unsigned int i;
438 for (i = 0; i < num_files; i++)
439 {
440 struct plugin_file_info *info = &files[i];
441 struct plugin_symtab *symtab = &info->symtab;
442 unsigned int j;
443 for (j = 0; j < symtab->nsyms; j++)
444 {
445 struct ld_plugin_symbol *s = &symtab->syms[j];
446 free (ptr: s->name);
447 free (ptr: s->comdat_key);
448 }
449 free (ptr: symtab->syms);
450 symtab->syms = NULL;
451 }
452}
453
454/* Free all remaining memory. */
455
456static void
457free_2 (void)
458{
459 unsigned int i;
460 for (i = 0; i < num_claimed_files; i++)
461 {
462 struct plugin_file_info *info = &claimed_files[i];
463 struct plugin_symtab *symtab = &info->symtab;
464 free (ptr: symtab->aux);
465 free (ptr: info->name);
466 }
467
468 for (i = 0; i < num_output_files; i++)
469 free (ptr: output_files[i]);
470 free (ptr: output_files);
471
472 free (ptr: claimed_files);
473 claimed_files = NULL;
474 num_claimed_files = 0;
475
476 while (offload_files)
477 {
478 struct plugin_offload_file *ofld = offload_files;
479 offload_files = offload_files->next;
480 free (ptr: ofld);
481 }
482 num_offload_files = 0;
483
484 free (ptr: arguments_file_name);
485 arguments_file_name = NULL;
486}
487
488/* Dump SYMTAB to resolution file F. */
489
490static void
491dump_symtab (FILE *f, struct plugin_symtab *symtab)
492{
493 unsigned j;
494
495 for (j = 0; j < symtab->nsyms; j++)
496 {
497 uint32_t slot = symtab->aux[j].slot;
498 unsigned int resolution = symtab->syms[j].resolution;
499
500 assert (resolution != LDPR_UNKNOWN);
501
502 fprintf (stream: f, format: "%u %" PRI_LL "x %s %s\n",
503 (unsigned int) slot, symtab->aux[j].id,
504 lto_resolution_str[resolution],
505 symtab->syms[j].name);
506 }
507}
508
509/* Finish the conflicts' resolution information after the linker resolved
510 the original symbols */
511
512static void
513finish_conflict_resolution (struct plugin_symtab *symtab,
514 struct plugin_symtab *conflicts)
515{
516 int i, j;
517
518 if (conflicts->nsyms == 0)
519 return;
520
521 for (i = 0; i < symtab->nsyms; i++)
522 {
523 char resolution = LDPR_UNKNOWN;
524
525 if (symtab->aux[i].next_conflict == -1)
526 continue;
527
528 switch (symtab->syms[i].def)
529 {
530 case LDPK_DEF:
531 case LDPK_COMMON: /* ??? */
532 resolution = LDPR_RESOLVED_IR;
533 break;
534 case LDPK_WEAKDEF:
535 resolution = LDPR_PREEMPTED_IR;
536 break;
537 case LDPK_UNDEF:
538 case LDPK_WEAKUNDEF:
539 resolution = symtab->syms[i].resolution;
540 break;
541 default:
542 assert (0);
543 }
544
545 assert (resolution != LDPR_UNKNOWN);
546
547 for (j = symtab->aux[i].next_conflict;
548 j != -1;
549 j = conflicts->aux[j].next_conflict)
550 conflicts->syms[j].resolution = resolution;
551 }
552}
553
554/* Free symbol table SYMTAB. */
555
556static void
557free_symtab (struct plugin_symtab *symtab)
558{
559 free (ptr: symtab->syms);
560 symtab->syms = NULL;
561 free (ptr: symtab->aux);
562 symtab->aux = NULL;
563}
564
565/* Writes the relocations to disk. */
566
567static void
568write_resolution (void)
569{
570 unsigned int i, included_files = 0;
571 FILE *f;
572
573 check (resolution_file, LDPL_FATAL, "resolution file not specified");
574 f = fopen (filename: resolution_file, modes: "w");
575 check (f, LDPL_FATAL, "could not open file");
576
577 for (i = 0; i < num_claimed_files; i++)
578 {
579 struct plugin_file_info *info = &claimed_files[i];
580 struct plugin_symtab *symtab = &info->symtab;
581 struct ld_plugin_symbol *syms = symtab->syms;
582
583 /* Version 2 of API supports IRONLY_EXP resolution that is
584 accepted by GCC-4.7 and newer.
585 Version 3 can return LDPS_NO_SYMS that means the object
586 will not be used at all. */
587 if (get_symbols_v3)
588 {
589 enum ld_plugin_status status
590 = get_symbols_v3 (info->handle, symtab->nsyms, syms);
591 if (status == LDPS_NO_SYMS)
592 {
593 info->skip_file = true;
594 continue;
595 }
596 }
597 else if (get_symbols_v2)
598 get_symbols_v2 (info->handle, symtab->nsyms, syms);
599 else
600 get_symbols (info->handle, symtab->nsyms, syms);
601
602 ++included_files;
603
604 finish_conflict_resolution (symtab, conflicts: &info->conflicts);
605 }
606
607 fprintf (stream: f, format: "%d\n", included_files);
608
609 for (i = 0; i < num_claimed_files; i++)
610 {
611 struct plugin_file_info *info = &claimed_files[i];
612 struct plugin_symtab *symtab = &info->symtab;
613
614 if (info->skip_file)
615 continue;
616
617 fprintf (stream: f, format: "%s %d\n", info->name, symtab->nsyms + info->conflicts.nsyms);
618 dump_symtab (f, symtab);
619 if (info->conflicts.nsyms)
620 {
621 dump_symtab (f, symtab: &info->conflicts);
622 free_symtab (symtab: &info->conflicts);
623 }
624 }
625 fclose (stream: f);
626}
627
628/* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
629 stdout. */
630
631static void
632add_output_files (FILE *f)
633{
634 for (;;)
635 {
636 const unsigned piece = 32;
637 char *buf, *s = xmalloc (piece);
638 size_t len;
639
640 buf = s;
641cont:
642 if (!fgets (s: buf, n: piece, stream: f))
643 {
644 free (ptr: s);
645 break;
646 }
647 len = strlen (s: s);
648 if (s[len - 1] != '\n')
649 {
650 s = xrealloc (s, len + piece);
651 buf = s + len;
652 goto cont;
653 }
654 s[len - 1] = '\0';
655
656 num_output_files++;
657 output_files
658 = xrealloc (output_files, num_output_files * sizeof (char *));
659 output_files[num_output_files - 1] = s;
660 add_input_file (output_files[num_output_files - 1]);
661 }
662}
663
664/* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
665 argument list. */
666
667static void
668exec_lto_wrapper (char *argv[])
669{
670 int t, i;
671 int status;
672 char *at_args;
673 FILE *args;
674 FILE *wrapper_output;
675 char *new_argv[3];
676 struct pex_obj *pex;
677 const char *errmsg;
678
679 /* Write argv to a file to avoid a command line that is too long
680 Save the file locally on save-temps. */
681 const char *suffix = ".lto_wrapper_args";
682 if (skip_in_suffix)
683 suffix++;
684 if (save_temps && link_output_name)
685 arguments_file_name = concat (link_output_name, suffix, NULL);
686 else
687 arguments_file_name = make_temp_file (".lto_wrapper_args");
688 check (arguments_file_name, LDPL_FATAL,
689 "Failed to generate a temorary file name");
690
691 args = fopen (filename: arguments_file_name, modes: "w");
692 check (args, LDPL_FATAL, "could not open arguments file");
693
694 t = writeargv (&argv[1], args);
695 check (t == 0, LDPL_FATAL, "could not write arguments");
696 t = fclose (stream: args);
697 check (t == 0, LDPL_FATAL, "could not close arguments file");
698
699 at_args = concat ("@", arguments_file_name, NULL);
700 check (at_args, LDPL_FATAL, "could not allocate");
701
702 for (i = 1; argv[i]; i++)
703 {
704 char *a = argv[i];
705 /* Check the input argument list for a verbose marker too. */
706 if (a[0] == '-' && a[1] == 'v' && a[2] == '\0')
707 {
708 verbose = true;
709 break;
710 }
711 }
712
713 if (verbose)
714 {
715 for (i = 0; argv[i]; i++)
716 fprintf (stderr, format: "%s ", argv[i]);
717 fprintf (stderr, format: "\n");
718 }
719
720 new_argv[0] = argv[0];
721 new_argv[1] = at_args;
722 new_argv[2] = NULL;
723
724 if (debug)
725 {
726 for (i = 0; new_argv[i]; i++)
727 fprintf (stderr, format: "%s ", new_argv[i]);
728 fprintf (stderr, format: "\n");
729 }
730
731 pex = pex_init (PEX_USE_PIPES, pname: "lto-wrapper", NULL);
732 check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper");
733
734 errmsg = pex_run (obj: pex, flags: 0, executable: new_argv[0], argv: new_argv, NULL, NULL, err: &t);
735 check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper");
736 check (t == 0, LDPL_FATAL, "could not run lto-wrapper");
737
738 wrapper_output = pex_read_output (pex, binary: 0);
739 check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output");
740
741 add_output_files (f: wrapper_output);
742
743 t = pex_get_status (pex, count: 1, vector: &status);
744 check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status");
745 check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL,
746 "lto-wrapper failed");
747
748 pex_free (pex);
749
750 free (ptr: at_args);
751}
752
753/* Pass the original files back to the linker. */
754
755static void
756use_original_files (void)
757{
758 unsigned i;
759 for (i = 0; i < num_claimed_files; i++)
760 {
761 struct plugin_file_info *info = &claimed_files[i];
762 add_input_file (info->name);
763 }
764}
765
766
767/* Called by the linker once all symbols have been read. */
768
769static enum ld_plugin_status
770all_symbols_read_handler (void)
771{
772 const unsigned num_lto_args
773 = num_claimed_files + lto_wrapper_num_args + 2
774 + !linker_output_known + !linker_output_auto_nolto_rel;
775 unsigned i;
776 char **lto_argv;
777 const char *linker_output_str = NULL;
778 const char **lto_arg_ptr;
779 if (num_claimed_files + num_offload_files == 0)
780 return LDPS_OK;
781
782 if (nop)
783 {
784 use_original_files ();
785 return LDPS_OK;
786 }
787
788 if (ltrans_objects)
789 {
790 FILE *objs = fopen (filename: ltrans_objects, modes: "r");
791 add_output_files (f: objs);
792 fclose (stream: objs);
793 return LDPS_OK;
794 }
795
796 lto_argv = (char **) xcalloc (sizeof (char *), num_lto_args);
797 lto_arg_ptr = (const char **) lto_argv;
798 assert (lto_wrapper_argv);
799
800 write_resolution ();
801
802 free_1 (files: claimed_files, num_files: num_claimed_files);
803
804 for (i = 0; i < lto_wrapper_num_args; i++)
805 *lto_arg_ptr++ = lto_wrapper_argv[i];
806
807 if (!linker_output_known)
808 {
809 assert (linker_output_set);
810 switch (linker_output)
811 {
812 case LDPO_REL:
813 if (non_claimed_files)
814 {
815 if (!linker_output_auto_nolto_rel)
816 message (LDPL_WARNING, "incremental linking of LTO and non-LTO"
817 " objects; using -flinker-output=nolto-rel which will"
818 " bypass whole program optimization");
819 linker_output_str = "-flinker-output=nolto-rel";
820 }
821 else
822 linker_output_str = "-flinker-output=rel";
823 break;
824 case LDPO_DYN:
825 linker_output_str = "-flinker-output=dyn";
826 break;
827 case LDPO_PIE:
828 linker_output_str = "-flinker-output=pie";
829 break;
830 case LDPO_EXEC:
831 linker_output_str = "-flinker-output=exec";
832 break;
833 default:
834 message (LDPL_FATAL, "unsupported linker output %i", linker_output);
835 break;
836 }
837 *lto_arg_ptr++ = xstrdup (linker_output_str);
838 }
839
840 if (num_offload_files > 0)
841 {
842 FILE *f;
843 char *arg;
844 char *offload_objects_file_name;
845 struct plugin_offload_file *ofld;
846 const char *suffix = ".ofldlist";
847
848 if (save_temps && link_output_name)
849 {
850 suffix += skip_in_suffix;
851 offload_objects_file_name = concat (link_output_name, suffix, NULL);
852 }
853 else
854 offload_objects_file_name = make_temp_file (suffix);
855 check (offload_objects_file_name, LDPL_FATAL,
856 "Failed to generate a temporary file name");
857 f = fopen (filename: offload_objects_file_name, modes: "w");
858 check (f, LDPL_FATAL, "could not open file with offload objects");
859 fprintf (stream: f, format: "%u\n", num_offload_files);
860
861 /* Skip the dummy item at the start of the list. */
862 ofld = offload_files->next;
863 while (ofld)
864 {
865 fprintf (stream: f, format: "%s\n", ofld->name);
866 ofld = ofld->next;
867 }
868 fclose (stream: f);
869
870 arg = concat ("-foffload-objects=", offload_objects_file_name, NULL);
871 check (arg, LDPL_FATAL, "could not allocate");
872 *lto_arg_ptr++ = arg;
873 }
874
875 for (i = 0; i < num_claimed_files; i++)
876 {
877 struct plugin_file_info *info = &claimed_files[i];
878
879 if (!info->skip_file)
880 *lto_arg_ptr++ = info->name;
881 }
882
883 *lto_arg_ptr++ = NULL;
884 exec_lto_wrapper (argv: lto_argv);
885
886 free (ptr: lto_argv);
887
888 /* --pass-through is not needed when using gold 1.11 or later. */
889 if (pass_through_items && gold_version < 111)
890 {
891 unsigned int i;
892 for (i = 0; i < num_pass_through_items; i++)
893 {
894 if (startswith (str: pass_through_items[i], prefix: "-l"))
895 add_input_library (pass_through_items[i] + 2);
896 else
897 add_input_file (pass_through_items[i]);
898 free (ptr: pass_through_items[i]);
899 pass_through_items[i] = NULL;
900 }
901 free (ptr: pass_through_items);
902 pass_through_items = NULL;
903 }
904
905 return LDPS_OK;
906}
907
908/* Helper, as used in collect2. */
909static int
910file_exists (const char *name)
911{
912 return access (name: name, R_OK) == 0;
913}
914
915/* Unlink FILE unless we have save-temps set.
916 Note that we're saving files if verbose output is set. */
917
918static void
919maybe_unlink (const char *file)
920{
921 if (save_temps && file_exists (name: file))
922 {
923 if (verbose)
924 fprintf (stderr, format: "[Leaving %s]\n", file);
925 return;
926 }
927
928 unlink_if_ordinary (file);
929}
930
931/* Remove temporary files at the end of the link. */
932
933static enum ld_plugin_status
934cleanup_handler (void)
935{
936 unsigned int i;
937
938 if (debug)
939 return LDPS_OK;
940
941 if (arguments_file_name)
942 maybe_unlink (file: arguments_file_name);
943
944 for (i = 0; i < num_output_files; i++)
945 maybe_unlink (file: output_files[i]);
946
947 free_2 ();
948 return LDPS_OK;
949}
950
951#define SWAP(type, a, b) \
952 do { type tmp_; tmp_ = (a); (a) = (b); (b) = tmp_; } while(0)
953
954/* Compare two hash table entries */
955
956static int eq_sym (const void *a, const void *b)
957{
958 const struct ld_plugin_symbol *as = (const struct ld_plugin_symbol *)a;
959 const struct ld_plugin_symbol *bs = (const struct ld_plugin_symbol *)b;
960
961 return !strcmp (s1: as->name, s2: bs->name);
962}
963
964/* Hash a symbol */
965
966static hashval_t hash_sym (const void *a)
967{
968 const struct ld_plugin_symbol *as = (const struct ld_plugin_symbol *)a;
969
970 return htab_hash_string (as->name);
971}
972
973/* Determine how strong a symbol is */
974
975static int symbol_strength (struct ld_plugin_symbol *s)
976{
977 switch (s->def)
978 {
979 case LDPK_UNDEF:
980 case LDPK_WEAKUNDEF:
981 return 0;
982 case LDPK_WEAKDEF:
983 return 1;
984 default:
985 return 2;
986 }
987}
988
989/* In the ld -r case we can get dups in the LTO symbol tables, where
990 the same symbol can have different resolutions (e.g. undefined and defined).
991
992 We have to keep that in the LTO symbol tables, but the dups confuse
993 gold and then finally gcc by supplying incorrect resolutions.
994
995 Problem is that the main gold symbol table doesn't know about subids
996 and does not distingush the same symbols in different states.
997
998 So we drop duplicates from the linker visible symbol table
999 and keep them in a private table. Then later do own symbol
1000 resolution for the duplicated based on the results for the
1001 originals.
1002
1003 Then when writing out the resolution file readd the dropped symbols.
1004
1005 XXX how to handle common? */
1006
1007static void
1008resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
1009{
1010 htab_t symtab = htab_create (t->nsyms, hash_sym, eq_sym, NULL);
1011 int i;
1012 int out;
1013 int outlen;
1014
1015 outlen = t->nsyms;
1016 conflicts->syms = xmalloc (sizeof (struct ld_plugin_symbol) * outlen);
1017 conflicts->aux = xmalloc (sizeof (struct sym_aux) * outlen);
1018
1019 /* Move all duplicate symbols into the auxiliary conflicts table. */
1020 out = 0;
1021 for (i = 0; i < t->nsyms; i++)
1022 {
1023 struct ld_plugin_symbol *s = &t->syms[i];
1024 struct sym_aux *aux = &t->aux[i];
1025 void **slot;
1026
1027 slot = htab_find_slot (symtab, s, INSERT);
1028 if (*slot != NULL)
1029 {
1030 int cnf;
1031 struct ld_plugin_symbol *orig = (struct ld_plugin_symbol *)*slot;
1032 struct sym_aux *orig_aux = &t->aux[orig - t->syms];
1033
1034 /* Always let the linker resolve the strongest symbol */
1035 if (symbol_strength (s: orig) < symbol_strength (s))
1036 {
1037 SWAP (struct ld_plugin_symbol, *orig, *s);
1038 SWAP (uint32_t, orig_aux->slot, aux->slot);
1039 SWAP (unsigned long long, orig_aux->id, aux->id);
1040 /* Don't swap conflict chain pointer */
1041 }
1042
1043 /* Move current symbol into the conflicts table */
1044 cnf = conflicts->nsyms++;
1045 conflicts->syms[cnf] = *s;
1046 conflicts->aux[cnf] = *aux;
1047 aux = &conflicts->aux[cnf];
1048
1049 /* Update conflicts chain of the original symbol */
1050 aux->next_conflict = orig_aux->next_conflict;
1051 orig_aux->next_conflict = cnf;
1052
1053 continue;
1054 }
1055
1056 /* Remove previous duplicates in the main table */
1057 if (out < i)
1058 {
1059 t->syms[out] = *s;
1060 t->aux[out] = *aux;
1061 }
1062
1063 /* Put original into the hash table */
1064 *slot = &t->syms[out];
1065 out++;
1066 }
1067
1068 assert (conflicts->nsyms <= outlen);
1069 assert (conflicts->nsyms + out == t->nsyms);
1070
1071 t->nsyms = out;
1072 htab_delete (symtab);
1073}
1074
1075/* Process one section of an object file. */
1076
1077static int
1078process_symtab (void *data, const char *name, off_t offset, off_t length)
1079{
1080 struct plugin_objfile *obj = (struct plugin_objfile *)data;
1081 char *s;
1082 char *secdatastart, *secdata;
1083
1084 if (!startswith (str: name, prefix: ".gnu.lto_.symtab"))
1085 return 1;
1086
1087 s = strrchr (s: name, c: '.');
1088 if (s)
1089 sscanf (s: s, format: ".%" PRI_LL "x", &obj->out->id);
1090 secdata = secdatastart = xmalloc (length);
1091 offset += obj->file->offset;
1092 if (offset != lseek (fd: obj->file->fd, offset: offset, SEEK_SET))
1093 goto err;
1094
1095 do
1096 {
1097 ssize_t got = read (fd: obj->file->fd, buf: secdata, nbytes: length);
1098 if (got == 0)
1099 break;
1100 else if (got > 0)
1101 {
1102 secdata += got;
1103 length -= got;
1104 }
1105 else if (errno != EINTR)
1106 goto err;
1107 }
1108 while (length > 0);
1109 if (length > 0)
1110 goto err;
1111
1112 translate (data: secdatastart, end: secdata, out: obj->out);
1113 obj->found++;
1114 free (ptr: secdatastart);
1115 return 1;
1116
1117err:
1118 if (message)
1119 message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
1120 /* Force claim_file_handler to abandon this file. */
1121 obj->found = 0;
1122 free (ptr: secdatastart);
1123 return 0;
1124}
1125
1126/* Process one section of an object file. */
1127
1128static int
1129process_symtab_extension (void *data, const char *name, off_t offset,
1130 off_t length)
1131{
1132 struct plugin_objfile *obj = (struct plugin_objfile *)data;
1133 char *s;
1134 char *secdatastart, *secdata;
1135
1136 if (!startswith (str: name, prefix: ".gnu.lto_.ext_symtab"))
1137 return 1;
1138
1139 s = strrchr (s: name, c: '.');
1140 if (s)
1141 sscanf (s: s, format: ".%" PRI_LL "x", &obj->out->id);
1142 secdata = secdatastart = xmalloc (length);
1143 offset += obj->file->offset;
1144 if (offset != lseek (fd: obj->file->fd, offset: offset, SEEK_SET))
1145 goto err;
1146
1147 do
1148 {
1149 ssize_t got = read (fd: obj->file->fd, buf: secdata, nbytes: length);
1150 if (got == 0)
1151 break;
1152 else if (got > 0)
1153 {
1154 secdata += got;
1155 length -= got;
1156 }
1157 else if (errno != EINTR)
1158 goto err;
1159 }
1160 while (length > 0);
1161 if (length > 0)
1162 goto err;
1163
1164 parse_symtab_extension (data: secdatastart, end: secdata, out: obj->out);
1165 obj->found++;
1166 free (ptr: secdatastart);
1167 return 1;
1168
1169err:
1170 if (message)
1171 message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
1172 /* Force claim_file_handler to abandon this file. */
1173 obj->found = 0;
1174 free (ptr: secdatastart);
1175 return 0;
1176}
1177
1178
1179/* Find an offload section of an object file. */
1180
1181static int
1182process_offload_section (void *data, const char *name, off_t offset, off_t len)
1183{
1184 if (startswith (str: name, prefix: ".gnu.offload_lto_.opts"))
1185 {
1186 struct plugin_objfile *obj = (struct plugin_objfile *) data;
1187 obj->offload = true;
1188 return 0;
1189 }
1190
1191 return 1;
1192}
1193
1194/* Callback used by a linker to check if the plugin will claim FILE. Writes
1195 the result in CLAIMED. If KNOWN_USED, the object is known by the linker
1196 to be used, or an older API version is in use that does not provide that
1197 information; otherwise, the linker is only determining whether this is
1198 a plugin object and it should not be registered as having offload data if
1199 not claimed by the plugin. */
1200
1201static enum ld_plugin_status
1202claim_file_handler_v2 (const struct ld_plugin_input_file *file, int *claimed,
1203 int known_used)
1204{
1205 enum ld_plugin_status status;
1206 struct plugin_objfile obj;
1207 struct plugin_file_info lto_file;
1208 int err;
1209 const char *errmsg;
1210
1211 memset (s: &lto_file, c: 0, n: sizeof (struct plugin_file_info));
1212
1213 if (file->offset != 0)
1214 {
1215 /* We pass the offset of the actual file, not the archive header.
1216 Can't use PRIx64, because that's C99, so we have to print the
1217 64-bit hex int as two 32-bit ones. Use xasprintf instead of
1218 asprintf because asprintf doesn't work as expected on some older
1219 mingw32 hosts. */
1220 int lo, hi;
1221 lo = file->offset & 0xffffffff;
1222 hi = ((int64_t)file->offset >> 32) & 0xffffffff;
1223 lto_file.name = hi ? xasprintf ("%s@0x%x%08x", file->name, hi, lo)
1224 : xasprintf ("%s@0x%x", file->name, lo);
1225 }
1226 else
1227 {
1228 lto_file.name = xstrdup (file->name);
1229 }
1230 lto_file.handle = file->handle;
1231
1232 *claimed = 0;
1233 obj.file = file;
1234 obj.found = 0;
1235 obj.offload = false;
1236 obj.out = &lto_file.symtab;
1237 errmsg = NULL;
1238 obj.objfile = simple_object_start_read (descriptor: file->fd, offset: file->offset, LTO_SEGMENT_NAME,
1239 errmsg: &errmsg, err: &err);
1240 /* No file, but also no error code means unrecognized format; just skip it. */
1241 if (!obj.objfile && !err)
1242 goto err;
1243
1244 if (obj.objfile)
1245 {
1246 errmsg = simple_object_find_sections (simple_object: obj.objfile, pfn: process_symtab, data: &obj,
1247 err: &err);
1248 /* Parsing symtab extension should be done only for add_symbols_v2 and
1249 later versions. */
1250 if (!errmsg && add_symbols_v2 != NULL)
1251 {
1252 obj.out->last_sym = 0;
1253 errmsg = simple_object_find_sections (simple_object: obj.objfile,
1254 pfn: process_symtab_extension,
1255 data: &obj, err: &err);
1256 }
1257 }
1258
1259 if (!obj.objfile || errmsg)
1260 {
1261 if (err && message)
1262 message (LDPL_FATAL, "%s: %s: %s", file->name, errmsg,
1263 xstrerror (err));
1264 else if (message)
1265 message (LDPL_FATAL, "%s: %s", file->name, errmsg);
1266 goto err;
1267 }
1268
1269 if (obj.objfile)
1270 simple_object_find_sections (simple_object: obj.objfile, pfn: process_offload_section,
1271 data: &obj, err: &err);
1272
1273 if (obj.found == 0 && !obj.offload)
1274 goto err;
1275
1276 if (obj.found > 1)
1277 resolve_conflicts (t: &lto_file.symtab, conflicts: &lto_file.conflicts);
1278
1279 if (obj.found > 0)
1280 {
1281 if (add_symbols_v2)
1282 status = add_symbols_v2 (file->handle, lto_file.symtab.nsyms,
1283 lto_file.symtab.syms);
1284 else
1285 status = add_symbols (file->handle, lto_file.symtab.nsyms,
1286 lto_file.symtab.syms);
1287 check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
1288
1289 LOCK_SECTION;
1290 num_claimed_files++;
1291 claimed_files =
1292 xrealloc (claimed_files,
1293 num_claimed_files * sizeof (struct plugin_file_info));
1294 claimed_files[num_claimed_files - 1] = lto_file;
1295 UNLOCK_SECTION;
1296
1297 *claimed = 1;
1298 }
1299
1300 LOCK_SECTION;
1301 if (offload_files == NULL)
1302 {
1303 /* Add dummy item to the start of the list. */
1304 offload_files = xmalloc (sizeof (struct plugin_offload_file));
1305 offload_files->name = NULL;
1306 offload_files->next = NULL;
1307 offload_files_last = offload_files;
1308 }
1309
1310 /* If this is an LTO file without offload, and it is the first LTO file, save
1311 the pointer to the last offload file in the list. Further offload LTO
1312 files will be inserted after it, if any. */
1313 if (*claimed && !obj.offload && offload_files_last_lto == NULL)
1314 offload_files_last_lto = offload_files_last;
1315
1316 if (obj.offload && (known_used || obj.found > 0))
1317 {
1318 /* Add file to the list. The order must be exactly the same as the final
1319 order after recompilation and linking, otherwise host and target tables
1320 with addresses wouldn't match. If a static library contains both LTO
1321 and non-LTO objects, ld and gold link them in a different order. */
1322 struct plugin_offload_file *ofld
1323 = xmalloc (sizeof (struct plugin_offload_file));
1324 ofld->name = lto_file.name;
1325 ofld->next = NULL;
1326
1327 if (*claimed && offload_files_last_lto == NULL && file->offset != 0
1328 && gold_version == -1)
1329 {
1330 /* ld only: insert first LTO file from the archive after the last real
1331 object file immediately preceding the archive, or at the begin of
1332 the list if there was no real objects before archives. */
1333 if (offload_files_last_obj != NULL)
1334 {
1335 ofld->next = offload_files_last_obj->next;
1336 offload_files_last_obj->next = ofld;
1337 }
1338 else
1339 {
1340 ofld->next = offload_files->next;
1341 offload_files->next = ofld;
1342 }
1343 }
1344 else if (*claimed && offload_files_last_lto != NULL)
1345 {
1346 /* Insert LTO file after the last LTO file in the list. */
1347 ofld->next = offload_files_last_lto->next;
1348 offload_files_last_lto->next = ofld;
1349 }
1350 else
1351 /* Add non-LTO file or first non-archive LTO file to the end of the
1352 list. */
1353 offload_files_last->next = ofld;
1354
1355 if (ofld->next == NULL)
1356 offload_files_last = ofld;
1357 if (file->offset == 0)
1358 offload_files_last_obj = ofld;
1359 if (*claimed)
1360 offload_files_last_lto = ofld;
1361 num_offload_files++;
1362 }
1363
1364 UNLOCK_SECTION;
1365
1366 goto cleanup;
1367
1368 err:
1369 LOCK_SECTION;
1370 non_claimed_files++;
1371 UNLOCK_SECTION;
1372 free (ptr: lto_file.name);
1373
1374 cleanup:
1375 if (obj.objfile)
1376 simple_object_release_read (obj.objfile);
1377
1378 return LDPS_OK;
1379}
1380
1381/* Callback used by a linker to check if the plugin will claim FILE. Writes
1382 the result in CLAIMED. */
1383
1384static enum ld_plugin_status
1385claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
1386{
1387 return claim_file_handler_v2 (file, claimed, known_used: true);
1388}
1389
1390/* Parse the plugin options. */
1391
1392static void
1393process_option (const char *option)
1394{
1395 if (strcmp (s1: option, s2: "-linker-output-known") == 0)
1396 linker_output_known = true;
1397 /* Also accept "notlo" for backwards compatibility. */
1398 else if ((strcmp (s1: option, s2: "-linker-output-auto-nolto-rel") == 0)
1399 || (strcmp (s1: option, s2: "-linker-output-auto-notlo-rel") == 0))
1400 linker_output_auto_nolto_rel = true;
1401 else if (strcmp (s1: option, s2: "-debug") == 0)
1402 debug = true;
1403 else if ((strcmp (s1: option, s2: "-v") == 0)
1404 || (strcmp (s1: option, s2: "--verbose") == 0))
1405 verbose = true;
1406 else if (strcmp (s1: option, s2: "-save-temps") == 0)
1407 save_temps = true;
1408 else if (strcmp (s1: option, s2: "-nop") == 0)
1409 nop = 1;
1410 else if (startswith (str: option, prefix: "-pass-through="))
1411 {
1412 num_pass_through_items++;
1413 pass_through_items = xrealloc (pass_through_items,
1414 num_pass_through_items * sizeof (char *));
1415 pass_through_items[num_pass_through_items - 1] =
1416 xstrdup (option + strlen (s: "-pass-through="));
1417 }
1418 else if (startswith (str: option, prefix: "-sym-style="))
1419 {
1420 switch (option[sizeof ("-sym-style=") - 1])
1421 {
1422 case 'w':
1423 sym_style = ss_win32;
1424 break;
1425 case 'u':
1426 sym_style = ss_uscore;
1427 break;
1428 default:
1429 sym_style = ss_none;
1430 break;
1431 }
1432 }
1433 else if (startswith (str: option, prefix: "-ltrans-objects="))
1434 ltrans_objects = xstrdup (option + strlen (s: "-ltrans-objects="));
1435 else
1436 {
1437 int size;
1438 char *opt = xstrdup (option);
1439 lto_wrapper_num_args += 1;
1440 size = lto_wrapper_num_args * sizeof (char *);
1441 lto_wrapper_argv = (char **) xrealloc (lto_wrapper_argv, size);
1442 lto_wrapper_argv[lto_wrapper_num_args - 1] = opt;
1443 if (startswith (str: option, prefix: "-fresolution="))
1444 resolution_file = opt + sizeof ("-fresolution=") - 1;
1445 }
1446 save_temps = save_temps || debug;
1447 verbose = verbose || debug;
1448}
1449
1450/* Negotiate linker API version. */
1451
1452static void
1453negotiate_api_version (void)
1454{
1455 const char *linker_identifier;
1456 const char *linker_version;
1457
1458 enum linker_api_version supported_api = LAPI_V0;
1459#if HAVE_PTHREAD_LOCKING
1460 supported_api = LAPI_V1;
1461#endif
1462
1463 api_version = get_api_version ("GCC", BASE_VERSION, LAPI_V0,
1464 supported_api, &linker_identifier, &linker_version);
1465 if (api_version > supported_api)
1466 {
1467 fprintf (stderr, format: "requested an unsupported API version (%d)\n", api_version);
1468 abort ();
1469 }
1470
1471 switch (api_version)
1472 {
1473 case LAPI_V0:
1474 break;
1475 case LAPI_V1:
1476 check (get_symbols_v3, LDPL_FATAL,
1477 "get_symbols_v3 required for API version 1");
1478 check (add_symbols_v2, LDPL_FATAL,
1479 "add_symbols_v2 required for API version 1");
1480 break;
1481 default:
1482 fprintf (stderr, format: "unsupported API version (%d)\n", api_version);
1483 abort ();
1484 }
1485}
1486
1487/* Called by a linker after loading the plugin. TV is the transfer vector. */
1488
1489enum ld_plugin_status
1490onload (struct ld_plugin_tv *tv)
1491{
1492 struct ld_plugin_tv *p;
1493 enum ld_plugin_status status;
1494
1495#if HAVE_PTHREAD_LOCKING
1496 if (pthread_mutex_init (mutex: &plugin_lock, NULL) != 0)
1497 {
1498 fprintf (stderr, format: "mutex init failed\n");
1499 abort ();
1500 }
1501#endif
1502
1503 p = tv;
1504 while (p->tv_tag)
1505 {
1506 switch (p->tv_tag)
1507 {
1508 case LDPT_MESSAGE:
1509 message = p->tv_u.tv_message;
1510 break;
1511 case LDPT_REGISTER_CLAIM_FILE_HOOK:
1512 register_claim_file = p->tv_u.tv_register_claim_file;
1513 break;
1514 case LDPT_REGISTER_CLAIM_FILE_HOOK_V2:
1515 register_claim_file_v2 = p->tv_u.tv_register_claim_file_v2;
1516 break;
1517 case LDPT_ADD_SYMBOLS_V2:
1518 add_symbols_v2 = p->tv_u.tv_add_symbols;
1519 break;
1520 case LDPT_ADD_SYMBOLS:
1521 add_symbols = p->tv_u.tv_add_symbols;
1522 break;
1523 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
1524 register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
1525 break;
1526 case LDPT_GET_SYMBOLS_V3:
1527 get_symbols_v3 = p->tv_u.tv_get_symbols;
1528 break;
1529 case LDPT_GET_SYMBOLS_V2:
1530 get_symbols_v2 = p->tv_u.tv_get_symbols;
1531 break;
1532 case LDPT_GET_SYMBOLS:
1533 get_symbols = p->tv_u.tv_get_symbols;
1534 break;
1535 case LDPT_REGISTER_CLEANUP_HOOK:
1536 register_cleanup = p->tv_u.tv_register_cleanup;
1537 break;
1538 case LDPT_ADD_INPUT_FILE:
1539 add_input_file = p->tv_u.tv_add_input_file;
1540 break;
1541 case LDPT_ADD_INPUT_LIBRARY:
1542 add_input_library = p->tv_u.tv_add_input_library;
1543 break;
1544 case LDPT_OPTION:
1545 process_option (option: p->tv_u.tv_string);
1546 break;
1547 case LDPT_GOLD_VERSION:
1548 gold_version = p->tv_u.tv_val;
1549 break;
1550 case LDPT_LINKER_OUTPUT:
1551 linker_output = (enum ld_plugin_output_file_type) p->tv_u.tv_val;
1552 linker_output_set = true;
1553 break;
1554 case LDPT_OUTPUT_NAME:
1555 /* We only use this to make user-friendly temp file names. */
1556 link_output_name = p->tv_u.tv_string;
1557 break;
1558 case LDPT_GET_API_VERSION:
1559 get_api_version = p->tv_u.tv_get_api_version;
1560 break;
1561 default:
1562 break;
1563 }
1564 p++;
1565 }
1566
1567 if (get_api_version)
1568 negotiate_api_version ();
1569
1570 check (register_claim_file, LDPL_FATAL, "register_claim_file not found");
1571 check (add_symbols, LDPL_FATAL, "add_symbols not found");
1572 status = register_claim_file (claim_file_handler);
1573 check (status == LDPS_OK, LDPL_FATAL,
1574 "could not register the claim_file callback");
1575
1576 if (register_claim_file_v2)
1577 {
1578 status = register_claim_file_v2 (claim_file_handler_v2);
1579 check (status == LDPS_OK, LDPL_FATAL,
1580 "could not register the claim_file_v2 callback");
1581 }
1582
1583 if (register_cleanup)
1584 {
1585 status = register_cleanup (cleanup_handler);
1586 check (status == LDPS_OK, LDPL_FATAL,
1587 "could not register the cleanup callback");
1588 }
1589
1590 if (register_all_symbols_read)
1591 {
1592 check (get_symbols, LDPL_FATAL, "get_symbols not found");
1593 status = register_all_symbols_read (all_symbols_read_handler);
1594 check (status == LDPS_OK, LDPL_FATAL,
1595 "could not register the all_symbols_read callback");
1596 }
1597
1598 char *collect_gcc_options = getenv (name: "COLLECT_GCC_OPTIONS");
1599 if (collect_gcc_options)
1600 {
1601 /* Support -fno-use-linker-plugin by failing to load the plugin
1602 for the case where it is auto-loaded by BFD. */
1603 if (strstr (haystack: collect_gcc_options, needle: "'-fno-use-linker-plugin'"))
1604 return LDPS_ERR;
1605
1606 if (strstr (haystack: collect_gcc_options, needle: "'-save-temps'"))
1607 save_temps = true;
1608
1609 if (strstr (haystack: collect_gcc_options, needle: "'-v'")
1610 || strstr (haystack: collect_gcc_options, needle: "'--verbose'"))
1611 verbose = true;
1612
1613 const char *p;
1614 if ((p = strstr (haystack: collect_gcc_options, needle: "'-dumpdir'")))
1615 {
1616 p += sizeof ("'-dumpdir'");
1617 while (*p == ' ')
1618 p++;
1619 const char *start = p;
1620 int ticks = 0, escapes = 0;
1621 /* Count ticks (') and escaped (\.) characters. Stop at the
1622 end of the options or at a blank after an even number of
1623 ticks (not counting escaped ones. */
1624 for (p = start; *p; p++)
1625 {
1626 if (*p == '\'')
1627 {
1628 ticks++;
1629 continue;
1630 }
1631 else if ((ticks % 2) != 0)
1632 {
1633 if (*p == ' ')
1634 break;
1635 if (*p == '\\')
1636 {
1637 if (*++p)
1638 escapes++;
1639 else
1640 p--;
1641 }
1642 }
1643 }
1644
1645 /* Now allocate a new link_output_name and decode dumpdir
1646 into it. The loop uses the same logic, except it counts
1647 ticks and escapes backwards (so ticks is adjusted if we
1648 find an odd number of them), and it copies characters
1649 that are escaped or not otherwise skipped. */
1650 int len = p - start - ticks - escapes + 1;
1651 char *q = xmalloc (len);
1652 link_output_name = q;
1653 int oddticks = (ticks % 2);
1654 ticks += oddticks;
1655 for (p = start; *p; p++)
1656 {
1657 if (*p == '\'')
1658 {
1659 ticks--;
1660 continue;
1661 }
1662 else if ((ticks % 2) != 0)
1663 {
1664 if (*p == ' ')
1665 break;
1666 if (*p == '\\')
1667 {
1668 if (*++p)
1669 escapes--;
1670 else
1671 p--;
1672 }
1673 }
1674 *q++ = *p;
1675 }
1676 *q = '\0';
1677 assert (escapes == 0);
1678 assert (ticks == oddticks);
1679 assert (q - link_output_name == len - 1);
1680 skip_in_suffix = true;
1681 }
1682 }
1683
1684 return LDPS_OK;
1685}
1686

source code of lto-plugin/lto-plugin.c