This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
- From: "Richard Earnshaw (lists)" <Richard dot Earnshaw at arm dot com>
- To: Thomas Preudhomme <thomas dot preudhomme at foss dot arm dot com>, binutils at sourceware dot org
- Cc: "nickc at redhat dot com" <nickc at redhat dot com>
- Date: Thu, 7 Jul 2016 12:01:12 +0100
- Subject: Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
- Authentication-results: sourceware.org; auth=none
- References: <005201d13d58$0d5314a0$27f93de0$@foss.arm.com> <2029781.vlWWHedL94@e108577-lin>
On 29/03/16 15:44, Thomas Preudhomme wrote:
> On Wednesday 23 December 2015 16:00:53 Thomas Preud'homme wrote:
>> Hi,
>>
>> [Posting patch series as RFC]
>>
>> This patch is part of a patch series to add support for ARMv8-M security
>> extension[1] to GNU ld. This specific patch adds target-independent support
>> for creating generic import library.
>>
>> One common development model for embedded devices is for ROM functions to be
>> bundled in such devices and application developers calling these functions
>> to interact with the device. In such cases, a way is needed for the
>> application to know the addresses of the ROM functions. One convenient
>> mechanism is to create a so called import library that application
>> developers can link against. Such a library can already be created with
>> objcopy --extract-symbol but this means it is done as a separate step than
>> linking.
>>
>> This patch extend the --out-implib switch from i386 PE backend to all ELF
>> backends. This switch specifies a file where an import library should be
>> created. The library is an object file containing no code or data section
>> but just a symbol table with all symbols being absolute. By default, all
>> global symbols in the output file are copied into the import library but
>> target backend can apply different filters as they see fit, for instance
>> when extra switches are supplied by the user.
>>
>>
>> [1] Software requirements for ARMv8-M security extension are described in
>> document ARM-ECM-0359818 [2] [2] Available on http://infocenter.arm.com in
>> Developer guides and articles > Software development > ARM®v8-M Security
>> Extensions: Requirements on Development Tools
>
> Please find an updated patch below.
>
This looks sensible to me (it's mostly just refactoring existing code to
make it available on multiple platforms). But since it touches generic
code it needs Nick's approval.
R.
> *** bfd/ChangeLog ***
>
> 2016-02-17 Thomas Preud'homme <thomas.preudhomme@arm.com>
>
> * elf-bfd.h (elf_backend_filter_implib_symbols): Declare backend hook.
> (_bfd_elf_filter_global_symbols): Declare.
> * elf.c (_bfd_elf_filter_global_symbols): New function.
> * elflink.c (elf_filter_global_symbols): Likewise.
> (elf_output_implib): Likewise.
> (bfd_elf_final_link): Call above function, failing if it does.
> * elfxx-target.h (elf_backend_filter_implib_symbols): Define macro and
> default it to NULL.
> (elf_backend_copy_indirect_symbol): Fix spacing.
> (elf_backend_hide_symbol): Likewise.
> (elfNN_bed): Initialize elf_backend_filter_implib_symbols backend hook.
>
>
> *** include/ChangeLog ***
>
> 2015-10-30 Thomas Preud'homme <thomas.preudhomme@arm.com>
>
> * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
> out_implib_bfd fields.
>
>
> *** ld/ChangeLog ***
>
> 2015-11-02 Thomas Preud'homme <thomas.preudhomme@arm.com>
>
> * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Open import
> library file for writing and initialize implib_bfd field of link_info
> structure.
> * emultempl/pe.em (pe_implib_filename): Remove variable declaration.
> (OPTION_IMPLIB_FILENAME): Remove macro definition.
> (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
> (gld_${EMULATION_NAME}_list_options): Likewise.
> (gld${EMULATION_NAME}_handle_option): Likewise.
> (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
> instead of pe_implib_filename.
> * emultempl/pep.em (pep_implib_filename): Remove variable declaration.
> (OPTION_IMPLIB_FILENAME): Remove enumerator.
> (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
> (gld_${EMULATION_NAME}_list_options): Likewise.
> (gld${EMULATION_NAME}_handle_option): Likewise.
> (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
> instead of pep_implib_filename.
> * ld.h (args_type): Declare new out_implib_filename field.
> * ld.texinfo (--out-implib): Move documentation to arch-independent
> part and rephrase to apply to ELF targets.
> * ldexp.c (exp_fold_tree_1): Set ldscript_def field to 1 for symbols
> defined in linker scripts.
> * ldlex.h (enum option_values): Declare new OPTION_OUT_IMPLIB
> enumerator.
> * lexsup.c (ld_options): Add entry for new --out-implib switch.
> (parse_args): Handle OPTION_OUT_IMPLIB case.
>
>
> *** ld/testsuite/ChangeLog ***
>
> 2015-10-30 Thomas Preud'homme <thomas.preudhomme@arm.com>
>
> * ld-elf/elf.exp (Generate empty import library): New test.
> (Generate import library): Likewise.
> * ld-elf/implib.s: Likewise.
> * ld-elf/implib.rd: New file.
> * ld-elf/empty-implib.out: Likewise
>
>
> diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
> index
> 6a04f044e78bcbf5975ca88987feb878865cbea5..dc25569cac448e336d90dcbe6813d5a26e188095
> 100644
> --- a/bfd/elf-bfd.h
> +++ b/bfd/elf-bfd.h
> @@ -1125,6 +1125,11 @@ struct elf_backend_data
> bfd_boolean (*) (void *, const char *, Elf_Internal_Sym *, asection *,
> struct elf_link_hash_entry *));
>
> + /* Filter what symbols of the output file to include in the import
> + library if one is created. */
> + unsigned int (*elf_backend_filter_implib_symbols)
> + (bfd *, struct bfd_link_info *, asymbol **, long);
> +
> /* Copy any information related to dynamic linking from a pre-existing
> symbol to a newly created symbol. Also called to copy flags and
> other back-end info to a weakdef, in which case the symbol is not
> @@ -1937,6 +1942,8 @@ extern bfd_boolean _bfd_elf_section_already_linked
> (bfd *, asection *, struct bfd_link_info *);
> extern void bfd_elf_set_group_contents
> (bfd *, asection *, void *);
> +extern unsigned int _bfd_elf_filter_global_symbols
> + (bfd *, struct bfd_link_info *, asymbol **, long);
> extern asection *_bfd_elf_check_kept_section
> (asection *, struct bfd_link_info *);
> #define _bfd_elf_link_just_syms _bfd_generic_link_just_syms
> diff --git a/bfd/elf.c b/bfd/elf.c
> index
> 74c2f2d33a46057fb1551a5f50190cf001ff1779..e82a2ca1174786c3c394662f7bda5e4787172c1b
> 100644
> --- a/bfd/elf.c
> +++ b/bfd/elf.c
> @@ -3676,6 +3676,43 @@ sym_is_global (bfd *abfd, asymbol *sym)
> || bfd_is_com_section (bfd_get_section (sym)));
> }
>
> +/* Filter global symbols of ABFD to include in the import library. All
> + SYMCOUNT symbols of ABFD can be examined from their pointers in
> + SYMS. Pointers of symbols to keep should be stored continuously at
> + the beginning of that array.
> +
> + Returns the number of symbols to keep. */
> +
> +unsigned int
> +_bfd_elf_filter_global_symbols (bfd *abfd, struct bfd_link_info *info,
> + asymbol **syms, long symcount)
> +{
> + long src_count, dst_count = 0;
> +
> + for (src_count = 0; src_count < symcount; src_count++)
> + {
> + asymbol *sym = syms[src_count];
> + char *name = (char *) bfd_asymbol_name (sym);
> + struct bfd_link_hash_entry *h;
> +
> + if (!sym_is_global (abfd, sym))
> + continue;
> +
> + h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE);
> + if (h->type != bfd_link_hash_defined && h->type !=
> bfd_link_hash_defweak)
> + continue;
> +
> + if (h->linker_def || h->ldscript_def)
> + continue;
> +
> + syms[dst_count++] = sym;
> + }
> +
> + syms[dst_count] = NULL;
> +
> + return dst_count;
> +}
> +
> /* Don't output section symbols for sections that are not going to be
> output, that are duplicates or there is no BFD section. */
>
> diff --git a/bfd/elflink.c b/bfd/elflink.c
> index
> ac03ce5003adea4a8fef6481e638c02a7d85d177..7c8809f02e6abeaac288fc17ddd17ce4ff5b1bc2
> 100644
> --- a/bfd/elflink.c
> +++ b/bfd/elflink.c
> @@ -10831,6 +10831,107 @@ elf_fixup_link_order (bfd *abfd, asection *o)
> return TRUE;
> }
>
> +/* Generate an import library in INFO->implib_bfd from symbols in ABFD.
> + Returns TRUE upon success, FALSE otherwise. */
> +
> +static bfd_boolean
> +elf_output_implib (bfd *abfd, struct bfd_link_info *info)
> +{
> + bfd_boolean ret = FALSE;
> + bfd *implib_bfd;
> + const struct elf_backend_data *bed;
> + flagword flags;
> + enum bfd_architecture arch;
> + unsigned int mach;
> + asymbol **sympp = NULL;
> + long symsize;
> + long symcount;
> + long src_count;
> + elf_symbol_type *osymbuf;
> +
> + implib_bfd = info->out_implib_bfd;
> + bed = get_elf_backend_data (abfd);
> +
> + if (!bfd_set_format (implib_bfd, bfd_object))
> + return FALSE;
> +
> + flags = bfd_get_file_flags (abfd);
> + flags &= ~HAS_RELOC;
> + if (!bfd_set_start_address (implib_bfd, 0)
> + || !bfd_set_file_flags (implib_bfd, flags))
> + return FALSE;
> +
> + /* Copy architecture of output file to import library file. */
> + arch = bfd_get_arch (abfd);
> + mach = bfd_get_mach (abfd);
> + if (!bfd_set_arch_mach (implib_bfd, arch, mach)
> + && (abfd->target_defaulted
> + || bfd_get_arch (abfd) != bfd_get_arch (implib_bfd)))
> + return FALSE;
> +
> + /* Get symbol table size. */
> + symsize = bfd_get_symtab_upper_bound (abfd);
> + if (symsize < 0)
> + return FALSE;
> +
> + /* Read in the symbol table. */
> + sympp = (asymbol **) xmalloc (symsize);
> + symcount = bfd_canonicalize_symtab (abfd, sympp);
> + if (symcount < 0)
> + goto free_sym_buf;
> +
> + /* Allow the BFD backend to copy any private header data it
> + understands from the output BFD to the import library BFD. */
> + if (! bfd_copy_private_header_data (abfd, implib_bfd))
> + goto free_sym_buf;
> +
> + /* Filter symbols to appear in the import library. */
> + if (bed->elf_backend_filter_implib_symbols)
> + symcount = bed->elf_backend_filter_implib_symbols (abfd, info, sympp,
> + symcount);
> + else
> + symcount = _bfd_elf_filter_global_symbols (abfd, info, sympp, symcount);
> + if (symcount == 0)
> + {
> + (*_bfd_error_handler) (_("%B: no symbol found for import library"),
> + implib_bfd);
> + goto free_sym_buf;
> + }
> +
> +
> + /* Make symbols absolute. */
> + osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount,
> + sizeof (*osymbuf));
> + for (src_count = 0; src_count < symcount; src_count++)
> + {
> + memcpy (&osymbuf[src_count], (elf_symbol_type *) sympp[src_count],
> + sizeof (*osymbuf));
> + osymbuf[src_count].symbol.section = bfd_abs_section_ptr;
> + osymbuf[src_count].internal_elf_sym.st_shndx = SHN_ABS;
> + osymbuf[src_count].symbol.value += sympp[src_count]->section->vma;
> + osymbuf[src_count].internal_elf_sym.st_value =
> + osymbuf[src_count].symbol.value;
> + sympp[src_count] = &osymbuf[src_count].symbol;
> + }
> +
> + bfd_set_symtab (implib_bfd, sympp, symcount);
> +
> + /* Allow the BFD backend to copy any private data it understands
> + from the output BFD to the import library BFD. This is done last
> + to permit the routine to look at the filtered symbol table. */
> + if (! bfd_copy_private_bfd_data (abfd, implib_bfd))
> + goto free_sym_buf;
> +
> + if (!bfd_close (implib_bfd))
> + goto free_sym_buf;
> +
> + ret = TRUE;
> +
> +free_sym_buf:
> + free (sympp);
> + return ret;
> +}
> +
> static void
> elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
> {
> @@ -11633,6 +11734,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info
> *info)
> return FALSE;
> }
>
> + if (info->out_implib_bfd && !elf_output_implib (abfd, info))
> + {
> + (*_bfd_error_handler) (_("%B: failed to generate import library"),
> + info->out_implib_bfd);
> + return FALSE;
> + }
> +
> /* Adjust the relocs to have the correct symbol indices. */
> for (o = abfd->sections; o != NULL; o = o->next)
> {
> diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
> index
> b3227ed3c521ad4e7dacbd0f0d433f4b45e4ba5f..f996885cb56ab24860ca18a4aafe1d33f3915649
> 100644
> --- a/bfd/elfxx-target.h
> +++ b/bfd/elfxx-target.h
> @@ -514,11 +514,14 @@
> #ifndef elf_backend_output_arch_syms
> #define elf_backend_output_arch_syms NULL
> #endif
> +#ifndef elf_backend_filter_implib_symbols
> +#define elf_backend_filter_implib_symbols NULL
> +#endif
> #ifndef elf_backend_copy_indirect_symbol
> -#define elf_backend_copy_indirect_symbol _bfd_elf_link_hash_copy_indirect
> +#define elf_backend_copy_indirect_symbol _bfd_elf_link_hash_copy_indirect
> #endif
> #ifndef elf_backend_hide_symbol
> -#define elf_backend_hide_symbol _bfd_elf_link_hash_hide_symbol
> +#define elf_backend_hide_symbol _bfd_elf_link_hash_hide_symbol
> #endif
> #ifndef elf_backend_fixup_symbol
> #define elf_backend_fixup_symbol NULL
> @@ -750,6 +753,7 @@ static struct elf_backend_data elfNN_bed =
> elf_backend_print_symbol_all,
> elf_backend_output_arch_local_syms,
> elf_backend_output_arch_syms,
> + elf_backend_filter_implib_symbols,
> elf_backend_copy_indirect_symbol,
> elf_backend_hide_symbol,
> elf_backend_fixup_symbol,
> diff --git a/include/bfdlink.h b/include/bfdlink.h
> index
> 9b849aa761e1e59d5f31f2ec6f2769f28421d251..5d772d0b8b41bdad06b9f02ff4a030c06fe75345
> 100644
> --- a/include/bfdlink.h
> +++ b/include/bfdlink.h
> @@ -99,6 +99,9 @@ struct bfd_link_hash_entry
> in a linker script. */
> unsigned int linker_def : 1;
>
> + /* Symbol defined in a linker script. */
> + unsigned int ldscript_def : 1;
> +
> /* A union of information depending upon the type. */
> union
> {
> @@ -499,6 +502,9 @@ struct bfd_link_info
> /* The output BFD. */
> bfd *output_bfd;
>
> + /* The import library generated. */
> + bfd *out_implib_bfd;
> +
> /* The list of input BFD's involved in the link. These are chained
> together via the link.next field. */
> bfd *input_bfds;
> diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
> index
> d9d3393ec04e48d690ddf528e86636e778bdccf3..d04a365563d3eb730f5404e906862bbcfd9f6bca
> 100644
> --- a/ld/emultempl/elf32.em
> +++ b/ld/emultempl/elf32.em
> @@ -1025,6 +1025,20 @@ gld${EMULATION_NAME}_after_open (void)
> if (!is_elf_hash_table (htab))
> return;
>
> + if (command_line.out_implib_filename)
> + {
> + unlink_if_ordinary (command_line.out_implib_filename);
> + link_info.out_implib_bfd
> + = bfd_openw (command_line.out_implib_filename,
> + bfd_get_target (link_info.output_bfd));
> +
> + if (link_info.out_implib_bfd == NULL)
> + {
> + einfo ("%F%s: Can't open for writing: %E\n",
> + command_line.out_implib_filename);
> + }
> + }
> +
> if (emit_note_gnu_build_id != NULL)
> {
> bfd *abfd;
> diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
> index
> f15c6c415c2c2b41b3c4f9753c4a2fafd2f59767..40980b490a89f69f42605f83798cf2c815437d30
> 100644
> --- a/ld/emultempl/pe.em
> +++ b/ld/emultempl/pe.em
> @@ -138,7 +138,6 @@ static const char *emit_build_id;
> #ifdef DLL_SUPPORT
> static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */
> static char *pe_out_def_filename = NULL;
> -static char *pe_implib_filename = NULL;
> static int pe_enable_auto_image_base = 0;
> static unsigned long pe_auto_image_base = 0x61500000;
> static char *pe_dll_search_prefix = NULL;
> @@ -228,8 +227,7 @@ fragment <<EOF
> #define OPTION_STDCALL_ALIASES (OPTION_KILL_ATS + 1)
> #define OPTION_ENABLE_STDCALL_FIXUP (OPTION_STDCALL_ALIASES + 1)
> #define OPTION_DISABLE_STDCALL_FIXUP (OPTION_ENABLE_STDCALL_FIXUP + 1)
> -#define OPTION_IMPLIB_FILENAME (OPTION_DISABLE_STDCALL_FIXUP + 1)
> -#define OPTION_THUMB_ENTRY (OPTION_IMPLIB_FILENAME + 1)
> +#define OPTION_THUMB_ENTRY (OPTION_DISABLE_STDCALL_FIXUP + 1)
> #define OPTION_WARN_DUPLICATE_EXPORTS (OPTION_THUMB_ENTRY + 1)
> #define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1)
> #define OPTION_ENABLE_AUTO_IMAGE_BASE (OPTION_IMP_COMPAT + 1)
> @@ -323,7 +321,6 @@ gld${EMULATION_NAME}_add_options
> {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
> {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
> {"disable-stdcall-fixup", no_argument, NULL,
> OPTION_DISABLE_STDCALL_FIXUP},
> - {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
> {"warn-duplicate-exports", no_argument, NULL,
> OPTION_WARN_DUPLICATE_EXPORTS},
> /* getopt() allows abbreviations, so we do this to stop it from
> treating -c as an abbreviation for these --compat-implib. */
> @@ -461,7 +458,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
> fprintf (file, _(" export, place into
> import library instead.\n"));
> fprintf (file, _(" --export-all-symbols Automatically export
> all globals to DLL\n"));
> fprintf (file, _(" --kill-at Remove @nn from
> exported symbols\n"));
> - fprintf (file, _(" --out-implib <file> Generate import
> library\n"));
> fprintf (file, _(" --output-def <file> Generate a .DEF file
> for the built DLL\n"));
> fprintf (file, _(" --warn-duplicate-exports Warn about duplicate
> exports\n"));
> fprintf (file, _(" --compat-implib Create backward
> compatible import libs;\n\
> @@ -805,9 +801,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
> case OPTION_DISABLE_STDCALL_FIXUP:
> pe_enable_stdcall_fixup = 0;
> break;
> - case OPTION_IMPLIB_FILENAME:
> - pe_implib_filename = xstrdup (optarg);
> - break;
> case OPTION_WARN_DUPLICATE_EXPORTS:
> pe_dll_warn_dup_exports = 1;
> break;
> @@ -2073,8 +2066,9 @@ gld_${EMULATION_NAME}_finish (void)
> )
> {
> pe_dll_fill_sections (link_info.output_bfd, &link_info);
> - if (pe_implib_filename)
> - pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info);
> + if (command_line.out_implib_filename)
> + pe_dll_generate_implib (pe_def_file, command_line.out_implib_filename,
> + &link_info);
> }
> #if defined(TARGET_IS_shpe)
> /* ARM doesn't need relocs. */
> diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
> index
> 054a98497f3c386adecd361612d4d1bbdc779049..def1a4f21737d87ca94c1c4616cc691ec5efffd0
> 100644
> --- a/ld/emultempl/pep.em
> +++ b/ld/emultempl/pep.em
> @@ -153,7 +153,6 @@ static const char *emit_build_id;
> #ifdef DLL_SUPPORT
> static int pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default).
> */
> static char * pep_out_def_filename = NULL;
> -static char * pep_implib_filename = NULL;
> static int pep_enable_auto_image_base = 0;
> static char * pep_dll_search_prefix = NULL;
> #endif
> @@ -217,7 +216,6 @@ enum options
> OPTION_STDCALL_ALIASES,
> OPTION_ENABLE_STDCALL_FIXUP,
> OPTION_DISABLE_STDCALL_FIXUP,
> - OPTION_IMPLIB_FILENAME,
> OPTION_WARN_DUPLICATE_EXPORTS,
> OPTION_IMP_COMPAT,
> OPTION_ENABLE_AUTO_IMAGE_BASE,
> @@ -296,7 +294,6 @@ gld${EMULATION_NAME}_add_options
> {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
> {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
> {"disable-stdcall-fixup", no_argument, NULL,
> OPTION_DISABLE_STDCALL_FIXUP},
> - {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
> {"warn-duplicate-exports", no_argument, NULL,
> OPTION_WARN_DUPLICATE_EXPORTS},
> /* getopt() allows abbreviations, so we do this to stop it from
> treating -c as an abbreviation for these --compat-implib. */
> @@ -427,7 +424,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
> fprintf (file, _(" export, place into
> import library instead.\n"));
> fprintf (file, _(" --export-all-symbols Automatically export
> all globals to DLL\n"));
> fprintf (file, _(" --kill-at Remove @nn from
> exported symbols\n"));
> - fprintf (file, _(" --out-implib <file> Generate import
> library\n"));
> fprintf (file, _(" --output-def <file> Generate a .DEF file
> for the built DLL\n"));
> fprintf (file, _(" --warn-duplicate-exports Warn about duplicate
> exports.\n"));
> fprintf (file, _(" --compat-implib Create backward
> compatible import libs;\n\
> @@ -761,9 +757,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
> case OPTION_DISABLE_STDCALL_FIXUP:
> pep_enable_stdcall_fixup = 0;
> break;
> - case OPTION_IMPLIB_FILENAME:
> - pep_implib_filename = xstrdup (optarg);
> - break;
> case OPTION_WARN_DUPLICATE_EXPORTS:
> pep_dll_warn_dup_exports = 1;
> break;
> @@ -1851,8 +1844,9 @@ gld_${EMULATION_NAME}_finish (void)
> && pep_def_file->num_exports != 0))
> {
> pep_dll_fill_sections (link_info.output_bfd, &link_info);
> - if (pep_implib_filename)
> - pep_dll_generate_implib (pep_def_file, pep_implib_filename, &link_info);
> + if (command_line.out_implib_filename)
> + pep_dll_generate_implib (pep_def_file,
> + command_line.out_implib_filename, &link_info);
> }
>
> if (pep_out_def_filename)
> diff --git a/ld/ld.h b/ld/ld.h
> index
> ab09032e455f8b64b1d8fd7cbb860d78cfd45e58..e41460fec76e3725fca0a5399e84389266100f32
> 100644
> --- a/ld/ld.h
> +++ b/ld/ld.h
> @@ -158,6 +158,9 @@ typedef struct {
> input files. */
> bfd_boolean accept_unknown_input_arch;
>
> + /* Name of the import library to generate. */
> + char *out_implib_filename;
> +
> /* If TRUE we'll just print the default output on stdout. */
> bfd_boolean print_output_format;
>
> diff --git a/ld/ld.texinfo b/ld/ld.texinfo
> index
> 8507c3fe677921c0c8fbd5fcb5b5a5799d8cfae0..a9a2e347a1e6960406916b36506746dadc557b96
> 100644
> --- a/ld/ld.texinfo
> +++ b/ld/ld.texinfo
> @@ -1696,6 +1696,16 @@ command @code{OUTPUT_FORMAT} can also specify the
> output format, but
> this option overrides it. @xref{BFD}.
> @end ifclear
>
> +@kindex --out-implib
> +@item --out-implib @var{file}
> +Create an import library in @var{file} corresponding to the executable
> +the linker is generating (eg. a DLL or ELF program). This import
> +library (which should be called @code{*.dll.a} or @code{*.a} for DLLs)
> +may be used to link clients against the generated executable; this
> +behaviour makes it possible to skip a separate import library creation
> +step (eg. @code{dlltool} for DLLs). This option is only available for
> +the i386 PE and ELF targetted ports of the linker.
> +
> @kindex -pie
> @kindex --pic-executable
> @item -pie
> @@ -2555,16 +2565,6 @@ automatically or implicitly exported symbols.
> [This option is specific to the i386 PE targeted port of the linker]
>
> @cindex DLLs, creating
> -@kindex --out-implib
> -@item --out-implib @var{file}
> -The linker will create the file @var{file} which will contain an
> -import lib corresponding to the DLL the linker is generating. This
> -import lib (which should be called @code{*.dll.a} or @code{*.a}
> -may be used to link clients against the generated DLL; this behaviour
> -makes it possible to skip a separate @code{dlltool} import library
> -creation step.
> -[This option is specific to the i386 PE targeted port of the linker]
> -
> @kindex --enable-auto-image-base
> @item --enable-auto-image-base
> @itemx --enable-auto-image-base=@var{value}
> diff --git a/ld/ldexp.c b/ld/ldexp.c
> index
> 22dd0d2f1d99beac27690f82c2db423d6db25c81..e8c5dcbd66e84bdc2d11b4c564dd4dc7aee6ca14
> 100644
> --- a/ld/ldexp.c
> +++ b/ld/ldexp.c
> @@ -1182,6 +1182,7 @@ exp_fold_tree_1 (etree_type *tree)
> h->u.def.value = expld.result.value;
> h->u.def.section = expld.result.section;
> h->linker_def = 0;
> + h->ldscript_def = 1;
> if (tree->type.node_class == etree_provide)
> tree->type.node_class = etree_provided;
>
> diff --git a/ld/ldlex.h b/ld/ldlex.h
> index
> cf943e425f9db0cca713334037a1fdc1186753e1..52f7198ad2ccec4a96474f2d865392657d6333da
> 100644
> --- a/ld/ldlex.h
> +++ b/ld/ldlex.h
> @@ -35,6 +35,7 @@ enum option_values
> OPTION_DYNAMIC_LINKER,
> OPTION_NO_DYNAMIC_LINKER,
> OPTION_SYSROOT,
> + OPTION_OUT_IMPLIB,
> OPTION_EB,
> OPTION_EL,
> OPTION_EMBEDDED_RELOCS,
> diff --git a/ld/lexsup.c b/ld/lexsup.c
> index
> 87341f93dcc41a5529f4258cf8d2ea0eff327c58..aede732f2b60f7af66a3ad505fb157603db20755
> 100644
> --- a/ld/lexsup.c
> +++ b/ld/lexsup.c
> @@ -164,6 +164,8 @@ 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 },
> + { {"out-implib", required_argument, NULL, OPTION_OUT_IMPLIB},
> + '\0', N_("FILE"), N_("Generate import library"), TWO_DASHES },
> #ifdef ENABLE_PLUGINS
> { {"plugin", required_argument, NULL, OPTION_PLUGIN},
> '\0', N_("PLUGIN"), N_("Load named plugin"), ONE_DASH },
> @@ -1004,6 +1006,9 @@ parse_args (unsigned argc, char **argv)
> case OPTION_OFORMAT:
> lang_add_output_format (optarg, NULL, NULL, 0);
> break;
> + case OPTION_OUT_IMPLIB:
> + command_line.out_implib_filename = xstrdup (optarg);
> + break;
> case OPTION_PRINT_SYSROOT:
> if (*ld_sysroot)
> puts (ld_sysroot);
> diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
> index
> af0b09187a4c37cf11bda76310c97301d69a4e2d..297b10cce0c5ad62e2a8e8ebff0c610e91d83cf1
> 100644
> --- a/ld/testsuite/ld-elf/elf.exp
> +++ b/ld/testsuite/ld-elf/elf.exp
> @@ -126,6 +126,22 @@ foreach t $test_list {
> run_dump_test [file rootname $t]
> }
>
> +# Check that the --out-implib option work correctly.
> +run_ld_link_tests {
> + {"Generate empty import library"
> + "--out-implib=tmpdir/implib.lib" ""
> + "--defsym NO_GLOBAL=1"
> + {implib.s}
> + {{ld empty-implib.out}}
> + "implib"}
> + {"Generate import library"
> + "-Tdata=0x1000 --out-implib=tmpdir/implib.lib" ""
> + ""
> + {implib.s}
> + {{readelf {-s tmpdir/implib.lib} implib.rd}}
> + "implib"}
> +}
> +
> if { [istarget *-*-linux*]
> || [istarget *-*-nacl*]
> || [istarget *-*-gnu*] } {
> diff --git a/ld/testsuite/ld-elf/empty-implib.out b/ld/testsuite/ld-elf/empty-
> implib.out
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..b123064df3f6f429c59fe204d57e57ed76a8d5be
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/empty-implib.out
> @@ -0,0 +1,2 @@
> +.*: .*: no symbol found for import library
> +.*: .*: failed to generate import library
> diff --git a/ld/testsuite/ld-elf/implib.rd b/ld/testsuite/ld-elf/implib.rd
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..9f854a59bd26054a8fdb49f6dbaac4120b2c7ef1
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/implib.rd
> @@ -0,0 +1,11 @@
> +File: tmpdir/implib.lib
> +
> +Symbol table '.symtab' contains 3 entries:
> + Num: Value +Size Type Bind Vis Ndx Name
> + 0: [0-9a-f]+ 0 NOTYPE LOCAL DEFAULT UND
> + 1: 0+100[0-3] 1 OBJECT GLOBAL DEFAULT ABS exported1
> + 2: 0+100[0-3] 1 OBJECT GLOBAL DEFAULT ABS exported2
> +
> +File: tmpdir/implib
> +
> +#...
> diff --git a/ld/testsuite/ld-elf/implib.s b/ld/testsuite/ld-elf/implib.s
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..a86a940c138d7dd65e42c609adbe594c579061ac
> --- /dev/null
> +++ b/ld/testsuite/ld-elf/implib.s
> @@ -0,0 +1,22 @@
> +.ifndef NO_GLOBAL
> + .bss
> + .comm exported1,1
> +
> + .data
> + .global exported2
> + .type exported2, %object
> + .size exported2, 1
> +exported2:
> + .byte 21
> +.endif
> +
> + .bss
> +not_exported1:
> + .space 1
> + .size not_exported1, 1
> +
> + .data
> + .type not_exported2, %object
> + .size not_exported2, 1
> +not_exported2:
> + .byte 42
>
>
> Is this ok for master branch?
>
> best regards,
>
> Thomas
>