OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [dllwrap.c] - Blame information for rev 139

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.