Add support for creating ELF import libraries

2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>

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.

2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
	    Nick Clifton  <nickc@redhat.com>

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.
	* testsuite/ld-elf/elf.exp (Generate empty import library): New test.
	(Generate import library): Likewise.
	* testsuite/ld-elf/implib.s: Likewise.
	* testsuite/ld-elf/implib.rd: New file.
	* testsuite/ld-elf/empty-implib.out: Likewise
This commit is contained in:
Thomas Preud'homme 2016-07-15 17:49:08 +01:00
parent bc7b765ab7
commit 7635954182
21 changed files with 317 additions and 31 deletions

View File

@ -1,3 +1,17 @@
2016-07-15 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.
2016-07-15 Andrew Burgess <andrew.burgess@embecosm.com>
Nick Clifton <nickc@redhat.com>

View File

@ -1126,6 +1126,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
@ -1951,6 +1956,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

View File

@ -3870,6 +3870,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 contiguously 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. */

View File

@ -11028,6 +11028,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)
{
@ -11830,6 +11931,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)
{

View File

@ -524,11 +524,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
@ -764,6 +767,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,

View File

@ -1,3 +1,8 @@
2016-07-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
* bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
out_implib_bfd fields.
2016-07-14 Claudiu Zissulescu <claziss@synopsys.com>
* elf/arc-reloc.def (ARC_SDA32): Don't use ME transformation.

View File

@ -108,6 +108,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
{
@ -532,6 +535,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;

View File

@ -1,3 +1,38 @@
2016-07-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
Nick Clifton <nickc@redhat.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.
* testsuite/ld-elf/elf.exp (Generate empty import library): New test.
(Generate import library): Likewise.
* testsuite/ld-elf/implib.s: Likewise.
* testsuite/ld-elf/implib.rd: New file.
* testsuite/ld-elf/empty-implib.out: Likewise
2016-07-15 Nick Clifton <nickc@redhat.com>
* testsuite/ld-arc/arc.exp: Always run the sda-relocs test in

View File

@ -1,5 +1,12 @@
-*- text -*-
Changes in 2.28:
* Extended the --out-implib=<file> option, previously restricted to x86 PE
targets, to any ELF based target. This allows the generation of an import
library for an ELF executable, which can then be used by another application
to link against the executable.
Changes in 2.27:
* Add a configure option --enable-relro to decide whether -z relro should

View File

@ -1027,6 +1027,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;

View File

@ -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\
@ -804,9 +800,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;
@ -2070,8 +2063,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. */

View File

@ -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)

View File

@ -163,6 +163,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;

View File

@ -1721,6 +1721,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
@ -2580,16 +2590,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}

View File

@ -1183,6 +1183,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 = ! tree->assign.type.lineno;
h->ldscript_def = 1;
if (tree->type.node_class == etree_provide)
tree->type.node_class = etree_provided;

View File

@ -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,

View File

@ -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);

View File

@ -136,6 +136,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*] } {

View File

@ -0,0 +1,2 @@
.*: .*: no symbol found for import library
.*: .*: failed to generate import library

View File

@ -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
#...

View File

@ -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