* NEWS: Mention new feature --exclude-modules-for-implib.
authorDave Korn <dave.korn@artimi.com>
Sat, 3 Jan 2009 18:04:16 +0000 (18:04 +0000)
committerDave Korn <dave.korn@artimi.com>
Sat, 3 Jan 2009 18:04:16 +0000 (18:04 +0000)
* ld.texinfo:  Document new --exclude-modules-for-implib option.
* pe-dll.c (exclude_list_struct):  Change type member from int to
new enumeration exclude_type.
(pe_dll_add_excludes):  Accept exclude_type instead of int param.
(auto_export):  Replace magic constants by exclude_type values and
handle new choice EXCLUDEFORIMPLIB.
(pe_dll_generate_implib):  Accept a pointer to the link_info and
iterate all input BFDs looking for EXCLUDEFORIMPLIB modules; re-open
fresh BFDs for any found and link into import lib archive chain.
* pe-dll.h (exclude_type):  Add new enumerated type to replace magic
constants previously used for exclude_list_struct type member.
(pe_dll_add_excludes, pe_dll_generate_implib):  Update prototypes.
* pep-dll.h (exclude_type, pe_dll_add_excludes,
pe_dll_generate_implib):  Likewise to all the above.
* emultempl/pe.em (OPTION_EXCLUDE_MODULES_FOR_IMPLIB):  Define new
getopts long option code for new --exclude-modules-for-implib option.
(gld${EMULATION_NAME}_add_options):  Add new entry to xtra_long[].
(gld_${EMULATION_NAME}_list_options):  List usage for it.
(gld${EMULATION_NAME}_handle_option):  Use exclude_type enumerated
values when calling pe_dll_add_excludes, and handle EXCLUDEFORIMPLIB.
(gld_${EMULATION_NAME}_finish):  Pass pointer to link_info when
calling pe_dll_generate_implib.
* emultempl/pep.em (options):  Define new enumerated value for getopts
long option code for new --exclude-modules-for-implib option.
(gld${EMULATION_NAME}_add_options, gld_${EMULATION_NAME}_list_options,
gld${EMULATION_NAME}_handle_option, gld_${EMULATION_NAME}_finish):
Again, likewise to all the above.

ld/ChangeLog
ld/NEWS
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/ld.texinfo
ld/pe-dll.c
ld/pe-dll.h
ld/pep-dll.h

index 531b8a70e99b9c08e59352bfabeb7f21f7481651..b7a94857afe242fad88cd613cc5f25cb864d8961 100644 (file)
@@ -1,3 +1,34 @@
+2009-01-03  Dave Korn  <dave.korn.cygwin@gmail.com>
+
+       * NEWS:  Mention new feature --exclude-modules-for-implib.
+       * ld.texinfo:  Document new --exclude-modules-for-implib option.
+       * pe-dll.c (exclude_list_struct):  Change type member from int to
+       new enumeration exclude_type.
+       (pe_dll_add_excludes):  Accept exclude_type instead of int param.
+       (auto_export):  Replace magic constants by exclude_type values and
+       handle new choice EXCLUDEFORIMPLIB.
+       (pe_dll_generate_implib):  Accept a pointer to the link_info and
+       iterate all input BFDs looking for EXCLUDEFORIMPLIB modules; re-open
+       fresh BFDs for any found and link into import lib archive chain.
+       * pe-dll.h (exclude_type):  Add new enumerated type to replace magic
+       constants previously used for exclude_list_struct type member.
+       (pe_dll_add_excludes, pe_dll_generate_implib):  Update prototypes.
+       * pep-dll.h (exclude_type, pe_dll_add_excludes,
+       pe_dll_generate_implib):  Likewise to all the above.
+       * emultempl/pe.em (OPTION_EXCLUDE_MODULES_FOR_IMPLIB):  Define new
+       getopts long option code for new --exclude-modules-for-implib option.
+       (gld${EMULATION_NAME}_add_options):  Add new entry to xtra_long[].
+       (gld_${EMULATION_NAME}_list_options):  List usage for it.
+       (gld${EMULATION_NAME}_handle_option):  Use exclude_type enumerated
+       values when calling pe_dll_add_excludes, and handle EXCLUDEFORIMPLIB.
+       (gld_${EMULATION_NAME}_finish):  Pass pointer to link_info when
+       calling pe_dll_generate_implib.
+       * emultempl/pep.em (options):  Define new enumerated value for getopts
+       long option code for new --exclude-modules-for-implib option.
+       (gld${EMULATION_NAME}_add_options, gld_${EMULATION_NAME}_list_options,
+       gld${EMULATION_NAME}_handle_option, gld_${EMULATION_NAME}_finish):
+       Again, likewise to all the above.
+
 2009-01-03  Dave Korn  <dave.korn.cygwin@gmail.com>
 
        * pe-dll.c (autofilter_liblist):  Add entry for shared libgcc.
