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.
This commit is contained in:
Dave Korn 2009-09-04 01:22:19 +00:00
parent 8f0e5a0604
commit 10e636d21e
4 changed files with 270 additions and 38 deletions

View 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");
/* 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)