public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [RFC PATCH, binutils, ARM 7/9] Add support for creating import libraries
@ 2015-12-23  8:01 Thomas Preud'homme
  2016-03-29 14:45 ` [RFC PATCH, binutils, ELF 9/11] " Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preud'homme @ 2015-12-23  8:01 UTC (permalink / raw)
  To: binutils

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


ChangeLog entries are as follow:

*** bfd/ChangeLog ***

2015-07-20  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * elf-bfd.h (elf_backend_filter_implib_symbols): Declare backend hook.
        (_bfd_elf_filter_global_symbols): Declare default hook for the above.
        * elf.c (_bfd_elf_filter_global_symbols): New function.
        * elflink.c (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 _bfd_elf_filter_global_symbols.
        (elf_backend_copy_indirect_symbol): Fix spacing.
        (elf_backend_hide_symbol): Likewise.
        (elfNN_bed): Initialize elf_backend_filter_implib_symbols backend hook.


*** include/ChangeLog ***

2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
        out_implib_bfd fields.


*** ld/ChangeLog ***

2015-11-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Open import
        library file for writing and initialize implib_bfd field of link_info
        structure.
        * emultempl/pe.em (pe_implib_filename): Remove variable declaration.
        (OPTION_IMPLIB_FILENAME): Remove macro definition.
        (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
        (gld_${EMULATION_NAME}_list_options): Likewise.
        (gld${EMULATION_NAME}_handle_option): Likewise.
        (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
        instead of pe_implib_filename.
        * emultempl/pep.em (pep_implib_filename): Remove variable declaration.
        (OPTION_IMPLIB_FILENAME): Remove enumerator.
        (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
        (gld_${EMULATION_NAME}_list_options): Likewise.
        (gld${EMULATION_NAME}_handle_option): Likewise.
        (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
        instead of pep_implib_filename.
        * ld.h (args_type): Declare new out_implib_filename field.
        * ld.texinfo (--out-implib): Move documentation to arch-independent
        part and rephrase to apply to ELF targets.
        * ldexp.c (exp_fold_tree_1): Set ldscript_def field to 1 for symbols
        defined in linker scripts.
        * ldlex.h (enum option_values): Declare new OPTION_OUT_IMPLIB
        enumerator.
        * lexsup.c (ld_options): Add entry for new --out-implib switch.
        (parse_args): Handle OPTION_OUT_IMPLIB case.


*** ld/testsuite/ChangeLog ***

2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * ld-elf/elf.exp (Generate empty import library): New test.
        (Generate import library): Likewise.
        * ld-elf/implib.s: Likewise.
        * ld-elf/implib.rd: New file.
        * ld-elf/empty-implib.out: Likewise


diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 70e33275054b5987777862b42c46e83d41ca7e6f..21566ac2fc9851f003d8f20737227e020a4e1434 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -57,7 +57,7 @@ extern "C" {
 #define elfNAME(X)	NAME(elf,X)
 
 /* Information held for an ELF symbol.  The first field is the
-   corresponding asymbol.  Every symbol is an ELF file is actually a
+   corresponding asymbol.  Every symbol in an ELF file is actually a
    pointer to this structure, although it is often handled as a
    pointer to an asymbol.  */
 
@@ -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 9a2cff5fe511ad7abbc1a275829cf812abd1c22b..ac94dbf8ea156e2c341c766b0b492b6557a440f7 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3697,6 +3697,45 @@ ignore_section_sym (bfd *abfd, asymbol *sym)
 	       || bfd_is_abs_section (sym->section)));
 }
 
+
+/* 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;
+}
+
 /* Map symbol from it's internal number to the external number, moving
    all local symbols to be at the head of the list.  */
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1b41c793a978dd5d974c8e73927a5b8d85416b33..e2d5337c3fd91c43776dded28f45598fa78c4ebf 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10829,6 +10829,104 @@ 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.  */
+  symcount = bed->elf_backend_filter_implib_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)
 {
@@ -11610,6 +11708,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 0acecafcb29217e9ab178672a4a69703a5eea646..289327a433113e60c4e83c999b2056646b5bff41 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	_bfd_elf_filter_global_symbols
+#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/bfdlink.h b/include/bfdlink.h
index 93abab1c04e48af4a258e25adb00b618b6d03808..df0f08c19cc3f772e439b1c6706a834f27e626e8 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 0405d4fa71554a672e6b3070f3f310fec2244760..8354f9a4e79b82e106dcd8062123e261fe13e789 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 0370c5a52637c4043e80963f4065ab13ee7f9a14..f51dea4fffd95c2c3c72e15cf8329f8769c45cb4 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -138,7 +138,6 @@ static const char *emit_build_id;
 #ifdef DLL_SUPPORT
 static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
 static char *pe_out_def_filename = NULL;
-static char *pe_implib_filename = NULL;
 static int pe_enable_auto_image_base = 0;
 static unsigned long pe_auto_image_base = 0x61500000;
 static char *pe_dll_search_prefix = NULL;
@@ -228,8 +227,7 @@ fragment <<EOF
 #define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
 #define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
 #define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
-#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
-#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
+#define OPTION_THUMB_ENTRY		(OPTION_DISABLE_STDCALL_FIXUP + 1)
 #define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
 #define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
 #define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
@@ -323,7 +321,6 @@ gld${EMULATION_NAME}_add_options
     {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
     {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
     {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
-    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
     {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
     /* getopt() allows abbreviations, so we do this to stop it from
        treating -c as an abbreviation for these --compat-implib.  */
@@ -461,7 +458,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
   fprintf (file, _("                                     export, place into import library instead.\n"));
   fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
   fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
-  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
   fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
   fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports\n"));
   fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
@@ -805,9 +801,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
     case OPTION_DISABLE_STDCALL_FIXUP:
       pe_enable_stdcall_fixup = 0;
       break;
-    case OPTION_IMPLIB_FILENAME:
-      pe_implib_filename = xstrdup (optarg);
-      break;
     case OPTION_WARN_DUPLICATE_EXPORTS:
       pe_dll_warn_dup_exports = 1;
       break;
@@ -2073,8 +2066,9 @@ gld_${EMULATION_NAME}_finish (void)
     )
     {
       pe_dll_fill_sections (link_info.output_bfd, &link_info);
-      if (pe_implib_filename)
-	pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info);
+      if (command_line.out_implib_filename)
+	pe_dll_generate_implib (pe_def_file, command_line.out_implib_filename,
+				&link_info);
     }
 #if defined(TARGET_IS_shpe)
   /* ARM doesn't need relocs.  */
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 91de50165d71765ee61179dbd4e1f6b3f6ebe486..081890206a5dbacb53a9f3202fee6daff3542c9c 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -153,7 +153,6 @@ static const char *emit_build_id;
 #ifdef DLL_SUPPORT
 static int    pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default).  */
 static char * pep_out_def_filename = NULL;
-static char * pep_implib_filename = NULL;
 static int    pep_enable_auto_image_base = 0;
 static char * pep_dll_search_prefix = NULL;
 #endif
@@ -217,7 +216,6 @@ enum options
   OPTION_STDCALL_ALIASES,
   OPTION_ENABLE_STDCALL_FIXUP,
   OPTION_DISABLE_STDCALL_FIXUP,
-  OPTION_IMPLIB_FILENAME,
   OPTION_WARN_DUPLICATE_EXPORTS,
   OPTION_IMP_COMPAT,
   OPTION_ENABLE_AUTO_IMAGE_BASE,
@@ -296,7 +294,6 @@ gld${EMULATION_NAME}_add_options
     {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
     {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
     {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
-    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
     {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
     /* getopt() allows abbreviations, so we do this to stop it from
        treating -c as an abbreviation for these --compat-implib.  */
@@ -427,7 +424,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
   fprintf (file, _("                                     export, place into import library instead.\n"));
   fprintf (file, _("  --export-all-symbols               Automatically export all globals to DLL\n"));
   fprintf (file, _("  --kill-at                          Remove @nn from exported symbols\n"));
-  fprintf (file, _("  --out-implib <file>                Generate import library\n"));
   fprintf (file, _("  --output-def <file>                Generate a .DEF file for the built DLL\n"));
   fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate exports.\n"));
   fprintf (file, _("  --compat-implib                    Create backward compatible import libs;\n\
@@ -761,9 +757,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
     case OPTION_DISABLE_STDCALL_FIXUP:
       pep_enable_stdcall_fixup = 0;
       break;
-    case OPTION_IMPLIB_FILENAME:
-      pep_implib_filename = xstrdup (optarg);
-      break;
     case OPTION_WARN_DUPLICATE_EXPORTS:
       pep_dll_warn_dup_exports = 1;
       break;
@@ -1851,8 +1844,9 @@ gld_${EMULATION_NAME}_finish (void)
 	  && pep_def_file->num_exports != 0))
     {
       pep_dll_fill_sections (link_info.output_bfd, &link_info);
-      if (pep_implib_filename)
-	pep_dll_generate_implib (pep_def_file, pep_implib_filename, &link_info);
+      if (command_line.out_implib_filename)
+	pep_dll_generate_implib (pep_def_file,
+				 command_line.out_implib_filename, &link_info);
     }
 
   if (pep_out_def_filename)
diff --git a/ld/ld.h b/ld/ld.h
index d84ec4e634eab5c0443767c3acded05073fa0484..807cd30e9e35eee8c23052dc9bcccf233be005f0 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 1dd749249acbf8c97ce7ec4fad66d56efb9367cd..b9e7f7ce652319f4d9833076aaa0c1bd7a36c923 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 2ec8eb6d19892b5751afcacf9839181acd20cfd5..d80698fb05e4f5392068acf2d4e7d819dee2aabd 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 6f11e7bd21782367ad8347d5f3754aa09192b5ed..61f3f80dc98f352791b1155984b16930ce1e8177 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 4cad2097a1fb232bb576e2dc5d46bbadc42e1a9d..a3d040eb32e6559fdcb0c449fda98f09ff1ae45c 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 e56c2054a69326c398b8f1298c010a3591a487a8..8b5799da8fb956f1bb5e4bf48448997f4ae6739f 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -124,6 +124,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


The patch doesn't show any regression when running the binutils-gdb testsuite for arm-none-eabi, i386-unknown-pe and x86_64-unknown-mingw32 targets.

Any comments?

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2015-12-23  8:01 [RFC PATCH, binutils, ARM 7/9] Add support for creating import libraries Thomas Preud'homme
@ 2016-03-29 14:45 ` Thomas Preudhomme
  2016-05-18 16:38   ` [PATCH, binutils, ELF 9/11, ping1] " Thomas Preudhomme
  2016-07-07 11:01   ` [RFC PATCH, binutils, ELF 9/11] " Richard Earnshaw (lists)
  0 siblings, 2 replies; 15+ messages in thread
From: Thomas Preudhomme @ 2016-03-29 14:45 UTC (permalink / raw)
  To: binutils

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.

