mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 12:39:59 +00:00
Applied patch series for LD plugin interface (six parts).
[PATCH] Add infrastructure for plugin API; functionality to follow. include/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 1/6). * plugin-api.h (LDPT_GNU_LD_VERSION): New ld_plugin_tag enum member. ld/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 1/6). * configure.in: Add AC_CHECKs for file io and dlfcn headers and functions and AC_SEARCH for -ldl. (enable_plugins): New shell variable set if above tests find dlopen functionality. (ENABLE_PLUGINS): Add related automake conditional. * configure: Regenerate. * config.in: Likewise. * Makefile.am (PLUGIN_C): Declare plugin C source file, conditional on ENABLE_PLUGINS being defined. (PLUGIN_H): Likewise for header file. (PLUGIN_OBJECT): Likewise for object file. (PLUGIN_CFLAGS): Likewise -D flag required to compile plugin support. (AM_CPPFLAGS): Use PLUGIN_CFLAGS. (CFILES): Use PLUGIN_C. (HFILES): Use PLUGIN_H. (OFILES): Use PLUGIN_OBJECT. (ld_new_SOURCES): Use PLUGIN_C. (noinst_LTLIBRARIES)[ENABLE_PLUGINS]: Declare test plugin. (libldtestplug_la_SOURCES)[ENABLE_PLUGINS]: Add automake definition for test plugin. (libldtestplug_la_CFLAGS)[ENABLE_PLUGINS]: Likewise. (libldtestplug_la_LDFLAGS)[ENABLE_PLUGINS]: Likewise. * Makefile.in: Regenerate. * sysdep.h: Include stdarg.h, unistd.h and one of fcntl.h or sys/file.h where available. Include dlfcn.h when ENABLE_PLUGINS. (O_RDONLY): Supply default definition likewise to bfd's sysdep.h (O_WRONLY): Likewise. (O_RDWR): Likewise. (O_ACCMODE): Likewise. (O_BINARY): Likewise. (SEEK_SET): Likewise. (SEEK_CUR): Likewise. (SEEK_END): Likewise. * ldmisc.c (vfinfo): Make non-static. Add %p format char. * ldmisc.h (vfinfo): Declare extern prototype. * lexsup.c (enum option_values)[ENABLE_PLUGINS]: Add new entries for OPTION_PLUGIN and OPTION_PLUGIN_OPT. (ld_options[])[ENABLE_PLUGINS]: Add option data for the above two. (parse_args)[ENABLE_PLUGINS]: Handle them, and load all plugins once option parsing is complete. * ldmain.c (main)[ENABLE_PLUGINS]: Call plugin cleanup hooks just after lang_finish. * plugin.c: New source file. * plugin.h: Likewise new header. * testplug.c: New source file. ld/testsuite/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 1/6). * ld-bootstrap/bootstrap.exp: Skip static tests also if LD plugins are enabled. * lib/ld-lib.exp (proc regexp_diff): Extend verbose debug output. (proc set_file_contents): Write a file with the supplied content. (run_ld_link_tests): Add new 'ld' action to test linker output. (proc check_plugin_api_available): Return true if linker under test supports the plugin API. * ld-plugin/func.c: New test source file. * ld-plugin/main.c: Likewise. * ld-plugin/text.c: Likewise. * ld-plugin/plugin-1.d: New dump test output pattern script. * ld-plugin/plugin-2.d: Likewise. * ld-plugin/plugin-3.d: Likewise. * ld-plugin/plugin-4.d: Likewise. * ld-plugin/plugin-5.d: Likewise. * ld-plugin/plugin.exp: New test control script. --- [PATCH] Implement claim file and all symbols read hooks and add symbols callback. ld/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 2/6). * ldfile.c (ldfile_try_open_bfd)[ENABLE_PLUGINS]: Don't return early during compat checks if they pass, instead offer any successfully opened and accepted file to the plugin claim file hooks chain. Create a dummy bfd to accept symbols added by the plugin, if the plugin claims the file. * ldlang.c (lang_process)[ENABLE_PLUGINS]: Call plugin all symbols read hook chain before ldemul_after_open. * ldlang.h (struct lang_input_statement_struct): Add new single-bit 'claimed' flag. * plugin.c (IRONLY_SUFFIX): New macro for dummy bfd file suffix. (IRONLY_SUFFIX_LEN): Length of the above string. (plugin_get_ir_dummy_bfd): New function to create the dummy bfd used to store symbols for ir-only files. (is_ir_dummy_bfd): New function to check if a bfd is ir-only. (asymbol_from_plugin_symbol): New function converts symbol formats. (add_symbols): Call it to convert plugin syms to bfd syms and add them to the dummy bfd. * plugin.h: Add missing include guards. (plugin_get_ir_dummy_bfd): Add prototype. (is_ir_dummy_bfd): Likewise. * testplug.c (TV_MESSAGE): New helper macro. (struct claim_file): New struct. (claim_file_t): New typedef. (tag_names[]): Make static and const. (claimfiles_list): New variable. (claimfiles_tail_chain_ptr): Likewise. (last_claimfile): Likewise. (record_claim_file): Record a file to claim on a singly-linked list. (parse_symdefstr): Parse an ASCII representation of a symbol from a plugin option into the fields of a struct ld_plugin_symbol. (record_claimed_file_symbol): Use it to parse plugin option for adding a symbol. (parse_option): Parse claim file and add symbol options. (dump_tv_tag): Use TV_MESSAGE. (onload): Likewise. (onclaim_file): Make static. Use TV_MESSAGE. Scan list of files to claim and claim this file if required, adding any symbols specified. (onall_symbols_read): Make static and use TV_MESSAGE. (oncleanup): Likewise. ld/testsuite/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 2/6). * ld-plugin/plugin-3.d: Enable regexes for new functionality. * ld-plugin/plugin-5.d: Likewise. * ld-plugin/plugin-6.d: New testcase. * ld-plugin/plugin-7.d: Likewise. * ld-plugin/plugin.exp: Use 'nm' on compiled test objects to determine whether symbols in plugin arguments need an underscore prefix. Add new plugin-6.d and plugin-7.d testcases. --- [PATCH] Implement get symbols callback. ld/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 3/6). * ldmain.c (notice)[ENABLE_PLUGINS]: Call plugin_notice. * plugin.c (non_ironly_hash): Add new bfd hash table. (plugin_load_plugins): Exit early if no plugins to load. If plugins do load successfully, set notice_all flag in link info. (get_symbols): Implement. (plugin_load_plugins): Exit early if no plugins to load, else after loading plugins successfully enable notice_all mode. (init_non_ironly_hash): Lazily init non_ironly_hash table. (plugin_notice): Record symbols referenced from non-IR files in the non_ironly_hash. Suppress tracing, cref generation and nocrossrefs tracking for symbols from dummy IR bfds. * plugin.h: Fix formatting. (plugin_notice): Add prototype. * testplug.c (dumpresolutions): New global var. (parse_options): Accept "dumpresolutions". (onall_symbols_read): Get syms and dump resolutions if it was given. ld/testsuite/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 3/6). * ld-plugin/plugin-8.d: New testcase. * ld-plugin/plugin.exp: Invoke it. --- [PATCH] Implement add input file, add input lib and set extra lib path callbacks. ld/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 4/6). * ldlang.c (lang_process)[ENABLE_PLUGINS]: Move invocation of plugin_call_all_symbols_read to before setting of gc_sym_list, and open any new input files that may have been added during it. * ldmain.c (multiple_definition)[ENABLE_PLUGINS]: Call out to plugin_multiple_definition and let it have first say over what to do with the clashing definitions. * plugin.c (no_more_claiming): New boolean variable. (plugin_cached_allow_multiple_defs): Likewise. (add_input_file): Implement. (add_input_library): Likewise. (set_extra_library_path): Likewise. (plugin_call_claim_file): Don't do anything when no_more_claiming set. (plugin_call_all_symbols_read): Set it. Disable link info "allow_multiple_definition" flag, but cache its value. (plugin_multiple_definition): New function. * plugin.h (plugin_multiple_definition): Add prototype. * testplug.c (addfile_enum_t): New enumerated typedef. (add_file_t): New struct typedef. (addfiles_list): New variable. (addfiles_tail_chain_ptr): Likewise. (record_add_file): New function. (parse_option): Parse "add:", "lib:" and "dir:" options and call it. (onall_symbols_read): Iterate the list of new files, libs and dirs, adding them. ld/testsuite/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 4/6). * ld-plugin/plugin-9.d: New testcase. * ld-plugin/plugin.exp: Invoke it. --- [PATCH] Add ELF symbol visibility support to plugin interface. ld/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 5/6). * plugin.c (asymbol_from_plugin_symbol): If the bfd is an ELF bfd, find the elf symbol data and set the visibility in the st_other field. ld/testsuite/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 5/6). * ld-plugin/plugin-ignore.d: New dump test control script. * ld-plugin/plugin-vis-1.d: Likewise. * ld-plugin/plugin.exp: Add list of ELF-only tests and run them if testing on an ELF target. --- [PATCH] Add archive support to plugin interface. bfd/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 6/6). * aoutx.h (aout_link_check_ar_symbols): Take new "subsbfd" reference parameter and pass it when invoking add_archive_element callback. (aout_link_check_archive_element): Handle substitute bfd if it was set during add_archive_element callback in the above. * cofflink.c (coff_link_check_ar_symbols): Take new "subsbfd" reference parameter and pass it when invoking add_archive_element callback. (coff_link_check_archive_element): Handle substitute bfd if it was set during add_archive_element callback in the above. * ecoff.c (read_ext_syms_and_strs): New function holds symbol-reading code factored-out from ecoff_link_check_archive_element. (reread_ext_syms_and_strs): Clear old symbols and call it. (ecoff_link_check_archive_element): Use the above. Handle substitute BFD if one is set by add_archive_element callback. (ecoff_link_add_archive_symbols): Likewise allow bfd substitution. * elflink.c (elf_link_add_archive_symbols): Likewise. * linker.c (generic_link_check_archive_element): Likewise. * pdp11.c (aout_link_check_ar_symbols): Take new "subsbfd" reference parameter and pass it when invoking add_archive_element callback. (aout_link_check_archive_element): Handle substitute bfd if it was set during add_archive_element callback in the above. * vms-alpha.c (alpha_vms_link_add_archive_symbols): Handle substitute BFD if one is set by add_archive_element callback. * xcofflink.c (xcoff_link_check_dynamic_ar_symbols): Take new "subsbfd" reference parameter and pass it when invoking add_archive_element callback. (xcoff_link_check_ar_symbols): Likewise. (xcoff_link_check_archive_element): Handle bfd substitution if it was set by callback in the above. include/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 6/6). * bfdlink.h (struct_bfd_link_callbacks): Document new argument to add_archive_element callback used to return a replacement bfd which is to be added to the hash table in place of the original element. ld/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 6/6). * ldlang.c (load_symbols): Handle bfd subsitution when calling the add_archive_element callback. * ldmain.c (add_archive_element)[ENABLE_PLUGINS]: Offer the archive member to the plugins and if claimed set "subsbfd" output parameter to point to the dummy IR-only BFD. ld/testsuite/ChangeLog: 2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com> Apply LD plugin patch series (part 6/6). * ld-plugin/plugin-10.d: New dump test control script. * ld-plugin/plugin-11.d: Likewise. * ld-plugin/plugin.exp: Run them. ---
This commit is contained in:
parent
c2a41a5128
commit
5d3236eea0
@ -1,3 +1,35 @@
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 6/6).
|
||||
* aoutx.h (aout_link_check_ar_symbols): Take new "subsbfd" reference
|
||||
parameter and pass it when invoking add_archive_element callback.
|
||||
(aout_link_check_archive_element): Handle substitute bfd if it
|
||||
was set during add_archive_element callback in the above.
|
||||
* cofflink.c (coff_link_check_ar_symbols): Take new "subsbfd" reference
|
||||
parameter and pass it when invoking add_archive_element callback.
|
||||
(coff_link_check_archive_element): Handle substitute bfd if it
|
||||
was set during add_archive_element callback in the above.
|
||||
* ecoff.c (read_ext_syms_and_strs): New function holds symbol-reading
|
||||
code factored-out from ecoff_link_check_archive_element.
|
||||
(reread_ext_syms_and_strs): Clear old symbols and call it.
|
||||
(ecoff_link_check_archive_element): Use the above. Handle substitute
|
||||
BFD if one is set by add_archive_element callback.
|
||||
(ecoff_link_add_archive_symbols): Likewise allow bfd substitution.
|
||||
* elflink.c (elf_link_add_archive_symbols): Likewise.
|
||||
* linker.c (generic_link_check_archive_element): Likewise.
|
||||
* pdp11.c (aout_link_check_ar_symbols): Take new "subsbfd" reference
|
||||
parameter and pass it when invoking add_archive_element callback.
|
||||
(aout_link_check_archive_element): Handle substitute bfd if it was
|
||||
set during add_archive_element callback in the above.
|
||||
* vms-alpha.c (alpha_vms_link_add_archive_symbols): Handle substitute
|
||||
BFD if one is set by add_archive_element callback.
|
||||
* xcofflink.c (xcoff_link_check_dynamic_ar_symbols): Take new "subsbfd"
|
||||
reference parameter and pass it when invoking add_archive_element
|
||||
callback.
|
||||
(xcoff_link_check_ar_symbols): Likewise.
|
||||
(xcoff_link_check_archive_element): Handle bfd substitution if it was
|
||||
set by callback in the above.
|
||||
|
||||
2010-10-11 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf32-frv.c (elf32_frv_relocate_section): Set "name" for global syms.
|
||||
|
24
bfd/aoutx.h
24
bfd/aoutx.h
@ -3210,7 +3210,8 @@ aout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
static bfd_boolean
|
||||
aout_link_check_ar_symbols (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_boolean *pneeded)
|
||||
bfd_boolean *pneeded,
|
||||
bfd **subsbfd)
|
||||
{
|
||||
struct external_nlist *p;
|
||||
struct external_nlist *pend;
|
||||
@ -3304,7 +3305,8 @@ aout_link_check_ar_symbols (bfd *abfd,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name, subsbfd))
|
||||
return FALSE;
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
@ -3331,9 +3333,8 @@ aout_link_check_ar_symbols (bfd *abfd,
|
||||
outside BFD. We assume that we should link
|
||||
in the object file. This is done for the -u
|
||||
option in the linker. */
|
||||
if (! (*info->callbacks->add_archive_element) (info,
|
||||
abfd,
|
||||
name))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name, subsbfd))
|
||||
return FALSE;
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
@ -3381,7 +3382,8 @@ aout_link_check_ar_symbols (bfd *abfd,
|
||||
it if the current link symbol is common. */
|
||||
if (h->type == bfd_link_hash_undefined)
|
||||
{
|
||||
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name, subsbfd))
|
||||
return FALSE;
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
@ -3402,15 +3404,21 @@ aout_link_check_archive_element (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_boolean *pneeded)
|
||||
{
|
||||
bfd *subsbfd = NULL;
|
||||
|
||||
if (! aout_get_external_symbols (abfd))
|
||||
return FALSE;
|
||||
|
||||
if (! aout_link_check_ar_symbols (abfd, info, pneeded))
|
||||
if (! aout_link_check_ar_symbols (abfd, info, pneeded, &subsbfd))
|
||||
return FALSE;
|
||||
|
||||
if (*pneeded)
|
||||
{
|
||||
if (! aout_link_add_symbols (abfd, info))
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (subsbfd && !aout_get_external_symbols (subsbfd))
|
||||
return FALSE;
|
||||
if (! aout_link_add_symbols (subsbfd ? subsbfd : abfd, info))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,8 @@ coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
static bfd_boolean
|
||||
coff_link_check_ar_symbols (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_boolean *pneeded)
|
||||
bfd_boolean *pneeded,
|
||||
bfd **subsbfd)
|
||||
{
|
||||
bfd_size_type symesz;
|
||||
bfd_byte *esym;
|
||||
@ -243,7 +244,8 @@ coff_link_check_ar_symbols (bfd *abfd,
|
||||
if (h != (struct bfd_link_hash_entry *) NULL
|
||||
&& h->type == bfd_link_hash_undefined)
|
||||
{
|
||||
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name, subsbfd))
|
||||
return FALSE;
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
@ -267,14 +269,23 @@ coff_link_check_archive_element (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_boolean *pneeded)
|
||||
{
|
||||
bfd *subsbfd = NULL;
|
||||
|
||||
if (! _bfd_coff_get_external_symbols (abfd))
|
||||
return FALSE;
|
||||
|
||||
if (! coff_link_check_ar_symbols (abfd, info, pneeded))
|
||||
if (! coff_link_check_ar_symbols (abfd, info, pneeded, &subsbfd))
|
||||
return FALSE;
|
||||
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (*pneeded
|
||||
&& subsbfd
|
||||
&& ! _bfd_coff_get_external_symbols (subsbfd))
|
||||
return FALSE;
|
||||
|
||||
if (*pneeded
|
||||
&& ! coff_link_add_symbols (abfd, info))
|
||||
&& ! coff_link_add_symbols (subsbfd ? subsbfd : abfd, info))
|
||||
return FALSE;
|
||||
|
||||
if ((! info->keep_memory || ! *pneeded)
|
||||
|
101
bfd/ecoff.c
101
bfd/ecoff.c
@ -3509,6 +3509,58 @@ ecoff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Factored out from ecoff_link_check_archive_element. */
|
||||
|
||||
static bfd_boolean
|
||||
read_ext_syms_and_strs (HDRR **symhdr, bfd_size_type *external_ext_size,
|
||||
bfd_size_type *esize, void **external_ext, char **ssext, bfd *abfd,
|
||||
const struct ecoff_backend_data * const backend)
|
||||
{
|
||||
if (! ecoff_slurp_symbolic_header (abfd))
|
||||
return FALSE;
|
||||
|
||||
/* If there are no symbols, we don't want it. */
|
||||
if (bfd_get_symcount (abfd) == 0)
|
||||
return TRUE;
|
||||
|
||||
*symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
|
||||
|
||||
*external_ext_size = backend->debug_swap.external_ext_size;
|
||||
*esize = (*symhdr)->iextMax * *external_ext_size;
|
||||
*external_ext = bfd_malloc (*esize);
|
||||
if (*external_ext == NULL && *esize != 0)
|
||||
return FALSE;
|
||||
|
||||
if (bfd_seek (abfd, (file_ptr) (*symhdr)->cbExtOffset, SEEK_SET) != 0
|
||||
|| bfd_bread (*external_ext, *esize, abfd) != *esize)
|
||||
return FALSE;
|
||||
|
||||
*ssext = (char *) bfd_malloc ((bfd_size_type) (*symhdr)->issExtMax);
|
||||
if (*ssext == NULL && (*symhdr)->issExtMax != 0)
|
||||
return FALSE;
|
||||
|
||||
if (bfd_seek (abfd, (file_ptr) (*symhdr)->cbSsExtOffset, SEEK_SET) != 0
|
||||
|| (bfd_bread (*ssext, (bfd_size_type) (*symhdr)->issExtMax, abfd)
|
||||
!= (bfd_size_type) (*symhdr)->issExtMax))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
reread_ext_syms_and_strs (HDRR **symhdr, bfd_size_type *external_ext_size,
|
||||
bfd_size_type *esize, void **external_ext, char **ssext, bfd *abfd,
|
||||
const struct ecoff_backend_data * const backend)
|
||||
{
|
||||
if (*external_ext != NULL)
|
||||
free (*external_ext);
|
||||
*external_ext = NULL;
|
||||
if (*ssext != NULL)
|
||||
free (*ssext);
|
||||
*ssext = NULL;
|
||||
return read_ext_syms_and_strs (symhdr, external_ext_size, esize,
|
||||
external_ext, ssext, abfd, backend);
|
||||
}
|
||||
|
||||
/* This is called if we used _bfd_generic_link_add_archive_symbols
|
||||
because we were not dealing with an ECOFF archive. */
|
||||
|
||||
@ -3530,35 +3582,15 @@ ecoff_link_check_archive_element (bfd *abfd,
|
||||
|
||||
*pneeded = FALSE;
|
||||
|
||||
if (! ecoff_slurp_symbolic_header (abfd))
|
||||
/* Read in the external symbols and external strings. */
|
||||
if (!read_ext_syms_and_strs (&symhdr, &external_ext_size, &esize,
|
||||
&external_ext, &ssext, abfd, backend))
|
||||
goto error_return;
|
||||
|
||||
/* If there are no symbols, we don't want it. */
|
||||
if (bfd_get_symcount (abfd) == 0)
|
||||
goto successful_return;
|
||||
|
||||
symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
|
||||
|
||||
/* Read in the external symbols and external strings. */
|
||||
external_ext_size = backend->debug_swap.external_ext_size;
|
||||
esize = symhdr->iextMax * external_ext_size;
|
||||
external_ext = bfd_malloc (esize);
|
||||
if (external_ext == NULL && esize != 0)
|
||||
goto error_return;
|
||||
|
||||
if (bfd_seek (abfd, (file_ptr) symhdr->cbExtOffset, SEEK_SET) != 0
|
||||
|| bfd_bread (external_ext, esize, abfd) != esize)
|
||||
goto error_return;
|
||||
|
||||
ssext = (char *) bfd_malloc ((bfd_size_type) symhdr->issExtMax);
|
||||
if (ssext == NULL && symhdr->issExtMax != 0)
|
||||
goto error_return;
|
||||
|
||||
if (bfd_seek (abfd, (file_ptr) symhdr->cbSsExtOffset, SEEK_SET) != 0
|
||||
|| (bfd_bread (ssext, (bfd_size_type) symhdr->issExtMax, abfd)
|
||||
!= (bfd_size_type) symhdr->issExtMax))
|
||||
goto error_return;
|
||||
|
||||
/* Look through the external symbols to see if they define some
|
||||
symbol that is currently undefined. */
|
||||
ext_ptr = (char *) external_ext;
|
||||
@ -3568,6 +3600,7 @@ ecoff_link_check_archive_element (bfd *abfd,
|
||||
EXTR esym;
|
||||
bfd_boolean def;
|
||||
const char *name;
|
||||
bfd *subsbfd;
|
||||
struct bfd_link_hash_entry *h;
|
||||
|
||||
(*swap_ext_in) (abfd, (void *) ext_ptr, &esym);
|
||||
@ -3612,9 +3645,18 @@ ecoff_link_check_archive_element (bfd *abfd,
|
||||
continue;
|
||||
|
||||
/* Include this element. */
|
||||
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
|
||||
subsbfd = NULL;
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name, &subsbfd))
|
||||
goto error_return;
|
||||
if (! ecoff_link_add_externals (abfd, info, external_ext, ssext))
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (subsbfd
|
||||
&& !reread_ext_syms_and_strs (&symhdr, &external_ext_size, &esize,
|
||||
&external_ext, &ssext, subsbfd, backend))
|
||||
goto error_return;
|
||||
if (! ecoff_link_add_externals (subsbfd ? subsbfd : abfd, info,
|
||||
external_ext, ssext))
|
||||
goto error_return;
|
||||
|
||||
*pneeded = TRUE;
|
||||
@ -3691,6 +3733,7 @@ ecoff_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
unsigned int file_offset;
|
||||
const char *name;
|
||||
bfd *element;
|
||||
bfd *subsbfd;
|
||||
|
||||
h = *pundef;
|
||||
|
||||
@ -3777,9 +3820,13 @@ ecoff_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
/* Unlike the generic linker, we know that this element provides
|
||||
a definition for an undefined symbol and we know that we want
|
||||
to include it. We don't need to check anything. */
|
||||
if (! (*info->callbacks->add_archive_element) (info, element, name))
|
||||
subsbfd = NULL;
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, element, name, &subsbfd))
|
||||
return FALSE;
|
||||
if (! ecoff_link_add_object_symbols (element, info))
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (! ecoff_link_add_object_symbols (subsbfd ? subsbfd : element, info))
|
||||
return FALSE;
|
||||
|
||||
pundef = &(*pundef)->u.undef.next;
|
||||
|
@ -5011,6 +5011,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
struct elf_link_hash_entry *h;
|
||||
bfd *element;
|
||||
bfd *subsbfd = NULL;
|
||||
struct bfd_link_hash_entry *undefs_tail;
|
||||
symindex mark;
|
||||
|
||||
@ -5073,10 +5074,12 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
|
||||
undefs_tail = info->hash->undefs_tail;
|
||||
|
||||
if (! (*info->callbacks->add_archive_element) (info, element,
|
||||
symdef->name))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, element, symdef->name, &subsbfd))
|
||||
goto error_return;
|
||||
if (! bfd_link_add_symbols (element, info))
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (! bfd_link_add_symbols (subsbfd ? subsbfd : element, info))
|
||||
goto error_return;
|
||||
|
||||
/* If there are any new undefined symbols, we need to make
|
||||
|
41
bfd/linker.c
41
bfd/linker.c
@ -223,7 +223,10 @@ SUBSUBSECTION
|
||||
archive and decide which elements of the archive should be
|
||||
included in the link. For each such element it must call the
|
||||
<<add_archive_element>> linker callback, and it must add the
|
||||
symbols from the object file to the linker hash table.
|
||||
symbols from the object file to the linker hash table. (The
|
||||
callback may in fact indicate that a replacement BFD should be
|
||||
used, in which case the symbols from that BFD should be added
|
||||
to the linker hash table instead.)
|
||||
|
||||
@findex _bfd_generic_link_add_archive_symbols
|
||||
In most cases the work of looking through the symbols in the
|
||||
@ -243,9 +246,13 @@ SUBSUBSECTION
|
||||
element should be included in the link. If the element is to
|
||||
be included, the <<add_archive_element>> linker callback
|
||||
routine must be called with the element as an argument, and
|
||||
the elements symbols must be added to the linker hash table
|
||||
the element's symbols must be added to the linker hash table
|
||||
just as though the element had itself been passed to the
|
||||
<<_bfd_link_add_symbols>> function.
|
||||
<<_bfd_link_add_symbols>> function. The <<add_archive_element>>
|
||||
callback has the option to indicate that it would like to
|
||||
replace the element archive with a substitute BFD, in which
|
||||
case it is the symbols of that substitute BFD that must be
|
||||
added to the linker hash table instead.
|
||||
|
||||
When the a.out <<_bfd_link_add_symbols>> function receives an
|
||||
archive, it calls <<_bfd_generic_link_add_archive_symbols>>
|
||||
@ -257,7 +264,8 @@ SUBSUBSECTION
|
||||
symbol) it calls the <<add_archive_element>> callback and then
|
||||
<<aout_link_check_archive_element>> calls
|
||||
<<aout_link_add_symbols>> to actually add the symbols to the
|
||||
linker hash table.
|
||||
linker hash table - possibly those of a substitute BFD, if the
|
||||
<<add_archive_element>> callback avails itself of that option.
|
||||
|
||||
The ECOFF back end is unusual in that it does not normally
|
||||
call <<_bfd_generic_link_add_archive_symbols>>, because ECOFF
|
||||
@ -957,8 +965,10 @@ archive_hash_table_init
|
||||
included. CHECKFN should set *PNEEDED to TRUE if the object file
|
||||
should be included, and must also call the bfd_link_info
|
||||
add_archive_element callback function and handle adding the symbols
|
||||
to the global hash table. CHECKFN should only return FALSE if some
|
||||
sort of error occurs.
|
||||
to the global hash table. CHECKFN must notice if the callback
|
||||
indicates a substitute BFD, and arrange to add those symbols instead
|
||||
if it does so. CHECKFN should only return FALSE if some sort of
|
||||
error occurs.
|
||||
|
||||
For some formats, such as a.out, it is possible to look through an
|
||||
object file but not actually include it in the link. The
|
||||
@ -1213,11 +1223,20 @@ generic_link_check_archive_element (bfd *abfd,
|
||||
{
|
||||
bfd_size_type symcount;
|
||||
asymbol **symbols;
|
||||
bfd *subsbfd = NULL;
|
||||
|
||||
/* This object file defines this symbol, so pull it in. */
|
||||
if (! (*info->callbacks->add_archive_element) (info, abfd,
|
||||
bfd_asymbol_name (p)))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, bfd_asymbol_name (p), &subsbfd))
|
||||
return FALSE;
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (subsbfd)
|
||||
{
|
||||
abfd = subsbfd;
|
||||
if (!bfd_generic_link_read_symbols (abfd))
|
||||
return FALSE;
|
||||
}
|
||||
symcount = _bfd_generic_link_get_symcount (abfd);
|
||||
symbols = _bfd_generic_link_get_symbols (abfd);
|
||||
if (! generic_link_add_symbol_list (abfd, info, symcount,
|
||||
@ -1238,12 +1257,16 @@ generic_link_check_archive_element (bfd *abfd,
|
||||
symbfd = h->u.undef.abfd;
|
||||
if (symbfd == NULL)
|
||||
{
|
||||
bfd *subsbfd = NULL;
|
||||
/* This symbol was created as undefined from outside
|
||||
BFD. We assume that we should link in the object
|
||||
file. This is for the -u option in the linker. */
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, bfd_asymbol_name (p)))
|
||||
(info, abfd, bfd_asymbol_name (p), &subsbfd))
|
||||
return FALSE;
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. But no symbols are going to get
|
||||
registered by anything we're returning to from here. */
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
18
bfd/pdp11.c
18
bfd/pdp11.c
@ -2545,7 +2545,8 @@ aout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
static bfd_boolean
|
||||
aout_link_check_ar_symbols (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_boolean *pneeded)
|
||||
bfd_boolean *pneeded,
|
||||
bfd **subsbfd)
|
||||
{
|
||||
struct external_nlist *p;
|
||||
struct external_nlist *pend;
|
||||
@ -2600,7 +2601,8 @@ aout_link_check_ar_symbols (bfd *abfd,
|
||||
but not if it is defined in the .text section. That
|
||||
seems a bit crazy to me, and I haven't implemented it.
|
||||
However, it might be correct. */
|
||||
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name, subsbfd))
|
||||
return FALSE;
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
@ -2628,7 +2630,7 @@ aout_link_check_ar_symbols (bfd *abfd,
|
||||
in the object file. This is done for the -u
|
||||
option in the linker. */
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name))
|
||||
(info, abfd, name, subsbfd))
|
||||
return FALSE;
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
@ -2680,15 +2682,21 @@ aout_link_check_archive_element (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_boolean *pneeded)
|
||||
{
|
||||
bfd *subsbfd = NULL;
|
||||
|
||||
if (! aout_get_external_symbols (abfd))
|
||||
return FALSE;
|
||||
|
||||
if (! aout_link_check_ar_symbols (abfd, info, pneeded))
|
||||
if (! aout_link_check_ar_symbols (abfd, info, pneeded, &subsbfd))
|
||||
return FALSE;
|
||||
|
||||
if (*pneeded)
|
||||
{
|
||||
if (! aout_link_add_symbols (abfd, info))
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (subsbfd && ! aout_get_external_symbols (subsbfd))
|
||||
return FALSE;
|
||||
if (! aout_link_add_symbols (subsbfd ? subsbfd : abfd, info))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -8220,6 +8220,7 @@ alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
symindex symidx;
|
||||
bfd *element;
|
||||
bfd *orig_element;
|
||||
bfd *subsbfd;
|
||||
|
||||
h = *pundef;
|
||||
next_pundef = &(*pundef)->u.undef.next;
|
||||
@ -8277,10 +8278,14 @@ alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
/* Unlike the generic linker, we know that this element provides
|
||||
a definition for an undefined symbol and we know that we want
|
||||
to include it. We don't need to check anything. */
|
||||
if (! (*info->callbacks->add_archive_element) (info, element,
|
||||
h->root.string))
|
||||
subsbfd = NULL;
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, element, h->root.string, &subsbfd))
|
||||
return FALSE;
|
||||
if (! alpha_vms_link_add_object_symbols (element, info))
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (! alpha_vms_link_add_object_symbols (subsbfd ? subsbfd : element,
|
||||
info))
|
||||
return FALSE;
|
||||
|
||||
orig_element->archive_pass = pass;
|
||||
|
@ -2233,7 +2233,8 @@ xcoff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
static bfd_boolean
|
||||
xcoff_link_check_dynamic_ar_symbols (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_boolean *pneeded)
|
||||
bfd_boolean *pneeded,
|
||||
bfd **subsbfd)
|
||||
{
|
||||
asection *lsec;
|
||||
bfd_byte *contents;
|
||||
@ -2291,7 +2292,8 @@ xcoff_link_check_dynamic_ar_symbols (bfd *abfd,
|
||||
&& (((struct xcoff_link_hash_entry *) h)->flags
|
||||
& XCOFF_DEF_DYNAMIC) == 0)
|
||||
{
|
||||
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name, subsbfd))
|
||||
return FALSE;
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
@ -2314,7 +2316,8 @@ xcoff_link_check_dynamic_ar_symbols (bfd *abfd,
|
||||
static bfd_boolean
|
||||
xcoff_link_check_ar_symbols (bfd *abfd,
|
||||
struct bfd_link_info *info,
|
||||
bfd_boolean *pneeded)
|
||||
bfd_boolean *pneeded,
|
||||
bfd **subsbfd)
|
||||
{
|
||||
bfd_size_type symesz;
|
||||
bfd_byte *esym;
|
||||
@ -2325,7 +2328,7 @@ xcoff_link_check_ar_symbols (bfd *abfd,
|
||||
if ((abfd->flags & DYNAMIC) != 0
|
||||
&& ! info->static_link
|
||||
&& info->output_bfd->xvec == abfd->xvec)
|
||||
return xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded);
|
||||
return xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded, subsbfd);
|
||||
|
||||
symesz = bfd_coff_symesz (abfd);
|
||||
esym = (bfd_byte *) obj_coff_external_syms (abfd);
|
||||
@ -2361,7 +2364,8 @@ xcoff_link_check_ar_symbols (bfd *abfd,
|
||||
|| (((struct xcoff_link_hash_entry *) h)->flags
|
||||
& XCOFF_DEF_DYNAMIC) == 0))
|
||||
{
|
||||
if (! (*info->callbacks->add_archive_element) (info, abfd, name))
|
||||
if (! (*info->callbacks->add_archive_element)
|
||||
(info, abfd, name, subsbfd))
|
||||
return FALSE;
|
||||
*pneeded = TRUE;
|
||||
return TRUE;
|
||||
@ -2386,17 +2390,22 @@ xcoff_link_check_archive_element (bfd *abfd,
|
||||
bfd_boolean *pneeded)
|
||||
{
|
||||
bfd_boolean keep_syms_p;
|
||||
bfd *subsbfd = NULL;
|
||||
|
||||
keep_syms_p = (obj_coff_external_syms (abfd) != NULL);
|
||||
if (! _bfd_coff_get_external_symbols (abfd))
|
||||
return FALSE;
|
||||
|
||||
if (! xcoff_link_check_ar_symbols (abfd, info, pneeded))
|
||||
if (! xcoff_link_check_ar_symbols (abfd, info, pneeded, &subsbfd))
|
||||
return FALSE;
|
||||
|
||||
if (*pneeded)
|
||||
{
|
||||
if (! xcoff_link_add_symbols (abfd, info))
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (subsbfd && !_bfd_coff_get_external_symbols (subsbfd))
|
||||
return FALSE;
|
||||
if (! xcoff_link_add_symbols (subsbfd ? subsbfd : abfd, info))
|
||||
return FALSE;
|
||||
if (info->keep_memory)
|
||||
keep_syms_p = TRUE;
|
||||
|
@ -1,3 +1,15 @@
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 6/6).
|
||||
* bfdlink.h (struct_bfd_link_callbacks): Document new argument
|
||||
to add_archive_element callback used to return a replacement bfd which
|
||||
is to be added to the hash table in place of the original element.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 1/6).
|
||||
* plugin-api.h (LDPT_GNU_LD_VERSION): New ld_plugin_tag enum member.
|
||||
|
||||
2010-10-06 Andi Kleen <ak@linux.intel.com>
|
||||
|
||||
* libiberty.h (setproctitle): Add prototype.
|
||||
|
@ -481,9 +481,11 @@ struct bfd_link_callbacks
|
||||
/* A function which is called when an object is added from an
|
||||
archive. ABFD is the archive element being added. NAME is the
|
||||
name of the symbol which caused the archive element to be pulled
|
||||
in. */
|
||||
in. This function may set *SUBSBFD to point to an alternative
|
||||
BFD from which symbols should in fact be added in place of the
|
||||
original BFD's symbols. */
|
||||
bfd_boolean (*add_archive_element)
|
||||
(struct bfd_link_info *, bfd *abfd, const char *name);
|
||||
(struct bfd_link_info *, bfd *abfd, const char *name, bfd **subsbfd);
|
||||
/* A function which is called when a symbol is found with multiple
|
||||
definitions. NAME is the symbol which is defined multiple times.
|
||||
OBFD is the old BFD, OSEC is the old section, OVAL is the old
|
||||
|
@ -268,7 +268,8 @@ enum ld_plugin_tag
|
||||
LDPT_RELEASE_INPUT_FILE,
|
||||
LDPT_ADD_INPUT_LIBRARY,
|
||||
LDPT_OUTPUT_NAME,
|
||||
LDPT_SET_EXTRA_LIBRARY_PATH
|
||||
LDPT_SET_EXTRA_LIBRARY_PATH,
|
||||
LDPT_GNU_LD_VERSION
|
||||
};
|
||||
|
||||
/* The plugin transfer vector. */
|
||||
|
155
ld/ChangeLog
155
ld/ChangeLog
@ -1,3 +1,158 @@
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 6/6).
|
||||
* ldlang.c (load_symbols): Handle bfd subsitution when calling the
|
||||
add_archive_element callback.
|
||||
* ldmain.c (add_archive_element)[ENABLE_PLUGINS]: Offer the archive
|
||||
member to the plugins and if claimed set "subsbfd" output parameter to
|
||||
point to the dummy IR-only BFD.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 5/6).
|
||||
* plugin.c (asymbol_from_plugin_symbol): If the bfd is an ELF bfd,
|
||||
find the elf symbol data and set the visibility in the st_other field.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 4/6).
|
||||
* ldlang.c (lang_process)[ENABLE_PLUGINS]: Move invocation of
|
||||
plugin_call_all_symbols_read to before setting of gc_sym_list, and
|
||||
open any new input files that may have been added during it.
|
||||
* ldmain.c (multiple_definition)[ENABLE_PLUGINS]: Call out to
|
||||
plugin_multiple_definition and let it have first say over what to do
|
||||
with the clashing definitions.
|
||||
* plugin.c (no_more_claiming): New boolean variable.
|
||||
(plugin_cached_allow_multiple_defs): Likewise.
|
||||
(add_input_file): Implement.
|
||||
(add_input_library): Likewise.
|
||||
(set_extra_library_path): Likewise.
|
||||
(plugin_call_claim_file): Don't do anything when no_more_claiming set.
|
||||
(plugin_call_all_symbols_read): Set it. Disable link info
|
||||
"allow_multiple_definition" flag, but cache its value.
|
||||
(plugin_multiple_definition): New function.
|
||||
* plugin.h (plugin_multiple_definition): Add prototype.
|
||||
* testplug.c (addfile_enum_t): New enumerated typedef.
|
||||
(add_file_t): New struct typedef.
|
||||
(addfiles_list): New variable.
|
||||
(addfiles_tail_chain_ptr): Likewise.
|
||||
(record_add_file): New function.
|
||||
(parse_option): Parse "add:", "lib:" and "dir:" options and call it.
|
||||
(onall_symbols_read): Iterate the list of new files, libs and dirs,
|
||||
adding them.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 3/6).
|
||||
* ldmain.c (notice)[ENABLE_PLUGINS]: Call plugin_notice.
|
||||
* plugin.c (non_ironly_hash): Add new bfd hash table.
|
||||
(plugin_load_plugins): Exit early if no plugins to load. If plugins
|
||||
do load successfully, set notice_all flag in link info.
|
||||
(get_symbols): Implement.
|
||||
(plugin_load_plugins): Exit early if no plugins to load, else after
|
||||
loading plugins successfully enable notice_all mode.
|
||||
(init_non_ironly_hash): Lazily init non_ironly_hash table.
|
||||
(plugin_notice): Record symbols referenced from non-IR files in the
|
||||
non_ironly_hash. Suppress tracing, cref generation and nocrossrefs
|
||||
tracking for symbols from dummy IR bfds.
|
||||
* plugin.h: Fix formatting.
|
||||
(plugin_notice): Add prototype.
|
||||
* testplug.c (dumpresolutions): New global var.
|
||||
(parse_options): Accept "dumpresolutions".
|
||||
(onall_symbols_read): Get syms and dump resolutions if it was given.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 2/6).
|
||||
* ldfile.c (ldfile_try_open_bfd)[ENABLE_PLUGINS]: Don't return early
|
||||
during compat checks if they pass, instead offer any successfully
|
||||
opened and accepted file to the plugin claim file hooks chain. Create
|
||||
a dummy bfd to accept symbols added by the plugin, if the plugin
|
||||
claims the file.
|
||||
* ldlang.c (lang_process)[ENABLE_PLUGINS]: Call plugin all symbols
|
||||
read hook chain before ldemul_after_open.
|
||||
* ldlang.h (struct lang_input_statement_struct): Add new single-bit
|
||||
'claimed' flag.
|
||||
* plugin.c (IRONLY_SUFFIX): New macro for dummy bfd file suffix.
|
||||
(IRONLY_SUFFIX_LEN): Length of the above string.
|
||||
(plugin_get_ir_dummy_bfd): New function to create the dummy bfd used
|
||||
to store symbols for ir-only files.
|
||||
(is_ir_dummy_bfd): New function to check if a bfd is ir-only.
|
||||
(asymbol_from_plugin_symbol): New function converts symbol formats.
|
||||
(add_symbols): Call it to convert plugin syms to bfd syms and add
|
||||
them to the dummy bfd.
|
||||
* plugin.h: Add missing include guards.
|
||||
(plugin_get_ir_dummy_bfd): Add prototype.
|
||||
(is_ir_dummy_bfd): Likewise.
|
||||
* testplug.c (TV_MESSAGE): New helper macro.
|
||||
(struct claim_file): New struct.
|
||||
(claim_file_t): New typedef.
|
||||
(tag_names[]): Make static and const.
|
||||
(claimfiles_list): New variable.
|
||||
(claimfiles_tail_chain_ptr): Likewise.
|
||||
(last_claimfile): Likewise.
|
||||
(record_claim_file): Record a file to claim on a singly-linked list.
|
||||
(parse_symdefstr): Parse an ASCII representation of a symbol from a
|
||||
plugin option into the fields of a struct ld_plugin_symbol.
|
||||
(record_claimed_file_symbol): Use it to parse plugin option for
|
||||
adding a symbol.
|
||||
(parse_option): Parse claim file and add symbol options.
|
||||
(dump_tv_tag): Use TV_MESSAGE.
|
||||
(onload): Likewise.
|
||||
(onclaim_file): Make static. Use TV_MESSAGE. Scan list of files to
|
||||
claim and claim this file if required, adding any symbols specified.
|
||||
(onall_symbols_read): Make static and use TV_MESSAGE.
|
||||
(oncleanup): Likewise.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 1/6).
|
||||
* configure.in: Add AC_CHECKs for file io and dlfcn headers and
|
||||
functions and AC_SEARCH for -ldl.
|
||||
(enable_plugins): New shell variable set if above tests find dlopen
|
||||
functionality.
|
||||
(ENABLE_PLUGINS): Add related automake conditional.
|
||||
* configure: Regenerate.
|
||||
* config.in: Likewise.
|
||||
* Makefile.am (PLUGIN_C): Declare plugin C source file, conditional
|
||||
on ENABLE_PLUGINS being defined.
|
||||
(PLUGIN_H): Likewise for header file.
|
||||
(PLUGIN_OBJECT): Likewise for object file.
|
||||
(PLUGIN_CFLAGS): Likewise -D flag required to compile plugin support.
|
||||
(AM_CPPFLAGS): Use PLUGIN_CFLAGS.
|
||||
(CFILES): Use PLUGIN_C.
|
||||
(HFILES): Use PLUGIN_H.
|
||||
(OFILES): Use PLUGIN_OBJECT.
|
||||
(ld_new_SOURCES): Use PLUGIN_C.
|
||||
(noinst_LTLIBRARIES)[ENABLE_PLUGINS]: Declare test plugin.
|
||||
(libldtestplug_la_SOURCES)[ENABLE_PLUGINS]: Add automake definition
|
||||
for test plugin.
|
||||
(libldtestplug_la_CFLAGS)[ENABLE_PLUGINS]: Likewise.
|
||||
(libldtestplug_la_LDFLAGS)[ENABLE_PLUGINS]: Likewise.
|
||||
* Makefile.in: Regenerate.
|
||||
* sysdep.h: Include stdarg.h, unistd.h and one of fcntl.h or
|
||||
sys/file.h where available. Include dlfcn.h when ENABLE_PLUGINS.
|
||||
(O_RDONLY): Supply default definition likewise to bfd's sysdep.h
|
||||
(O_WRONLY): Likewise.
|
||||
(O_RDWR): Likewise.
|
||||
(O_ACCMODE): Likewise.
|
||||
(O_BINARY): Likewise.
|
||||
(SEEK_SET): Likewise.
|
||||
(SEEK_CUR): Likewise.
|
||||
(SEEK_END): Likewise.
|
||||
* ldmisc.c (vfinfo): Make non-static. Add %p format char.
|
||||
* ldmisc.h (vfinfo): Declare extern prototype.
|
||||
* lexsup.c (enum option_values)[ENABLE_PLUGINS]: Add new entries for
|
||||
OPTION_PLUGIN and OPTION_PLUGIN_OPT.
|
||||
(ld_options[])[ENABLE_PLUGINS]: Add option data for the above two.
|
||||
(parse_args)[ENABLE_PLUGINS]: Handle them, and load all plugins once
|
||||
option parsing is complete.
|
||||
* ldmain.c (main)[ENABLE_PLUGINS]: Call plugin cleanup hooks just
|
||||
after lang_finish.
|
||||
* plugin.c: New source file.
|
||||
* plugin.h: Likewise new header.
|
||||
* testplug.c: New source file.
|
||||
|
||||
2010-10-12 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
||||
|
||||
* emultempl/solaris2.em (elf_solaris2_before_allocation): Renamed
|
||||
|
@ -21,6 +21,19 @@ WARN_CFLAGS = @WARN_CFLAGS@
|
||||
NO_WERROR = @NO_WERROR@
|
||||
AM_CFLAGS = $(WARN_CFLAGS)
|
||||
|
||||
# Conditionally enable the plugin interface.
|
||||
if ENABLE_PLUGINS
|
||||
PLUGIN_C = plugin.c
|
||||
PLUGIN_H = plugin.h
|
||||
PLUGIN_OBJECT = plugin.@OBJEXT@
|
||||
PLUGIN_CFLAGS = -DENABLE_PLUGINS
|
||||
else
|
||||
PLUGIN_C =
|
||||
PLUGIN_H =
|
||||
PLUGIN_OBJECT =
|
||||
PLUGIN_CFLAGS =
|
||||
endif
|
||||
|
||||
# We put the scripts in the directory $(scriptdir)/ldscripts.
|
||||
# We can't put the scripts in $(datadir) because the SEARCH_DIR
|
||||
# directives need to be different for native and cross linkers.
|
||||
@ -108,7 +121,7 @@ TEXI2DVI = texi2dvi -I $(srcdir) -I $(BFDDIR)/doc -I ../bfd/doc \
|
||||
-I $(top_srcdir)/../libiberty
|
||||
|
||||
AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \
|
||||
@INCINTL@ $(HDEFINES) $(CFLAGS) \
|
||||
@INCINTL@ $(HDEFINES) $(CFLAGS) $(PLUGIN_CFLAGS) \
|
||||
-DLOCALEDIR="\"$(datadir)/locale\""
|
||||
|
||||
BFDLIB = ../bfd/libbfd.la
|
||||
@ -459,11 +472,13 @@ ALL_EMUL_EXTRA_OFILES = \
|
||||
|
||||
CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
|
||||
ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
|
||||
mri.c ldcref.c pe-dll.c pep-dll.c ldlex-wrapper.c
|
||||
mri.c ldcref.c pe-dll.c pep-dll.c ldlex-wrapper.c \
|
||||
$(PLUGIN_C)
|
||||
|
||||
HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
|
||||
ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
|
||||
ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
|
||||
ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h \
|
||||
elf-hints-local.h $(PLUGIN_H)
|
||||
|
||||
GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
|
||||
GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
|
||||
@ -472,7 +487,8 @@ GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
|
||||
# tracking will not cause them to be built beforehand.
|
||||
BUILT_SOURCES = $(GENERATED_HFILES)
|
||||
|
||||
OFILES = ldgram.@OBJEXT@ ldlex-wrapper.@OBJEXT@ lexsup.@OBJEXT@ ldlang.@OBJEXT@ mri.@OBJEXT@ ldctor.@OBJEXT@ ldmain.@OBJEXT@ \
|
||||
OFILES = ldgram.@OBJEXT@ ldlex-wrapper.@OBJEXT@ lexsup.@OBJEXT@ ldlang.@OBJEXT@ \
|
||||
mri.@OBJEXT@ ldctor.@OBJEXT@ ldmain.@OBJEXT@ $(PLUGIN_OBJECT) \
|
||||
ldwrite.@OBJEXT@ ldexp.@OBJEXT@ ldemul.@OBJEXT@ ldver.@OBJEXT@ ldmisc.@OBJEXT@ \
|
||||
ldfile.@OBJEXT@ ldcref.@OBJEXT@ ${EMULATION_OFILES} ${EMUL_EXTRA_OFILES}
|
||||
|
||||
@ -1890,7 +1906,7 @@ EXTRA_ld_new_SOURCES = deffilep.y ldlex.l
|
||||
EXTRA_ld_new_SOURCES += pep-dll.c pe-dll.c
|
||||
|
||||
ld_new_SOURCES = ldgram.y ldlex-wrapper.c lexsup.c ldlang.c mri.c ldctor.c ldmain.c \
|
||||
ldwrite.c ldexp.c ldemul.c ldver.c ldmisc.c ldfile.c ldcref.c
|
||||
ldwrite.c ldexp.c ldemul.c ldver.c ldmisc.c ldfile.c ldcref.c $(PLUGIN_C)
|
||||
ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL_DEP)
|
||||
ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
|
||||
|
||||
@ -1972,6 +1988,16 @@ bootstrap: ld3$(EXEEXT)
|
||||
|
||||
# END OF CHECK TARGETS
|
||||
|
||||
#
|
||||
# Build a dummy plugin using libtool.
|
||||
#
|
||||
if ENABLE_PLUGINS
|
||||
noinst_LTLIBRARIES = libldtestplug.la
|
||||
libldtestplug_la_SOURCES = testplug.c
|
||||
libldtestplug_la_CFLAGS= -g -O2
|
||||
libldtestplug_la_LDFLAGS = -no-undefined -rpath /nowhere
|
||||
endif
|
||||
|
||||
# DOCUMENTATION TARGETS
|
||||
# Manual configuration file; not usually attached to normal configuration,
|
||||
# because almost all configs use "gen" version of manual.
|
||||
|
149
ld/Makefile.in
149
ld/Makefile.in
@ -15,6 +15,7 @@
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
@ -71,14 +72,25 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES = po/Makefile.in
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||
libldtestplug_la_LIBADD =
|
||||
@ENABLE_PLUGINS_TRUE@am_libldtestplug_la_OBJECTS = \
|
||||
@ENABLE_PLUGINS_TRUE@ libldtestplug_la-testplug.lo
|
||||
libldtestplug_la_OBJECTS = $(am_libldtestplug_la_OBJECTS)
|
||||
libldtestplug_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libldtestplug_la_CFLAGS) \
|
||||
$(CFLAGS) $(libldtestplug_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
@ENABLE_PLUGINS_TRUE@am_libldtestplug_la_rpath =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(infodir)" \
|
||||
"$(DESTDIR)$(man1dir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
@ENABLE_PLUGINS_TRUE@am__objects_1 = plugin.$(OBJEXT)
|
||||
am_ld_new_OBJECTS = ldgram.$(OBJEXT) ldlex-wrapper.$(OBJEXT) \
|
||||
lexsup.$(OBJEXT) ldlang.$(OBJEXT) mri.$(OBJEXT) \
|
||||
ldctor.$(OBJEXT) ldmain.$(OBJEXT) ldwrite.$(OBJEXT) \
|
||||
ldexp.$(OBJEXT) ldemul.$(OBJEXT) ldver.$(OBJEXT) \
|
||||
ldmisc.$(OBJEXT) ldfile.$(OBJEXT) ldcref.$(OBJEXT)
|
||||
ldmisc.$(OBJEXT) ldfile.$(OBJEXT) ldcref.$(OBJEXT) \
|
||||
$(am__objects_1)
|
||||
ld_new_OBJECTS = $(am_ld_new_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
@ -103,7 +115,8 @@ YLWRAP = $(top_srcdir)/../ylwrap
|
||||
YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
|
||||
LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
--mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
|
||||
SOURCES = $(ld_new_SOURCES) $(EXTRA_ld_new_SOURCES)
|
||||
SOURCES = $(libldtestplug_la_SOURCES) $(ld_new_SOURCES) \
|
||||
$(EXTRA_ld_new_SOURCES)
|
||||
INFO_DEPS = ld.info
|
||||
am__TEXINFO_TEX_DIR = $(srcdir)/$(top_srcdir)/../texinfo
|
||||
DVIS = ld.dvi
|
||||
@ -333,6 +346,16 @@ tooldir = $(exec_prefix)/$(target_alias)
|
||||
am__skiplex =
|
||||
am__skipyacc =
|
||||
AM_CFLAGS = $(WARN_CFLAGS)
|
||||
@ENABLE_PLUGINS_FALSE@PLUGIN_C =
|
||||
|
||||
# Conditionally enable the plugin interface.
|
||||
@ENABLE_PLUGINS_TRUE@PLUGIN_C = plugin.c
|
||||
@ENABLE_PLUGINS_FALSE@PLUGIN_H =
|
||||
@ENABLE_PLUGINS_TRUE@PLUGIN_H = plugin.h
|
||||
@ENABLE_PLUGINS_FALSE@PLUGIN_OBJECT =
|
||||
@ENABLE_PLUGINS_TRUE@PLUGIN_OBJECT = plugin.@OBJEXT@
|
||||
@ENABLE_PLUGINS_FALSE@PLUGIN_CFLAGS =
|
||||
@ENABLE_PLUGINS_TRUE@PLUGIN_CFLAGS = -DENABLE_PLUGINS
|
||||
|
||||
# We put the scripts in the directory $(scriptdir)/ldscripts.
|
||||
# We can't put the scripts in $(datadir) because the SEARCH_DIR
|
||||
@ -399,7 +422,7 @@ TEXI2DVI = texi2dvi -I $(srcdir) -I $(BFDDIR)/doc -I ../bfd/doc \
|
||||
-I $(top_srcdir)/../libiberty
|
||||
|
||||
AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \
|
||||
@INCINTL@ $(HDEFINES) $(CFLAGS) \
|
||||
@INCINTL@ $(HDEFINES) $(CFLAGS) $(PLUGIN_CFLAGS) \
|
||||
-DLOCALEDIR="\"$(datadir)/locale\""
|
||||
|
||||
BFDLIB = ../bfd/libbfd.la
|
||||
@ -747,11 +770,13 @@ ALL_EMUL_EXTRA_OFILES = \
|
||||
|
||||
CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \
|
||||
ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \
|
||||
mri.c ldcref.c pe-dll.c pep-dll.c ldlex-wrapper.c
|
||||
mri.c ldcref.c pe-dll.c pep-dll.c ldlex-wrapper.c \
|
||||
$(PLUGIN_C)
|
||||
|
||||
HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
|
||||
ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
|
||||
ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h elf-hints-local.h
|
||||
ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h \
|
||||
elf-hints-local.h $(PLUGIN_H)
|
||||
|
||||
GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
|
||||
GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
|
||||
@ -759,7 +784,8 @@ GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
|
||||
# Require an early dependency on the generated headers, as the dependency
|
||||
# tracking will not cause them to be built beforehand.
|
||||
BUILT_SOURCES = $(GENERATED_HFILES)
|
||||
OFILES = ldgram.@OBJEXT@ ldlex-wrapper.@OBJEXT@ lexsup.@OBJEXT@ ldlang.@OBJEXT@ mri.@OBJEXT@ ldctor.@OBJEXT@ ldmain.@OBJEXT@ \
|
||||
OFILES = ldgram.@OBJEXT@ ldlex-wrapper.@OBJEXT@ lexsup.@OBJEXT@ ldlang.@OBJEXT@ \
|
||||
mri.@OBJEXT@ ldctor.@OBJEXT@ ldmain.@OBJEXT@ $(PLUGIN_OBJECT) \
|
||||
ldwrite.@OBJEXT@ ldexp.@OBJEXT@ ldemul.@OBJEXT@ ldver.@OBJEXT@ ldmisc.@OBJEXT@ \
|
||||
ldfile.@OBJEXT@ ldcref.@OBJEXT@ ${EMULATION_OFILES} ${EMUL_EXTRA_OFILES}
|
||||
|
||||
@ -783,10 +809,49 @@ ELF_GEN_DEPS = $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/elf-generic.em
|
||||
EXTRA_ld_new_SOURCES = deffilep.y ldlex.l pep-dll.c pe-dll.c \
|
||||
$(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES)
|
||||
ld_new_SOURCES = ldgram.y ldlex-wrapper.c lexsup.c ldlang.c mri.c ldctor.c ldmain.c \
|
||||
ldwrite.c ldexp.c ldemul.c ldver.c ldmisc.c ldfile.c ldcref.c
|
||||
ldwrite.c ldexp.c ldemul.c ldver.c ldmisc.c ldfile.c ldcref.c $(PLUGIN_C)
|
||||
|
||||
ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL_DEP)
|
||||
ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
|
||||
|
||||
# A test program for C++ constructors and destructors.
|
||||
# This test is now in the testsuite.
|
||||
#
|
||||
#cdtest: cdtest-main.@OBJEXT@ cdtest-bar.@OBJEXT@ cdtest-foo.@OBJEXT@ ld.new
|
||||
# ./ld.new $(HOSTING_EMU) -o cdtest $(HOSTING_CRT0) \
|
||||
# cdtest-main.@OBJEXT@ cdtest-bar.@OBJEXT@ cdtest-foo.@OBJEXT@ $(HOSTING_LIBS)
|
||||
#
|
||||
#cdtest.out: cdtest
|
||||
# ./cdtest > cdtest.tmp
|
||||
# mv cdtest.tmp cdtest.out
|
||||
#
|
||||
#cdtest-ur.@OBJEXT@: cdtest-main.@OBJEXT@ cdtest-bar.@OBJEXT@ cdtest-foo.@OBJEXT@ ld.new
|
||||
# ./ld.new $(HOSTING_EMU) -o cdtest-ur.@OBJEXT@ -Ur cdtest-main.@OBJEXT@ \
|
||||
# cdtest-bar.@OBJEXT@ cdtest-foo.@OBJEXT@
|
||||
#
|
||||
#cdtest-ur: cdtest-ur.@OBJEXT@
|
||||
# ./ld.new $(HOSTING_EMU) -o cdtest-ur $(HOSTING_CRT0) cdtest-ur.@OBJEXT@ \
|
||||
# $(HOSTING_LIBS)
|
||||
#
|
||||
#cdtest-ur.out: cdtest-ur
|
||||
# ./cdtest-ur > cdtest-ur.tmp
|
||||
# mv cdtest-ur.tmp cdtest-ur.out
|
||||
#
|
||||
#check-cdtest: cdtest.out cdtest-ur.out $(srcdir)/cdtest.exp
|
||||
# diff $(srcdir)/cdtest.exp cdtest.out
|
||||
# diff $(srcdir)/cdtest.exp cdtest-ur.out
|
||||
#
|
||||
#.PHONY: check-cdtest
|
||||
|
||||
# END OF CHECK TARGETS
|
||||
|
||||
#
|
||||
# Build a dummy plugin using libtool.
|
||||
#
|
||||
@ENABLE_PLUGINS_TRUE@noinst_LTLIBRARIES = libldtestplug.la
|
||||
@ENABLE_PLUGINS_TRUE@libldtestplug_la_SOURCES = testplug.c
|
||||
@ENABLE_PLUGINS_TRUE@libldtestplug_la_CFLAGS = -g -O2
|
||||
@ENABLE_PLUGINS_TRUE@libldtestplug_la_LDFLAGS = -no-undefined -rpath /nowhere
|
||||
MAINTAINERCLEANFILES = configdoc.texi ld.1 ld.info
|
||||
|
||||
# We want to reconfigure if configure.host or configure.tgt changes. We
|
||||
@ -863,6 +928,17 @@ distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
po/Makefile.in: $(top_builddir)/config.status $(top_srcdir)/po/Make-in
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $@
|
||||
|
||||
clean-noinstLTLIBRARIES:
|
||||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
|
||||
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
|
||||
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
|
||||
test "$$dir" != "$$p" || dir=.; \
|
||||
echo "rm -f \"$${dir}/so_locations\""; \
|
||||
rm -f "$${dir}/so_locations"; \
|
||||
done
|
||||
libldtestplug.la: $(libldtestplug_la_OBJECTS) $(libldtestplug_la_DEPENDENCIES)
|
||||
$(libldtestplug_la_LINK) $(am_libldtestplug_la_rpath) $(libldtestplug_la_OBJECTS) $(libldtestplug_la_LIBADD) $(LIBS)
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||
@ -1271,9 +1347,11 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldver.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldwrite.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexsup.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug_la-testplug.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mri.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-dll.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pep-dll.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@ -1296,6 +1374,13 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
libldtestplug_la-testplug.lo: testplug.c
|
||||
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libldtestplug_la_CFLAGS) $(CFLAGS) -MT libldtestplug_la-testplug.lo -MD -MP -MF $(DEPDIR)/libldtestplug_la-testplug.Tpo -c -o libldtestplug_la-testplug.lo `test -f 'testplug.c' || echo '$(srcdir)/'`testplug.c
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libldtestplug_la-testplug.Tpo $(DEPDIR)/libldtestplug_la-testplug.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testplug.c' object='libldtestplug_la-testplug.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libldtestplug_la_CFLAGS) $(CFLAGS) -c -o libldtestplug_la-testplug.lo `test -f 'testplug.c' || echo '$(srcdir)/'`testplug.c
|
||||
|
||||
.l.c:
|
||||
$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
|
||||
|
||||
@ -1650,7 +1735,8 @@ check-am: all-am
|
||||
$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
|
||||
check: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) check-recursive
|
||||
all-am: Makefile $(INFO_DEPS) $(PROGRAMS) $(MANS) config.h
|
||||
all-am: Makefile $(INFO_DEPS) $(LTLIBRARIES) $(PROGRAMS) $(MANS) \
|
||||
config.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \
|
||||
@ -1695,7 +1781,7 @@ maintainer-clean-generic:
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-aminfo clean-binPROGRAMS clean-generic clean-libtool \
|
||||
mostlyclean-am
|
||||
clean-noinstLTLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
|
||||
@ -1855,13 +1941,13 @@ uninstall-man: uninstall-man1
|
||||
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
|
||||
all all-am am--refresh check check-DEJAGNU check-am clean \
|
||||
clean-aminfo clean-binPROGRAMS clean-generic clean-libtool \
|
||||
ctags ctags-recursive dist-info distclean distclean-DEJAGNU \
|
||||
distclean-compile distclean-generic distclean-hdr \
|
||||
distclean-libtool distclean-local distclean-tags dvi dvi-am \
|
||||
html html-am info info-am install install-am \
|
||||
install-binPROGRAMS install-data install-data-am \
|
||||
install-data-local install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-exec-local install-html \
|
||||
clean-noinstLTLIBRARIES ctags ctags-recursive dist-info \
|
||||
distclean distclean-DEJAGNU distclean-compile \
|
||||
distclean-generic distclean-hdr distclean-libtool \
|
||||
distclean-local distclean-tags dvi dvi-am html html-am info \
|
||||
info-am install install-am install-binPROGRAMS install-data \
|
||||
install-data-am install-data-local install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-exec-local install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-man1 install-pdf install-pdf-am install-ps \
|
||||
install-ps-am install-strip installcheck installcheck-am \
|
||||
@ -3278,37 +3364,6 @@ bootstrap: ld3$(EXEEXT)
|
||||
|
||||
.PHONY: bootstrap
|
||||
|
||||
# A test program for C++ constructors and destructors.
|
||||
# This test is now in the testsuite.
|
||||
#
|
||||
#cdtest: cdtest-main.@OBJEXT@ cdtest-bar.@OBJEXT@ cdtest-foo.@OBJEXT@ ld.new
|
||||
# ./ld.new $(HOSTING_EMU) -o cdtest $(HOSTING_CRT0) \
|
||||
# cdtest-main.@OBJEXT@ cdtest-bar.@OBJEXT@ cdtest-foo.@OBJEXT@ $(HOSTING_LIBS)
|
||||
#
|
||||
#cdtest.out: cdtest
|
||||
# ./cdtest > cdtest.tmp
|
||||
# mv cdtest.tmp cdtest.out
|
||||
#
|
||||
#cdtest-ur.@OBJEXT@: cdtest-main.@OBJEXT@ cdtest-bar.@OBJEXT@ cdtest-foo.@OBJEXT@ ld.new
|
||||
# ./ld.new $(HOSTING_EMU) -o cdtest-ur.@OBJEXT@ -Ur cdtest-main.@OBJEXT@ \
|
||||
# cdtest-bar.@OBJEXT@ cdtest-foo.@OBJEXT@
|
||||
#
|
||||
#cdtest-ur: cdtest-ur.@OBJEXT@
|
||||
# ./ld.new $(HOSTING_EMU) -o cdtest-ur $(HOSTING_CRT0) cdtest-ur.@OBJEXT@ \
|
||||
# $(HOSTING_LIBS)
|
||||
#
|
||||
#cdtest-ur.out: cdtest-ur
|
||||
# ./cdtest-ur > cdtest-ur.tmp
|
||||
# mv cdtest-ur.tmp cdtest-ur.out
|
||||
#
|
||||
#check-cdtest: cdtest.out cdtest-ur.out $(srcdir)/cdtest.exp
|
||||
# diff $(srcdir)/cdtest.exp cdtest.out
|
||||
# diff $(srcdir)/cdtest.exp cdtest-ur.out
|
||||
#
|
||||
#.PHONY: check-cdtest
|
||||
|
||||
# END OF CHECK TARGETS
|
||||
|
||||
# DOCUMENTATION TARGETS
|
||||
# Manual configuration file; not usually attached to normal configuration,
|
||||
# because almost all configs use "gen" version of manual.
|
||||
|
27
ld/config.in
27
ld/config.in
@ -10,6 +10,9 @@
|
||||
/* Define to choose default GOT handling scheme */
|
||||
#undef GOT_HANDLING_DEFAULT
|
||||
|
||||
/* Define to 1 if you have the `close' function. */
|
||||
#undef HAVE_CLOSE
|
||||
|
||||
/* Define to 1 if you have the declaration of `environ', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_ENVIRON
|
||||
@ -37,12 +40,24 @@
|
||||
*/
|
||||
#undef HAVE_DIRENT_H
|
||||
|
||||
/* Define to 1 if you have the `dlclose' function. */
|
||||
#undef HAVE_DLCLOSE
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the `dlopen' function. */
|
||||
#undef HAVE_DLOPEN
|
||||
|
||||
/* Define to 1 if you have the `dlsym' function. */
|
||||
#undef HAVE_DLSYM
|
||||
|
||||
/* Define to 1 if you have the <elf-hints.h> header file. */
|
||||
#undef HAVE_ELF_HINTS_H
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `glob' function. */
|
||||
#undef HAVE_GLOB
|
||||
|
||||
@ -52,6 +67,9 @@
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define to 1 if you have the `lseek' function. */
|
||||
#undef HAVE_LSEEK
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
@ -61,6 +79,9 @@
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
#undef HAVE_NDIR_H
|
||||
|
||||
/* Define to 1 if you have the `open' function. */
|
||||
#undef HAVE_OPEN
|
||||
|
||||
/* Define to 1 if you have the `realpath' function. */
|
||||
#undef HAVE_REALPATH
|
||||
|
||||
@ -83,6 +104,9 @@
|
||||
*/
|
||||
#undef HAVE_SYS_DIR_H
|
||||
|
||||
/* Define to 1 if you have the <sys/file.h> header file. */
|
||||
#undef HAVE_SYS_FILE_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#undef HAVE_SYS_NDIR_H
|
||||
@ -93,6 +117,9 @@
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
|
130
ld/configure
vendored
130
ld/configure
vendored
@ -609,6 +609,8 @@ EMUL_EXTRA_OFILES
|
||||
EMULATION_OFILES
|
||||
EMUL
|
||||
STRINGIFY
|
||||
ENABLE_PLUGINS_FALSE
|
||||
ENABLE_PLUGINS_TRUE
|
||||
NATIVE_LIB_DIRS
|
||||
HOSTING_LIBS
|
||||
HOSTING_CRT0
|
||||
@ -11620,7 +11622,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 11623 "configure"
|
||||
#line 11625 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -11726,7 +11728,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 11729 "configure"
|
||||
#line 11731 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -12633,6 +12635,20 @@ fi
|
||||
|
||||
done
|
||||
|
||||
for ac_header in fcntl.h sys/file.h sys/time.h sys/stat.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
eval as_val=\$$as_ac_Header
|
||||
if test "x$as_val" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
for ac_func in glob mkstemp realpath sbrk waitpid
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
@ -12646,6 +12662,19 @@ _ACEOF
|
||||
fi
|
||||
done
|
||||
|
||||
for ac_func in open lseek close
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
eval as_val=\$$as_ac_var
|
||||
if test "x$as_val" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
ac_header_dirent=no
|
||||
for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
|
||||
as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
|
||||
@ -12806,6 +12835,99 @@ fi
|
||||
fi
|
||||
|
||||
|
||||
# Check for dlopen support and enable plugins if possible.
|
||||
enable_plugins=yes
|
||||
ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_dlfcn_h" = x""yes; then :
|
||||
|
||||
else
|
||||
enable_plugins=no
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
|
||||
$as_echo_n "checking for library containing dlopen... " >&6; }
|
||||
if test "${ac_cv_search_dlopen+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char dlopen ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return dlopen ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' dl; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_search_dlopen=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if test "${ac_cv_search_dlopen+set}" = set; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test "${ac_cv_search_dlopen+set}" = set; then :
|
||||
|
||||
else
|
||||
ac_cv_search_dlopen=no
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
|
||||
$as_echo "$ac_cv_search_dlopen" >&6; }
|
||||
ac_res=$ac_cv_search_dlopen
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
else
|
||||
enable_plugins=no
|
||||
fi
|
||||
|
||||
for ac_func in dlopen dlsym dlclose
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
eval as_val=\$$as_ac_var
|
||||
if test "x$as_val" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
enable_plugins=no
|
||||
fi
|
||||
done
|
||||
|
||||
if test x$enable_plugins = xyes; then
|
||||
ENABLE_PLUGINS_TRUE=
|
||||
ENABLE_PLUGINS_FALSE='#'
|
||||
else
|
||||
ENABLE_PLUGINS_TRUE='#'
|
||||
ENABLE_PLUGINS_FALSE=
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a known getopt prototype in unistd.h" >&5
|
||||
$as_echo_n "checking for a known getopt prototype in unistd.h... " >&6; }
|
||||
if test "${ld_cv_decl_getopt_unistd_h+set}" = set; then :
|
||||
@ -13300,6 +13422,10 @@ if test -z "${GENINSRC_NEVER_TRUE}" && test -z "${GENINSRC_NEVER_FALSE}"; then
|
||||
as_fn_error "conditional \"GENINSRC_NEVER\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
fi
|
||||
if test -z "${ENABLE_PLUGINS_TRUE}" && test -z "${ENABLE_PLUGINS_FALSE}"; then
|
||||
as_fn_error "conditional \"ENABLE_PLUGINS\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
fi
|
||||
|
||||
: ${CONFIG_STATUS=./config.status}
|
||||
ac_write_fail=0
|
||||
|
@ -159,9 +159,18 @@ AC_SUBST(HOSTING_LIBS)
|
||||
AC_SUBST(NATIVE_LIB_DIRS)
|
||||
|
||||
AC_CHECK_HEADERS(string.h strings.h stdlib.h unistd.h elf-hints.h limits.h sys/param.h)
|
||||
AC_CHECK_HEADERS(fcntl.h sys/file.h sys/time.h sys/stat.h)
|
||||
AC_CHECK_FUNCS(glob mkstemp realpath sbrk waitpid)
|
||||
AC_CHECK_FUNCS(open lseek close)
|
||||
AC_HEADER_DIRENT
|
||||
|
||||
# Check for dlopen support and enable plugins if possible.
|
||||
enable_plugins=yes
|
||||
AC_CHECK_HEADER([dlfcn.h],[],[enable_plugins=no],[AC_INCLUDES_DEFAULT])
|
||||
AC_SEARCH_LIBS([dlopen],[dl],[],[enable_plugins=no],[])
|
||||
AC_CHECK_FUNCS([dlopen dlsym dlclose],[],[enable_plugins=no])
|
||||
AM_CONDITIONAL([ENABLE_PLUGINS], [test x$enable_plugins = xyes])
|
||||
|
||||
AC_MSG_CHECKING(for a known getopt prototype in unistd.h)
|
||||
AC_CACHE_VAL(ld_cv_decl_getopt_unistd_h,
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <unistd.h>], [extern int getopt (int, char *const*, const char *);])],
|
||||
|
63
ld/ldfile.c
63
ld/ldfile.c
@ -34,6 +34,10 @@
|
||||
#include "ldemul.h"
|
||||
#include "libiberty.h"
|
||||
#include "filenames.h"
|
||||
#ifdef ENABLE_PLUGINS
|
||||
#include "plugin-api.h"
|
||||
#include "plugin.h"
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
const char * ldfile_input_filename;
|
||||
bfd_boolean ldfile_assumed_script = FALSE;
|
||||
@ -150,7 +154,12 @@ ldfile_try_open_bfd (const char *attempt,
|
||||
compatible with the output file. If it isn't, keep searching.
|
||||
If we can't open the file as an object file, stop the search
|
||||
here. If we are statically linking, ensure that we don't link
|
||||
a dynamic object. */
|
||||
a dynamic object.
|
||||
|
||||
In the code below, it's OK to exit early if the check fails,
|
||||
closing the checked BFD and returning FALSE, but if the BFD
|
||||
checks out compatible, do not exit early returning TRUE, or
|
||||
the plugins will not get a chance to claim the file. */
|
||||
|
||||
if (entry->search_dirs_flag || !entry->dynamic)
|
||||
{
|
||||
@ -259,7 +268,7 @@ ldfile_try_open_bfd (const char *attempt,
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
goto success;
|
||||
}
|
||||
|
||||
if (!entry->dynamic && (entry->the_bfd->flags & DYNAMIC) != 0)
|
||||
@ -289,7 +298,57 @@ ldfile_try_open_bfd (const char *attempt,
|
||||
}
|
||||
}
|
||||
}
|
||||
success:
|
||||
#ifdef ENABLE_PLUGINS
|
||||
/* If plugins are active, they get first chance to claim
|
||||
any successfully-opened input file. We skip archives
|
||||
here; the plugin wants us to offer it the individual
|
||||
members when we enumerate them, not the whole file. We
|
||||
also ignore corefiles, because that's just weird. It is
|
||||
a needed side-effect of calling bfd_check_format with
|
||||
bfd_object that it sets the bfd's arch and mach, which
|
||||
will be needed when and if we want to bfd_create a new
|
||||
one using this one as a template. */
|
||||
if (bfd_check_format (entry->the_bfd, bfd_object))
|
||||
{
|
||||
int fd = open (attempt, O_RDONLY | O_BINARY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
struct ld_plugin_input_file file;
|
||||
int claimed = 0;
|
||||
|
||||
file.name = attempt;
|
||||
file.offset = 0;
|
||||
file.filesize = lseek (fd, 0, SEEK_END);
|
||||
file.fd = fd;
|
||||
/* We create a dummy BFD, initially empty, to house
|
||||
whatever symbols the plugin may want to add. */
|
||||
file.handle = plugin_get_ir_dummy_bfd (attempt, entry->the_bfd);
|
||||
if (plugin_call_claim_file (&file, &claimed))
|
||||
einfo (_("%P%F: %s: plugin reported error claiming file\n"),
|
||||
plugin_error_plugin ());
|
||||
if (claimed)
|
||||
{
|
||||
/* Discard the real file's BFD and substitute the dummy one. */
|
||||
bfd_close (entry->the_bfd);
|
||||
entry->the_bfd = file.handle;
|
||||
entry->claimed = TRUE;
|
||||
bfd_make_readable (entry->the_bfd);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If plugin didn't claim the file, we don't need the fd or the
|
||||
dummy bfd. Can't avoid speculatively creating it, alas. */
|
||||
bfd_close_all_done (file.handle);
|
||||
close (fd);
|
||||
entry->claimed = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
/* It opened OK, the format checked out, and the plugins have had
|
||||
their chance to claim it, so this is success. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
32
ld/ldlang.c
32
ld/ldlang.c
@ -40,6 +40,10 @@
|
||||
#include "fnmatch.h"
|
||||
#include "demangle.h"
|
||||
#include "hashtab.h"
|
||||
#include "libbfd.h"
|
||||
#ifdef ENABLE_PLUGINS
|
||||
#include "plugin.h"
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
|
||||
@ -2701,6 +2705,7 @@ load_symbols (lang_input_statement_type *entry,
|
||||
|
||||
for (;;)
|
||||
{
|
||||
bfd *subsbfd;
|
||||
member = bfd_openr_next_archived_file (entry->the_bfd, member);
|
||||
|
||||
if (member == NULL)
|
||||
@ -2713,11 +2718,15 @@ load_symbols (lang_input_statement_type *entry,
|
||||
loaded = FALSE;
|
||||
}
|
||||
|
||||
subsbfd = NULL;
|
||||
if (! ((*link_info.callbacks->add_archive_element)
|
||||
(&link_info, member, "--whole-archive")))
|
||||
(&link_info, member, "--whole-archive", &subsbfd)))
|
||||
abort ();
|
||||
|
||||
if (! bfd_link_add_symbols (member, &link_info))
|
||||
/* Potentially, the add_archive_element hook may have set a
|
||||
substitute BFD for us. */
|
||||
if (! bfd_link_add_symbols (subsbfd ? subsbfd : member,
|
||||
&link_info))
|
||||
{
|
||||
einfo (_("%F%B: could not read symbols: %E\n"), member);
|
||||
loaded = FALSE;
|
||||
@ -6348,6 +6357,25 @@ lang_process (void)
|
||||
current_target = default_target;
|
||||
open_input_bfds (statement_list.head, FALSE);
|
||||
|
||||
#ifdef ENABLE_PLUGINS
|
||||
{
|
||||
union lang_statement_union **listend;
|
||||
/* Now all files are read, let the plugin(s) decide if there
|
||||
are any more to be added to the link before we call the
|
||||
emulation's after_open hook. */
|
||||
listend = statement_list.tail;
|
||||
ASSERT (!*listend);
|
||||
if (plugin_call_all_symbols_read ())
|
||||
einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
|
||||
plugin_error_plugin ());
|
||||
/* If any new files were added, they will be on the end of the
|
||||
statement list, and we can open them now by getting open_input_bfds
|
||||
to carry on from where it ended last time. */
|
||||
if (*listend)
|
||||
open_input_bfds (*listend, FALSE);
|
||||
}
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
link_info.gc_sym_list = &entry_symbol;
|
||||
if (entry_symbol.name == NULL)
|
||||
link_info.gc_sym_list = ldlang_undef_chain_list_head;
|
||||
|
@ -286,6 +286,10 @@ typedef struct lang_input_statement_struct
|
||||
|
||||
/* Set if the file does not exist. */
|
||||
unsigned int missing_file : 1;
|
||||
|
||||
/* Set if the file was claimed by a plugin. */
|
||||
unsigned int claimed : 1;
|
||||
|
||||
} lang_input_statement_type;
|
||||
|
||||
typedef struct
|
||||
|
96
ld/ldmain.c
96
ld/ldmain.c
@ -40,6 +40,11 @@
|
||||
#include "ldfile.h"
|
||||
#include "ldemul.h"
|
||||
#include "ldctor.h"
|
||||
#ifdef ENABLE_PLUGINS
|
||||
#include "plugin.h"
|
||||
#include "plugin-api.h"
|
||||
#include "libbfd.h"
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
/* Somewhere above, sys/stat.h got included. */
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
@ -116,7 +121,7 @@ static const char *get_sysroot
|
||||
static char *get_emulation
|
||||
(int, char **);
|
||||
static bfd_boolean add_archive_element
|
||||
(struct bfd_link_info *, bfd *, const char *);
|
||||
(struct bfd_link_info *, bfd *, const char *, bfd **);
|
||||
static bfd_boolean multiple_definition
|
||||
(struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
|
||||
bfd *, asection *, bfd_vma);
|
||||
@ -474,6 +479,12 @@ main (int argc, char **argv)
|
||||
|
||||
lang_finish ();
|
||||
|
||||
#ifdef ENABLE_PLUGINS
|
||||
/* Now everything is finished, we can tell the plugins to clean up. */
|
||||
if (plugin_call_cleanup ())
|
||||
info_msg (_("%P: %s: error in plugin cleanup (ignored)\n"), plugin_error_plugin ());
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
/* Even if we're producing relocatable output, some non-fatal errors should
|
||||
be reported in the exit status. (What non-fatal errors, if any, do we
|
||||
want to ignore for relocatable output?) */
|
||||
@ -781,9 +792,11 @@ add_keepsyms_file (const char *filename)
|
||||
static bfd_boolean
|
||||
add_archive_element (struct bfd_link_info *info,
|
||||
bfd *abfd,
|
||||
const char *name)
|
||||
const char *name,
|
||||
bfd **subsbfd ATTRIBUTE_UNUSED)
|
||||
{
|
||||
lang_input_statement_type *input;
|
||||
lang_input_statement_type orig_input;
|
||||
|
||||
input = (lang_input_statement_type *)
|
||||
xcalloc (1, sizeof (lang_input_statement_type));
|
||||
@ -791,6 +804,52 @@ add_archive_element (struct bfd_link_info *info,
|
||||
input->local_sym_name = abfd->filename;
|
||||
input->the_bfd = abfd;
|
||||
|
||||
/* Save the original data for trace files/tries below, as plugins
|
||||
(if enabled) may possibly alter it to point to a replacement
|
||||
BFD, but we still want to output the original BFD filename. */
|
||||
orig_input = *input;
|
||||
#ifdef ENABLE_PLUGINS
|
||||
if (bfd_my_archive (abfd) != NULL)
|
||||
{
|
||||
/* We must offer this archive member to the plugins to claim. */
|
||||
int fd = open (bfd_my_archive (abfd)->filename, O_RDONLY | O_BINARY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
struct ld_plugin_input_file file;
|
||||
int claimed = 0;
|
||||
/* Offset and filesize must refer to the individual archive
|
||||
member, not the whole file, and must exclude the header.
|
||||
Fortunately for us, that is how the data is stored in the
|
||||
origin field of the bfd and in the arelt_data. */
|
||||
file.name = bfd_my_archive (abfd)->filename;
|
||||
file.offset = abfd->origin;
|
||||
file.filesize = arelt_size (abfd);
|
||||
file.fd = fd;
|
||||
/* We create a dummy BFD, initially empty, to house
|
||||
whatever symbols the plugin may want to add. */
|
||||
file.handle = plugin_get_ir_dummy_bfd (abfd->filename, abfd);
|
||||
if (plugin_call_claim_file (&file, &claimed))
|
||||
einfo (_("%P%F: %s: plugin reported error claiming file\n"),
|
||||
plugin_error_plugin ());
|
||||
if (claimed)
|
||||
{
|
||||
/* Substitute the dummy BFD. */
|
||||
input->the_bfd = file.handle;
|
||||
input->claimed = TRUE;
|
||||
bfd_make_readable (input->the_bfd);
|
||||
*subsbfd = input->the_bfd;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Abandon the dummy BFD. */
|
||||
bfd_close_all_done (file.handle);
|
||||
close (fd);
|
||||
input->claimed = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
ldlang_add_file (input);
|
||||
|
||||
if (config.map_file != NULL)
|
||||
@ -871,8 +930,7 @@ add_archive_element (struct bfd_link_info *info,
|
||||
}
|
||||
|
||||
if (trace_files || trace_file_tries)
|
||||
info_msg ("%I\n", input);
|
||||
|
||||
info_msg ("%I\n", &orig_input);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -889,6 +947,17 @@ multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||
asection *nsec,
|
||||
bfd_vma nval)
|
||||
{
|
||||
#ifdef ENABLE_PLUGINS
|
||||
/* We may get called back even when --allow-multiple-definition is in
|
||||
effect, as the plugin infrastructure needs to use this hook in
|
||||
order to swap out IR-only symbols for real ones. In that case,
|
||||
it will let us know not to continue by returning TRUE even if this
|
||||
is not an IR-only vs. non-IR symbol conflict. */
|
||||
if (plugin_multiple_definition (info, name, obfd, osec, oval, nbfd,
|
||||
nsec, nval))
|
||||
return TRUE;
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
/* If either section has the output_section field set to
|
||||
bfd_abs_section_ptr, it means that the section is being
|
||||
discarded, and this is not really a multiple definition at all.
|
||||
@ -1371,7 +1440,10 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||
|
||||
/* This is called if link_info.notice_all is set, or when a symbol in
|
||||
link_info.notice_hash is found. Symbols are put in notice_hash
|
||||
using the -y option. */
|
||||
using the -y option, while notice_all is set if the --cref option
|
||||
has been supplied, or if there are any NOCROSSREFS sections in the
|
||||
linker script; and if plugins are active, since they need to monitor
|
||||
all references from non-IR files. */
|
||||
|
||||
static bfd_boolean
|
||||
notice (struct bfd_link_info *info,
|
||||
@ -1387,9 +1459,17 @@ notice (struct bfd_link_info *info,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (! info->notice_all
|
||||
|| (info->notice_hash != NULL
|
||||
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
|
||||
#ifdef ENABLE_PLUGINS
|
||||
/* We should hide symbols in the dummy IR BFDs from the nocrossrefs list
|
||||
and let the real object files that are generated and added later trip
|
||||
the error instead. Similarly would be better to trace the real symbol
|
||||
from the real file than the temporary dummy. */
|
||||
if (!plugin_notice (info, name, abfd, section, value))
|
||||
return TRUE;
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
if (info->notice_hash != NULL
|
||||
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
|
||||
{
|
||||
if (bfd_is_und_section (section))
|
||||
einfo ("%B: reference to %s\n", abfd, name);
|
||||
|
@ -57,12 +57,13 @@
|
||||
%d integer, like printf
|
||||
%ld long, like printf
|
||||
%lu unsigned long, like printf
|
||||
%p native (host) void* pointer, like printf
|
||||
%s arbitrary string, like printf
|
||||
%u integer, like printf
|
||||
%v hex bfd_vma, no leading zeros
|
||||
*/
|
||||
|
||||
static void
|
||||
void
|
||||
vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
|
||||
{
|
||||
bfd_boolean fatal = FALSE;
|
||||
@ -368,6 +369,11 @@ vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
/* native (host) void* pointer, like printf */
|
||||
fprintf (fp, "%p", va_arg (arg, void *));
|
||||
break;
|
||||
|
||||
case 's':
|
||||
/* arbitrary string, like printf */
|
||||
fprintf (fp, "%s", va_arg (arg, char *));
|
||||
|
@ -22,6 +22,7 @@
|
||||
#ifndef LDMISC_H
|
||||
#define LDMISC_H
|
||||
|
||||
extern void vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning);
|
||||
extern void einfo (const char *, ...);
|
||||
extern void minfo (const char *, ...);
|
||||
extern void info_msg (const char *, ...);
|
||||
|
31
ld/lexsup.c
31
ld/lexsup.c
@ -40,6 +40,9 @@
|
||||
#include "ldver.h"
|
||||
#include "ldemul.h"
|
||||
#include "demangle.h"
|
||||
#ifdef ENABLE_PLUGINS
|
||||
#include "plugin.h"
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
|
||||
#ifndef PATH_SEPARATOR
|
||||
#if defined (__MSDOS__) || (defined (_WIN32) && ! defined (__CYGWIN32__))
|
||||
@ -167,7 +170,11 @@ enum option_values
|
||||
OPTION_WARN_SHARED_TEXTREL,
|
||||
OPTION_WARN_ALTERNATE_EM,
|
||||
OPTION_REDUCE_MEMORY_OVERHEADS,
|
||||
OPTION_DEFAULT_SCRIPT
|
||||
#ifdef ENABLE_PLUGINS
|
||||
OPTION_PLUGIN,
|
||||
OPTION_PLUGIN_OPT,
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
OPTION_DEFAULT_SCRIPT,
|
||||
};
|
||||
|
||||
/* The long options. This structure is used for both the option
|
||||
@ -271,6 +278,12 @@ static const struct ld_option ld_options[] =
|
||||
'o', N_("FILE"), N_("Set output file name"), EXACTLY_TWO_DASHES },
|
||||
{ {NULL, required_argument, NULL, '\0'},
|
||||
'O', NULL, N_("Optimize output file"), ONE_DASH },
|
||||
#ifdef ENABLE_PLUGINS
|
||||
{ {"plugin", required_argument, NULL, OPTION_PLUGIN},
|
||||
'\0', N_("PLUGIN"), N_("Load named plugin"), ONE_DASH },
|
||||
{ {"plugin-opt", required_argument, NULL, OPTION_PLUGIN_OPT},
|
||||
'\0', N_("ARG"), N_("Send arg to last-loaded plugin"), ONE_DASH },
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
{ {"Qy", no_argument, NULL, OPTION_IGNORE},
|
||||
'\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
|
||||
{ {"emit-relocs", no_argument, NULL, 'q'},
|
||||
@ -1040,6 +1053,16 @@ parse_args (unsigned argc, char **argv)
|
||||
case OPTION_OFORMAT:
|
||||
lang_add_output_format (optarg, NULL, NULL, 0);
|
||||
break;
|
||||
#ifdef ENABLE_PLUGINS
|
||||
case OPTION_PLUGIN:
|
||||
if (plugin_opt_plugin (optarg))
|
||||
einfo(_("%P%F: bad -plugin option\n"));
|
||||
break;
|
||||
case OPTION_PLUGIN_OPT:
|
||||
if (plugin_opt_plugin_arg (optarg))
|
||||
einfo(_("%P%F: bad -plugin-opt option\n"));
|
||||
break;
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
case 'q':
|
||||
link_info.emitrelocations = TRUE;
|
||||
break;
|
||||
@ -1517,6 +1540,12 @@ parse_args (unsigned argc, char **argv)
|
||||
if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET)
|
||||
/* FIXME: Should we allow emulations a chance to set this ? */
|
||||
link_info.unresolved_syms_in_shared_libs = how_to_report_unresolved_symbols;
|
||||
|
||||
#ifdef ENABLE_PLUGINS
|
||||
/* Now all the plugin arguments have been gathered, we can load them. */
|
||||
if (plugin_load_plugins ())
|
||||
einfo (_("%P%F: %s: error loading plugin\n"), plugin_error_plugin ());
|
||||
#endif /* ENABLE_PLUGINS */
|
||||
}
|
||||
|
||||
/* Add the (colon-separated) elements of DIRLIST_PTR to the
|
||||
|
795
ld/plugin.c
Normal file
795
ld/plugin.c
Normal file
@ -0,0 +1,795 @@
|
||||
/* Plugin control for the GNU linker.
|
||||
Copyright 2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
MA 02110-1301, USA. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include "libiberty.h"
|
||||
#include "bfd.h"
|
||||
#include "bfdlink.h"
|
||||
#include "bfdver.h"
|
||||
#include "ld.h"
|
||||
#include "ldmain.h"
|
||||
#include "ldmisc.h"
|
||||
#include "ldexp.h"
|
||||
#include "ldlang.h"
|
||||
#include "ldfile.h"
|
||||
#include "plugin.h"
|
||||
#include "plugin-api.h"
|
||||
#include "elf-bfd.h"
|
||||
|
||||
/* The suffix to append to the name of the real (claimed) object file
|
||||
when generating a dummy BFD to hold the IR symbols sent from the
|
||||
plugin. */
|
||||
#define IRONLY_SUFFIX ".ironly\004"
|
||||
|
||||
/* This is sizeof an array of chars, not sizeof a const char *. We
|
||||
also have to avoid inadvertently counting the trailing NUL. */
|
||||
#define IRONLY_SUFFIX_LEN (sizeof (IRONLY_SUFFIX) - 1)
|
||||
|
||||
/* Stores a single argument passed to a plugin. */
|
||||
typedef struct plugin_arg
|
||||
{
|
||||
struct plugin_arg *next;
|
||||
const char *arg;
|
||||
} plugin_arg_t;
|
||||
|
||||
/* Holds all details of a single plugin. */
|
||||
typedef struct plugin
|
||||
{
|
||||
/* Next on the list of plugins, or NULL at end of chain. */
|
||||
struct plugin *next;
|
||||
/* The argument string given to --plugin. */
|
||||
const char *name;
|
||||
/* The shared library handle returned by dlopen. */
|
||||
void *dlhandle;
|
||||
/* The list of argument string given to --plugin-opt. */
|
||||
plugin_arg_t *args;
|
||||
/* Number of args in the list, for convenience. */
|
||||
size_t n_args;
|
||||
/* The plugin's event handlers. */
|
||||
ld_plugin_claim_file_handler claim_file_handler;
|
||||
ld_plugin_all_symbols_read_handler all_symbols_read_handler;
|
||||
ld_plugin_cleanup_handler cleanup_handler;
|
||||
/* TRUE if the cleanup handlers have been called. */
|
||||
bfd_boolean cleanup_done;
|
||||
} plugin_t;
|
||||
|
||||
/* The master list of all plugins. */
|
||||
static plugin_t *plugins_list = NULL;
|
||||
|
||||
/* We keep a tail pointer for easy linking on the end. */
|
||||
static plugin_t **plugins_tail_chain_ptr = &plugins_list;
|
||||
|
||||
/* The last plugin added to the list, for receiving args. */
|
||||
static plugin_t *last_plugin = NULL;
|
||||
|
||||
/* The tail of the arg chain of the last plugin added to the list. */
|
||||
static plugin_arg_t **last_plugin_args_tail_chain_ptr = NULL;
|
||||
|
||||
/* The plugin which is currently having a callback executed. */
|
||||
static plugin_t *called_plugin = NULL;
|
||||
|
||||
/* Last plugin to cause an error, if any. */
|
||||
static const char *error_plugin = NULL;
|
||||
|
||||
/* A hash table that records symbols referenced by non-IR files. Used
|
||||
at get_symbols time to determine whether any prevailing defs from
|
||||
IR files are referenced only from other IR files, so tthat we can
|
||||
we can distinguish the LDPR_PREVAILING_DEF and LDPR_PREVAILING_DEF_IRONLY
|
||||
cases when establishing symbol resolutions. */
|
||||
static struct bfd_hash_table *non_ironly_hash = NULL;
|
||||
|
||||
/* Set at all symbols read time, to avoid recursively offering the plugin
|
||||
its own newly-added input files and libs to claim. */
|
||||
static bfd_boolean no_more_claiming = FALSE;
|
||||
|
||||
/* If the --allow-multiple-definition command-line option is active, we
|
||||
have to disable it so that BFD always calls our hook, and simulate the
|
||||
effect (when not resolving IR vs. real symbols) ourselves by ensuring
|
||||
TRUE is returned from the hook. */
|
||||
static bfd_boolean plugin_cached_allow_multiple_defs = FALSE;
|
||||
|
||||
/* List of tags to set in the constant leading part of the tv array. */
|
||||
static const enum ld_plugin_tag tv_header_tags[] =
|
||||
{
|
||||
LDPT_MESSAGE,
|
||||
LDPT_API_VERSION,
|
||||
LDPT_GNU_LD_VERSION,
|
||||
LDPT_LINKER_OUTPUT,
|
||||
LDPT_OUTPUT_NAME,
|
||||
LDPT_REGISTER_CLAIM_FILE_HOOK,
|
||||
LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
|
||||
LDPT_REGISTER_CLEANUP_HOOK,
|
||||
LDPT_ADD_SYMBOLS,
|
||||
LDPT_GET_INPUT_FILE,
|
||||
LDPT_RELEASE_INPUT_FILE,
|
||||
LDPT_GET_SYMBOLS,
|
||||
LDPT_ADD_INPUT_FILE,
|
||||
LDPT_ADD_INPUT_LIBRARY,
|
||||
LDPT_SET_EXTRA_LIBRARY_PATH
|
||||
};
|
||||
|
||||
/* How many entries in the constant leading part of the tv array. */
|
||||
static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
|
||||
|
||||
/* Helper function for exiting with error status. */
|
||||
static int
|
||||
set_plugin_error (const char *plugin)
|
||||
{
|
||||
error_plugin = plugin;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Test if an error occurred. */
|
||||
static bfd_boolean
|
||||
plugin_error_p (void)
|
||||
{
|
||||
return error_plugin != NULL;
|
||||
}
|
||||
|
||||
/* Return name of plugin which caused an error if any. */
|
||||
const char *plugin_error_plugin (void)
|
||||
{
|
||||
return error_plugin ? error_plugin : _("<no plugin>");
|
||||
}
|
||||
|
||||
/* Handle -plugin arg: find and load plugin, or return error. */
|
||||
int plugin_opt_plugin (const char *plugin)
|
||||
{
|
||||
plugin_t *newplug;
|
||||
|
||||
newplug = xmalloc (sizeof *newplug);
|
||||
memset (newplug, 0, sizeof *newplug);
|
||||
newplug->name = plugin;
|
||||
newplug->dlhandle = dlopen (plugin, RTLD_NOW);
|
||||
if (!newplug->dlhandle)
|
||||
return set_plugin_error (plugin);
|
||||
|
||||
/* Chain on end, so when we run list it is in command-line order. */
|
||||
*plugins_tail_chain_ptr = newplug;
|
||||
plugins_tail_chain_ptr = &newplug->next;
|
||||
|
||||
/* Record it as current plugin for receiving args. */
|
||||
last_plugin = newplug;
|
||||
last_plugin_args_tail_chain_ptr = &newplug->args;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Accumulate option arguments for last-loaded plugin, or return
|
||||
error if none. */
|
||||
int plugin_opt_plugin_arg (const char *arg)
|
||||
{
|
||||
plugin_arg_t *newarg;
|
||||
|
||||
if (!last_plugin)
|
||||
return set_plugin_error (_("<no plugin>"));
|
||||
|
||||
newarg = xmalloc (sizeof *newarg);
|
||||
newarg->arg = arg;
|
||||
newarg->next = NULL;
|
||||
|
||||
/* Chain on end to preserve command-line order. */
|
||||
*last_plugin_args_tail_chain_ptr = newarg;
|
||||
last_plugin_args_tail_chain_ptr = &newarg->next;
|
||||
last_plugin->n_args++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a dummy BFD. */
|
||||
bfd *
|
||||
plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
|
||||
{
|
||||
asection *sec;
|
||||
bfd *abfd = bfd_create (
|
||||
concat (name, IRONLY_SUFFIX, (const char *)NULL),
|
||||
srctemplate);
|
||||
bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
|
||||
bfd_make_writable (abfd);
|
||||
/* Create a minimal set of sections to own the symbols. */
|
||||
sec = bfd_make_section_old_way (abfd, ".text");
|
||||
bfd_set_section_flags (abfd, sec,
|
||||
SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
|
||||
| SEC_ALLOC | SEC_LOAD | SEC_KEEP);
|
||||
sec->output_section = sec;
|
||||
sec->output_offset = 0;
|
||||
return abfd;
|
||||
}
|
||||
|
||||
/* Check if the BFD is an IR dummy. */
|
||||
bfd_boolean
|
||||
is_ir_dummy_bfd (const bfd *abfd)
|
||||
{
|
||||
size_t namlen = strlen (abfd->filename);
|
||||
if (namlen < IRONLY_SUFFIX_LEN)
|
||||
return FALSE;
|
||||
return !strcmp (abfd->filename + namlen - IRONLY_SUFFIX_LEN, IRONLY_SUFFIX);
|
||||
}
|
||||
|
||||
/* Helpers to convert between BFD and GOLD symbol formats. */
|
||||
static enum ld_plugin_status
|
||||
asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
|
||||
const struct ld_plugin_symbol *ldsym)
|
||||
{
|
||||
flagword flags = BSF_NO_FLAGS;
|
||||
struct bfd_section *section;
|
||||
|
||||
asym->the_bfd = abfd;
|
||||
asym->name = ldsym->version
|
||||
? concat (ldsym->name, "@", ldsym->version, NULL)
|
||||
: ldsym->name;
|
||||
asym->value = 0;
|
||||
switch (ldsym->def)
|
||||
{
|
||||
case LDPK_WEAKDEF:
|
||||
flags = BSF_WEAK;
|
||||
/* FALLTHRU */
|
||||
case LDPK_DEF:
|
||||
flags |= BSF_GLOBAL;
|
||||
section = bfd_get_section_by_name (abfd, ".text");
|
||||
break;
|
||||
|
||||
case LDPK_WEAKUNDEF:
|
||||
flags = BSF_WEAK;
|
||||
/* FALLTHRU */
|
||||
case LDPK_UNDEF:
|
||||
section = bfd_und_section_ptr;
|
||||
break;
|
||||
|
||||
case LDPK_COMMON:
|
||||
flags = BSF_GLOBAL;
|
||||
section = bfd_com_section_ptr;
|
||||
asym->value = ldsym->size;
|
||||
break;
|
||||
|
||||
default:
|
||||
return LDPS_ERR;
|
||||
}
|
||||
asym->flags = flags;
|
||||
asym->section = section;
|
||||
|
||||
/* Visibility only applies on ELF targets. */
|
||||
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
|
||||
{
|
||||
elf_symbol_type *elfsym = elf_symbol_from (abfd, asym);
|
||||
if (!elfsym)
|
||||
einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!"), asym->name);
|
||||
elfsym->internal_elf_sym.st_other &= ~3;
|
||||
elfsym->internal_elf_sym.st_other |= ldsym->visibility;
|
||||
}
|
||||
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Register a claim-file handler. */
|
||||
static enum ld_plugin_status
|
||||
register_claim_file (ld_plugin_claim_file_handler handler)
|
||||
{
|
||||
ASSERT (called_plugin);
|
||||
called_plugin->claim_file_handler = handler;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Register an all-symbols-read handler. */
|
||||
static enum ld_plugin_status
|
||||
register_all_symbols_read (ld_plugin_all_symbols_read_handler handler)
|
||||
{
|
||||
ASSERT (called_plugin);
|
||||
called_plugin->all_symbols_read_handler = handler;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Register a cleanup handler. */
|
||||
static enum ld_plugin_status
|
||||
register_cleanup (ld_plugin_cleanup_handler handler)
|
||||
{
|
||||
ASSERT (called_plugin);
|
||||
called_plugin->cleanup_handler = handler;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Add symbols from a plugin-claimed input file. */
|
||||
static enum ld_plugin_status
|
||||
add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
|
||||
{
|
||||
asymbol **symptrs;
|
||||
bfd *abfd = handle;
|
||||
int n;
|
||||
ASSERT (called_plugin);
|
||||
symptrs = xmalloc (nsyms * sizeof *symptrs);
|
||||
for (n = 0; n < nsyms; n++)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
asymbol *bfdsym = bfd_make_empty_symbol (abfd);
|
||||
symptrs[n] = bfdsym;
|
||||
rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);
|
||||
if (rv != LDPS_OK)
|
||||
return rv;
|
||||
}
|
||||
bfd_set_symtab (abfd, symptrs, nsyms);
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Get the input file information with an open (possibly re-opened)
|
||||
file descriptor. */
|
||||
static enum ld_plugin_status
|
||||
get_input_file (const void *handle, struct ld_plugin_input_file *file)
|
||||
{
|
||||
ASSERT (called_plugin);
|
||||
handle = handle;
|
||||
file = file;
|
||||
return LDPS_ERR;
|
||||
}
|
||||
|
||||
/* Release the input file. */
|
||||
static enum ld_plugin_status
|
||||
release_input_file (const void *handle)
|
||||
{
|
||||
ASSERT (called_plugin);
|
||||
handle = handle;
|
||||
return LDPS_ERR;
|
||||
}
|
||||
|
||||
/* Get the symbol resolution info for a plugin-claimed input file. */
|
||||
static enum ld_plugin_status
|
||||
get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
|
||||
{
|
||||
const bfd *abfd = handle;
|
||||
int n;
|
||||
ASSERT (called_plugin);
|
||||
for (n = 0; n < nsyms; n++)
|
||||
{
|
||||
struct bfd_link_hash_entry *blhe;
|
||||
bfd_boolean ironly;
|
||||
|
||||
blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
|
||||
FALSE, FALSE, TRUE);
|
||||
if (!blhe)
|
||||
{
|
||||
syms[n].resolution = LDPR_UNKNOWN;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine resolution from blhe type and symbol's original type. */
|
||||
if (blhe->type == bfd_link_hash_undefined
|
||||
|| blhe->type == bfd_link_hash_undefweak)
|
||||
{
|
||||
syms[n].resolution = LDPR_UNDEF;
|
||||
continue;
|
||||
}
|
||||
if (blhe->type != bfd_link_hash_defined
|
||||
&& blhe->type != bfd_link_hash_defweak
|
||||
&& blhe->type != bfd_link_hash_common)
|
||||
{
|
||||
/* We should not have a new, indirect or warning symbol here. */
|
||||
einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)",
|
||||
called_plugin->name, blhe->type);
|
||||
}
|
||||
|
||||
/* We need to know if the sym is referenced from non-IR files. */
|
||||
ironly = !bfd_hash_lookup (non_ironly_hash, syms[n].name, FALSE, FALSE);
|
||||
|
||||
/* If it was originally undefined or common, then it has been
|
||||
resolved; determine how. */
|
||||
if (syms[n].def == LDPK_UNDEF || syms[n].def == LDPK_WEAKUNDEF
|
||||
|| syms[n].def == LDPK_COMMON)
|
||||
{
|
||||
asection *owner_sec = (syms[n].def == LDPK_COMMON)
|
||||
? blhe->u.c.p->section
|
||||
: blhe->u.def.section;
|
||||
if (owner_sec->owner == link_info.output_bfd)
|
||||
syms[n].resolution = LDPR_RESOLVED_EXEC;
|
||||
else if (owner_sec->owner == abfd)
|
||||
syms[n].resolution = (ironly)
|
||||
? LDPR_PREVAILING_DEF_IRONLY
|
||||
: LDPR_PREVAILING_DEF;
|
||||
else if (is_ir_dummy_bfd (owner_sec->owner))
|
||||
syms[n].resolution = LDPR_RESOLVED_IR;
|
||||
else if (owner_sec->owner->flags & DYNAMIC)
|
||||
syms[n].resolution = LDPR_RESOLVED_DYN;
|
||||
else
|
||||
syms[n].resolution = LDPR_RESOLVED_EXEC;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Was originally def, or weakdef. Does it prevail? If the
|
||||
owner is the original dummy bfd that supplied it, then this
|
||||
is the definition that has prevailed. */
|
||||
if (blhe->u.def.section->owner == link_info.output_bfd)
|
||||
syms[n].resolution = LDPR_PREEMPTED_REG;
|
||||
else if (blhe->u.def.section->owner == abfd)
|
||||
{
|
||||
syms[n].resolution = (ironly)
|
||||
? LDPR_PREVAILING_DEF_IRONLY
|
||||
: LDPR_PREVAILING_DEF;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Was originally def, weakdef, or common, but has been pre-empted. */
|
||||
syms[n].resolution = is_ir_dummy_bfd (blhe->u.def.section->owner)
|
||||
? LDPR_PREEMPTED_IR
|
||||
: LDPR_PREEMPTED_REG;
|
||||
}
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Add a new (real) input file generated by a plugin. */
|
||||
static enum ld_plugin_status
|
||||
add_input_file (const char *pathname)
|
||||
{
|
||||
ASSERT (called_plugin);
|
||||
if (!lang_add_input_file (pathname, lang_input_file_is_file_enum, NULL))
|
||||
return LDPS_ERR;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Add a new (real) library required by a plugin. */
|
||||
static enum ld_plugin_status
|
||||
add_input_library (const char *pathname)
|
||||
{
|
||||
ASSERT (called_plugin);
|
||||
if (!lang_add_input_file (pathname, lang_input_file_is_l_enum, NULL))
|
||||
return LDPS_ERR;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Set the extra library path to be used by libraries added via
|
||||
add_input_library. */
|
||||
static enum ld_plugin_status
|
||||
set_extra_library_path (const char *path)
|
||||
{
|
||||
ASSERT (called_plugin);
|
||||
ldfile_add_library_path (path, FALSE);
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Issue a diagnostic message from a plugin. */
|
||||
static enum ld_plugin_status
|
||||
message (int level, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case LDPL_INFO:
|
||||
vfinfo (stdout, format, args, FALSE);
|
||||
break;
|
||||
case LDPL_WARNING:
|
||||
vfinfo (stdout, format, args, TRUE);
|
||||
break;
|
||||
case LDPL_FATAL:
|
||||
case LDPL_ERROR:
|
||||
default:
|
||||
{
|
||||
char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%F" : "%X",
|
||||
format, NULL));
|
||||
vfinfo (stderr, newfmt, args, TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
va_end (args);
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Helper to size leading part of tv array and set it up. */
|
||||
static size_t
|
||||
set_tv_header (struct ld_plugin_tv *tv)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/* Version info. */
|
||||
static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL);
|
||||
static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100;
|
||||
|
||||
if (!tv)
|
||||
return tv_header_size;
|
||||
|
||||
for (i = 0; i < tv_header_size; i++)
|
||||
{
|
||||
tv[i].tv_tag = tv_header_tags[i];
|
||||
#define TVU(x) tv[i].tv_u.tv_ ## x
|
||||
switch (tv[i].tv_tag)
|
||||
{
|
||||
case LDPT_MESSAGE:
|
||||
TVU(message) = message;
|
||||
break;
|
||||
case LDPT_API_VERSION:
|
||||
TVU(val) = LD_PLUGIN_API_VERSION;
|
||||
break;
|
||||
case LDPT_GNU_LD_VERSION:
|
||||
TVU(val) = major * 100 + minor;
|
||||
break;
|
||||
case LDPT_LINKER_OUTPUT:
|
||||
TVU(val) = link_info.relocatable ? LDPO_REL
|
||||
: (link_info.shared ? LDPO_DYN : LDPO_EXEC);
|
||||
break;
|
||||
case LDPT_OUTPUT_NAME:
|
||||
TVU(string) = output_filename;
|
||||
break;
|
||||
case LDPT_REGISTER_CLAIM_FILE_HOOK:
|
||||
TVU(register_claim_file) = register_claim_file;
|
||||
break;
|
||||
case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
|
||||
TVU(register_all_symbols_read) = register_all_symbols_read;
|
||||
break;
|
||||
case LDPT_REGISTER_CLEANUP_HOOK:
|
||||
TVU(register_cleanup) = register_cleanup;
|
||||
break;
|
||||
case LDPT_ADD_SYMBOLS:
|
||||
TVU(add_symbols) = add_symbols;
|
||||
break;
|
||||
case LDPT_GET_INPUT_FILE:
|
||||
TVU(get_input_file) = get_input_file;
|
||||
break;
|
||||
case LDPT_RELEASE_INPUT_FILE:
|
||||
TVU(release_input_file) = release_input_file;
|
||||
break;
|
||||
case LDPT_GET_SYMBOLS:
|
||||
TVU(get_symbols) = get_symbols;
|
||||
break;
|
||||
case LDPT_ADD_INPUT_FILE:
|
||||
TVU(add_input_file) = add_input_file;
|
||||
break;
|
||||
case LDPT_ADD_INPUT_LIBRARY:
|
||||
TVU(add_input_library) = add_input_library;
|
||||
break;
|
||||
case LDPT_SET_EXTRA_LIBRARY_PATH:
|
||||
TVU(set_extra_library_path) = set_extra_library_path;
|
||||
break;
|
||||
default:
|
||||
/* Added a new entry to the array without adding
|
||||
a new case to set up its value is a bug. */
|
||||
FAIL ();
|
||||
}
|
||||
#undef TVU
|
||||
}
|
||||
return tv_header_size;
|
||||
}
|
||||
|
||||
/* Append the per-plugin args list and trailing LDPT_NULL to tv. */
|
||||
static void
|
||||
set_tv_plugin_args (plugin_t *plugin, struct ld_plugin_tv *tv)
|
||||
{
|
||||
plugin_arg_t *arg = plugin->args;
|
||||
while (arg)
|
||||
{
|
||||
tv->tv_tag = LDPT_OPTION;
|
||||
tv->tv_u.tv_string = arg->arg;
|
||||
arg = arg->next;
|
||||
tv++;
|
||||
}
|
||||
tv->tv_tag = LDPT_NULL;
|
||||
tv->tv_u.tv_val = 0;
|
||||
}
|
||||
|
||||
/* Load up and initialise all plugins after argument parsing. */
|
||||
int plugin_load_plugins (void)
|
||||
{
|
||||
struct ld_plugin_tv *my_tv;
|
||||
unsigned int max_args = 0;
|
||||
plugin_t *curplug = plugins_list;
|
||||
|
||||
/* If there are no plugins, we need do nothing this run. */
|
||||
if (!curplug)
|
||||
return 0;
|
||||
|
||||
/* First pass over plugins to find max # args needed so that we
|
||||
can size and allocate the tv array. */
|
||||
while (curplug)
|
||||
{
|
||||
if (curplug->n_args > max_args)
|
||||
max_args = curplug->n_args;
|
||||
curplug = curplug->next;
|
||||
}
|
||||
|
||||
/* Allocate tv array and initialise constant part. */
|
||||
my_tv = xmalloc ((max_args + 1 + tv_header_size) * sizeof *my_tv);
|
||||
set_tv_header (my_tv);
|
||||
|
||||
/* Pass over plugins again, activating them. */
|
||||
curplug = plugins_list;
|
||||
while (curplug)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
ld_plugin_onload onloadfn = dlsym (curplug->dlhandle, "onload");
|
||||
if (!onloadfn)
|
||||
onloadfn = dlsym (curplug->dlhandle, "_onload");
|
||||
if (!onloadfn)
|
||||
return set_plugin_error (curplug->name);
|
||||
set_tv_plugin_args (curplug, &my_tv[tv_header_size]);
|
||||
called_plugin = curplug;
|
||||
rv = (*onloadfn) (my_tv);
|
||||
called_plugin = NULL;
|
||||
if (rv != LDPS_OK)
|
||||
return set_plugin_error (curplug->name);
|
||||
curplug = curplug->next;
|
||||
}
|
||||
|
||||
/* Since plugin(s) inited ok, assume they're going to want symbol
|
||||
resolutions, which needs us to track which symbols are referenced
|
||||
by non-IR files using the linker's notice callback. */
|
||||
link_info.notice_all = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Call 'claim file' hook for all plugins. */
|
||||
int
|
||||
plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
|
||||
{
|
||||
plugin_t *curplug = plugins_list;
|
||||
*claimed = FALSE;
|
||||
if (no_more_claiming)
|
||||
return 0;
|
||||
while (curplug && !*claimed)
|
||||
{
|
||||
if (curplug->claim_file_handler)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
called_plugin = curplug;
|
||||
rv = (*curplug->claim_file_handler) (file, claimed);
|
||||
called_plugin = NULL;
|
||||
if (rv != LDPS_OK)
|
||||
set_plugin_error (curplug->name);
|
||||
}
|
||||
curplug = curplug->next;
|
||||
}
|
||||
return plugin_error_p () ? -1 : 0;
|
||||
}
|
||||
|
||||
/* Call 'all symbols read' hook for all plugins. */
|
||||
int
|
||||
plugin_call_all_symbols_read (void)
|
||||
{
|
||||
plugin_t *curplug = plugins_list;
|
||||
|
||||
/* Disable any further file-claiming. */
|
||||
no_more_claiming = TRUE;
|
||||
|
||||
/* If --allow-multiple-definition is in effect, we need to disable it,
|
||||
as the plugin infrastructure relies on the multiple_definition
|
||||
callback to swap out the dummy IR-only BFDs for new real ones
|
||||
when it starts opening the files added during this callback. */
|
||||
plugin_cached_allow_multiple_defs = link_info.allow_multiple_definition;
|
||||
link_info.allow_multiple_definition = FALSE;
|
||||
|
||||
while (curplug)
|
||||
{
|
||||
if (curplug->all_symbols_read_handler)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
called_plugin = curplug;
|
||||
rv = (*curplug->all_symbols_read_handler) ();
|
||||
called_plugin = NULL;
|
||||
if (rv != LDPS_OK)
|
||||
set_plugin_error (curplug->name);
|
||||
}
|
||||
curplug = curplug->next;
|
||||
}
|
||||
return plugin_error_p () ? -1 : 0;
|
||||
}
|
||||
|
||||
/* Call 'cleanup' hook for all plugins. */
|
||||
int
|
||||
plugin_call_cleanup (void)
|
||||
{
|
||||
plugin_t *curplug = plugins_list;
|
||||
while (curplug)
|
||||
{
|
||||
if (curplug->cleanup_handler && !curplug->cleanup_done)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
curplug->cleanup_done = TRUE;
|
||||
called_plugin = curplug;
|
||||
rv = (*curplug->cleanup_handler) ();
|
||||
called_plugin = NULL;
|
||||
if (rv != LDPS_OK)
|
||||
set_plugin_error (curplug->name);
|
||||
dlclose (curplug->dlhandle);
|
||||
}
|
||||
curplug = curplug->next;
|
||||
}
|
||||
return plugin_error_p () ? -1 : 0;
|
||||
}
|
||||
|
||||
/* Lazily init the non_ironly hash table. */
|
||||
static void
|
||||
init_non_ironly_hash (void)
|
||||
{
|
||||
if (non_ironly_hash == NULL)
|
||||
{
|
||||
non_ironly_hash =
|
||||
(struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
|
||||
if (!bfd_hash_table_init_n (non_ironly_hash,
|
||||
bfd_hash_newfunc,
|
||||
sizeof (struct bfd_hash_entry),
|
||||
61))
|
||||
einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
|
||||
and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
|
||||
the linker adds them to the linker hash table. If we see a symbol
|
||||
being referenced from a non-IR file, we add it to the non_ironly hash
|
||||
table. If we can't find it there at get_symbols time, we know that
|
||||
it was referenced only by IR files. We have to notice_all symbols,
|
||||
because we won't necessarily know until later which ones will be
|
||||
contributed by IR files. */
|
||||
bfd_boolean
|
||||
plugin_notice (struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||
const char *name, bfd *abfd,
|
||||
asection *section, bfd_vma value ATTRIBUTE_UNUSED)
|
||||
{
|
||||
bfd_boolean is_ref = bfd_is_und_section (section);
|
||||
bfd_boolean is_dummy = is_ir_dummy_bfd (abfd);
|
||||
init_non_ironly_hash ();
|
||||
/* We only care about refs, not defs, indicated by section pointing
|
||||
to the undefined section (according to the bfd linker notice callback
|
||||
interface definition). */
|
||||
if (is_ref && !is_dummy)
|
||||
{
|
||||
/* This is a ref from a non-IR file, so note the ref'd symbol
|
||||
in the non-IR-only hash. */
|
||||
if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
|
||||
einfo (_("%P%X: %s: hash table failure adding symbol %s"),
|
||||
abfd->filename, name);
|
||||
}
|
||||
else if (!is_ref && is_dummy)
|
||||
{
|
||||
/* No further processing since this is a def from an IR dummy BFD. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Continue with cref/nocrossref/trace-sym processing. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* When we add new object files to the link at all symbols read time,
|
||||
these contain the real code and symbols generated from the IR files,
|
||||
and so duplicate all the definitions already supplied by the dummy
|
||||
IR-only BFDs that we created at claim files time. We use the linker's
|
||||
multiple-definitions callback hook to fix up the clash, discarding
|
||||
the symbol from the IR-only BFD in favour of the symbol from the
|
||||
real BFD. We return true if this was not-really-a-clash because
|
||||
we've fixed it up, or anyway if --allow-multiple-definition was in
|
||||
effect (before we disabled it to ensure we got called back). */
|
||||
bfd_boolean
|
||||
plugin_multiple_definition (struct bfd_link_info *info, const char *name,
|
||||
bfd *obfd, asection *osec ATTRIBUTE_UNUSED,
|
||||
bfd_vma oval ATTRIBUTE_UNUSED,
|
||||
bfd *nbfd, asection *nsec, bfd_vma nval)
|
||||
{
|
||||
if (is_ir_dummy_bfd (obfd))
|
||||
{
|
||||
struct bfd_link_hash_entry *blhe = bfd_link_hash_lookup (info->hash,
|
||||
name, FALSE, FALSE, FALSE);
|
||||
if (!blhe)
|
||||
einfo (_("%P%X: %s: can't find IR symbol '%s'"), nbfd->filename,
|
||||
name);
|
||||
else if (blhe->type != bfd_link_hash_defined)
|
||||
einfo (_("%P%x: %s: bad IR symbol type %d"), name, blhe->type);
|
||||
/* Replace it with new details. */
|
||||
blhe->u.def.section = nsec;
|
||||
blhe->u.def.value = nval;
|
||||
return TRUE;
|
||||
}
|
||||
return plugin_cached_allow_multiple_defs;
|
||||
}
|
73
ld/plugin.h
Normal file
73
ld/plugin.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* Plugin control for the GNU linker.
|
||||
Copyright 2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
MA 02110-1301, USA. */
|
||||
|
||||
#ifndef GLD_PLUGIN_H
|
||||
#define GLD_PLUGIN_H
|
||||
|
||||
|
||||
/* This is the only forward declaration we need to avoid having
|
||||
to include the plugin-api.h header in order to use this file. */
|
||||
struct ld_plugin_input_file;
|
||||
|
||||
/* Handle -plugin arg: find and load plugin, or return error. */
|
||||
extern int plugin_opt_plugin (const char *plugin);
|
||||
|
||||
/* Accumulate option arguments for last-loaded plugin, or return
|
||||
error if none. */
|
||||
extern int plugin_opt_plugin_arg (const char *arg);
|
||||
|
||||
/* Load up and initialise all plugins after argument parsing. */
|
||||
extern int plugin_load_plugins (void);
|
||||
|
||||
/* Return name of plugin which caused an error in any of the above. */
|
||||
extern const char *plugin_error_plugin (void);
|
||||
|
||||
/* Call 'claim file' hook for all plugins. */
|
||||
extern int plugin_call_claim_file (const struct ld_plugin_input_file *file,
|
||||
int *claimed);
|
||||
|
||||
/* Call 'all symbols read' hook for all plugins. */
|
||||
extern int plugin_call_all_symbols_read (void);
|
||||
|
||||
/* Call 'cleanup' hook for all plugins. */
|
||||
extern int plugin_call_cleanup (void);
|
||||
|
||||
/* Generate a dummy BFD to represent an IR file, for any callers of
|
||||
plugin_call_claim_file to use as the handle in the ld_plugin_input_file
|
||||
struct that they build to pass in. The BFD is initially writable, so
|
||||
that symbols can be added to it; it must be made readable after the
|
||||
add_symbols hook has been called so that it can be read when linking. */
|
||||
extern bfd *plugin_get_ir_dummy_bfd (const char *name, bfd *template);
|
||||
|
||||
/* Check if the BFD passed in is an IR dummy object file. */
|
||||
extern bfd_boolean is_ir_dummy_bfd (const bfd *abfd);
|
||||
|
||||
/* Notice-symbol bfd linker callback hook. */
|
||||
extern bfd_boolean plugin_notice (struct bfd_link_info *info,
|
||||
const char *name, bfd *abfd, asection *section,
|
||||
bfd_vma value);
|
||||
|
||||
/* Multiple-definition bfd linker callback hook. */
|
||||
extern bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
|
||||
const char *name,
|
||||
bfd *obfd, asection *osec, bfd_vma oval,
|
||||
bfd *nbfd, asection *nsec, bfd_vma nval);
|
||||
|
||||
#endif /* !def GLD_PLUGIN_H */
|
45
ld/sysdep.h
45
ld/sysdep.h
@ -27,6 +27,7 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
@ -71,12 +72,56 @@ extern char *strrchr ();
|
||||
# define REALPATH(a,b) NULL
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_BINARY_FOPEN
|
||||
#include "fopen-bin.h"
|
||||
#else
|
||||
#include "fopen-same.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#ifdef HAVE_SYS_FILE_H
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This is both more precise than and includes HAVE_DLFCN_H. */
|
||||
#ifdef ENABLE_PLUGINS
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifndef O_RDONLY
|
||||
#define O_RDONLY 0
|
||||
#endif
|
||||
#ifndef O_WRONLY
|
||||
#define O_WRONLY 1
|
||||
#endif
|
||||
#ifndef O_RDWR
|
||||
#define O_RDWR 2
|
||||
#endif
|
||||
#ifndef O_ACCMODE
|
||||
#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
|
||||
#endif
|
||||
/* Systems that don't already define this, don't need it. */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
#ifndef SEEK_CUR
|
||||
#define SEEK_CUR 1
|
||||
#endif
|
||||
#ifndef SEEK_END
|
||||
#define SEEK_END 2
|
||||
#endif
|
||||
|
||||
#if !HAVE_DECL_STRSTR
|
||||
extern char *strstr ();
|
||||
#endif
|
||||
|
617
ld/testplug.c
Normal file
617
ld/testplug.c
Normal file
@ -0,0 +1,617 @@
|
||||
/* Test plugin for the GNU linker.
|
||||
Copyright 2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Binutils.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
MA 02110-1301, USA. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include "bfd.h"
|
||||
#include "plugin-api.h"
|
||||
/* For ARRAY_SIZE macro only - we don't link the library itself. */
|
||||
#include "libiberty.h"
|
||||
|
||||
extern enum ld_plugin_status onload (struct ld_plugin_tv *tv);
|
||||
static enum ld_plugin_status onclaim_file (const struct ld_plugin_input_file *file,
|
||||
int *claimed);
|
||||
static enum ld_plugin_status onall_symbols_read (void);
|
||||
static enum ld_plugin_status oncleanup (void);
|
||||
|
||||
/* Helper for calling plugin api message function. */
|
||||
#define TV_MESSAGE if (tv_message) (*tv_message)
|
||||
|
||||
/* Struct for recording files to claim / files claimed. */
|
||||
typedef struct claim_file
|
||||
{
|
||||
struct claim_file *next;
|
||||
struct ld_plugin_input_file file;
|
||||
bfd_boolean claimed;
|
||||
struct ld_plugin_symbol *symbols;
|
||||
int n_syms_allocated;
|
||||
int n_syms_used;
|
||||
} claim_file_t;
|
||||
|
||||
/* Types of things that can be added at all symbols read time. */
|
||||
typedef enum addfile_enum
|
||||
{
|
||||
ADD_FILE,
|
||||
ADD_LIB,
|
||||
ADD_DIR
|
||||
} addfile_enum_t;
|
||||
|
||||
/* Struct for recording files to add to final link. */
|
||||
typedef struct add_file
|
||||
{
|
||||
struct add_file *next;
|
||||
const char *name;
|
||||
addfile_enum_t type;
|
||||
} add_file_t;
|
||||
|
||||
/* Helper macro for defining array of transfer vector tags and names. */
|
||||
#define ADDENTRY(tag) { tag, #tag }
|
||||
|
||||
/* Struct for looking up human-readable versions of tag names. */
|
||||
typedef struct tag_name
|
||||
{
|
||||
enum ld_plugin_tag tag;
|
||||
const char *name;
|
||||
} tag_name_t;
|
||||
|
||||
/* Array of all known tags and their names. */
|
||||
static const tag_name_t tag_names[] =
|
||||
{
|
||||
ADDENTRY(LDPT_NULL),
|
||||
ADDENTRY(LDPT_API_VERSION),
|
||||
ADDENTRY(LDPT_GOLD_VERSION),
|
||||
ADDENTRY(LDPT_LINKER_OUTPUT),
|
||||
ADDENTRY(LDPT_OPTION),
|
||||
ADDENTRY(LDPT_REGISTER_CLAIM_FILE_HOOK),
|
||||
ADDENTRY(LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK),
|
||||
ADDENTRY(LDPT_REGISTER_CLEANUP_HOOK),
|
||||
ADDENTRY(LDPT_ADD_SYMBOLS),
|
||||
ADDENTRY(LDPT_GET_SYMBOLS),
|
||||
ADDENTRY(LDPT_ADD_INPUT_FILE),
|
||||
ADDENTRY(LDPT_MESSAGE),
|
||||
ADDENTRY(LDPT_GET_INPUT_FILE),
|
||||
ADDENTRY(LDPT_RELEASE_INPUT_FILE),
|
||||
ADDENTRY(LDPT_ADD_INPUT_LIBRARY),
|
||||
ADDENTRY(LDPT_OUTPUT_NAME),
|
||||
ADDENTRY(LDPT_SET_EXTRA_LIBRARY_PATH),
|
||||
ADDENTRY(LDPT_GNU_LD_VERSION)
|
||||
};
|
||||
|
||||
/* Function pointers to cache hooks passed at onload time. */
|
||||
static ld_plugin_register_claim_file tv_register_claim_file = 0;
|
||||
static ld_plugin_register_all_symbols_read tv_register_all_symbols_read = 0;
|
||||
static ld_plugin_register_cleanup tv_register_cleanup = 0;
|
||||
static ld_plugin_add_symbols tv_add_symbols = 0;
|
||||
static ld_plugin_get_symbols tv_get_symbols = 0;
|
||||
static ld_plugin_add_input_file tv_add_input_file = 0;
|
||||
static ld_plugin_message tv_message = 0;
|
||||
static ld_plugin_get_input_file tv_get_input_file = 0;
|
||||
static ld_plugin_release_input_file tv_release_input_file = 0;
|
||||
static ld_plugin_add_input_library tv_add_input_library = 0;
|
||||
static ld_plugin_set_extra_library_path tv_set_extra_library_path = 0;
|
||||
|
||||
/* Other cached info from the transfer vector. */
|
||||
static enum ld_plugin_output_file_type linker_output;
|
||||
static const char *output_name;
|
||||
|
||||
/* Behaviour control flags set by plugin options. */
|
||||
static enum ld_plugin_status onload_ret = LDPS_OK;
|
||||
static enum ld_plugin_status claim_file_ret = LDPS_OK;
|
||||
static enum ld_plugin_status all_symbols_read_ret = LDPS_OK;
|
||||
static enum ld_plugin_status cleanup_ret = LDPS_OK;
|
||||
static bfd_boolean register_claimfile_hook = FALSE;
|
||||
static bfd_boolean register_allsymbolsread_hook = FALSE;
|
||||
static bfd_boolean register_cleanup_hook = FALSE;
|
||||
static bfd_boolean dumpresolutions = FALSE;
|
||||
|
||||
/* The master list of all claimable/claimed files. */
|
||||
static claim_file_t *claimfiles_list = NULL;
|
||||
|
||||
/* We keep a tail pointer for easy linking on the end. */
|
||||
static claim_file_t **claimfiles_tail_chain_ptr = &claimfiles_list;
|
||||
|
||||
/* The last claimed file added to the list, for receiving syms. */
|
||||
static claim_file_t *last_claimfile = NULL;
|
||||
|
||||
/* The master list of all files to add to the final link. */
|
||||
static add_file_t *addfiles_list = NULL;
|
||||
|
||||
/* We keep a tail pointer for easy linking on the end. */
|
||||
static add_file_t **addfiles_tail_chain_ptr = &addfiles_list;
|
||||
|
||||
/* Add a new claimfile on the end of the chain. */
|
||||
static enum ld_plugin_status
|
||||
record_claim_file (const char *file)
|
||||
{
|
||||
claim_file_t *newfile;
|
||||
|
||||
newfile = malloc (sizeof *newfile);
|
||||
if (!newfile)
|
||||
return LDPS_ERR;
|
||||
memset (newfile, 0, sizeof *newfile);
|
||||
/* Only setup for now is remembering the name to look for. */
|
||||
newfile->file.name = file;
|
||||
/* Chain it on the end of the list. */
|
||||
*claimfiles_tail_chain_ptr = newfile;
|
||||
claimfiles_tail_chain_ptr = &newfile->next;
|
||||
/* Record it as active for receiving symbols to register. */
|
||||
last_claimfile = newfile;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Add a new addfile on the end of the chain. */
|
||||
static enum ld_plugin_status
|
||||
record_add_file (const char *file, addfile_enum_t type)
|
||||
{
|
||||
add_file_t *newfile;
|
||||
|
||||
newfile = malloc (sizeof *newfile);
|
||||
if (!newfile)
|
||||
return LDPS_ERR;
|
||||
newfile->next = NULL;
|
||||
newfile->name = file;
|
||||
newfile->type = type;;
|
||||
/* Chain it on the end of the list. */
|
||||
*addfiles_tail_chain_ptr = newfile;
|
||||
addfiles_tail_chain_ptr = &newfile->next;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Parse a command-line argument string into a symbol definition.
|
||||
Symbol-strings follow the colon-separated format:
|
||||
NAME:VERSION:def:vis:size:COMDATKEY
|
||||
where the fields in capitals are strings and those in lower
|
||||
case are integers. We don't allow to specify a resolution as
|
||||
doing so is not meaningful when calling the add symbols hook. */
|
||||
static enum ld_plugin_status
|
||||
parse_symdefstr (const char *str, struct ld_plugin_symbol *sym)
|
||||
{
|
||||
int n;
|
||||
long long size;
|
||||
const char *colon1, *colon2, *colon5;
|
||||
|
||||
/* Locate the colons separating the first two strings. */
|
||||
colon1 = strchr (str, ':');
|
||||
if (!colon1)
|
||||
return LDPS_ERR;
|
||||
colon2 = strchr (colon1+1, ':');
|
||||
if (!colon2)
|
||||
return LDPS_ERR;
|
||||
/* Name must not be empty (version may be). */
|
||||
if (colon1 == str)
|
||||
return LDPS_ERR;
|
||||
|
||||
/* The fifth colon and trailing comdat key string are optional,
|
||||
but the intermediate ones must all be present. */
|
||||
colon5 = strchr (colon2+1, ':'); /* Actually only third so far. */
|
||||
if (!colon5)
|
||||
return LDPS_ERR;
|
||||
colon5 = strchr (colon5+1, ':'); /* Hopefully fourth now. */
|
||||
if (!colon5)
|
||||
return LDPS_ERR;
|
||||
colon5 = strchr (colon5+1, ':'); /* Optional fifth now. */
|
||||
|
||||
/* Finally we'll use sscanf to parse the numeric fields, then
|
||||
we'll split out the strings which we need to allocate separate
|
||||
storage for anyway so that we can add nul termination. */
|
||||
n = sscanf (colon2 + 1, "%i:%i:%lli", &sym->def, &sym->visibility, &size);
|
||||
if (n != 3)
|
||||
return LDPS_ERR;
|
||||
|
||||
/* Parsed successfully, so allocate strings and fill out fields. */
|
||||
sym->size = size;
|
||||
sym->resolution = LDPR_UNKNOWN;
|
||||
sym->name = malloc (colon1 - str + 1);
|
||||
if (!sym->name)
|
||||
return LDPS_ERR;
|
||||
memcpy (sym->name, str, colon1 - str);
|
||||
sym->name[colon1 - str] = '\0';
|
||||
if (colon2 > (colon1 + 1))
|
||||
{
|
||||
sym->version = malloc (colon2 - colon1);
|
||||
if (!sym->version)
|
||||
return LDPS_ERR;
|
||||
memcpy (sym->version, colon1 + 1, colon2 - (colon1 + 1));
|
||||
sym->version[colon2 - (colon1 + 1)] = '\0';
|
||||
}
|
||||
else
|
||||
sym->version = NULL;
|
||||
if (colon5 && colon5[1])
|
||||
{
|
||||
sym->comdat_key = malloc (strlen (colon5 + 1) + 1);
|
||||
if (!sym->comdat_key)
|
||||
return LDPS_ERR;
|
||||
strcpy (sym->comdat_key, colon5 + 1);
|
||||
}
|
||||
else
|
||||
sym->comdat_key = 0;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Record a symbol to be added for the last-added claimfile. */
|
||||
static enum ld_plugin_status
|
||||
record_claimed_file_symbol (const char *symdefstr)
|
||||
{
|
||||
struct ld_plugin_symbol sym;
|
||||
|
||||
/* Can't add symbols except as belonging to claimed files. */
|
||||
if (!last_claimfile)
|
||||
return LDPS_ERR;
|
||||
|
||||
/* If string doesn't parse correctly, give an error. */
|
||||
if (parse_symdefstr (symdefstr, &sym) != LDPS_OK)
|
||||
return LDPS_ERR;
|
||||
|
||||
/* Check for enough space, resize array if needed, and add it. */
|
||||
if (last_claimfile->n_syms_allocated == last_claimfile->n_syms_used)
|
||||
{
|
||||
int new_n_syms = last_claimfile->n_syms_allocated
|
||||
? 2 * last_claimfile->n_syms_allocated
|
||||
: 10;
|
||||
last_claimfile->symbols = realloc (last_claimfile->symbols,
|
||||
new_n_syms * sizeof *last_claimfile->symbols);
|
||||
if (!last_claimfile->symbols)
|
||||
return LDPS_ERR;
|
||||
last_claimfile->n_syms_allocated = new_n_syms;
|
||||
}
|
||||
last_claimfile->symbols[last_claimfile->n_syms_used++] = sym;
|
||||
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Records the status to return from one of the registered hooks. */
|
||||
static enum ld_plugin_status
|
||||
set_ret_val (const char *whichval, enum ld_plugin_status retval)
|
||||
{
|
||||
if (!strcmp ("onload", whichval))
|
||||
onload_ret = retval;
|
||||
else if (!strcmp ("claimfile", whichval))
|
||||
claim_file_ret = retval;
|
||||
else if (!strcmp ("allsymbolsread", whichval))
|
||||
all_symbols_read_ret = retval;
|
||||
else if (!strcmp ("cleanup", whichval))
|
||||
cleanup_ret = retval;
|
||||
else
|
||||
return LDPS_ERR;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Records hooks which should be registered. */
|
||||
static enum ld_plugin_status
|
||||
set_register_hook (const char *whichhook, bfd_boolean yesno)
|
||||
{
|
||||
if (!strcmp ("claimfile", whichhook))
|
||||
register_claimfile_hook = yesno;
|
||||
else if (!strcmp ("allsymbolsread", whichhook))
|
||||
register_allsymbolsread_hook = yesno;
|
||||
else if (!strcmp ("cleanup", whichhook))
|
||||
register_cleanup_hook = yesno;
|
||||
else
|
||||
return LDPS_ERR;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Determine type of plugin option and pass to individual parsers. */
|
||||
static enum ld_plugin_status
|
||||
parse_option (const char *opt)
|
||||
{
|
||||
if (!strncmp ("fail", opt, 4))
|
||||
return set_ret_val (opt + 4, LDPS_ERR);
|
||||
else if (!strncmp ("pass", opt, 4))
|
||||
return set_ret_val (opt + 4, LDPS_OK);
|
||||
else if (!strncmp ("register", opt, 8))
|
||||
return set_register_hook (opt + 8, TRUE);
|
||||
else if (!strncmp ("noregister", opt, 10))
|
||||
return set_register_hook (opt + 10, FALSE);
|
||||
else if (!strncmp ("claim:", opt, 6))
|
||||
return record_claim_file (opt + 6);
|
||||
else if (!strncmp ("sym:", opt, 4))
|
||||
return record_claimed_file_symbol (opt + 4);
|
||||
else if (!strncmp ("add:", opt, 4))
|
||||
return record_add_file (opt + 4, ADD_FILE);
|
||||
else if (!strncmp ("lib:", opt, 4))
|
||||
return record_add_file (opt + 4, ADD_LIB);
|
||||
else if (!strncmp ("dir:", opt, 4))
|
||||
return record_add_file (opt + 4, ADD_DIR);
|
||||
else if (!strcmp ("dumpresolutions", opt))
|
||||
dumpresolutions = TRUE;
|
||||
else
|
||||
return LDPS_ERR;
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Output contents of transfer vector array entry in human-readable form. */
|
||||
static void
|
||||
dump_tv_tag (size_t n, struct ld_plugin_tv *tv)
|
||||
{
|
||||
size_t tag;
|
||||
char unknownbuf[40];
|
||||
const char *name;
|
||||
|
||||
for (tag = 0; tag < ARRAY_SIZE (tag_names); tag++)
|
||||
if (tag_names[tag].tag == tv->tv_tag)
|
||||
break;
|
||||
sprintf (unknownbuf, "unknown tag #%d", tv->tv_tag);
|
||||
name = (tag < ARRAY_SIZE (tag_names)) ? tag_names[tag].name : unknownbuf;
|
||||
TV_MESSAGE (LDPL_INFO, "tv[%d]: %s ", n, name);
|
||||
switch (tv->tv_tag)
|
||||
{
|
||||
case LDPT_OPTION:
|
||||
case LDPT_OUTPUT_NAME:
|
||||
TV_MESSAGE (LDPL_INFO, "'%s'\n", tv->tv_u.tv_string);
|
||||
break;
|
||||
case LDPT_REGISTER_CLAIM_FILE_HOOK:
|
||||
case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
|
||||
case LDPT_REGISTER_CLEANUP_HOOK:
|
||||
case LDPT_ADD_SYMBOLS:
|
||||
case LDPT_GET_SYMBOLS:
|
||||
case LDPT_ADD_INPUT_FILE:
|
||||
case LDPT_MESSAGE:
|
||||
case LDPT_GET_INPUT_FILE:
|
||||
case LDPT_RELEASE_INPUT_FILE:
|
||||
case LDPT_ADD_INPUT_LIBRARY:
|
||||
case LDPT_SET_EXTRA_LIBRARY_PATH:
|
||||
TV_MESSAGE (LDPL_INFO, "func@0x%p\n",
|
||||
(void *)(tv->tv_u.tv_message));
|
||||
break;
|
||||
case LDPT_NULL:
|
||||
case LDPT_API_VERSION:
|
||||
case LDPT_GOLD_VERSION:
|
||||
case LDPT_LINKER_OUTPUT:
|
||||
case LDPT_GNU_LD_VERSION:
|
||||
default:
|
||||
TV_MESSAGE (LDPL_INFO, "value %W (%d)\n",
|
||||
(bfd_vma)tv->tv_u.tv_val, tv->tv_u.tv_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle/record information received in a transfer vector entry. */
|
||||
static enum ld_plugin_status
|
||||
parse_tv_tag (struct ld_plugin_tv *tv)
|
||||
{
|
||||
#define SETVAR(x) x = tv->tv_u.x
|
||||
switch (tv->tv_tag)
|
||||
{
|
||||
case LDPT_OPTION:
|
||||
return parse_option (tv->tv_u.tv_string);
|
||||
case LDPT_NULL:
|
||||
case LDPT_GOLD_VERSION:
|
||||
case LDPT_GNU_LD_VERSION:
|
||||
case LDPT_API_VERSION:
|
||||
default:
|
||||
break;
|
||||
case LDPT_OUTPUT_NAME:
|
||||
output_name = tv->tv_u.tv_string;
|
||||
break;
|
||||
case LDPT_LINKER_OUTPUT:
|
||||
linker_output = tv->tv_u.tv_val;
|
||||
break;
|
||||
case LDPT_REGISTER_CLAIM_FILE_HOOK:
|
||||
SETVAR(tv_register_claim_file);
|
||||
break;
|
||||
case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
|
||||
SETVAR(tv_register_all_symbols_read);
|
||||
break;
|
||||
case LDPT_REGISTER_CLEANUP_HOOK:
|
||||
SETVAR(tv_register_cleanup);
|
||||
break;
|
||||
case LDPT_ADD_SYMBOLS:
|
||||
SETVAR(tv_add_symbols);
|
||||
break;
|
||||
case LDPT_GET_SYMBOLS:
|
||||
SETVAR(tv_get_symbols);
|
||||
break;
|
||||
case LDPT_ADD_INPUT_FILE:
|
||||
SETVAR(tv_add_input_file);
|
||||
break;
|
||||
case LDPT_MESSAGE:
|
||||
SETVAR(tv_message);
|
||||
break;
|
||||
case LDPT_GET_INPUT_FILE:
|
||||
SETVAR(tv_get_input_file);
|
||||
break;
|
||||
case LDPT_RELEASE_INPUT_FILE:
|
||||
SETVAR(tv_release_input_file);
|
||||
break;
|
||||
case LDPT_ADD_INPUT_LIBRARY:
|
||||
SETVAR(tv_add_input_library);
|
||||
break;
|
||||
case LDPT_SET_EXTRA_LIBRARY_PATH:
|
||||
SETVAR(tv_set_extra_library_path);
|
||||
break;
|
||||
}
|
||||
#undef SETVAR
|
||||
return LDPS_OK;
|
||||
}
|
||||
|
||||
/* Record any useful information in transfer vector entry and display
|
||||
it in human-readable form using the plugin API message() callback. */
|
||||
enum ld_plugin_status
|
||||
parse_and_dump_tv_tag (size_t n, struct ld_plugin_tv *tv)
|
||||
{
|
||||
enum ld_plugin_status rv = parse_tv_tag (tv);
|
||||
dump_tv_tag (n, tv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Standard plugin API entry point. */
|
||||
enum ld_plugin_status
|
||||
onload (struct ld_plugin_tv *tv)
|
||||
{
|
||||
size_t n = 0;
|
||||
enum ld_plugin_status rv;
|
||||
|
||||
/* This plugin does nothing but dump the tv array. It would
|
||||
be an error if this function was called without one. */
|
||||
if (!tv)
|
||||
return LDPS_ERR;
|
||||
|
||||
/* First entry should always be LDPT_MESSAGE, letting us get
|
||||
hold of it easily so we can send output straight away. */
|
||||
if (tv[0].tv_tag == LDPT_MESSAGE)
|
||||
tv_message = tv[0].tv_u.tv_message;
|
||||
|
||||
fflush (NULL);
|
||||
TV_MESSAGE (LDPL_INFO, "Hello from testplugin.\n");
|
||||
|
||||
do
|
||||
if ((rv = parse_and_dump_tv_tag (n++, tv)) != LDPS_OK)
|
||||
return rv;
|
||||
while ((tv++)->tv_tag != LDPT_NULL);
|
||||
|
||||
TV_MESSAGE (LDPL_INFO, "\n");
|
||||
|
||||
/* Register hooks only if instructed by options. */
|
||||
if (register_claimfile_hook)
|
||||
{
|
||||
if (!tv_register_claim_file)
|
||||
{
|
||||
TV_MESSAGE (LDPL_FATAL, "No register_claim_file hook\n");
|
||||
fflush (NULL);
|
||||
return LDPS_ERR;
|
||||
}
|
||||
(*tv_register_claim_file) (onclaim_file);
|
||||
}
|
||||
if (register_allsymbolsread_hook)
|
||||
{
|
||||
if (!tv_register_all_symbols_read)
|
||||
{
|
||||
TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook\n");
|
||||
fflush (NULL);
|
||||
return LDPS_ERR;
|
||||
}
|
||||
(*tv_register_all_symbols_read) (onall_symbols_read);
|
||||
}
|
||||
if (register_cleanup_hook)
|
||||
{
|
||||
if (!tv_register_cleanup)
|
||||
{
|
||||
TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook\n");
|
||||
fflush (NULL);
|
||||
return LDPS_ERR;
|
||||
}
|
||||
(*tv_register_cleanup) (oncleanup);
|
||||
}
|
||||
fflush (NULL);
|
||||
return onload_ret;
|
||||
}
|
||||
|
||||
/* Standard plugin API registerable hook. */
|
||||
static enum ld_plugin_status
|
||||
onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
|
||||
{
|
||||
/* Let's see if we want to claim this file. */
|
||||
claim_file_t *claimfile = claimfiles_list;
|
||||
while (claimfile)
|
||||
{
|
||||
if (!strcmp (file->name, claimfile->file.name))
|
||||
break;
|
||||
claimfile = claimfile->next;
|
||||
}
|
||||
|
||||
/* Inform the user/testsuite. */
|
||||
TV_MESSAGE (LDPL_INFO, "hook called: claim_file %s [@%ld/%ld] %s\n",
|
||||
file->name, (long)file->offset, (long)file->filesize,
|
||||
claimfile ? "CLAIMED" : "not claimed");
|
||||
fflush (NULL);
|
||||
|
||||
/* If we decided to claim it, record that fact, and add any symbols
|
||||
that were defined for it by plugin options. */
|
||||
*claimed = (claimfile != 0);
|
||||
if (claimfile)
|
||||
{
|
||||
claimfile->claimed = TRUE;
|
||||
claimfile->file = *file;
|
||||
if (claimfile->n_syms_used && !tv_add_symbols)
|
||||
return LDPS_ERR;
|
||||
else if (claimfile->n_syms_used)
|
||||
return (*tv_add_symbols) (claimfile->file.handle,
|
||||
claimfile->n_syms_used, claimfile->symbols);
|
||||
}
|
||||
|
||||
return claim_file_ret;
|
||||
}
|
||||
|
||||
/* Standard plugin API registerable hook. */
|
||||
static enum ld_plugin_status
|
||||
onall_symbols_read (void)
|
||||
{
|
||||
static const char *resolutions[] =
|
||||
{
|
||||
"LDPR_UNKNOWN",
|
||||
"LDPR_UNDEF",
|
||||
"LDPR_PREVAILING_DEF",
|
||||
"LDPR_PREVAILING_DEF_IRONLY",
|
||||
"LDPR_PREEMPTED_REG",
|
||||
"LDPR_PREEMPTED_IR",
|
||||
"LDPR_RESOLVED_IR",
|
||||
"LDPR_RESOLVED_EXEC",
|
||||
"LDPR_RESOLVED_DYN",
|
||||
};
|
||||
claim_file_t *claimfile = dumpresolutions ? claimfiles_list : NULL;
|
||||
add_file_t *addfile = addfiles_list;
|
||||
TV_MESSAGE (LDPL_INFO, "hook called: all symbols read.\n");
|
||||
for ( ; claimfile; claimfile = claimfile->next)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
int n;
|
||||
if (claimfile->n_syms_used && !tv_get_symbols)
|
||||
return LDPS_ERR;
|
||||
else if (!claimfile->n_syms_used)
|
||||
continue;
|
||||
rv = tv_get_symbols (claimfile->file.handle, claimfile->n_syms_used,
|
||||
claimfile->symbols);
|
||||
if (rv != LDPS_OK)
|
||||
return rv;
|
||||
for (n = 0; n < claimfile->n_syms_used; n++)
|
||||
TV_MESSAGE (LDPL_INFO, "Sym: '%s%s%s' Resolution: %s\n",
|
||||
claimfile->symbols[n].name,
|
||||
claimfile->symbols[n].version ? "@" : "",
|
||||
claimfile->symbols[n].version ? claimfile->symbols[n].version
|
||||
: "",
|
||||
resolutions[claimfile->symbols[n].resolution]);
|
||||
}
|
||||
for ( ; addfile ; addfile = addfile->next)
|
||||
{
|
||||
enum ld_plugin_status rv;
|
||||
if (addfile->type == ADD_LIB && tv_add_input_library)
|
||||
rv = (*tv_add_input_library) (addfile->name);
|
||||
else if (addfile->type == ADD_FILE && tv_add_input_file)
|
||||
rv = (*tv_add_input_file) (addfile->name);
|
||||
else if (addfile->type == ADD_DIR && tv_set_extra_library_path)
|
||||
rv = (*tv_set_extra_library_path) (addfile->name);
|
||||
else
|
||||
rv = LDPS_ERR;
|
||||
if (rv != LDPS_OK)
|
||||
return rv;
|
||||
}
|
||||
fflush (NULL);
|
||||
return all_symbols_read_ret;
|
||||
}
|
||||
|
||||
/* Standard plugin API registerable hook. */
|
||||
static enum ld_plugin_status
|
||||
oncleanup (void)
|
||||
{
|
||||
TV_MESSAGE (LDPL_INFO, "hook called: cleanup.\n");
|
||||
fflush (NULL);
|
||||
return cleanup_ret;
|
||||
}
|
||||
|
@ -1,3 +1,61 @@
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 6/6).
|
||||
* ld-plugin/plugin-10.d: New dump test control script.
|
||||
* ld-plugin/plugin-11.d: Likewise.
|
||||
* ld-plugin/plugin.exp: Run them.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 5/6).
|
||||
* ld-plugin/plugin-ignore.d: New dump test control script.
|
||||
* ld-plugin/plugin-vis-1.d: Likewise.
|
||||
* ld-plugin/plugin.exp: Add list of ELF-only tests and run them if
|
||||
testing on an ELF target.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 4/6).
|
||||
* ld-plugin/plugin-9.d: New testcase.
|
||||
* ld-plugin/plugin.exp: Invoke it.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 3/6).
|
||||
* ld-plugin/plugin-8.d: New testcase.
|
||||
* ld-plugin/plugin.exp: Invoke it.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 2/6).
|
||||
* ld-plugin/plugin-3.d: Enable regexes for new functionality.
|
||||
* ld-plugin/plugin-5.d: Likewise.
|
||||
* ld-plugin/plugin-6.d: New testcase.
|
||||
* ld-plugin/plugin-7.d: Likewise.
|
||||
* ld-plugin/plugin.exp: Use 'nm' on compiled test objects to determine
|
||||
whether symbols in plugin arguments need an underscore prefix. Add
|
||||
new plugin-6.d and plugin-7.d testcases.
|
||||
|
||||
2010-10-14 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||
|
||||
Apply LD plugin patch series (part 1/6).
|
||||
* ld-bootstrap/bootstrap.exp: Skip static tests also if LD plugins
|
||||
are enabled.
|
||||
* lib/ld-lib.exp (proc regexp_diff): Extend verbose debug output.
|
||||
(proc set_file_contents): Write a file with the supplied content.
|
||||
(run_ld_link_tests): Add new 'ld' action to test linker output.
|
||||
(proc check_plugin_api_available): Return true if linker under test
|
||||
supports the plugin API.
|
||||
* ld-plugin/func.c: New test source file.
|
||||
* ld-plugin/main.c: Likewise.
|
||||
* ld-plugin/text.c: Likewise.
|
||||
* ld-plugin/plugin-1.d: New dump test output pattern script.
|
||||
* ld-plugin/plugin-2.d: Likewise.
|
||||
* ld-plugin/plugin-3.d: Likewise.
|
||||
* ld-plugin/plugin-4.d: Likewise.
|
||||
* ld-plugin/plugin-5.d: Likewise.
|
||||
* ld-plugin/plugin.exp: New test control script.
|
||||
|
||||
2010-10-11 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ld-elf/orphan-region.d: xfail frv-*-*.
|
||||
|
@ -40,6 +40,11 @@ if [info exists plugins] then {
|
||||
set plugins "no"
|
||||
}
|
||||
|
||||
# LD can have plugin support even if BFD does not.
|
||||
if [check_plugin_api_available] {
|
||||
set plugins "yes"
|
||||
}
|
||||
|
||||
# Bootstrap ld. First link the object files together using -r, in
|
||||
# order to test -r. Then link the result into an executable, ld1, to
|
||||
# really test -r. Use ld1 to link a fresh ld, ld2. Use ld2 to link a
|
||||
|
7
ld/testsuite/ld-plugin/func.c
Normal file
7
ld/testsuite/ld-plugin/func.c
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
extern int retval;
|
||||
|
||||
int func (void)
|
||||
{
|
||||
return retval;
|
||||
}
|
13
ld/testsuite/ld-plugin/main.c
Normal file
13
ld/testsuite/ld-plugin/main.c
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
extern int printf (const char *fmt, ...);
|
||||
|
||||
extern const char *text;
|
||||
extern int func (void);
|
||||
|
||||
int retval = 0;
|
||||
|
||||
int main (int argc, const char **argv)
|
||||
{
|
||||
printf ("%s\n", text);
|
||||
return func ();
|
||||
}
|
18
ld/testsuite/ld-plugin/plugin-1.d
Normal file
18
ld/testsuite/ld-plugin/plugin-1.d
Normal file
@ -0,0 +1,18 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
36
ld/testsuite/ld-plugin/plugin-10.d
Normal file
36
ld/testsuite/ld-plugin/plugin-10.d
Normal file
@ -0,0 +1,36 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'registerclaimfile'
|
||||
tv\[16\]: LDPT_OPTION 'registerallsymbolsread'
|
||||
tv\[17\]: LDPT_OPTION 'registercleanup'
|
||||
tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o'
|
||||
tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0'
|
||||
tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0'
|
||||
tv\[21\]: LDPT_OPTION 'dumpresolutions'
|
||||
tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o'
|
||||
tv\[23\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
|
||||
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
|
||||
#...
|
||||
hook called: claim_file tmpdir/libtext.a \[@.* not claimed
|
||||
#...
|
||||
hook called: all symbols read.
|
||||
Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
|
||||
Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
|
||||
hook called: cleanup.
|
||||
#...
|
40
ld/testsuite/ld-plugin/plugin-11.d
Normal file
40
ld/testsuite/ld-plugin/plugin-11.d
Normal file
@ -0,0 +1,40 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'registerclaimfile'
|
||||
tv\[16\]: LDPT_OPTION 'registerallsymbolsread'
|
||||
tv\[17\]: LDPT_OPTION 'registercleanup'
|
||||
tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o'
|
||||
tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0'
|
||||
tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0'
|
||||
tv\[21\]: LDPT_OPTION 'dumpresolutions'
|
||||
tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o'
|
||||
tv\[23\]: LDPT_OPTION 'claim:tmpdir/libtext.a'
|
||||
tv\[24\]: LDPT_OPTION 'sym:_?text::0:0:0'
|
||||
tv\[25\]: LDPT_OPTION 'add:tmpdir/text.o'
|
||||
tv\[26\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
|
||||
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
|
||||
#...
|
||||
hook called: claim_file tmpdir/libtext.a \[@.* CLAIMED
|
||||
#...
|
||||
hook called: all symbols read.
|
||||
Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
|
||||
Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
|
||||
Sym: '_?text' Resolution: LDPR_PREVAILING_DEF
|
||||
hook called: cleanup.
|
||||
#...
|
21
ld/testsuite/ld-plugin/plugin-2.d
Normal file
21
ld/testsuite/ld-plugin/plugin-2.d
Normal file
@ -0,0 +1,21 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'failonload'
|
||||
tv\[16\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
.*ld.*:.*ldtestplug.*: error loading plugin
|
||||
#...
|
22
ld/testsuite/ld-plugin/plugin-3.d
Normal file
22
ld/testsuite/ld-plugin/plugin-3.d
Normal file
@ -0,0 +1,22 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'registerallsymbolsread'
|
||||
tv\[16\]: LDPT_OPTION 'failallsymbolsread'
|
||||
tv\[17\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
.*ld.*:.*ldtestplug.*: plugin reported error after all symbols read
|
||||
#...
|
23
ld/testsuite/ld-plugin/plugin-4.d
Normal file
23
ld/testsuite/ld-plugin/plugin-4.d
Normal file
@ -0,0 +1,23 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'failcleanup'
|
||||
tv\[16\]: LDPT_OPTION 'registercleanup'
|
||||
tv\[17\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
hook called: cleanup.
|
||||
.*ld.*:.*ldtestplug.*: error in plugin cleanup \(ignored\)
|
||||
#...
|
29
ld/testsuite/ld-plugin/plugin-5.d
Normal file
29
ld/testsuite/ld-plugin/plugin-5.d
Normal file
@ -0,0 +1,29 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'registerclaimfile'
|
||||
tv\[16\]: LDPT_OPTION 'registerallsymbolsread'
|
||||
tv\[17\]: LDPT_OPTION 'registercleanup'
|
||||
tv\[18\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
hook called: claim_file tmpdir/main.o \[@0/.*
|
||||
hook called: claim_file tmpdir/func.o \[@0/.*
|
||||
hook called: claim_file tmpdir/text.o \[@0/.*
|
||||
#...
|
||||
hook called: all symbols read.
|
||||
#...
|
||||
hook called: cleanup.
|
||||
#...
|
31
ld/testsuite/ld-plugin/plugin-6.d
Normal file
31
ld/testsuite/ld-plugin/plugin-6.d
Normal file
@ -0,0 +1,31 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'registerclaimfile'
|
||||
tv\[16\]: LDPT_OPTION 'registerallsymbolsread'
|
||||
tv\[17\]: LDPT_OPTION 'registercleanup'
|
||||
tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o'
|
||||
tv\[19\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
|
||||
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
|
||||
hook called: claim_file tmpdir/text.o \[@0/.* not claimed
|
||||
#...
|
||||
hook called: all symbols read.
|
||||
tmpdir/main.o: In function `main':
|
||||
.*ld/testsuite/ld-plugin/main.c:12: undefined reference to `func'
|
||||
hook called: cleanup.
|
||||
#...
|
30
ld/testsuite/ld-plugin/plugin-7.d
Normal file
30
ld/testsuite/ld-plugin/plugin-7.d
Normal file
@ -0,0 +1,30 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'registerclaimfile'
|
||||
tv\[16\]: LDPT_OPTION 'registerallsymbolsread'
|
||||
tv\[17\]: LDPT_OPTION 'registercleanup'
|
||||
tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o'
|
||||
tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0'
|
||||
tv\[20\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
|
||||
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
|
||||
hook called: claim_file tmpdir/text.o \[@0/.* not claimed
|
||||
#...
|
||||
hook called: all symbols read.
|
||||
hook called: cleanup.
|
||||
#...
|
34
ld/testsuite/ld-plugin/plugin-8.d
Normal file
34
ld/testsuite/ld-plugin/plugin-8.d
Normal file
@ -0,0 +1,34 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'registerclaimfile'
|
||||
tv\[16\]: LDPT_OPTION 'registerallsymbolsread'
|
||||
tv\[17\]: LDPT_OPTION 'registercleanup'
|
||||
tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o'
|
||||
tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0'
|
||||
tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0'
|
||||
tv\[21\]: LDPT_OPTION 'dumpresolutions'
|
||||
tv\[22\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
|
||||
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
|
||||
hook called: claim_file tmpdir/text.o \[@0/.* not claimed
|
||||
#...
|
||||
hook called: all symbols read.
|
||||
Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
|
||||
Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
|
||||
hook called: cleanup.
|
||||
#...
|
35
ld/testsuite/ld-plugin/plugin-9.d
Normal file
35
ld/testsuite/ld-plugin/plugin-9.d
Normal file
@ -0,0 +1,35 @@
|
||||
Hello from testplugin.
|
||||
tv\[0\]: LDPT_MESSAGE func@0x.*
|
||||
tv\[1\]: LDPT_API_VERSION value 0x1 \(1\)
|
||||
tv\[2\]: LDPT_GNU_LD_VERSION value 0x.*
|
||||
tv\[3\]: LDPT_LINKER_OUTPUT value 0x1 \(1\)
|
||||
tv\[4\]: LDPT_OUTPUT_NAME 'tmpdir/main.x'
|
||||
tv\[5\]: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
|
||||
tv\[6\]: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
|
||||
tv\[7\]: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
|
||||
tv\[8\]: LDPT_ADD_SYMBOLS func@0x.*
|
||||
tv\[9\]: LDPT_GET_INPUT_FILE func@0x.*
|
||||
tv\[10\]: LDPT_RELEASE_INPUT_FILE func@0x.*
|
||||
tv\[11\]: LDPT_GET_SYMBOLS func@0x.*
|
||||
tv\[12\]: LDPT_ADD_INPUT_FILE func@0x.*
|
||||
tv\[13\]: LDPT_ADD_INPUT_LIBRARY func@0x.*
|
||||
tv\[14\]: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
|
||||
tv\[15\]: LDPT_OPTION 'registerclaimfile'
|
||||
tv\[16\]: LDPT_OPTION 'registerallsymbolsread'
|
||||
tv\[17\]: LDPT_OPTION 'registercleanup'
|
||||
tv\[18\]: LDPT_OPTION 'claim:tmpdir/func.o'
|
||||
tv\[19\]: LDPT_OPTION 'sym:_?func::0:0:0'
|
||||
tv\[20\]: LDPT_OPTION 'sym:_?func2::0:0:0'
|
||||
tv\[21\]: LDPT_OPTION 'dumpresolutions'
|
||||
tv\[22\]: LDPT_OPTION 'add:tmpdir/func.o'
|
||||
tv\[23\]: LDPT_NULL value 0x0 \(0\)
|
||||
#...
|
||||
hook called: claim_file tmpdir/main.o \[@0/.* not claimed
|
||||
hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
|
||||
hook called: claim_file tmpdir/text.o \[@0/.* not claimed
|
||||
#...
|
||||
hook called: all symbols read.
|
||||
Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
|
||||
Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
|
||||
hook called: cleanup.
|
||||
#...
|
1
ld/testsuite/ld-plugin/plugin-ignore.d
Normal file
1
ld/testsuite/ld-plugin/plugin-ignore.d
Normal file
@ -0,0 +1 @@
|
||||
#pass
|
9
ld/testsuite/ld-plugin/plugin-vis-1.d
Normal file
9
ld/testsuite/ld-plugin/plugin-vis-1.d
Normal file
@ -0,0 +1,9 @@
|
||||
#...
|
||||
.*(PROTECTED.*func3|DEFAULT.*func|HIDDEN.*func2|INTERNAL.*func1)
|
||||
#...
|
||||
.*(PROTECTED.*func3|DEFAULT.*func|HIDDEN.*func2|INTERNAL.*func1)
|
||||
#...
|
||||
.*(PROTECTED.*func3|DEFAULT.*func|HIDDEN.*func2|INTERNAL.*func1)
|
||||
#...
|
||||
.*(PROTECTED.*func3|DEFAULT.*func|HIDDEN.*func2|INTERNAL.*func1)
|
||||
#...
|
169
ld/testsuite/ld-plugin/plugin.exp
Normal file
169
ld/testsuite/ld-plugin/plugin.exp
Normal file
@ -0,0 +1,169 @@
|
||||
# Expect script for ld-plugin tests
|
||||
# Copyright 2010
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of the GNU Binutils.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
# These tests require the plugin API to be configured in.
|
||||
if ![check_plugin_api_available] {
|
||||
return
|
||||
}
|
||||
|
||||
pass "plugin API enabled"
|
||||
|
||||
global base_dir
|
||||
|
||||
# Look for the name we can dlopen in the test plugin's libtool control script.
|
||||
set plugin_name [file_contents "$base_dir/libldtestplug.la"]
|
||||
set plugin_name [regsub "'.*" [regsub ".*dlname='" "$plugin_name" ""] ""]
|
||||
verbose "plugin name is '$plugin_name'"
|
||||
|
||||
# Use libtool to find full path to plugin rather than worrying
|
||||
# about run paths or anything like that.
|
||||
catch "exec $base_dir/libtool --config" lt_config
|
||||
verbose "Full lt config: $lt_config" 3
|
||||
# Look for "objdir=.libs"
|
||||
regexp -line "^objdir=.*$" "$lt_config" lt_objdir
|
||||
verbose "lt_objdir line is '$lt_objdir'" 3
|
||||
set lt_objdir [regsub "objdir=" "$lt_objdir" ""]
|
||||
set plugin_path "$base_dir/$lt_objdir/$plugin_name"
|
||||
verbose "Full plugin path $plugin_path" 2
|
||||
|
||||
set testobjfiles "$HOSTING_CRT0 tmpdir/main.o tmpdir/func.o tmpdir/text.o"
|
||||
set testobjfiles_notext "$HOSTING_CRT0 tmpdir/main.o tmpdir/func.o"
|
||||
set libs "$LIBS $HOSTING_LIBS"
|
||||
|
||||
set regclm "-plugin-opt registerclaimfile"
|
||||
set regas "-plugin-opt registerallsymbolsread"
|
||||
set regcln "-plugin-opt registercleanup"
|
||||
|
||||
# In order to define symbols in plugin options in the list of tests below,
|
||||
# we need to know if the platform prepends an underscore to C symbols,
|
||||
# which we find out by compiling the test objects now. If there is any
|
||||
# error compiling, we defer reporting it until after the list of tests has
|
||||
# been initialised, so that we can use the names in the list to report;
|
||||
# otherwise, we scan one of the files with 'nm' and look for a known symbol
|
||||
# in the output to see if it is prefixed or not.
|
||||
set failed_compile 0
|
||||
set _ ""
|
||||
set plugin_nm_output ""
|
||||
if { ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/main.c tmpdir/main.o]
|
||||
|| ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func.c tmpdir/func.o]
|
||||
|| ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/text.c tmpdir/text.o] } {
|
||||
# Defer fail until we have list of tests set.
|
||||
set failed_compile 1
|
||||
} else {
|
||||
# Find out if symbols have prefix on this platform before setting tests.
|
||||
catch "exec $NM tmpdir/func.o" plugin_nm_output
|
||||
if { [regexp "_func" "$plugin_nm_output"] } {
|
||||
set _ "_"
|
||||
}
|
||||
}
|
||||
|
||||
set plugin_tests [list \
|
||||
[list "load plugin" "-plugin $plugin_path \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-1.d}} "main.x" ] \
|
||||
[list "fail plugin onload" "-plugin $plugin_path -plugin-opt failonload \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-2.d}} "main.x" ] \
|
||||
[list "fail plugin allsymbolsread" "-plugin $plugin_path $regas \
|
||||
-plugin-opt failallsymbolsread \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-3.d}} "main.x" ] \
|
||||
[list "fail plugin cleanup" "-plugin $plugin_path -plugin-opt failcleanup \
|
||||
$regcln \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-4.d}} "main.x" ] \
|
||||
[list "plugin all hooks" "-plugin $plugin_path $regclm $regas $regcln \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-5.d}} "main.x" ] \
|
||||
[list "plugin claimfile lost symbol" "-plugin $plugin_path $regclm \
|
||||
$regas $regcln -plugin-opt claim:tmpdir/func.o \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-6.d}} "main.x" ] \
|
||||
[list "plugin claimfile replace symbol" "-plugin $plugin_path $regclm \
|
||||
$regas $regcln -plugin-opt claim:tmpdir/func.o \
|
||||
-plugin-opt sym:${_}func::0:0:0 \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-7.d}} "main.x" ] \
|
||||
[list "plugin claimfile resolve symbol" "-plugin $plugin_path $regclm \
|
||||
$regas $regcln -plugin-opt claim:tmpdir/func.o \
|
||||
-plugin-opt sym:${_}func::0:0:0 \
|
||||
-plugin-opt sym:${_}func2::0:0:0 \
|
||||
-plugin-opt dumpresolutions \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-8.d}} "main.x" ] \
|
||||
[list "plugin claimfile replace file" "-plugin $plugin_path $regclm \
|
||||
$regas $regcln -plugin-opt claim:tmpdir/func.o \
|
||||
-plugin-opt sym:${_}func::0:0:0 \
|
||||
-plugin-opt sym:${_}func2::0:0:0 \
|
||||
-plugin-opt dumpresolutions \
|
||||
-plugin-opt add:tmpdir/func.o \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-9.d}} "main.x" ] \
|
||||
]
|
||||
|
||||
set plugin_lib_tests [list \
|
||||
[list "plugin ignore lib" "-plugin $plugin_path $regclm \
|
||||
$regas $regcln -plugin-opt claim:tmpdir/func.o \
|
||||
-plugin-opt sym:${_}func::0:0:0 \
|
||||
-plugin-opt sym:${_}func2::0:0:0 \
|
||||
-plugin-opt dumpresolutions \
|
||||
-plugin-opt add:tmpdir/func.o \
|
||||
$testobjfiles_notext -Ltmpdir -ltext $libs" "" "" {{ld plugin-10.d}} "main.x" ] \
|
||||
[list "plugin claimfile replace lib" "-plugin $plugin_path $regclm \
|
||||
$regas $regcln -plugin-opt claim:tmpdir/func.o \
|
||||
-plugin-opt sym:${_}func::0:0:0 \
|
||||
-plugin-opt sym:${_}func2::0:0:0 \
|
||||
-plugin-opt dumpresolutions \
|
||||
-plugin-opt add:tmpdir/func.o \
|
||||
-plugin-opt claim:tmpdir/libtext.a \
|
||||
-plugin-opt sym:${_}text::0:0:0 \
|
||||
-plugin-opt add:tmpdir/text.o \
|
||||
$testobjfiles_notext -Ltmpdir -ltext $libs" "" "" {{ld plugin-11.d}} "main.x" ] \
|
||||
]
|
||||
|
||||
set plugin_extra_elf_tests [list \
|
||||
[list "plugin set symbol visibility" "-plugin $plugin_path $regclm \
|
||||
$regas $regcln -plugin-opt claim:tmpdir/func.o \
|
||||
-plugin-opt sym:${_}func::0:0:0 \
|
||||
-plugin-opt sym:${_}func1::0:1:0 \
|
||||
-plugin-opt sym:${_}func2::0:2:0 \
|
||||
-plugin-opt sym:${_}func3::0:3:0 \
|
||||
-plugin-opt dumpresolutions \
|
||||
$testobjfiles $libs" "" "" {{ld plugin-ignore.d} \
|
||||
{readelf -s plugin-vis-1.d}} "main.x" ] \
|
||||
]
|
||||
|
||||
if { $failed_compile != 0 } {
|
||||
foreach testitem $plugin_tests {
|
||||
unresolved [lindex $testitem 0]
|
||||
}
|
||||
if { [is_elf_format] } {
|
||||
foreach testitem $plugin_extra_elf_tests {
|
||||
unresolved [lindex $testitem 0]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
run_ld_link_tests $plugin_tests
|
||||
|
||||
if { [is_elf_format] } {
|
||||
run_ld_link_tests $plugin_extra_elf_tests
|
||||
}
|
||||
|
||||
if ![ar_simple_create $ar "" "tmpdir/libtext.a" "tmpdir/text.o"] {
|
||||
foreach testitem $plugin_lib_tests {
|
||||
unresolved [lindex $testitem 0]
|
||||
}
|
||||
} else {
|
||||
run_ld_link_tests $plugin_lib_tests
|
||||
}
|
3
ld/testsuite/ld-plugin/text.c
Normal file
3
ld/testsuite/ld-plugin/text.c
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
const char *text = "Hello world!\n";
|
||||
|
@ -1151,6 +1151,7 @@ proc regexp_diff { file_1 file_2 } {
|
||||
} else {
|
||||
verbose "regexp \"^$line_b$\"\nline \"$line_a\"" 3
|
||||
if ![regexp "^$line_b$" "$line_a"] {
|
||||
verbose "regexp_diff match failure\n" 3
|
||||
send_log "regexp_diff match failure\n"
|
||||
send_log "regexp \"^$line_b$\"\nline \"$line_a\"\n"
|
||||
set differences 1
|
||||
@ -1185,6 +1186,12 @@ proc file_contents { filename } {
|
||||
return $contents
|
||||
}
|
||||
|
||||
proc set_file_contents { filename contents } {
|
||||
set file [open $filename w]
|
||||
puts $file "$contents"
|
||||
close $file
|
||||
}
|
||||
|
||||
# Create an archive using ar
|
||||
#
|
||||
proc ar_simple_create { ar aropts target objects } {
|
||||
@ -1211,6 +1218,10 @@ proc ar_simple_create { ar aropts target objects } {
|
||||
# objdump: Apply objdump options on result. Compare with regex (last arg).
|
||||
# nm: Apply nm options on result. Compare with regex (last arg).
|
||||
# readelf: Apply readelf options on result. Compare with regex (last arg).
|
||||
# ld: Don't apply anything on result. Compare output during linking with
|
||||
# regex (second arg). Note that this *must* be the first action if it
|
||||
# is to be used at all; in all other cases, any output from the linker
|
||||
# during linking is treated as a sign of an error and FAILs the test.
|
||||
#
|
||||
proc run_ld_link_tests { ldtests } {
|
||||
global ld
|
||||
@ -1225,6 +1236,7 @@ proc run_ld_link_tests { ldtests } {
|
||||
global CC
|
||||
global CFLAGS
|
||||
global runtests
|
||||
global exec_output
|
||||
|
||||
foreach testitem $ldtests {
|
||||
set testname [lindex $testitem 0]
|
||||
@ -1242,6 +1254,8 @@ proc run_ld_link_tests { ldtests } {
|
||||
set objfiles {}
|
||||
set is_unresolved 0
|
||||
set failed 0
|
||||
set maybe_failed 0
|
||||
set ld_output ""
|
||||
|
||||
# verbose -log "Testname is $testname"
|
||||
# verbose -log "ld_options is $ld_options"
|
||||
@ -1284,8 +1298,8 @@ proc run_ld_link_tests { ldtests } {
|
||||
set failed 0
|
||||
}
|
||||
} elseif { ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] } {
|
||||
fail $testname
|
||||
set failed 1
|
||||
set maybe_failed 1
|
||||
set ld_output "$exec_output"
|
||||
} else {
|
||||
set failed 0
|
||||
}
|
||||
@ -1306,6 +1320,8 @@ proc run_ld_link_tests { ldtests } {
|
||||
{ set dump_prog $nm }
|
||||
readelf
|
||||
{ set dump_prog $READELF }
|
||||
ld
|
||||
{ set dump_prog "ld" }
|
||||
default
|
||||
{
|
||||
perror "Unrecognized action $action"
|
||||
@ -1314,7 +1330,21 @@ proc run_ld_link_tests { ldtests } {
|
||||
}
|
||||
}
|
||||
|
||||
if { $dump_prog != "" } {
|
||||
if { $action == "ld" } {
|
||||
set dumpfile [lindex $actionlist 1]
|
||||
verbose "dumpfile is $dumpfile"
|
||||
set_file_contents "tmpdir/ld.messages" "$ld_output"
|
||||
verbose "ld.messages has '[file_contents tmpdir/ld.messages]'"
|
||||
if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$dumpfile"] } then {
|
||||
verbose "output is $ld_output" 2
|
||||
set failed 1
|
||||
break
|
||||
}
|
||||
set maybe_failed 0
|
||||
} elseif { $maybe_failed != 0 } {
|
||||
set failed 1
|
||||
break
|
||||
} elseif { $dump_prog != "" } {
|
||||
set dumpfile [lindex $actionlist 2]
|
||||
set binary $dump_prog
|
||||
|
||||
@ -1720,6 +1750,22 @@ proc check_gc_sections_available { } {
|
||||
return $gc_sections_available_saved
|
||||
}
|
||||
|
||||
# Returns true if the target ld supports the plugin API.
|
||||
proc check_plugin_api_available { } {
|
||||
global plugin_api_available_saved
|
||||
global ld
|
||||
if {![info exists plugin_api_available_saved]} {
|
||||
# Check if the ld used by gcc supports --plugin.
|
||||
set ld_output [remote_exec host $ld "--help"]
|
||||
if { [ string first "-plugin" $ld_output ] >= 0 } {
|
||||
set plugin_api_available_saved 1
|
||||
} else {
|
||||
set plugin_api_available_saved 0
|
||||
}
|
||||
}
|
||||
return $plugin_api_available_saved
|
||||
}
|
||||
|
||||
# Check if the assembler supports CFI statements.
|
||||
|
||||
proc check_as_cfi { } {
|
||||
|
Loading…
Reference in New Issue
Block a user