2009-09-04 Timo Kreuzer <timo.kreuzer@web.de>
authorDave Korn <dave.korn@artimi.com>
Fri, 4 Sep 2009 01:22:19 +0000 (01:22 +0000)
committerDave Korn <dave.korn@artimi.com>
Fri, 4 Sep 2009 01:22:19 +0000 (01:22 +0000)
* dlltool.c (delayimp_name): Add new global variable
(usage, long_options, main): Add new option "-y" / "--output-delaylib"
(struct mac): Add fields how_dljtab_size, how_dljtab_roff1,
how_dljtab_roff2, how_dljtab, trampoline.
(i386_dljtab): Add binary stub for x86 delay import.
(i386_trampoline): Add text assembly stub for x86 delay import.
(mtable): Add delay import data for M386 and MX86 only.
(make_delay_head): New function.
(make_one_lib_file): New arg delay creates delay-load import stub.
(gen_lib_file): New arg delay likewise.
(HOW_JTAB, HOW_JTAB_SIZE, HOW_JTAB_ROFF): New arg delay likewise.
(HOW_JTAB_ROFF2, HOW_JTAB_ROFF3): New macros for delay import.
(make_tail): Convert hard TABS embedded in strings to "\t" escapes.
* NEWS: Mention new feature.  Also fix whitespace.
* doc/binutils.texi: Updated dlltool documentation.

binutils/ChangeLog
binutils/NEWS
binutils/dlltool.c
binutils/doc/binutils.texi

index 015519a..36b3582 100644 (file)
@@ -1,3 +1,21 @@
+2009-09-04  Timo Kreuzer  <timo.kreuzer@web.de>
+
+       * dlltool.c (delayimp_name): Add new global variable
+       (usage, long_options, main): Add new option "-y" / "--output-delaylib"
+       (struct mac): Add fields how_dljtab_size, how_dljtab_roff1, 
+       how_dljtab_roff2, how_dljtab, trampoline.
+       (i386_dljtab): Add binary stub for x86 delay import.
+       (i386_trampoline): Add text assembly stub for x86 delay import.
+       (mtable): Add delay import data for M386 and MX86 only.
+       (make_delay_head): New function.
+       (make_one_lib_file): New arg delay creates delay-load import stub.
+       (gen_lib_file): New arg delay likewise.
+       (HOW_JTAB, HOW_JTAB_SIZE, HOW_JTAB_ROFF): New arg delay likewise.
+       (HOW_JTAB_ROFF2, HOW_JTAB_ROFF3): New macros for delay import.
+       (make_tail): Convert hard TABS embedded in strings to "\t" escapes.
+       * NEWS: Mention new feature.  Also fix whitespace.
+       * doc/binutils.texi: Updated dlltool documentation.
+
 2009-09-02  Tristan Gingold  <gingold@adacore.com>
 
        * configure.com: Do not copy makefile.vms-in to makefile.vms
index b3fd137..894c735 100644 (file)
@@ -1,7 +1,13 @@
 -*- text -*-
+* Add support for delay importing to dlltool.  Use the --output-delaylib <file>
+  switch to create a delay-import library.  The resulting app will load the dll
+  as soon as the first function is called.  It will link to __delayLoadHelper2()
+  from the static delayimp library, which will import LoadLibraryA and
+  GetProcAddress from kernel32.
+
 * Add a new command line option, --insn-width=WIDTH, to objdump to specify
-number of bytes to be displayed on a single line when disassembling
-instructions.
+  number of bytes to be displayed on a single line when disassembling
+  instructions.
 
 * Readelf can now display the relocated contents of a section as a sequence
   of bytes via the --relocated-dump=<name|number> command line option.
index 85ddaac..71fd993 100644 (file)
@@ -352,6 +352,7 @@ static int no_idata4;
 static int no_idata5;
 static char *exp_name;
 static char *imp_name;
