* Makefile.am: Rebuild dependencies.
[binutils.git] / binutils / dllwrap.c
blob574611b3dd97b009f3ca3fcb0113fe37def10120
1 /* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs
2 Copyright (C) 1998, 1999 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
20 02111-1307, USA. */
22 /* AIX requires this to be the first thing in the file. */
23 #ifndef __GNUC__
24 # ifdef _AIX
25 #pragma alloca
26 #endif
27 #endif
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
34 #include <stdio.h>
35 #include <errno.h>
36 #include <string.h>
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
44 #include "bfd.h"
45 #include "libiberty.h"
46 #include "bucomm.h"
47 #include "getopt.h"
48 #include "dyn-string.h"
50 #include <ctype.h>
51 #include <time.h>
53 #ifdef HAVE_SYS_WAIT_H
54 #include <sys/wait.h>
55 #else /* ! HAVE_SYS_WAIT_H */
56 #if ! defined (_WIN32) || defined (__CYGWIN32__)
57 #ifndef WIFEXITED
58 #define WIFEXITED(w) (((w)&0377) == 0)
59 #endif
60 #ifndef WIFSIGNALED
61 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
62 #endif
63 #ifndef WTERMSIG
64 #define WTERMSIG(w) ((w) & 0177)
65 #endif
66 #ifndef WEXITSTATUS
67 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
68 #endif
69 #else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
70 #ifndef WIFEXITED
71 #define WIFEXITED(w) (((w) & 0xff) == 0)
72 #endif
73 #ifndef WIFSIGNALED
74 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
75 #endif
76 #ifndef WTERMSIG
77 #define WTERMSIG(w) ((w) & 0x7f)
78 #endif
79 #ifndef WEXITSTATUS
80 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
81 #endif
82 #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
83 #endif /* ! HAVE_SYS_WAIT_H */
85 static char *program_version = "0.2.4";
86 static char *driver_name = "gcc";
87 static char *cygwin_driver_flags =
88 "-Wl,--dll -nostartfiles";
89 static char *mingw32_driver_flags = "-mdll";
90 static char *generic_driver_flags = "-Wl,--dll";
92 static char *entry_point;
94 static char *dlltool_name = "dlltool";
96 static char *target = TARGET;
98 typedef enum {
99 UNKNOWN_TARGET,
100 CYGWIN_TARGET,
101 MINGW32_TARGET
103 target_type;
105 static target_type which_target = UNKNOWN_TARGET;
107 static int dontdeltemps = 0;
108 static int dry_run = 0;
110 static char *program_name;
112 static int verbose = 0;
114 static char *dll_file_name;
115 static char *dll_name;
116 static char *base_file_name;
117 static char *exp_file_name;
118 static char *def_file_name;
119 static int delete_base_file = 1;
120 static int delete_exp_file = 1;
121 static int delete_def_file = 1;
123 static int run PARAMS ((const char *, char *));
124 static void usage PARAMS ((FILE *, int));
125 static void delete_temp_files PARAMS ((void));
126 static void cleanup_and_exit PARAMS ((int status));
128 /**********************************************************************/
130 static void
131 delete_temp_files ()
133 if (delete_base_file && base_file_name)
135 if (verbose)
136 fprintf (stderr, "%s temporary base file %s\n",
137 dontdeltemps ? "Keeping" : "Deleting",
138 base_file_name);
139 if (! dontdeltemps)
141 unlink (base_file_name);
142 free (base_file_name);
146 if (delete_exp_file && exp_file_name)
148 if (verbose)
149 fprintf (stderr, "%s temporary exp file %s\n",
150 dontdeltemps ? "Keeping" : "Deleting",
151 exp_file_name);
152 if (! dontdeltemps)
154 unlink (exp_file_name);
155 free (exp_file_name);
158 if (delete_def_file && def_file_name)
160 if (verbose)
161 fprintf (stderr, "%s temporary def file %s\n",
162 dontdeltemps ? "Keeping" : "Deleting",
163 def_file_name);
164 if (! dontdeltemps)
166 unlink (def_file_name);
167 free (def_file_name);
172 static void
173 cleanup_and_exit (int status)
175 delete_temp_files ();
176 exit (status);
179 static int
180 run (what, args)
181 const char *what;
182 char *args;
184 char *s;
185 int pid, wait_status, retcode;
186 int i;
187 const char **argv;
188 char *errmsg_fmt, *errmsg_arg;
189 char *temp_base = choose_temp_base ();
190 int in_quote;
191 char sep;
193 if (verbose || dry_run)
194 fprintf (stderr, "%s %s\n", what, args);
196 /* Count the args */
197 i = 0;
198 for (s = args; *s; s++)
199 if (*s == ' ')
200 i++;
201 i++;
202 argv = alloca (sizeof (char *) * (i + 3));
203 i = 0;
204 argv[i++] = what;
205 s = args;
206 while (1)
208 while (*s == ' ' && *s != 0)
209 s++;
210 if (*s == 0)
211 break;
212 in_quote = (*s == '\'' || *s == '"');
213 sep = (in_quote) ? *s++ : ' ';
214 argv[i++] = s;
215 while (*s != sep && *s != 0)
216 s++;
217 if (*s == 0)
218 break;
219 *s++ = 0;
220 if (in_quote)
221 s++;
223 argv[i++] = NULL;
225 if (dry_run)
226 return 0;
228 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
229 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
231 if (pid == -1)
233 int errno_val = errno;
235 fprintf (stderr, "%s: ", program_name);
236 fprintf (stderr, errmsg_fmt, errmsg_arg);
237 fprintf (stderr, ": %s\n", strerror (errno_val));
238 return 1;
241 retcode = 0;
242 pid = pwait (pid, &wait_status, 0);
243 if (pid == -1)
245 fprintf (stderr, "%s: wait: %s\n", program_name, strerror (errno));
246 retcode = 1;
248 else if (WIFSIGNALED (wait_status))
250 fprintf (stderr, "%s: subprocess got fatal signal %d\n",
251 program_name, WTERMSIG (wait_status));
252 retcode = 1;
254 else if (WIFEXITED (wait_status))
256 if (WEXITSTATUS (wait_status) != 0)
258 fprintf (stderr, "%s: %s exited with status %d\n",
259 program_name, what, WEXITSTATUS (wait_status));
260 retcode = 1;
263 else
264 retcode = 1;
266 return retcode;
269 static char *
270 mybasename (name)
271 const char *name;
273 const char *base = name;
275 while (*name)
277 if (*name == '/' || *name == '\\')
279 base = name + 1;
281 ++name;
283 return (char *) base;
286 static int
287 strhash (const char *str)
289 const unsigned char *s;
290 unsigned long hash;
291 unsigned int c;
292 unsigned int len;
294 hash = 0;
295 len = 0;
296 s = (const unsigned char *) str;
297 while ((c = *s++) != '\0')
299 hash += c + (c << 17);
300 hash ^= hash >> 2;
301 ++len;
303 hash += len + (len << 17);
304 hash ^= hash >> 2;
306 return hash;
309 /**********************************************************************/
311 void
312 print_version (name)
313 const char *name;
315 /* This output is intended to follow the GNU standards document. */
316 /* xgettext:c-format */
317 printf ("GNU %s %s\n", name, program_version);
318 printf ("Copyright 1998 Free Software Foundation, Inc.\n");
319 printf ("\
320 This program is free software; you may redistribute it under the terms of\n\
321 the GNU General Public License. This program has absolutely no warranty.\n");
322 exit (0);
325 static void
326 usage (file, status)
327 FILE *file;
328 int status;
330 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
331 fprintf (file, " Generic options:\n");
332 fprintf (file, " --quiet, -q Work quietly\n");
333 fprintf (file, " --verbose, -v Verbose\n");
334 fprintf (file, " --version Print dllwrap version\n");
335 fprintf (file, " --implib <outname> Synonym for --output-lib\n");
336 fprintf (file, " Options for %s:\n", program_name);
337 fprintf (file, " --driver-name <driver> Defaults to \"gcc\"\n");
338 fprintf (file, " --driver-flags <flags> Override default ld flags\n");
339 fprintf (file, " --dlltool-name <dlltool> Defaults to \"dlltool\"\n");
340 fprintf (file, " --entry <entry> Specify alternate DLL entry point\n");
341 fprintf (file, " --image-base <base> Specify image base address\n");
342 fprintf (file, " --target <machine> i386-cygwin32 or i386-mingw32\n");
343 fprintf (file, " --dry-run Show what needs to be run\n");
344 fprintf (file, " Options passed to DLLTOOL:\n");
345 fprintf (file, " --machine <machine>\n");
346 fprintf (file, " --output-exp <outname> Generate export file.\n");
347 fprintf (file, " --output-lib <outname> Generate input library.\n");
348 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
349 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
350 fprintf (file, " --def <deffile> Name input .def file\n");
351 fprintf (file, " --output-def <deffile> Name output .def file\n");
352 fprintf (file, " --export-all-symbols Export all symbols to .def\n");
353 fprintf (file, " --no-export-all-symbols Only export .drectve symbols\n");
354 fprintf (file, " --exclude-symbols <list> Exclude <list> from .def\n");
355 fprintf (file, " --no-default-excludes Zap default exclude symbols\n");
356 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
357 fprintf (file, " --no-idata4 Don't generate idata$4 section\n");
358 fprintf (file, " --no-idata5 Don't generate idata$5 section\n");
359 fprintf (file, " -U Add underscores to .lib\n");
360 fprintf (file, " -k Kill @<n> from exported names\n");
361 fprintf (file, " --add-stdcall-alias Add aliases without @<n>\n");
362 fprintf (file, " --as <name> Use <name> for assembler\n");
363 fprintf (file, " --nodelete Keep temp files.\n");
364 fprintf (file, " Rest are passed unmodified to the language driver\n");
365 fprintf (file, "\n\n");
366 exit (status);
369 #define OPTION_START 149
371 /* GENERIC options. */
372 #define OPTION_QUIET (OPTION_START + 1)
373 #define OPTION_VERBOSE (OPTION_QUIET + 1)
374 #define OPTION_VERSION (OPTION_VERBOSE + 1)
376 /* DLLWRAP options. */
377 #define OPTION_DRY_RUN (OPTION_VERSION + 1)
378 #define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1)
379 #define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1)
380 #define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1)
381 #define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1)
382 #define OPTION_IMAGE_BASE (OPTION_ENTRY + 1)
383 #define OPTION_TARGET (OPTION_IMAGE_BASE + 1)
385 /* DLLTOOL options. */
386 #define OPTION_NODELETE (OPTION_TARGET + 1)
387 #define OPTION_DLLNAME (OPTION_NODELETE + 1)
388 #define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1)
389 #define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1)
390 #define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1)
391 #define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1)
392 #define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1)
393 #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
394 #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
395 #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
396 #define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1)
397 #define OPTION_DEF (OPTION_OUTPUT_LIB + 1)
398 #define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1)
399 #define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1)
400 #define OPTION_HELP (OPTION_KILLAT + 1)
401 #define OPTION_MACHINE (OPTION_HELP + 1)
402 #define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1)
403 #define OPTION_BASE_FILE (OPTION_ADD_INDIRECT + 1)
404 #define OPTION_AS (OPTION_BASE_FILE + 1)
406 static const struct option long_options[] =
408 /* generic options. */
409 {"quiet", no_argument, NULL, 'q'},
410 {"verbose", no_argument, NULL, 'v'},
411 {"version", no_argument, NULL, OPTION_VERSION},
412 {"implib", required_argument, NULL, OPTION_OUTPUT_LIB},
414 /* dllwrap options. */
415 {"dry-run", no_argument, NULL, OPTION_DRY_RUN},
416 {"driver-name", required_argument, NULL, OPTION_DRIVER_NAME},
417 {"driver-flags", required_argument, NULL, OPTION_DRIVER_FLAGS},
418 {"dlltool-name", required_argument, NULL, OPTION_DLLTOOL_NAME},
419 {"entry", required_argument, NULL, 'e'},
420 {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
421 {"target", required_argument, NULL, OPTION_TARGET},
423 /* dlltool options. */
424 {"no-delete", no_argument, NULL, 'n'},
425 {"dllname", required_argument, NULL, OPTION_DLLNAME},
426 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
427 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
428 {"output-exp", required_argument, NULL, OPTION_OUTPUT_EXP},
429 {"output-def", required_argument, NULL, OPTION_OUTPUT_DEF},
430 {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
431 {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
432 {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
433 {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
434 {"output-lib", required_argument, NULL, OPTION_OUTPUT_LIB},
435 {"def", required_argument, NULL, OPTION_DEF},
436 {"add-underscore", no_argument, NULL, 'U'},
437 {"killat", no_argument, NULL, 'k'},
438 {"add-stdcall-alias", no_argument, NULL, 'A'},
439 {"help", no_argument, NULL, 'h'},
440 {"machine", required_argument, NULL, OPTION_MACHINE},
441 {"add-indirect", no_argument, NULL, OPTION_ADD_INDIRECT},
442 {"base-file", required_argument, NULL, OPTION_BASE_FILE},
443 {"as", required_argument, NULL, OPTION_AS},
448 main (argc, argv)
449 int argc;
450 char **argv;
452 int c;
453 int i;
455 char **saved_argv = 0;
456 int cmdline_len = 0;
458 int export_all = 0;
460 int *dlltool_arg_indices;
461 int *driver_arg_indices;
463 char *driver_flags = 0;
464 char *output_lib_file_name = 0;
466 dyn_string_t dlltool_cmdline;
467 dyn_string_t driver_cmdline;
469 int def_file_seen = 0;
471 char *image_base_str = 0;
473 program_name = argv[0];
475 saved_argv = (char **) xmalloc (argc * sizeof (char*));
476 dlltool_arg_indices = (int *) xmalloc (argc * sizeof (int));
477 driver_arg_indices = (int *) xmalloc (argc * sizeof (int));
478 for (i = 0; i < argc; ++i)
480 size_t len = strlen (argv[i]);
481 char *arg = (char *) xmalloc (len + 1);
482 strcpy (arg, argv[i]);
483 cmdline_len += len;
484 saved_argv[i] = arg;
485 dlltool_arg_indices[i] = 0;
486 driver_arg_indices[i] = 1;
488 cmdline_len++;
490 /* We recognize dllwrap and dlltool options, and everything else is
491 passed onto the language driver (eg., to GCC). We collect options
492 to dlltool and driver in dlltool_args and driver_args. */
494 opterr = 0;
495 while ((c = getopt_long_only (argc, argv, "nkAqve:Uho:l:L:I:",
496 long_options, (int *) 0)) != EOF)
498 int dlltool_arg;
499 int driver_arg;
500 int single_word_option_value_pair;
502 dlltool_arg = 0;
503 driver_arg = 1;
504 single_word_option_value_pair = 0;
506 if (c != '?')
508 /* We recognize this option, so it has to be either dllwrap or
509 dlltool option. Do not pass to driver unless it's one of the
510 generic options that are passed to all the tools (such as -v)
511 which are dealt with later. */
512 driver_arg = 0;
515 /* deal with generic and dllwrap options first. */
516 switch (c)
518 case 'h':
519 usage (stdout, 0);
520 break;
521 case 'q':
522 verbose = 0;
523 break;
524 case 'v':
525 verbose = 1;
526 break;
527 case OPTION_VERSION:
528 print_version (program_name);
529 break;
530 case 'e':
531 entry_point = optarg;
532 break;
533 case OPTION_IMAGE_BASE:
534 image_base_str = optarg;
535 break;
536 case OPTION_DEF:
537 def_file_name = optarg;
538 def_file_seen = 1;
539 delete_def_file = 0;
540 break;
541 case 'n':
542 dontdeltemps = 1;
543 dlltool_arg = 1;
544 break;
545 case 'o':
546 dll_file_name = optarg;
547 break;
548 case 'I':
549 case 'l':
550 case 'L':
551 driver_arg = 1;
552 break;
553 case OPTION_DLLNAME:
554 dll_name = optarg;
555 break;
556 case OPTION_DRY_RUN:
557 dry_run = 1;
558 break;
559 case OPTION_DRIVER_NAME:
560 driver_name = optarg;
561 break;
562 case OPTION_DRIVER_FLAGS:
563 driver_flags = optarg;
564 break;
565 case OPTION_DLLTOOL_NAME:
566 dlltool_name = optarg;
567 break;
568 case OPTION_TARGET:
569 target = optarg;
570 break;
571 case OPTION_BASE_FILE:
572 base_file_name = optarg;
573 delete_base_file = 0;
574 break;
575 case OPTION_OUTPUT_EXP:
576 exp_file_name = optarg;
577 delete_exp_file = 0;
578 break;
579 case OPTION_EXPORT_ALL_SYMS:
580 export_all = 1;
581 break;
582 case OPTION_OUTPUT_LIB:
583 output_lib_file_name = optarg;
584 break;
585 case '?':
586 break;
587 default:
588 dlltool_arg = 1;
589 break;
592 /* Handle passing through --option=value case. */
593 if (optarg
594 && saved_argv[optind-1][0] == '-'
595 && saved_argv[optind-1][1] == '-'
596 && strchr (saved_argv[optind-1], '='))
597 single_word_option_value_pair = 1;
599 if (dlltool_arg)
601 dlltool_arg_indices[optind-1] = 1;
602 if (optarg && ! single_word_option_value_pair)
604 dlltool_arg_indices[optind-2] = 1;
608 if (! driver_arg)
610 driver_arg_indices[optind-1] = 0;
611 if (optarg && ! single_word_option_value_pair)
613 driver_arg_indices[optind-2] = 0;
618 /* sanity checks. */
619 if (! dll_name && ! dll_file_name)
621 fprintf (stderr,
622 "%s: Must provide at least one of -o or --dllname options\n",
623 program_name);
624 exit (1);
626 else if (! dll_name)
628 dll_name = xstrdup (mybasename (dll_file_name));
630 else if (! dll_file_name)
632 dll_file_name = xstrdup (dll_name);
635 if (! def_file_seen)
637 char *fileprefix = choose_temp_base ();
638 def_file_name = (char *) xmalloc (strlen (fileprefix) + 5);
639 sprintf (def_file_name, "%s.def",
640 (dontdeltemps) ? mybasename (fileprefix) : fileprefix);
641 delete_def_file = 1;
642 free (fileprefix);
643 delete_def_file = 1;
644 fprintf (stderr, "Warning: no export definition file provided\n");
645 fprintf (stderr,
646 "dllwrap will create one, but may not be what you want\n");
649 /* set the target platform. */
650 if (strstr (target, "cygwin32"))
651 which_target = CYGWIN_TARGET;
652 else if (strstr (target, "mingw32"))
653 which_target = MINGW32_TARGET;
654 else
655 which_target = UNKNOWN_TARGET;
657 /* re-create the command lines as a string, taking care to quote stuff. */
658 dlltool_cmdline = dyn_string_new (cmdline_len);
659 if (verbose)
661 dyn_string_append (dlltool_cmdline, " -v");
663 dyn_string_append (dlltool_cmdline, " --dllname ");
664 dyn_string_append (dlltool_cmdline, dll_name);
666 for (i = 1; i < argc; ++i)
668 if (dlltool_arg_indices[i])
670 char *arg = saved_argv[i];
671 int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
672 dyn_string_append (dlltool_cmdline,
673 (quote) ? " \"" : " ");
674 dyn_string_append (dlltool_cmdline, arg);
675 dyn_string_append (dlltool_cmdline,
676 (quote) ? "\"" : "");
680 driver_cmdline = dyn_string_new (cmdline_len);
681 if (! driver_flags || strlen (driver_flags) == 0)
683 switch (which_target)
685 case CYGWIN_TARGET:
686 driver_flags = cygwin_driver_flags;
687 break;
689 case MINGW32_TARGET:
690 driver_flags = mingw32_driver_flags;
691 break;
693 default:
694 driver_flags = generic_driver_flags;
695 break;
698 dyn_string_append (driver_cmdline, driver_flags);
699 dyn_string_append (driver_cmdline, " -o ");
700 dyn_string_append (driver_cmdline, dll_file_name);
702 if (! entry_point || strlen (entry_point) == 0)
704 switch (which_target)
706 case CYGWIN_TARGET:
707 entry_point = "__cygwin_dll_entry@12";
708 break;
710 case MINGW32_TARGET:
711 entry_point = "_DllMainCRTStartup@12";
712 break;
714 default:
715 entry_point = "_DllMain@12";
716 break;
719 dyn_string_append (driver_cmdline, " -Wl,-e,");
720 dyn_string_append (driver_cmdline, entry_point);
721 dyn_string_append (dlltool_cmdline, " --exclude-symbol=");
722 dyn_string_append (dlltool_cmdline,
723 (entry_point[0] == '_') ? entry_point+1 : entry_point);
725 if (! image_base_str || strlen (image_base_str) == 0)
727 char *tmpbuf = (char *) xmalloc (sizeof ("0x12345678") + 1);
728 unsigned long hash = strhash (dll_file_name);
729 sprintf (tmpbuf, "0x%.8lX", 0x60000000|((hash<<16)&0xFFC0000));
730 image_base_str = tmpbuf;
733 dyn_string_append (driver_cmdline, " -Wl,--image-base,");
734 dyn_string_append (driver_cmdline, image_base_str);
736 if (verbose)
738 dyn_string_append (driver_cmdline, " -v");
741 for (i = 1; i < argc; ++i)
743 if (driver_arg_indices[i])
745 char *arg = saved_argv[i];
746 int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
747 dyn_string_append (driver_cmdline,
748 (quote) ? " \"" : " ");
749 dyn_string_append (driver_cmdline, arg);
750 dyn_string_append (driver_cmdline,
751 (quote) ? "\"" : "");
756 * Step pre-1. If no --def <EXPORT_DEF> is specified, then create it
757 * and then pass it on.
760 if (! def_file_seen)
762 int i;
763 dyn_string_t step_pre1;
765 step_pre1 = dyn_string_new (1024);
767 dyn_string_append (step_pre1, dlltool_cmdline->s);
768 if (export_all)
770 dyn_string_append (step_pre1, " --export-all --exclude-symbol=");
771 dyn_string_append (step_pre1,
772 "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12");
774 dyn_string_append (step_pre1, " --output-def ");
775 dyn_string_append (step_pre1, def_file_name);
777 for (i = 1; i < argc; ++i)
779 if (driver_arg_indices[i])
781 char *arg = saved_argv[i];
782 size_t len = strlen (arg);
783 if (len >= 2 && arg[len-2] == '.'
784 && (arg[len-1] == 'o' || arg[len-1] == 'a'))
786 int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
787 dyn_string_append (step_pre1,
788 (quote) ? " \"" : " ");
789 dyn_string_append (step_pre1, arg);
790 dyn_string_append (step_pre1,
791 (quote) ? "\"" : "");
796 if (run (dlltool_name, step_pre1->s))
797 cleanup_and_exit (1);
799 dyn_string_delete (step_pre1);
802 dyn_string_append (dlltool_cmdline, " --def ");
803 dyn_string_append (dlltool_cmdline, def_file_name);
805 if (verbose)
807 fprintf (stderr, "DLLTOOL name : %s\n", dlltool_name);
808 fprintf (stderr, "DLLTOOL options : %s\n", dlltool_cmdline->s);
809 fprintf (stderr, "DRIVER name : %s\n", driver_name);
810 fprintf (stderr, "DRIVER options : %s\n", driver_cmdline->s);
814 * Step 1. Call GCC/LD to create base relocation file. If using GCC, the
815 * driver command line will look like the following:
817 * % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
819 * If the user does not specify a base name, create temporary one that
820 * is deleted at exit.
824 if (! base_file_name)
826 char *fileprefix = choose_temp_base ();
827 base_file_name = (char *) xmalloc (strlen (fileprefix) + 6);
828 sprintf (base_file_name, "%s.base",
829 (dontdeltemps) ? mybasename (fileprefix) : fileprefix);
830 delete_base_file = 1;
831 free (fileprefix);
835 int quote;
837 dyn_string_t step1 = dyn_string_new (driver_cmdline->length
838 + strlen (base_file_name)
839 + 20);
840 dyn_string_append (step1, "-Wl,--base-file,");
841 quote = (strchr (base_file_name, ' ')
842 || strchr (base_file_name, '\t'));
843 dyn_string_append (step1,
844 (quote) ? "\"" : "");
845 dyn_string_append (step1, base_file_name);
846 dyn_string_append (step1,
847 (quote) ? "\"" : "");
848 if (driver_cmdline->length)
850 dyn_string_append (step1, " ");
851 dyn_string_append (step1, driver_cmdline->s);
854 if (run (driver_name, step1->s))
855 cleanup_and_exit (1);
857 dyn_string_delete (step1);
863 * Step 2. generate the exp file by running dlltool.
864 * dlltool command line will look like the following:
866 * % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
868 * If the user does not specify a base name, create temporary one that
869 * is deleted at exit.
873 if (! exp_file_name)
875 char *p = strrchr (dll_name, '.');
876 size_t prefix_len = (p) ? p - dll_name : strlen (dll_name);
877 exp_file_name = (char *) xmalloc (prefix_len + 4 + 1);
878 strncpy (exp_file_name, dll_name, prefix_len);
879 exp_file_name[prefix_len] = '\0';
880 strcat (exp_file_name, ".exp");
881 delete_exp_file = 1;
885 int quote;
886 dyn_string_t step2 = dyn_string_new (dlltool_cmdline->length
887 + strlen (base_file_name)
888 + strlen (exp_file_name)
889 + 20);
891 dyn_string_append (step2, "--base-file ");
892 quote = (strchr (base_file_name, ' ')
893 || strchr (base_file_name, '\t'));
894 dyn_string_append (step2,
895 (quote) ? "\"" : "");
896 dyn_string_append (step2, base_file_name);
897 dyn_string_append (step2,
898 (quote) ? "\" " : " ");
900 dyn_string_append (step2, "--output-exp ");
901 quote = (strchr (exp_file_name, ' ')
902 || strchr (exp_file_name, '\t'));
903 dyn_string_append (step2,
904 (quote) ? "\"" : "");
905 dyn_string_append (step2, exp_file_name);
906 dyn_string_append (step2,
907 (quote) ? "\"" : "");
909 if (dlltool_cmdline->length)
911 dyn_string_append (step2, " ");
912 dyn_string_append (step2, dlltool_cmdline->s);
915 if (run (dlltool_name, step2->s))
916 cleanup_and_exit (1);
918 dyn_string_delete (step2);
922 * Step 3. Call GCC/LD to again, adding the exp file this time.
923 * driver command line will look like the following:
925 * % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...]
929 int quote;
931 dyn_string_t step3 = dyn_string_new (driver_cmdline->length
932 + strlen (exp_file_name)
933 + strlen (base_file_name)
934 + 20);
935 dyn_string_append (step3, "-Wl,--base-file,");
936 quote = (strchr (base_file_name, ' ')
937 || strchr (base_file_name, '\t'));
938 dyn_string_append (step3,
939 (quote) ? "\"" : "");
940 dyn_string_append (step3, base_file_name);
941 dyn_string_append (step3,
942 (quote) ? "\" " : " ");
944 quote = (strchr (exp_file_name, ' ')
945 || strchr (exp_file_name, '\t'));
946 dyn_string_append (step3,
947 (quote) ? "\"" : "");
948 dyn_string_append (step3, exp_file_name);
949 dyn_string_append (step3,
950 (quote) ? "\"" : "");
952 if (driver_cmdline->length)
954 dyn_string_append (step3, " ");
955 dyn_string_append (step3, driver_cmdline->s);
958 if (run (driver_name, step3->s))
959 cleanup_and_exit (1);
961 dyn_string_delete (step3);
966 * Step 4. Run DLLTOOL again using the same command line.
970 int quote;
971 dyn_string_t step4 = dyn_string_new (dlltool_cmdline->length
972 + strlen (base_file_name)
973 + strlen (exp_file_name)
974 + 20);
976 dyn_string_append (step4, "--base-file ");
977 quote = (strchr (base_file_name, ' ')
978 || strchr (base_file_name, '\t'));
979 dyn_string_append (step4,
980 (quote) ? "\"" : "");
981 dyn_string_append (step4, base_file_name);
982 dyn_string_append (step4,
983 (quote) ? "\" " : " ");
985 dyn_string_append (step4, "--output-exp ");
986 quote = (strchr (exp_file_name, ' ')
987 || strchr (exp_file_name, '\t'));
988 dyn_string_append (step4,
989 (quote) ? "\"" : "");
990 dyn_string_append (step4, exp_file_name);
991 dyn_string_append (step4,
992 (quote) ? "\"" : "");
994 if (dlltool_cmdline->length)
996 dyn_string_append (step4, " ");
997 dyn_string_append (step4, dlltool_cmdline->s);
1000 if (output_lib_file_name)
1002 dyn_string_append (step4, " --output-lib ");
1003 dyn_string_append (step4, output_lib_file_name);
1006 if (run (dlltool_name, step4->s))
1007 cleanup_and_exit (1);
1009 dyn_string_delete (step4);
1014 * Step 5. Link it all together and be done with it.
1015 * driver command line will look like the following:
1017 * % gcc -Wl,--dll foo.exp [rest ...]
1022 int quote;
1024 dyn_string_t step5 = dyn_string_new (driver_cmdline->length
1025 + strlen (exp_file_name)
1026 + 20);
1027 quote = (strchr (exp_file_name, ' ')
1028 || strchr (exp_file_name, '\t'));
1029 dyn_string_append (step5,
1030 (quote) ? "\"" : "");
1031 dyn_string_append (step5, exp_file_name);
1032 dyn_string_append (step5,
1033 (quote) ? "\"" : "");
1035 if (driver_cmdline->length)
1037 dyn_string_append (step5, " ");
1038 dyn_string_append (step5, driver_cmdline->s);
1041 if (run (driver_name, step5->s))
1042 cleanup_and_exit (1);
1044 dyn_string_delete (step5);
1047 cleanup_and_exit (0);
1049 return 0;