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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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