+static char *delayimp_name;
 static char *identify_imp_name;
 static bfd_boolean identify_strict;
 
@@ -499,6 +500,13 @@ static const unsigned char i386_jtab[] =
   0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
 };
 
+static const unsigned char i386_dljtab[] =
+{
+  0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, /* jmp __imp__function             */
+  0xB8, 0x00, 0x00, 0x00, 0x00,       /* mov eax, offset __imp__function */
+  0xE9, 0x00, 0x00, 0x00, 0x00        /* jmp __tailMerge__dllname        */
+};
+
 static const unsigned char arm_jtab[] =
 {
   0x00, 0xc0, 0x9f, 0xe5,      /* ldr  ip, [pc] */
@@ -565,6 +573,16 @@ static const unsigned char ppc_jtab[] =
 static bfd_vma ppc_glue_insn = 0x80410004;
 #endif
 
+static const char i386_trampoline[] =  
+  "\tpushl %%ecx\n"
+  "\tpushl %%edx\n"
+  "\tpushl %%eax\n"
+  "\tpushl $__DELAY_IMPORT_DESCRIPTOR_%s\n"
+  "\tcall ___delayLoadHelper2@8\n"
+  "\tpopl %%edx\n"
+  "\tpopl %%ecx\n"
+  "\tjmp *%%eax\n";
+
 struct mac
   {
     const char *type;
@@ -584,6 +602,12 @@ struct mac
     const unsigned char *how_jtab;
     int how_jtab_size; /* Size of the jtab entry.  */
     int how_jtab_roff; /* Offset into it for the ind 32 reloc into idata 5.  */
+    const unsigned char *how_dljtab;
+    int how_dljtab_size; /* Size of the dljtab entry.  */
+    int how_dljtab_roff1; /* Offset for the ind 32 reloc into idata 5.  */
+    int how_dljtab_roff2; /* Offset for the ind 32 reloc into idata 5.  */
+    int how_dljtab_roff3; /* Offset for the ind 32 reloc into idata 5.  */
+    const char *trampoline;
   };
 
 static const struct mac
@@ -595,7 +619,8 @@ mtable[] =
     "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
     ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
     "pe-arm-little", bfd_arch_arm,
-    arm_jtab, sizeof (arm_jtab), 8
+    arm_jtab, sizeof (arm_jtab), 8,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -603,7 +628,8 @@ mtable[] =
     "i386", ".byte", ".short", ".long", ".asciz", "#",
     "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
     "pe-i386",bfd_arch_i386,
-    i386_jtab, sizeof (i386_jtab), 2
+    i386_jtab, sizeof (i386_jtab), 2,
+    i386_dljtab, sizeof (i386_dljtab), 2, 7, 12, i386_trampoline
   }
   ,
   {
@@ -611,7 +637,8 @@ mtable[] =
     "ppc", ".byte", ".short", ".long", ".asciz", "#",
     "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
     "pe-powerpcle",bfd_arch_powerpc,
-    ppc_jtab, sizeof (ppc_jtab), 0
+    ppc_jtab, sizeof (ppc_jtab), 0,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -620,7 +647,8 @@ mtable[] =
     "push\t{r6}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tmov\tip, r6\n\tpop\t{r6}\n\tbx\tip",
     ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
     "pe-arm-little", bfd_arch_arm,
-    thumb_jtab, sizeof (thumb_jtab), 12
+    thumb_jtab, sizeof (thumb_jtab), 12,
+    0, 0, 0, 0, 0, 0
   }
   ,
 #define MARM_INTERWORK 4
@@ -629,7 +657,8 @@ mtable[] =
     "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
     ".global", ".space", ".align\t2",".align\t4", "-mthumb-interwork",
     "pe-arm-little", bfd_arch_arm,
