This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] dlltool new option to create delay-import library [was Re: Binutils branch 2.20 (soon)]


Dave Korn wrote:
> Tristan Gingold wrote:
>> Hi,
>>
>> I'd like to create the branch for binutils 2.20 soon (ie within the next
>> 24 hours).
>> If you have a patch to commit or still waiting for a approval, please
>> speak now.  Thanks!
> 
>   Argh, one more thing (which I'll get on to straight away): Timo Kreuzer's
> assign papers just came through, for his dlltool delay-load import library patch.
> 
> http://sourceware.org/ml/binutils/2009-08/threads.html#00269
> 
>   I can get it done in the next couple of hours if that's good enough?

  Committed after testing on i686-pc-cygwin with this changelog:

2009-09-04  Timo Kreuzer  <timo.kreuzer@REDACTED_FOR_THE_LIST>

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

  Tristan, I'm definitely all done for the branch now, thanks for your patience.

  Timo, your patch is now part of binutils and will be in the forthcoming 2.20
release!  Thanks very much for contributing it :)

    cheers,
      DaveK


Index: binutils/dlltool.c
===================================================================
RCS file: /cvs/src/src/binutils/dlltool.c,v
retrieving revision 1.92
diff -p -u -r1.92 dlltool.c
--- binutils/dlltool.c	1 Apr 2009 17:20:18 -0000	1.92
+++ binutils/dlltool.c	4 Sep 2009 01:19:45 -0000
@@ -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 *nam
 #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, cons
 }
 
 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
     {
       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
 	      /* 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
 		  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
 	    }
 	  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");
+      /* 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 "
+			"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: binutils/NEWS
===================================================================
RCS file: /cvs/src/src/binutils/NEWS,v
retrieving revision 1.85
diff -p -u -r1.85 NEWS
--- binutils/NEWS	20 Jul 2009 13:40:48 -0000	1.85
+++ binutils/NEWS	4 Sep 2009 01:19:45 -0000
@@ -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: binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.152
diff -p -u -r1.152 binutils.texi
--- binutils/doc/binutils.texi	27 Aug 2009 14:58:08 -0000	1.152
+++ binutils/doc/binutils.texi	4 Sep 2009 01:19:46 -0000
@@ -3497,6 +3497,7 @@ dlltool [@option{-d}|@option{--input-def
         [@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 fu
 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} fi
 @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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]