*** bfd/ChangeLog ***

2016-02-17  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * elf-bfd.h (elf_backend_filter_implib_symbols): Declare backend hook.
        (_bfd_elf_filter_global_symbols): Declare.
        * elf.c (_bfd_elf_filter_global_symbols): New function.
        * elflink.c (elf_filter_global_symbols): Likewise.
        (elf_output_implib): Likewise.
        (bfd_elf_final_link): Call above function, failing if it does.
        * elfxx-target.h (elf_backend_filter_implib_symbols): Define macro and
        default it to NULL.
        (elf_backend_copy_indirect_symbol): Fix spacing.
        (elf_backend_hide_symbol): Likewise.
        (elfNN_bed): Initialize elf_backend_filter_implib_symbols backend hook.


*** include/ChangeLog ***

2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
        out_implib_bfd fields.


*** ld/ChangeLog ***

2015-11-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Open import
        library file for writing and initialize implib_bfd field of link_info
        structure.
        * emultempl/pe.em (pe_implib_filename): Remove variable declaration.
        (OPTION_IMPLIB_FILENAME): Remove macro definition.
        (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
        (gld_${EMULATION_NAME}_list_options): Likewise.
        (gld${EMULATION_NAME}_handle_option): Likewise.
        (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
        instead of pe_implib_filename.
        * emultempl/pep.em (pep_implib_filename): Remove variable declaration.
        (OPTION_IMPLIB_FILENAME): Remove enumerator.
        (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
        (gld_${EMULATION_NAME}_list_options): Likewise.
        (gld${EMULATION_NAME}_handle_option): Likewise.
        (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
        instead of pep_implib_filename.
        * ld.h (args_type): Declare new out_implib_filename field.
        * ld.texinfo (--out-implib): Move documentation to arch-independent
        part and rephrase to apply to ELF targets.
        * ldexp.c (exp_fold_tree_1): Set ldscript_def field to 1 for symbols
        defined in linker scripts.
        * ldlex.h (enum option_values): Declare new OPTION_OUT_IMPLIB
        enumerator.
        * lexsup.c (ld_options): Add entry for new --out-implib switch.
        (parse_args): Handle OPTION_OUT_IMPLIB case.


*** ld/testsuite/ChangeLog ***

2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * ld-elf/elf.exp (Generate empty import library): New test.
        (Generate import library): Likewise.
        * ld-elf/implib.s: Likewise.
        * ld-elf/implib.rd: New file.
        * ld-elf/empty-implib.out: Likewise


diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 
6a04f044e78bcbf5975ca88987feb878865cbea5..dc25569cac448e336d90dcbe6813d5a26e188095 
100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1125,6 +1125,11 @@ struct elf_backend_data
      bfd_boolean (*) (void *, const char *, Elf_Internal_Sym *, asection *,
 		      struct elf_link_hash_entry *));
 
+  /* Filter what symbols of the output file to include in the import
+     library if one is created.  */
+  unsigned int (*elf_backend_filter_implib_symbols)
+    (bfd *, struct bfd_link_info *, asymbol **, long);
+
   /* Copy any information related to dynamic linking from a pre-existing
      symbol to a newly created symbol.  Also called to copy flags and
      other back-end info to a weakdef, in which case the symbol is not
@@ -1937,6 +1942,8 @@ extern bfd_boolean _bfd_elf_section_already_linked
   (bfd *, asection *, struct bfd_link_info *);
 extern void bfd_elf_set_group_contents
   (bfd *, asection *, void *);
+extern unsigned int _bfd_elf_filter_global_symbols
+  (bfd *, struct bfd_link_info *, asymbol **, long);
 extern asection *_bfd_elf_check_kept_section
   (asection *, struct bfd_link_info *);
 #define _bfd_elf_link_just_syms _bfd_generic_link_just_syms
diff --git a/bfd/elf.c b/bfd/elf.c
index 
74c2f2d33a46057fb1551a5f50190cf001ff1779..e82a2ca1174786c3c394662f7bda5e4787172c1b 
100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3676,6 +3676,43 @@ sym_is_global (bfd *abfd, asymbol *sym)
 	  || bfd_is_com_section (bfd_get_section (sym)));
 }
 
+/* Filter global symbols of ABFD to include in the import library.  All
+   SYMCOUNT symbols of ABFD can be examined from their pointers in
+   SYMS.  Pointers of symbols to keep should be stored continuously at
+   the beginning of that array.
+
+   Returns the number of symbols to keep.  */
+
+unsigned int
+_bfd_elf_filter_global_symbols (bfd *abfd, struct bfd_link_info *info,
+				asymbol **syms, long symcount)
+{
+  long src_count, dst_count = 0;
+
+  for (src_count = 0; src_count < symcount; src_count++)
+    {
+      asymbol *sym = syms[src_count];
+      char *name = (char *) bfd_asymbol_name (sym);
+      struct bfd_link_hash_entry *h;
+
+      if (!sym_is_global (abfd, sym))
+	continue;
+
+      h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE);
+      if (h->type != bfd_link_hash_defined && h->type != 
bfd_link_hash_defweak)
+	continue;
+
+      if (h->linker_def || h->ldscript_def)
+	continue;
+
+      syms[dst_count++] = sym;
+    }
+
+  syms[dst_count] = NULL;
+
+  return dst_count;
+}
+
 /* Don't output section symbols for sections that are not going to be
    output, that are duplicates or there is no BFD section.  */
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 
ac03ce5003adea4a8fef6481e638c02a7d85d177..7c8809f02e6abeaac288fc17ddd17ce4ff5b1bc2 
100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -10831,6 +10831,107 @@ elf_fixup_link_order (bfd *abfd, asection *o)
   return TRUE;
 }
 
+/* Generate an import library in INFO->implib_bfd from symbols in ABFD.
+   Returns TRUE upon success, FALSE otherwise.  */
+
+static bfd_boolean
+elf_output_implib (bfd *abfd, struct bfd_link_info *info)
+{
+  bfd_boolean ret = FALSE;
+  bfd *implib_bfd;
+  const struct elf_backend_data *bed;
+  flagword flags;
+  enum bfd_architecture arch;
+  unsigned int mach;
+  asymbol **sympp = NULL;
+  long symsize;
+  long symcount;
+  long src_count;
+  elf_symbol_type *osymbuf;
+
+  implib_bfd = info->out_implib_bfd;
+  bed = get_elf_backend_data (abfd);
+
+  if (!bfd_set_format (implib_bfd, bfd_object))
+    return FALSE;
+
+  flags = bfd_get_file_flags (abfd);
+  flags &= ~HAS_RELOC;
+  if (!bfd_set_start_address (implib_bfd, 0)
+      || !bfd_set_file_flags (implib_bfd, flags))
+    return FALSE;
+
+  /* Copy architecture of output file to import library file.  */
+  arch = bfd_get_arch (abfd);
+  mach = bfd_get_mach (abfd);
+  if (!bfd_set_arch_mach (implib_bfd, arch, mach)
+      && (abfd->target_defaulted
+	  || bfd_get_arch (abfd) != bfd_get_arch (implib_bfd)))
+    return FALSE;
+
+  /* Get symbol table size.  */
+  symsize = bfd_get_symtab_upper_bound (abfd);
+  if (symsize < 0)
+    return FALSE;
+
+  /* Read in the symbol table.  */
+  sympp = (asymbol **) xmalloc (symsize);
+  symcount = bfd_canonicalize_symtab (abfd, sympp);
+  if (symcount < 0)
+    goto free_sym_buf;
+
+  /* Allow the BFD backend to copy any private header data it
+     understands from the output BFD to the import library BFD.  */
+  if (! bfd_copy_private_header_data (abfd, implib_bfd))
+    goto free_sym_buf;
+
+  /* Filter symbols to appear in the import library.  */
+  if (bed->elf_backend_filter_implib_symbols)
+    symcount = bed->elf_backend_filter_implib_symbols (abfd, info, sympp,
+						       symcount);
+  else
+    symcount = _bfd_elf_filter_global_symbols (abfd, info, sympp, symcount);
+  if (symcount == 0)
+    {
+      (*_bfd_error_handler) (_("%B: no symbol found for import library"),
+			     implib_bfd);
+      goto free_sym_buf;
+    }
+
+
+  /* Make symbols absolute.  */
+  osymbuf = (elf_symbol_type *) bfd_alloc2 (implib_bfd, symcount,
+					    sizeof (*osymbuf));
+  for (src_count = 0; src_count < symcount; src_count++)
+    {
+      memcpy (&osymbuf[src_count], (elf_symbol_type *) sympp[src_count],
+	      sizeof (*osymbuf));
+      osymbuf[src_count].symbol.section = bfd_abs_section_ptr;
+      osymbuf[src_count].internal_elf_sym.st_shndx = SHN_ABS;
+      osymbuf[src_count].symbol.value += sympp[src_count]->section->vma;
+      osymbuf[src_count].internal_elf_sym.st_value =
+	osymbuf[src_count].symbol.value;
+      sympp[src_count] = &osymbuf[src_count].symbol;
+    }
+
+  bfd_set_symtab (implib_bfd, sympp, symcount);
+
+  /* Allow the BFD backend to copy any private data it understands
+     from the output BFD to the import library BFD.  This is done last
+     to permit the routine to look at the filtered symbol table.  */
+  if (! bfd_copy_private_bfd_data (abfd, implib_bfd))
+    goto free_sym_buf;
+
+  if (!bfd_close (implib_bfd))
+    goto free_sym_buf;
+
+  ret = TRUE;
+
+free_sym_buf:
+  free (sympp);
+  return ret;
+}
+
 static void
 elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
 {
@@ -11633,6 +11734,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info 
*info)
 	return FALSE;
     }
 