-    arm_interwork_jtab, sizeof (arm_interwork_jtab), 12
+    arm_interwork_jtab, sizeof (arm_interwork_jtab), 12,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -638,7 +667,8 @@ mtable[] =
     "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
     ".global", ".space", ".align\t2",".align\t4", "",
     "pe-mcore-big", bfd_arch_mcore,
-    mcore_be_jtab, sizeof (mcore_be_jtab), 8
+    mcore_be_jtab, sizeof (mcore_be_jtab), 8,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -647,7 +677,8 @@ mtable[] =
     "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
     ".global", ".space", ".align\t2",".align\t4", "-EL",
     "pe-mcore-little", bfd_arch_mcore,
-    mcore_le_jtab, sizeof (mcore_le_jtab), 8
+    mcore_le_jtab, sizeof (mcore_le_jtab), 8,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -656,7 +687,8 @@ mtable[] =
     "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
     ".global", ".space", ".align\t2",".align\t4", "",
     "elf32-mcore-big", bfd_arch_mcore,
-    mcore_be_jtab, sizeof (mcore_be_jtab), 8
+    mcore_be_jtab, sizeof (mcore_be_jtab), 8,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -665,7 +697,8 @@ mtable[] =
     "lrw r1,[1f]\n\tld.w r1,(r1,0)\n\tjmp r1\n\tnop\n1:.long",
     ".global", ".space", ".align\t2",".align\t4", "-EL",
     "elf32-mcore-little", bfd_arch_mcore,
-    mcore_le_jtab, sizeof (mcore_le_jtab), 8
+    mcore_le_jtab, sizeof (mcore_le_jtab), 8,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -674,7 +707,8 @@ mtable[] =
     "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
     ".global", ".space", ".align\t2",".align\t4", "",
     "epoc-pe-arm-little", bfd_arch_arm,
-    arm_jtab, sizeof (arm_jtab), 8
+    arm_jtab, sizeof (arm_jtab), 8,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -683,7 +717,8 @@ mtable[] =
     "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
     ".global", ".space", ".align\t2",".align\t4", "-mapcs-32",
     "pe-arm-wince-little", bfd_arch_arm,
-    arm_jtab, sizeof (arm_jtab), 8
+    arm_jtab, sizeof (arm_jtab), 8,
+    0, 0, 0, 0, 0, 0
   }
   ,
   {
@@ -691,10 +726,11 @@ mtable[] =
     "i386:x86-64", ".byte", ".short", ".long", ".asciz", "#",
     "jmp *", ".global", ".space", ".align\t2",".align\t4", "",
     "pe-x86-64",bfd_arch_i386,
-    i386_jtab, sizeof (i386_jtab), 2
+    i386_jtab, sizeof (i386_jtab), 2,
+    i386_dljtab, sizeof (i386_dljtab), 2, 7, 12, i386_trampoline
   }
   ,
-  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
 typedef struct dlist
@@ -756,10 +792,11 @@ static void gen_exp_file (void);
 static const char *xlate (const char *);
 static char *make_label (const char *, const char *);
 static char *make_imp_label (const char *, const char *);
-static bfd *make_one_lib_file (export_type *, int);
+static bfd *make_one_lib_file (export_type *, int, int);
 static bfd *make_head (void);
 static bfd *make_tail (void);
-static void gen_lib_file (void);
+static bfd *make_delay_head (void);
+static void gen_lib_file (int);
 static void dll_name_list_append (dll_name_list_type *, bfd_byte *);
 static int  dll_name_list_count (dll_name_list_type *);
 static void dll_name_list_print (dll_name_list_type *);
@@ -923,9 +960,14 @@ asm_prefix (int machine, const char *name)
 #define HOW_BFD_READ_TARGET    0  /* Always default.  */
 #define HOW_BFD_WRITE_TARGET   mtable[machine].how_bfd_target
 #define HOW_BFD_ARCH           mtable[machine].how_bfd_arch
