Add support for creating ELF import libraries
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Fri, 15 Jul 2016 16:49:08 +0000 (17:49 +0100)
committerThomas Preud'homme <thomas.preudhomme@arm.com>
Fri, 15 Jul 2016 16:50:48 +0000 (17:50 +0100)
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

21 files changed:
bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf.c
bfd/elflink.c
bfd/elfxx-target.h
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/NEWS
ld/emultempl/elf32.em
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/ld.h
ld/ld.texinfo
ld/ldexp.c
ld/ldlex.h
ld/lexsup.c
ld/testsuite/ld-elf/elf.exp
ld/testsuite/ld-elf/empty-implib.out [new file with mode: 0644]
ld/testsuite/ld-elf/implib.rd [new file with mode: 0644]
ld/testsuite/ld-elf/implib.s [new file with mode: 0644]

index b553e1cb5a29a5c16b2906bae6d7155af61ee1a6..ec8fd851ff862cb7ff1b6d5cbe5f0d73df93a1dc 100644 (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>
 
index 163ef35fadcc41987dd234c56d818be606a10cfe..bb3371fec88c67f359ff145aa7ff8182ef0429b4 100644 (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
index cb4de50ac9ae6723488cbdfbc4343b33d7c96727..ebcf40a92578b588c19312b1e4e521fff8ddad14 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -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.  */
 
index 3e249400f67f75f492c1a7f72b811965aa39995c..b2a814fda4297d9d2019b0b6de648815f652b606 100644 (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)
     {
index 97aa5e690bf6c8ab400796b4a01cedebd0a8b03d..364bddf7419ba85da2935ebed32ee33e74d17986 100644 (file)
 #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,
index 23b8a07338f592764186f399f501a910c525198c..f000f725e289687ef9b61eb64c7b0a503796befa 100644 (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.
index b392d54b3557690161beb5a13505668557041756..9b2194f6d5ca930f661e338062cc64877fdfc66a 100644 (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;
index ea4494859b725261187ee70404a2f7f6b74597b7..70c64c65cee39c272a0f0a38df3fbf92df66d866 100644 (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
diff --git a/ld/NEWS b/ld/NEWS
index b988df007d357f9ef4ddfcd717b9ce44489437c9..2a0b4ac704a088a24cfc1633785a50477513c4db 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -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
index 47fa549a9afef3c5d5a5538574dba5a7788fb4d6..dd4d35ab110c3edb086b49e3e32d81bfd2e42636 100644 (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;
index c13fa4d1a2c9d4f003223c04a597d332e697c582..7b8fec78db86e0a10f6312a5fd9bf4e7b3dbef13 100644 (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.  */
index ab7c473439a0cddf95e6ef2ca210759454348890..60deeedd35754fcd7545f31dcfc142beedf1f176 100644 (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)
diff --git a/ld/ld.h b/ld/ld.h
index 85a48ad58d940d2fb0d87060daa8bf117fe47e20..410ee993ee50fe8042fd7f59a4c191275ba9f566 100644 (file)
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -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;
 
index bc16764b0554851217316c438ada863843915307..b2dff10e449cd88c6f3be65138aacb55a6c2fc4a 100644 (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}
index 649954fbfdcf016c03c66b4659353147708936f7..68c4bc5869081715cb158dffb30842123fc612aa 100644 (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;
 
index cf943e425f9db0cca713334037a1fdc1186753e1..52f7198ad2ccec4a96474f2d865392657d6333da 100644 (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,
index 6d28e9142b090814dd9dd0637e4a44da5732a91a..6e279ae397e8173abfe9d804a0ca55f2697f037d 100644 (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);
index 2dfd0e8012f6a99b8143bf650989f7077c88d2fe..832f313c5b4f290a37df83d5e5dfcd4c3e624cb0 100644 (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*] } {
diff --git a/ld/testsuite/ld-elf/empty-implib.out b/ld/testsuite/ld-elf/empty-implib.out
new file mode 100644 (file)
index 0000000..b123064
--- /dev/null
@@ -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 (file)
index 0000000..9f854a5
--- /dev/null
@@ -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 (file)
index 0000000..a86a940
--- /dev/null
@@ -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