aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog18
-rw-r--r--binutils/NEWS10
-rw-r--r--binutils/dlltool.c268
-rw-r--r--binutils/doc/binutils.texi12
4 files changed, 270 insertions, 38 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 015519a..36b3582 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -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
diff --git a/binutils/NEWS b/binutils/NEWS
index b3fd137..894c735 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -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.
diff --git a/binutils/dlltool.c b/binutils/dlltool.c
index 85ddaac..71fd993 100644
--- a/binutils/dlltool.c
+++ b/binutils/dlltool.c
@@ -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");
+ /* 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)
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 6353fd1..cc01546 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -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