-#define HOW_JTAB               mtable[machine].how_jtab
-#define HOW_JTAB_SIZE          mtable[machine].how_jtab_size
-#define HOW_JTAB_ROFF          mtable[machine].how_jtab_roff
+#define HOW_JTAB               (delay ? mtable[machine].how_dljtab \
+                                       : mtable[machine].how_jtab)
+#define HOW_JTAB_SIZE          (delay ? mtable[machine].how_dljtab_size \
+                                       : mtable[machine].how_jtab_size)
+#define HOW_JTAB_ROFF          (delay ? mtable[machine].how_dljtab_roff1 \
+                                       : mtable[machine].how_jtab_roff)
+#define HOW_JTAB_ROFF2         (delay ? mtable[machine].how_dljtab_roff2 : 0)
+#define HOW_JTAB_ROFF3         (delay ? mtable[machine].how_dljtab_roff3 : 0)
 #define ASM_SWITCHES           mtable[machine].how_default_as_switches
 
 static char **oav;
@@ -2296,7 +2338,7 @@ make_imp_label (const char *prefix, const char *name)
 }
 
 static bfd *
-make_one_lib_file (export_type *exp, int i)
+make_one_lib_file (export_type *exp, int i, int delay)
 {
   bfd *      abfd;
   asymbol *  exp_label;
@@ -2462,7 +2504,7 @@ make_one_lib_file (export_type *exp, int i)
     {
       sinfo *si = secdata + i;
       asection *sec = si->sec;
-      arelent *rel;
+      arelent *rel, *rel2 = 0, *rel3 = 0;
       arelent **rpp;
 
       switch (i)
@@ -2477,13 +2519,26 @@ make_one_lib_file (export_type *exp, int i)
              /* Add the reloc into idata$5.  */
              rel = xmalloc (sizeof (arelent));
 
-             rpp = xmalloc (sizeof (arelent *) * 2);
+             rpp = xmalloc (sizeof (arelent *) * (delay ? 4 : 2));
              rpp[0] = rel;
              rpp[1] = 0;
 
              rel->address = HOW_JTAB_ROFF;
              rel->addend = 0;
 
+             if (delay)
+               {
+                 rel2 = xmalloc (sizeof (arelent));
+                 rpp[1] = rel2;
+                 rel2->address = HOW_JTAB_ROFF2;
+                 rel2->addend = 0;
+                 rel3 = xmalloc (sizeof (arelent));
+                 rpp[2] = rel3;
+                 rel3->address = HOW_JTAB_ROFF3;
+                 rel3->addend = 0;
+                 rpp[3] = 0;
+               }
+
              if (machine == MPPC)
                {
                  rel->howto = bfd_reloc_type_lookup (abfd,
@@ -2501,12 +2556,41 @@ make_one_lib_file (export_type *exp, int i)
                  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
                  rel->sym_ptr_ptr = secdata[IDATA5].sympp;
                }
+
+             if (delay)
+               {
+                 rel2->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+                 rel2->sym_ptr_ptr = rel->sym_ptr_ptr;
+                 rel3->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32_PCREL);
+                 rel3->sym_ptr_ptr = iname_lab_pp;
+               }
+
              sec->orelocation = rpp;
-             sec->reloc_count = 1;
+             sec->reloc_count = delay ? 3 : 1;
            }
          break;
-       case IDATA4:
+
        case IDATA5:
+         if (delay)
+           {
+             si->data = xmalloc (4);
+             si->size = 4;
+             sec->reloc_count = 1;
+             memset (si->data, 0, si->size);
+             si->data[0] = 6;
+             rel = xmalloc (sizeof (arelent));
+             rpp = xmalloc (sizeof (arelent *) * 2);
+             rpp[0] = rel;
+             rpp[1] = 0;
+             rel->address = 0;
+             rel->addend = 0;
+             rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+             rel->sym_ptr_ptr = secdata[TEXT].sympp;
+             sec->orelocation = rpp;
+             break;
+           }
+         /* else fall through */
+       case IDATA4:
          /* An idata$4 or idata$5 is one word long, and has an
             rva to idata$6.  */
 
@@ -2584,6 +2668,8 @@ make_one_lib_file (export_type *exp, int i)
            }
          break;
        case IDATA7:
