--- C:/Dev/MSYS/home/colin/binutils-2.19/binutils/dlltool.org.c Sa 25. Jul 00:39:15 2009 +++ C:/Dev/MSYS/home/colin/binutils-2.19/binutils/dlltool.c Sa 25. Jul 20:18:48 2009 @@ -352,6 +352,7 @@ static int no_idata5; static char *exp_name; static char *imp_name; +static char *delayimp_name; static char *head_label; static char *imp_name_lab; static char *dll_name; @@ -463,6 +464,13 @@ 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] */ @@ -548,6 +556,11 @@ 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 jtab entry. */ + int how_dljtab_roff1; /* Offset into it for the ind 32 reloc into idata 5. */ + int how_dljtab_roff2; /* Offset into it for the ind 32 reloc into idata 5. */ + int how_dljtab_roff3; /* Offset into it for the ind 32 reloc into idata 5. */ }; static const struct mac @@ -559,7 +572,8 @@ "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, + arm_jtab, sizeof (arm_jtab), 8, 0, 0 } , { @@ -567,7 +581,8 @@ "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 } , { @@ -575,7 +590,8 @@ "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, + ppc_jtab, sizeof (ppc_jtab), 0, 0, 0 } , { @@ -584,7 +600,8 @@ "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, + thumb_jtab, sizeof (thumb_jtab), 12, 12, 12 } , #define MARM_INTERWORK 4 @@ -593,7 +610,8 @@ "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, + arm_interwork_jtab, sizeof (arm_interwork_jtab), 12, 12, 12 } , { @@ -602,7 +620,8 @@ "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, + mcore_be_jtab, sizeof (mcore_be_jtab), 8, 8, 8 } , { @@ -611,7 +630,8 @@ "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, + mcore_le_jtab, sizeof (mcore_le_jtab), 8, 8, 8 } , { @@ -620,7 +640,8 @@ "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, + mcore_be_jtab, sizeof (mcore_be_jtab), 8, 8, 8 } , { @@ -629,7 +650,8 @@ "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, + mcore_le_jtab, sizeof (mcore_le_jtab), 8, 8, 8 } , { @@ -638,7 +660,8 @@ "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, + arm_jtab, sizeof (arm_jtab), 8, 8, 8 } , { @@ -647,7 +670,8 @@ "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, + arm_jtab, sizeof (arm_jtab), 8, 8, 8 } , { @@ -655,10 +679,11 @@ "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 } , - { 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 @@ -720,10 +745,11 @@ 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 int pfunc (const void *, const void *); static int nfunc (const void *, const void *); static void remove_null_names (export_type **); @@ -873,9 +899,11 @@ #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; @@ -2219,7 +2247,7 @@ } 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; @@ -2385,7 +2413,7 @@ { sinfo *si = secdata + i; asection *sec = si->sec; - arelent *rel; + arelent *rel, *rel2 = 0, *rel3 = 0; arelent **rpp; switch (i) @@ -2400,13 +2428,26 @@ /* 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, @@ -2424,12 +2465,41 @@ 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 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: - case IDATA5: /* An idata$4 or idata$5 is one word long, and has an rva to idata$6. */ @@ -2505,6 +2575,7 @@ } break; case IDATA7: + if (delay) break; si->size = 4; si->data = xmalloc (4); memset (si->data, 0, si->size); @@ -2657,7 +2728,9 @@ } bfd_set_symtab (abfd, ptrs, oidx); + bfd_close (abfd); + abfd = bfd_openr (outname, HOW_BFD_READ_TARGET); return abfd; } @@ -2724,8 +2797,90 @@ return bfd_openr (TMP_HEAD_O, HOW_BFD_READ_TARGET); } +#define ASM_DELAY_TRAMPOLINE(f, label) \ + fprintf(f, "\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", label) + +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 .text\n"); + fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label); + fprintf (f, "%s:\n", head_label); + ASM_DELAY_TRAMPOLINE(f, imp_name_lab); + + /* Output the delay import descriptor */ + fprintf (f, "\n%s DELAY_IMPORT_DESCRIPTOR\n", ASM_C); + fprintf (f, ".section .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"); +#ifdef DLLTOOL_MX86_64 + fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG); /* NULL terminating list. */ +#else + fprintf (f,"\t%s\t0\n", ASM_LONG); /* NULL terminating list. */ +#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 .idata$4\n"); + fprintf (f, "__INT_%s:\n", imp_name_lab); + } + + fprintf (f, "\t.section .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) +make_tail () { FILE *f = fopen (TMP_TAIL_S, FOPEN_WT); @@ -2791,7 +2946,7 @@ } static void -gen_lib_file (void) +gen_lib_file (int delay) { int i; export_type *exp; @@ -2816,7 +2971,14 @@ 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) @@ -2828,7 +2990,7 @@ /* 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) @@ -2847,7 +3009,7 @@ 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; } @@ -3155,6 +3317,7 @@ fprintf (file, _(" -k --kill-at Kill @ from exported names.\n")); fprintf (file, _(" -A --add-stdcall-alias Add aliases without @.\n")); fprintf (file, _(" -p --ext-prefix-alias Add aliases with .\n")); + fprintf (file, _(" -y --output-delaylib Create delay import stubs.\n")); fprintf (file, _(" -S --as Use for assembler.\n")); fprintf (file, _(" -f --as-flags Pass to the assembler.\n")); fprintf (file, _(" -C --compat-implib Create backward compatible import library.\n")); @@ -3211,6 +3374,7 @@ {"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} }; @@ -3240,7 +3404,7 @@ #ifdef DLLTOOL_MCORE_ELF "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHhM:L:F:", #else - "m:e:l:aD:d:z:b:xp:cCuUkAS:f:nvVHh", + "m:e:l:y:aD:d:z:b:xp:cCuUkAS:f:nvVHh", #endif long_options, 0)) != EOF) @@ -3352,6 +3516,9 @@ case 'C': create_compat_implib = 1; break; + case 'y': + delayimp_name = optarg; + break; default: usage (stderr, 1); break; @@ -3375,8 +3542,8 @@ { /* If we are inferring dll_name from exp_name, strip off any path components, without emitting - a warning. */ - const char* exp_basename = lbasename (exp_name); + a warning. */ + const char* exp_basename = lbasename (exp_name); const int len = strlen (exp_basename) + 5; dll_name = xmalloc (len); strcpy (dll_name, exp_basename); @@ -3423,9 +3590,26 @@ *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; + + 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) gen_def_file ();