13d8817e4Smiod /* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs
23d8817e4Smiod Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
33d8817e4Smiod Contributed by Mumit Khan (khan@xraylith.wisc.edu).
43d8817e4Smiod
53d8817e4Smiod This file is part of GNU Binutils.
63d8817e4Smiod
73d8817e4Smiod This program is free software; you can redistribute it and/or modify
83d8817e4Smiod it under the terms of the GNU General Public License as published by
93d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
103d8817e4Smiod (at your option) any later version.
113d8817e4Smiod
123d8817e4Smiod This program is distributed in the hope that it will be useful,
133d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
143d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
153d8817e4Smiod GNU General Public License for more details.
163d8817e4Smiod
173d8817e4Smiod You should have received a copy of the GNU General Public License
183d8817e4Smiod along with this program; if not, write to the Free Software
193d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
203d8817e4Smiod 02110-1301, USA. */
213d8817e4Smiod
223d8817e4Smiod /* AIX requires this to be the first thing in the file. */
233d8817e4Smiod #ifndef __GNUC__
243d8817e4Smiod # ifdef _AIX
253d8817e4Smiod #pragma alloca
263d8817e4Smiod #endif
273d8817e4Smiod #endif
283d8817e4Smiod
293d8817e4Smiod #ifdef HAVE_CONFIG_H
303d8817e4Smiod #include "config.h"
313d8817e4Smiod #endif
323d8817e4Smiod
333d8817e4Smiod #include "bfd.h"
343d8817e4Smiod #include "libiberty.h"
353d8817e4Smiod #include "bucomm.h"
363d8817e4Smiod #include "getopt.h"
373d8817e4Smiod #include "dyn-string.h"
383d8817e4Smiod
393d8817e4Smiod #include <time.h>
403d8817e4Smiod #include <sys/stat.h>
413d8817e4Smiod #include <stdarg.h>
423d8817e4Smiod
433d8817e4Smiod #ifdef HAVE_SYS_WAIT_H
443d8817e4Smiod #include <sys/wait.h>
453d8817e4Smiod #else /* ! HAVE_SYS_WAIT_H */
463d8817e4Smiod #if ! defined (_WIN32) || defined (__CYGWIN32__)
473d8817e4Smiod #ifndef WIFEXITED
483d8817e4Smiod #define WIFEXITED(w) (((w)&0377) == 0)
493d8817e4Smiod #endif
503d8817e4Smiod #ifndef WIFSIGNALED
513d8817e4Smiod #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
523d8817e4Smiod #endif
533d8817e4Smiod #ifndef WTERMSIG
543d8817e4Smiod #define WTERMSIG(w) ((w) & 0177)
553d8817e4Smiod #endif
563d8817e4Smiod #ifndef WEXITSTATUS
573d8817e4Smiod #define WEXITSTATUS(w) (((w) >> 8) & 0377)
583d8817e4Smiod #endif
593d8817e4Smiod #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
603d8817e4Smiod #ifndef WIFEXITED
613d8817e4Smiod #define WIFEXITED(w) (((w) & 0xff) == 0)
623d8817e4Smiod #endif
633d8817e4Smiod #ifndef WIFSIGNALED
643d8817e4Smiod #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
653d8817e4Smiod #endif
663d8817e4Smiod #ifndef WTERMSIG
673d8817e4Smiod #define WTERMSIG(w) ((w) & 0x7f)
683d8817e4Smiod #endif
693d8817e4Smiod #ifndef WEXITSTATUS
703d8817e4Smiod #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
713d8817e4Smiod #endif
723d8817e4Smiod #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
733d8817e4Smiod #endif /* ! HAVE_SYS_WAIT_H */
743d8817e4Smiod
753d8817e4Smiod static char *driver_name = NULL;
763d8817e4Smiod static char *cygwin_driver_flags =
773d8817e4Smiod "-Wl,--dll -nostartfiles";
783d8817e4Smiod static char *mingw32_driver_flags = "-mdll";
793d8817e4Smiod static char *generic_driver_flags = "-Wl,--dll";
803d8817e4Smiod
813d8817e4Smiod static char *entry_point;
823d8817e4Smiod
833d8817e4Smiod static char *dlltool_name = NULL;
843d8817e4Smiod
853d8817e4Smiod static char *target = TARGET;
863d8817e4Smiod
873d8817e4Smiod typedef enum {
883d8817e4Smiod UNKNOWN_TARGET,
893d8817e4Smiod CYGWIN_TARGET,
903d8817e4Smiod MINGW_TARGET
913d8817e4Smiod }
923d8817e4Smiod target_type;
933d8817e4Smiod
943d8817e4Smiod static target_type which_target = UNKNOWN_TARGET;
953d8817e4Smiod
963d8817e4Smiod static int dontdeltemps = 0;
973d8817e4Smiod static int dry_run = 0;
983d8817e4Smiod
993d8817e4Smiod static char *prog_name;
1003d8817e4Smiod
1013d8817e4Smiod static int verbose = 0;
1023d8817e4Smiod
1033d8817e4Smiod static char *dll_file_name;
1043d8817e4Smiod static char *dll_name;
1053d8817e4Smiod static char *base_file_name;
1063d8817e4Smiod static char *exp_file_name;
1073d8817e4Smiod static char *def_file_name;
1083d8817e4Smiod static int delete_base_file = 1;
1093d8817e4Smiod static int delete_exp_file = 1;
1103d8817e4Smiod static int delete_def_file = 1;
1113d8817e4Smiod
1123d8817e4Smiod static int run (const char *, char *);
1133d8817e4Smiod static char *mybasename (const char *);
1143d8817e4Smiod static int strhash (const char *);
1153d8817e4Smiod static void usage (FILE *, int);
1163d8817e4Smiod static void display (const char *, va_list) ATTRIBUTE_PRINTF(1,0);
1173d8817e4Smiod static void inform (const char *, ...) ATTRIBUTE_PRINTF_1;
1183d8817e4Smiod static void warn (const char *, ...) ATTRIBUTE_PRINTF_1;
1193d8817e4Smiod static char *look_for_prog (const char *, const char *, int);
1203d8817e4Smiod static char *deduce_name (const char *);
1213d8817e4Smiod static void delete_temp_files (void);
1223d8817e4Smiod static void cleanup_and_exit (int);
1233d8817e4Smiod
1243d8817e4Smiod /**********************************************************************/
1253d8817e4Smiod
1263d8817e4Smiod /* Please keep the following 4 routines in sync with dlltool.c:
1273d8817e4Smiod display ()
1283d8817e4Smiod inform ()
1293d8817e4Smiod look_for_prog ()
1303d8817e4Smiod deduce_name ()
1313d8817e4Smiod It's not worth the hassle to break these out since dllwrap will
1323d8817e4Smiod (hopefully) soon be retired in favor of `ld --shared. */
1333d8817e4Smiod
1343d8817e4Smiod static void
display(const char * message,va_list args)1353d8817e4Smiod display (const char * message, va_list args)
1363d8817e4Smiod {
1373d8817e4Smiod if (prog_name != NULL)
1383d8817e4Smiod fprintf (stderr, "%s: ", prog_name);
1393d8817e4Smiod
1403d8817e4Smiod vfprintf (stderr, message, args);
1413d8817e4Smiod fputc ('\n', stderr);
1423d8817e4Smiod }
1433d8817e4Smiod
1443d8817e4Smiod
1453d8817e4Smiod static void
inform(const char * message,...)1463d8817e4Smiod inform VPARAMS ((const char *message, ...))
1473d8817e4Smiod {
1483d8817e4Smiod VA_OPEN (args, message);
1493d8817e4Smiod VA_FIXEDARG (args, const char *, message);
1503d8817e4Smiod
1513d8817e4Smiod if (!verbose)
1523d8817e4Smiod return;
1533d8817e4Smiod
1543d8817e4Smiod display (message, args);
1553d8817e4Smiod
1563d8817e4Smiod VA_CLOSE (args);
1573d8817e4Smiod }
1583d8817e4Smiod
1593d8817e4Smiod static void
warn(const char * format,...)1603d8817e4Smiod warn VPARAMS ((const char *format, ...))
1613d8817e4Smiod {
1623d8817e4Smiod VA_OPEN (args, format);
1633d8817e4Smiod VA_FIXEDARG (args, const char *, format);
1643d8817e4Smiod
1653d8817e4Smiod display (format, args);
1663d8817e4Smiod
1673d8817e4Smiod VA_CLOSE (args);
1683d8817e4Smiod }
1693d8817e4Smiod
1703d8817e4Smiod /* Look for the program formed by concatenating PROG_NAME and the
1713d8817e4Smiod string running from PREFIX to END_PREFIX. If the concatenated
1723d8817e4Smiod string contains a '/', try appending EXECUTABLE_SUFFIX if it is
1733d8817e4Smiod appropriate. */
1743d8817e4Smiod
1753d8817e4Smiod static char *
look_for_prog(const char * prog_name,const char * prefix,int end_prefix)1763d8817e4Smiod look_for_prog (const char *prog_name, const char *prefix, int end_prefix)
1773d8817e4Smiod {
1783d8817e4Smiod struct stat s;
1793d8817e4Smiod char *cmd;
1803d8817e4Smiod
1813d8817e4Smiod cmd = xmalloc (strlen (prefix)
1823d8817e4Smiod + strlen (prog_name)
1833d8817e4Smiod #ifdef HAVE_EXECUTABLE_SUFFIX
1843d8817e4Smiod + strlen (EXECUTABLE_SUFFIX)
1853d8817e4Smiod #endif
1863d8817e4Smiod + 10);
1873d8817e4Smiod strcpy (cmd, prefix);
1883d8817e4Smiod
1893d8817e4Smiod sprintf (cmd + end_prefix, "%s", prog_name);
1903d8817e4Smiod
1913d8817e4Smiod if (strchr (cmd, '/') != NULL)
1923d8817e4Smiod {
1933d8817e4Smiod int found;
1943d8817e4Smiod
1953d8817e4Smiod found = (stat (cmd, &s) == 0
1963d8817e4Smiod #ifdef HAVE_EXECUTABLE_SUFFIX
1973d8817e4Smiod || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
1983d8817e4Smiod #endif
1993d8817e4Smiod );
2003d8817e4Smiod
2013d8817e4Smiod if (! found)
2023d8817e4Smiod {
2033d8817e4Smiod /* xgettext:c-format */
2043d8817e4Smiod inform (_("Tried file: %s"), cmd);
2053d8817e4Smiod free (cmd);
2063d8817e4Smiod return NULL;
2073d8817e4Smiod }
2083d8817e4Smiod }
2093d8817e4Smiod
2103d8817e4Smiod /* xgettext:c-format */
2113d8817e4Smiod inform (_("Using file: %s"), cmd);
2123d8817e4Smiod
2133d8817e4Smiod return cmd;
2143d8817e4Smiod }
2153d8817e4Smiod
2163d8817e4Smiod /* Deduce the name of the program we are want to invoke.
2173d8817e4Smiod PROG_NAME is the basic name of the program we want to run,
2183d8817e4Smiod eg "as" or "ld". The catch is that we might want actually
2193d8817e4Smiod run "i386-pe-as" or "ppc-pe-ld".
2203d8817e4Smiod
2213d8817e4Smiod If argv[0] contains the full path, then try to find the program
2223d8817e4Smiod in the same place, with and then without a target-like prefix.
2233d8817e4Smiod
2243d8817e4Smiod Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
2253d8817e4Smiod deduce_name("as") uses the following search order:
2263d8817e4Smiod
2273d8817e4Smiod /usr/local/bin/i586-cygwin32-as
2283d8817e4Smiod /usr/local/bin/as
2293d8817e4Smiod as
2303d8817e4Smiod
2313d8817e4Smiod If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
2323d8817e4Smiod name, it'll try without and then with EXECUTABLE_SUFFIX.
2333d8817e4Smiod
2343d8817e4Smiod Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
2353d8817e4Smiod as the fallback, but rather return i586-cygwin32-as.
2363d8817e4Smiod
2373d8817e4Smiod Oh, and given, argv[0] = dlltool, it'll return "as".
2383d8817e4Smiod
2393d8817e4Smiod Returns a dynamically allocated string. */
2403d8817e4Smiod
2413d8817e4Smiod static char *
deduce_name(const char * name)2423d8817e4Smiod deduce_name (const char * name)
2433d8817e4Smiod {
2443d8817e4Smiod char *cmd;
2453d8817e4Smiod const char *dash;
2463d8817e4Smiod const char *slash;
2473d8817e4Smiod const char *cp;
2483d8817e4Smiod
2493d8817e4Smiod dash = NULL;
2503d8817e4Smiod slash = NULL;
2513d8817e4Smiod for (cp = prog_name; *cp != '\0'; ++cp)
2523d8817e4Smiod {
2533d8817e4Smiod if (*cp == '-')
2543d8817e4Smiod dash = cp;
2553d8817e4Smiod
2563d8817e4Smiod if (
2573d8817e4Smiod #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
2583d8817e4Smiod *cp == ':' || *cp == '\\' ||
2593d8817e4Smiod #endif
2603d8817e4Smiod *cp == '/')
2613d8817e4Smiod {
2623d8817e4Smiod slash = cp;
2633d8817e4Smiod dash = NULL;
2643d8817e4Smiod }
2653d8817e4Smiod }
2663d8817e4Smiod
2673d8817e4Smiod cmd = NULL;
2683d8817e4Smiod
2693d8817e4Smiod if (dash != NULL)
2703d8817e4Smiod /* First, try looking for a prefixed NAME in the
2713d8817e4Smiod PROG_NAME directory, with the same prefix as PROG_NAME. */
2723d8817e4Smiod cmd = look_for_prog (name, prog_name, dash - prog_name + 1);
2733d8817e4Smiod
2743d8817e4Smiod if (slash != NULL && cmd == NULL)
2753d8817e4Smiod /* Next, try looking for a NAME in the same directory as
2763d8817e4Smiod that of this program. */
2773d8817e4Smiod cmd = look_for_prog (name, prog_name, slash - prog_name + 1);
2783d8817e4Smiod
2793d8817e4Smiod if (cmd == NULL)
2803d8817e4Smiod /* Just return NAME as is. */
2813d8817e4Smiod cmd = xstrdup (name);
2823d8817e4Smiod
2833d8817e4Smiod return cmd;
2843d8817e4Smiod }
2853d8817e4Smiod
2863d8817e4Smiod static void
delete_temp_files(void)2873d8817e4Smiod delete_temp_files (void)
2883d8817e4Smiod {
2893d8817e4Smiod if (delete_base_file && base_file_name)
2903d8817e4Smiod {
2913d8817e4Smiod if (verbose)
2923d8817e4Smiod {
2933d8817e4Smiod if (dontdeltemps)
2943d8817e4Smiod warn (_("Keeping temporary base file %s"), base_file_name);
2953d8817e4Smiod else
2963d8817e4Smiod warn (_("Deleting temporary base file %s"), base_file_name);
2973d8817e4Smiod }
2983d8817e4Smiod if (! dontdeltemps)
2993d8817e4Smiod {
3003d8817e4Smiod unlink (base_file_name);
3013d8817e4Smiod free (base_file_name);
3023d8817e4Smiod }
3033d8817e4Smiod }
3043d8817e4Smiod
3053d8817e4Smiod if (delete_exp_file && exp_file_name)
3063d8817e4Smiod {
3073d8817e4Smiod if (verbose)
3083d8817e4Smiod {
3093d8817e4Smiod if (dontdeltemps)
3103d8817e4Smiod warn (_("Keeping temporary exp file %s"), exp_file_name);
3113d8817e4Smiod else
3123d8817e4Smiod warn (_("Deleting temporary exp file %s"), exp_file_name);
3133d8817e4Smiod }
3143d8817e4Smiod if (! dontdeltemps)
3153d8817e4Smiod {
3163d8817e4Smiod unlink (exp_file_name);
3173d8817e4Smiod free (exp_file_name);
3183d8817e4Smiod }
3193d8817e4Smiod }
3203d8817e4Smiod if (delete_def_file && def_file_name)
3213d8817e4Smiod {
3223d8817e4Smiod if (verbose)
3233d8817e4Smiod {
3243d8817e4Smiod if (dontdeltemps)
3253d8817e4Smiod warn (_("Keeping temporary def file %s"), def_file_name);
3263d8817e4Smiod else
3273d8817e4Smiod warn (_("Deleting temporary def file %s"), def_file_name);
3283d8817e4Smiod }
3293d8817e4Smiod if (! dontdeltemps)
3303d8817e4Smiod {
3313d8817e4Smiod unlink (def_file_name);
3323d8817e4Smiod free (def_file_name);
3333d8817e4Smiod }
3343d8817e4Smiod }
3353d8817e4Smiod }
3363d8817e4Smiod
3373d8817e4Smiod static void
cleanup_and_exit(int status)3383d8817e4Smiod cleanup_and_exit (int status)
3393d8817e4Smiod {
3403d8817e4Smiod delete_temp_files ();
3413d8817e4Smiod exit (status);
3423d8817e4Smiod }
3433d8817e4Smiod
3443d8817e4Smiod static int
run(const char * what,char * args)3453d8817e4Smiod run (const char *what, char *args)
3463d8817e4Smiod {
3473d8817e4Smiod char *s;
3483d8817e4Smiod int pid, wait_status, retcode;
3493d8817e4Smiod int i;
3503d8817e4Smiod const char **argv;
3513d8817e4Smiod char *errmsg_fmt, *errmsg_arg;
352*d2386abeSmiod #if defined(__MSDOS__) && !defined(__GO32__)
3533d8817e4Smiod char *temp_base = choose_temp_base ();
354*d2386abeSmiod #else
355*d2386abeSmiod char *temp_base = NULL;
356*d2386abeSmiod #endif
3573d8817e4Smiod int in_quote;
3583d8817e4Smiod char sep;
3593d8817e4Smiod
3603d8817e4Smiod if (verbose || dry_run)
3613d8817e4Smiod fprintf (stderr, "%s %s\n", what, args);
3623d8817e4Smiod
3633d8817e4Smiod /* Count the args */
3643d8817e4Smiod i = 0;
3653d8817e4Smiod for (s = args; *s; s++)
3663d8817e4Smiod if (*s == ' ')
3673d8817e4Smiod i++;
3683d8817e4Smiod i++;
3693d8817e4Smiod argv = alloca (sizeof (char *) * (i + 3));
3703d8817e4Smiod i = 0;
3713d8817e4Smiod argv[i++] = what;
3723d8817e4Smiod s = args;
3733d8817e4Smiod while (1)
3743d8817e4Smiod {
3753d8817e4Smiod while (*s == ' ' && *s != 0)
3763d8817e4Smiod s++;
3773d8817e4Smiod if (*s == 0)
3783d8817e4Smiod break;
3793d8817e4Smiod in_quote = (*s == '\'' || *s == '"');
3803d8817e4Smiod sep = (in_quote) ? *s++ : ' ';
3813d8817e4Smiod argv[i++] = s;
3823d8817e4Smiod while (*s != sep && *s != 0)
3833d8817e4Smiod s++;
3843d8817e4Smiod if (*s == 0)
3853d8817e4Smiod break;
3863d8817e4Smiod *s++ = 0;
3873d8817e4Smiod if (in_quote)
3883d8817e4Smiod s++;
3893d8817e4Smiod }
3903d8817e4Smiod argv[i++] = NULL;
3913d8817e4Smiod
3923d8817e4Smiod if (dry_run)
3933d8817e4Smiod return 0;
3943d8817e4Smiod
3953d8817e4Smiod pid = pexecute (argv[0], (char * const *) argv, prog_name, temp_base,
3963d8817e4Smiod &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
3973d8817e4Smiod
3983d8817e4Smiod if (pid == -1)
3993d8817e4Smiod {
4003d8817e4Smiod int errno_val = errno;
4013d8817e4Smiod
4023d8817e4Smiod fprintf (stderr, "%s: ", prog_name);
4033d8817e4Smiod fprintf (stderr, errmsg_fmt, errmsg_arg);
4043d8817e4Smiod fprintf (stderr, ": %s\n", strerror (errno_val));
4053d8817e4Smiod return 1;
4063d8817e4Smiod }
4073d8817e4Smiod
4083d8817e4Smiod retcode = 0;
4093d8817e4Smiod pid = pwait (pid, &wait_status, 0);
4103d8817e4Smiod if (pid == -1)
4113d8817e4Smiod {
4123d8817e4Smiod warn ("wait: %s", strerror (errno));
4133d8817e4Smiod retcode = 1;
4143d8817e4Smiod }
4153d8817e4Smiod else if (WIFSIGNALED (wait_status))
4163d8817e4Smiod {
4173d8817e4Smiod warn (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
4183d8817e4Smiod retcode = 1;
4193d8817e4Smiod }
4203d8817e4Smiod else if (WIFEXITED (wait_status))
4213d8817e4Smiod {
4223d8817e4Smiod if (WEXITSTATUS (wait_status) != 0)
4233d8817e4Smiod {
4243d8817e4Smiod warn (_("%s exited with status %d"), what, WEXITSTATUS (wait_status));
4253d8817e4Smiod retcode = 1;
4263d8817e4Smiod }
4273d8817e4Smiod }
4283d8817e4Smiod else
4293d8817e4Smiod retcode = 1;
4303d8817e4Smiod
4313d8817e4Smiod return retcode;
4323d8817e4Smiod }
4333d8817e4Smiod
4343d8817e4Smiod static char *
mybasename(const char * name)4353d8817e4Smiod mybasename (const char *name)
4363d8817e4Smiod {
4373d8817e4Smiod const char *base = name;
4383d8817e4Smiod
4393d8817e4Smiod while (*name)
4403d8817e4Smiod {
4413d8817e4Smiod if (*name == '/' || *name == '\\')
4423d8817e4Smiod {
4433d8817e4Smiod base = name + 1;
4443d8817e4Smiod }
4453d8817e4Smiod ++name;
4463d8817e4Smiod }
4473d8817e4Smiod return (char *) base;
4483d8817e4Smiod }
4493d8817e4Smiod
4503d8817e4Smiod static int
strhash(const char * str)4513d8817e4Smiod strhash (const char *str)
4523d8817e4Smiod {
4533d8817e4Smiod const unsigned char *s;
4543d8817e4Smiod unsigned long hash;
4553d8817e4Smiod unsigned int c;
4563d8817e4Smiod unsigned int len;
4573d8817e4Smiod
4583d8817e4Smiod hash = 0;
4593d8817e4Smiod len = 0;
4603d8817e4Smiod s = (const unsigned char *) str;
4613d8817e4Smiod while ((c = *s++) != '\0')
4623d8817e4Smiod {
4633d8817e4Smiod hash += c + (c << 17);
4643d8817e4Smiod hash ^= hash >> 2;
4653d8817e4Smiod ++len;
4663d8817e4Smiod }
4673d8817e4Smiod hash += len + (len << 17);
4683d8817e4Smiod hash ^= hash >> 2;
4693d8817e4Smiod
4703d8817e4Smiod return hash;
4713d8817e4Smiod }
4723d8817e4Smiod
4733d8817e4Smiod /**********************************************************************/
4743d8817e4Smiod
4753d8817e4Smiod static void
usage(FILE * file,int status)4763d8817e4Smiod usage (FILE *file, int status)
4773d8817e4Smiod {
4783d8817e4Smiod fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), prog_name);
4793d8817e4Smiod fprintf (file, _(" Generic options:\n"));
4803d8817e4Smiod fprintf (file, _(" @<file> Read options from <file>\n"));
4813d8817e4Smiod fprintf (file, _(" --quiet, -q Work quietly\n"));
4823d8817e4Smiod fprintf (file, _(" --verbose, -v Verbose\n"));
4833d8817e4Smiod fprintf (file, _(" --version Print dllwrap version\n"));
4843d8817e4Smiod fprintf (file, _(" --implib <outname> Synonym for --output-lib\n"));
4853d8817e4Smiod fprintf (file, _(" Options for %s:\n"), prog_name);
4863d8817e4Smiod fprintf (file, _(" --driver-name <driver> Defaults to \"gcc\"\n"));
4873d8817e4Smiod fprintf (file, _(" --driver-flags <flags> Override default ld flags\n"));
4883d8817e4Smiod fprintf (file, _(" --dlltool-name <dlltool> Defaults to \"dlltool\"\n"));
4893d8817e4Smiod fprintf (file, _(" --entry <entry> Specify alternate DLL entry point\n"));
4903d8817e4Smiod fprintf (file, _(" --image-base <base> Specify image base address\n"));
4913d8817e4Smiod fprintf (file, _(" --target <machine> i386-cygwin32 or i386-mingw32\n"));
4923d8817e4Smiod fprintf (file, _(" --dry-run Show what needs to be run\n"));
4933d8817e4Smiod fprintf (file, _(" --mno-cygwin Create Mingw DLL\n"));
4943d8817e4Smiod fprintf (file, _(" Options passed to DLLTOOL:\n"));
4953d8817e4Smiod fprintf (file, _(" --machine <machine>\n"));
4963d8817e4Smiod fprintf (file, _(" --output-exp <outname> Generate export file.\n"));
4973d8817e4Smiod fprintf (file, _(" --output-lib <outname> Generate input library.\n"));
4983d8817e4Smiod fprintf (file, _(" --add-indirect Add dll indirects to export file.\n"));
4993d8817e4Smiod fprintf (file, _(" --dllname <name> Name of input dll to put into output lib.\n"));
5003d8817e4Smiod fprintf (file, _(" --def <deffile> Name input .def file\n"));
5013d8817e4Smiod fprintf (file, _(" --output-def <deffile> Name output .def file\n"));
5023d8817e4Smiod fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
5033d8817e4Smiod fprintf (file, _(" --no-export-all-symbols Only export .drectve symbols\n"));
5043d8817e4Smiod fprintf (file, _(" --exclude-symbols <list> Exclude <list> from .def\n"));
5053d8817e4Smiod fprintf (file, _(" --no-default-excludes Zap default exclude symbols\n"));
5063d8817e4Smiod fprintf (file, _(" --base-file <basefile> Read linker generated base file\n"));
5073d8817e4Smiod fprintf (file, _(" --no-idata4 Don't generate idata$4 section\n"));
5083d8817e4Smiod fprintf (file, _(" --no-idata5 Don't generate idata$5 section\n"));
5093d8817e4Smiod fprintf (file, _(" -U Add underscores to .lib\n"));
5103d8817e4Smiod fprintf (file, _(" -k Kill @<n> from exported names\n"));
5113d8817e4Smiod fprintf (file, _(" --add-stdcall-alias Add aliases without @<n>\n"));
5123d8817e4Smiod fprintf (file, _(" --as <name> Use <name> for assembler\n"));
5133d8817e4Smiod fprintf (file, _(" --nodelete Keep temp files.\n"));
5143d8817e4Smiod fprintf (file, _(" Rest are passed unmodified to the language driver\n"));
5153d8817e4Smiod fprintf (file, "\n\n");
5163d8817e4Smiod exit (status);
5173d8817e4Smiod }
5183d8817e4Smiod
5193d8817e4Smiod #define OPTION_START 149
5203d8817e4Smiod
5213d8817e4Smiod /* GENERIC options. */
5223d8817e4Smiod #define OPTION_QUIET (OPTION_START + 1)
5233d8817e4Smiod #define OPTION_VERBOSE (OPTION_QUIET + 1)
5243d8817e4Smiod #define OPTION_VERSION (OPTION_VERBOSE + 1)
5253d8817e4Smiod
5263d8817e4Smiod /* DLLWRAP options. */
5273d8817e4Smiod #define OPTION_DRY_RUN (OPTION_VERSION + 1)
5283d8817e4Smiod #define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1)
5293d8817e4Smiod #define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1)
5303d8817e4Smiod #define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1)
5313d8817e4Smiod #define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1)
5323d8817e4Smiod #define OPTION_IMAGE_BASE (OPTION_ENTRY + 1)
5333d8817e4Smiod #define OPTION_TARGET (OPTION_IMAGE_BASE + 1)
5343d8817e4Smiod #define OPTION_MNO_CYGWIN (OPTION_TARGET + 1)
5353d8817e4Smiod
5363d8817e4Smiod /* DLLTOOL options. */
5373d8817e4Smiod #define OPTION_NODELETE (OPTION_MNO_CYGWIN + 1)
5383d8817e4Smiod #define OPTION_DLLNAME (OPTION_NODELETE + 1)
5393d8817e4Smiod #define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1)
5403d8817e4Smiod #define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1)
5413d8817e4Smiod #define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1)
5423d8817e4Smiod #define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1)
5433d8817e4Smiod #define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1)
5443d8817e4Smiod #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
5453d8817e4Smiod #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
5463d8817e4Smiod #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
5473d8817e4Smiod #define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1)
5483d8817e4Smiod #define OPTION_DEF (OPTION_OUTPUT_LIB + 1)
5493d8817e4Smiod #define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1)
5503d8817e4Smiod #define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1)
5513d8817e4Smiod #define OPTION_HELP (OPTION_KILLAT + 1)
5523d8817e4Smiod #define OPTION_MACHINE (OPTION_HELP + 1)
5533d8817e4Smiod #define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1)
5543d8817e4Smiod #define OPTION_BASE_FILE (OPTION_ADD_INDIRECT + 1)
5553d8817e4Smiod #define OPTION_AS (OPTION_BASE_FILE + 1)
5563d8817e4Smiod
5573d8817e4Smiod static const struct option long_options[] =
5583d8817e4Smiod {
5593d8817e4Smiod /* generic options. */
5603d8817e4Smiod {"quiet", no_argument, NULL, 'q'},
5613d8817e4Smiod {"verbose", no_argument, NULL, 'v'},
5623d8817e4Smiod {"version", no_argument, NULL, OPTION_VERSION},
5633d8817e4Smiod {"implib", required_argument, NULL, OPTION_OUTPUT_LIB},
5643d8817e4Smiod
5653d8817e4Smiod /* dllwrap options. */
5663d8817e4Smiod {"dry-run", no_argument, NULL, OPTION_DRY_RUN},
5673d8817e4Smiod {"driver-name", required_argument, NULL, OPTION_DRIVER_NAME},
5683d8817e4Smiod {"driver-flags", required_argument, NULL, OPTION_DRIVER_FLAGS},
5693d8817e4Smiod {"dlltool-name", required_argument, NULL, OPTION_DLLTOOL_NAME},
5703d8817e4Smiod {"entry", required_argument, NULL, 'e'},
5713d8817e4Smiod {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
5723d8817e4Smiod {"target", required_argument, NULL, OPTION_TARGET},
5733d8817e4Smiod
5743d8817e4Smiod /* dlltool options. */
5753d8817e4Smiod {"no-delete", no_argument, NULL, 'n'},
5763d8817e4Smiod {"dllname", required_argument, NULL, OPTION_DLLNAME},
5773d8817e4Smiod {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
5783d8817e4Smiod {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
5793d8817e4Smiod {"output-exp", required_argument, NULL, OPTION_OUTPUT_EXP},
5803d8817e4Smiod {"output-def", required_argument, NULL, OPTION_OUTPUT_DEF},
5813d8817e4Smiod {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
5823d8817e4Smiod {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
5833d8817e4Smiod {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
5843d8817e4Smiod {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
5853d8817e4Smiod {"output-lib", required_argument, NULL, OPTION_OUTPUT_LIB},
5863d8817e4Smiod {"def", required_argument, NULL, OPTION_DEF},
5873d8817e4Smiod {"add-underscore", no_argument, NULL, 'U'},
5883d8817e4Smiod {"killat", no_argument, NULL, 'k'},
5893d8817e4Smiod {"add-stdcall-alias", no_argument, NULL, 'A'},
5903d8817e4Smiod {"help", no_argument, NULL, 'h'},
5913d8817e4Smiod {"machine", required_argument, NULL, OPTION_MACHINE},
5923d8817e4Smiod {"add-indirect", no_argument, NULL, OPTION_ADD_INDIRECT},
5933d8817e4Smiod {"base-file", required_argument, NULL, OPTION_BASE_FILE},
5943d8817e4Smiod {"as", required_argument, NULL, OPTION_AS},
5953d8817e4Smiod {0, 0, 0, 0}
5963d8817e4Smiod };
5973d8817e4Smiod
5983d8817e4Smiod int main (int, char **);
5993d8817e4Smiod
6003d8817e4Smiod int
main(int argc,char ** argv)6013d8817e4Smiod main (int argc, char **argv)
6023d8817e4Smiod {
6033d8817e4Smiod int c;
6043d8817e4Smiod int i;
6053d8817e4Smiod
6063d8817e4Smiod char **saved_argv = 0;
6073d8817e4Smiod int cmdline_len = 0;
6083d8817e4Smiod
6093d8817e4Smiod int export_all = 0;
6103d8817e4Smiod
6113d8817e4Smiod int *dlltool_arg_indices;
6123d8817e4Smiod int *driver_arg_indices;
6133d8817e4Smiod
6143d8817e4Smiod char *driver_flags = 0;
6153d8817e4Smiod char *output_lib_file_name = 0;
6163d8817e4Smiod
6173d8817e4Smiod dyn_string_t dlltool_cmdline;
6183d8817e4Smiod dyn_string_t driver_cmdline;
6193d8817e4Smiod
6203d8817e4Smiod int def_file_seen = 0;
6213d8817e4Smiod
6223d8817e4Smiod char *image_base_str = 0;
6233d8817e4Smiod
6243d8817e4Smiod prog_name = argv[0];
6253d8817e4Smiod
6263d8817e4Smiod #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
6273d8817e4Smiod setlocale (LC_MESSAGES, "");
6283d8817e4Smiod #endif
6293d8817e4Smiod #if defined (HAVE_SETLOCALE)
6303d8817e4Smiod setlocale (LC_CTYPE, "");
6313d8817e4Smiod #endif
6323d8817e4Smiod bindtextdomain (PACKAGE, LOCALEDIR);
6333d8817e4Smiod textdomain (PACKAGE);
6343d8817e4Smiod
6353d8817e4Smiod expandargv (&argc, &argv);
6363d8817e4Smiod
6373d8817e4Smiod saved_argv = (char **) xmalloc (argc * sizeof (char*));
6383d8817e4Smiod dlltool_arg_indices = (int *) xmalloc (argc * sizeof (int));
6393d8817e4Smiod driver_arg_indices = (int *) xmalloc (argc * sizeof (int));
6403d8817e4Smiod for (i = 0; i < argc; ++i)
6413d8817e4Smiod {
6423d8817e4Smiod size_t len = strlen (argv[i]);
6433d8817e4Smiod char *arg = (char *) xmalloc (len + 1);
6443d8817e4Smiod strcpy (arg, argv[i]);
6453d8817e4Smiod cmdline_len += len;
6463d8817e4Smiod saved_argv[i] = arg;
6473d8817e4Smiod dlltool_arg_indices[i] = 0;
6483d8817e4Smiod driver_arg_indices[i] = 1;
6493d8817e4Smiod }
6503d8817e4Smiod cmdline_len++;
6513d8817e4Smiod
6523d8817e4Smiod /* We recognize dllwrap and dlltool options, and everything else is
6533d8817e4Smiod passed onto the language driver (eg., to GCC). We collect options
6543d8817e4Smiod to dlltool and driver in dlltool_args and driver_args. */
6553d8817e4Smiod
6563d8817e4Smiod opterr = 0;
6573d8817e4Smiod while ((c = getopt_long_only (argc, argv, "nkAqve:Uho:l:L:I:",
6583d8817e4Smiod long_options, (int *) 0)) != EOF)
6593d8817e4Smiod {
6603d8817e4Smiod int dlltool_arg;
6613d8817e4Smiod int driver_arg;
6623d8817e4Smiod int single_word_option_value_pair;
6633d8817e4Smiod
6643d8817e4Smiod dlltool_arg = 0;
6653d8817e4Smiod driver_arg = 1;
6663d8817e4Smiod single_word_option_value_pair = 0;
6673d8817e4Smiod
6683d8817e4Smiod if (c != '?')
6693d8817e4Smiod {
6703d8817e4Smiod /* We recognize this option, so it has to be either dllwrap or
6713d8817e4Smiod dlltool option. Do not pass to driver unless it's one of the
6723d8817e4Smiod generic options that are passed to all the tools (such as -v)
6733d8817e4Smiod which are dealt with later. */
6743d8817e4Smiod driver_arg = 0;
6753d8817e4Smiod }
6763d8817e4Smiod
6773d8817e4Smiod /* deal with generic and dllwrap options first. */
6783d8817e4Smiod switch (c)
6793d8817e4Smiod {
6803d8817e4Smiod case 'h':
6813d8817e4Smiod usage (stdout, 0);
6823d8817e4Smiod break;
6833d8817e4Smiod case 'q':
6843d8817e4Smiod verbose = 0;
6853d8817e4Smiod break;
6863d8817e4Smiod case 'v':
6873d8817e4Smiod verbose = 1;
6883d8817e4Smiod break;
6893d8817e4Smiod case OPTION_VERSION:
6903d8817e4Smiod print_version (prog_name);
6913d8817e4Smiod break;
6923d8817e4Smiod case 'e':
6933d8817e4Smiod entry_point = optarg;
6943d8817e4Smiod break;
6953d8817e4Smiod case OPTION_IMAGE_BASE:
6963d8817e4Smiod image_base_str = optarg;
6973d8817e4Smiod break;
6983d8817e4Smiod case OPTION_DEF:
6993d8817e4Smiod def_file_name = optarg;
7003d8817e4Smiod def_file_seen = 1;
7013d8817e4Smiod delete_def_file = 0;
7023d8817e4Smiod break;
7033d8817e4Smiod case 'n':
7043d8817e4Smiod dontdeltemps = 1;
7053d8817e4Smiod dlltool_arg = 1;
7063d8817e4Smiod break;
7073d8817e4Smiod case 'o':
7083d8817e4Smiod dll_file_name = optarg;
7093d8817e4Smiod break;
7103d8817e4Smiod case 'I':
7113d8817e4Smiod case 'l':
7123d8817e4Smiod case 'L':
7133d8817e4Smiod driver_arg = 1;
7143d8817e4Smiod break;
7153d8817e4Smiod case OPTION_DLLNAME:
7163d8817e4Smiod dll_name = optarg;
7173d8817e4Smiod break;
7183d8817e4Smiod case OPTION_DRY_RUN:
7193d8817e4Smiod dry_run = 1;
7203d8817e4Smiod break;
7213d8817e4Smiod case OPTION_DRIVER_NAME:
7223d8817e4Smiod driver_name = optarg;
7233d8817e4Smiod break;
7243d8817e4Smiod case OPTION_DRIVER_FLAGS:
7253d8817e4Smiod driver_flags = optarg;
7263d8817e4Smiod break;
7273d8817e4Smiod case OPTION_DLLTOOL_NAME:
7283d8817e4Smiod dlltool_name = optarg;
7293d8817e4Smiod break;
7303d8817e4Smiod case OPTION_TARGET:
7313d8817e4Smiod target = optarg;
7323d8817e4Smiod break;
7333d8817e4Smiod case OPTION_MNO_CYGWIN:
7343d8817e4Smiod target = "i386-mingw32";
7353d8817e4Smiod break;
7363d8817e4Smiod case OPTION_BASE_FILE:
7373d8817e4Smiod base_file_name = optarg;
7383d8817e4Smiod delete_base_file = 0;
7393d8817e4Smiod break;
7403d8817e4Smiod case OPTION_OUTPUT_EXP:
7413d8817e4Smiod exp_file_name = optarg;
7423d8817e4Smiod delete_exp_file = 0;
7433d8817e4Smiod break;
7443d8817e4Smiod case OPTION_EXPORT_ALL_SYMS:
7453d8817e4Smiod export_all = 1;
7463d8817e4Smiod break;
7473d8817e4Smiod case OPTION_OUTPUT_LIB:
7483d8817e4Smiod output_lib_file_name = optarg;
7493d8817e4Smiod break;
7503d8817e4Smiod case '?':
7513d8817e4Smiod break;
7523d8817e4Smiod default:
7533d8817e4Smiod dlltool_arg = 1;
7543d8817e4Smiod break;
7553d8817e4Smiod }
7563d8817e4Smiod
7573d8817e4Smiod /* Handle passing through --option=value case. */
7583d8817e4Smiod if (optarg
7593d8817e4Smiod && saved_argv[optind-1][0] == '-'
7603d8817e4Smiod && saved_argv[optind-1][1] == '-'
7613d8817e4Smiod && strchr (saved_argv[optind-1], '='))
7623d8817e4Smiod single_word_option_value_pair = 1;
7633d8817e4Smiod
7643d8817e4Smiod if (dlltool_arg)
7653d8817e4Smiod {
7663d8817e4Smiod dlltool_arg_indices[optind-1] = 1;
7673d8817e4Smiod if (optarg && ! single_word_option_value_pair)
7683d8817e4Smiod {
7693d8817e4Smiod dlltool_arg_indices[optind-2] = 1;
7703d8817e4Smiod }
7713d8817e4Smiod }
7723d8817e4Smiod
7733d8817e4Smiod if (! driver_arg)
7743d8817e4Smiod {
7753d8817e4Smiod driver_arg_indices[optind-1] = 0;
7763d8817e4Smiod if (optarg && ! single_word_option_value_pair)
7773d8817e4Smiod {
7783d8817e4Smiod driver_arg_indices[optind-2] = 0;
7793d8817e4Smiod }
7803d8817e4Smiod }
7813d8817e4Smiod }
7823d8817e4Smiod
7833d8817e4Smiod /* Sanity checks. */
7843d8817e4Smiod if (! dll_name && ! dll_file_name)
7853d8817e4Smiod {
7863d8817e4Smiod warn (_("Must provide at least one of -o or --dllname options"));
7873d8817e4Smiod exit (1);
7883d8817e4Smiod }
7893d8817e4Smiod else if (! dll_name)
7903d8817e4Smiod {
7913d8817e4Smiod dll_name = xstrdup (mybasename (dll_file_name));
7923d8817e4Smiod }
7933d8817e4Smiod else if (! dll_file_name)
7943d8817e4Smiod {
7953d8817e4Smiod dll_file_name = xstrdup (dll_name);
7963d8817e4Smiod }
7973d8817e4Smiod
7983d8817e4Smiod /* Deduce driver-name and dlltool-name from our own. */
7993d8817e4Smiod if (driver_name == NULL)
8003d8817e4Smiod driver_name = deduce_name ("gcc");
8013d8817e4Smiod
8023d8817e4Smiod if (dlltool_name == NULL)
8033d8817e4Smiod dlltool_name = deduce_name ("dlltool");
8043d8817e4Smiod
8053d8817e4Smiod if (! def_file_seen)
8063d8817e4Smiod {
807*d2386abeSmiod def_file_name = make_temp_file (".def");
808*d2386abeSmiod if (dontdeltemps)
809*d2386abeSmiod def_file_name = mybasename (def_file_name);
8103d8817e4Smiod free (fileprefix);
8113d8817e4Smiod delete_def_file = 1;
8123d8817e4Smiod warn (_("no export definition file provided.\n\
8133d8817e4Smiod Creating one, but that may not be what you want"));
8143d8817e4Smiod }
8153d8817e4Smiod
8163d8817e4Smiod /* Set the target platform. */
8173d8817e4Smiod if (strstr (target, "cygwin"))
8183d8817e4Smiod which_target = CYGWIN_TARGET;
8193d8817e4Smiod else if (strstr (target, "mingw"))
8203d8817e4Smiod which_target = MINGW_TARGET;
8213d8817e4Smiod else
8223d8817e4Smiod which_target = UNKNOWN_TARGET;
8233d8817e4Smiod
8243d8817e4Smiod /* Re-create the command lines as a string, taking care to quote stuff. */
8253d8817e4Smiod dlltool_cmdline = dyn_string_new (cmdline_len);
8263d8817e4Smiod if (verbose)
8273d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline, " -v");
8283d8817e4Smiod
8293d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline, " --dllname ");
8303d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline, dll_name);
8313d8817e4Smiod
8323d8817e4Smiod for (i = 1; i < argc; ++i)
8333d8817e4Smiod {
8343d8817e4Smiod if (dlltool_arg_indices[i])
8353d8817e4Smiod {
8363d8817e4Smiod char *arg = saved_argv[i];
8373d8817e4Smiod int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
8383d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline,
8393d8817e4Smiod (quote) ? " \"" : " ");
8403d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline, arg);
8413d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline,
8423d8817e4Smiod (quote) ? "\"" : "");
8433d8817e4Smiod }
8443d8817e4Smiod }
8453d8817e4Smiod
8463d8817e4Smiod driver_cmdline = dyn_string_new (cmdline_len);
8473d8817e4Smiod if (! driver_flags || strlen (driver_flags) == 0)
8483d8817e4Smiod {
8493d8817e4Smiod switch (which_target)
8503d8817e4Smiod {
8513d8817e4Smiod case CYGWIN_TARGET:
8523d8817e4Smiod driver_flags = cygwin_driver_flags;
8533d8817e4Smiod break;
8543d8817e4Smiod
8553d8817e4Smiod case MINGW_TARGET:
8563d8817e4Smiod driver_flags = mingw32_driver_flags;
8573d8817e4Smiod break;
8583d8817e4Smiod
8593d8817e4Smiod default:
8603d8817e4Smiod driver_flags = generic_driver_flags;
8613d8817e4Smiod break;
8623d8817e4Smiod }
8633d8817e4Smiod }
8643d8817e4Smiod dyn_string_append_cstr (driver_cmdline, driver_flags);
8653d8817e4Smiod dyn_string_append_cstr (driver_cmdline, " -o ");
8663d8817e4Smiod dyn_string_append_cstr (driver_cmdline, dll_file_name);
8673d8817e4Smiod
8683d8817e4Smiod if (! entry_point || strlen (entry_point) == 0)
8693d8817e4Smiod {
8703d8817e4Smiod switch (which_target)
8713d8817e4Smiod {
8723d8817e4Smiod case CYGWIN_TARGET:
8733d8817e4Smiod entry_point = "__cygwin_dll_entry@12";
8743d8817e4Smiod break;
8753d8817e4Smiod
8763d8817e4Smiod case MINGW_TARGET:
8773d8817e4Smiod entry_point = "_DllMainCRTStartup@12";
8783d8817e4Smiod break;
8793d8817e4Smiod
8803d8817e4Smiod default:
8813d8817e4Smiod entry_point = "_DllMain@12";
8823d8817e4Smiod break;
8833d8817e4Smiod }
8843d8817e4Smiod }
8853d8817e4Smiod dyn_string_append_cstr (driver_cmdline, " -Wl,-e,");
8863d8817e4Smiod dyn_string_append_cstr (driver_cmdline, entry_point);
8873d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline, " --exclude-symbol=");
8883d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline,
8893d8817e4Smiod (entry_point[0] == '_') ? entry_point+1 : entry_point);
8903d8817e4Smiod
8913d8817e4Smiod if (! image_base_str || strlen (image_base_str) == 0)
8923d8817e4Smiod {
8933d8817e4Smiod char *tmpbuf = (char *) xmalloc (sizeof ("0x12345678") + 1);
8943d8817e4Smiod unsigned long hash = strhash (dll_file_name);
8953d8817e4Smiod sprintf (tmpbuf, "0x%.8lX", 0x60000000|((hash<<16)&0xFFC0000));
8963d8817e4Smiod image_base_str = tmpbuf;
8973d8817e4Smiod }
8983d8817e4Smiod
8993d8817e4Smiod dyn_string_append_cstr (driver_cmdline, " -Wl,--image-base,");
9003d8817e4Smiod dyn_string_append_cstr (driver_cmdline, image_base_str);
9013d8817e4Smiod
9023d8817e4Smiod if (verbose)
9033d8817e4Smiod {
9043d8817e4Smiod dyn_string_append_cstr (driver_cmdline, " -v");
9053d8817e4Smiod }
9063d8817e4Smiod
9073d8817e4Smiod for (i = 1; i < argc; ++i)
9083d8817e4Smiod {
9093d8817e4Smiod if (driver_arg_indices[i])
9103d8817e4Smiod {
9113d8817e4Smiod char *arg = saved_argv[i];
9123d8817e4Smiod int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
9133d8817e4Smiod dyn_string_append_cstr (driver_cmdline,
9143d8817e4Smiod (quote) ? " \"" : " ");
9153d8817e4Smiod dyn_string_append_cstr (driver_cmdline, arg);
9163d8817e4Smiod dyn_string_append_cstr (driver_cmdline,
9173d8817e4Smiod (quote) ? "\"" : "");
9183d8817e4Smiod }
9193d8817e4Smiod }
9203d8817e4Smiod
9213d8817e4Smiod /* Step pre-1. If no --def <EXPORT_DEF> is specified,
9223d8817e4Smiod then create it and then pass it on. */
9233d8817e4Smiod
9243d8817e4Smiod if (! def_file_seen)
9253d8817e4Smiod {
9263d8817e4Smiod int i;
9273d8817e4Smiod dyn_string_t step_pre1;
9283d8817e4Smiod
9293d8817e4Smiod step_pre1 = dyn_string_new (1024);
9303d8817e4Smiod
9313d8817e4Smiod dyn_string_append_cstr (step_pre1, dlltool_cmdline->s);
9323d8817e4Smiod if (export_all)
9333d8817e4Smiod {
9343d8817e4Smiod dyn_string_append_cstr (step_pre1, " --export-all --exclude-symbol=");
9353d8817e4Smiod dyn_string_append_cstr (step_pre1,
9363d8817e4Smiod "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12");
9373d8817e4Smiod }
9383d8817e4Smiod dyn_string_append_cstr (step_pre1, " --output-def ");
9393d8817e4Smiod dyn_string_append_cstr (step_pre1, def_file_name);
9403d8817e4Smiod
9413d8817e4Smiod for (i = 1; i < argc; ++i)
9423d8817e4Smiod {
9433d8817e4Smiod if (driver_arg_indices[i])
9443d8817e4Smiod {
9453d8817e4Smiod char *arg = saved_argv[i];
9463d8817e4Smiod size_t len = strlen (arg);
9473d8817e4Smiod if (len >= 2 && arg[len-2] == '.'
9483d8817e4Smiod && (arg[len-1] == 'o' || arg[len-1] == 'a'))
9493d8817e4Smiod {
9503d8817e4Smiod int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
9513d8817e4Smiod dyn_string_append_cstr (step_pre1,
9523d8817e4Smiod (quote) ? " \"" : " ");
9533d8817e4Smiod dyn_string_append_cstr (step_pre1, arg);
9543d8817e4Smiod dyn_string_append_cstr (step_pre1,
9553d8817e4Smiod (quote) ? "\"" : "");
9563d8817e4Smiod }
9573d8817e4Smiod }
9583d8817e4Smiod }
9593d8817e4Smiod
9603d8817e4Smiod if (run (dlltool_name, step_pre1->s))
9613d8817e4Smiod cleanup_and_exit (1);
9623d8817e4Smiod
9633d8817e4Smiod dyn_string_delete (step_pre1);
9643d8817e4Smiod }
9653d8817e4Smiod
9663d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline, " --def ");
9673d8817e4Smiod dyn_string_append_cstr (dlltool_cmdline, def_file_name);
9683d8817e4Smiod
9693d8817e4Smiod if (verbose)
9703d8817e4Smiod {
9713d8817e4Smiod fprintf (stderr, _("DLLTOOL name : %s\n"), dlltool_name);
9723d8817e4Smiod fprintf (stderr, _("DLLTOOL options : %s\n"), dlltool_cmdline->s);
9733d8817e4Smiod fprintf (stderr, _("DRIVER name : %s\n"), driver_name);
9743d8817e4Smiod fprintf (stderr, _("DRIVER options : %s\n"), driver_cmdline->s);
9753d8817e4Smiod }
9763d8817e4Smiod
9773d8817e4Smiod /* Step 1. Call GCC/LD to create base relocation file. If using GCC, the
9783d8817e4Smiod driver command line will look like the following:
9793d8817e4Smiod
9803d8817e4Smiod % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
9813d8817e4Smiod
9823d8817e4Smiod If the user does not specify a base name, create temporary one that
9833d8817e4Smiod is deleted at exit. */
9843d8817e4Smiod
9853d8817e4Smiod if (! base_file_name)
9863d8817e4Smiod {
987*d2386abeSmiod base_file_name = make_temp_file (".base");
988*d2386abeSmiod if (dontdeltemps)
989*d2386abeSmiod base_file_name = mybasename (base_file_name);
9903d8817e4Smiod delete_base_file = 1;
9913d8817e4Smiod }
9923d8817e4Smiod
9933d8817e4Smiod {
9943d8817e4Smiod int quote;
9953d8817e4Smiod
9963d8817e4Smiod dyn_string_t step1 = dyn_string_new (driver_cmdline->length
9973d8817e4Smiod + strlen (base_file_name)
9983d8817e4Smiod + 20);
9993d8817e4Smiod dyn_string_append_cstr (step1, "-Wl,--base-file,");
10003d8817e4Smiod quote = (strchr (base_file_name, ' ')
10013d8817e4Smiod || strchr (base_file_name, '\t'));
10023d8817e4Smiod dyn_string_append_cstr (step1,
10033d8817e4Smiod (quote) ? "\"" : "");
10043d8817e4Smiod dyn_string_append_cstr (step1, base_file_name);
10053d8817e4Smiod dyn_string_append_cstr (step1,
10063d8817e4Smiod (quote) ? "\"" : "");
10073d8817e4Smiod if (driver_cmdline->length)
10083d8817e4Smiod {
10093d8817e4Smiod dyn_string_append_cstr (step1, " ");
10103d8817e4Smiod dyn_string_append_cstr (step1, driver_cmdline->s);
10113d8817e4Smiod }
10123d8817e4Smiod
10133d8817e4Smiod if (run (driver_name, step1->s))
10143d8817e4Smiod cleanup_and_exit (1);
10153d8817e4Smiod
10163d8817e4Smiod dyn_string_delete (step1);
10173d8817e4Smiod }
10183d8817e4Smiod
10193d8817e4Smiod /* Step 2. generate the exp file by running dlltool.
10203d8817e4Smiod dlltool command line will look like the following:
10213d8817e4Smiod
10223d8817e4Smiod % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
10233d8817e4Smiod
10243d8817e4Smiod If the user does not specify a base name, create temporary one that
10253d8817e4Smiod is deleted at exit. */
10263d8817e4Smiod
10273d8817e4Smiod if (! exp_file_name)
10283d8817e4Smiod {
10293d8817e4Smiod char *p = strrchr (dll_name, '.');
10303d8817e4Smiod size_t prefix_len = (p) ? (size_t) (p - dll_name) : strlen (dll_name);
10313d8817e4Smiod
10323d8817e4Smiod exp_file_name = (char *) xmalloc (prefix_len + 4 + 1);
10333d8817e4Smiod strncpy (exp_file_name, dll_name, prefix_len);
10343d8817e4Smiod exp_file_name[prefix_len] = '\0';
10353d8817e4Smiod strcat (exp_file_name, ".exp");
10363d8817e4Smiod delete_exp_file = 1;
10373d8817e4Smiod }
10383d8817e4Smiod
10393d8817e4Smiod {
10403d8817e4Smiod int quote;
10413d8817e4Smiod
10423d8817e4Smiod dyn_string_t step2 = dyn_string_new (dlltool_cmdline->length
10433d8817e4Smiod + strlen (base_file_name)
10443d8817e4Smiod + strlen (exp_file_name)
10453d8817e4Smiod + 20);
10463d8817e4Smiod
10473d8817e4Smiod dyn_string_append_cstr (step2, "--base-file ");
10483d8817e4Smiod quote = (strchr (base_file_name, ' ')
10493d8817e4Smiod || strchr (base_file_name, '\t'));
10503d8817e4Smiod dyn_string_append_cstr (step2,
10513d8817e4Smiod (quote) ? "\"" : "");
10523d8817e4Smiod dyn_string_append_cstr (step2, base_file_name);
10533d8817e4Smiod dyn_string_append_cstr (step2,
10543d8817e4Smiod (quote) ? "\" " : " ");
10553d8817e4Smiod
10563d8817e4Smiod dyn_string_append_cstr (step2, "--output-exp ");
10573d8817e4Smiod quote = (strchr (exp_file_name, ' ')
10583d8817e4Smiod || strchr (exp_file_name, '\t'));
10593d8817e4Smiod dyn_string_append_cstr (step2,
10603d8817e4Smiod (quote) ? "\"" : "");
10613d8817e4Smiod dyn_string_append_cstr (step2, exp_file_name);
10623d8817e4Smiod dyn_string_append_cstr (step2,
10633d8817e4Smiod (quote) ? "\"" : "");
10643d8817e4Smiod
10653d8817e4Smiod if (dlltool_cmdline->length)
10663d8817e4Smiod {
10673d8817e4Smiod dyn_string_append_cstr (step2, " ");
10683d8817e4Smiod dyn_string_append_cstr (step2, dlltool_cmdline->s);
10693d8817e4Smiod }
10703d8817e4Smiod
10713d8817e4Smiod if (run (dlltool_name, step2->s))
10723d8817e4Smiod cleanup_and_exit (1);
10733d8817e4Smiod
10743d8817e4Smiod dyn_string_delete (step2);
10753d8817e4Smiod }
10763d8817e4Smiod
10773d8817e4Smiod /*
10783d8817e4Smiod * Step 3. Call GCC/LD to again, adding the exp file this time.
10793d8817e4Smiod * driver command line will look like the following:
10803d8817e4Smiod *
10813d8817e4Smiod * % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...]
10823d8817e4Smiod */
10833d8817e4Smiod
10843d8817e4Smiod {
10853d8817e4Smiod int quote;
10863d8817e4Smiod
10873d8817e4Smiod dyn_string_t step3 = dyn_string_new (driver_cmdline->length
10883d8817e4Smiod + strlen (exp_file_name)
10893d8817e4Smiod + strlen (base_file_name)
10903d8817e4Smiod + 20);
10913d8817e4Smiod dyn_string_append_cstr (step3, "-Wl,--base-file,");
10923d8817e4Smiod quote = (strchr (base_file_name, ' ')
10933d8817e4Smiod || strchr (base_file_name, '\t'));
10943d8817e4Smiod dyn_string_append_cstr (step3,
10953d8817e4Smiod (quote) ? "\"" : "");
10963d8817e4Smiod dyn_string_append_cstr (step3, base_file_name);
10973d8817e4Smiod dyn_string_append_cstr (step3,
10983d8817e4Smiod (quote) ? "\" " : " ");
10993d8817e4Smiod
11003d8817e4Smiod quote = (strchr (exp_file_name, ' ')
11013d8817e4Smiod || strchr (exp_file_name, '\t'));
11023d8817e4Smiod dyn_string_append_cstr (step3,
11033d8817e4Smiod (quote) ? "\"" : "");
11043d8817e4Smiod dyn_string_append_cstr (step3, exp_file_name);
11053d8817e4Smiod dyn_string_append_cstr (step3,
11063d8817e4Smiod (quote) ? "\"" : "");
11073d8817e4Smiod
11083d8817e4Smiod if (driver_cmdline->length)
11093d8817e4Smiod {
11103d8817e4Smiod dyn_string_append_cstr (step3, " ");
11113d8817e4Smiod dyn_string_append_cstr (step3, driver_cmdline->s);
11123d8817e4Smiod }
11133d8817e4Smiod
11143d8817e4Smiod if (run (driver_name, step3->s))
11153d8817e4Smiod cleanup_and_exit (1);
11163d8817e4Smiod
11173d8817e4Smiod dyn_string_delete (step3);
11183d8817e4Smiod }
11193d8817e4Smiod
11203d8817e4Smiod
11213d8817e4Smiod /*
11223d8817e4Smiod * Step 4. Run DLLTOOL again using the same command line.
11233d8817e4Smiod */
11243d8817e4Smiod
11253d8817e4Smiod {
11263d8817e4Smiod int quote;
11273d8817e4Smiod dyn_string_t step4 = dyn_string_new (dlltool_cmdline->length
11283d8817e4Smiod + strlen (base_file_name)
11293d8817e4Smiod + strlen (exp_file_name)
11303d8817e4Smiod + 20);
11313d8817e4Smiod
11323d8817e4Smiod dyn_string_append_cstr (step4, "--base-file ");
11333d8817e4Smiod quote = (strchr (base_file_name, ' ')
11343d8817e4Smiod || strchr (base_file_name, '\t'));
11353d8817e4Smiod dyn_string_append_cstr (step4,
11363d8817e4Smiod (quote) ? "\"" : "");
11373d8817e4Smiod dyn_string_append_cstr (step4, base_file_name);
11383d8817e4Smiod dyn_string_append_cstr (step4,
11393d8817e4Smiod (quote) ? "\" " : " ");
11403d8817e4Smiod
11413d8817e4Smiod dyn_string_append_cstr (step4, "--output-exp ");
11423d8817e4Smiod quote = (strchr (exp_file_name, ' ')
11433d8817e4Smiod || strchr (exp_file_name, '\t'));
11443d8817e4Smiod dyn_string_append_cstr (step4,
11453d8817e4Smiod (quote) ? "\"" : "");
11463d8817e4Smiod dyn_string_append_cstr (step4, exp_file_name);
11473d8817e4Smiod dyn_string_append_cstr (step4,
11483d8817e4Smiod (quote) ? "\"" : "");
11493d8817e4Smiod
11503d8817e4Smiod if (dlltool_cmdline->length)
11513d8817e4Smiod {
11523d8817e4Smiod dyn_string_append_cstr (step4, " ");
11533d8817e4Smiod dyn_string_append_cstr (step4, dlltool_cmdline->s);
11543d8817e4Smiod }
11553d8817e4Smiod
11563d8817e4Smiod if (output_lib_file_name)
11573d8817e4Smiod {
11583d8817e4Smiod dyn_string_append_cstr (step4, " --output-lib ");
11593d8817e4Smiod dyn_string_append_cstr (step4, output_lib_file_name);
11603d8817e4Smiod }
11613d8817e4Smiod
11623d8817e4Smiod if (run (dlltool_name, step4->s))
11633d8817e4Smiod cleanup_and_exit (1);
11643d8817e4Smiod
11653d8817e4Smiod dyn_string_delete (step4);
11663d8817e4Smiod }
11673d8817e4Smiod
11683d8817e4Smiod
11693d8817e4Smiod /*
11703d8817e4Smiod * Step 5. Link it all together and be done with it.
11713d8817e4Smiod * driver command line will look like the following:
11723d8817e4Smiod *
11733d8817e4Smiod * % gcc -Wl,--dll foo.exp [rest ...]
11743d8817e4Smiod *
11753d8817e4Smiod */
11763d8817e4Smiod
11773d8817e4Smiod {
11783d8817e4Smiod int quote;
11793d8817e4Smiod
11803d8817e4Smiod dyn_string_t step5 = dyn_string_new (driver_cmdline->length
11813d8817e4Smiod + strlen (exp_file_name)
11823d8817e4Smiod + 20);
11833d8817e4Smiod quote = (strchr (exp_file_name, ' ')
11843d8817e4Smiod || strchr (exp_file_name, '\t'));
11853d8817e4Smiod dyn_string_append_cstr (step5,
11863d8817e4Smiod (quote) ? "\"" : "");
11873d8817e4Smiod dyn_string_append_cstr (step5, exp_file_name);
11883d8817e4Smiod dyn_string_append_cstr (step5,
11893d8817e4Smiod (quote) ? "\"" : "");
11903d8817e4Smiod
11913d8817e4Smiod if (driver_cmdline->length)
11923d8817e4Smiod {
11933d8817e4Smiod dyn_string_append_cstr (step5, " ");
11943d8817e4Smiod dyn_string_append_cstr (step5, driver_cmdline->s);
11953d8817e4Smiod }
11963d8817e4Smiod
11973d8817e4Smiod if (run (driver_name, step5->s))
11983d8817e4Smiod cleanup_and_exit (1);
11993d8817e4Smiod
12003d8817e4Smiod dyn_string_delete (step5);
12013d8817e4Smiod }
12023d8817e4Smiod
12033d8817e4Smiod cleanup_and_exit (0);
12043d8817e4Smiod
12053d8817e4Smiod return 0;
12063d8817e4Smiod }
1207