/* dlltool.c -- tool to generate stuff for PE style DLLs
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
This file is part of GNU Binutils.
.idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc). */
-/* AIX requires this to be the first thing in the file. */
-#ifndef __GNUC__
-# ifdef _AIX
- #pragma alloca
-#endif
-#endif
-
-#define show_allnames 0
-
#include "sysdep.h"
#include "bfd.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include <time.h>
-#include <sys/stat.h>
-#include <stdarg.h>
#include <assert.h>
#ifdef DLLTOOL_ARM
#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
#endif /* ! HAVE_SYS_WAIT_H */
+#define show_allnames 0
+
/* ifunc and ihead data structures: ttk@cygnus.com 1997
When IMPORT declarations are encountered in a .def file the
static char *head_label;
static char *imp_name_lab;
static char *dll_name;
+static int dll_name_set_by_exp_name;
static int add_indirect = 0;
static int add_underscore = 0;
static int add_stdcall_underscore = 0;
0xE9, 0x00, 0x00, 0x00, 0x00 /* jmp __tailMerge__dllname */
};
+static const unsigned char i386_x64_dljtab[] =
+{
+ 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, /* jmp __imp__function */
+ 0x48, 0x8d, 0x05, /* leaq rax, (__imp__function) */
+ 0x00, 0x00, 0x00, 0x00,
+ 0xE9, 0x00, 0x00, 0x00, 0x00 /* jmp __tailMerge__dllname */
+};
+
static const unsigned char arm_jtab[] =
{
0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
"\tpopl %%ecx\n"
"\tjmp *%%eax\n";
+static const char i386_x64_trampoline[] =
+ "\tpushq %%rcx\n"
+ "\tpushq %%rdx\n"
+ "\tpushq %%r8\n"
+ "\tpushq %%r9\n"
+ "\tsubq $40, %%rsp\n"
+ "\tmovq %%rax, %%rdx\n"
+ "\tleaq __DELAY_IMPORT_DESCRIPTOR_%s(%%rip), %%rcx\n"
+ "\tcall __delayLoadHelper2\n"
+ "\taddq $40, %%rsp\n"
+ "\tpopq %%r9\n"
+ "\tpopq %%r8\n"
+ "\tpopq %%rdx\n"
+ "\tpopq %%rcx\n"
+ "\tjmp *%%rax\n";
+
struct mac
{
const char *type;
"jmp *", ".global", ".space", ".align\t2",".align\t4", "",
"pe-x86-64",bfd_arch_i386,
i386_jtab, sizeof (i386_jtab), 2,
- i386_dljtab, sizeof (i386_dljtab), 2, 7, 12, i386_trampoline
+ i386_x64_dljtab, sizeof (i386_x64_dljtab), 2, 9, 14, i386_x64_trampoline
}
,
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
if (d_is_dll)
non_fatal (_("Can't have LIBRARY and NAME"));
+ if (dll_name_set_by_exp_name && name && *name != 0)
+ {
+ dll_name = NULL;
+ dll_name_set_by_exp_name = 0;
+ }
/* If --dllname not provided, use the one in the DEF file.
FIXME: Is this appropriate for executables? */
if (!dll_name)
if (d_is_exe)
non_fatal (_("Can't have LIBRARY and NAME"));
+ if (dll_name_set_by_exp_name && name && *name != 0)
+ {
+ dll_name = NULL;
+ dll_name_set_by_exp_name = 0;
+ }
+
/* If --dllname not provided, use the one in the DEF file. */
if (!dll_name)
set_dll_name_from_def (name, 1);
void
def_version (int major, int minor)
{
- printf ("VERSION %d.%d\n", major, minor);
+ printf (_("VERSION %d.%d\n"), major, minor);
}
void
char *errmsg_fmt, *errmsg_arg;
char *temp_base = choose_temp_base ();
- inform ("run: %s %s", what, args);
+ inform (_("run: %s %s"), what, args);
/* Count the args */
i = 0;
flagword flags = BSF_FUNCTION;
p += 8;
- name = p;
- while (p < e && *p != ',' && *p != ' ' && *p != '-')
- p++;
+ /* Do we have a quoted export? */
+ if (*p == '"')
+ {
+ p++;
+ name = p;
+ while (p < e && *p != '"')
+ ++p;
+ }
+ else
+ {
+ name = p;
+ while (p < e && *p != ',' && *p != ' ' && *p != '-')
+ p++;
+ }
c = xmalloc (p - name + 1);
memcpy (c, name, p - name);
c[p - name] = 0;
+ /* Advance over trailing quote. */
+ if (p < e && *p == '"')
+ ++p;
if (p < e && *p == ',') /* found type tag. */
{
char *tag_start = ++p;
iname_lab = bfd_make_empty_symbol (abfd);
iname_lab->name = head_label;
- iname_lab->section = (asection *) &bfd_und_section;
+ iname_lab->section = bfd_und_section_ptr;
iname_lab->flags = 0;
iname_lab->value = 0;
toc_symbol = bfd_make_empty_symbol (abfd);
toc_symbol->name = make_label (".", "toc");
- toc_symbol->section = (asection *)&bfd_und_section;
+ toc_symbol->section = bfd_und_section_ptr;
toc_symbol->flags = BSF_GLOBAL;
toc_symbol->value = 0;
if (delay)
{
- rel2->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ if (machine == MX86)
+ rel2->howto = bfd_reloc_type_lookup (abfd,
+ BFD_RELOC_32_PCREL);
+ else
+ 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->howto = bfd_reloc_type_lookup (abfd,
+ BFD_RELOC_32_PCREL);
rel3->sym_ptr_ptr = iname_lab_pp;
}
case IDATA5:
if (delay)
{
- si->data = xmalloc (4);
- si->size = 4;
+ si->size = create_for_pep ? 8 : 4;
+ si->data = xmalloc (si->size);
sec->reloc_count = 1;
memset (si->data, 0, si->size);
+ /* Point after jmp [__imp_...] instruction. */
si->data[0] = 6;
rel = xmalloc (sizeof (arelent));
rpp = xmalloc (sizeof (arelent *) * 2);
rpp[1] = 0;
rel->address = 0;
rel->addend = 0;
- rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ if (create_for_pep)
+ rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_64);
+ else
+ rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
rel->sym_ptr_ptr = secdata[TEXT].sympp;
sec->orelocation = rpp;
break;
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);
+ if (create_for_pep)
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
fprintf (f, "\n");
fprintf (f, "%sStuff for compatibility\n", ASM_C);
{
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
+ if (create_for_pep)
+ fprintf (f,"\t%s\t0\n\t%s\t0\n", ASM_LONG, ASM_LONG);
+ else
+ fprintf (f,"\t%s\t0\n", ASM_LONG);
fprintf (f, "__IAT_%s:\n", imp_name_lab);
}
{
fprintf (f, "\t.section\t.idata$4\n");
fprintf (f, "\t%s\t0\n", ASM_LONG);
+ if (create_for_pep)
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
fprintf (f, "\t.section\t.idata$4\n");
fprintf (f, "__INT_%s:\n", imp_name_lab);
}
/* Check if we generated PE+. */
create_for_pep = strcmp (mname, "i386:x86-64") == 0;
+ {
+ /* Check the default underscore */
+ int u = leading_underscore; /* Underscoring mode. -1 for use default. */
+ if (u == -1)
+ bfd_get_target_info (mtable[machine].how_bfd_target, NULL,
+ NULL, &u, NULL);
+ if (u != -1)
+ leading_underscore = (u != 0 ? TRUE : FALSE);
+ }
+
if (!dll_name && exp_name)
{
/* If we are inferring dll_name from exp_name,
dll_name = xmalloc (len);
strcpy (dll_name, exp_basename);
strcat (dll_name, ".dll");
+ dll_name_set_by_exp_name = 1;
}
if (as_name == NULL)