* addr2line.c: Convert to ISO C90 prototypes, change PTR, remove
[deliverable/binutils-gdb.git] / binutils / dllwrap.c
CommitLineData
252b5132 1/* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs
2da42df6 2 Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
252b5132
RH
3 Contributed by Mumit Khan (khan@xraylith.wisc.edu).
4
5 This file is part of GNU Binutils.
6
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.
11
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.
16
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. */
21
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
28
252b5132
RH
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
252b5132
RH
33#include "bfd.h"
34#include "libiberty.h"
35#include "bucomm.h"
36#include "getopt.h"
37#include "dyn-string.h"
38
252b5132 39#include <time.h>
bb0cb4db
ILT
40#include <sys/stat.h>
41
42#ifdef ANSI_PROTOTYPES
43#include <stdarg.h>
44#else
45#include <varargs.h>
46#endif
252b5132
RH
47
48#ifdef HAVE_SYS_WAIT_H
49#include <sys/wait.h>
50#else /* ! HAVE_SYS_WAIT_H */
51#if ! defined (_WIN32) || defined (__CYGWIN32__)
52#ifndef WIFEXITED
53#define WIFEXITED(w) (((w)&0377) == 0)
54#endif
55#ifndef WIFSIGNALED
56#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
57#endif
58#ifndef WTERMSIG
59#define WTERMSIG(w) ((w) & 0177)
60#endif
61#ifndef WEXITSTATUS
62#define WEXITSTATUS(w) (((w) >> 8) & 0377)
63#endif
64#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */
65#ifndef WIFEXITED
66#define WIFEXITED(w) (((w) & 0xff) == 0)
67#endif
68#ifndef WIFSIGNALED
69#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
70#endif
71#ifndef WTERMSIG
72#define WTERMSIG(w) ((w) & 0x7f)
73#endif
74#ifndef WEXITSTATUS
75#define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
76#endif
77#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */
78#endif /* ! HAVE_SYS_WAIT_H */
79
bb0cb4db 80static char *driver_name = NULL;
26044998 81static char *cygwin_driver_flags =
252b5132
RH
82 "-Wl,--dll -nostartfiles";
83static char *mingw32_driver_flags = "-mdll";
84static char *generic_driver_flags = "-Wl,--dll";
85
86static char *entry_point;
87
bb0cb4db 88static char *dlltool_name = NULL;
252b5132
RH
89
90static char *target = TARGET;
91
92typedef enum {
26044998
KH
93 UNKNOWN_TARGET,
94 CYGWIN_TARGET,
087f88b2 95 MINGW_TARGET
26044998 96}
252b5132
RH
97target_type;
98
99static target_type which_target = UNKNOWN_TARGET;
100
101static int dontdeltemps = 0;
102static int dry_run = 0;
103
104static char *program_name;
105
106static int verbose = 0;
107
108static char *dll_file_name;
109static char *dll_name;
110static char *base_file_name;
111static char *exp_file_name;
112static char *def_file_name;
113static int delete_base_file = 1;
114static int delete_exp_file = 1;
115static int delete_def_file = 1;
116
2da42df6
AJ
117static int run (const char *, char *);
118static char *mybasename (const char *);
119static int strhash (const char *);
120static void usage (FILE *, int);
121static void display (const char *, va_list);
122static void inform (const char *, ...);
123static void warn (const char *, ...);
124static char *look_for_prog (const char *, const char *, int);
125static char *deduce_name (const char *);
126static void delete_temp_files (void);
127static void cleanup_and_exit (int);
252b5132
RH
128
129/**********************************************************************/
130
bb0cb4db
ILT
131/* Please keep the following 4 routines in sync with dlltool.c:
132 display ()
133 inform ()
134 look_for_prog ()
135 deduce_name ()
136 It's not worth the hassle to break these out since dllwrap will
137 (hopefully) soon be retired in favor of `ld --shared. */
138
139static void
2da42df6 140display (const char * message, va_list args)
bb0cb4db
ILT
141{
142 if (program_name != NULL)
143 fprintf (stderr, "%s: ", program_name);
144
145 vfprintf (stderr, message, args);
37cc8ec1
AM
146 fputc ('\n', stderr);
147}
bb0cb4db
ILT
148
149
37cc8ec1 150static void
e80ff7de 151inform VPARAMS ((const char *message, ...))
37cc8ec1 152{
e80ff7de
AM
153 VA_OPEN (args, message);
154 VA_FIXEDARG (args, const char *, message);
37cc8ec1
AM
155
156 if (!verbose)
157 return;
158
37cc8ec1 159 display (message, args);
bb0cb4db 160
e80ff7de 161 VA_CLOSE (args);
bb0cb4db
ILT
162}
163
37cc8ec1 164static void
e80ff7de 165warn VPARAMS ((const char *format, ...))
37cc8ec1 166{
e80ff7de
AM
167 VA_OPEN (args, format);
168 VA_FIXEDARG (args, const char *, format);
37cc8ec1 169
37cc8ec1 170 display (format, args);
e80ff7de
AM
171
172 VA_CLOSE (args);
37cc8ec1 173}
37cc8ec1 174
bb0cb4db
ILT
175/* Look for the program formed by concatenating PROG_NAME and the
176 string running from PREFIX to END_PREFIX. If the concatenated
177 string contains a '/', try appending EXECUTABLE_SUFFIX if it is
2481e6a2 178 appropriate. */
bb0cb4db
ILT
179
180static char *
2da42df6 181look_for_prog (const char *prog_name, const char *prefix, int end_prefix)
bb0cb4db
ILT
182{
183 struct stat s;
184 char *cmd;
185
26044998
KH
186 cmd = xmalloc (strlen (prefix)
187 + strlen (prog_name)
2481e6a2 188#ifdef HAVE_EXECUTABLE_SUFFIX
26044998 189 + strlen (EXECUTABLE_SUFFIX)
bb0cb4db
ILT
190#endif
191 + 10);
192 strcpy (cmd, prefix);
193
194 sprintf (cmd + end_prefix, "%s", prog_name);
195
196 if (strchr (cmd, '/') != NULL)
197 {
198 int found;
199
200 found = (stat (cmd, &s) == 0
2481e6a2 201#ifdef HAVE_EXECUTABLE_SUFFIX
26044998 202 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
bb0cb4db
ILT
203#endif
204 );
205
206 if (! found)
26044998 207 {
bb0cb4db
ILT
208 /* xgettext:c-format */
209 inform (_("Tried file: %s"), cmd);
210 free (cmd);
211 return NULL;
212 }
213 }
214
215 /* xgettext:c-format */
216 inform (_("Using file: %s"), cmd);
217
218 return cmd;
219}
220
221/* Deduce the name of the program we are want to invoke.
222 PROG_NAME is the basic name of the program we want to run,
223 eg "as" or "ld". The catch is that we might want actually
26044998 224 run "i386-pe-as" or "ppc-pe-ld".
bb0cb4db
ILT
225
226 If argv[0] contains the full path, then try to find the program
227 in the same place, with and then without a target-like prefix.
228
229 Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool,
26044998 230 deduce_name("as") uses the following search order:
bb0cb4db
ILT
231
232 /usr/local/bin/i586-cygwin32-as
233 /usr/local/bin/as
234 as
26044998 235
bb0cb4db
ILT
236 If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each
237 name, it'll try without and then with EXECUTABLE_SUFFIX.
238
239 Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as"
240 as the fallback, but rather return i586-cygwin32-as.
26044998 241
bb0cb4db
ILT
242 Oh, and given, argv[0] = dlltool, it'll return "as".
243
244 Returns a dynamically allocated string. */
245
246static char *
2da42df6 247deduce_name (const char *prog_name)
bb0cb4db
ILT
248{
249 char *cmd;
250 char *dash, *slash, *cp;
251
252 dash = NULL;
253 slash = NULL;
254 for (cp = program_name; *cp != '\0'; ++cp)
255 {
256 if (*cp == '-')
257 dash = cp;
258 if (
259#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
260 *cp == ':' || *cp == '\\' ||
261#endif
262 *cp == '/')
263 {
264 slash = cp;
265 dash = NULL;
266 }
267 }
268
269 cmd = NULL;
270
271 if (dash != NULL)
272 {
273 /* First, try looking for a prefixed PROG_NAME in the
274 PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */
275 cmd = look_for_prog (prog_name, program_name, dash - program_name + 1);
276 }
277
278 if (slash != NULL && cmd == NULL)
279 {
280 /* Next, try looking for a PROG_NAME in the same directory as
281 that of this program. */
282 cmd = look_for_prog (prog_name, program_name, slash - program_name + 1);
283 }
284
285 if (cmd == NULL)
286 {
287 /* Just return PROG_NAME as is. */
288 cmd = xstrdup (prog_name);
289 }
290
291 return cmd;
292}
293
252b5132 294static void
2da42df6 295delete_temp_files (void)
252b5132
RH
296{
297 if (delete_base_file && base_file_name)
298 {
299 if (verbose)
37cc8ec1
AM
300 {
301 if (dontdeltemps)
302 warn (_("Keeping temporary base file %s"), base_file_name);
303 else
304 warn (_("Deleting temporary base file %s"), base_file_name);
305 }
252b5132 306 if (! dontdeltemps)
26044998
KH
307 {
308 unlink (base_file_name);
252b5132
RH
309 free (base_file_name);
310 }
311 }
26044998 312
252b5132
RH
313 if (delete_exp_file && exp_file_name)
314 {
315 if (verbose)
37cc8ec1
AM
316 {
317 if (dontdeltemps)
318 warn (_("Keeping temporary exp file %s"), exp_file_name);
319 else
320 warn (_("Deleting temporary exp file %s"), exp_file_name);
321 }
252b5132 322 if (! dontdeltemps)
26044998
KH
323 {
324 unlink (exp_file_name);
325 free (exp_file_name);
252b5132
RH
326 }
327 }
328 if (delete_def_file && def_file_name)
329 {
330 if (verbose)
37cc8ec1
AM
331 {
332 if (dontdeltemps)
333 warn (_("Keeping temporary def file %s"), def_file_name);
334 else
335 warn (_("Deleting temporary def file %s"), def_file_name);
336 }
252b5132 337 if (! dontdeltemps)
26044998
KH
338 {
339 unlink (def_file_name);
340 free (def_file_name);
252b5132
RH
341 }
342 }
343}
344
26044998 345static void
2da42df6 346cleanup_and_exit (int status)
252b5132
RH
347{
348 delete_temp_files ();
349 exit (status);
350}
26044998 351
252b5132 352static int
2da42df6 353run (const char *what, char *args)
252b5132
RH
354{
355 char *s;
356 int pid, wait_status, retcode;
357 int i;
358 const char **argv;
359 char *errmsg_fmt, *errmsg_arg;
360 char *temp_base = choose_temp_base ();
361 int in_quote;
362 char sep;
363
364 if (verbose || dry_run)
365 fprintf (stderr, "%s %s\n", what, args);
366
367 /* Count the args */
368 i = 0;
369 for (s = args; *s; s++)
370 if (*s == ' ')
371 i++;
372 i++;
373 argv = alloca (sizeof (char *) * (i + 3));
374 i = 0;
375 argv[i++] = what;
376 s = args;
377 while (1)
378 {
379 while (*s == ' ' && *s != 0)
380 s++;
381 if (*s == 0)
382 break;
383 in_quote = (*s == '\'' || *s == '"');
384 sep = (in_quote) ? *s++ : ' ';
385 argv[i++] = s;
386 while (*s != sep && *s != 0)
387 s++;
388 if (*s == 0)
389 break;
390 *s++ = 0;
391 if (in_quote)
26044998 392 s++;
252b5132
RH
393 }
394 argv[i++] = NULL;
395
396 if (dry_run)
397 return 0;
398
399 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
400 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
401
402 if (pid == -1)
403 {
404 int errno_val = errno;
405
406 fprintf (stderr, "%s: ", program_name);
407 fprintf (stderr, errmsg_fmt, errmsg_arg);
408 fprintf (stderr, ": %s\n", strerror (errno_val));
409 return 1;
410 }
411
412 retcode = 0;
413 pid = pwait (pid, &wait_status, 0);
414 if (pid == -1)
415 {
37cc8ec1 416 warn ("wait: %s", strerror (errno));
252b5132
RH
417 retcode = 1;
418 }
419 else if (WIFSIGNALED (wait_status))
420 {
37cc8ec1 421 warn (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
252b5132
RH
422 retcode = 1;
423 }
424 else if (WIFEXITED (wait_status))
425 {
426 if (WEXITSTATUS (wait_status) != 0)
427 {
37cc8ec1 428 warn (_("%s exited with status %d"), what, WEXITSTATUS (wait_status));
252b5132
RH
429 retcode = 1;
430 }
431 }
432 else
433 retcode = 1;
26044998 434
252b5132
RH
435 return retcode;
436}
437
438static char *
2da42df6 439mybasename (const char *name)
252b5132
RH
440{
441 const char *base = name;
442
443 while (*name)
444 {
445 if (*name == '/' || *name == '\\')
446 {
447 base = name + 1;
448 }
449 ++name;
450 }
451 return (char *) base;
452}
453
26044998 454static int
2da42df6 455strhash (const char *str)
252b5132
RH
456{
457 const unsigned char *s;
458 unsigned long hash;
459 unsigned int c;
460 unsigned int len;
461
462 hash = 0;
463 len = 0;
464 s = (const unsigned char *) str;
465 while ((c = *s++) != '\0')
466 {
467 hash += c + (c << 17);
468 hash ^= hash >> 2;
469 ++len;
470 }
471 hash += len + (len << 17);
472 hash ^= hash >> 2;
473
474 return hash;
475}
476
477/**********************************************************************/
478
252b5132 479static void
2da42df6 480usage (FILE *file, int status)
252b5132 481{
8b53311e 482 fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), program_name);
37cc8ec1
AM
483 fprintf (file, _(" Generic options:\n"));
484 fprintf (file, _(" --quiet, -q Work quietly\n"));
485 fprintf (file, _(" --verbose, -v Verbose\n"));
486 fprintf (file, _(" --version Print dllwrap version\n"));
487 fprintf (file, _(" --implib <outname> Synonym for --output-lib\n"));
488 fprintf (file, _(" Options for %s:\n"), program_name);
489 fprintf (file, _(" --driver-name <driver> Defaults to \"gcc\"\n"));
490 fprintf (file, _(" --driver-flags <flags> Override default ld flags\n"));
491 fprintf (file, _(" --dlltool-name <dlltool> Defaults to \"dlltool\"\n"));
492 fprintf (file, _(" --entry <entry> Specify alternate DLL entry point\n"));
493 fprintf (file, _(" --image-base <base> Specify image base address\n"));
494 fprintf (file, _(" --target <machine> i386-cygwin32 or i386-mingw32\n"));
495 fprintf (file, _(" --dry-run Show what needs to be run\n"));
496 fprintf (file, _(" --mno-cygwin Create Mingw DLL\n"));
497 fprintf (file, _(" Options passed to DLLTOOL:\n"));
498 fprintf (file, _(" --machine <machine>\n"));
499 fprintf (file, _(" --output-exp <outname> Generate export file.\n"));
500 fprintf (file, _(" --output-lib <outname> Generate input library.\n"));
501 fprintf (file, _(" --add-indirect Add dll indirects to export file.\n"));
502 fprintf (file, _(" --dllname <name> Name of input dll to put into output lib.\n"));
503 fprintf (file, _(" --def <deffile> Name input .def file\n"));
504 fprintf (file, _(" --output-def <deffile> Name output .def file\n"));
505 fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
506 fprintf (file, _(" --no-export-all-symbols Only export .drectve symbols\n"));
507 fprintf (file, _(" --exclude-symbols <list> Exclude <list> from .def\n"));
508 fprintf (file, _(" --no-default-excludes Zap default exclude symbols\n"));
509 fprintf (file, _(" --base-file <basefile> Read linker generated base file\n"));
510 fprintf (file, _(" --no-idata4 Don't generate idata$4 section\n"));
511 fprintf (file, _(" --no-idata5 Don't generate idata$5 section\n"));
512 fprintf (file, _(" -U Add underscores to .lib\n"));
513 fprintf (file, _(" -k Kill @<n> from exported names\n"));
514 fprintf (file, _(" --add-stdcall-alias Add aliases without @<n>\n"));
515 fprintf (file, _(" --as <name> Use <name> for assembler\n"));
516 fprintf (file, _(" --nodelete Keep temp files.\n"));
517 fprintf (file, _(" Rest are passed unmodified to the language driver\n"));
252b5132
RH
518 fprintf (file, "\n\n");
519 exit (status);
520}
521
522#define OPTION_START 149
523
26044998 524/* GENERIC options. */
252b5132
RH
525#define OPTION_QUIET (OPTION_START + 1)
526#define OPTION_VERBOSE (OPTION_QUIET + 1)
527#define OPTION_VERSION (OPTION_VERBOSE + 1)
528
26044998 529/* DLLWRAP options. */
252b5132
RH
530#define OPTION_DRY_RUN (OPTION_VERSION + 1)
531#define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1)
532#define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1)
533#define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1)
534#define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1)
535#define OPTION_IMAGE_BASE (OPTION_ENTRY + 1)
536#define OPTION_TARGET (OPTION_IMAGE_BASE + 1)
bb0cb4db 537#define OPTION_MNO_CYGWIN (OPTION_TARGET + 1)
252b5132 538
26044998 539/* DLLTOOL options. */
bb0cb4db 540#define OPTION_NODELETE (OPTION_MNO_CYGWIN + 1)
252b5132 541#define OPTION_DLLNAME (OPTION_NODELETE + 1)
2da42df6 542#define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1)
252b5132
RH
543#define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1)
544#define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1)
545#define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1)
546#define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1)
547#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
548#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
549#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
550#define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1)
551#define OPTION_DEF (OPTION_OUTPUT_LIB + 1)
552#define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1)
553#define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1)
554#define OPTION_HELP (OPTION_KILLAT + 1)
555#define OPTION_MACHINE (OPTION_HELP + 1)
556#define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1)
557#define OPTION_BASE_FILE (OPTION_ADD_INDIRECT + 1)
558#define OPTION_AS (OPTION_BASE_FILE + 1)
559
560static const struct option long_options[] =
561{
26044998 562 /* generic options. */
252b5132
RH
563 {"quiet", no_argument, NULL, 'q'},
564 {"verbose", no_argument, NULL, 'v'},
565 {"version", no_argument, NULL, OPTION_VERSION},
566 {"implib", required_argument, NULL, OPTION_OUTPUT_LIB},
567
26044998 568 /* dllwrap options. */
252b5132
RH
569 {"dry-run", no_argument, NULL, OPTION_DRY_RUN},
570 {"driver-name", required_argument, NULL, OPTION_DRIVER_NAME},
571 {"driver-flags", required_argument, NULL, OPTION_DRIVER_FLAGS},
572 {"dlltool-name", required_argument, NULL, OPTION_DLLTOOL_NAME},
573 {"entry", required_argument, NULL, 'e'},
574 {"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
575 {"target", required_argument, NULL, OPTION_TARGET},
576
26044998 577 /* dlltool options. */
252b5132
RH
578 {"no-delete", no_argument, NULL, 'n'},
579 {"dllname", required_argument, NULL, OPTION_DLLNAME},
580 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
581 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
582 {"output-exp", required_argument, NULL, OPTION_OUTPUT_EXP},
583 {"output-def", required_argument, NULL, OPTION_OUTPUT_DEF},
584 {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS},
585 {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS},
586 {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS},
587 {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
588 {"output-lib", required_argument, NULL, OPTION_OUTPUT_LIB},
589 {"def", required_argument, NULL, OPTION_DEF},
590 {"add-underscore", no_argument, NULL, 'U'},
591 {"killat", no_argument, NULL, 'k'},
592 {"add-stdcall-alias", no_argument, NULL, 'A'},
593 {"help", no_argument, NULL, 'h'},
594 {"machine", required_argument, NULL, OPTION_MACHINE},
595 {"add-indirect", no_argument, NULL, OPTION_ADD_INDIRECT},
596 {"base-file", required_argument, NULL, OPTION_BASE_FILE},
597 {"as", required_argument, NULL, OPTION_AS},
37cc8ec1 598 {0, 0, 0, 0}
252b5132
RH
599};
600
2da42df6 601int main (int, char **);
e80ff7de 602
252b5132 603int
2da42df6 604main (int argc, char **argv)
252b5132
RH
605{
606 int c;
607 int i;
608
609 char **saved_argv = 0;
610 int cmdline_len = 0;
611
612 int export_all = 0;
613
614 int *dlltool_arg_indices;
615 int *driver_arg_indices;
616
617 char *driver_flags = 0;
618 char *output_lib_file_name = 0;
619
620 dyn_string_t dlltool_cmdline;
621 dyn_string_t driver_cmdline;
622
623 int def_file_seen = 0;
624
625 char *image_base_str = 0;
626
627 program_name = argv[0];
628
3882b010
L
629#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
630 setlocale (LC_MESSAGES, "");
631#endif
632#if defined (HAVE_SETLOCALE)
633 setlocale (LC_CTYPE, "");
634#endif
635 bindtextdomain (PACKAGE, LOCALEDIR);
636 textdomain (PACKAGE);
637
252b5132
RH
638 saved_argv = (char **) xmalloc (argc * sizeof (char*));
639 dlltool_arg_indices = (int *) xmalloc (argc * sizeof (int));
640 driver_arg_indices = (int *) xmalloc (argc * sizeof (int));
26044998 641 for (i = 0; i < argc; ++i)
252b5132
RH
642 {
643 size_t len = strlen (argv[i]);
644 char *arg = (char *) xmalloc (len + 1);
645 strcpy (arg, argv[i]);
646 cmdline_len += len;
647 saved_argv[i] = arg;
648 dlltool_arg_indices[i] = 0;
649 driver_arg_indices[i] = 1;
650 }
651 cmdline_len++;
652
653 /* We recognize dllwrap and dlltool options, and everything else is
654 passed onto the language driver (eg., to GCC). We collect options
26044998
KH
655 to dlltool and driver in dlltool_args and driver_args. */
656
252b5132 657 opterr = 0;
26044998
KH
658 while ((c = getopt_long_only (argc, argv, "nkAqve:Uho:l:L:I:",
659 long_options, (int *) 0)) != EOF)
252b5132
RH
660 {
661 int dlltool_arg;
662 int driver_arg;
663 int single_word_option_value_pair;
664
665 dlltool_arg = 0;
666 driver_arg = 1;
667 single_word_option_value_pair = 0;
668
669 if (c != '?')
26044998 670 {
252b5132
RH
671 /* We recognize this option, so it has to be either dllwrap or
672 dlltool option. Do not pass to driver unless it's one of the
673 generic options that are passed to all the tools (such as -v)
26044998 674 which are dealt with later. */
252b5132
RH
675 driver_arg = 0;
676 }
677
26044998 678 /* deal with generic and dllwrap options first. */
252b5132
RH
679 switch (c)
680 {
681 case 'h':
682 usage (stdout, 0);
683 break;
684 case 'q':
685 verbose = 0;
686 break;
687 case 'v':
688 verbose = 1;
689 break;
690 case OPTION_VERSION:
691 print_version (program_name);
692 break;
693 case 'e':
694 entry_point = optarg;
695 break;
696 case OPTION_IMAGE_BASE:
697 image_base_str = optarg;
698 break;
699 case OPTION_DEF:
700 def_file_name = optarg;
701 def_file_seen = 1;
702 delete_def_file = 0;
703 break;
704 case 'n':
705 dontdeltemps = 1;
706 dlltool_arg = 1;
707 break;
708 case 'o':
709 dll_file_name = optarg;
710 break;
711 case 'I':
712 case 'l':
713 case 'L':
714 driver_arg = 1;
715 break;
716 case OPTION_DLLNAME:
717 dll_name = optarg;
718 break;
719 case OPTION_DRY_RUN:
720 dry_run = 1;
721 break;
722 case OPTION_DRIVER_NAME:
723 driver_name = optarg;
724 break;
725 case OPTION_DRIVER_FLAGS:
726 driver_flags = optarg;
727 break;
728 case OPTION_DLLTOOL_NAME:
729 dlltool_name = optarg;
730 break;
731 case OPTION_TARGET:
732 target = optarg;
733 break;
bb0cb4db
ILT
734 case OPTION_MNO_CYGWIN:
735 target = "i386-mingw32";
736 break;
252b5132
RH
737 case OPTION_BASE_FILE:
738 base_file_name = optarg;
739 delete_base_file = 0;
740 break;
741 case OPTION_OUTPUT_EXP:
742 exp_file_name = optarg;
743 delete_exp_file = 0;
744 break;
745 case OPTION_EXPORT_ALL_SYMS:
746 export_all = 1;
747 break;
748 case OPTION_OUTPUT_LIB:
749 output_lib_file_name = optarg;
750 break;
751 case '?':
752 break;
753 default:
754 dlltool_arg = 1;
755 break;
756 }
26044998
KH
757
758 /* Handle passing through --option=value case. */
759 if (optarg
760 && saved_argv[optind-1][0] == '-'
761 && saved_argv[optind-1][1] == '-'
252b5132
RH
762 && strchr (saved_argv[optind-1], '='))
763 single_word_option_value_pair = 1;
764
765 if (dlltool_arg)
26044998 766 {
252b5132
RH
767 dlltool_arg_indices[optind-1] = 1;
768 if (optarg && ! single_word_option_value_pair)
769 {
770 dlltool_arg_indices[optind-2] = 1;
26044998 771 }
252b5132
RH
772 }
773
774 if (! driver_arg)
26044998 775 {
252b5132
RH
776 driver_arg_indices[optind-1] = 0;
777 if (optarg && ! single_word_option_value_pair)
778 {
779 driver_arg_indices[optind-2] = 0;
26044998 780 }
252b5132
RH
781 }
782 }
bb0cb4db 783
26044998 784 /* sanity checks. */
252b5132
RH
785 if (! dll_name && ! dll_file_name)
786 {
37cc8ec1 787 warn (_("Must provide at least one of -o or --dllname options"));
252b5132
RH
788 exit (1);
789 }
790 else if (! dll_name)
791 {
792 dll_name = xstrdup (mybasename (dll_file_name));
793 }
794 else if (! dll_file_name)
795 {
796 dll_file_name = xstrdup (dll_name);
797 }
bb0cb4db 798
26044998 799 /* Deduce driver-name and dlltool-name from our own. */
bb0cb4db
ILT
800 if (driver_name == NULL)
801 driver_name = deduce_name ("gcc");
802
803 if (dlltool_name == NULL)
804 dlltool_name = deduce_name ("dlltool");
805
252b5132
RH
806 if (! def_file_seen)
807 {
808 char *fileprefix = choose_temp_base ();
809 def_file_name = (char *) xmalloc (strlen (fileprefix) + 5);
26044998
KH
810 sprintf (def_file_name, "%s.def",
811 (dontdeltemps) ? mybasename (fileprefix) : fileprefix);
252b5132
RH
812 delete_def_file = 1;
813 free (fileprefix);
814 delete_def_file = 1;
e3c8793a
NC
815 warn (_("no export definition file provided.\n\
816Creating one, but that may not be what you want"));
252b5132 817 }
26044998
KH
818
819 /* set the target platform. */
087f88b2 820 if (strstr (target, "cygwin"))
252b5132 821 which_target = CYGWIN_TARGET;
087f88b2
NC
822 else if (strstr (target, "mingw"))
823 which_target = MINGW_TARGET;
26044998 824 else
252b5132
RH
825 which_target = UNKNOWN_TARGET;
826
26044998 827 /* re-create the command lines as a string, taking care to quote stuff. */
252b5132
RH
828 dlltool_cmdline = dyn_string_new (cmdline_len);
829 if (verbose)
830 {
7f143ac1 831 dyn_string_append_cstr (dlltool_cmdline, " -v");
252b5132 832 }
7f143ac1
DD
833 dyn_string_append_cstr (dlltool_cmdline, " --dllname ");
834 dyn_string_append_cstr (dlltool_cmdline, dll_name);
252b5132
RH
835
836 for (i = 1; i < argc; ++i)
837 {
838 if (dlltool_arg_indices[i])
26044998 839 {
252b5132 840 char *arg = saved_argv[i];
26044998
KH
841 int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
842 dyn_string_append_cstr (dlltool_cmdline,
252b5132 843 (quote) ? " \"" : " ");
7f143ac1 844 dyn_string_append_cstr (dlltool_cmdline, arg);
26044998 845 dyn_string_append_cstr (dlltool_cmdline,
252b5132
RH
846 (quote) ? "\"" : "");
847 }
848 }
849
850 driver_cmdline = dyn_string_new (cmdline_len);
851 if (! driver_flags || strlen (driver_flags) == 0)
852 {
853 switch (which_target)
26044998 854 {
252b5132 855 case CYGWIN_TARGET:
26044998 856 driver_flags = cygwin_driver_flags;
252b5132 857 break;
26044998 858
087f88b2 859 case MINGW_TARGET:
26044998 860 driver_flags = mingw32_driver_flags;
252b5132 861 break;
26044998 862
252b5132 863 default:
26044998 864 driver_flags = generic_driver_flags;
252b5132
RH
865 break;
866 }
867 }
7f143ac1
DD
868 dyn_string_append_cstr (driver_cmdline, driver_flags);
869 dyn_string_append_cstr (driver_cmdline, " -o ");
870 dyn_string_append_cstr (driver_cmdline, dll_file_name);
252b5132
RH
871
872 if (! entry_point || strlen (entry_point) == 0)
873 {
874 switch (which_target)
26044998 875 {
252b5132
RH
876 case CYGWIN_TARGET:
877 entry_point = "__cygwin_dll_entry@12";
878 break;
26044998 879
087f88b2 880 case MINGW_TARGET:
252b5132
RH
881 entry_point = "_DllMainCRTStartup@12";
882 break;
26044998 883
252b5132 884 default:
26044998 885 entry_point = "_DllMain@12";
252b5132
RH
886 break;
887 }
888 }
7f143ac1
DD
889 dyn_string_append_cstr (driver_cmdline, " -Wl,-e,");
890 dyn_string_append_cstr (driver_cmdline, entry_point);
891 dyn_string_append_cstr (dlltool_cmdline, " --exclude-symbol=");
26044998
KH
892 dyn_string_append_cstr (dlltool_cmdline,
893 (entry_point[0] == '_') ? entry_point+1 : entry_point);
252b5132
RH
894
895 if (! image_base_str || strlen (image_base_str) == 0)
896 {
897 char *tmpbuf = (char *) xmalloc (sizeof ("0x12345678") + 1);
898 unsigned long hash = strhash (dll_file_name);
899 sprintf (tmpbuf, "0x%.8lX", 0x60000000|((hash<<16)&0xFFC0000));
900 image_base_str = tmpbuf;
901 }
902
7f143ac1
DD
903 dyn_string_append_cstr (driver_cmdline, " -Wl,--image-base,");
904 dyn_string_append_cstr (driver_cmdline, image_base_str);
252b5132
RH
905
906 if (verbose)
907 {
7f143ac1 908 dyn_string_append_cstr (driver_cmdline, " -v");
252b5132
RH
909 }
910
911 for (i = 1; i < argc; ++i)
912 {
913 if (driver_arg_indices[i])
26044998 914 {
252b5132 915 char *arg = saved_argv[i];
26044998
KH
916 int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
917 dyn_string_append_cstr (driver_cmdline,
252b5132 918 (quote) ? " \"" : " ");
7f143ac1 919 dyn_string_append_cstr (driver_cmdline, arg);
26044998 920 dyn_string_append_cstr (driver_cmdline,
252b5132
RH
921 (quote) ? "\"" : "");
922 }
923 }
26044998 924
252b5132
RH
925 /*
926 * Step pre-1. If no --def <EXPORT_DEF> is specified, then create it
927 * and then pass it on.
928 */
26044998
KH
929
930 if (! def_file_seen)
252b5132
RH
931 {
932 int i;
933 dyn_string_t step_pre1;
934
935 step_pre1 = dyn_string_new (1024);
936
7f143ac1 937 dyn_string_append_cstr (step_pre1, dlltool_cmdline->s);
252b5132
RH
938 if (export_all)
939 {
26044998
KH
940 dyn_string_append_cstr (step_pre1, " --export-all --exclude-symbol=");
941 dyn_string_append_cstr (step_pre1,
252b5132
RH
942 "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12");
943 }
7f143ac1
DD
944 dyn_string_append_cstr (step_pre1, " --output-def ");
945 dyn_string_append_cstr (step_pre1, def_file_name);
252b5132
RH
946
947 for (i = 1; i < argc; ++i)
948 {
949 if (driver_arg_indices[i])
950 {
951 char *arg = saved_argv[i];
952 size_t len = strlen (arg);
26044998 953 if (len >= 2 && arg[len-2] == '.'
252b5132
RH
954 && (arg[len-1] == 'o' || arg[len-1] == 'a'))
955 {
956 int quote = (strchr (arg, ' ') || strchr (arg, '\t'));
7f143ac1 957 dyn_string_append_cstr (step_pre1,
252b5132 958 (quote) ? " \"" : " ");
7f143ac1
DD
959 dyn_string_append_cstr (step_pre1, arg);
960 dyn_string_append_cstr (step_pre1,
252b5132
RH
961 (quote) ? "\"" : "");
962 }
963 }
964 }
965
966 if (run (dlltool_name, step_pre1->s))
967 cleanup_and_exit (1);
26044998 968
252b5132
RH
969 dyn_string_delete (step_pre1);
970 }
971
7f143ac1
DD
972 dyn_string_append_cstr (dlltool_cmdline, " --def ");
973 dyn_string_append_cstr (dlltool_cmdline, def_file_name);
252b5132
RH
974
975 if (verbose)
976 {
37cc8ec1
AM
977 fprintf (stderr, _("DLLTOOL name : %s\n"), dlltool_name);
978 fprintf (stderr, _("DLLTOOL options : %s\n"), dlltool_cmdline->s);
979 fprintf (stderr, _("DRIVER name : %s\n"), driver_name);
980 fprintf (stderr, _("DRIVER options : %s\n"), driver_cmdline->s);
252b5132 981 }
26044998 982
252b5132
RH
983 /*
984 * Step 1. Call GCC/LD to create base relocation file. If using GCC, the
985 * driver command line will look like the following:
26044998 986 *
252b5132
RH
987 * % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
988 *
989 * If the user does not specify a base name, create temporary one that
990 * is deleted at exit.
991 *
992 */
26044998 993
252b5132
RH
994 if (! base_file_name)
995 {
996 char *fileprefix = choose_temp_base ();
997 base_file_name = (char *) xmalloc (strlen (fileprefix) + 6);
26044998
KH
998 sprintf (base_file_name, "%s.base",
999 (dontdeltemps) ? mybasename (fileprefix) : fileprefix);
252b5132
RH
1000 delete_base_file = 1;
1001 free (fileprefix);
1002 }
26044998 1003
252b5132
RH
1004 {
1005 int quote;
1006
26044998
KH
1007 dyn_string_t step1 = dyn_string_new (driver_cmdline->length
1008 + strlen (base_file_name)
1009 + 20);
7f143ac1 1010 dyn_string_append_cstr (step1, "-Wl,--base-file,");
26044998
KH
1011 quote = (strchr (base_file_name, ' ')
1012 || strchr (base_file_name, '\t'));
1013 dyn_string_append_cstr (step1,
252b5132 1014 (quote) ? "\"" : "");
7f143ac1 1015 dyn_string_append_cstr (step1, base_file_name);
26044998 1016 dyn_string_append_cstr (step1,
252b5132
RH
1017 (quote) ? "\"" : "");
1018 if (driver_cmdline->length)
1019 {
26044998
KH
1020 dyn_string_append_cstr (step1, " ");
1021 dyn_string_append_cstr (step1, driver_cmdline->s);
252b5132
RH
1022 }
1023
1024 if (run (driver_name, step1->s))
1025 cleanup_and_exit (1);
26044998 1026
252b5132
RH
1027 dyn_string_delete (step1);
1028 }
1029
1030
1031
1032 /*
26044998 1033 * Step 2. generate the exp file by running dlltool.
252b5132 1034 * dlltool command line will look like the following:
26044998 1035 *
252b5132
RH
1036 * % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line]
1037 *
1038 * If the user does not specify a base name, create temporary one that
1039 * is deleted at exit.
1040 *
1041 */
26044998 1042
252b5132
RH
1043 if (! exp_file_name)
1044 {
1045 char *p = strrchr (dll_name, '.');
1046 size_t prefix_len = (p) ? p - dll_name : strlen (dll_name);
1047 exp_file_name = (char *) xmalloc (prefix_len + 4 + 1);
1048 strncpy (exp_file_name, dll_name, prefix_len);
1049 exp_file_name[prefix_len] = '\0';
1050 strcat (exp_file_name, ".exp");
1051 delete_exp_file = 1;
1052 }
26044998 1053
252b5132
RH
1054 {
1055 int quote;
26044998
KH
1056 dyn_string_t step2 = dyn_string_new (dlltool_cmdline->length
1057 + strlen (base_file_name)
1058 + strlen (exp_file_name)
252b5132
RH
1059 + 20);
1060
7f143ac1 1061 dyn_string_append_cstr (step2, "--base-file ");
26044998
KH
1062 quote = (strchr (base_file_name, ' ')
1063 || strchr (base_file_name, '\t'));
1064 dyn_string_append_cstr (step2,
252b5132 1065 (quote) ? "\"" : "");
7f143ac1 1066 dyn_string_append_cstr (step2, base_file_name);
26044998 1067 dyn_string_append_cstr (step2,
252b5132
RH
1068 (quote) ? "\" " : " ");
1069
7f143ac1 1070 dyn_string_append_cstr (step2, "--output-exp ");
26044998
KH
1071 quote = (strchr (exp_file_name, ' ')
1072 || strchr (exp_file_name, '\t'));
1073 dyn_string_append_cstr (step2,
252b5132 1074 (quote) ? "\"" : "");
7f143ac1 1075 dyn_string_append_cstr (step2, exp_file_name);
26044998 1076 dyn_string_append_cstr (step2,
252b5132
RH
1077 (quote) ? "\"" : "");
1078
1079 if (dlltool_cmdline->length)
1080 {
26044998
KH
1081 dyn_string_append_cstr (step2, " ");
1082 dyn_string_append_cstr (step2, dlltool_cmdline->s);
252b5132
RH
1083 }
1084
1085 if (run (dlltool_name, step2->s))
1086 cleanup_and_exit (1);
26044998 1087
252b5132
RH
1088 dyn_string_delete (step2);
1089 }
1090
1091 /*
1092 * Step 3. Call GCC/LD to again, adding the exp file this time.
1093 * driver command line will look like the following:
26044998 1094 *
252b5132
RH
1095 * % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...]
1096 */
1097
1098 {
1099 int quote;
1100
26044998
KH
1101 dyn_string_t step3 = dyn_string_new (driver_cmdline->length
1102 + strlen (exp_file_name)
1103 + strlen (base_file_name)
252b5132 1104 + 20);
7f143ac1 1105 dyn_string_append_cstr (step3, "-Wl,--base-file,");
26044998
KH
1106 quote = (strchr (base_file_name, ' ')
1107 || strchr (base_file_name, '\t'));
1108 dyn_string_append_cstr (step3,
252b5132 1109 (quote) ? "\"" : "");
7f143ac1 1110 dyn_string_append_cstr (step3, base_file_name);
26044998 1111 dyn_string_append_cstr (step3,
252b5132
RH
1112 (quote) ? "\" " : " ");
1113
26044998
KH
1114 quote = (strchr (exp_file_name, ' ')
1115 || strchr (exp_file_name, '\t'));
1116 dyn_string_append_cstr (step3,
252b5132 1117 (quote) ? "\"" : "");
7f143ac1 1118 dyn_string_append_cstr (step3, exp_file_name);
26044998 1119 dyn_string_append_cstr (step3,
252b5132
RH
1120 (quote) ? "\"" : "");
1121
1122 if (driver_cmdline->length)
1123 {
26044998
KH
1124 dyn_string_append_cstr (step3, " ");
1125 dyn_string_append_cstr (step3, driver_cmdline->s);
252b5132
RH
1126 }
1127
1128 if (run (driver_name, step3->s))
1129 cleanup_and_exit (1);
26044998 1130
252b5132
RH
1131 dyn_string_delete (step3);
1132 }
1133
1134
1135 /*
1136 * Step 4. Run DLLTOOL again using the same command line.
1137 */
1138
1139 {
1140 int quote;
26044998
KH
1141 dyn_string_t step4 = dyn_string_new (dlltool_cmdline->length
1142 + strlen (base_file_name)
1143 + strlen (exp_file_name)
252b5132
RH
1144 + 20);
1145
7f143ac1 1146 dyn_string_append_cstr (step4, "--base-file ");
26044998
KH
1147 quote = (strchr (base_file_name, ' ')
1148 || strchr (base_file_name, '\t'));
1149 dyn_string_append_cstr (step4,
252b5132 1150 (quote) ? "\"" : "");
7f143ac1 1151 dyn_string_append_cstr (step4, base_file_name);
26044998 1152 dyn_string_append_cstr (step4,
252b5132
RH
1153 (quote) ? "\" " : " ");
1154
7f143ac1 1155 dyn_string_append_cstr (step4, "--output-exp ");
26044998
KH
1156 quote = (strchr (exp_file_name, ' ')
1157 || strchr (exp_file_name, '\t'));
1158 dyn_string_append_cstr (step4,
252b5132 1159 (quote) ? "\"" : "");
7f143ac1 1160 dyn_string_append_cstr (step4, exp_file_name);
26044998 1161 dyn_string_append_cstr (step4,
252b5132
RH
1162 (quote) ? "\"" : "");
1163
1164 if (dlltool_cmdline->length)
1165 {
26044998
KH
1166 dyn_string_append_cstr (step4, " ");
1167 dyn_string_append_cstr (step4, dlltool_cmdline->s);
252b5132
RH
1168 }
1169
1170 if (output_lib_file_name)
1171 {
26044998
KH
1172 dyn_string_append_cstr (step4, " --output-lib ");
1173 dyn_string_append_cstr (step4, output_lib_file_name);
252b5132
RH
1174 }
1175
1176 if (run (dlltool_name, step4->s))
1177 cleanup_and_exit (1);
26044998 1178
252b5132
RH
1179 dyn_string_delete (step4);
1180 }
26044998 1181
252b5132
RH
1182
1183 /*
1184 * Step 5. Link it all together and be done with it.
1185 * driver command line will look like the following:
26044998 1186 *
252b5132
RH
1187 * % gcc -Wl,--dll foo.exp [rest ...]
1188 *
1189 */
1190
1191 {
1192 int quote;
1193
26044998
KH
1194 dyn_string_t step5 = dyn_string_new (driver_cmdline->length
1195 + strlen (exp_file_name)
252b5132 1196 + 20);
26044998
KH
1197 quote = (strchr (exp_file_name, ' ')
1198 || strchr (exp_file_name, '\t'));
1199 dyn_string_append_cstr (step5,
252b5132 1200 (quote) ? "\"" : "");
7f143ac1 1201 dyn_string_append_cstr (step5, exp_file_name);
26044998 1202 dyn_string_append_cstr (step5,
252b5132
RH
1203 (quote) ? "\"" : "");
1204
1205 if (driver_cmdline->length)
1206 {
26044998
KH
1207 dyn_string_append_cstr (step5, " ");
1208 dyn_string_append_cstr (step5, driver_cmdline->s);
252b5132
RH
1209 }
1210
1211 if (run (driver_name, step5->s))
1212 cleanup_and_exit (1);
26044998 1213
252b5132
RH
1214 dyn_string_delete (step5);
1215 }
1216
1217 cleanup_and_exit (0);
1218
1219 return 0;
1220}
This page took 0.226794 seconds and 4 git commands to generate.