1 /* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs
2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3 Contributed by Mumit Khan (khan@xraylith.wisc.edu).
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 /* AIX requires this to be the first thing in the file. */
34 #include "libiberty.h"
37 #include "dyn-string.h"
43 #ifdef ANSI_PROTOTYPES
49 #ifdef HAVE_SYS_WAIT_H
51 #else /* ! HAVE_SYS_WAIT_H */
52 #if ! defined (_WIN32) || defined (__CYGWIN32__)
54 #define WIFEXITED(w) (((w)&0377) == 0)
57 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
60 #define WTERMSIG(w) ((w) & 0177)
63 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
65 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
67 #define WIFEXITED(w) (((w) & 0xff) == 0)
70 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
73 #define WTERMSIG(w) ((w) & 0x7f)
76 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
78 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
79 #endif /* ! HAVE_SYS_WAIT_H */
81 static char *driver_name
= NULL
;
82 static char *cygwin_driver_flags
=
83 "-Wl,--dll -nostartfiles";
84 static char *mingw32_driver_flags
= "-mdll";
85 static char *generic_driver_flags
= "-Wl,--dll";
87 static char *entry_point
;
89 static char *dlltool_name
= NULL
;
91 static char *target
= TARGET
;
100 static target_type which_target
= UNKNOWN_TARGET
;
102 static int dontdeltemps
= 0;
103 static int dry_run
= 0;
105 static char *program_name
;
107 static int verbose
= 0;
109 static char *dll_file_name
;
110 static char *dll_name
;
111 static char *base_file_name
;
112 static char *exp_file_name
;
113 static char *def_file_name
;
114 static int delete_base_file
= 1;
115 static int delete_exp_file
= 1;
116 static int delete_def_file
= 1;
118 static int run
PARAMS ((const char *, char *));
119 static void usage
PARAMS ((FILE *, int));
120 static void display
PARAMS ((const char *, va_list));
121 static void inform
PARAMS ((const char *, ...));
122 static void warn
PARAMS ((const char *format
, ...));
123 static char *look_for_prog
PARAMS ((const char *, const char *, int));
124 static char *deduce_name
PARAMS ((const char *));
125 static void delete_temp_files
PARAMS ((void));
126 static void cleanup_and_exit
PARAMS ((int status
));
128 /**********************************************************************/
130 /* Please keep the following 4 routines in sync with dlltool.c:
135 It's not worth the hassle to break these out since dllwrap will
136 (hopefully) soon be retired in favor of `ld --shared. */
139 display (message
, args
)
140 const char * message
;
143 if (program_name
!= NULL
)
144 fprintf (stderr
, "%s: ", program_name
);
146 vfprintf (stderr
, message
, args
);
147 fputc ('\n', stderr
);
153 inform (const char * message
, ...)
160 va_start (args
, message
);
161 display (message
, args
);
166 warn (const char *format
, ...)
170 va_start (args
, format
);
171 display (format
, args
);
177 inform (message
, va_alist
)
178 const char * message
;
187 display (message
, args
);
192 warn (format
, va_alist
)
199 display (format
, args
);
204 /* Look for the program formed by concatenating PROG_NAME and the
205 string running from PREFIX to END_PREFIX. If the concatenated
206 string contains a '/', try appending EXECUTABLE_SUFFIX if it is
210 look_for_prog (prog_name
, prefix
, end_prefix
)
211 const char *prog_name
;
218 cmd
= xmalloc (strlen (prefix
)
220 #ifdef HAVE_EXECUTABLE_SUFFIX
221 + strlen (EXECUTABLE_SUFFIX
)
224 strcpy (cmd
, prefix
);
226 sprintf (cmd
+ end_prefix
, "%s", prog_name
);
228 if (strchr (cmd
, '/') != NULL
)
232 found
= (stat (cmd
, &s
) == 0
233 #ifdef HAVE_EXECUTABLE_SUFFIX
234 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
240 /* xgettext:c-format */
241 inform (_("Tried file: %s"), cmd
);
247 /* xgettext:c-format */
248 inform (_("Using file: %s"), cmd
);
253 /* Deduce the name of the program we are want to invoke.
254 PROG_NAME is the basic name of the program we want to run,
255 eg "as" or "ld". The catch is that we might want actually
256 run "i386-pe-as" or "ppc-pe-ld".
258 If argv[0] contains the full path, then try to find the program
259 in the same place, with and then without a target-like prefix.
261 Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
262 deduce_name("as") uses the following search order:
264 /usr/local/bin/i586-cygwin32-as
268 If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
269 name, it'll try without and then with EXECUTABLE_SUFFIX.
271 Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
272 as the fallback, but rather return i586-cygwin32-as.
274 Oh, and given, argv[0] = dlltool, it'll return "as".
276 Returns a dynamically allocated string. */
279 deduce_name (prog_name
)
280 const char *prog_name
;
283 char *dash
, *slash
, *cp
;
287 for (cp
= program_name
; *cp
!= '\0'; ++cp
)
292 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
293 *cp
== ':' || *cp
== '\\' ||
306 /* First, try looking for a prefixed PROG_NAME in the
307 PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */
308 cmd
= look_for_prog (prog_name
, program_name
, dash
- program_name
+ 1);
311 if (slash
!= NULL
&& cmd
== NULL
)
313 /* Next, try looking for a PROG_NAME in the same directory as
314 that of this program. */
315 cmd
= look_for_prog (prog_name
, program_name
, slash
- program_name
+ 1);
320 /* Just return PROG_NAME as is. */
321 cmd
= xstrdup (prog_name
);
330 if (delete_base_file
&& base_file_name
)
335 warn (_("Keeping temporary base file %s"), base_file_name
);
337 warn (_("Deleting temporary base file %s"), base_file_name
);
341 unlink (base_file_name
);
342 free (base_file_name
);
346 if (delete_exp_file
&& exp_file_name
)
351 warn (_("Keeping temporary exp file %s"), exp_file_name
);
353 warn (_("Deleting temporary exp file %s"), exp_file_name
);
357 unlink (exp_file_name
);
358 free (exp_file_name
);
361 if (delete_def_file
&& def_file_name
)
366 warn (_("Keeping temporary def file %s"), def_file_name
);
368 warn (_("Deleting temporary def file %s"), def_file_name
);
372 unlink (def_file_name
);
373 free (def_file_name
);
379 cleanup_and_exit (int status
)
381 delete_temp_files ();
391 int pid
, wait_status
, retcode
;
394 char *errmsg_fmt
, *errmsg_arg
;
395 char *temp_base
= choose_temp_base ();
399 if (verbose
|| dry_run
)
400 fprintf (stderr
, "%s %s\n", what
, args
);
404 for (s
= args
; *s
; s
++)
408 argv
= alloca (sizeof (char *) * (i
+ 3));
414 while (*s
== ' ' && *s
!= 0)
418 in_quote
= (*s
== '\'' || *s
== '"');
419 sep
= (in_quote
) ? *s
++ : ' ';
421 while (*s
!= sep
&& *s
!= 0)
434 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
435 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
439 int errno_val
= errno
;
441 fprintf (stderr
, "%s: ", program_name
);
442 fprintf (stderr
, errmsg_fmt
, errmsg_arg
);
443 fprintf (stderr
, ": %s\n", strerror (errno_val
));
448 pid
= pwait (pid
, &wait_status
, 0);
451 warn ("wait: %s", strerror (errno
));
454 else if (WIFSIGNALED (wait_status
))
456 warn (_("subprocess got fatal signal %d"), WTERMSIG (wait_status
));
459 else if (WIFEXITED (wait_status
))
461 if (WEXITSTATUS (wait_status
) != 0)
463 warn (_("%s exited with status %d"), what
, WEXITSTATUS (wait_status
));
477 const char *base
= name
;
481 if (*name
== '/' || *name
== '\\')
487 return (char *) base
;
491 strhash (const char *str
)
493 const unsigned char *s
;
500 s
= (const unsigned char *) str
;
501 while ((c
= *s
++) != '\0')
503 hash
+= c
+ (c
<< 17);
507 hash
+= len
+ (len
<< 17);
513 /**********************************************************************/
520 fprintf (file
, _("Usage %s <options> <object-files>\n"), program_name
);
521 fprintf (file
, _(" Generic options:\n"));
522 fprintf (file
, _(" --quiet, -q Work quietly\n"));
523 fprintf (file
, _(" --verbose, -v Verbose\n"));
524 fprintf (file
, _(" --version Print dllwrap version\n"));
525 fprintf (file
, _(" --implib <outname> Synonym for --output-lib\n"));
526 fprintf (file
, _(" Options for %s:\n"), program_name
);
527 fprintf (file
, _(" --driver-name <driver> Defaults to \"gcc\"\n"));
528 fprintf (file
, _(" --driver-flags <flags> Override default ld flags\n"));
529 fprintf (file
, _(" --dlltool-name <dlltool> Defaults to \"dlltool\"\n"));
530 fprintf (file
, _(" --entry <entry> Specify alternate DLL entry point\n"));
531 fprintf (file
, _(" --image-base <base> Specify image base address\n"));
532 fprintf (file
, _(" --target <machine> i386-cygwin32 or i386-mingw32\n"));
533 fprintf (file
, _(" --dry-run Show what needs to be run\n"));
534 fprintf (file
, _(" --mno-cygwin Create Mingw DLL\n"));
535 fprintf (file
, _(" Options passed to DLLTOOL:\n"));
536 fprintf (file
, _(" --machine <machine>\n"));
537 fprintf (file
, _(" --output-exp <outname> Generate export file.\n"));
538 fprintf (file
, _(" --output-lib <outname> Generate input library.\n"));
539 fprintf (file
, _(" --add-indirect Add dll indirects to export file.\n"));
540 fprintf (file
, _(" --dllname <name> Name of input dll to put into output lib.\n"));
541 fprintf (file
, _(" --def <deffile> Name input .def file\n"));
542 fprintf (file
, _(" --output-def <deffile> Name output .def file\n"));
543 fprintf (file
, _(" --export-all-symbols Export all symbols to .def\n"));
544 fprintf (file
, _(" --no-export-all-symbols Only export .drectve symbols\n"));
545 fprintf (file
, _(" --exclude-symbols <list> Exclude <list> from .def\n"));
546 fprintf (file
, _(" --no-default-excludes Zap default exclude symbols\n"));
547 fprintf (file
, _(" --base-file <basefile> Read linker generated base file\n"));
548 fprintf (file
, _(" --no-idata4 Don't generate idata$4 section\n"));
549 fprintf (file
, _(" --no-idata5 Don't generate idata$5 section\n"));
550 fprintf (file
, _(" -U Add underscores to .lib\n"));
551 fprintf (file
, _(" -k Kill @<n> from exported names\n"));
552 fprintf (file
, _(" --add-stdcall-alias Add aliases without @<n>\n"));
553 fprintf (file
, _(" --as <name> Use <name> for assembler\n"));
554 fprintf (file
, _(" --nodelete Keep temp files.\n"));
555 fprintf (file
, _(" Rest are passed unmodified to the language driver\n"));
556 fprintf (file
, "\n\n");
560 #define OPTION_START 149
562 /* GENERIC options. */
563 #define OPTION_QUIET (OPTION_START + 1)
564 #define OPTION_VERBOSE (OPTION_QUIET + 1)
565 #define OPTION_VERSION (OPTION_VERBOSE + 1)
567 /* DLLWRAP options. */
568 #define OPTION_DRY_RUN (OPTION_VERSION + 1)
569 #define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1)
570 #define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1)
571 #define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1)
572 #define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1)
573 #define OPTION_IMAGE_BASE (OPTION_ENTRY + 1)
574 #define OPTION_TARGET (OPTION_IMAGE_BASE + 1)
575 #define OPTION_MNO_CYGWIN (OPTION_TARGET + 1)
577 /* DLLTOOL options. */
578 #define OPTION_NODELETE (OPTION_MNO_CYGWIN + 1)
579 #define OPTION_DLLNAME (OPTION_NODELETE + 1)
580 #define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1)
581 #define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1)
582 #define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1)
583 #define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1)
584 #define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1)
585 #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
586 #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
587 #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
588 #define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1)
589 #define OPTION_DEF (OPTION_OUTPUT_LIB + 1)
590 #define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1)
591 #define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1)
592 #define OPTION_HELP (OPTION_KILLAT + 1)
593 #define OPTION_MACHINE (OPTION_HELP + 1)
594 #define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1)
595 #define OPTION_BASE_FILE (OPTION_ADD_INDIRECT + 1)
596 #define OPTION_AS (OPTION_BASE_FILE + 1)
598 static const struct option long_options
[] =
600 /* generic options. */
601 {"quiet", no_argument
, NULL
, 'q'},
602 {"verbose", no_argument
, NULL
, 'v'},
603 {"version", no_argument
, NULL
, OPTION_VERSION
},
604 {"implib", required_argument
, NULL
, OPTION_OUTPUT_LIB
},
606 /* dllwrap options. */
607 {"dry-run", no_argument
, NULL
, OPTION_DRY_RUN
},
608 {"driver-name", required_argument
, NULL
, OPTION_DRIVER_NAME
},
609 {"driver-flags", required_argument
, NULL
, OPTION_DRIVER_FLAGS
},
610 {"dlltool-name", required_argument
, NULL
, OPTION_DLLTOOL_NAME
},
611 {"entry", required_argument
, NULL
, 'e'},
612 {"image-base", required_argument
, NULL
, OPTION_IMAGE_BASE
},
613 {"target", required_argument
, NULL
, OPTION_TARGET
},
615 /* dlltool options. */
616 {"no-delete", no_argument
, NULL
, 'n'},
617 {"dllname", required_argument
, NULL
, OPTION_DLLNAME
},
618 {"no-idata4", no_argument
, NULL
, OPTION_NO_IDATA4
},
619 {"no-idata5", no_argument
, NULL
, OPTION_NO_IDATA5
},
620 {"output-exp", required_argument
, NULL
, OPTION_OUTPUT_EXP
},
621 {"output-def", required_argument
, NULL
, OPTION_OUTPUT_DEF
},
622 {"export-all-symbols", no_argument
, NULL
, OPTION_EXPORT_ALL_SYMS
},
623 {"no-export-all-symbols", no_argument
, NULL
, OPTION_NO_EXPORT_ALL_SYMS
},
624 {"exclude-symbols", required_argument
, NULL
, OPTION_EXCLUDE_SYMS
},
625 {"no-default-excludes", no_argument
, NULL
, OPTION_NO_DEFAULT_EXCLUDES
},
626 {"output-lib", required_argument
, NULL
, OPTION_OUTPUT_LIB
},
627 {"def", required_argument
, NULL
, OPTION_DEF
},
628 {"add-underscore", no_argument
, NULL
, 'U'},
629 {"killat", no_argument
, NULL
, 'k'},
630 {"add-stdcall-alias", no_argument
, NULL
, 'A'},
631 {"help", no_argument
, NULL
, 'h'},
632 {"machine", required_argument
, NULL
, OPTION_MACHINE
},
633 {"add-indirect", no_argument
, NULL
, OPTION_ADD_INDIRECT
},
634 {"base-file", required_argument
, NULL
, OPTION_BASE_FILE
},
635 {"as", required_argument
, NULL
, OPTION_AS
},
647 char **saved_argv
= 0;
652 int *dlltool_arg_indices
;
653 int *driver_arg_indices
;
655 char *driver_flags
= 0;
656 char *output_lib_file_name
= 0;
658 dyn_string_t dlltool_cmdline
;
659 dyn_string_t driver_cmdline
;
661 int def_file_seen
= 0;
663 char *image_base_str
= 0;
665 program_name
= argv
[0];
667 saved_argv
= (char **) xmalloc (argc
* sizeof (char*));
668 dlltool_arg_indices
= (int *) xmalloc (argc
* sizeof (int));
669 driver_arg_indices
= (int *) xmalloc (argc
* sizeof (int));
670 for (i
= 0; i
< argc
; ++i
)
672 size_t len
= strlen (argv
[i
]);
673 char *arg
= (char *) xmalloc (len
+ 1);
674 strcpy (arg
, argv
[i
]);
677 dlltool_arg_indices
[i
] = 0;
678 driver_arg_indices
[i
] = 1;
682 /* We recognize dllwrap and dlltool options, and everything else is
683 passed onto the language driver (eg., to GCC). We collect options
684 to dlltool and driver in dlltool_args and driver_args. */
687 while ((c
= getopt_long_only (argc
, argv
, "nkAqve:Uho:l:L:I:",
688 long_options
, (int *) 0)) != EOF
)
692 int single_word_option_value_pair
;
696 single_word_option_value_pair
= 0;
700 /* We recognize this option, so it has to be either dllwrap or
701 dlltool option. Do not pass to driver unless it's one of the
702 generic options that are passed to all the tools (such as -v)
703 which are dealt with later. */
707 /* deal with generic and dllwrap options first. */
720 print_version (program_name
);
723 entry_point
= optarg
;
725 case OPTION_IMAGE_BASE
:
726 image_base_str
= optarg
;
729 def_file_name
= optarg
;
738 dll_file_name
= optarg
;
751 case OPTION_DRIVER_NAME
:
752 driver_name
= optarg
;
754 case OPTION_DRIVER_FLAGS
:
755 driver_flags
= optarg
;
757 case OPTION_DLLTOOL_NAME
:
758 dlltool_name
= optarg
;
763 case OPTION_MNO_CYGWIN
:
764 target
= "i386-mingw32";
766 case OPTION_BASE_FILE
:
767 base_file_name
= optarg
;
768 delete_base_file
= 0;
770 case OPTION_OUTPUT_EXP
:
771 exp_file_name
= optarg
;
774 case OPTION_EXPORT_ALL_SYMS
:
777 case OPTION_OUTPUT_LIB
:
778 output_lib_file_name
= optarg
;
787 /* Handle passing through --option=value case. */
789 && saved_argv
[optind
-1][0] == '-'
790 && saved_argv
[optind
-1][1] == '-'
791 && strchr (saved_argv
[optind
-1], '='))
792 single_word_option_value_pair
= 1;
796 dlltool_arg_indices
[optind
-1] = 1;
797 if (optarg
&& ! single_word_option_value_pair
)
799 dlltool_arg_indices
[optind
-2] = 1;
805 driver_arg_indices
[optind
-1] = 0;
806 if (optarg
&& ! single_word_option_value_pair
)
808 driver_arg_indices
[optind
-2] = 0;
814 if (! dll_name
&& ! dll_file_name
)
816 warn (_("Must provide at least one of -o or --dllname options"));
821 dll_name
= xstrdup (mybasename (dll_file_name
));
823 else if (! dll_file_name
)
825 dll_file_name
= xstrdup (dll_name
);
828 /* Deduce driver-name and dlltool-name from our own. */
829 if (driver_name
== NULL
)
830 driver_name
= deduce_name ("gcc");
832 if (dlltool_name
== NULL
)
833 dlltool_name
= deduce_name ("dlltool");
837 char *fileprefix
= choose_temp_base ();
838 def_file_name
= (char *) xmalloc (strlen (fileprefix
) + 5);
839 sprintf (def_file_name
, "%s.def",
840 (dontdeltemps
) ? mybasename (fileprefix
) : fileprefix
);
844 warn (_("no export definition file provided"));
845 warn (_("creating one, but that may not be what you want"));
848 /* set the target platform. */
849 if (strstr (target
, "cygwin"))
850 which_target
= CYGWIN_TARGET
;
851 else if (strstr (target
, "mingw"))
852 which_target
= MINGW_TARGET
;
854 which_target
= UNKNOWN_TARGET
;
856 /* re-create the command lines as a string, taking care to quote stuff. */
857 dlltool_cmdline
= dyn_string_new (cmdline_len
);
860 dyn_string_append_cstr (dlltool_cmdline
, " -v");
862 dyn_string_append_cstr (dlltool_cmdline
, " --dllname ");
863 dyn_string_append_cstr (dlltool_cmdline
, dll_name
);
865 for (i
= 1; i
< argc
; ++i
)
867 if (dlltool_arg_indices
[i
])
869 char *arg
= saved_argv
[i
];
870 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
871 dyn_string_append_cstr (dlltool_cmdline
,
872 (quote
) ? " \"" : " ");
873 dyn_string_append_cstr (dlltool_cmdline
, arg
);
874 dyn_string_append_cstr (dlltool_cmdline
,
875 (quote
) ? "\"" : "");
879 driver_cmdline
= dyn_string_new (cmdline_len
);
880 if (! driver_flags
|| strlen (driver_flags
) == 0)
882 switch (which_target
)
885 driver_flags
= cygwin_driver_flags
;
889 driver_flags
= mingw32_driver_flags
;
893 driver_flags
= generic_driver_flags
;
897 dyn_string_append_cstr (driver_cmdline
, driver_flags
);
898 dyn_string_append_cstr (driver_cmdline
, " -o ");
899 dyn_string_append_cstr (driver_cmdline
, dll_file_name
);
901 if (! entry_point
|| strlen (entry_point
) == 0)
903 switch (which_target
)
906 entry_point
= "__cygwin_dll_entry@12";
910 entry_point
= "_DllMainCRTStartup@12";
914 entry_point
= "_DllMain@12";
918 dyn_string_append_cstr (driver_cmdline
, " -Wl,-e,");
919 dyn_string_append_cstr (driver_cmdline
, entry_point
);
920 dyn_string_append_cstr (dlltool_cmdline
, " --exclude-symbol=");
921 dyn_string_append_cstr (dlltool_cmdline
,
922 (entry_point
[0] == '_') ? entry_point
+1 : entry_point
);
924 if (! image_base_str
|| strlen (image_base_str
) == 0)
926 char *tmpbuf
= (char *) xmalloc (sizeof ("0x12345678") + 1);
927 unsigned long hash
= strhash (dll_file_name
);
928 sprintf (tmpbuf
, "0x%.8lX", 0x60000000|((hash
<<16)&0xFFC0000));
929 image_base_str
= tmpbuf
;
932 dyn_string_append_cstr (driver_cmdline
, " -Wl,--image-base,");
933 dyn_string_append_cstr (driver_cmdline
, image_base_str
);
937 dyn_string_append_cstr (driver_cmdline
, " -v");
940 for (i
= 1; i
< argc
; ++i
)
942 if (driver_arg_indices
[i
])
944 char *arg
= saved_argv
[i
];
945 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
946 dyn_string_append_cstr (driver_cmdline
,
947 (quote
) ? " \"" : " ");
948 dyn_string_append_cstr (driver_cmdline
, arg
);
949 dyn_string_append_cstr (driver_cmdline
,
950 (quote
) ? "\"" : "");
955 * Step pre-1. If no --def <EXPORT_DEF> is specified, then create it
956 * and then pass it on.
962 dyn_string_t step_pre1
;
964 step_pre1
= dyn_string_new (1024);
966 dyn_string_append_cstr (step_pre1
, dlltool_cmdline
->s
);
969 dyn_string_append_cstr (step_pre1
, " --export-all --exclude-symbol=");
970 dyn_string_append_cstr (step_pre1
,
971 "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12");
973 dyn_string_append_cstr (step_pre1
, " --output-def ");
974 dyn_string_append_cstr (step_pre1
, def_file_name
);
976 for (i
= 1; i
< argc
; ++i
)
978 if (driver_arg_indices
[i
])
980 char *arg
= saved_argv
[i
];
981 size_t len
= strlen (arg
);
982 if (len
>= 2 && arg
[len
-2] == '.'
983 && (arg
[len
-1] == 'o' || arg
[len
-1] == 'a'))
985 int quote
= (strchr (arg
, ' ') || strchr (arg
, '\t'));
986 dyn_string_append_cstr (step_pre1
,
987 (quote
) ? " \"" : " ");
988 dyn_string_append_cstr (step_pre1
, arg
);
989 dyn_string_append_cstr (step_pre1
,
990 (quote
) ? "\"" : "");
995 if (run (dlltool_name
, step_pre1
->s
))
996 cleanup_and_exit (1);
998 dyn_string_delete (step_pre1
);
1001 dyn_string_append_cstr (dlltool_cmdline
, " --def ");
1002 dyn_string_append_cstr (dlltool_cmdline
, def_file_name
);
1006 fprintf (stderr
, _("DLLTOOL name : %s\n"), dlltool_name
);
1007 fprintf (stderr
, _("DLLTOOL options : %s\n"), dlltool_cmdline
->s
);
1008 fprintf (stderr
, _("DRIVER name : %s\n"), driver_name
);
1009 fprintf (stderr
, _("DRIVER options : %s\n"), driver_cmdline
->s
);
1013 * Step 1. Call GCC/LD to create base relocation file. If using GCC, the
1014 * driver command line will look like the following:
1016 * % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
1018 * If the user does not specify a base name, create temporary one that
1019 * is deleted at exit.
1023 if (! base_file_name
)
1025 char *fileprefix
= choose_temp_base ();
1026 base_file_name
= (char *) xmalloc (strlen (fileprefix
) + 6);
1027 sprintf (base_file_name
, "%s.base",
1028 (dontdeltemps
) ? mybasename (fileprefix
) : fileprefix
);
1029 delete_base_file
= 1;
1036 dyn_string_t step1
= dyn_string_new (driver_cmdline
->length
1037 + strlen (base_file_name
)
1039 dyn_string_append_cstr (step1
, "-Wl,--base-file,");
1040 quote
= (strchr (base_file_name
, ' ')
1041 || strchr (base_file_name
, '\t'));
1042 dyn_string_append_cstr (step1
,
1043 (quote
) ? "\"" : "");
1044 dyn_string_append_cstr (step1
, base_file_name
);
1045 dyn_string_append_cstr (step1
,
1046 (quote
) ? "\"" : "");
1047 if (driver_cmdline
->length
)
1049 dyn_string_append_cstr (step1
, " ");
1050 dyn_string_append_cstr (step1
, driver_cmdline
->s
);
1053 if (run (driver_name
, step1
->s
))
1054 cleanup_and_exit (1);
1056 dyn_string_delete (step1
);
1062 * Step 2. generate the exp file by running dlltool.
1063 * dlltool command line will look like the following:
1065 * % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
1067 * If the user does not specify a base name, create temporary one that
1068 * is deleted at exit.
1072 if (! exp_file_name
)
1074 char *p
= strrchr (dll_name
, '.');
1075 size_t prefix_len
= (p
) ? p
- dll_name
: strlen (dll_name
);
1076 exp_file_name
= (char *) xmalloc (prefix_len
+ 4 + 1);
1077 strncpy (exp_file_name
, dll_name
, prefix_len
);
1078 exp_file_name
[prefix_len
] = '\0';
1079 strcat (exp_file_name
, ".exp");
1080 delete_exp_file
= 1;
1085 dyn_string_t step2
= dyn_string_new (dlltool_cmdline
->length
1086 + strlen (base_file_name
)
1087 + strlen (exp_file_name
)
1090 dyn_string_append_cstr (step2
, "--base-file ");
1091 quote
= (strchr (base_file_name
, ' ')
1092 || strchr (base_file_name
, '\t'));
1093 dyn_string_append_cstr (step2
,
1094 (quote
) ? "\"" : "");
1095 dyn_string_append_cstr (step2
, base_file_name
);
1096 dyn_string_append_cstr (step2
,
1097 (quote
) ? "\" " : " ");
1099 dyn_string_append_cstr (step2
, "--output-exp ");
1100 quote
= (strchr (exp_file_name
, ' ')
1101 || strchr (exp_file_name
, '\t'));
1102 dyn_string_append_cstr (step2
,
1103 (quote
) ? "\"" : "");
1104 dyn_string_append_cstr (step2
, exp_file_name
);
1105 dyn_string_append_cstr (step2
,
1106 (quote
) ? "\"" : "");
1108 if (dlltool_cmdline
->length
)
1110 dyn_string_append_cstr (step2
, " ");
1111 dyn_string_append_cstr (step2
, dlltool_cmdline
->s
);
1114 if (run (dlltool_name
, step2
->s
))
1115 cleanup_and_exit (1);
1117 dyn_string_delete (step2
);
1121 * Step 3. Call GCC/LD to again, adding the exp file this time.
1122 * driver command line will look like the following:
1124 * % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...]
1130 dyn_string_t step3
= dyn_string_new (driver_cmdline
->length
1131 + strlen (exp_file_name
)
1132 + strlen (base_file_name
)
1134 dyn_string_append_cstr (step3
, "-Wl,--base-file,");
1135 quote
= (strchr (base_file_name
, ' ')
1136 || strchr (base_file_name
, '\t'));
1137 dyn_string_append_cstr (step3
,
1138 (quote
) ? "\"" : "");
1139 dyn_string_append_cstr (step3
, base_file_name
);
1140 dyn_string_append_cstr (step3
,
1141 (quote
) ? "\" " : " ");
1143 quote
= (strchr (exp_file_name
, ' ')
1144 || strchr (exp_file_name
, '\t'));
1145 dyn_string_append_cstr (step3
,
1146 (quote
) ? "\"" : "");
1147 dyn_string_append_cstr (step3
, exp_file_name
);
1148 dyn_string_append_cstr (step3
,
1149 (quote
) ? "\"" : "");
1151 if (driver_cmdline
->length
)
1153 dyn_string_append_cstr (step3
, " ");
1154 dyn_string_append_cstr (step3
, driver_cmdline
->s
);
1157 if (run (driver_name
, step3
->s
))
1158 cleanup_and_exit (1);
1160 dyn_string_delete (step3
);
1165 * Step 4. Run DLLTOOL again using the same command line.
1170 dyn_string_t step4
= dyn_string_new (dlltool_cmdline
->length
1171 + strlen (base_file_name
)
1172 + strlen (exp_file_name
)
1175 dyn_string_append_cstr (step4
, "--base-file ");
1176 quote
= (strchr (base_file_name
, ' ')
1177 || strchr (base_file_name
, '\t'));
1178 dyn_string_append_cstr (step4
,
1179 (quote
) ? "\"" : "");
1180 dyn_string_append_cstr (step4
, base_file_name
);
1181 dyn_string_append_cstr (step4
,
1182 (quote
) ? "\" " : " ");
1184 dyn_string_append_cstr (step4
, "--output-exp ");
1185 quote
= (strchr (exp_file_name
, ' ')
1186 || strchr (exp_file_name
, '\t'));
1187 dyn_string_append_cstr (step4
,
1188 (quote
) ? "\"" : "");
1189 dyn_string_append_cstr (step4
, exp_file_name
);
1190 dyn_string_append_cstr (step4
,
1191 (quote
) ? "\"" : "");
1193 if (dlltool_cmdline
->length
)
1195 dyn_string_append_cstr (step4
, " ");
1196 dyn_string_append_cstr (step4
, dlltool_cmdline
->s
);
1199 if (output_lib_file_name
)
1201 dyn_string_append_cstr (step4
, " --output-lib ");
1202 dyn_string_append_cstr (step4
, output_lib_file_name
);
1205 if (run (dlltool_name
, step4
->s
))
1206 cleanup_and_exit (1);
1208 dyn_string_delete (step4
);
1213 * Step 5. Link it all together and be done with it.
1214 * driver command line will look like the following:
1216 * % gcc -Wl,--dll foo.exp [rest ...]
1223 dyn_string_t step5
= dyn_string_new (driver_cmdline
->length
1224 + strlen (exp_file_name
)
1226 quote
= (strchr (exp_file_name
, ' ')
1227 || strchr (exp_file_name
, '\t'));
1228 dyn_string_append_cstr (step5
,
1229 (quote
) ? "\"" : "");
1230 dyn_string_append_cstr (step5
, exp_file_name
);
1231 dyn_string_append_cstr (step5
,
1232 (quote
) ? "\"" : "");
1234 if (driver_cmdline
->length
)
1236 dyn_string_append_cstr (step5
, " ");
1237 dyn_string_append_cstr (step5
, driver_cmdline
->s
);
1240 if (run (driver_name
, step5
->s
))
1241 cleanup_and_exit (1);
1243 dyn_string_delete (step5
);
1246 cleanup_and_exit (0);