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 166

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

powered by: WebSVN 2.1.0

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