diff --git a/ld/NEWS b/ld/NEWS
index 35c993704a658852e3f509ef3807e8ed27ad35e0..9bf378064ac133469db7f1e5e0be659d19c08839 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,4 +1,8 @@
 -*- text -*-
+* Windows PE systems now support a new --exclude-modules-for-implib option,
+  allowing users to partition object files and archive members between a DLL
+  and its associated import library as they are generated during linking.
+
 * Add support for Lattice Mico32 (lm32) architecture.
 
 * Add CR16 ELF --embedded-relocs (used to embedded relocations into binaries 
index 43c0be348f372df8e4aa7e29ec60f556f593ffb7..f902812b176a325f0e51a6150cb69e6b542b53ae 100644 (file)
@@ -207,6 +207,8 @@ gld_${EMULATION_NAME}_before_parse (void)
                                        (OPTION_LARGE_ADDRESS_AWARE + 1)
 #define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2      \
                                        (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1 + 1)
+#define OPTION_EXCLUDE_MODULES_FOR_IMPLIB \
+                                       (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2 + 1)
 
 static void
 gld${EMULATION_NAME}_add_options
@@ -240,6 +242,7 @@ gld${EMULATION_NAME}_add_options
     {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
     {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
     {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+    {"exclude-modules-for-implib", required_argument, NULL, OPTION_EXCLUDE_MODULES_FOR_IMPLIB},
     {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
     {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
     {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
@@ -341,6 +344,9 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
   fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
   fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
   fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));
+  fprintf (file, _("  --exclude-modules-for-implib mod,mod,...\n"));
+  fprintf (file, _("                                     Exclude objects, archive members from auto\n"));
+  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"));
@@ -598,10 +604,13 @@ gld${EMULATION_NAME}_handle_option (int optc)
       pe_dll_export_everything = 1;
       break;
     case OPTION_EXCLUDE_SYMBOLS:
-      pe_dll_add_excludes (optarg, 0);
+      pe_dll_add_excludes (optarg, EXCLUDESYMS);
       break;
     case OPTION_EXCLUDE_LIBS:
-      pe_dll_add_excludes (optarg, 1);
+      pe_dll_add_excludes (optarg, EXCLUDELIBS);
+      break;
+    case OPTION_EXCLUDE_MODULES_FOR_IMPLIB:
+      pe_dll_add_excludes (optarg, EXCLUDEFORIMPLIB);
       break;
     case OPTION_KILL_ATS:
       pe_dll_kill_ats = 1;
@@ -1584,7 +1593,7 @@ 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);
+       pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info);
     }
 #if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe)
   /* ARM doesn't need relocs.  */
index 35fd6e0924fa0f5a84579f94c53e1574afdb7e77..721fc23d5503fd8a4f8fb875c0e706dfe0af4762 100644 (file)
@@ -175,7 +175,8 @@ enum options
   OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC,
   OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC,
   OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1,
-  OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2
+  OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2,
+  OPTION_EXCLUDE_MODULES_FOR_IMPLIB
 };
 
 static void
@@ -213,6 +214,7 @@ gld${EMULATION_NAME}_add_options
     {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
     {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
     {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
+    {"exclude-modules-for-implib", required_argument, NULL, OPTION_EXCLUDE_MODULES_FOR_IMPLIB},
     {"kill-at", no_argument, NULL, OPTION_KILL_ATS},
     {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
     {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
@@ -307,6 +309,9 @@ gld_${EMULATION_NAME}_list_options (FILE *file)
   fprintf (file, _("  --enable-stdcall-fixup             Link _sym to _sym@nn without warnings\n"));
   fprintf (file, _("  --exclude-symbols sym,sym,...      Exclude symbols from automatic export\n"));
   fprintf (file, _("  --exclude-libs lib,lib,...         Exclude libraries from automatic export\n"));
+  fprintf (file, _("  --exclude-modules-for-implib mod,mod,...\n"));
+  fprintf (file, _("                                     Exclude objects, archive members from auto\n"));
+  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"));
@@ -559,10 +564,13 @@ gld${EMULATION_NAME}_handle_option (int optc)
       pep_dll_export_everything = 1;
       break;
     case OPTION_EXCLUDE_SYMBOLS:
-      pep_dll_add_excludes (optarg, 0);
+      pep_dll_add_excludes (optarg, EXCLUDESYMS);
       break;
     case OPTION_EXCLUDE_LIBS:
-      pep_dll_add_excludes (optarg, 1);
+      pep_dll_add_excludes (optarg, EXCLUDELIBS);
+      break;
+    case OPTION_EXCLUDE_MODULES_FOR_IMPLIB:
+      pep_dll_add_excludes (optarg, EXCLUDEFORIMPLIB);
       break;
     case OPTION_KILL_ATS:
       pep_dll_kill_ats = 1;
@@ -1386,7 +1394,7 @@ gld_${EMULATION_NAME}_finish (void)
     {
       pep_dll_fill_sections (link_info.output_bfd, &link_info);
       if (pep_implib_filename)
-       pep_dll_generate_implib (pep_def_file, pep_implib_filename);
+       pep_dll_generate_implib (pep_def_file, pep_implib_filename, &link_info);
     }
 
   if (pep_out_def_filename)
index 4e8cf8a6f82636013cb405b13ea50bca6a393f30..11bde2936fd32205335e0bcbedde70c4df50fd7d 100644 (file)
@@ -457,7 +457,7 @@ and other ways of specifying the entry point.
 @kindex --exclude-libs
 @item --exclude-libs @var{lib},@var{lib},...
 Specifies a list of archive libraries from which symbols should not be automatically
-exported. The library names may be delimited by commas or colons.  Specifying
+exported.  The library names may be delimited by commas or colons.  Specifying
 @code{--exclude-libs ALL} excludes symbols in all archive libraries from
 automatic export.  This option is available only for the i386 PE targeted
 port of the linker and for ELF targeted ports.  For i386 PE, symbols
@@ -465,6 +465,19 @@ explicitly listed in a .def file are still exported, regardless of this
 option.  For ELF targeted ports, symbols affected by this option will
 be treated as hidden.
 
+@kindex --exclude-modules-for-implib
+@item --exclude-modules-for-implib @var{module},@var{module},...
+Specifies a list of object files or archive members, from which symbols
+should not be automatically exported, but which should be copied wholesale
+into the import library being generated during the link.  The module names
+may be delimited by commas or colons, and must match exactly the filenames
+used by @command{ld} to open the files; for archive members, this is simply
+the member name, but for object files the name listed must include and
+match precisely any path used to specify the input file on the linker's
+command-line.  This option is available only for the i386 PE targeted port
+of the linker.  Symbols explicitly listed in a .def file are still exported,
+regardless of this option.
+
 @cindex dynamic symbol table
 @kindex -E
 @kindex --export-dynamic
@@ -6232,6 +6245,7 @@ which is controlled by the following command line options:
 @item --export-all-symbols   [This is the default]
 @item --exclude-symbols
 @item --exclude-libs
+@item --exclude-modules-for-implib
 @end itemize
 
 If, however, @samp{--export-all-symbols} is not given explicitly on the
index de43e34329592ee4a0ee518540df738e7c1fdc79..d76d0cfc34930e1ff91c01207e886e3b64654862 100644 (file)
@@ -463,14 +463,14 @@ typedef struct exclude_list_struct
   {
     char *string;
     struct exclude_list_struct *next;
-    int type;
+    exclude_type type;
   }
 exclude_list_struct;
 
 static struct exclude_list_struct *excludes = 0;
 
 void
-pe_dll_add_excludes (const char *new_excludes, const int type)
+pe_dll_add_excludes (const char *new_excludes, const exclude_type type)
 {
   char *local_copy;
   char *exclude_string;
@@ -593,13 +593,18 @@ auto_export (bfd *abfd, def_file *d, const char *n)
 
   for (ex = excludes; ex; ex = ex->next)
     {
-      if (ex->type == 1) /* exclude-libs */
+      if (ex->type == EXCLUDELIBS)
        {
          if (libname
              && ((strcmp (libname, ex->string) == 0)
                   || (strcasecmp ("ALL", ex->string) == 0)))
            return 0;
        }
+      else if (ex->type == EXCLUDEFORIMPLIB)
+       {
+         if (strcmp (abfd->filename, ex->string) == 0)
+           return 0;
+       }
       else if (strcmp (n, ex->string) == 0)
        return 0;
     }
@@ -2480,12 +2485,13 @@ pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend)
 
 
 void
-pe_dll_generate_implib (def_file *def, const char *impfilename)
+pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_info *info)
 {
   int i;
   bfd *ar_head;
   bfd *ar_tail;
   bfd *outarch;
+  bfd *ibfd;
   bfd *head = 0;
 
   dll_filename = (def->name) ? def->name : dll_name;
@@ -2514,6 +2520,61 @@ pe_dll_generate_implib (def_file *def, const char *impfilename)
   /* Work out a reasonable size of things to put onto one line.  */
   ar_head = make_head (outarch);
 
+  /* Iterate the input BFDs, looking for exclude-modules-for-implib.  */
+  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
+    {
+      /* Iterate the exclude list.  */
+      struct exclude_list_struct *ex;
+      char found;
+      for (ex = excludes, found = 0; ex && !found; ex = ex->next)
+       {
+         if (ex->type != EXCLUDEFORIMPLIB)
+           continue;
+         found = (strcmp (ex->string, ibfd->filename) == 0);
+       }
+      /* If it matched, we must open a fresh BFD for it (the original
+        input BFD is still needed for the DLL's final link) and add
+       it into the archive member chain.  */
+      if (found)
+       {
+         bfd *newbfd = bfd_openr (ibfd->my_archive 
+               ? ibfd->my_archive->filename : ibfd->filename, NULL);
+         if (!newbfd)
+           {
+             einfo (_("%Xbfd_openr %s: %E\n"), ibfd->filename);
+             return;
+           }
+         if (ibfd->my_archive)
+           {
+             /* Must now iterate through archive until we find the
+               required member.  A minor shame that we'll open the
+               archive once per member that we require from it, and
+               leak those archive bfds rather than reuse them.  */
+             bfd *arbfd = newbfd;
+             if (!bfd_check_format_matches (arbfd, bfd_archive, NULL))
+               {
+                 einfo (_("%X%s(%s): can't find member in non-archive file"), 
+                   ibfd->my_archive->filename, ibfd->filename);
+                 return;
+               }
+             newbfd = NULL;
+             while ((newbfd = bfd_openr_next_archived_file (arbfd, newbfd)) != 0)
+               {
+                 if (strcmp (newbfd->filename, ibfd->filename) == 0)
+                   break;
+               }
+             if (!newbfd)
+               {
+                 einfo (_("%X%s(%s): can't find member in archive"), 
+                   ibfd->my_archive->filename, ibfd->filename);
+                 return;
+               }
+           }
+         newbfd->archive_next = head;
+         head = newbfd;
+       }
+    }
+
   for (i = 0; i < def->num_exports; i++)
     {
       /* The import library doesn't know about the internal name.  */
index 6645c4c83b82488629218f34461014555f79c74f..83e7422fe6f2f3c69dc8c9b10016aeb857caabdb 100644 (file)
@@ -36,14 +36,16 @@ extern int pe_dll_warn_dup_exports;
 extern int pe_dll_compat_implib;
 extern int pe_dll_extra_pe_debug;
 
+typedef enum { EXCLUDESYMS, EXCLUDELIBS, EXCLUDEFORIMPLIB } exclude_type;
+
 extern void pe_dll_id_target
   (const char *);
 extern void pe_dll_add_excludes
-  (const char *, const int);
+  (const char *, const exclude_type);
 extern void pe_dll_generate_def_file
   (const char *);
 extern void pe_dll_generate_implib
-  (def_file *, const char *);
+  (def_file *, const char *, struct bfd_link_info *);
 extern void pe_process_import_defs
   (bfd *, struct bfd_link_info *);
 extern bfd_boolean pe_implied_import_dll
index ae0dcbe9d83aa9bb1b10b6d1f3f347e2bef1a843..5d09658894f9df31f58464ed486726fa77e760a8 100644 (file)
@@ -36,10 +36,12 @@ extern int pep_dll_warn_dup_exports;
 extern int pep_dll_compat_implib;
 extern int pep_dll_extra_pe_debug;
 
+typedef enum { EXCLUDESYMS, EXCLUDELIBS, EXCLUDEFORIMPLIB } exclude_type;
+
 extern void pep_dll_id_target  (const char *);
-extern void pep_dll_add_excludes  (const char *, const int);
+extern void pep_dll_add_excludes  (const char *, const exclude_type);
 extern void pep_dll_generate_def_file  (const char *);
-extern void pep_dll_generate_implib  (def_file *, const char *);
+extern void pep_dll_generate_implib  (def_file *, const char *, struct bfd_link_info *);
 extern void pep_process_import_defs  (bfd *, struct bfd_link_info *);
 extern bfd_boolean pep_implied_import_dll  (const char *);
 extern void pep_dll_build_sections  (bfd *, struct bfd_link_info *);