+         if (delay)
+           break;
          si->size = 4;
          si->data = xmalloc (4);
          memset (si->data, 0, si->size);
@@ -2753,9 +2839,9 @@ make_head (void)
     }
 
   fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
-  fprintf (f, "\t.section      .idata$2\n");
+  fprintf (f, "\t.section\t.idata$2\n");
 
-  fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
+  fprintf (f,"\t%s\t%s\n", ASM_GLOBAL, head_label);
 
   fprintf (f, "%s:\n", head_label);
 
@@ -2810,6 +2896,79 @@ make_head (void)
   return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
 }
 
+bfd *
+make_delay_head (void)
+{
+  FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
+
+  if (f == NULL)
+    {
+      fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
+      return NULL;
+    }
+
+  /* Output the __tailMerge__xxx function */
+  fprintf (f, "%s Import trampoline\n", ASM_C);
+  fprintf (f, "\t.section\t.text\n");
+  fprintf(f,"\t%s\t%s\n", ASM_GLOBAL, head_label);
+  fprintf (f, "%s:\n", head_label);
+  fprintf (f, mtable[machine].trampoline, imp_name_lab);
+
+  /* Output the delay import descriptor */
+  fprintf (f, "\n%s DELAY_IMPORT_DESCRIPTOR\n", ASM_C);
+  fprintf (f, ".section\t.text$2\n");
+  fprintf (f,"%s __DELAY_IMPORT_DESCRIPTOR_%s\n", ASM_GLOBAL,imp_name_lab);
+  fprintf (f, "__DELAY_IMPORT_DESCRIPTOR_%s:\n", imp_name_lab);
+  fprintf (f, "\t%s 1\t%s grAttrs\n", ASM_LONG, ASM_C);
+  fprintf (f, "\t%s__%s_iname%s\t%s rvaDLLName\n",
+          ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
+  fprintf (f, "\t%s__DLL_HANDLE_%s%s\t%s rvaHmod\n",
+          ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
+  fprintf (f, "\t%s__IAT_%s%s\t%s rvaIAT\n",
+          ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
+  fprintf (f, "\t%s__INT_%s%s\t%s rvaINT\n",
+          ASM_RVA_BEFORE, imp_name_lab, ASM_RVA_AFTER, ASM_C);
+  fprintf (f, "\t%s\t0\t%s rvaBoundIAT\n", ASM_LONG, ASM_C);
+  fprintf (f, "\t%s\t0\t%s rvaUnloadIAT\n", ASM_LONG, ASM_C);
+  fprintf (f, "\t%s\t0\t%s dwTimeStamp\n", ASM_LONG, ASM_C);
+
+  /* Output the dll_handle */
+  fprintf (f, "\n.section .data\n");
+  fprintf (f, "__DLL_HANDLE_%s:\n", imp_name_lab);
+  fprintf (f, "\t%s\t0\t%s Handle\n", ASM_LONG, ASM_C);
+  fprintf (f, "\n");
+
+  fprintf (f, "%sStuff for compatibility\n", ASM_C);
+
+  if (!no_idata5)
+    {
+      fprintf (f, "\t.section\t.idata$5\n");\r
+      /* NULL terminating list.  */
+#ifdef DLLTOOL_MX86_64
+      fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
+#else
+      fprintf (f,"\t%s\t0\n", ASM_LONG);
+#endif
+      fprintf (f, "__IAT_%s:\n", imp_name_lab);
+    }
+
+  if (!no_idata4)
+    {
+      fprintf (f, "\t.section\t.idata$4\n");
+      fprintf (f, "\t%s\t0\n", ASM_LONG);
+      fprintf (f, "\t.section\t.idata$4\n");
+      fprintf (f, "__INT_%s:\n", imp_name_lab);
+    }
+
+  fprintf (f, "\t.section\t.idata$2\n");
+
+  fclose (f);
+
+  assemble_file (TMP_HEAD_S, TMP_HEAD_O);
+
+  return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET);
+}
+
 static bfd *
 make_tail (void)
 {
@@ -2823,7 +2982,7 @@ make_tail (void)
 
   if (!no_idata4)
     {
-      fprintf (f, "\t.section  .idata$4\n");
+      fprintf (f, "\t.section\t.idata$4\n");
       if (create_for_pep)
        fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
       else
@@ -2832,7 +2991,7 @@ make_tail (void)
 
   if (!no_idata5)
     {
-      fprintf (f, "\t.section  .idata$5\n");
+      fprintf (f, "\t.section\t.idata$5\n");
       if (create_for_pep)
        fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
       else
@@ -2847,7 +3006,7 @@ make_tail (void)
      comdat, that is) or cause it to be inserted by something else (say
      crt0).  */
 
-  fprintf (f, "\t.section      .idata$3\n");
+  fprintf (f, "\t.section\t.idata$3\n");
   fprintf (f, "\t%s\t0\n", ASM_LONG);
   fprintf (f, "\t%s\t0\n", ASM_LONG);
   fprintf (f, "\t%s\t0\n", ASM_LONG);
@@ -2858,9 +3017,9 @@ make_tail (void)
 #ifdef DLLTOOL_PPC
   /* Other PowerPC NT compilers use idata$6 for the dllname, so I
      do too. Original, huh?  */
-  fprintf (f, "\t.section      .idata$6\n");
+  fprintf (f, "\t.section\t.idata$6\n");
 #else
-  fprintf (f, "\t.section      .idata$7\n");
+  fprintf (f, "\t.section\t.idata$7\n");
 #endif
 
   fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
@@ -2875,7 +3034,7 @@ make_tail (void)
 }
 
 static void
-gen_lib_file (void)
+gen_lib_file (int delay)
 {
   int i;
   export_type *exp;
@@ -2900,7 +3059,14 @@ gen_lib_file (void)
   outarch->is_thin_archive = 0;
 
   /* Work out a reasonable size of things to put onto one line.  */
-  ar_head = make_head ();
+  if (delay)
+    {
+      ar_head = make_delay_head ();
+    }
+  else
+    {
+      ar_head = make_head ();
+    }
   ar_tail = make_tail();
 
   if (ar_head == NULL || ar_tail == NULL)
@@ -2912,7 +3078,7 @@ gen_lib_file (void)
       /* Don't add PRIVATE entries to import lib.  */
       if (exp->private)
        continue;
-      n = make_one_lib_file (exp, i);
+      n = make_one_lib_file (exp, i, delay);
       n->archive_next = head;
       head = n;
       if (ext_prefix_alias)
@@ -2931,7 +3097,7 @@ gen_lib_file (void)
          alias_exp.hint = exp->hint;
          alias_exp.forward = exp->forward;
          alias_exp.next = exp->next;
-         n = make_one_lib_file (&alias_exp, i + PREFIX_ALIAS_BASE);
+         n = make_one_lib_file (&alias_exp, i + PREFIX_ALIAS_BASE, delay);
          n->archive_next = head;
          head = n;
        }
@@ -3628,6 +3794,7 @@ usage (FILE *file, int status)
   fprintf (file, _("        possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n"));
   fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
   fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
+  fprintf (file, _("   -y --output-delaylib <outname> Create a delay-import library.\n"));
   fprintf (file, _("   -a --add-indirect         Add dll indirects to export file.\n"));
   fprintf (file, _("   -D --dllname <name>       Name of input dll to put into interface lib.\n"));
   fprintf (file, _("   -d --input-def <deffile>  Name of .def file to be read in.\n"));
@@ -3710,6 +3877,7 @@ static const struct option long_options[] =
   {"mcore-elf", required_argument, NULL, 'M'},
   {"compat-implib", no_argument, NULL, 'C'},
   {"temp-prefix", required_argument, NULL, 't'},
+  {"output-delaylib", required_argument, NULL, 'y'},
   {NULL,0,NULL,0}
 };
 
@@ -3739,7 +3907,7 @@ main (int ac, char **av)
 #ifdef DLLTOOL_MCORE_ELF
                           "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nI:vVHhM:L:F:",
 #else
-                          "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nI:vVHh",
+                          "m:e:l:y:aD:d:z:b:xp:cCuUkAS:f:nI:vVHh",
 #endif
                           long_options, 0))
         != EOF)
