From e1ad2ef69510f27bb45244872cbfcf5f227b361b Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 29 Mar 2016 20:17:58 +0100 Subject: [PATCH] Add support for creating import libraries 2016-03-29 Thomas Preud'homme bfd/ * 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/ * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and out_implib_bfd fields. ld/ * 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/ * 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 --- bfd/ChangeLog.arm | 14 ++++ bfd/elf-bfd.h | 7 ++ bfd/elf.c | 37 +++++++++ bfd/elflink.c | 108 +++++++++++++++++++++++++++ bfd/elfxx-target.h | 8 +- include/ChangeLog.arm | 4 + include/bfdlink.h | 6 ++ ld/ChangeLog.arm | 29 +++++++ ld/emultempl/elf32.em | 14 ++++ ld/emultempl/pe.em | 14 +--- ld/emultempl/pep.em | 12 +-- ld/ld.h | 3 + ld/ld.texinfo | 20 ++--- ld/ldexp.c | 1 + ld/ldlex.h | 1 + ld/lexsup.c | 5 ++ ld/testsuite/ChangeLog.arm | 8 ++ ld/testsuite/ld-elf/elf.exp | 16 ++++ ld/testsuite/ld-elf/empty-implib.out | 2 + ld/testsuite/ld-elf/implib.rd | 11 +++ ld/testsuite/ld-elf/implib.s | 22 ++++++ 21 files changed, 311 insertions(+), 31 deletions(-) create mode 100644 include/ChangeLog.arm create mode 100644 ld/testsuite/ld-elf/empty-implib.out create mode 100644 ld/testsuite/ld-elf/implib.rd create mode 100644 ld/testsuite/ld-elf/implib.s diff --git a/bfd/ChangeLog.arm b/bfd/ChangeLog.arm index cabe693bf9b..012cad80985 100644 --- a/bfd/ChangeLog.arm +++ b/bfd/ChangeLog.arm @@ -1,3 +1,17 @@ +2016-03-29 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. + 2016-03-29 Thomas Preud'homme * elf32-arm.c (CMSE_PREFIX): Define macro. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 70e33275054..7a7b39554af 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 @@ -1932,6 +1937,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 7f38fa0c62c..064149feb86 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 842e85ba741..17fcbc059d4 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -10837,6 +10837,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) { @@ -11618,6 +11719,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 0acecafcb29..d29d9ff7968 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 @@ -747,6 +750,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/ChangeLog.arm b/include/ChangeLog.arm new file mode 100644 index 00000000000..5783c79d492 --- /dev/null +++ b/include/ChangeLog.arm @@ -0,0 +1,4 @@ +2016-03-29 Thomas Preud'homme + + * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and + out_implib_bfd fields. diff --git a/include/bfdlink.h b/include/bfdlink.h index 93abab1c04e..df0f08c19cc 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/ChangeLog.arm b/ld/ChangeLog.arm index 0adb6ba8835..4632d93d1e1 100644 --- a/ld/ChangeLog.arm +++ b/ld/ChangeLog.arm @@ -1,3 +1,32 @@ +2016-03-29 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. + 2016-03-29 Thomas Preud'homme * ld.texinfo (Placement of SG veneers): New concept entry. diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 809b27c8bf7..5a5de95ab80 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 bddd9a8607d..f6a7c3bc379 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 < 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 5ddeffc9718..bb6b3ac0ed9 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 d84ec4e634e..807cd30e9e3 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 9df74c8a1f4..477bd3bd0b6 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -1702,6 +1702,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 @@ -2561,16 +2571,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 2ec8eb6d198..d80698fb05e 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 6f11e7bd217..61f3f80dc98 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 e2fb21264f0..ce38ef260b9 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/ChangeLog.arm b/ld/testsuite/ChangeLog.arm index 091c47dacca..a5f4e0365ba 100644 --- a/ld/testsuite/ChangeLog.arm +++ b/ld/testsuite/ChangeLog.arm @@ -1,3 +1,11 @@ +2016-03-29 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 + 2016-03-29 Thomas Preud'homme * ld-arm/cmse-veneers.s: New file. diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp index 01d4aab4aa4..c84d9e988a6 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 00000000000..b123064df3f --- /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 00000000000..9f854a59bd2 --- /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 00000000000..a86a940c138 --- /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 -- 2.47.3