]> git.ipfire.org Git - thirdparty/gcc.git/blob - lto-plugin/lto-plugin.c
64a0164da3cf1766d03633eb475605ba5d348040
[thirdparty/gcc.git] / lto-plugin / lto-plugin.c
1 /* LTO plugin for gold and/or GNU ld.
2 Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3 Contributed by Rafael Avila de Espindola (espindola@google.com).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING3. If not see
17 <http://www.gnu.org/licenses/>. */
18
19 /* The plugin has only one external function: onload. Gold passes it an array of
20 function that the plugin uses to communicate back to gold.
21
22 With the functions provided by gold, the plugin can be notified when
23 gold first analyzes a file and pass a symbol table back to gold. The plugin
24 is also notified when all symbols have been read and it is time to generate
25 machine code for the necessary symbols.
26
27 More information at http://gcc.gnu.org/wiki/whopr/driver.
28
29 This plugin should be passed the lto-wrapper options and will forward them.
30 It also has 2 options of its own:
31 -debug: Print the command line used to run lto-wrapper.
32 -nop: Instead of running lto-wrapper, pass the original to the plugin. This
33 only works if the input files are hybrid. */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 #if HAVE_STDINT_H
39 #include <stdint.h>
40 #endif
41 #include <assert.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <inttypes.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <sys/types.h>
50 #ifdef HAVE_SYS_WAIT_H
51 #include <sys/wait.h>
52 #endif
53 #ifndef WIFEXITED
54 #define WIFEXITED(S) (((S) & 0xff) == 0)
55 #endif
56 #ifndef WEXITSTATUS
57 #define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
58 #endif
59 #include <libiberty.h>
60 #include <hashtab.h>
61 #include "../gcc/lto/common.h"
62 #include "simple-object.h"
63 #include "plugin-api.h"
64
65 /* Handle opening elf files on hosts, such as Windows, that may use
66 text file handling that will break binary access. */
67 #ifndef O_BINARY
68 # define O_BINARY 0
69 #endif
70
71 /* Segment name for LTO sections. This is only used for Mach-O.
72 FIXME: This needs to be kept in sync with darwin.c. */
73
74 #define LTO_SEGMENT_NAME "__GNU_LTO"
75
76 /* LTO magic section name. */
77
78 #define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
79 #define LTO_SECTION_PREFIX_LEN (sizeof (LTO_SECTION_PREFIX) - 1)
80
81 /* The part of the symbol table the plugin has to keep track of. Note that we
82 must keep SYMS until all_symbols_read is called to give the linker time to
83 copy the symbol information. */
84
85 struct sym_aux
86 {
87 uint32_t slot;
88 unsigned id;
89 unsigned next_conflict;
90 };
91
92 struct plugin_symtab
93 {
94 int nsyms;
95 struct sym_aux *aux;
96 struct ld_plugin_symbol *syms;
97 unsigned id;
98 };
99
100 /* Encapsulates object file data during symbol scan. */
101 struct plugin_objfile
102 {
103 int found;
104 simple_object_read *objfile;
105 struct plugin_symtab *out;
106 const struct ld_plugin_input_file *file;
107 };
108
109 /* All that we have to remember about a file. */
110
111 struct plugin_file_info
112 {
113 char *name;
114 void *handle;
115 struct plugin_symtab symtab;
116 struct plugin_symtab conflicts;
117 };
118
119 /* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
120 stdio file streams, we do simple label translation here. */
121
122 enum symbol_style
123 {
124 ss_none, /* No underscore prefix. */
125 ss_win32, /* Underscore prefix any symbol not beginning with '@'. */
126 ss_uscore, /* Underscore prefix all symbols. */
127 };
128
129 static char *arguments_file_name;
130 static ld_plugin_register_claim_file register_claim_file;
131 static ld_plugin_register_all_symbols_read register_all_symbols_read;
132 static ld_plugin_get_symbols get_symbols;
133 static ld_plugin_register_cleanup register_cleanup;
134 static ld_plugin_add_input_file add_input_file;
135 static ld_plugin_add_input_library add_input_library;
136 static ld_plugin_message message;
137 static ld_plugin_add_symbols add_symbols;
138
139 static struct plugin_file_info *claimed_files = NULL;
140 static unsigned int num_claimed_files = 0;
141
142 static char **output_files = NULL;
143 static unsigned int num_output_files = 0;
144
145 static char **lto_wrapper_argv;
146 static int lto_wrapper_num_args;
147
148 static char **pass_through_items = NULL;
149 static unsigned int num_pass_through_items;
150
151 static char debug;
152 static char nop;
153 static char *resolution_file = NULL;
154
155 /* The version of gold being used, or -1 if not gold. The number is
156 MAJOR * 100 + MINOR. */
157 static int gold_version = -1;
158
159 /* Not used by default, but can be overridden at runtime
160 by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
161 (in fact, only first letter of style arg is checked.) */
162 static enum symbol_style sym_style = ss_none;
163
164 static void
165 check_1 (int gate, enum ld_plugin_level level, const char *text)
166 {
167 if (gate)
168 return;
169
170 if (message)
171 message (level, text);
172 else
173 {
174 /* If there is no nicer way to inform the user, fallback to stderr. */
175 fprintf (stderr, "%s\n", text);
176 if (level == LDPL_FATAL)
177 abort ();
178 }
179 }
180
181 /* This little wrapper allows check to be called with a non-integer
182 first argument, such as a pointer that must be non-NULL. We can't
183 use c99 bool type to coerce it into range, so we explicitly test. */
184 #define check(GATE, LEVEL, TEXT) check_1 (((GATE) != 0), (LEVEL), (TEXT))
185
186 /* Parse an entry of the IL symbol table. The data to be parsed is pointed
187 by P and the result is written in ENTRY. The slot number is stored in SLOT.
188 Returns the address of the next entry. */
189
190 static char *
191 parse_table_entry (char *p, struct ld_plugin_symbol *entry,
192 struct sym_aux *aux)
193 {
194 unsigned char t;
195 enum ld_plugin_symbol_kind translate_kind[] =
196 {
197 LDPK_DEF,
198 LDPK_WEAKDEF,
199 LDPK_UNDEF,
200 LDPK_WEAKUNDEF,
201 LDPK_COMMON
202 };
203
204 enum ld_plugin_symbol_visibility translate_visibility[] =
205 {
206 LDPV_DEFAULT,
207 LDPV_PROTECTED,
208 LDPV_INTERNAL,
209 LDPV_HIDDEN
210 };
211
212 switch (sym_style)
213 {
214 case ss_win32:
215 if (p[0] == '@')
216 {
217 /* cf. Duff's device. */
218 case ss_none:
219 entry->name = xstrdup (p);
220 break;
221 }
222 /* FALL-THROUGH. */
223 case ss_uscore:
224 entry->name = concat ("_", p, NULL);
225 break;
226 default:
227 check (0, LDPL_FATAL, "invalid symbol style requested");
228 break;
229 }
230 while (*p)
231 p++;
232 p++;
233
234 entry->version = NULL;
235
236 entry->comdat_key = p;
237 while (*p)
238 p++;
239 p++;
240
241 if (strlen (entry->comdat_key) == 0)
242 entry->comdat_key = NULL;
243 else
244 entry->comdat_key = xstrdup (entry->comdat_key);
245
246 t = *p;
247 check (t <= 4, LDPL_FATAL, "invalid symbol kind found");
248 entry->def = translate_kind[t];
249 p++;
250
251 t = *p;
252 check (t <= 3, LDPL_FATAL, "invalid symbol visibility found");
253 entry->visibility = translate_visibility[t];
254 p++;
255
256 memcpy (&entry->size, p, sizeof (uint64_t));
257 p += 8;
258
259 memcpy (&aux->slot, p, sizeof (uint32_t));
260 p += 4;
261
262 entry->resolution = LDPR_UNKNOWN;
263
264 aux->next_conflict = -1;
265
266 return p;
267 }
268
269 /* Translate the IL symbol table located between DATA and END. Append the
270 slots and symbols to OUT. */
271
272 static void
273 translate (char *data, char *end, struct plugin_symtab *out)
274 {
275 struct sym_aux *aux;
276 struct ld_plugin_symbol *syms = NULL;
277 int n, len;
278
279 /* This overestimates the output buffer sizes, but at least
280 the algorithm is O(1) now. */
281
282 len = (end - data)/8 + out->nsyms + 1;
283 syms = xrealloc (out->syms, len * sizeof (struct ld_plugin_symbol));
284 aux = xrealloc (out->aux, len * sizeof (struct sym_aux));
285
286 for (n = out->nsyms; data < end; n++)
287 {
288 aux[n].id = out->id;
289 data = parse_table_entry (data, &syms[n], &aux[n]);
290 }
291
292 assert(n < len);
293
294 out->nsyms = n;
295 out->syms = syms;
296 out->aux = aux;
297 }
298
299 /* Free all memory that is no longer needed after writing the symbol
300 resolution. */
301
302 static void
303 free_1 (void)
304 {
305 unsigned int i;
306 for (i = 0; i < num_claimed_files; i++)
307 {
308 struct plugin_file_info *info = &claimed_files[i];
309 struct plugin_symtab *symtab = &info->symtab;
310 unsigned int j;
311 for (j = 0; j < symtab->nsyms; j++)
312 {
313 struct ld_plugin_symbol *s = &symtab->syms[j];
314 free (s->name);
315 if (s->comdat_key)
316 free (s->comdat_key);
317 }
318 free (symtab->syms);
319 symtab->syms = NULL;
320 }
321 }
322
323 /* Free all remaining memory. */
324
325 static void
326 free_2 (void)
327 {
328 unsigned int i;
329 for (i = 0; i < num_claimed_files; i++)
330 {
331 struct plugin_file_info *info = &claimed_files[i];
332 struct plugin_symtab *symtab = &info->symtab;
333 free (symtab->aux);
334 free (info->name);
335 }
336
337 for (i = 0; i < num_output_files; i++)
338 free (output_files[i]);
339 free (output_files);
340
341 free (claimed_files);
342 claimed_files = NULL;
343 num_claimed_files = 0;
344
345 if (arguments_file_name)
346 free (arguments_file_name);
347 arguments_file_name = NULL;
348 }
349
350 /* Dump SYMTAB to resolution file F. */
351
352 static void
353 dump_symtab (FILE *f, struct plugin_symtab *symtab)
354 {
355 unsigned j;
356
357 for (j = 0; j < symtab->nsyms; j++)
358 {
359 uint32_t slot = symtab->aux[j].slot;
360 unsigned int resolution = symtab->syms[j].resolution;
361
362 assert (resolution != LDPR_UNKNOWN);
363
364 fprintf (f, "%u %x %s %s\n", (unsigned int) slot, symtab->aux[j].id,
365 lto_resolution_str[resolution],
366 symtab->syms[j].name);
367 }
368 }
369
370 /* Finish the conflicts' resolution information after the linker resolved
371 the original symbols */
372
373 static void
374 finish_conflict_resolution (struct plugin_symtab *symtab,
375 struct plugin_symtab *conflicts)
376 {
377 int i, j;
378
379 if (conflicts->nsyms == 0)
380 return;
381
382 for (i = 0; i < symtab->nsyms; i++)
383 {
384 int resolution = LDPR_UNKNOWN;
385
386 if (symtab->aux[i].next_conflict == -1)
387 continue;
388
389 switch (symtab->syms[i].def)
390 {
391 case LDPK_DEF:
392 case LDPK_COMMON: /* ??? */
393 resolution = LDPR_RESOLVED_IR;
394 break;
395 case LDPK_WEAKDEF:
396 resolution = LDPR_PREEMPTED_IR;
397 break;
398 case LDPK_UNDEF:
399 case LDPK_WEAKUNDEF:
400 resolution = symtab->syms[i].resolution;
401 break;
402 default:
403 assert (0);
404 }
405
406 assert (resolution != LDPR_UNKNOWN);
407
408 for (j = symtab->aux[i].next_conflict;
409 j != -1;
410 j = conflicts->aux[j].next_conflict)
411 conflicts->syms[j].resolution = resolution;
412 }
413 }
414
415 /* Free symbol table SYMTAB. */
416
417 static void
418 free_symtab (struct plugin_symtab *symtab)
419 {
420 free (symtab->syms);
421 symtab->syms = NULL;
422 free (symtab->aux);
423 symtab->aux = NULL;
424 }
425
426 /* Writes the relocations to disk. */
427
428 static void
429 write_resolution (void)
430 {
431 unsigned int i;
432 FILE *f;
433
434 check (resolution_file, LDPL_FATAL, "resolution file not specified");
435 f = fopen (resolution_file, "w");
436 check (f, LDPL_FATAL, "could not open file");
437
438 fprintf (f, "%d\n", num_claimed_files);
439
440 for (i = 0; i < num_claimed_files; i++)
441 {
442 struct plugin_file_info *info = &claimed_files[i];
443 struct plugin_symtab *symtab = &info->symtab;
444 struct ld_plugin_symbol *syms = symtab->syms;
445
446 get_symbols (info->handle, symtab->nsyms, syms);
447
448 finish_conflict_resolution (symtab, &info->conflicts);
449
450 fprintf (f, "%s %d\n", info->name, symtab->nsyms + info->conflicts.nsyms);
451 dump_symtab (f, symtab);
452 if (info->conflicts.nsyms)
453 {
454 dump_symtab (f, &info->conflicts);
455 free_symtab (&info->conflicts);
456 }
457 }
458 fclose (f);
459 }
460
461 /* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
462 stdout. */
463
464 static void
465 add_output_files (FILE *f)
466 {
467 for (;;)
468 {
469 const unsigned piece = 32;
470 char *buf, *s = xmalloc (piece);
471 size_t len;
472
473 buf = s;
474 cont:
475 if (!fgets (buf, piece, f))
476 {
477 free (s);
478 break;
479 }
480 len = strlen (s);
481 if (s[len - 1] != '\n')
482 {
483 s = xrealloc (s, len + piece);
484 buf = s + len;
485 goto cont;
486 }
487 s[len - 1] = '\0';
488
489 num_output_files++;
490 output_files
491 = xrealloc (output_files, num_output_files * sizeof (char *));
492 output_files[num_output_files - 1] = s;
493 add_input_file (output_files[num_output_files - 1]);
494 }
495 }
496
497 /* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
498 argument list. */
499
500 static void
501 exec_lto_wrapper (char *argv[])
502 {
503 int t, i;
504 int status;
505 char *at_args;
506 FILE *args;
507 FILE *wrapper_output;
508 char *new_argv[3];
509 struct pex_obj *pex;
510 const char *errmsg;
511
512 /* Write argv to a file to avoid a command line that is too long. */
513 arguments_file_name = make_temp_file ("");
514 check (arguments_file_name, LDPL_FATAL,
515 "Failed to generate a temorary file name");
516
517 args = fopen (arguments_file_name, "w");
518 check (args, LDPL_FATAL, "could not open arguments file");
519
520 t = writeargv (&argv[1], args);
521 check (t == 0, LDPL_FATAL, "could not write arguments");
522 t = fclose (args);
523 check (t == 0, LDPL_FATAL, "could not close arguments file");
524
525 at_args = concat ("@", arguments_file_name, NULL);
526 check (at_args, LDPL_FATAL, "could not allocate");
527
528 for (i = 1; argv[i]; i++)
529 {
530 char *a = argv[i];
531 if (a[0] == '-' && a[1] == 'v' && a[2] == '\0')
532 {
533 for (i = 0; argv[i]; i++)
534 fprintf (stderr, "%s ", argv[i]);
535 fprintf (stderr, "\n");
536 break;
537 }
538 }
539
540 new_argv[0] = argv[0];
541 new_argv[1] = at_args;
542 new_argv[2] = NULL;
543
544 if (debug)
545 {
546 for (i = 0; new_argv[i]; i++)
547 fprintf (stderr, "%s ", new_argv[i]);
548 fprintf (stderr, "\n");
549 }
550
551
552 pex = pex_init (PEX_USE_PIPES, "lto-wrapper", NULL);
553 check (pex != NULL, LDPL_FATAL, "could not pex_init lto-wrapper");
554
555 errmsg = pex_run (pex, 0, new_argv[0], new_argv, NULL, NULL, &t);
556 check (errmsg == NULL, LDPL_FATAL, "could not run lto-wrapper");
557 check (t == 0, LDPL_FATAL, "could not run lto-wrapper");
558
559 wrapper_output = pex_read_output (pex, 0);
560 check (wrapper_output, LDPL_FATAL, "could not read lto-wrapper output");
561
562 add_output_files (wrapper_output);
563
564 t = pex_get_status (pex, 1, &status);
565 check (t == 1, LDPL_FATAL, "could not get lto-wrapper exit status");
566 check (WIFEXITED (status) && WEXITSTATUS (status) == 0, LDPL_FATAL,
567 "lto-wrapper failed");
568
569 pex_free (pex);
570
571 free (at_args);
572 }
573
574 /* Pass the original files back to the linker. */
575
576 static void
577 use_original_files (void)
578 {
579 unsigned i;
580 for (i = 0; i < num_claimed_files; i++)
581 {
582 struct plugin_file_info *info = &claimed_files[i];
583 add_input_file (info->name);
584 }
585 }
586
587
588 /* Called by the linker once all symbols have been read. */
589
590 static enum ld_plugin_status
591 all_symbols_read_handler (void)
592 {
593 unsigned i;
594 unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 1;
595 char **lto_argv;
596 const char **lto_arg_ptr;
597 if (num_claimed_files == 0)
598 return LDPS_OK;
599
600 if (nop)
601 {
602 use_original_files ();
603 return LDPS_OK;
604 }
605
606 lto_argv = (char **) xcalloc (sizeof (char *), num_lto_args);
607 lto_arg_ptr = (const char **) lto_argv;
608 assert (lto_wrapper_argv);
609
610 write_resolution ();
611
612 free_1 ();
613
614 for (i = 0; i < lto_wrapper_num_args; i++)
615 *lto_arg_ptr++ = lto_wrapper_argv[i];
616
617 for (i = 0; i < num_claimed_files; i++)
618 {
619 struct plugin_file_info *info = &claimed_files[i];
620
621 *lto_arg_ptr++ = info->name;
622 }
623
624 *lto_arg_ptr++ = NULL;
625 exec_lto_wrapper (lto_argv);
626
627 free (lto_argv);
628
629 /* --pass-through is not needed when using gold 1.11 or later. */
630 if (pass_through_items && gold_version < 111)
631 {
632 unsigned int i;
633 for (i = 0; i < num_pass_through_items; i++)
634 {
635 if (strncmp (pass_through_items[i], "-l", 2) == 0)
636 add_input_library (pass_through_items[i] + 2);
637 else
638 add_input_file (pass_through_items[i]);
639 free (pass_through_items[i]);
640 pass_through_items[i] = NULL;
641 }
642 free (pass_through_items);
643 pass_through_items = NULL;
644 }
645
646 return LDPS_OK;
647 }
648
649 /* Remove temporary files at the end of the link. */
650
651 static enum ld_plugin_status
652 cleanup_handler (void)
653 {
654 unsigned int i;
655 int t;
656
657 if (debug)
658 return LDPS_OK;
659
660 if (arguments_file_name)
661 {
662 t = unlink (arguments_file_name);
663 check (t == 0, LDPL_FATAL, "could not unlink arguments file");
664 }
665
666 for (i = 0; i < num_output_files; i++)
667 {
668 t = unlink (output_files[i]);
669 check (t == 0, LDPL_FATAL, "could not unlink output file");
670 }
671
672 free_2 ();
673 return LDPS_OK;
674 }
675
676 #define SWAP(type, a, b) \
677 do { type tmp_; tmp_ = (a); (a) = (b); (b) = tmp_; } while(0)
678
679 /* Compare two hash table entries */
680
681 static int eq_sym (const void *a, const void *b)
682 {
683 const struct ld_plugin_symbol *as = (const struct ld_plugin_symbol *)a;
684 const struct ld_plugin_symbol *bs = (const struct ld_plugin_symbol *)b;
685
686 return !strcmp (as->name, bs->name);
687 }
688
689 /* Hash a symbol */
690
691 static hashval_t hash_sym (const void *a)
692 {
693 const struct ld_plugin_symbol *as = (const struct ld_plugin_symbol *)a;
694
695 return htab_hash_string (as->name);
696 }
697
698 /* Determine how strong a symbol is */
699
700 static int symbol_strength (struct ld_plugin_symbol *s)
701 {
702 switch (s->def)
703 {
704 case LDPK_UNDEF:
705 case LDPK_WEAKUNDEF:
706 return 0;
707 case LDPK_WEAKDEF:
708 return 1;
709 default:
710 return 2;
711 }
712 }
713
714 /* In the ld -r case we can get dups in the LTO symbol tables, where
715 the same symbol can have different resolutions (e.g. undefined and defined).
716
717 We have to keep that in the LTO symbol tables, but the dups confuse
718 gold and then finally gcc by supplying incorrect resolutions.
719
720 Problem is that the main gold symbol table doesn't know about subids
721 and does not distingush the same symbols in different states.
722
723 So we drop duplicates from the linker visible symbol table
724 and keep them in a private table. Then later do own symbol
725 resolution for the duplicated based on the results for the
726 originals.
727
728 Then when writing out the resolution file readd the dropped symbols.
729
730 XXX how to handle common? */
731
732 static void
733 resolve_conflicts (struct plugin_symtab *t, struct plugin_symtab *conflicts)
734 {
735 htab_t symtab = htab_create (t->nsyms, hash_sym, eq_sym, NULL);
736 int i;
737 int out;
738 int outlen;
739
740 outlen = t->nsyms;
741 conflicts->syms = xmalloc (sizeof (struct ld_plugin_symbol) * outlen);
742 conflicts->aux = xmalloc (sizeof (struct sym_aux) * outlen);
743
744 /* Move all duplicate symbols into the auxillary conflicts table. */
745 out = 0;
746 for (i = 0; i < t->nsyms; i++)
747 {
748 struct ld_plugin_symbol *s = &t->syms[i];
749 struct sym_aux *aux = &t->aux[i];
750 void **slot;
751
752 slot = htab_find_slot (symtab, s, INSERT);
753 if (*slot != NULL)
754 {
755 int cnf;
756 struct ld_plugin_symbol *orig = (struct ld_plugin_symbol *)*slot;
757 struct sym_aux *orig_aux = &t->aux[orig - t->syms];
758
759 /* Always let the linker resolve the strongest symbol */
760 if (symbol_strength (orig) < symbol_strength (s))
761 {
762 SWAP (struct ld_plugin_symbol, *orig, *s);
763 SWAP (uint32_t, orig_aux->slot, aux->slot);
764 SWAP (unsigned, orig_aux->id, aux->id);
765 /* Don't swap conflict chain pointer */
766 }
767
768 /* Move current symbol into the conflicts table */
769 cnf = conflicts->nsyms++;
770 conflicts->syms[cnf] = *s;
771 conflicts->aux[cnf] = *aux;
772 aux = &conflicts->aux[cnf];
773
774 /* Update conflicts chain of the original symbol */
775 aux->next_conflict = orig_aux->next_conflict;
776 orig_aux->next_conflict = cnf;
777
778 continue;
779 }
780
781 /* Remove previous duplicates in the main table */
782 if (out < i)
783 {
784 t->syms[out] = *s;
785 t->aux[out] = *aux;
786 }
787
788 /* Put original into the hash table */
789 *slot = &t->syms[out];
790 out++;
791 }
792
793 assert (conflicts->nsyms <= outlen);
794 assert (conflicts->nsyms + out == t->nsyms);
795
796 t->nsyms = out;
797 htab_delete (symtab);
798 }
799
800 /* Process one section of an object file. */
801
802 static int
803 process_symtab (void *data, const char *name, off_t offset, off_t length)
804 {
805 struct plugin_objfile *obj = (struct plugin_objfile *)data;
806 char *s;
807 char *secdata;
808
809 if (strncmp (name, LTO_SECTION_PREFIX, LTO_SECTION_PREFIX_LEN) != 0)
810 return 1;
811
812 s = strrchr (name, '.');
813 if (s)
814 sscanf (s, ".%x", &obj->out->id);
815 secdata = xmalloc (length);
816 offset += obj->file->offset;
817 if (offset != lseek (obj->file->fd, offset, SEEK_SET)
818 || length != read (obj->file->fd, secdata, length))
819 {
820 if (message)
821 message (LDPL_FATAL, "%s: corrupt object file", obj->file->name);
822 /* Force claim_file_handler to abandon this file. */
823 obj->found = 0;
824 free (secdata);
825 return 0;
826 }
827
828 translate (secdata, secdata + length, obj->out);
829 obj->found++;
830 free (secdata);
831 return 1;
832 }
833
834 /* Callback used by gold to check if the plugin will claim FILE. Writes
835 the result in CLAIMED. */
836
837 static enum ld_plugin_status
838 claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
839 {
840 enum ld_plugin_status status;
841 struct plugin_objfile obj;
842 struct plugin_file_info lto_file;
843 int err;
844 const char *errmsg;
845
846 memset (&lto_file, 0, sizeof (struct plugin_file_info));
847
848 if (file->offset != 0)
849 {
850 char *objname;
851 /* We pass the offset of the actual file, not the archive header.
852 Can't use PRIx64, because that's C99, so we have to print the
853 64-bit hex int as two 32-bit ones. */
854 int lo, hi;
855 lo = file->offset & 0xffffffff;
856 hi = ((int64_t)file->offset >> 32) & 0xffffffff;
857 int t = hi ? asprintf (&objname, "%s@0x%x%08x", file->name, lo, hi)
858 : asprintf (&objname, "%s@0x%x", file->name, lo);
859 check (t >= 0, LDPL_FATAL, "asprintf failed");
860 lto_file.name = objname;
861 }
862 else
863 {
864 lto_file.name = xstrdup (file->name);
865 }
866 lto_file.handle = file->handle;
867
868 *claimed = 0;
869 obj.file = file;
870 obj.found = 0;
871 obj.out = &lto_file.symtab;
872 errmsg = NULL;
873 obj.objfile = simple_object_start_read (file->fd, file->offset, LTO_SEGMENT_NAME,
874 &errmsg, &err);
875 /* No file, but also no error code means unrecognized format; just skip it. */
876 if (!obj.objfile && !err)
877 goto err;
878
879 if (obj.objfile)
880 errmsg = simple_object_find_sections (obj.objfile, process_symtab, &obj, &err);
881
882 if (!obj.objfile || errmsg)
883 {
884 if (err && message)
885 message (LDPL_FATAL, "%s: %s: %s", file->name, errmsg,
886 xstrerror (err));
887 else if (message)
888 message (LDPL_FATAL, "%s: %s", file->name, errmsg);
889 goto err;
890 }
891
892 if (obj.found == 0)
893 goto err;
894
895 if (obj.found > 1)
896 resolve_conflicts (&lto_file.symtab, &lto_file.conflicts);
897
898 status = add_symbols (file->handle, lto_file.symtab.nsyms,
899 lto_file.symtab.syms);
900 check (status == LDPS_OK, LDPL_FATAL, "could not add symbols");
901
902 *claimed = 1;
903 num_claimed_files++;
904 claimed_files =
905 xrealloc (claimed_files,
906 num_claimed_files * sizeof (struct plugin_file_info));
907 claimed_files[num_claimed_files - 1] = lto_file;
908
909 goto cleanup;
910
911 err:
912 free (lto_file.name);
913
914 cleanup:
915 if (obj.objfile)
916 simple_object_release_read (obj.objfile);
917
918 return LDPS_OK;
919 }
920
921 /* Parse the plugin options. */
922
923 static void
924 process_option (const char *option)
925 {
926 if (strcmp (option, "-debug") == 0)
927 debug = 1;
928 else if (strcmp (option, "-nop") == 0)
929 nop = 1;
930 else if (!strncmp (option, "-pass-through=", strlen("-pass-through=")))
931 {
932 num_pass_through_items++;
933 pass_through_items = xrealloc (pass_through_items,
934 num_pass_through_items * sizeof (char *));
935 pass_through_items[num_pass_through_items - 1] =
936 xstrdup (option + strlen ("-pass-through="));
937 }
938 else if (!strncmp (option, "-sym-style=", sizeof ("-sym-style=") - 1))
939 {
940 switch (option[sizeof ("-sym-style=") - 1])
941 {
942 case 'w':
943 sym_style = ss_win32;
944 break;
945 case 'u':
946 sym_style = ss_uscore;
947 break;
948 default:
949 sym_style = ss_none;
950 break;
951 }
952 }
953 else
954 {
955 int size;
956 char *opt = xstrdup (option);
957 lto_wrapper_num_args += 1;
958 size = lto_wrapper_num_args * sizeof (char *);
959 lto_wrapper_argv = (char **) xrealloc (lto_wrapper_argv, size);
960 lto_wrapper_argv[lto_wrapper_num_args - 1] = opt;
961 if (strncmp (option, "-fresolution=", sizeof ("-fresolution=") - 1) == 0)
962 resolution_file = opt + sizeof ("-fresolution=") - 1;
963 }
964 }
965
966 /* Called by gold after loading the plugin. TV is the transfer vector. */
967
968 enum ld_plugin_status
969 onload (struct ld_plugin_tv *tv)
970 {
971 struct ld_plugin_tv *p;
972 enum ld_plugin_status status;
973
974 p = tv;
975 while (p->tv_tag)
976 {
977 switch (p->tv_tag)
978 {
979 case LDPT_MESSAGE:
980 message = p->tv_u.tv_message;
981 break;
982 case LDPT_REGISTER_CLAIM_FILE_HOOK:
983 register_claim_file = p->tv_u.tv_register_claim_file;
984 break;
985 case LDPT_ADD_SYMBOLS:
986 add_symbols = p->tv_u.tv_add_symbols;
987 break;
988 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
989 register_all_symbols_read = p->tv_u.tv_register_all_symbols_read;
990 break;
991 case LDPT_GET_SYMBOLS:
992 get_symbols = p->tv_u.tv_get_symbols;
993 break;
994 case LDPT_REGISTER_CLEANUP_HOOK:
995 register_cleanup = p->tv_u.tv_register_cleanup;
996 break;
997 case LDPT_ADD_INPUT_FILE:
998 add_input_file = p->tv_u.tv_add_input_file;
999 break;
1000 case LDPT_ADD_INPUT_LIBRARY:
1001 add_input_library = p->tv_u.tv_add_input_library;
1002 break;
1003 case LDPT_OPTION:
1004 process_option (p->tv_u.tv_string);
1005 break;
1006 case LDPT_GOLD_VERSION:
1007 gold_version = p->tv_u.tv_val;
1008 break;
1009 default:
1010 break;
1011 }
1012 p++;
1013 }
1014
1015 check (register_claim_file, LDPL_FATAL, "register_claim_file not found");
1016 check (add_symbols, LDPL_FATAL, "add_symbols not found");
1017 status = register_claim_file (claim_file_handler);
1018 check (status == LDPS_OK, LDPL_FATAL,
1019 "could not register the claim_file callback");
1020
1021 if (register_cleanup)
1022 {
1023 status = register_cleanup (cleanup_handler);
1024 check (status == LDPS_OK, LDPL_FATAL,
1025 "could not register the cleanup callback");
1026 }
1027
1028 if (register_all_symbols_read)
1029 {
1030 check (get_symbols, LDPL_FATAL, "get_symbols not found");
1031 status = register_all_symbols_read (all_symbols_read_handler);
1032 check (status == LDPS_OK, LDPL_FATAL,
1033 "could not register the all_symbols_read callback");
1034 }
1035
1036 return LDPS_OK;
1037 }