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).
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)
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING3. If not see
17 <http://www.gnu.org/licenses/>. */
19 /* The plugin has only one external function: onload. Gold passes it an array of
20 function that the plugin uses to communicate back to gold.
22 With the functions provided by gold, the plugin can be notified when
23 gold first analyzes a file and pass a symbol table back to gold. The plugin
24 is also notified when all symbols have been read and it is time to generate
25 machine code for the necessary symbols.
27 More information at http://gcc.gnu.org/wiki/whopr/driver.
29 This plugin should be passed the lto-wrapper options and will forward them.
30 It also has 2 options of its own:
31 -debug: Print the command line used to run lto-wrapper.
32 -nop: Instead of running lto-wrapper, pass the original to the plugin. This
33 only works if the input files are hybrid. */
49 #include <sys/types.h>
50 #ifdef HAVE_SYS_WAIT_H
54 #define WIFEXITED(S) (((S) & 0xff) == 0)
57 #define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
59 #include <libiberty.h>
61 #include "../gcc/lto/common.h"
62 #include "simple-object.h"
63 #include "plugin-api.h"
65 /* We need to use I64 instead of ll width-specifier on native Windows.
66 The reason for this is that older MS-runtimes don't support the ll. */
73 /* Handle opening elf files on hosts, such as Windows, that may use
74 text file handling that will break binary access. */
79 /* Segment name for LTO sections. This is only used for Mach-O.
80 FIXME: This needs to be kept in sync with darwin.c. */
82 #define LTO_SEGMENT_NAME "__GNU_LTO"
84 /* LTO magic section name. */
86 #define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
87 #define LTO_SECTION_PREFIX_LEN (sizeof (LTO_SECTION_PREFIX) - 1)
89 /* The part of the symbol table the plugin has to keep track of. Note that we
90 must keep SYMS until all_symbols_read is called to give the linker time to
91 copy the symbol information.
92 The id must be 64bit to minimze collisions. */
97 unsigned long long id
;
98 unsigned next_conflict
;
105 struct ld_plugin_symbol
*syms
;
106 unsigned long long id
;
109 /* Encapsulates object file data during symbol scan. */
110 struct plugin_objfile
113 simple_object_read
*objfile
;
114 struct plugin_symtab
*out
;
115 const struct ld_plugin_input_file
*file
;
118 /* All that we have to remember about a file. */
120 struct plugin_file_info
124 struct plugin_symtab symtab
;
125 struct plugin_symtab conflicts
;
128 /* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
129 stdio file streams, we do simple label translation here. */
133 ss_none
, /* No underscore prefix. */
134 ss_win32
, /* Underscore prefix any symbol not beginning with '@'. */
135 ss_uscore
, /* Underscore prefix all symbols. */
138 static char *arguments_file_name
;
139 static ld_plugin_register_claim_file register_claim_file
;
140 static ld_plugin_register_all_symbols_read register_all_symbols_read
;
141 static ld_plugin_get_symbols get_symbols
, get_symbols_v2
;
142 static ld_plugin_register_cleanup register_cleanup
;
143 static ld_plugin_add_input_file add_input_file
;
144 static ld_plugin_add_input_library add_input_library
;
145 static ld_plugin_message message
;
146 static ld_plugin_add_symbols add_symbols
;
148 static struct plugin_file_info
*claimed_files
= NULL
;
149 static unsigned int num_claimed_files
= 0;
151 static char **output_files
= NULL
;
152 static unsigned int num_output_files
= 0;
154 static char **lto_wrapper_argv
;
155 static int lto_wrapper_num_args
;
157 static char **pass_through_items
= NULL
;
158 static unsigned int num_pass_through_items
;
162 static char *resolution_file
= NULL
;
164 /* The version of gold being used, or -1 if not gold. The number is
165 MAJOR * 100 + MINOR. */
166 static int gold_version
= -1;
168 /* Not used by default, but can be overridden at runtime
169 by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
170 (in fact, only first letter of style arg is checked.) */
171 static enum symbol_style sym_style
= ss_none
;
174 check_1 (int gate
, enum ld_plugin_level level
, const char *text
)
180 message (level
, text
);
183 /* If there is no nicer way to inform the user, fallback to stderr. */
184 fprintf (stderr
, "%s\n", text
);
185 if (level
== LDPL_FATAL
)
190 /* This little wrapper allows check to be called with a non-integer
191 first argument, such as a pointer that must be non-NULL. We can't
192 use c99 bool type to coerce it into range, so we explicitly test. */
193 #define check(GATE, LEVEL, TEXT) check_1 (((GATE) != 0), (LEVEL), (TEXT))
195 /* Parse an entry of the IL symbol table. The data to be parsed is pointed
196 by P and the result is written in ENTRY. The slot number is stored in SLOT.
197 Returns the address of the next entry. */
200 parse_table_entry (char *p
, struct ld_plugin_symbol
*entry
,
204 enum ld_plugin_symbol_kind translate_kind
[] =
213 enum ld_plugin_symbol_visibility translate_visibility
[] =
226 /* cf. Duff's device. */
228 entry
->name
= xstrdup (p
);
233 entry
->name
= concat ("_", p
, NULL
);
236 check (0, LDPL_FATAL
, "invalid symbol style requested");
243 entry
->version
= NULL
;
245 entry
->comdat_key
= p
;
250 if (strlen (entry
->comdat_key
) == 0)
251 entry
->comdat_key
= NULL
;
253 entry
->comdat_key
= xstrdup (entry
->comdat_key
);
256 check (t
<= 4, LDPL_FATAL
, "invalid symbol kind found");
257 entry
->def
= translate_kind
[t
];
261 check (t
<= 3, LDPL_FATAL
, "invalid symbol visibility found");
262 entry
->visibility
= translate_visibility
[t
];
265 memcpy (&entry
->size
, p
, sizeof (uint64_t));
268 memcpy (&aux
->slot
, p
, sizeof (uint32_t));
271 entry
->resolution
= LDPR_UNKNOWN
;
273 aux
->next_conflict
= -1;
278 /* Translate the IL symbol table located between DATA and END. Append the
279 slots and symbols to OUT. */
282 translate (char *data
, char *end
, struct plugin_symtab
*out
)
285 struct ld_plugin_symbol
*syms
= NULL
;
288 /* This overestimates the output buffer sizes, but at least
289 the algorithm is O(1) now. */
291 len
= (end
- data
)/8 + out
->nsyms
+ 1;
292 syms
= xrealloc (out
->syms
, len
* sizeof (struct ld_plugin_symbol
));
293 aux
= xrealloc (out
->aux
, len
* sizeof (struct sym_aux
));
295 for (n
= out
->nsyms
; data
< end
; n
++)
298 data
= parse_table_entry (data
, &syms
[n
], &aux
[n
]);
308 /* Free all memory that is no longer needed after writing the symbol
315 for (i
= 0; i
< num_claimed_files
; i
++)
317 struct plugin_file_info
*info
= &claimed_files
[i
];
318 struct plugin_symtab
*symtab
= &info
->symtab
;
320 for (j
= 0; j
< symtab
->nsyms
; j
++)
322 struct ld_plugin_symbol
*s
= &symtab
->syms
[j
];
324 free (s
->comdat_key
);
331 /* Free all remaining memory. */
337 for (i
= 0; i
< num_claimed_files
; i
++)
339 struct plugin_file_info
*info
= &claimed_files
[i
];
340 struct plugin_symtab
*symtab
= &info
->symtab
;
345 for (i
= 0; i
< num_output_files
; i
++)
346 free (output_files
[i
]);
349 free (claimed_files
);
350 claimed_files
= NULL
;
351 num_claimed_files
= 0;
353 free (arguments_file_name
);
354 arguments_file_name
= NULL
;
357 /* Dump SYMTAB to resolution file F. */
360 dump_symtab (FILE *f
, struct plugin_symtab
*symtab
)
364 for (j
= 0; j
< symtab
->nsyms
; j
++)
366 uint32_t slot
= symtab
->aux
[j
].slot
;
367 unsigned int resolution
= symtab
->syms
[j
].resolution
;
369 assert (resolution
!= LDPR_UNKNOWN
);
371 fprintf (f
, "%u %" PRI_LL
"x %s %s\n",
372 (unsigned int) slot
, symtab
->aux
[j
].id
,
373 lto_resolution_str
[resolution
],
374 symtab
->syms
[j
].name
);
378 /* Finish the conflicts' resolution information after the linker resolved
379 the original symbols */
382 finish_conflict_resolution (struct plugin_symtab
*symtab
,
383 struct plugin_symtab
*conflicts
)
387 if (conflicts
->nsyms
== 0)
390 for (i
= 0; i
< symtab
->nsyms
; i
++)
392 int resolution
= LDPR_UNKNOWN
;
394 if (symtab
->aux
[i
].next_conflict
== -1)
397 switch (symtab
->syms
[i
].def
)
400 case LDPK_COMMON
: /* ??? */
401 resolution
= LDPR_RESOLVED_IR
;
404 resolution
= LDPR_PREEMPTED_IR
;
408 resolution
= symtab
->syms
[i
].resolution
;
414 assert (resolution
!= LDPR_UNKNOWN
);
416 for (j
= symtab
->aux
[i
].next_conflict
;
418 j
= conflicts
->aux
[j
].next_conflict
)
419 conflicts
->syms
[j
].resolution
= resolution
;
423 /* Free symbol table SYMTAB. */
426 free_symtab (struct plugin_symtab
*symtab
)
434 /* Writes the relocations to disk. */
437 write_resolution (void)
442 check (resolution_file
, LDPL_FATAL
, "resolution file not specified");
443 f
= fopen (resolution_file
, "w");
444 check (f
, LDPL_FATAL
, "could not open file");
446 fprintf (f
, "%d\n", num_claimed_files
);
448 for (i
= 0; i
< num_claimed_files
; i
++)
450 struct plugin_file_info
*info
= &claimed_files
[i
];
451 struct plugin_symtab
*symtab
= &info
->symtab
;
452 struct ld_plugin_symbol
*syms
= symtab
->syms
;
454 /* Version 2 of API supports IRONLY_EXP resolution that is
455 accepted by GCC-4.7 and newer. */
457 get_symbols_v2 (info
->handle
, symtab
->nsyms
, syms
);
459 get_symbols (info
->handle
, symtab
->nsyms
, syms
);
461 finish_conflict_resolution (symtab
, &info
->conflicts
);
463 fprintf (f
, "%s %d\n", info
->name
, symtab
->nsyms
+ info
->conflicts
.nsyms
);
464 dump_symtab (f
, symtab
);
465 if (info
->conflicts
.nsyms
)
467 dump_symtab (f
, &info
->conflicts
);
468 free_symtab (&info
->conflicts
);
474 /* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
478 add_output_files (FILE *f
)
482 const unsigned piece
= 32;
483 char *buf
, *s
= xmalloc (piece
);
488 if (!fgets (buf
, piece
, f
))
494 if (s
[len
- 1] != '\n')
496 s
= xrealloc (s
, len
+ piece
);
504 = xrealloc (output_files
, num_output_files
* sizeof (char *));
505 output_files
[num_output_files
- 1] = s
;
506 add_input_file (output_files
[num_output_files
- 1]);
510 /* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
514 exec_lto_wrapper (char *argv
[])
520 FILE *wrapper_output
;
525 /* Write argv to a file to avoid a command line that is too long. */
526 arguments_file_name
= make_temp_file ("");
527 check (arguments_file_name
, LDPL_FATAL
,
528 "Failed to generate a temorary file name");
530 args
= fopen (arguments_file_name
, "w");
531 check (args
, LDPL_FATAL
, "could not open arguments file");
533 t
= writeargv (&argv
[1], args
);
534 check (t
== 0, LDPL_FATAL
, "could not write arguments");
536 check (t
== 0, LDPL_FATAL
, "could not close arguments file");
538 at_args
= concat ("@", arguments_file_name
, NULL
);
539 check (at_args
, LDPL_FATAL
, "could not allocate");
541 for (i
= 1; argv
[i
]; i
++)
544 if (a
[0] == '-' && a
[1] == 'v' && a
[2] == '\0')
546 for (i
= 0; argv
[i
]; i
++)
547 fprintf (stderr
, "%s ", argv
[i
]);
548 fprintf (stderr
, "\n");
553 new_argv
[0] = argv
[0];
554 new_argv
[1] = at_args
;
559 for (i
= 0; new_argv
[i
]; i
++)
560 fprintf (stderr
, "%s ", new_argv
[i
]);
561 fprintf (stderr
, "\n");
565 pex
= pex_init (PEX_USE_PIPES
, "lto-wrapper", NULL
);
566 check (pex
!= NULL
, LDPL_FATAL
, "could not pex_init lto-wrapper");
568 errmsg
= pex_run (pex
, 0, new_argv
[0], new_argv
, NULL
, NULL
, &t
);
569 check (errmsg
== NULL
, LDPL_FATAL
, "could not run lto-wrapper");
570 check (t
== 0, LDPL_FATAL
, "could not run lto-wrapper");
572 wrapper_output
= pex_read_output (pex
, 0);
573 check (wrapper_output
, LDPL_FATAL
, "could not read lto-wrapper output");
575 add_output_files (wrapper_output
);
577 t
= pex_get_status (pex
, 1, &status
);
578 check (t
== 1, LDPL_FATAL
, "could not get lto-wrapper exit status");
579 check (WIFEXITED (status
) && WEXITSTATUS (status
) == 0, LDPL_FATAL
,
580 "lto-wrapper failed");
587 /* Pass the original files back to the linker. */
590 use_original_files (void)
593 for (i
= 0; i
< num_claimed_files
; i
++)
595 struct plugin_file_info
*info
= &claimed_files
[i
];
596 add_input_file (info
->name
);
601 /* Called by the linker once all symbols have been read. */
603 static enum ld_plugin_status
604 all_symbols_read_handler (void)
607 unsigned num_lto_args
= num_claimed_files
+ lto_wrapper_num_args
+ 1;
609 const char **lto_arg_ptr
;
610 if (num_claimed_files
== 0)
615 use_original_files ();
619 lto_argv
= (char **) xcalloc (sizeof (char *), num_lto_args
);
620 lto_arg_ptr
= (const char **) lto_argv
;
621 assert (lto_wrapper_argv
);
627 for (i
= 0; i
< lto_wrapper_num_args
; i
++)
628 *lto_arg_ptr
++ = lto_wrapper_argv
[i
];
630 for (i
= 0; i
< num_claimed_files
; i
++)
632 struct plugin_file_info
*info
= &claimed_files
[i
];
634 *lto_arg_ptr
++ = info
->name
;
637 *lto_arg_ptr
++ = NULL
;
638 exec_lto_wrapper (lto_argv
);
642 /* --pass-through is not needed when using gold 1.11 or later. */
643 if (pass_through_items
&& gold_version
< 111)
646 for (i
= 0; i
< num_pass_through_items
; i
++)
648 if (strncmp (pass_through_items
[i
], "-l", 2) == 0)
649 add_input_library (pass_through_items
[i
] + 2);
651 add_input_file (pass_through_items
[i
]);
652 free (pass_through_items
[i
]);
653 pass_through_items
[i
] = NULL
;
655 free (pass_through_items
);
656 pass_through_items
= NULL
;
662 /* Remove temporary files at the end of the link. */
664 static enum ld_plugin_status
665 cleanup_handler (void)
673 if (arguments_file_name
)
675 t
= unlink (arguments_file_name
);
676 check (t
== 0, LDPL_FATAL
, "could not unlink arguments file");
679 for (i
= 0; i
< num_output_files
; i
++)
681 t
= unlink (output_files
[i
]);
682 check (t
== 0, LDPL_FATAL
, "could not unlink output file");
689 #define SWAP(type, a, b) \
690 do { type tmp_; tmp_ = (a); (a) = (b); (b) = tmp_; } while(0)
692 /* Compare two hash table entries */
694 static int eq_sym (const void *a
, const void *b
)
696 const struct ld_plugin_symbol
*as
= (const struct ld_plugin_symbol
*)a
;
697 const struct ld_plugin_symbol
*bs
= (const struct ld_plugin_symbol
*)b
;
699 return !strcmp (as
->name
, bs
->name
);
704 static hashval_t
hash_sym (const void *a
)
706 const struct ld_plugin_symbol
*as
= (const struct ld_plugin_symbol
*)a
;
708 return htab_hash_string (as
->name
);
711 /* Determine how strong a symbol is */
713 static int symbol_strength (struct ld_plugin_symbol
*s
)
727 /* In the ld -r case we can get dups in the LTO symbol tables, where
728 the same symbol can have different resolutions (e.g. undefined and defined).
730 We have to keep that in the LTO symbol tables, but the dups confuse
731 gold and then finally gcc by supplying incorrect resolutions.
733 Problem is that the main gold symbol table doesn't know about subids
734 and does not distingush the same symbols in different states.
736 So we drop duplicates from the linker visible symbol table
737 and keep them in a private table. Then later do own symbol
738 resolution for the duplicated based on the results for the
741 Then when writing out the resolution file readd the dropped symbols.
743 XXX how to handle common? */
746 resolve_conflicts (struct plugin_symtab
*t
, struct plugin_symtab
*conflicts
)
748 htab_t symtab
= htab_create (t
->nsyms
, hash_sym
, eq_sym
, NULL
);
754 conflicts
->syms
= xmalloc (sizeof (struct ld_plugin_symbol
) * outlen
);
755 conflicts
->aux
= xmalloc (sizeof (struct sym_aux
) * outlen
);
757 /* Move all duplicate symbols into the auxiliary conflicts table. */
759 for (i
= 0; i
< t
->nsyms
; i
++)
761 struct ld_plugin_symbol
*s
= &t
->syms
[i
];
762 struct sym_aux
*aux
= &t
->aux
[i
];
765 slot
= htab_find_slot (symtab
, s
, INSERT
);
769 struct ld_plugin_symbol
*orig
= (struct ld_plugin_symbol
*)*slot
;
770 struct sym_aux
*orig_aux
= &t
->aux
[orig
- t
->syms
];
772 /* Always let the linker resolve the strongest symbol */
773 if (symbol_strength (orig
) < symbol_strength (s
))
775 SWAP (struct ld_plugin_symbol
, *orig
, *s
);
776 SWAP (uint32_t, orig_aux
->slot
, aux
->slot
);
777 SWAP (unsigned long long, orig_aux
->id
, aux
->id
);
778 /* Don't swap conflict chain pointer */
781 /* Move current symbol into the conflicts table */
782 cnf
= conflicts
->nsyms
++;
783 conflicts
->syms
[cnf
] = *s
;
784 conflicts
->aux
[cnf
] = *aux
;
785 aux
= &conflicts
->aux
[cnf
];
787 /* Update conflicts chain of the original symbol */
788 aux
->next_conflict
= orig_aux
->next_conflict
;
789 orig_aux
->next_conflict
= cnf
;
794 /* Remove previous duplicates in the main table */
801 /* Put original into the hash table */
802 *slot
= &t
->syms
[out
];
806 assert (conflicts
->nsyms
<= outlen
);
807 assert (conflicts
->nsyms
+ out
== t
->nsyms
);
810 htab_delete (symtab
);
813 /* Process one section of an object file. */
816 process_symtab (void *data
, const char *name
, off_t offset
, off_t length
)
818 struct plugin_objfile
*obj
= (struct plugin_objfile
*)data
;
822 if (strncmp (name
, LTO_SECTION_PREFIX
, LTO_SECTION_PREFIX_LEN
) != 0)
825 s
= strrchr (name
, '.');
827 sscanf (s
, ".%" PRI_LL
"x", &obj
->out
->id
);
828 secdata
= xmalloc (length
);
829 offset
+= obj
->file
->offset
;
830 if (offset
!= lseek (obj
->file
->fd
, offset
, SEEK_SET
)
831 || length
!= read (obj
->file
->fd
, secdata
, length
))
834 message (LDPL_FATAL
, "%s: corrupt object file", obj
->file
->name
);
835 /* Force claim_file_handler to abandon this file. */
841 translate (secdata
, secdata
+ length
, obj
->out
);
847 /* Callback used by gold to check if the plugin will claim FILE. Writes
848 the result in CLAIMED. */
850 static enum ld_plugin_status
851 claim_file_handler (const struct ld_plugin_input_file
*file
, int *claimed
)
853 enum ld_plugin_status status
;
854 struct plugin_objfile obj
;
855 struct plugin_file_info lto_file
;
859 memset (<o_file
, 0, sizeof (struct plugin_file_info
));
861 if (file
->offset
!= 0)
864 /* We pass the offset of the actual file, not the archive header.
865 Can't use PRIx64, because that's C99, so we have to print the
866 64-bit hex int as two 32-bit ones. */
868 lo
= file
->offset
& 0xffffffff;
869 hi
= ((int64_t)file
->offset
>> 32) & 0xffffffff;
870 t
= hi
? asprintf (&objname
, "%s@0x%x%08x", file
->name
, lo
, hi
)
871 : asprintf (&objname
, "%s@0x%x", file
->name
, lo
);
872 check (t
>= 0, LDPL_FATAL
, "asprintf failed");
873 lto_file
.name
= objname
;
877 lto_file
.name
= xstrdup (file
->name
);
879 lto_file
.handle
= file
->handle
;
884 obj
.out
= <o_file
.symtab
;
886 obj
.objfile
= simple_object_start_read (file
->fd
, file
->offset
, LTO_SEGMENT_NAME
,
888 /* No file, but also no error code means unrecognized format; just skip it. */
889 if (!obj
.objfile
&& !err
)
893 errmsg
= simple_object_find_sections (obj
.objfile
, process_symtab
, &obj
, &err
);
895 if (!obj
.objfile
|| errmsg
)
898 message (LDPL_FATAL
, "%s: %s: %s", file
->name
, errmsg
,
901 message (LDPL_FATAL
, "%s: %s", file
->name
, errmsg
);
909 resolve_conflicts (<o_file
.symtab
, <o_file
.conflicts
);
911 status
= add_symbols (file
->handle
, lto_file
.symtab
.nsyms
,
912 lto_file
.symtab
.syms
);
913 check (status
== LDPS_OK
, LDPL_FATAL
, "could not add symbols");
918 xrealloc (claimed_files
,
919 num_claimed_files
* sizeof (struct plugin_file_info
));
920 claimed_files
[num_claimed_files
- 1] = lto_file
;
925 free (lto_file
.name
);
929 simple_object_release_read (obj
.objfile
);
934 /* Parse the plugin options. */
937 process_option (const char *option
)
939 if (strcmp (option
, "-debug") == 0)
941 else if (strcmp (option
, "-nop") == 0)
943 else if (!strncmp (option
, "-pass-through=", strlen("-pass-through=")))
945 num_pass_through_items
++;
946 pass_through_items
= xrealloc (pass_through_items
,
947 num_pass_through_items
* sizeof (char *));
948 pass_through_items
[num_pass_through_items
- 1] =
949 xstrdup (option
+ strlen ("-pass-through="));
951 else if (!strncmp (option
, "-sym-style=", sizeof ("-sym-style=") - 1))
953 switch (option
[sizeof ("-sym-style=") - 1])
956 sym_style
= ss_win32
;
959 sym_style
= ss_uscore
;
969 char *opt
= xstrdup (option
);
970 lto_wrapper_num_args
+= 1;
971 size
= lto_wrapper_num_args
* sizeof (char *);
972 lto_wrapper_argv
= (char **) xrealloc (lto_wrapper_argv
, size
);
973 lto_wrapper_argv
[lto_wrapper_num_args
- 1] = opt
;
974 if (strncmp (option
, "-fresolution=", sizeof ("-fresolution=") - 1) == 0)
975 resolution_file
= opt
+ sizeof ("-fresolution=") - 1;
979 /* Called by gold after loading the plugin. TV is the transfer vector. */
981 enum ld_plugin_status
982 onload (struct ld_plugin_tv
*tv
)
984 struct ld_plugin_tv
*p
;
985 enum ld_plugin_status status
;
993 message
= p
->tv_u
.tv_message
;
995 case LDPT_REGISTER_CLAIM_FILE_HOOK
:
996 register_claim_file
= p
->tv_u
.tv_register_claim_file
;
998 case LDPT_ADD_SYMBOLS
:
999 add_symbols
= p
->tv_u
.tv_add_symbols
;
1001 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK
:
1002 register_all_symbols_read
= p
->tv_u
.tv_register_all_symbols_read
;
1004 case LDPT_GET_SYMBOLS_V2
:
1005 get_symbols_v2
= p
->tv_u
.tv_get_symbols
;
1007 case LDPT_GET_SYMBOLS
:
1008 get_symbols
= p
->tv_u
.tv_get_symbols
;
1010 case LDPT_REGISTER_CLEANUP_HOOK
:
1011 register_cleanup
= p
->tv_u
.tv_register_cleanup
;
1013 case LDPT_ADD_INPUT_FILE
:
1014 add_input_file
= p
->tv_u
.tv_add_input_file
;
1016 case LDPT_ADD_INPUT_LIBRARY
:
1017 add_input_library
= p
->tv_u
.tv_add_input_library
;
1020 process_option (p
->tv_u
.tv_string
);
1022 case LDPT_GOLD_VERSION
:
1023 gold_version
= p
->tv_u
.tv_val
;
1031 check (register_claim_file
, LDPL_FATAL
, "register_claim_file not found");
1032 check (add_symbols
, LDPL_FATAL
, "add_symbols not found");
1033 status
= register_claim_file (claim_file_handler
);
1034 check (status
== LDPS_OK
, LDPL_FATAL
,
1035 "could not register the claim_file callback");
1037 if (register_cleanup
)
1039 status
= register_cleanup (cleanup_handler
);
1040 check (status
== LDPS_OK
, LDPL_FATAL
,
1041 "could not register the cleanup callback");
1044 if (register_all_symbols_read
)
1046 check (get_symbols
, LDPL_FATAL
, "get_symbols not found");
1047 status
= register_all_symbols_read (all_symbols_read_handler
);
1048 check (status
== LDPS_OK
, LDPL_FATAL
,
1049 "could not register the all_symbols_read callback");