From 10e636d21ea3e704dca34a6393fdefd1e90f07c8 Mon Sep 17 00:00:00 2001 From: Dave Korn Date: Fri, 4 Sep 2009 01:22:19 +0000 Subject: [PATCH] 2009-09-04 Timo Kreuzer * 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 | 18 +++ binutils/NEWS | 10 +- binutils/dlltool.c | 268 +++++++++++++++++++++++++++++++++++++++------ binutils/doc/binutils.texi | 12 ++ 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 + + * 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 * 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 + 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= 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 : arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb\n")); fprintf (file, _(" -e --output-exp Generate an export file.\n")); fprintf (file, _(" -l --output-lib Generate an interface library.\n")); + fprintf (file, _(" -y --output-delaylib Create a delay-import library.\n")); fprintf (file, _(" -a --add-indirect Add dll indirects to export file.\n")); fprintf (file, _(" -D --dllname Name of input dll to put into interface lib.\n")); fprintf (file, _(" -d --input-def 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 -- 2.7.4