@@ -3860,6 +4028,9 @@ main (int ac, char **av)
        case 'C':
          create_compat_implib = 1;
          break;
+       case 'y':
+         delayimp_name = optarg;
+         break;
        default:
          usage (stderr, 1);
          break;
@@ -3934,7 +4105,32 @@ main (int ac, char **av)
            *p = '_';
        }
       head_label = make_label("_head_", imp_name_lab);
-      gen_lib_file ();
+      gen_lib_file (0);
+    }
+
+  if (delayimp_name)
+    {
+      /* Make delayimp_name safe for use as a label.  */
+      char *p;
+
+      if (mtable[machine].how_dljtab == 0)
+        {
+          inform (_("Warning, machine type (%d) not supported for "\r
+                       "delayimport."), machine);
+        }
+      else
+        {
+          killat = 1;
+          imp_name = delayimp_name;
+          imp_name_lab = xstrdup (imp_name);
+          for (p = imp_name_lab; *p; p++)
+            {
+              if (!ISALNUM (*p))
+                *p = '_';
+            }
+          head_label = make_label("__tailMerge_", imp_name_lab);
+          gen_lib_file (1);
+        }
     }
 
   if (output_def)
index 6353fd1..cc01546 100644 (file)
@@ -3497,6 +3497,7 @@ dlltool [@option{-d}|@option{--input-def} @var{def-file-name}]
         [@option{-e}|@option{--output-exp} @var{exports-file-name}]
         [@option{-z}|@option{--output-def} @var{def-file-name}]
         [@option{-l}|@option{--output-lib} @var{library-file-name}]