+  if (info->out_implib_bfd && !elf_output_implib (abfd, info))
+    {
+      (*_bfd_error_handler) (_("%B: failed to generate import library"),
+			     info->out_implib_bfd);
+      return FALSE;
+    }
+
   /* Adjust the relocs to have the correct symbol indices.  */
   for (o = abfd->sections; o != NULL; o = o->next)
     {
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 
b3227ed3c521ad4e7dacbd0f0d433f4b45e4ba5f..f996885cb56ab24860ca18a4aafe1d33f3915649 
100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -514,11 +514,14 @@
 #ifndef elf_backend_output_arch_syms
 #define elf_backend_output_arch_syms		NULL
 #endif
+#ifndef elf_backend_filter_implib_symbols
+#define elf_backend_filter_implib_symbols	NULL
+#endif
 #ifndef elf_backend_copy_indirect_symbol
-#define elf_backend_copy_indirect_symbol  _bfd_elf_link_hash_copy_indirect
+#define elf_backend_copy_indirect_symbol	_bfd_elf_link_hash_copy_indirect
 #endif
 #ifndef elf_backend_hide_symbol
-#define elf_backend_hide_symbol		_bfd_elf_link_hash_hide_symbol
+#define elf_backend_hide_symbol			_bfd_elf_link_hash_hide_symbol
 #endif
 #ifndef elf_backend_fixup_symbol
 #define elf_backend_fixup_symbol		NULL
@@ -750,6 +753,7 @@ static struct elf_backend_data elfNN_bed =
   elf_backend_print_symbol_all,
   elf_backend_output_arch_local_syms,
   elf_backend_output_arch_syms,
+  elf_backend_filter_implib_symbols,
   elf_backend_copy_indirect_symbol,
   elf_backend_hide_symbol,
   elf_backend_fixup_symbol,
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 
9b849aa761e1e59d5f31f2ec6f2769f28421d251..5d772d0b8b41bdad06b9f02ff4a030c06fe75345 
100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -99,6 +99,9 @@ struct bfd_link_hash_entry
      in a linker script.  */
   unsigned int linker_def : 1;
 
+  /* Symbol defined in a linker script.  */
+  unsigned int ldscript_def : 1;
+
   /* A union of information depending upon the type.  */
   union
     {
@@ -499,6 +502,9 @@ struct bfd_link_info
   /* The output BFD.  */
   bfd *output_bfd;
 
+  /* The import library generated.  */
+  bfd *out_implib_bfd;
+
   /* The list of input BFD's involved in the link.  These are chained
      together via the link.next field.  */
   bfd *input_bfds;
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 
d9d3393ec04e48d690ddf528e86636e778bdccf3..d04a365563d3eb730f5404e906862bbcfd9f6bca 
100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -1025,6 +1025,20 @@ gld${EMULATION_NAME}_after_open (void)
   if (!is_elf_hash_table (htab))
     return;
 
+  if (command_line.out_implib_filename)
+    {
+      unlink_if_ordinary (command_line.out_implib_filename);
+      link_info.out_implib_bfd
+	= bfd_openw (command_line.out_implib_filename,
+		     bfd_get_target (link_info.output_bfd));
+
+      if (link_info.out_implib_bfd == NULL)
+	{
+	  einfo ("%F%s: Can't open for writing: %E\n",
+		 command_line.out_implib_filename);
+	}
+    }
+
   if (emit_note_gnu_build_id != NULL)
     {
       bfd *abfd;
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 
f15c6c415c2c2b41b3c4f9753c4a2fafd2f59767..40980b490a89f69f42605f83798cf2c815437d30 
100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -138,7 +138,6 @@ static const char *emit_build_id;
 #ifdef DLL_SUPPORT
 static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
 static char *pe_out_def_filename = NULL;
-static char *pe_implib_filename = NULL;
 static int pe_enable_auto_image_base = 0;
 static unsigned long pe_auto_image_base = 0x61500000;
 static char *pe_dll_search_prefix = NULL;
@@ -228,8 +227,7 @@ fragment <<EOF
 #define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
 #define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
 #define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
-#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
-#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
+#define OPTION_THUMB_ENTRY		(OPTION_DISABLE_STDCALL_FIXUP + 1)
 #define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
 #define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
 #define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
@@ -323,7 +321,6 @@ gld${EMULATION_NAME}_add_options
     {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
     {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
     {"disable-stdcall-fixup", no_argument, NULL, 
OPTION_DISABLE_STDCALL_FIXUP},
-    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
     {"warn-duplicate-exports", no_argument, NULL, 
OPTION_WARN_DUPLICATE_EXPORTS},
     /* getopt() allows abbreviations, so we do this to stop it from
        treating -c as an abbreviation for these --compat-implib.  */
@@ -461,7 +458,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
   fprintf (file, _("                                     export, place into 
import library instead.\n"));
   fprintf (file, _("  --export-all-symbols               Automatically export 
all globals to DLL\n"));
   fprintf (file, _("  --kill-at                          Remove @nn from 
exported symbols\n"));
-  fprintf (file, _("  --out-implib <file>                Generate import 
library\n"));
   fprintf (file, _("  --output-def <file>                Generate a .DEF file 
for the built DLL\n"));
   fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate 
exports\n"));
   fprintf (file, _("  --compat-implib                    Create backward 
compatible import libs;\n\
@@ -805,9 +801,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
     case OPTION_DISABLE_STDCALL_FIXUP:
       pe_enable_stdcall_fixup = 0;
       break;
-    case OPTION_IMPLIB_FILENAME:
-      pe_implib_filename = xstrdup (optarg);
-      break;
     case OPTION_WARN_DUPLICATE_EXPORTS:
       pe_dll_warn_dup_exports = 1;
       break;
@@ -2073,8 +2066,9 @@ gld_${EMULATION_NAME}_finish (void)
     )
     {
       pe_dll_fill_sections (link_info.output_bfd, &link_info);
-      if (pe_implib_filename)
-	pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info);
+      if (command_line.out_implib_filename)
+	pe_dll_generate_implib (pe_def_file, command_line.out_implib_filename,
+				&link_info);
     }
 #if defined(TARGET_IS_shpe)
   /* ARM doesn't need relocs.  */
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 
054a98497f3c386adecd361612d4d1bbdc779049..def1a4f21737d87ca94c1c4616cc691ec5efffd0 
100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -153,7 +153,6 @@ static const char *emit_build_id;
 #ifdef DLL_SUPPORT
 static int    pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable (default).  
*/
 static char * pep_out_def_filename = NULL;
-static char * pep_implib_filename = NULL;
 static int    pep_enable_auto_image_base = 0;
 static char * pep_dll_search_prefix = NULL;
 #endif
@@ -217,7 +216,6 @@ enum options
   OPTION_STDCALL_ALIASES,
   OPTION_ENABLE_STDCALL_FIXUP,
   OPTION_DISABLE_STDCALL_FIXUP,
-  OPTION_IMPLIB_FILENAME,
   OPTION_WARN_DUPLICATE_EXPORTS,
   OPTION_IMP_COMPAT,
   OPTION_ENABLE_AUTO_IMAGE_BASE,
@@ -296,7 +294,6 @@ gld${EMULATION_NAME}_add_options
     {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
     {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
     {"disable-stdcall-fixup", no_argument, NULL, 
OPTION_DISABLE_STDCALL_FIXUP},
-    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
     {"warn-duplicate-exports", no_argument, NULL, 
OPTION_WARN_DUPLICATE_EXPORTS},
     /* getopt() allows abbreviations, so we do this to stop it from
        treating -c as an abbreviation for these --compat-implib.  */
@@ -427,7 +424,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
   fprintf (file, _("                                     export, place into 
import library instead.\n"));
   fprintf (file, _("  --export-all-symbols               Automatically export 
all globals to DLL\n"));
   fprintf (file, _("  --kill-at                          Remove @nn from 
exported symbols\n"));
-  fprintf (file, _("  --out-implib <file>                Generate import 
library\n"));
   fprintf (file, _("  --output-def <file>                Generate a .DEF file 
for the built DLL\n"));
   fprintf (file, _("  --warn-duplicate-exports           Warn about duplicate 
exports.\n"));
   fprintf (file, _("  --compat-implib                    Create backward 
compatible import libs;\n\
@@ -761,9 +757,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
     case OPTION_DISABLE_STDCALL_FIXUP:
       pep_enable_stdcall_fixup = 0;
       break;
-    case OPTION_IMPLIB_FILENAME:
-      pep_implib_filename = xstrdup (optarg);
-      break;
     case OPTION_WARN_DUPLICATE_EXPORTS:
       pep_dll_warn_dup_exports = 1;
       break;
@@ -1851,8 +1844,9 @@ gld_${EMULATION_NAME}_finish (void)
 	  && pep_def_file->num_exports != 0))
     {
       pep_dll_fill_sections (link_info.output_bfd, &link_info);
-      if (pep_implib_filename)
-	pep_dll_generate_implib (pep_def_file, pep_implib_filename, &link_info);
+      if (command_line.out_implib_filename)
+	pep_dll_generate_implib (pep_def_file,
+				 command_line.out_implib_filename, &link_info);
     }
 
   if (pep_out_def_filename)
diff --git a/ld/ld.h b/ld/ld.h
index 
ab09032e455f8b64b1d8fd7cbb860d78cfd45e58..e41460fec76e3725fca0a5399e84389266100f32 
100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -158,6 +158,9 @@ typedef struct {
      input files.  */
   bfd_boolean accept_unknown_input_arch;
 
+  /* Name of the import library to generate.  */
+  char *out_implib_filename;
+
   /* If TRUE we'll just print the default output on stdout.  */
   bfd_boolean print_output_format;
 
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 
8507c3fe677921c0c8fbd5fcb5b5a5799d8cfae0..a9a2e347a1e6960406916b36506746dadc557b96 
100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1696,6 +1696,16 @@ command @code{OUTPUT_FORMAT} can also specify the 
output format, but
 this option overrides it.  @xref{BFD}.
 @end ifclear
 
+@kindex --out-implib
+@item --out-implib @var{file}
+Create an import library in @var{file} corresponding to the executable
+the linker is generating (eg. a DLL or ELF program).  This import
+library (which should be called @code{*.dll.a} or @code{*.a} for DLLs)
+may be used to link clients against the generated executable; this
+behaviour makes it possible to skip a separate import library creation
+step (eg. @code{dlltool} for DLLs).  This option is only available for
+the i386 PE and ELF targetted ports of the linker.
+
 @kindex -pie
 @kindex --pic-executable
 @item -pie
@@ -2555,16 +2565,6 @@ automatically or implicitly exported symbols.
 [This option is specific to the i386 PE targeted port of the linker]
 
 @cindex DLLs, creating
-@kindex --out-implib
-@item --out-implib @var{file}
-The linker will create the file @var{file} which will contain an
-import lib corresponding to the DLL the linker is generating. This
-import lib (which should be called @code{*.dll.a} or @code{*.a}
-may be used to link clients against the generated DLL; this behaviour
-makes it possible to skip a separate @code{dlltool} import library
-creation step.
-[This option is specific to the i386 PE targeted port of the linker]
-
 @kindex --enable-auto-image-base
 @item --enable-auto-image-base
 @itemx --enable-auto-image-base=@var{value}
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 
22dd0d2f1d99beac27690f82c2db423d6db25c81..e8c5dcbd66e84bdc2d11b4c564dd4dc7aee6ca14 
100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -1182,6 +1182,7 @@ exp_fold_tree_1 (etree_type *tree)
 	      h->u.def.value = expld.result.value;
 	      h->u.def.section = expld.result.section;
 	      h->linker_def = 0;
+	      h->ldscript_def = 1;
 	      if (tree->type.node_class == etree_provide)
 		tree->type.node_class = etree_provided;
 
diff --git a/ld/ldlex.h b/ld/ldlex.h
index 
cf943e425f9db0cca713334037a1fdc1186753e1..52f7198ad2ccec4a96474f2d865392657d6333da 
100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -35,6 +35,7 @@ enum option_values
   OPTION_DYNAMIC_LINKER,
   OPTION_NO_DYNAMIC_LINKER,
   OPTION_SYSROOT,
+  OPTION_OUT_IMPLIB,
   OPTION_EB,
   OPTION_EL,
   OPTION_EMBEDDED_RELOCS,
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 
87341f93dcc41a5529f4258cf8d2ea0eff327c58..aede732f2b60f7af66a3ad505fb157603db20755 
100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -164,6 +164,8 @@ static const struct ld_option ld_options[] =
     'o', N_("FILE"), N_("Set output file name"), EXACTLY_TWO_DASHES },
   { {NULL, required_argument, NULL, '\0'},
     'O', NULL, N_("Optimize output file"), ONE_DASH },
+  { {"out-implib", required_argument, NULL, OPTION_OUT_IMPLIB},
+    '\0', N_("FILE"), N_("Generate import library"), TWO_DASHES },
 #ifdef ENABLE_PLUGINS
   { {"plugin", required_argument, NULL, OPTION_PLUGIN},
     '\0', N_("PLUGIN"), N_("Load named plugin"), ONE_DASH },
@@ -1004,6 +1006,9 @@ parse_args (unsigned argc, char **argv)
 	case OPTION_OFORMAT:
 	  lang_add_output_format (optarg, NULL, NULL, 0);
 	  break;
+	case OPTION_OUT_IMPLIB:
+	  command_line.out_implib_filename = xstrdup (optarg);
+	  break;
 	case OPTION_PRINT_SYSROOT:
 	  if (*ld_sysroot)
 	    puts (ld_sysroot);
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index 
af0b09187a4c37cf11bda76310c97301d69a4e2d..297b10cce0c5ad62e2a8e8ebff0c610e91d83cf1 
100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -126,6 +126,22 @@ foreach t $test_list {
     run_dump_test [file rootname $t]
 }
 
+# Check that the --out-implib option work correctly.
+run_ld_link_tests {
+    {"Generate empty import library"
+     "--out-implib=tmpdir/implib.lib" ""
+     "--defsym NO_GLOBAL=1"
+     {implib.s}
+     {{ld empty-implib.out}}
+     "implib"}
+    {"Generate import library"
+     "-Tdata=0x1000 --out-implib=tmpdir/implib.lib" ""
+     ""
+     {implib.s}
+     {{readelf {-s tmpdir/implib.lib} implib.rd}}
+     "implib"}
+}
+
 if { [istarget *-*-linux*]
      || [istarget *-*-nacl*]
      || [istarget *-*-gnu*] } {
diff --git a/ld/testsuite/ld-elf/empty-implib.out b/ld/testsuite/ld-elf/empty-
implib.out
new file mode 100644
index 
0000000000000000000000000000000000000000..b123064df3f6f429c59fe204d57e57ed76a8d5be
--- /dev/null
+++ b/ld/testsuite/ld-elf/empty-implib.out
@@ -0,0 +1,2 @@
+.*: .*: no symbol found for import library
+.*: .*: failed to generate import library
diff --git a/ld/testsuite/ld-elf/implib.rd b/ld/testsuite/ld-elf/implib.rd
new file mode 100644
index 
0000000000000000000000000000000000000000..9f854a59bd26054a8fdb49f6dbaac4120b2c7ef1
--- /dev/null
+++ b/ld/testsuite/ld-elf/implib.rd
@@ -0,0 +1,11 @@
+File: tmpdir/implib.lib
+
+Symbol table '.symtab' contains 3 entries:
+   Num:    Value +Size Type    Bind   Vis      Ndx Name
+     0: [0-9a-f]+     0 NOTYPE  LOCAL  DEFAULT  UND 
+     1: 0+100[0-3]     1 OBJECT  GLOBAL DEFAULT  ABS exported1
+     2: 0+100[0-3]     1 OBJECT  GLOBAL DEFAULT  ABS exported2
+
+File: tmpdir/implib
+
+#...
diff --git a/ld/testsuite/ld-elf/implib.s b/ld/testsuite/ld-elf/implib.s
new file mode 100644
index 
0000000000000000000000000000000000000000..a86a940c138d7dd65e42c609adbe594c579061ac
--- /dev/null
+++ b/ld/testsuite/ld-elf/implib.s
@@ -0,0 +1,22 @@
+.ifndef NO_GLOBAL
+	.bss
+	.comm	exported1,1
+
+	.data
+	.global	exported2
+	.type	exported2, %object
+	.size	exported2, 1
+exported2:
+	.byte	21
+.endif
+
+	.bss
+not_exported1:
+	.space	1
+	.size	not_exported1, 1
+
+	.data
+	.type	not_exported2, %object
+	.size	not_exported2, 1
+not_exported2:
+	.byte	42


Is this ok for master branch?

best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH, binutils, ELF 9/11, ping1] Add support for creating import libraries
  2016-03-29 14:45 ` [RFC PATCH, binutils, ELF 9/11] " Thomas Preudhomme
@ 2016-05-18 16:38   ` Thomas Preudhomme
  2016-05-18 16:40     ` Thomas Preudhomme
  2016-07-07 11:01   ` [RFC PATCH, binutils, ELF 9/11] " Richard Earnshaw (lists)
  1 sibling, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-05-18 16:38 UTC (permalink / raw)
  To: binutils

[CCing Richard Earnshaw and Nick Clifton who reviewed previous ARMv8-M 
patches]

ping?

See [1][2] for previous discussion on this proposition.

[1] https://sourceware.org/ml/binutils/2016-02/msg00075.html
[2] https://sourceware.org/ml/binutils/2016-02/msg00222.html

Best regards,

Thomas

On Tuesday 29 March 2016 15:44:38 Thomas Preudhomme wrote:
> On Wednesday 23 December 2015 16:00:53 Thomas Preud'homme wrote:

[removing mention of 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.
> 
> *** bfd/ChangeLog ***
> 
> 2016-02-17  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * elf-bfd.h (elf_backend_filter_implib_symbols): Declare backend
> hook. (_bfd_elf_filter_global_symbols): Declare.
>         * elf.c (_bfd_elf_filter_global_symbols): New function.
>         * elflink.c (elf_filter_global_symbols): Likewise.
>         (elf_output_implib): Likewise.
>         (bfd_elf_final_link): Call above function, failing if it does.
>         * elfxx-target.h (elf_backend_filter_implib_symbols): Define macro
> and default it to NULL.
>         (elf_backend_copy_indirect_symbol): Fix spacing.
>         (elf_backend_hide_symbol): Likewise.
>         (elfNN_bed): Initialize elf_backend_filter_implib_symbols backend
> hook.
> 
> 
> *** include/ChangeLog ***
> 
> 2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
>         out_implib_bfd fields.
> 
> 
> *** ld/ChangeLog ***
> 
> 2015-11-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Open import
>         library file for writing and initialize implib_bfd field of
> link_info structure.
>         * emultempl/pe.em (pe_implib_filename): Remove variable declaration.
> (OPTION_IMPLIB_FILENAME): Remove macro definition.
>         (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
>         (gld_${EMULATION_NAME}_list_options): Likewise.
>         (gld${EMULATION_NAME}_handle_option): Likewise.
>         (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
> instead of pe_implib_filename.
>         * emultempl/pep.em (pep_implib_filename): Remove variable
> declaration. (OPTION_IMPLIB_FILENAME): Remove enumerator.
>         (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
>         (gld_${EMULATION_NAME}_list_options): Likewise.
>         (gld${EMULATION_NAME}_handle_option): Likewise.
>         (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
> instead of pep_implib_filename.
>         * ld.h (args_type): Declare new out_implib_filename field.
>         * ld.texinfo (--out-implib): Move documentation to arch-independent
>         part and rephrase to apply to ELF targets.
>         * ldexp.c (exp_fold_tree_1): Set ldscript_def field to 1 for symbols
> defined in linker scripts.
>         * ldlex.h (enum option_values): Declare new OPTION_OUT_IMPLIB
>         enumerator.
>         * lexsup.c (ld_options): Add entry for new --out-implib switch.
>         (parse_args): Handle OPTION_OUT_IMPLIB case.
> 
> 
> *** ld/testsuite/ChangeLog ***
> 
> 2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * ld-elf/elf.exp (Generate empty import library): New test.
>         (Generate import library): Likewise.
>         * ld-elf/implib.s: Likewise.
>         * ld-elf/implib.rd: New file.
>         * ld-elf/empty-implib.out: Likewise
> 
> 
> diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
> index
> 6a04f044e78bcbf5975ca88987feb878865cbea5..dc25569cac448e336d90dcbe6813d5a26e
> 188095 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..e82a2ca1174786c3c394662f7bda5e4787
> 172c1b 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..7c8809f02e6abeaac288fc17ddd17ce4ff
> 5b1bc2 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..f996885cb56ab24860ca18a4aafe1d33f3
> 915649 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..5d772d0b8b41bdad06b9f02ff4a030c06f
> e75345 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..d04a365563d3eb730f5404e906862bbcfd
> 9f6bca 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..40980b490a89f69f42605f83798cf2c815
> 437d30 100644
> --- a/ld/emultempl/pe.em
> +++ b/ld/emultempl/pe.em
> @@ -138,7 +138,6 @@ static const char *emit_build_id;
>  #ifdef DLL_SUPPORT
>  static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
>  static char *pe_out_def_filename = NULL;
> -static char *pe_implib_filename = NULL;
>  static int pe_enable_auto_image_base = 0;
>  static unsigned long pe_auto_image_base = 0x61500000;
>  static char *pe_dll_search_prefix = NULL;
> @@ -228,8 +227,7 @@ fragment <<EOF
>  #define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
>  #define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
>  #define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
> -#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
> -#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
> +#define OPTION_THUMB_ENTRY		(OPTION_DISABLE_STDCALL_FIXUP + 1)
>  #define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
>  #define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
>  #define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
> @@ -323,7 +321,6 @@ gld${EMULATION_NAME}_add_options
>      {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
>      {"enable-stdcall-fixup", no_argument, NULL,
> OPTION_ENABLE_STDCALL_FIXUP}, {"disable-stdcall-fixup", no_argument, NULL,
> OPTION_DISABLE_STDCALL_FIXUP},
> -    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
>      {"warn-duplicate-exports", no_argument, NULL,
> OPTION_WARN_DUPLICATE_EXPORTS},
>      /* getopt() allows abbreviations, so we do this to stop it from
>         treating -c as an abbreviation for these --compat-implib.  */
> @@ -461,7 +458,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
>    fprintf (file, _("                                     export, place into
> import library instead.\n"));
>    fprintf (file, _("  --export-all-symbols               Automatically
> export all globals to DLL\n"));
>    fprintf (file, _("  --kill-at                          Remove @nn from
> exported symbols\n"));
> -  fprintf (file, _("  --out-implib <file>                Generate import
> library\n"));
>    fprintf (file, _("  --output-def <file>                Generate a .DEF
> file for the built DLL\n"));
>    fprintf (file, _("  --warn-duplicate-exports           Warn about
> duplicate exports\n"));
>    fprintf (file, _("  --compat-implib                    Create backward
> compatible import libs;\n\
> @@ -805,9 +801,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
>      case OPTION_DISABLE_STDCALL_FIXUP:
>        pe_enable_stdcall_fixup = 0;
>        break;
> -    case OPTION_IMPLIB_FILENAME:
> -      pe_implib_filename = xstrdup (optarg);
> -      break;
>      case OPTION_WARN_DUPLICATE_EXPORTS:
>        pe_dll_warn_dup_exports = 1;
>        break;
> @@ -2073,8 +2066,9 @@ gld_${EMULATION_NAME}_finish (void)
>      )
>      {
>        pe_dll_fill_sections (link_info.output_bfd, &link_info);
> -      if (pe_implib_filename)
> -	pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info);
> +      if (command_line.out_implib_filename)
> +	pe_dll_generate_implib (pe_def_file, command_line.out_implib_filename,
> +				&link_info);
>      }
>  #if defined(TARGET_IS_shpe)
>    /* ARM doesn't need relocs.  */
> diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
> index
> 054a98497f3c386adecd361612d4d1bbdc779049..def1a4f21737d87ca94c1c4616cc691ec5
> efffd0 100644
> --- a/ld/emultempl/pep.em
> +++ b/ld/emultempl/pep.em
> @@ -153,7 +153,6 @@ static const char *emit_build_id;
>  #ifdef DLL_SUPPORT
>  static int    pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable
> (default). */
>  static char * pep_out_def_filename = NULL;
> -static char * pep_implib_filename = NULL;
>  static int    pep_enable_auto_image_base = 0;
>  static char * pep_dll_search_prefix = NULL;
>  #endif
> @@ -217,7 +216,6 @@ enum options
>    OPTION_STDCALL_ALIASES,
>    OPTION_ENABLE_STDCALL_FIXUP,
>    OPTION_DISABLE_STDCALL_FIXUP,
> -  OPTION_IMPLIB_FILENAME,
>    OPTION_WARN_DUPLICATE_EXPORTS,
>    OPTION_IMP_COMPAT,
>    OPTION_ENABLE_AUTO_IMAGE_BASE,
> @@ -296,7 +294,6 @@ gld${EMULATION_NAME}_add_options
>      {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
>      {"enable-stdcall-fixup", no_argument, NULL,
> OPTION_ENABLE_STDCALL_FIXUP}, {"disable-stdcall-fixup", no_argument, NULL,
> OPTION_DISABLE_STDCALL_FIXUP},
> -    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
>      {"warn-duplicate-exports", no_argument, NULL,
> OPTION_WARN_DUPLICATE_EXPORTS},
>      /* getopt() allows abbreviations, so we do this to stop it from
>         treating -c as an abbreviation for these --compat-implib.  */
> @@ -427,7 +424,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
>    fprintf (file, _("                                     export, place into
> import library instead.\n"));
>    fprintf (file, _("  --export-all-symbols               Automatically
> export all globals to DLL\n"));
>    fprintf (file, _("  --kill-at                          Remove @nn from
> exported symbols\n"));
> -  fprintf (file, _("  --out-implib <file>                Generate import
> library\n"));
>    fprintf (file, _("  --output-def <file>                Generate a .DEF
> file for the built DLL\n"));
>    fprintf (file, _("  --warn-duplicate-exports           Warn about
> duplicate exports.\n"));
>    fprintf (file, _("  --compat-implib                    Create backward
> compatible import libs;\n\
> @@ -761,9 +757,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
>      case OPTION_DISABLE_STDCALL_FIXUP:
>        pep_enable_stdcall_fixup = 0;
>        break;
> -    case OPTION_IMPLIB_FILENAME:
> -      pep_implib_filename = xstrdup (optarg);
> -      break;
>      case OPTION_WARN_DUPLICATE_EXPORTS:
>        pep_dll_warn_dup_exports = 1;
>        break;
> @@ -1851,8 +1844,9 @@ gld_${EMULATION_NAME}_finish (void)
>  	  && pep_def_file->num_exports != 0))
>      {
>        pep_dll_fill_sections (link_info.output_bfd, &link_info);
> -      if (pep_implib_filename)
> -	pep_dll_generate_implib (pep_def_file, pep_implib_filename, &link_info);
> +      if (command_line.out_implib_filename)
> +	pep_dll_generate_implib (pep_def_file,
> +				 command_line.out_implib_filename, &link_info);
>      }
> 
>    if (pep_out_def_filename)
> diff --git a/ld/ld.h b/ld/ld.h
> index
> ab09032e455f8b64b1d8fd7cbb860d78cfd45e58..e41460fec76e3725fca0a5399e84389266
> 100f32 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..a9a2e347a1e6960406916b36506746dadc
> 557b96 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..e8c5dcbd66e84bdc2d11b4c564dd4dc7ae
> e6ca14 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..52f7198ad2ccec4a96474f2d865392657d
> 6333da 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..aede732f2b60f7af66a3ad505fb157603d
> b20755 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..297b10cce0c5ad62e2a8e8ebff0c610e91
> d83cf1 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..b123064df3f6f429c59fe204d57e57ed76
> a8d5be --- /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..9f854a59bd26054a8fdb49f6dbaac4120b
> 2c7ef1 --- /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..a86a940c138d7dd65e42c609adbe594c57
> 9061ac --- /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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH, binutils, ELF 9/11, ping1] Add support for creating import libraries
  2016-05-18 16:38   ` [PATCH, binutils, ELF 9/11, ping1] " Thomas Preudhomme
@ 2016-05-18 16:40     ` Thomas Preudhomme
  0 siblings, 0 replies; 15+ messages in thread
From: Thomas Preudhomme @ 2016-05-18 16:40 UTC (permalink / raw)
  To: binutils, richard.earnshaw, nickc

[Actually adding the Cc]

Best regards,

Thomas

On Wednesday 18 May 2016 17:38:01 Thomas Preudhomme wrote:
> [CCing Richard Earnshaw and Nick Clifton who reviewed previous ARMv8-M
> patches]
> 
> ping?
> 
> See [1][2] for previous discussion on this proposition.
> 
> [1] https://sourceware.org/ml/binutils/2016-02/msg00075.html
> [2] https://sourceware.org/ml/binutils/2016-02/msg00222.html
> 
> Best regards,
> 
> Thomas
> 
> On Tuesday 29 March 2016 15:44:38 Thomas Preudhomme wrote:
> > On Wednesday 23 December 2015 16:00:53 Thomas Preud'homme wrote:
> [removing mention of 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.
> > 
> > *** bfd/ChangeLog ***
> > 
> > 2016-02-17  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> > 
> >         * elf-bfd.h (elf_backend_filter_implib_symbols): Declare backend
> > 
> > hook. (_bfd_elf_filter_global_symbols): Declare.
> > 
> >         * elf.c (_bfd_elf_filter_global_symbols): New function.
> >         * elflink.c (elf_filter_global_symbols): Likewise.
> >         (elf_output_implib): Likewise.
> >         (bfd_elf_final_link): Call above function, failing if it does.
> >         * elfxx-target.h (elf_backend_filter_implib_symbols): Define macro
> > 
> > and default it to NULL.
> > 
> >         (elf_backend_copy_indirect_symbol): Fix spacing.
> >         (elf_backend_hide_symbol): Likewise.
> >         (elfNN_bed): Initialize elf_backend_filter_implib_symbols backend
> > 
> > hook.
> > 
> > 
> > *** include/ChangeLog ***
> > 
> > 2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> > 
> >         * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
> >         out_implib_bfd fields.
> > 
> > *** ld/ChangeLog ***
> > 
> > 2015-11-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> > 
> >         * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Open
> >         import
> >         library file for writing and initialize implib_bfd field of
> > 
> > link_info structure.
> > 
> >         * emultempl/pe.em (pe_implib_filename): Remove variable
> >         declaration.
> > 
> > (OPTION_IMPLIB_FILENAME): Remove macro definition.
> > 
> >         (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
> >         (gld_${EMULATION_NAME}_list_options): Likewise.
> >         (gld${EMULATION_NAME}_handle_option): Likewise.
> >         (gld_${EMULATION_NAME}_finish): Use
> >         command_line.out_implib_filename
> > 
> > instead of pe_implib_filename.
> > 
> >         * emultempl/pep.em (pep_implib_filename): Remove variable
> > 
> > declaration. (OPTION_IMPLIB_FILENAME): Remove enumerator.
> > 
> >         (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
> >         (gld_${EMULATION_NAME}_list_options): Likewise.
> >         (gld${EMULATION_NAME}_handle_option): Likewise.
> >         (gld_${EMULATION_NAME}_finish): Use
> >         command_line.out_implib_filename
> > 
> > instead of pep_implib_filename.
> > 
> >         * ld.h (args_type): Declare new out_implib_filename field.
> >         * ld.texinfo (--out-implib): Move documentation to
> >         arch-independent
> >         part and rephrase to apply to ELF targets.
> >         * ldexp.c (exp_fold_tree_1): Set ldscript_def field to 1 for
> >         symbols
> > 
> > defined in linker scripts.
> > 
> >         * ldlex.h (enum option_values): Declare new OPTION_OUT_IMPLIB
> >         enumerator.
> >         * lexsup.c (ld_options): Add entry for new --out-implib switch.
> >         (parse_args): Handle OPTION_OUT_IMPLIB case.
> > 
> > *** ld/testsuite/ChangeLog ***
> > 
> > 2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> > 
> >         * ld-elf/elf.exp (Generate empty import library): New test.
> >         (Generate import library): Likewise.
> >         * ld-elf/implib.s: Likewise.
> >         * ld-elf/implib.rd: New file.
> >         * ld-elf/empty-implib.out: Likewise
> > 
> > diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
> > index
> > 6a04f044e78bcbf5975ca88987feb878865cbea5..dc25569cac448e336d90dcbe6813d5a2
> > 6e 188095 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..e82a2ca1174786c3c394662f7bda5e47
> > 87 172c1b 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..7c8809f02e6abeaac288fc17ddd17ce4
> > ff 5b1bc2 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..f996885cb56ab24860ca18a4aafe1d33
> > f3 915649 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..5d772d0b8b41bdad06b9f02ff4a030c0
> > 6f e75345 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..d04a365563d3eb730f5404e906862bbc
> > fd 9f6bca 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..40980b490a89f69f42605f83798cf2c8
> > 15 437d30 100644
> > --- a/ld/emultempl/pe.em
> > +++ b/ld/emultempl/pe.em
> > @@ -138,7 +138,6 @@ static const char *emit_build_id;
> > 
> >  #ifdef DLL_SUPPORT
> >  static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable.  */
> >  static char *pe_out_def_filename = NULL;
> > 
> > -static char *pe_implib_filename = NULL;
> > 
> >  static int pe_enable_auto_image_base = 0;
> >  static unsigned long pe_auto_image_base = 0x61500000;
> >  static char *pe_dll_search_prefix = NULL;
> > 
> > @@ -228,8 +227,7 @@ fragment <<EOF
> > 
> >  #define OPTION_STDCALL_ALIASES		(OPTION_KILL_ATS + 1)
> >  #define OPTION_ENABLE_STDCALL_FIXUP	(OPTION_STDCALL_ALIASES + 1)
> >  #define OPTION_DISABLE_STDCALL_FIXUP	(OPTION_ENABLE_STDCALL_FIXUP + 1)
> > 
> > -#define OPTION_IMPLIB_FILENAME		(OPTION_DISABLE_STDCALL_FIXUP + 1)
> > -#define OPTION_THUMB_ENTRY		(OPTION_IMPLIB_FILENAME + 1)
> > +#define OPTION_THUMB_ENTRY		(OPTION_DISABLE_STDCALL_FIXUP + 1)
> > 
> >  #define OPTION_WARN_DUPLICATE_EXPORTS	(OPTION_THUMB_ENTRY + 1)
> >  #define OPTION_IMP_COMPAT		(OPTION_WARN_DUPLICATE_EXPORTS + 1)
> >  #define OPTION_ENABLE_AUTO_IMAGE_BASE	(OPTION_IMP_COMPAT + 1)
> > 
> > @@ -323,7 +321,6 @@ gld${EMULATION_NAME}_add_options
> > 
> >      {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
> >      {"enable-stdcall-fixup", no_argument, NULL,
> > 
> > OPTION_ENABLE_STDCALL_FIXUP}, {"disable-stdcall-fixup", no_argument, NULL,
> > OPTION_DISABLE_STDCALL_FIXUP},
> > -    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
> > 
> >      {"warn-duplicate-exports", no_argument, NULL,
> > 
> > OPTION_WARN_DUPLICATE_EXPORTS},
> > 
> >      /* getopt() allows abbreviations, so we do this to stop it from
> >      
> >         treating -c as an abbreviation for these --compat-implib.  */
> > 
> > @@ -461,7 +458,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
> > 
> >    fprintf (file, _("                                     export, place
> >    into
> > 
> > import library instead.\n"));
> > 
> >    fprintf (file, _("  --export-all-symbols               Automatically
> > 
> > export all globals to DLL\n"));
> > 
> >    fprintf (file, _("  --kill-at                          Remove @nn from
> > 
> > exported symbols\n"));
> > -  fprintf (file, _("  --out-implib <file>                Generate import
> > library\n"));
> > 
> >    fprintf (file, _("  --output-def <file>                Generate a .DEF
> > 
> > file for the built DLL\n"));
> > 
> >    fprintf (file, _("  --warn-duplicate-exports           Warn about
> > 
> > duplicate exports\n"));
> > 
> >    fprintf (file, _("  --compat-implib                    Create backward
> > 
> > compatible import libs;\n\
> > @@ -805,9 +801,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
> > 
> >      case OPTION_DISABLE_STDCALL_FIXUP:
> >        pe_enable_stdcall_fixup = 0;
> >        break;
> > 
> > -    case OPTION_IMPLIB_FILENAME:
> > -      pe_implib_filename = xstrdup (optarg);
> > -      break;
> > 
> >      case OPTION_WARN_DUPLICATE_EXPORTS:
> >        pe_dll_warn_dup_exports = 1;
> >        break;
> > 
> > @@ -2073,8 +2066,9 @@ gld_${EMULATION_NAME}_finish (void)
> > 
> >      )
> >      {
> >      
> >        pe_dll_fill_sections (link_info.output_bfd, &link_info);
> > 
> > -      if (pe_implib_filename)
> > -	pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info);
> > +      if (command_line.out_implib_filename)
> > +	pe_dll_generate_implib (pe_def_file, command_line.out_implib_filename,
> > +				&link_info);
> > 
> >      }
> >  
> >  #if defined(TARGET_IS_shpe)
> >  
> >    /* ARM doesn't need relocs.  */
> > 
> > diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
> > index
> > 054a98497f3c386adecd361612d4d1bbdc779049..def1a4f21737d87ca94c1c4616cc691e
> > c5 efffd0 100644
> > --- a/ld/emultempl/pep.em
> > +++ b/ld/emultempl/pep.em
> > @@ -153,7 +153,6 @@ static const char *emit_build_id;
> > 
> >  #ifdef DLL_SUPPORT
> >  static int    pep_enable_stdcall_fixup = 1; /* 0=disable 1=enable
> > 
> > (default). */
> > 
> >  static char * pep_out_def_filename = NULL;
> > 
> > -static char * pep_implib_filename = NULL;
> > 
> >  static int    pep_enable_auto_image_base = 0;
> >  static char * pep_dll_search_prefix = NULL;
> >  #endif
> > 
> > @@ -217,7 +216,6 @@ enum options
> > 
> >    OPTION_STDCALL_ALIASES,
> >    OPTION_ENABLE_STDCALL_FIXUP,
> >    OPTION_DISABLE_STDCALL_FIXUP,
> > 
> > -  OPTION_IMPLIB_FILENAME,
> > 
> >    OPTION_WARN_DUPLICATE_EXPORTS,
> >    OPTION_IMP_COMPAT,
> >    OPTION_ENABLE_AUTO_IMAGE_BASE,
> > 
> > @@ -296,7 +294,6 @@ gld${EMULATION_NAME}_add_options
> > 
> >      {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
> >      {"enable-stdcall-fixup", no_argument, NULL,
> > 
> > OPTION_ENABLE_STDCALL_FIXUP}, {"disable-stdcall-fixup", no_argument, NULL,
> > OPTION_DISABLE_STDCALL_FIXUP},
> > -    {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
> > 
> >      {"warn-duplicate-exports", no_argument, NULL,
> > 
> > OPTION_WARN_DUPLICATE_EXPORTS},
> > 
> >      /* getopt() allows abbreviations, so we do this to stop it from
> >      
> >         treating -c as an abbreviation for these --compat-implib.  */
> > 
> > @@ -427,7 +424,6 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
> > 
> >    fprintf (file, _("                                     export, place
> >    into
> > 
> > import library instead.\n"));
> > 
> >    fprintf (file, _("  --export-all-symbols               Automatically
> > 
> > export all globals to DLL\n"));
> > 
> >    fprintf (file, _("  --kill-at                          Remove @nn from
> > 
> > exported symbols\n"));
> > -  fprintf (file, _("  --out-implib <file>                Generate import
> > library\n"));
> > 
> >    fprintf (file, _("  --output-def <file>                Generate a .DEF
> > 
> > file for the built DLL\n"));
> > 
> >    fprintf (file, _("  --warn-duplicate-exports           Warn about
> > 
> > duplicate exports.\n"));
> > 
> >    fprintf (file, _("  --compat-implib                    Create backward
> > 
> > compatible import libs;\n\
> > @@ -761,9 +757,6 @@ gld${EMULATION_NAME}_handle_option (int optc)
> > 
> >      case OPTION_DISABLE_STDCALL_FIXUP:
> >        pep_enable_stdcall_fixup = 0;
> >        break;
> > 
> > -    case OPTION_IMPLIB_FILENAME:
> > -      pep_implib_filename = xstrdup (optarg);
> > -      break;
> > 
> >      case OPTION_WARN_DUPLICATE_EXPORTS:
> >        pep_dll_warn_dup_exports = 1;
> >        break;
> > 
> > @@ -1851,8 +1844,9 @@ gld_${EMULATION_NAME}_finish (void)
> > 
> >  	  && pep_def_file->num_exports != 0))
> >  	  
> >      {
> >      
> >        pep_dll_fill_sections (link_info.output_bfd, &link_info);
> > 
> > -      if (pep_implib_filename)
> > -	pep_dll_generate_implib (pep_def_file, pep_implib_filename, 
&link_info);
> > +      if (command_line.out_implib_filename)
> > +	pep_dll_generate_implib (pep_def_file,
> > +				 command_line.out_implib_filename, &link_info);
> > 
> >      }
> >    
> >    if (pep_out_def_filename)
> > 
> > diff --git a/ld/ld.h b/ld/ld.h
> > index
> > ab09032e455f8b64b1d8fd7cbb860d78cfd45e58..e41460fec76e3725fca0a5399e843892
> > 66 100f32 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..a9a2e347a1e6960406916b36506746da
> > dc 557b96 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..e8c5dcbd66e84bdc2d11b4c564dd4dc7
> > ae e6ca14 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..52f7198ad2ccec4a96474f2d86539265
> > 7d 6333da 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..aede732f2b60f7af66a3ad505fb15760
> > 3d b20755 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..297b10cce0c5ad62e2a8e8ebff0c610e
> > 91 d83cf1 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..b123064df3f6f429c59fe204d57e57ed
> > 76 a8d5be --- /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..9f854a59bd26054a8fdb49f6dbaac412
> > 0b 2c7ef1 --- /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..a86a940c138d7dd65e42c609adbe594c
> > 57 9061ac --- /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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2016-03-29 14:45 ` [RFC PATCH, binutils, ELF 9/11] " Thomas Preudhomme
  2016-05-18 16:38   ` [PATCH, binutils, ELF 9/11, ping1] " Thomas Preudhomme
@ 2016-07-07 11:01   ` Richard Earnshaw (lists)
  2016-07-07 11:48     ` Nick Clifton
  1 sibling, 1 reply; 15+ messages in thread
From: Richard Earnshaw (lists) @ 2016-07-07 11:01 UTC (permalink / raw)
  To: Thomas Preudhomme, binutils; +Cc: nickc

On 29/03/16 15:44, Thomas Preudhomme wrote:
> On Wednesday 23 December 2015 16:00:53 Thomas Preud'homme wrote:
>> Hi,
>>
>> [Posting patch series as RFC]
>>
>> This patch is part of a patch series to add support for ARMv8-M security
>> extension[1] to GNU ld. This specific patch adds target-independent support
>> for creating generic import library.
>>
>> One common development model for embedded devices is for ROM functions to be
>> bundled in such devices and application developers calling these functions
>> to interact with the device. In such cases, a way is needed for the
>> application to know the addresses of the ROM functions. One convenient
>> mechanism is to create a so called import library that application
>> developers can link against. Such a library can already be created with
>> objcopy --extract-symbol but this means it is done as a separate step than
>> linking.
>>
>> This patch extend the --out-implib switch from i386 PE backend to all ELF
>> backends. This switch specifies a file where an import library should be
>> created. The library is an object file containing no code or data section
>> but just a symbol table with all symbols being absolute. By default, all
>> global symbols in the output file are copied into the import library but
>> target backend can apply different filters as they see fit, for instance
>> when extra switches are supplied by the user.
>>
>>
>> [1] Software requirements for ARMv8-M security extension are described in
>> document ARM-ECM-0359818 [2] [2] Available on http://infocenter.arm.com in
>> Developer guides and articles > Software development > ARM®v8-M Security
>> Extensions: Requirements on Development Tools
> 
> Please find an updated patch below.
> 

This looks sensible to me (it's mostly just refactoring existing code to
make it available on multiple platforms).  But since it touches generic
code it needs Nick's approval.

R.


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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2016-07-07 11:01   ` [RFC PATCH, binutils, ELF 9/11] " Richard Earnshaw (lists)
@ 2016-07-07 11:48     ` Nick Clifton
  2016-07-07 14:26       ` Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Nick Clifton @ 2016-07-07 11:48 UTC (permalink / raw)
  To: Richard Earnshaw (lists), Thomas Preudhomme; +Cc: binutils

Hi Thomas,

>> Please find an updated patch below.

>> *** bfd/ChangeLog ***
>>
>> 2016-02-17  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>
>>         * elf-bfd.h (elf_backend_filter_implib_symbols): Declare backend hook.
>>         (_bfd_elf_filter_global_symbols): Declare.
>>         * elf.c (_bfd_elf_filter_global_symbols): New function.
>>         * elflink.c (elf_filter_global_symbols): Likewise.
>>         (elf_output_implib): Likewise.
>>         (bfd_elf_final_link): Call above function, failing if it does.
>>         * elfxx-target.h (elf_backend_filter_implib_symbols): Define macro and
>>         default it to NULL.
>>         (elf_backend_copy_indirect_symbol): Fix spacing.
>>         (elf_backend_hide_symbol): Likewise.
>>         (elfNN_bed): Initialize elf_backend_filter_implib_symbols backend hook.
>>
>>
>> *** include/ChangeLog ***
>>
>> 2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>
>>         * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
>>         out_implib_bfd fields.
>>
>>
>> *** ld/ChangeLog ***
>>
>> 2015-11-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>
>>         * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Open import
>>         library file for writing and initialize implib_bfd field of link_info
>>         structure.
>>         * emultempl/pe.em (pe_implib_filename): Remove variable declaration.
>>         (OPTION_IMPLIB_FILENAME): Remove macro definition.
>>         (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
>>         (gld_${EMULATION_NAME}_list_options): Likewise.
>>         (gld${EMULATION_NAME}_handle_option): Likewise.
>>         (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
>>         instead of pe_implib_filename.
>>         * emultempl/pep.em (pep_implib_filename): Remove variable declaration.
>>         (OPTION_IMPLIB_FILENAME): Remove enumerator.
>>         (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
>>         (gld_${EMULATION_NAME}_list_options): Likewise.
>>         (gld${EMULATION_NAME}_handle_option): Likewise.
>>         (gld_${EMULATION_NAME}_finish): Use command_line.out_implib_filename
>>         instead of pep_implib_filename.
>>         * ld.h (args_type): Declare new out_implib_filename field.
>>         * ld.texinfo (--out-implib): Move documentation to arch-independent
>>         part and rephrase to apply to ELF targets.
>>         * ldexp.c (exp_fold_tree_1): Set ldscript_def field to 1 for symbols
>>         defined in linker scripts.
>>         * ldlex.h (enum option_values): Declare new OPTION_OUT_IMPLIB
>>         enumerator.
>>         * lexsup.c (ld_options): Add entry for new --out-implib switch.
>>         (parse_args): Handle OPTION_OUT_IMPLIB case.
>>
>>
>> *** ld/testsuite/ChangeLog ***
>>
>> 2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>
>>         * ld-elf/elf.exp (Generate empty import library): New test.
>>         (Generate import library): Likewise.
>>         * ld-elf/implib.s: Likewise.
>>         * ld-elf/implib.rd: New file.
>>         * ld-elf/empty-implib.out: Likewise
>>

Approved - please apply - but please could you add a line to the ld/NEWS 
file mentioning the new feature.

Also - I suspect that you will want this patch to go in to the 2.27 
release.  The decision is up to Tristan, but I would urge that it be
delayed until 2.28 as I think that it needs some time to bed-in, so to
speak.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2016-07-07 11:48     ` Nick Clifton
@ 2016-07-07 14:26       ` Thomas Preudhomme
       [not found]         ` <14263055.eCW0WH2dUv@e108577-lin>
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-07-07 14:26 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Richard Earnshaw (lists), binutils

On Thursday 07 July 2016 12:48:31 Nick Clifton wrote:
> Hi Thomas,
> 
> >> Please find an updated patch below.
> >> 
> >> *** bfd/ChangeLog ***
> >> 
> >> 2016-02-17  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> >> 
> >>         * elf-bfd.h (elf_backend_filter_implib_symbols): Declare backend
> >>         hook.
> >>         (_bfd_elf_filter_global_symbols): Declare.
> >>         * elf.c (_bfd_elf_filter_global_symbols): New function.
> >>         * elflink.c (elf_filter_global_symbols): Likewise.
> >>         (elf_output_implib): Likewise.
> >>         (bfd_elf_final_link): Call above function, failing if it does.
> >>         * elfxx-target.h (elf_backend_filter_implib_symbols): Define
> >>         macro and
> >>         default it to NULL.
> >>         (elf_backend_copy_indirect_symbol): Fix spacing.
> >>         (elf_backend_hide_symbol): Likewise.
> >>         (elfNN_bed): Initialize elf_backend_filter_implib_symbols backend
> >>         hook.
> >> 
> >> *** include/ChangeLog ***
> >> 
> >> 2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> >> 
> >>         * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
> >>         out_implib_bfd fields.
> >> 
> >> *** ld/ChangeLog ***
> >> 
> >> 2015-11-02  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> >> 
> >>         * emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Open
> >>         import
> >>         library file for writing and initialize implib_bfd field of
> >>         link_info
> >>         structure.
> >>         * emultempl/pe.em (pe_implib_filename): Remove variable
> >>         declaration.
> >>         (OPTION_IMPLIB_FILENAME): Remove macro definition.
> >>         (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
> >>         (gld_${EMULATION_NAME}_list_options): Likewise.
> >>         (gld${EMULATION_NAME}_handle_option): Likewise.
> >>         (gld_${EMULATION_NAME}_finish): Use
> >>         command_line.out_implib_filename
> >>         instead of pe_implib_filename.
> >>         * emultempl/pep.em (pep_implib_filename): Remove variable
> >>         declaration.
> >>         (OPTION_IMPLIB_FILENAME): Remove enumerator.
> >>         (gld${EMULATION_NAME}_add_options): Remove --out-implib option.
> >>         (gld_${EMULATION_NAME}_list_options): Likewise.
> >>         (gld${EMULATION_NAME}_handle_option): Likewise.
> >>         (gld_${EMULATION_NAME}_finish): Use
> >>         command_line.out_implib_filename
> >>         instead of pep_implib_filename.
> >>         * ld.h (args_type): Declare new out_implib_filename field.
> >>         * ld.texinfo (--out-implib): Move documentation to
> >>         arch-independent
> >>         part and rephrase to apply to ELF targets.
> >>         * ldexp.c (exp_fold_tree_1): Set ldscript_def field to 1 for
> >>         symbols
> >>         defined in linker scripts.
> >>         * ldlex.h (enum option_values): Declare new OPTION_OUT_IMPLIB
> >>         enumerator.
> >>         * lexsup.c (ld_options): Add entry for new --out-implib switch.
> >>         (parse_args): Handle OPTION_OUT_IMPLIB case.
> >> 
> >> *** ld/testsuite/ChangeLog ***
> >> 
> >> 2015-10-30  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> >> 
> >>         * ld-elf/elf.exp (Generate empty import library): New test.
> >>         (Generate import library): Likewise.
> >>         * ld-elf/implib.s: Likewise.
> >>         * ld-elf/implib.rd: New file.
> >>         * ld-elf/empty-implib.out: Likewise
> 
> Approved - please apply - but please could you add a line to the ld/NEWS
> file mentioning the new feature.

Sure, will do.

> 
> Also - I suspect that you will want this patch to go in to the 2.27
> release.  The decision is up to Tristan, but I would urge that it be
> delayed until 2.28 as I think that it needs some time to bed-in, so to
> speak.

Absolutely, I agree. I'll post an updated patch with a NEWS entry against 
current trunk but will wait for 2.27 to be released before applying it. 
Therefore don't worry if you see the NEWS entry in the 2.27 section, I'll 
rebase it once 2.27 is out.

Thanks Richard and Nick for the review.

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
       [not found]         ` <14263055.eCW0WH2dUv@e108577-lin>
@ 2016-07-14 10:38           ` Nick Clifton
       [not found]             ` <4727760.r7lFBcU4UC@e108577-lin>
  0 siblings, 1 reply; 15+ messages in thread
From: Nick Clifton @ 2016-07-14 10:38 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: Richard Earnshaw (lists), binutils

Hi Thomas,

> What do you think of the NEWS entry in the updated patch (the NEWS entry is 
> the only change)? 

It is invisible. :-)  [I think that you might have forgotten to include it in the patch...]


> As said previously, I'll wait for 2.28 to commit.

There is no need to wait.  The 2.27 branch has already been made, so any commits
made to the mainline will not affect the 2.27 release.

Cheers
  Nick

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
       [not found]             ` <4727760.r7lFBcU4UC@e108577-lin>
@ 2016-07-14 13:41               ` Nick Clifton
  2016-07-14 15:30                 ` Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Nick Clifton @ 2016-07-14 13:41 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: Richard Earnshaw (lists), binutils

Hi Thomas,

> +* Add support for creating an ELF import library when generating an executable.
> +  The import library can then be used by applications to link against the
> +  generated executable.  The existing --out-implib option is now available to
> +  ELF targets for that purpose.

Not to be a pedant, but to me that paragraph implies that "--out-implib" is the 
option to be used when an application wants to link against an import library,
rather than the option to be used when creating an import library.

How about this slight rewording ?

 * 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.

Cheers
  Nick

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2016-07-14 13:41               ` Nick Clifton
@ 2016-07-14 15:30                 ` Thomas Preudhomme
  2016-07-14 16:08                   ` Nick Clifton
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-07-14 15:30 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Richard Earnshaw (lists), binutils

On Thursday 14 July 2016 14:41:10 Nick Clifton wrote:
> Hi Thomas,
> 
> > +* Add support for creating an ELF import library when generating an
> > executable. +  The import library can then be used by applications to
> > link against the +  generated executable.  The existing --out-implib
> > option is now available to +  ELF targets for that purpose.
> 
> Not to be a pedant, but to me that paragraph implies that "--out-implib" is
> the option to be used when an application wants to link against an import
> library, rather than the option to be used when creating an import library.
> 
> How about this slight rewording ?
> 
>  * 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.

Looks good, thanks.

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2016-07-14 15:30                 ` Thomas Preudhomme
@ 2016-07-14 16:08                   ` Nick Clifton
  2016-07-15 16:52                     ` Thomas Preudhomme
  0 siblings, 1 reply; 15+ messages in thread
From: Nick Clifton @ 2016-07-14 16:08 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: Richard Earnshaw (lists), binutils

Hi Thomas,

> Looks good, thanks.

OK then - please go ahead and apply the patch if you have not already done so.

Cheers
  Nick

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2016-07-14 16:08                   ` Nick Clifton
@ 2016-07-15 16:52                     ` Thomas Preudhomme
  2016-07-16 13:39                       ` Alan Modra
  0 siblings, 1 reply; 15+ messages in thread
From: Thomas Preudhomme @ 2016-07-15 16:52 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Richard Earnshaw (lists), binutils

On Thursday 14 July 2016 17:08:10 Nick Clifton wrote:
> Hi Thomas,
> 
> > Looks good, thanks.
> 
> OK then - please go ahead and apply the patch if you have not already done
> so.

Committed.

Thanks,

Thomas

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2016-07-15 16:52                     ` Thomas Preudhomme
@ 2016-07-16 13:39                       ` Alan Modra
       [not found]                         ` <20406296.IDmVSFSBlq@e108577-lin>
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Modra @ 2016-07-16 13:39 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: Nick Clifton, Richard Earnshaw (lists), binutils

On Fri, Jul 15, 2016 at 05:51:57PM +0100, Thomas Preudhomme wrote:
> On Thursday 14 July 2016 17:08:10 Nick Clifton wrote:
> > Hi Thomas,
> > 
> > > Looks good, thanks.
> > 
> > OK then - please go ahead and apply the patch if you have not already done
> > so.
> 
> Committed.

alpha-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
alpha-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
alpha-netbsd  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
alpha-netbsd  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
alpha-unknown-freebsd4.7  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
alpha-unknown-freebsd4.7  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
am33_2.0-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
am33_2.0-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
arc-linux-uclibc  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
arc-linux-uclibc  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
avr-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
avr-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
bfin-elf  +FAIL: Generate import library
cr16-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
cr16-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
cris-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
cris-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
crisv32-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
crisv32-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
crx-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
crx-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
d10v-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
d10v-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
d30v-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
d30v-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
dlx-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
dlx-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
epiphany-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
epiphany-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
fr30-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
fr30-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
frv-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
frv-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
frv-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
frv-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
ft32-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
ft32-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
h8300-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
h8300-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
hppa64-hp-hpux11.23  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
hppa64-hp-hpux11.23  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
hppa64-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
hppa64-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
hppa-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
hppa-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
i370-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
i370-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
i860-stardent-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
i860-stardent-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
i960-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
i960-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
ip2k-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
ip2k-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
iq2000-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
iq2000-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
lm32-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
lm32-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
m32r-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
m32r-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
m68hc11-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
m68hc11-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
m68hc12-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
m68hc12-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
m68k-elf  +FAIL: Generate import library
m68k-linux  +FAIL: Generate import library
mcore-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
mcore-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
mep-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
mep-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
metag-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
metag-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
microblaze-elf  +FAIL: Generate import library
mips64-linux  +FAIL: Generate import library
mipsel-linux-gnu  +FAIL: Generate import library
mipsisa32el-linux  +FAIL: Generate import library
mips-linux  +FAIL: Generate import library
mipstx39-elf  +FAIL: Generate empty import library
mipstx39-elf  +FAIL: Generate import library
mn10200-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
mn10200-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
mn10300-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
mn10300-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
moxie-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
moxie-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
ms1-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
ms1-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
msp430-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
msp430-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
nds32le-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
nds32le-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
nios2-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
nios2-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
or1k-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
or1k-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
pj-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
pj-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc64le-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc64le-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc64-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc64-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc-eabisim  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc-eabisim  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc-eabivle  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc-eabivle  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpcle-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpcle-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
powerpc-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
s390-linux  +FAIL: Generate import library
s390x-linux  +FAIL: Generate import library
sh-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
sh-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
shl-unknown-netbsdelf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
shl-unknown-netbsdelf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
sh-rtems  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
sh-rtems  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
sparc64-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
sparc64-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
sparc-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
sparc-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
spu-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
spu-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
tic6x-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
tic6x-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
tilegx-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
tilegx-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
tilepro-linux  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
tilepro-linux  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
vax-netbsdelf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
vax-netbsdelf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
visium-elf  +FAIL: Generate import library
xgate-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
xgate-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
xstormy16-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
xstormy16-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
xtensa-elf  +ERROR: --defsym NO_GLOBAL=1 /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed
xtensa-elf  +ERROR:  /home/alan/src/binutils-gdb/ld/testsuite/ld-elf/implib.s: assembly failed

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
       [not found]                         ` <20406296.IDmVSFSBlq@e108577-lin>
@ 2016-07-18 10:31                           ` Alan Modra
  2016-07-18 11:00                             ` Nick Clifton
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Modra @ 2016-07-18 10:31 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: Nick Clifton, Richard Earnshaw (lists), binutils

On Mon, Jul 18, 2016 at 09:04:02AM +0100, Thomas Preudhomme wrote:
> Oh wow, I feel real bad now. I did test on x86 and ARM, I guess it wasn't 
> enough. So the problem is .bss which I should replace by .section .bss. Now 
> there is also the issue of the default linker script.

Yes, and some targets don't like -Tdata at the address you chose, so
you need at least the attached.  There are other issues too.

- The testsuite needs modifying to exclude some targets.  Not all ELF
targets use elflink.c:bfd_elf_final_link.  There are some that instead
use _bfd_generic_final_link.  (See elfxx-target.h)

- Missing bfd_set_error on "no symbol found for import library" error
path.

- mipstx39-elf segfault.

diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index 832f313..7220813 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -145,7 +145,7 @@ run_ld_link_tests {
      {{ld empty-implib.out}}
      "implib"}
     {"Generate import library"
-     "-Tdata=0x1000 --out-implib=tmpdir/implib.lib" ""
+     "--out-implib=tmpdir/implib.lib" ""
      ""
      {implib.s}
      {{readelf {-s tmpdir/implib.lib} implib.rd}}
diff --git a/ld/testsuite/ld-elf/empty-implib.out b/ld/testsuite/ld-elf/empty-implib.out
index b123064..cc6a9f4 100644
--- a/ld/testsuite/ld-elf/empty-implib.out
+++ b/ld/testsuite/ld-elf/empty-implib.out
@@ -1,2 +1,3 @@
 .*: .*: 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
index 9f854a5..6835f39 100644
--- a/ld/testsuite/ld-elf/implib.rd
+++ b/ld/testsuite/ld-elf/implib.rd
@@ -1,10 +1,10 @@
-File: tmpdir/implib.lib
+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
+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-9a-f]+ +1 OBJECT +GLOBAL DEFAULT +ABS exported1
+ +2: [0-9a-f]+ +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
index a86a940..e4d527b 100644
--- a/ld/testsuite/ld-elf/implib.s
+++ b/ld/testsuite/ld-elf/implib.s
@@ -1,5 +1,4 @@
 .ifndef NO_GLOBAL
-	.bss
 	.comm	exported1,1
 
 	.data
@@ -10,7 +9,7 @@ exported2:
 	.byte	21
 .endif
 
-	.bss
+	.section ".bss", "aw", %nobits
 not_exported1:
 	.space	1
 	.size	not_exported1, 1

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH, binutils, ELF 9/11] Add support for creating import libraries
  2016-07-18 10:31                           ` Alan Modra
@ 2016-07-18 11:00                             ` Nick Clifton
  0 siblings, 0 replies; 15+ messages in thread
From: Nick Clifton @ 2016-07-18 11:00 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: Alan Modra, Richard Earnshaw (lists), binutils

[-- Attachment #1: Type: text/plain, Size: 451 bytes --]

Hi Thomas,

> - mipstx39-elf segfault.

The attached patch should fix this particular problem.  Plus stop an assertion
from triggering in the dlx target.  Please consider including this in your full 
patch to fix the other problems.

Cheers
  Nick

PS.  Sorry for not testing your patch locally before approving.  I looked over
  the new tests and they looked fine to me, but obviously I missed the problems
  that they would cause for some targets.


[-- Attachment #2: elf.c.patch --]
[-- Type: text/x-patch, Size: 1213 bytes --]

diff --git a/bfd/elf.c b/bfd/elf.c
index ebcf40a..2d5f69c 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3893,9 +3893,10 @@ _bfd_elf_filter_global_symbols (bfd *abfd, struct bfd_link_info *info,
 	continue;
 
       h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE);
+      if (h == NULL)
+	continue;
       if (h->type != bfd_link_hash_defined && h->type != bfd_link_hash_defweak)
 	continue;
-
       if (h->linker_def || h->ldscript_def)
 	continue;
 
@@ -7641,7 +7642,9 @@ error_return:
 		     section of a symbol to be a section that is
 		     actually in the output file.  */
 		  sec2 = bfd_get_section_by_name (abfd, sec->name);
-		  if (sec2 == NULL)
+		  if (sec2 != NULL)
+		    shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
+		  if (shndx == SHN_BAD)
 		    {
 		      _bfd_error_handler (_("\
 Unable to find equivalent output section for symbol '%s' from section '%s'"),
@@ -7650,9 +7653,6 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
 		      bfd_set_error (bfd_error_invalid_operation);
 		      goto error_return;
 		    }
-
-		  shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
-		  BFD_ASSERT (shndx != SHN_BAD);
 		}
 	    }
 

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-07-18 11:00 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-23  8:01 [RFC PATCH, binutils, ARM 7/9] Add support for creating import libraries Thomas Preud'homme
2016-03-29 14:45 ` [RFC PATCH, binutils, ELF 9/11] " Thomas Preudhomme
2016-05-18 16:38   ` [PATCH, binutils, ELF 9/11, ping1] " Thomas Preudhomme
2016-05-18 16:40     ` Thomas Preudhomme
2016-07-07 11:01   ` [RFC PATCH, binutils, ELF 9/11] " Richard Earnshaw (lists)
2016-07-07 11:48     ` Nick Clifton
2016-07-07 14:26       ` Thomas Preudhomme
     [not found]         ` <14263055.eCW0WH2dUv@e108577-lin>
2016-07-14 10:38           ` Nick Clifton
     [not found]             ` <4727760.r7lFBcU4UC@e108577-lin>
2016-07-14 13:41               ` Nick Clifton
2016-07-14 15:30                 ` Thomas Preudhomme
2016-07-14 16:08                   ` Nick Clifton
2016-07-15 16:52                     ` Thomas Preudhomme
2016-07-16 13:39                       ` Alan Modra
     [not found]                         ` <20406296.IDmVSFSBlq@e108577-lin>
2016-07-18 10:31                           ` Alan Modra
2016-07-18 11:00                             ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).