/* dlltool.c -- tool to generate stuff for PE style DLLs
- Copyright (C) 1995, 96, 97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96, 97, 98, 1999 Free Software Foundation, Inc.
This file is part of GNU Binutils.
printf ("hello from the dll and the other entry point %s\n", s);
}
- printf()
+ int printf (void)
{
return 9;
}
- main.c
-
- void main()
+ themain.c:
+ int main (void)
{
- cdef();
+ cdef ();
+ return 0;
}
thedll.def
gcc -c themain.c
# link the executable with the import library
- ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
+ gcc -o themain.exe themain.o thedll.a
*/
#include "bucomm.h"
#include "getopt.h"
#include "demangle.h"
+#include "dyn-string.h"
#include "dlltool.h"
#include <ctype.h>
#include <time.h>
-#ifdef __STDC__
+#include <sys/stat.h>
+
+#ifdef ANSI_PROTOTYPES
#include <stdarg.h>
#else
#include <varargs.h>
#include "coff/internal.h"
#endif
+/* Forward references. */
+static char *look_for_prog PARAMS ((const char *, const char *, int));
+static char *deduce_name PARAMS ((const char *));
+
+#ifdef DLLTOOL_MCORE_ELF
+static void mcore_elf_cache_filename (char *);
+static void mcore_elf_gen_out_file (void);
+#endif
+
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#else /* ! HAVE_SYS_WAIT_H */
static iheadtype *import_list = NULL;
-static char *as_name = "as";
+static char *as_name = NULL;
static char * as_flags = "";
static int no_idata4;
static int add_underscore = 0;
static int dontdeltemps = 0;
-#ifdef DLLTOOL_ARM
-static int interwork = 0;
-#endif
-
/* True if we should export all symbols. Otherwise, we only export
symbols listed in .drectve sections or in the def file. */
static boolean export_all_symbols;
static int machine;
static int killat;
+static int add_stdcall_alias;
static int verbose;
static FILE *output_def;
static FILE *base_file;
static const char *mname = "ppc";
#endif
+#ifdef DLLTOOL_MCORE
+static const char * mname = "mcore";
+#endif
+
+#ifdef DLLTOOL_MCORE_ELF
+static const char * mname = "mcore-elf";
+static char * mcore_elf_out_file = NULL;
+static char * mcore_elf_linker = NULL;
+static char * mcore_elf_linker_flags = NULL;
+
+#define DRECTVE_SECTION_NAME ((machine == MMCORE_ELF || machine == MMCORE_ELF_LE) ? ".exports" : ".drectve")
+#endif
+
+#ifndef DRECTVE_SECTION_NAME
+#define DRECTVE_SECTION_NAME ".drectve"
+#endif
+
#define PATHMAX 250 /* What's the right name for this ? */
#define TMP_ASM "dc.s"
#define TMP_TAIL_O "dt.o"
#define TMP_STUB "ds"
-/* This bit of assemly does jmp * ....
-s set how_jtab_roff to mark where the 32bit abs branch should go */
+/* This bit of assemly does jmp * .... */
static const unsigned char i386_jtab[] =
{
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
static const unsigned char arm_jtab[] =
{
- 0x00, 0xc0, 0x9f, 0xe5,
- 0x00, 0xf0, 0x9c, 0xe5,
+ 0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
+ 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */
+ 0, 0, 0, 0
+};
+
+static const unsigned char arm_interwork_jtab[] =
+{
+ 0x04, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
+ 0x00, 0xc0, 0x9c, 0xe5, /* ldr ip, [ip] */
+ 0x1c, 0xff, 0x2f, 0xe1, /* bx ip */
0, 0, 0, 0
};
static const unsigned char thumb_jtab[] =
{
- 0xc0, 0xb4,
- 0x02, 0x4e,
- 0x36, 0x68,
- 0x01, 0x96,
- 0x40, 0xbd,
- 0xc0, 0x46,
+ 0x40, 0xb4, /* push {r6} */
+ 0x02, 0x4e, /* ldr r6, [pc, #8] */
+ 0x36, 0x68, /* ldr r6, [r6] */
+ 0xb4, 0x46, /* mov ip, r6 */
+ 0x40, 0xbc, /* pop {r6} */
+ 0x60, 0x47, /* bx ip */
0, 0, 0, 0
};
+static const unsigned char mcore_be_jtab[] =
+{
+ 0x70, 0x01, /* jmpi 1 */
+ 0x12, 0x11, /* nop */
+ 0x00, 0x00, 0x00, 0x00 /* <address> */
+};
+
+static const unsigned char mcore_le_jtab[] =
+{
+ 0x01, 0x70, /* jmpi 1 */
+ 0x11, 0x12, /* nop */
+ 0x00, 0x00, 0x00, 0x00 /* <address> */
+};
+
/* This is the glue sequence for PowerPC PE. There is a */
/* tocrel16-tocdefn reloc against the first instruction. */
/* We also need a IMGLUE reloc against the glue function */
static bfd_vma ppc_glue_insn = 0x80410004;
#endif
-/* The outfile array must be big enough to contain a fully
- qualified path name, plus an arbitary series of command
- line switches. We hope that PATH_MAX times two will be
- enough. */
-static char outfile [PATHMAX * 2];
-
struct mac
{
const char *type;
{
#define MTHUMB 3
"thumb", ".byte", ".short", ".long", ".asciz", "@",
- "push\t{r6, r7}\n\tldr\tr6, [pc, #8]\n\tldr\tr6, [r6]\n\tstr\tr6, [sp, #4]\n\tpop\t{r6, pc}\n\tnop",
+ "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","pe-arm-little", bfd_arch_arm,
thumb_jtab, sizeof (thumb_jtab), 12
}
,
-{ 0}
+#define MARM_INTERWORK 4
+ {
+ "arm_interwork", ".byte", ".short", ".long", ".asciz", "@",
+ "ldr\tip,[pc]\n\tldr\tip,[ip]\n\tbx\tip\n\t.long",
+ ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
+ arm_interwork_jtab, sizeof (arm_interwork_jtab), 12
+ }
+ ,
+ {
+#define MMCORE_BE 5
+ "mcore", ".byte", ".short", ".long", ".asciz", "//",
+ "jmpi\t1\n\tnop\n\t.long",
+ ".global", ".space", ".align\t2",".align\t4","pe-mcore-big", bfd_arch_mcore,
+ mcore_be_jtab, sizeof (mcore_be_jtab), 8
+ }
+ ,
+ {
+#define MMCORE_LE 6
+ "mcore-le", ".byte", ".short", ".long", ".asciz", "//",
+ "jmpi\t1\n\tnop\n\t.long",
+ ".global", ".space", ".align\t2",".align\t4","pe-mcore-little", bfd_arch_mcore,
+ mcore_le_jtab, sizeof (mcore_le_jtab), 8
+ }
+ ,
+ {
+#define MMCORE_ELF 7
+ "mcore-elf", ".byte", ".short", ".long", ".asciz", "//",
+ "jmpi\t1\n\tnop\n\t.long",
+ ".global", ".space", ".align\t2",".align\t4","elf32-mcore-big", bfd_arch_mcore,
+ mcore_be_jtab, sizeof (mcore_be_jtab), 8
+ }
+ ,
+ {
+#define MMCORE_ELF_LE 8
+ "mcore-elf-le", ".byte", ".short", ".long", ".asciz", "//",
+ "jmpi\t1\n\tnop\n\t.long",
+ ".global", ".space", ".align\t2",".align\t4","elf32-mcore-little", bfd_arch_mcore,
+ mcore_le_jtab, sizeof (mcore_le_jtab), 8
+ }
+ ,
+ { 0}
};
typedef struct dlist
case M386:
case MPPC:
case MTHUMB:
+ case MARM_INTERWORK:
+ case MMCORE_BE:
+ case MMCORE_LE:
+ case MMCORE_ELF:
+ case MMCORE_ELF_LE:
break;
default:
/* xgettext:c-format */
case M386:
case MPPC:
case MTHUMB:
+ case MARM_INTERWORK:
+ case MMCORE_BE:
+ case MMCORE_LE:
+ case MMCORE_ELF:
+ case MMCORE_ELF_LE:
return ".rva\t";
default:
/* xgettext:c-format */
case MARM:
case MPPC:
case MTHUMB:
+ case MARM_INTERWORK:
+ case MMCORE_BE:
+ case MMCORE_LE:
+ case MMCORE_ELF:
+ case MMCORE_ELF_LE:
break;
case M386:
return "_";
#define ASM_RVA_BEFORE rvabefore(machine)
#define ASM_RVA_AFTER rvaafter(machine)
#define ASM_PREFIX asm_prefix(machine)
-#define ASM_ALIGN_LONG mtable[machine].how_align_long
+#define ASM_ALIGN_LONG mtable[machine].how_align_long
#define HOW_BFD_TARGET 0 /* always default*/
-#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_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
static char **oav;
void
warn (_("Can't have LIBRARY and NAME\n"));
d_name = name;
+ /* if --dllname not provided, use the one in the DEF file.
+ FIXME: Is this appropriate for executables? */
+ if (! dll_name)
+ dll_name = xstrdup (name);
d_is_exe = 1;
}
warn (_("%s: Can't have LIBRARY and NAME\n"), program_name);
d_name = name;
+ /* if --dllname not provided, use the one in the DEF file. */
+ if (! dll_name)
+ dll_name = xstrdup (name);
d_is_dll = 1;
}
char * buf;
char * p;
char * e;
-
+
/* Look for .drectve's */
- s = bfd_get_section_by_name (abfd, ".drectve");
+ s = bfd_get_section_by_name (abfd, DRECTVE_SECTION_NAME);
if (s == NULL)
return;
bfd_get_section_contents (abfd, s, buf, 0, size);
/* xgettext:c-format */
- inform (_("Sucking in info from .drective section in %s\n"),
- bfd_get_filename (abfd));
+ inform (_("Sucking in info from %s section in %s\n"),
+ DRECTVE_SECTION_NAME, bfd_get_filename (abfd));
/* Search for -export: strings */
p = buf;
c = xmalloc (p - name + 1);
memcpy (c, name, p - name);
c[p - name] = 0;
+
/* FIXME: The 5th arg is for the `constant' field.
What should it be? Not that it matters since it's not
currently useful. */
def_exports (c, 0, -1, 0, 0, 0);
+
+ if (add_stdcall_alias && strchr (c, '@'))
+ {
+ char *exported_name = xstrdup (c);
+ char *atsym = strchr (exported_name, '@');
+ *atsym = '\0';
+ def_exports (exported_name, xstrdup (c), -1, 0, 0, 0);
+ }
}
else
p++;
if (bfd_get_symbol_leading_char (abfd) == symbol_name[0])
++symbol_name;
- def_exports (xstrdup (symbol_name), 0, -1, 0, 0, 0);
+ def_exports (xstrdup (symbol_name) , 0, -1, 0, 0, 0);
+
+ if (add_stdcall_alias && strchr (symbol_name, '@'))
+ {
+ char *exported_name = xstrdup (symbol_name);
+ char *atsym = strchr (exported_name, '@');
+ *atsym = '\0';
+ def_exports (exported_name, xstrdup (symbol_name), -1, 0, 0, 0);
+ }
}
}
PTR minisyms;
unsigned int size;
+ /* Ignore bfds with an import descriptor table. We assume that any
+ such BFD contains symbols which are exported from another DLL,
+ and we don't want to reexport them from here. */
+ if (bfd_get_section_by_name (abfd, ".idata$4"))
+ return;
+
if (! (bfd_get_file_flags (abfd) & HAS_SYMS))
{
/* xgettext:c-format */
/* FIXME: we ought to read in and block out the base relocations */
/* xgettext:c-format */
- inform (_("%s: Done reading %s\n"), bfd_get_filename (abfd));
+ inform (_("Done reading %s\n"), bfd_get_filename (abfd));
}
static void
bfd_close (arfile);
arfile = bfd_openr_next_archived_file (f, arfile);
}
+
+#ifdef DLLTOOL_MCORE_ELF
+ if (mcore_elf_out_file)
+ inform (_("Cannot produce mcore-elf dll from archive file: %s"), filename);
+#endif
}
else if (bfd_check_format (f, bfd_object))
{
scan_open_obj_file (f);
+
+#ifdef DLLTOOL_MCORE_ELF
+ if (mcore_elf_out_file)
+ mcore_elf_cache_filename ((char *) filename);
+#endif
}
bfd_close (f);
char *quote = strchr (exp->name, '.') ? "\"" : "";
char *res = cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS);
- fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
- quote,
- exp->name,
- quote,
- exp->ordinal,
- exp->noname ? " NONAME" : "",
- exp->data ? " DATA" : "",
- res ? res : "");
+ if (strcmp (exp->name, exp->internal_name) == 0)
+ {
+
+ fprintf (output_def, "\t%s%s%s @ %d%s%s ; %s\n",
+ quote,
+ exp->name,
+ quote,
+ exp->ordinal,
+ exp->noname ? " NONAME" : "",
+ exp->data ? " DATA" : "",
+ res ? res : "");
+ }
+ else
+ {
+ char *quote1 = strchr (exp->internal_name, '.') ? "\"" : "";
+ /* char *alias = */
+ fprintf (output_def, "\t%s%s%s = %s%s%s @ %d%s%s ; %s\n",
+ quote,
+ exp->name,
+ quote,
+ quote1,
+ exp->internal_name,
+ quote1,
+ exp->ordinal,
+ exp->noname ? " NONAME" : "",
+ exp->data ? " DATA" : "",
+ res ? res : "");
+ }
if (res)
free (res);
}
int i;
export_type *exp;
dlist_type *dl;
+ char *cmd;
/* xgettext:c-format */
inform (_("Generating export file: %s\n"), exp_name);
}
}
fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
- ASM_PREFIX,
- exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
+ ASM_PREFIX,
+ exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
i++;
}
if (a_list)
{
- fprintf (f, "\t.section .drectve\n");
+ fprintf (f, "\t.section %s\n", DRECTVE_SECTION_NAME);
for (dl = a_list; dl; dl = dl->next)
{
fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
}
}
+
if (d_list)
{
fprintf (f, "\t.section .rdata\n");
fclose (f);
/* assemble the file */
- sprintf (outfile, "%s -o %s %s", as_flags, exp_name, TMP_ASM);
+ cmd = (char *) alloca (strlen (as_flags) + strlen (exp_name)
+ + sizeof TMP_ASM + 50);
+ sprintf (cmd, "%s -o %s %s", as_flags, exp_name, TMP_ASM);
#ifdef DLLTOOL_ARM
- if (interwork)
- strcat (outfile, " -mthumb-interwork");
+ if (machine == MARM_INTERWORK || machine == MTHUMB)
+ strcat (cmd, " -mthumb-interwork");
#endif
-
- run (as_name, outfile);
-
+
+ run (as_name, cmd);
+
if (dontdeltemps == 0)
unlink (TMP_ASM);
{
#if 0
{
+ char *name;
FILE *f;
- char *prefix="d";
- sprintf (outfile, "%ss%d.s", prefix, i);
- f = fopen (outfile, FOPEN_WT);
+ const char *prefix = "d";
+ char *cmd;
+
+ name = (char *) alloca (strlen (prefix) + 10);
+ sprintf (name, "%ss%05d.s", prefix, i);
+ f = fopen (name, FOPEN_WT);
fprintf (f, "\t.text\n");
fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
fclose (f);
- sprintf (outfile, "%s -o %ss%d.o %ss%d.s",
+ cmd = (char *) alloca (strlen (as_flags) + 2 * strlen (prefix) + 50);
+ sprintf (cmd, "%s -o %ss%05d.o %ss%d.s",
as_flags, prefix, i, prefix, i);
#ifdef DLLTOOL_ARM
- if (interwork)
- strcat (outfile, " -mthumb-interwork");
+ if (machine == MARM_INTERWORK || machine == MTHUMB)
+ strcat (cmd, " -mthumb-interwork");
#endif
- run (as_name, outfile);
+ run (as_name, cmd);
}
#else /* if 0 */
{
int oidx = 0;
- sprintf (outname, "%s%d.o", TMP_STUB, i);
+ sprintf (outname, "%s%05d.o", TMP_STUB, i);
abfd = bfd_openw (outname, HOW_BFD_TARGET);
bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
#ifdef DLLTOOL_ARM
- if (interwork)
+ if (machine == MARM_INTERWORK || machine == MTHUMB)
bfd_set_private_flags (abfd, F_INTERWORK);
#endif
#ifdef DLLTOOL_ARM
if (machine == MTHUMB)
- bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXT);
+ bfd_coff_set_symbol_class (abfd, exp_label, C_THUMBEXTFUNC);
#endif
ptrs[oidx++] = exp_label;
}
static bfd *
make_head ()
{
- FILE * f = fopen (TMP_HEAD_S, FOPEN_WT);
+ FILE *f = fopen (TMP_HEAD_S, FOPEN_WT);
+ char *cmd;
+ if (f == NULL)
+ {
+ fatal (_("failed to open temporary head file: %s"), TMP_HEAD_S);
+ return NULL;
+ }
+
fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
fprintf (f, "\t.section .idata$2\n");
fprintf (f, "\t%s\t0\n", ASM_LONG);
fprintf (f, "fthunk:\n");
}
+
if (!no_idata4)
{
fprintf (f, "\t.section\t.idata$4\n");
fprintf (f, "\t.section .idata$4\n");
fprintf (f, "hname:\n");
}
+
fclose (f);
- sprintf (outfile, "%s -o %s %s", as_flags, TMP_HEAD_O, TMP_HEAD_S);
+ cmd = (char *) alloca (strlen (as_flags) + sizeof TMP_HEAD_O
+ + sizeof TMP_HEAD_S + 50);
+ sprintf (cmd, "%s -o %s %s", as_flags, TMP_HEAD_O, TMP_HEAD_S);
#ifdef DLLTOOL_ARM
- if (interwork)
- strcat (outfile, " -mthumb-interwork");
+ if (machine == MARM_INTERWORK || machine == MTHUMB)
+ strcat (cmd, " -mthumb-interwork");
#endif
- run (as_name, outfile);
+ run (as_name, cmd);
- return bfd_openr (TMP_HEAD_O, HOW_BFD_TARGET);
+ return bfd_openr (TMP_HEAD_O, HOW_BFD_TARGET);
}
static bfd *
make_tail ()
{
- FILE * f = fopen (TMP_TAIL_S, FOPEN_WT);
+ FILE *f = fopen (TMP_TAIL_S, FOPEN_WT);
+ char *cmd;
+ if (f == NULL)
+ {
+ fatal (_("failed to open temporary tail file: %s"), TMP_TAIL_S);
+ return NULL;
+ }
+
if (!no_idata4)
{
fprintf (f, "\t.section .idata$4\n");
fprintf (f, "\t%s\t0\n", ASM_LONG);
}
+
if (!no_idata5)
{
fprintf (f, "\t.section .idata$5\n");
fclose (f);
- sprintf (outfile, "%s -o %s %s", as_flags, TMP_TAIL_O, TMP_TAIL_S);
+ cmd = (char *) alloca (strlen (as_flags) + sizeof TMP_TAIL_O
+ + sizeof TMP_TAIL_S + 50);
+ sprintf (cmd, "%s -o %s %s", as_flags, TMP_TAIL_O, TMP_TAIL_S);
#ifdef DLLTOOL_ARM
- if (interwork)
- strcat (outfile, " -mthumb-interwork");
+ if (machine == MARM_INTERWORK || MTHUMB)
+ strcat (cmd, " -mthumb-interwork");
#endif
- run (as_name, outfile);
+ run (as_name, cmd);
return bfd_openr (TMP_TAIL_O, HOW_BFD_TARGET);
}
if (dontdeltemps < 2)
{
+ char *name;
+
+ name = (char *) alloca (sizeof TMP_STUB + 10);
for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
{
- sprintf (outfile, "%s%d.o", TMP_STUB, i);
- if (unlink (outfile) < 0)
+ sprintf (name, "%s%05d.o", TMP_STUB, i);
+ if (unlink (name) < 0)
/* xgettext:c-format */
- warn (_("cannot delete %s: %s\n"), outfile, strerror (errno));
+ warn (_("cannot delete %s: %s\n"), name, strerror (errno));
}
}
/* xgetext:c-format */
fprintf (file, _("Usage %s <options> <object-files>\n"), program_name);
/* xgetext:c-format */
- fprintf (file, _(" -m --machine <machine> Create {arm, i386, ppc, thumb} DLL. [default: %s]\n"), mname);
+ fprintf (file, _(" -m --machine <machine> Create as DLL for <machine>. [default: %s]\n"), mname);
+ fprintf (file, _(" possible <machine>: arm[_interwork], i386, mcore[-elf][-le], 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, _(" -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"));
fprintf (file, _(" -z --output-def <deffile> Name of .def file to be created.\n"));
- fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
- fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n"));
- fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n"));
- fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n"));
+ fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
+ fprintf (file, _(" --no-export-all-symbols Only export listed symbols\n"));
+ fprintf (file, _(" --exclude-symbols <list> Don't export <list>\n"));
+ fprintf (file, _(" --no-default-excludes Clear default exclude symbols\n"));
fprintf (file, _(" -b --base-file <basefile> Read linker generated base file.\n"));
fprintf (file, _(" -x --no-idata4 Don't generate idata$4 section.\n"));
fprintf (file, _(" -c --no-idata5 Don't generate idata$5 section.\n"));
fprintf (file, _(" -U --add-underscore Add underscores to symbols in interface library.\n"));
fprintf (file, _(" -k --kill-at Kill @<n> from exported names.\n"));
+ fprintf (file, _(" -A --add-stdcall-alias Add aliases without @<n>.\n"));
fprintf (file, _(" -S --as <name> Use <name> for assembler.\n"));
fprintf (file, _(" -f --as-flags <flags> Pass <flags> to the assembler.\n"));
-#ifdef DLLTOOL_ARM
- fprintf (file, _(" -i --interwork Support ARM/Thumb interworking.\n"));
-#endif
fprintf (file, _(" -n --no-delete Keep temp files (repeat for extra preservation).\n"));
fprintf (file, _(" -v --verbose Be verbose.\n"));
fprintf (file, _(" -V --version Display the program version.\n"));
fprintf (file, _(" -h --help Display this information.\n"));
-
+#ifdef DLLTOOL_MCORE_ELF
+ fprintf (file, _(" -M --mcore-elf <outname> Process mcore-elf object files into <outname>.\n"));
+ fprintf (file, _(" -L --linker <name> Use <name> as the linker.\n"));
+ fprintf (file, _(" -F --linker-flags <flags> Pass <flags> to the linker.\n"));
+#endif
exit (status);
}
#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
-#define OPTION_NO_IDATA4 'x'
-#define OPTION_NO_IDATA5 'c'
static const struct option long_options[] =
{
{"no-delete", no_argument, NULL, 'n'},
{"dllname", required_argument, NULL, 'D'},
- {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
- {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
+ {"no-idata4", no_argument, NULL, 'x'},
+ {"no-idata5", no_argument, NULL, 'c'},
{"output-exp", required_argument, NULL, 'e'},
{"output-def", required_argument, NULL, 'z'},
{"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
{"input-def", required_argument, NULL, 'd'},
{"add-underscore", no_argument, NULL, 'U'},
{"kill-at", no_argument, NULL, 'k'},
+ {"add-stdcall-alias", no_argument, NULL, 'A'},
{"verbose", no_argument, NULL, 'v'},
{"version", no_argument, NULL, 'V'},
{"help", no_argument, NULL, 'h'},
{"base-file", required_argument, NULL, 'b'},
{"as", required_argument, NULL, 'S'},
{"as-flags", required_argument, NULL, 'f'},
-#ifdef DLLTOOL_ARM
- {"interwork", no_argument, NULL, 'i'},
-#endif
+ {"mcore-elf", required_argument, NULL, 'M'},
{0}
};
program_name = av[0];
oav = av;
-#ifdef HAVE_SETLOCALE
+#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
setlocale (LC_MESSAGES, "");
#endif
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
- while ((c = getopt_long (ac, av, "xcz:S:aD:l:e:nkvVb:Uh?m:d:f:i",
+ while ((c = getopt_long (ac, av,
+#ifdef DLLTOOL_MCORE_ELF
+ "m:e:l:aD:d:z:b:xcuUkAS:f:nvVhM:L:F:",
+#else
+ "m:e:l:aD:d:z:b:xcuUkAS:f:nvVh",
+#endif
long_options, 0))
!= EOF)
{
switch (c)
{
- case OPTION_NO_IDATA4:
- no_idata4 = 1;
- break;
- case OPTION_NO_IDATA5:
- no_idata5 = 1;
- break;
case OPTION_EXPORT_ALL_SYMS:
export_all_symbols = true;
break;
case OPTION_NO_DEFAULT_EXCLUDES:
do_default_excludes = false;
break;
+ case 'x':
+ no_idata4 = 1;
+ break;
+ case 'c':
+ no_idata5 = 1;
+ break;
case 'S':
as_name = optarg;
break;
case 'V':
print_version (program_name);
break;
-#ifdef DLLTOOL_ARM
- case 'i':
- interwork = 1;
- break;
-#endif
- case 'y':
-#if 0
- /* We don't currently define YYDEBUG when building
- defparse.y. */
- yydebug = 1;
-#endif
- break;
case 'U':
add_underscore = 1;
break;
case 'k':
killat = 1;
break;
+ case 'A':
+ add_stdcall_alias = 1;
+ break;
case 'd':
def_file = optarg;
break;
fatal (_("Unable to open base-file: %s"), optarg);
break;
+#ifdef DLLTOOL_MCORE_ELF
+ case 'M':
+ mcore_elf_out_file = optarg;
+ break;
+ case 'L':
+ mcore_elf_linker = optarg;
+ break;
+ case 'F':
+ mcore_elf_linker_flags = optarg;
+ break;
+#endif
default:
usage (stderr, 1);
break;
}
for (i = 0; mtable[i].type; i++)
- {
- if (strcmp (mtable[i].type, mname) == 0)
- break;
- }
+ if (strcmp (mtable[i].type, mname) == 0)
+ break;
if (!mtable[i].type)
/* xgettext:c-format */
machine = i;
-#ifdef DLLTOOL_ARM
- /* Always enable interworking for Thumb targets. */
- if (machine == MTHUMB && (! interwork))
- interwork = 1;
-#endif
-
if (!dll_name && exp_name)
{
int len = strlen (exp_name) + 5;
strcat (dll_name, ".dll");
}
+ if (as_name == NULL)
+ as_name = deduce_name ("as");
+
/* Don't use the default exclude list if we're reading only the
symbols in the .drectve section. The default excludes are meant
to avoid exporting DLL entry point and Cygwin32 impure_ptr. */
if (output_def)
gen_def_file ();
-
+
+#ifdef DLLTOOL_MCORE_ELF
+ if (mcore_elf_out_file)
+ mcore_elf_gen_out_file ();
+#endif
+
return 0;
}
+
+/* Look for the program formed by concatenating PROG_NAME and the
+ string running from PREFIX to END_PREFIX. If the concatenated
+ string contains a '/', try appending EXECUTABLE_SUFFIX if it is
+ appropriate. */
+
+static char *
+look_for_prog (prog_name, prefix, end_prefix)
+ const char *prog_name;
+ const char *prefix;
+ int end_prefix;
+{
+ struct stat s;
+ char *cmd;
+
+ cmd = xmalloc (strlen (prefix)
+ + strlen (prog_name)
+#ifdef HAVE_EXECUTABLE_SUFFIX
+ + strlen (EXECUTABLE_SUFFIX)
+#endif
+ + 10);
+ strcpy (cmd, prefix);
+
+ sprintf (cmd + end_prefix, "%s", prog_name);
+
+ if (strchr (cmd, '/') != NULL)
+ {
+ int found;
+
+ found = (stat (cmd, &s) == 0
+#ifdef HAVE_EXECUTABLE_SUFFIX
+ || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
+#endif
+ );
+
+ if (! found)
+ {
+ /* xgettext:c-format */
+ inform (_("Tried file: %s"), cmd);
+ free (cmd);
+ return NULL;
+ }
+ }
+
+ /* xgettext:c-format */
+ inform (_("Using file: %s"), cmd);
+
+ return cmd;
+}
+
+/* Deduce the name of the program we are want to invoke.
+ PROG_NAME is the basic name of the program we want to run,
+ eg "as" or "ld". The catch is that we might want actually
+ run "i386-pe-as" or "ppc-pe-ld".
+
+ If argv[0] contains the full path, then try to find the program
+ in the same place, with and then without a target-like prefix.
+
+ Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
+ deduce_name("as") uses the following search order:
+
+ /usr/local/bin/i586-cygwin32-as
+ /usr/local/bin/as
+ as
+
+ If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
+ name, it'll try without and then with EXECUTABLE_SUFFIX.
+
+ Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
+ as the fallback, but rather return i586-cygwin32-as.
+
+ Oh, and given, argv[0] = dlltool, it'll return "as".
+
+ Returns a dynamically allocated string. */
+
+static char *
+deduce_name (prog_name)
+ const char *prog_name;
+{
+ char *cmd;
+ char *dash, *slash, *cp;
+
+ dash = NULL;
+ slash = NULL;
+ for (cp = program_name; *cp != '\0'; ++cp)
+ {
+ if (*cp == '-')
+ dash = cp;
+ if (
+#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
+ *cp == ':' || *cp == '\\' ||
+#endif
+ *cp == '/')
+ {
+ slash = cp;
+ dash = NULL;
+ }
+ }
+
+ cmd = NULL;
+
+ if (dash != NULL)
+ {
+ /* First, try looking for a prefixed PROG_NAME in the
+ PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */
+ cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
+ }
+
+ if (slash != NULL && cmd == NULL)
+ {
+ /* Next, try looking for a PROG_NAME in the same directory as
+ that of this program. */
+ cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
+ }
+
+ if (cmd == NULL)
+ {
+ /* Just return PROG_NAME as is. */
+ cmd = xstrdup (prog_name);
+ }
+
+ return cmd;
+}
+
+#ifdef DLLTOOL_MCORE_ELF
+typedef struct fname_cache
+{
+ char * filename;
+ struct fname_cache * next;
+}
+fname_cache;
+
+static fname_cache fnames;
+
+static void
+mcore_elf_cache_filename (char * filename)
+{
+ fname_cache * ptr;
+
+ ptr = & fnames;
+
+ while (ptr->next != NULL)
+ ptr = ptr->next;
+
+ ptr->filename = filename;
+ ptr->next = (fname_cache *) malloc (sizeof (fname_cache));
+ if (ptr->next != NULL)
+ ptr->next->next = NULL;
+}
+
+#define MCORE_ELF_TMP_OBJ "mcoreelf.o"
+#define MCORE_ELF_TMP_EXP "mcoreelf.exp"
+#define MCORE_ELF_TMP_LIB "mcoreelf.lib"
+
+static void
+mcore_elf_gen_out_file (void)
+{
+ fname_cache * ptr;
+ dyn_string_t ds;
+
+ /* Step one. Run 'ld -r' on the input object files in order to resolve
+ any internal references and to generate a single .exports section. */
+ ptr = & fnames;
+
+ ds = dyn_string_new (100);
+ dyn_string_append (ds, "-r ");
+
+ if (mcore_elf_linker_flags != NULL)
+ dyn_string_append (ds, mcore_elf_linker_flags);
+
+ while (ptr->next != NULL)
+ {
+ dyn_string_append (ds, ptr->filename);
+ dyn_string_append (ds, " ");
+
+ ptr = ptr->next;
+ }
+
+ dyn_string_append (ds, "-o ");
+ dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
+
+ if (mcore_elf_linker == NULL)
+ mcore_elf_linker = deduce_name ("ld");
+
+ run (mcore_elf_linker, ds->s);
+
+ dyn_string_delete (ds);
+
+ /* Step two. Create a .exp file and a .lib file from the temporary file.
+ Do this by recursively invoking dlltool....*/
+ ds = dyn_string_new (100);
+
+ dyn_string_append (ds, "-S ");
+ dyn_string_append (ds, as_name);
+
+ dyn_string_append (ds, " -e ");
+ dyn_string_append (ds, MCORE_ELF_TMP_EXP);
+ dyn_string_append (ds, " -l ");
+ dyn_string_append (ds, MCORE_ELF_TMP_LIB);
+ dyn_string_append (ds, " " );
+ dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
+
+ if (verbose)
+ dyn_string_append (ds, " -v");
+
+ if (dontdeltemps)
+ {
+ dyn_string_append (ds, " -n");
+
+ if (dontdeltemps > 1)
+ dyn_string_append (ds, " -n");
+ }
+
+ /* XXX - FIME: ought to check/copy other command line options as well. */
+
+ run (program_name, ds->s);
+
+ dyn_string_delete (ds);
+
+ /* Step four. Feed the .exp and object files to ld -shared to create the dll. */
+ ds = dyn_string_new (100);
+
+ dyn_string_append (ds, "-shared ");
+
+ if (mcore_elf_linker_flags)
+ dyn_string_append (ds, mcore_elf_linker_flags);
+
+ dyn_string_append (ds, " ");
+ dyn_string_append (ds, MCORE_ELF_TMP_EXP);
+ dyn_string_append (ds, " ");
+ dyn_string_append (ds, MCORE_ELF_TMP_OBJ);
+ dyn_string_append (ds, " -o ");
+ dyn_string_append (ds, mcore_elf_out_file);
+
+ run (mcore_elf_linker, ds->s);
+
+ dyn_string_delete (ds);
+
+ if (dontdeltemps == 0)
+ unlink (MCORE_ELF_TMP_EXP);
+
+ if (dontdeltemps < 2)
+ unlink (MCORE_ELF_TMP_OBJ);
+}
+#endif /* DLLTOOL_MCORE_ELF */