+        [@option{-y}|@option{--output-delaylib} @var{library-file-name}]
         [@option{--export-all-symbols}] [@option{--no-export-all-symbols}]
         [@option{--exclude-symbols} @var{list}]
         [@option{--no-default-excludes}]
@@ -3563,6 +3564,13 @@ will link with in order to access the functions in the DLL (an `import
 library').  This file can be created by giving the @option{-l} option to
 dlltool when it is creating or reading in a @file{.def} file.
 
+If the @option{-y} option is specified, dlltool generates a delay-import
+library that can be used instead of the normal import library to allow
+a program to link to the dll only as soon as an imported function is
+called for the first time. The resulting executable will need to be
+linked to the static delayimp library containing __delayLoadHelper2(),
+which in turn will import LoadLibraryA and GetProcAddress from kernel32.
+
 @command{dlltool} builds the library file by hand, but it builds the
 exports file by creating temporary files containing assembler statements
 and then assembling these.  The @option{-S} command line option can be
@@ -3621,6 +3629,10 @@ Specifies the name of the @file{.def} file to be created by dlltool.
 @itemx --output-lib @var{filename}
 Specifies the name of the library file to be created by dlltool.
 
+@item -y @var{filename}
+@itemx --output-delaylib @var{filename}
+Specifies the name of the delay-import library file to be created by dlltool.
+
 @item --export-all-symbols
 Treat all global and weak defined symbols found in the input object
 files as symbols to be exported.  There is a small list of symbols which