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>
51 #include <libiberty.h>
53 #include "../gcc/lto/common.h"
54 #include "simple-object.h"
55 #include "plugin-api.h"
57 /* Handle opening elf files on hosts, such as Windows, that may use
58 text file handling that will break binary access. */
63 /* Segment name for LTO sections. This is only used for Mach-O.
64 FIXME: This needs to be kept in sync with darwin.c. */
66 #define LTO_SEGMENT_NAME "__GNU_LTO"
68 /* LTO magic section name. */
70 #define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
71 #define LTO_SECTION_PREFIX_LEN (sizeof (LTO_SECTION_PREFIX) - 1)
73 /* The part of the symbol table the plugin has to keep track of. Note that we
74 must keep SYMS until all_symbols_read is called to give the linker time to
75 copy the symbol information. */
81 unsigned next_conflict
;
88 struct ld_plugin_symbol
*syms
;
92 /* Encapsulates object file data during symbol scan. */
96 simple_object_read
*objfile
;
97 struct plugin_symtab
*out
;
98 const struct ld_plugin_input_file
*file
;
101 /* All that we have to remember about a file. */
103 struct plugin_file_info
107 struct plugin_symtab symtab
;
108 struct plugin_symtab conflicts
;
111 /* Until ASM_OUTPUT_LABELREF can be hookized and decoupled from
112 stdio file streams, we do simple label translation here. */
116 ss_none
, /* No underscore prefix. */
117 ss_win32
, /* Underscore prefix any symbol not beginning with '@'. */
118 ss_uscore
, /* Underscore prefix all symbols. */
121 static char *arguments_file_name
;
122 static ld_plugin_register_claim_file register_claim_file
;
123 static ld_plugin_register_all_symbols_read register_all_symbols_read
;
124 static ld_plugin_get_symbols get_symbols
;
125 static ld_plugin_register_cleanup register_cleanup
;
126 static ld_plugin_add_input_file add_input_file
;
127 static ld_plugin_add_input_library add_input_library
;
128 static ld_plugin_message message
;
129 static ld_plugin_add_symbols add_symbols
;
131 static struct plugin_file_info
*claimed_files
= NULL
;
132 static unsigned int num_claimed_files
= 0;
134 static char **output_files
= NULL
;
135 static unsigned int num_output_files
= 0;
137 static char **lto_wrapper_argv
;
138 static int lto_wrapper_num_args
;
140 static char **pass_through_items
= NULL
;
141 static unsigned int num_pass_through_items
;
145 static char *resolution_file
= NULL
;
147 /* Set by default from configure.ac, but can be overridden at runtime
148 by using -plugin-opt=-sym-style={none,win32,underscore|uscore}
149 (in fact, only first letter of style arg is checked.) */
150 static enum symbol_style sym_style
= SYM_STYLE
;
153 check_1 (int gate
, enum ld_plugin_level level
, const char *text
)
159 message (level
, text
);
162 /* If there is no nicer way to inform the user, fallback to stderr. */
163 fprintf (stderr
, "%s\n", text
);
164 if (level
== LDPL_FATAL
)
169 /* This little wrapper allows check to be called with a non-integer
170 first argument, such as a pointer that must be non-NULL. We can't
171 use c99 bool type to coerce it into range, so we explicitly test. */
172 #define check(GATE, LEVEL, TEXT) check_1 (((GATE) != 0), (LEVEL), (TEXT))
174 /* Parse an entry of the IL symbol table. The data to be parsed is pointed
175 by P and the result is written in ENTRY. The slot number is stored in SLOT.
176 Returns the address of the next entry. */
179 parse_table_entry (char *p
, struct ld_plugin_symbol
*entry
,
183 enum ld_plugin_symbol_kind translate_kind
[] =
192 enum ld_plugin_symbol_visibility translate_visibility
[] =
205 /* cf. Duff's device. */
207 entry
->name
= xstrdup (p
);
212 entry
->name
= concat ("_", p
, NULL
);
215 check (0, LDPL_FATAL
, "invalid symbol style requested");
222 entry
->version
= NULL
;
224 entry
->comdat_key
= p
;
229 if (strlen (entry
->comdat_key
) == 0)
230 entry
->comdat_key
= NULL
;
232 entry
->comdat_key
= xstrdup (entry
->comdat_key
);
235 check (t
<= 4, LDPL_FATAL
, "invalid symbol kind found");
236 entry
->def
= translate_kind
[t
];
240 check (t
<= 3, LDPL_FATAL
, "invalid symbol visibility found");
241 entry
->visibility
= translate_visibility
[t
];
244 entry
->size
= *(uint64_t *) p
;
247 aux
->slot
= *(uint32_t *) p
;
250 entry
->resolution
= LDPR_UNKNOWN
;
252 aux
->next_conflict
= -1;
257 /* Translate the IL symbol table located between DATA and END. Append the
258 slots and symbols to OUT. */
261 translate (char *data
, char *end
, struct plugin_symtab
*out
)
264 struct ld_plugin_symbol
*syms
= NULL
;
267 /* This overestimates the output buffer sizes, but at least
268 the algorithm is O(1) now. */
270 len
= (end
- data
)/8 + out
->nsyms
+ 1;
271 syms
= xrealloc (out
->syms
, len
* sizeof (struct ld_plugin_symbol
));
272 aux
= xrealloc (out
->aux
, len
* sizeof (struct sym_aux
));
274 for (n
= out
->nsyms
; data
< end
; n
++)
277 data
= parse_table_entry (data
, &syms
[n
], &aux
[n
]);
287 /* Free all memory that is no longer needed after writing the symbol
294 for (i
= 0; i
< num_claimed_files
; i
++)
296 struct plugin_file_info
*info
= &claimed_files
[i
];
297 struct plugin_symtab
*symtab
= &info
->symtab
;
299 for (j
= 0; j
< symtab
->nsyms
; j
++)
301 struct ld_plugin_symbol
*s
= &symtab
->syms
[j
];
304 free (s
->comdat_key
);
311 /* Free all remaining memory. */
317 for (i
= 0; i
< num_claimed_files
; i
++)
319 struct plugin_file_info
*info
= &claimed_files
[i
];
320 struct plugin_symtab
*symtab
= &info
->symtab
;
325 for (i
= 0; i
< num_output_files
; i
++)
326 free (output_files
[i
]);
329 free (claimed_files
);
330 claimed_files
= NULL
;
331 num_claimed_files
= 0;
333 if (arguments_file_name
)
334 free (arguments_file_name
);
335 arguments_file_name
= NULL
;
338 /* Dump SYMTAB to resolution file F. */
341 dump_symtab (FILE *f
, struct plugin_symtab
*symtab
)
345 for (j
= 0; j
< symtab
->nsyms
; j
++)
347 uint32_t slot
= symtab
->aux
[j
].slot
;
348 unsigned int resolution
= symtab
->syms
[j
].resolution
;
350 assert (resolution
!= LDPR_UNKNOWN
);
352 fprintf (f
, "%u %x %s %s\n", (unsigned int) slot
, symtab
->aux
[j
].id
,
353 lto_resolution_str
[resolution
],
354 symtab
->syms
[j
].name
);
358 /* Finish the conflicts' resolution information after the linker resolved
359 the original symbols */
362 finish_conflict_resolution (struct plugin_symtab
*symtab
,
363 struct plugin_symtab
*conflicts
)
367 if (conflicts
->nsyms
== 0)
370 for (i
= 0; i
< symtab
->nsyms
; i
++)
372 int resolution
= LDPR_UNKNOWN
;
374 if (symtab
->aux
[i
].next_conflict
== -1)
377 switch (symtab
->syms
[i
].def
)
380 case LDPK_COMMON
: /* ??? */
381 resolution
= LDPR_RESOLVED_IR
;
384 resolution
= LDPR_PREEMPTED_IR
;
388 resolution
= symtab
->syms
[i
].resolution
;
394 assert (resolution
!= LDPR_UNKNOWN
);
396 for (j
= symtab
->aux
[i
].next_conflict
;
398 j
= conflicts
->aux
[j
].next_conflict
)
399 conflicts
->syms
[j
].resolution
= resolution
;
403 /* Free symbol table SYMTAB. */
406 free_symtab (struct plugin_symtab
*symtab
)
414 /* Writes the relocations to disk. */
417 write_resolution (void)
422 check (resolution_file
, LDPL_FATAL
, "resolution file not specified");
423 f
= fopen (resolution_file
, "w");
424 check (f
, LDPL_FATAL
, "could not open file");
426 fprintf (f
, "%d\n", num_claimed_files
);
428 for (i
= 0; i
< num_claimed_files
; i
++)
430 struct plugin_file_info
*info
= &claimed_files
[i
];
431 struct plugin_symtab
*symtab
= &info
->symtab
;
432 struct ld_plugin_symbol
*syms
= symtab
->syms
;
434 get_symbols (info
->handle
, symtab
->nsyms
, syms
);
436 finish_conflict_resolution (symtab
, &info
->conflicts
);
438 fprintf (f
, "%s %d\n", info
->name
, symtab
->nsyms
+ info
->conflicts
.nsyms
);
439 dump_symtab (f
, symtab
);
440 if (info
->conflicts
.nsyms
)
442 dump_symtab (f
, &info
->conflicts
);
443 free_symtab (&info
->conflicts
);
449 /* Pass files generated by the lto-wrapper to the linker. FD is lto-wrapper's
453 add_output_files (FILE *f
)
457 const unsigned piece
= 32;
458 char *buf
, *s
= xmalloc (piece
);
463 if (!fgets (buf
, piece
, f
))
469 if (s
[len
- 1] != '\n')
471 s
= xrealloc (s
, len
+ piece
);
479 = xrealloc (output_files
, num_output_files
* sizeof (char *));
480 output_files
[num_output_files
- 1] = s
;
481 add_input_file (output_files
[num_output_files
- 1]);
485 /* Execute the lto-wrapper. ARGV[0] is the binary. The rest of ARGV is the
489 exec_lto_wrapper (char *argv
[])
495 FILE *wrapper_output
;
500 /* Write argv to a file to avoid a command line that is too long. */
501 arguments_file_name
= make_temp_file ("");
502 check (arguments_file_name
, LDPL_FATAL
,
503 "Failed to generate a temorary file name");
505 args
= fopen (arguments_file_name
, "w");
506 check (args
, LDPL_FATAL
, "could not open arguments file");
508 t
= writeargv (&argv
[1], args
);
509 check (t
== 0, LDPL_FATAL
, "could not write arguments");
511 check (t
== 0, LDPL_FATAL
, "could not close arguments file");
513 at_args
= concat ("@", arguments_file_name
, NULL
);
514 check (at_args
, LDPL_FATAL
, "could not allocate");
516 for (i
= 1; argv
[i
]; i
++)
519 if (a
[0] == '-' && a
[1] == 'v' && a
[2] == '\0')
521 for (i
= 0; argv
[i
]; i
++)
522 fprintf (stderr
, "%s ", argv
[i
]);
523 fprintf (stderr
, "\n");
528 new_argv
[0] = argv
[0];
529 new_argv
[1] = at_args
;
534 for (i
= 0; new_argv
[i
]; i
++)
535 fprintf (stderr
, "%s ", new_argv
[i
]);
536 fprintf (stderr
, "\n");
540 pex
= pex_init (PEX_USE_PIPES
, "lto-wrapper", NULL
);
541 check (pex
!= NULL
, LDPL_FATAL
, "could not pex_init lto-wrapper");
543 errmsg
= pex_run (pex
, 0, new_argv
[0], new_argv
, NULL
, NULL
, &t
);
544 check (errmsg
== NULL
, LDPL_FATAL
, "could not run lto-wrapper");
545 check (t
== 0, LDPL_FATAL
, "could not run lto-wrapper");
547 wrapper_output
= pex_read_output (pex
, 0);
548 check (wrapper_output
, LDPL_FATAL
, "could not read lto-wrapper output");
550 add_output_files (wrapper_output
);
552 t
= pex_get_status (pex
, 1, &status
);
553 check (t
== 1, LDPL_FATAL
, "could not get lto-wrapper exit status");
554 check (WIFEXITED (status
) && WEXITSTATUS (status
) == 0, LDPL_FATAL
,
555 "lto-wrapper failed");
562 /* Pass the original files back to the linker. */
565 use_original_files (void)
568 for (i
= 0; i
< num_claimed_files
; i
++)
570 struct plugin_file_info
*info
= &claimed_files
[i
];
571 add_input_file (info
->name
);
576 /* Called by the linker once all symbols have been read. */
578 static enum ld_plugin_status
579 all_symbols_read_handler (void)
582 unsigned num_lto_args
= num_claimed_files
+ lto_wrapper_num_args
+ 1;
584 const char **lto_arg_ptr
;
585 if (num_claimed_files
== 0)
590 use_original_files ();
594 lto_argv
= (char **) xcalloc (sizeof (char *), num_lto_args
);
595 lto_arg_ptr
= (const char **) lto_argv
;
596 assert (lto_wrapper_argv
);
602 for (i
= 0; i
< lto_wrapper_num_args
; i
++)
603 *lto_arg_ptr
++ = lto_wrapper_argv
[i
];
605 for (i
= 0; i
< num_claimed_files
; i
++)
607 struct plugin_file_info
*info
= &claimed_files
[i
];
609 *lto_arg_ptr
++ = info
->name
;
612 *lto_arg_ptr
++ = NULL
;
613 exec_lto_wrapper (lto_argv
);
617 if (pass_through_items
)
620 for (i
= 0; i
< num_pass_through_items
; i
++)
622 if (strncmp (pass_through_items
[i
], "-l", 2) == 0)
623 add_input_library (pass_through_items
[i
] + 2);
625 add_input_file (pass_through_items
[i
]);
626 free (pass_through_items
[i
]);
627 pass_through_items
[i
] = NULL
;
629 free (pass_through_items
);
630 pass_through_items
= NULL
;
636 /* Remove temporary files at the end of the link. */
638 static enum ld_plugin_status
639 cleanup_handler (void)
647 if (arguments_file_name
)
649 t
= unlink (arguments_file_name
);
650 check (t
== 0, LDPL_FATAL
, "could not unlink arguments file");
653 for (i
= 0; i
< num_output_files
; i
++)
655 t
= unlink (output_files
[i
]);
656 check (t
== 0, LDPL_FATAL
, "could not unlink output file");
663 #define SWAP(type, a, b) \
664 do { type tmp_; tmp_ = (a); (a) = (b); (b) = tmp_; } while(0)
666 /* Compare two hash table entries */
668 static int eq_sym (const void *a
, const void *b
)
670 const struct ld_plugin_symbol
*as
= (const struct ld_plugin_symbol
*)a
;
671 const struct ld_plugin_symbol
*bs
= (const struct ld_plugin_symbol
*)b
;
673 return !strcmp (as
->name
, bs
->name
);
678 static hashval_t
hash_sym (const void *a
)
680 const struct ld_plugin_symbol
*as
= (const struct ld_plugin_symbol
*)a
;
682 return htab_hash_string (as
->name
);
685 /* Determine how strong a symbol is */
687 static int symbol_strength (struct ld_plugin_symbol
*s
)
701 /* In the ld -r case we can get dups in the LTO symbol tables, where
702 the same symbol can have different resolutions (e.g. undefined and defined).
704 We have to keep that in the LTO symbol tables, but the dups confuse
705 gold and then finally gcc by supplying incorrect resolutions.
707 Problem is that the main gold symbol table doesn't know about subids
708 and does not distingush the same symbols in different states.
710 So we drop duplicates from the linker visible symbol table
711 and keep them in a private table. Then later do own symbol
712 resolution for the duplicated based on the results for the
715 Then when writing out the resolution file readd the dropped symbols.
717 XXX how to handle common? */
720 resolve_conflicts (struct plugin_symtab
*t
, struct plugin_symtab
*conflicts
)
722 htab_t symtab
= htab_create (t
->nsyms
, hash_sym
, eq_sym
, NULL
);
728 conflicts
->syms
= xmalloc (sizeof (struct ld_plugin_symbol
) * outlen
);
729 conflicts
->aux
= xmalloc (sizeof (struct sym_aux
) * outlen
);
731 /* Move all duplicate symbols into the auxillary conflicts table. */
733 for (i
= 0; i
< t
->nsyms
; i
++)
735 struct ld_plugin_symbol
*s
= &t
->syms
[i
];
736 struct sym_aux
*aux
= &t
->aux
[i
];
739 slot
= htab_find_slot (symtab
, s
, INSERT
);
743 struct ld_plugin_symbol
*orig
= (struct ld_plugin_symbol
*)*slot
;
744 struct sym_aux
*orig_aux
= &t
->aux
[orig
- t
->syms
];
746 /* Always let the linker resolve the strongest symbol */
747 if (symbol_strength (orig
) < symbol_strength (s
))
749 SWAP (struct ld_plugin_symbol
, *orig
, *s
);
750 SWAP (uint32_t, orig_aux
->slot
, aux
->slot
);
751 SWAP (unsigned, orig_aux
->id
, aux
->id
);
752 /* Don't swap conflict chain pointer */
755 /* Move current symbol into the conflicts table */
756 cnf
= conflicts
->nsyms
++;
757 conflicts
->syms
[cnf
] = *s
;
758 conflicts
->aux
[cnf
] = *aux
;
759 aux
= &conflicts
->aux
[cnf
];
761 /* Update conflicts chain of the original symbol */
762 aux
->next_conflict
= orig_aux
->next_conflict
;
763 orig_aux
->next_conflict
= cnf
;
768 /* Remove previous duplicates in the main table */
775 /* Put original into the hash table */
776 *slot
= &t
->syms
[out
];
780 assert (conflicts
->nsyms
<= outlen
);
781 assert (conflicts
->nsyms
+ out
== t
->nsyms
);
784 htab_delete (symtab
);
787 /* Process one section of an object file. */
790 process_symtab (void *data
, const char *name
, off_t offset
, off_t length
)
792 struct plugin_objfile
*obj
= (struct plugin_objfile
*)data
;
796 if (strncmp (name
, LTO_SECTION_PREFIX
, LTO_SECTION_PREFIX_LEN
) != 0)
799 s
= strrchr (name
, '.');
801 sscanf (s
, ".%x", &obj
->out
->id
);
802 secdata
= xmalloc (length
);
803 offset
+= obj
->file
->offset
;
804 if (offset
!= lseek (obj
->file
->fd
, offset
, SEEK_SET
)
805 || length
!= read (obj
->file
->fd
, secdata
, length
))
808 message (LDPL_FATAL
, "%s: corrupt object file", obj
->file
->name
);
809 /* Force claim_file_handler to abandon this file. */
815 translate (secdata
, secdata
+ length
, obj
->out
);
821 /* Callback used by gold to check if the plugin will claim FILE. Writes
822 the result in CLAIMED. */
824 static enum ld_plugin_status
825 claim_file_handler (const struct ld_plugin_input_file
*file
, int *claimed
)
827 enum ld_plugin_status status
;
828 struct plugin_objfile obj
;
829 struct plugin_file_info lto_file
;
833 memset (<o_file
, 0, sizeof (struct plugin_file_info
));
835 if (file
->offset
!= 0)
838 /* We pass the offset of the actual file, not the archive header.
839 Can't use PRIx64, because that's C99, so we have to print the
840 64-bit hex int as two 32-bit ones. */
842 lo
= file
->offset
& 0xffffffff;
843 hi
= ((int64_t)file
->offset
>> 32) & 0xffffffff;
844 int t
= hi
? asprintf (&objname
, "%s@0x%x%08x", file
->name
, lo
, hi
)
845 : asprintf (&objname
, "%s@0x%x", file
->name
, lo
);
846 check (t
>= 0, LDPL_FATAL
, "asprintf failed");
847 lto_file
.name
= objname
;
851 lto_file
.name
= xstrdup (file
->name
);
853 lto_file
.handle
= file
->handle
;
858 obj
.out
= <o_file
.symtab
;
860 obj
.objfile
= simple_object_start_read (file
->fd
, file
->offset
, LTO_SEGMENT_NAME
,
862 /* No file, but also no error code means unrecognized format; just skip it. */
863 if (!obj
.objfile
&& !err
)
867 errmsg
= simple_object_find_sections (obj
.objfile
, process_symtab
, &obj
, &err
);
869 if (!obj
.objfile
|| errmsg
)
872 message (LDPL_FATAL
, "%s: %s: %s", file
->name
, errmsg
,
875 message (LDPL_FATAL
, "%s: %s", file
->name
, errmsg
);
883 resolve_conflicts (<o_file
.symtab
, <o_file
.conflicts
);
885 status
= add_symbols (file
->handle
, lto_file
.symtab
.nsyms
,
886 lto_file
.symtab
.syms
);
887 check (status
== LDPS_OK
, LDPL_FATAL
, "could not add symbols");
892 xrealloc (claimed_files
,
893 num_claimed_files
* sizeof (struct plugin_file_info
));
894 claimed_files
[num_claimed_files
- 1] = lto_file
;
899 free (lto_file
.name
);
903 simple_object_release_read (obj
.objfile
);
908 /* Parse the plugin options. */
911 process_option (const char *option
)
913 if (strcmp (option
, "-debug") == 0)
915 else if (strcmp (option
, "-nop") == 0)
917 else if (!strncmp (option
, "-pass-through=", strlen("-pass-through=")))
919 num_pass_through_items
++;
920 pass_through_items
= xrealloc (pass_through_items
,
921 num_pass_through_items
* sizeof (char *));
922 pass_through_items
[num_pass_through_items
- 1] =
923 xstrdup (option
+ strlen ("-pass-through="));
925 else if (!strncmp (option
, "-sym-style=", sizeof ("-sym-style=") - 1))
927 switch (option
[sizeof ("-sym-style=") - 1])
930 sym_style
= ss_win32
;
933 sym_style
= ss_uscore
;
943 char *opt
= xstrdup (option
);
944 lto_wrapper_num_args
+= 1;
945 size
= lto_wrapper_num_args
* sizeof (char *);
946 lto_wrapper_argv
= (char **) xrealloc (lto_wrapper_argv
, size
);
947 lto_wrapper_argv
[lto_wrapper_num_args
- 1] = opt
;
948 if (strncmp (option
, "-fresolution=", sizeof ("-fresolution=") - 1) == 0)
949 resolution_file
= opt
+ sizeof ("-fresolution=") - 1;
953 /* Called by gold after loading the plugin. TV is the transfer vector. */
955 enum ld_plugin_status
956 onload (struct ld_plugin_tv
*tv
)
958 struct ld_plugin_tv
*p
;
959 enum ld_plugin_status status
;
967 message
= p
->tv_u
.tv_message
;
969 case LDPT_REGISTER_CLAIM_FILE_HOOK
:
970 register_claim_file
= p
->tv_u
.tv_register_claim_file
;
972 case LDPT_ADD_SYMBOLS
:
973 add_symbols
= p
->tv_u
.tv_add_symbols
;
975 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK
:
976 register_all_symbols_read
= p
->tv_u
.tv_register_all_symbols_read
;
978 case LDPT_GET_SYMBOLS
:
979 get_symbols
= p
->tv_u
.tv_get_symbols
;
981 case LDPT_REGISTER_CLEANUP_HOOK
:
982 register_cleanup
= p
->tv_u
.tv_register_cleanup
;
984 case LDPT_ADD_INPUT_FILE
:
985 add_input_file
= p
->tv_u
.tv_add_input_file
;
987 case LDPT_ADD_INPUT_LIBRARY
:
988 add_input_library
= p
->tv_u
.tv_add_input_library
;
991 process_option (p
->tv_u
.tv_string
);
999 check (register_claim_file
, LDPL_FATAL
, "register_claim_file not found");
1000 check (add_symbols
, LDPL_FATAL
, "add_symbols not found");
1001 status
= register_claim_file (claim_file_handler
);
1002 check (status
== LDPS_OK
, LDPL_FATAL
,
1003 "could not register the claim_file callback");
1005 if (register_cleanup
)
1007 status
= register_cleanup (cleanup_handler
);
1008 check (status
== LDPS_OK
, LDPL_FATAL
,
1009 "could not register the cleanup callback");
1012 if (register_all_symbols_read
)
1014 check (get_symbols
, LDPL_FATAL
, "get_symbols not found");
1015 status
= register_all_symbols_read (all_symbols_read_handler
);
1016 check (status
== LDPS_OK
, LDPL_FATAL
,
1017 "could not register the all_symbols_read callback");