From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26891 invoked by alias); 7 Jul 2016 11:01:29 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 26861 invoked by uid 89); 7 Jul 2016 11:01:26 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.2 required=5.0 tests=BAYES_50,KAM_LOTSOFHASH,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 spammy=December, december, GLOBAL, nn X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 07 Jul 2016 11:01:15 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5179328; Thu, 7 Jul 2016 04:02:14 -0700 (PDT) Received: from e105689-lin.cambridge.arm.com (e105689-lin.cambridge.arm.com [10.2.207.32]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DB7E73F213; Thu, 7 Jul 2016 04:01:13 -0700 (PDT) Subject: Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries To: Thomas Preudhomme , binutils@sourceware.org References: <005201d13d58$0d5314a0$27f93de0$@foss.arm.com> <2029781.vlWWHedL94@e108577-lin> Cc: "nickc@redhat.com" From: "Richard Earnshaw (lists)" Message-ID: <577E3678.1060802@arm.com> Date: Thu, 07 Jul 2016 11:01:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <2029781.vlWWHedL94@e108577-lin> Content-Type: text/plain; charset=iso-8859-15 Content-Transfer-Encoding: 8bit X-SW-Source: 2016-07/txt/msg00095.txt.bz2 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 > > * 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 > > * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and > out_implib_bfd fields. > > > *** ld/ChangeLog *** > > 2015-11-02 Thomas Preud'homme > > * 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 > > * 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 < #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 Generate import > library\n")); > fprintf (file, _(" --output-def 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 Generate import > library\n")); > fprintf (file, _(" --output-def 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 >