1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
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
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
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
70: #endif
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: typedef enum {
85: UNKNOWN_TARGET,
86: CYGWIN_TARGET,
87: MINGW_TARGET
88: }
89: target_type;
90:
91: static target_type which_target = UNKNOWN_TARGET;
92:
93: static int dontdeltemps = 0;
94: static int dry_run = 0;
95:
96: static char *prog_name;
97:
98: static int verbose = 0;
99:
100: static char *dll_file_name;
101: static char *dll_name;
102: static char *base_file_name;
103: static char *exp_file_name;
104: static char *def_file_name;
105: static int delete_base_file = 1;
106: static int delete_exp_file = 1;
107: static int delete_def_file = 1;
108:
109: static int run (const char *, char *);
110: static char *mybasename (const char *);
111: static int strhash (const char *);
112: static void usage (FILE *, int);
113: static void display (const char *, va_list) ATTRIBUTE_PRINTF(1,0);
114: static void inform (const char *, ...) ATTRIBUTE_PRINTF_1;
115: static void warn (const char *, ...) ATTRIBUTE_PRINTF_1;
116: static char *look_for_prog (const char *, const char *, int);
117: static char *deduce_name (const char *);
118: static void delete_temp_files (void);
119: static void cleanup_and_exit (int);
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131: static void
132: display (const char * message, va_list args)
133: {
134: if (prog_name != NULL)
135: fprintf (stderr, "%s: ", prog_name);
136:
137: vfprintf (stderr, message, args);
138: fputc ('\n', stderr);
139: }
140:
141:
142: static void
143: inform VPARAMS ((const char *message, ...))
144: {
145: VA_OPEN (args, message);
146: VA_FIXEDARG (args, const char *, message);
147:
148: if (!verbose)
149: return;
150:
151: display (message, args);
152:
153: VA_CLOSE (args);
154: }
155:
156: static void
157: warn VPARAMS ((const char *format, ...))
158: {
159: VA_OPEN (args, format);
160: VA_FIXEDARG (args, const char *, format);
161:
162: display (format, args);
163:
164: VA_CLOSE (args);
165: }
166:
167:
168:
169:
170:
171:
172: static char *
173: look_for_prog (const char *prog_name, const char *prefix, int end_prefix)
174: {
175: struct stat s;
176: char *cmd;
177:
178: cmd = xmalloc (strlen (prefix)
179: + strlen (prog_name)
180: #ifdef HAVE_EXECUTABLE_SUFFIX
181: + strlen (EXECUTABLE_SUFFIX)
182: #endif
183: + 10);
184: strcpy (cmd, prefix);
185:
186: sprintf (cmd + end_prefix, "%s", prog_name);
187:
188: if (strchr (cmd, '/') != NULL)
189: {
190: int found;
191:
192: found = (stat (cmd, &s) == 0
193: #ifdef HAVE_EXECUTABLE_SUFFIX
194: || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
195: #endif
196: );
197:
198: if (! found)
199: {
200:
201: inform (_("Tried file: %s"), cmd);
202: free (cmd);
203: return NULL;
204: }
205: }
206:
207:
208: inform (_("Using file: %s"), cmd);
209:
210: return cmd;
211: }
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238: static char *
239: deduce_name (const char * name)
240: {
241: char *cmd;
242: const char *dash;
243: const char *slash;
244: const char *cp;
245:
246: dash = NULL;
247: slash = NULL;
248: for (cp = prog_name; *cp != '\0'; ++cp)
249: {
250: if (*cp == '-')
251: dash = cp;
252:
253: if (
254: #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
255: *cp == ':' || *cp == '\\' ||
256: #endif
257: *cp == '/')
258: {
259: slash = cp;
260: dash = NULL;
261: }
262: }
263:
264: cmd = NULL;
265:
266: if (dash != NULL)
267:
268:
269: cmd = look_for_prog (name, prog_name, dash - prog_name + 1);
270:
271: if (slash != NULL && cmd == NULL)
272:
273:
274: cmd = look_for_prog (name, prog_name, slash - prog_name + 1);
275:
276: if (cmd == NULL)
277:
278: cmd = xstrdup (name);
279:
280: return cmd;
281: }
282:
283: static void
284: delete_temp_files (void)
285: {
286: if (delete_base_file && base_file_name)
287: {
288: if (verbose)
289: {
290: if (dontdeltemps)
291: warn (_("Keeping temporary base file %s"), base_file_name);
292: else
293: warn (_("Deleting temporary base file %s"), base_file_name);
294: }
295: if (! dontdeltemps)
296: {
297: unlink (base_file_name);
298: free (base_file_name);
299: }
300: }
301:
302: if (delete_exp_file && exp_file_name)
303: {
304: if (verbose)
305: {
306: if (dontdeltemps)
307: warn (_("Keeping temporary exp file %s"), exp_file_name);
308: else
309: warn (_("Deleting temporary exp file %s"), exp_file_name);
310: }
311: if (! dontdeltemps)
312: {
313: unlink (exp_file_name);
314: free (exp_file_name);
315: }
316: }
317: if (delete_def_file && def_file_name)
318: {
319: if (verbose)
320: {
321: if (dontdeltemps)
322: warn (_("Keeping temporary def file %s"), def_file_name);
323: else
324: warn (_("Deleting temporary def file %s"), def_file_name);
325: }
326: if (! dontdeltemps)
327: {
328: unlink (def_file_name);
329: free (def_file_name);
330: }
331: }
332: }
333:
334: static void
335: cleanup_and_exit (int status)
336: {
337: delete_temp_files ();
338: exit (status);
339: }
340:
341: static int
342: run (const char *what, char *args)
343: {
344: char *s;
345: int pid, wait_status, retcode;
346: int i;
347: const char **argv;
348: char *errmsg_fmt, *errmsg_arg;
349: char *temp_base = choose_temp_base ();
350: int in_quote;
351: char sep;
352:
353: if (verbose || dry_run)
354: fprintf (stderr, "%s %s\n", what, args);
355:
356:
357: i = 0;
358: for (s = args; *s; s++)
359: if (*s == ' ')
360: i++;
361: i++;
362: argv = alloca (sizeof (char *) * (i + 3));
363: i = 0;
364: argv[i++] = what;
365: s = args;
366: while (1)
367: {
368: while (*s == ' ' && *s != 0)
369: s++;
370: if (*s == 0)
371: break;
372: in_quote = (*s == '\'' || *s == '"');
373: sep = (in_quote) ? *s++ : ' ';
374: argv[i++] = s;
375: while (*s != sep && *s != 0)
376: s++;
377: if (*s == 0)
378: break;
379: *s++ = 0;
380: if (in_quote)
381: s++;
382: }
383: argv[i++] = NULL;
384:
385: if (dry_run)
386: return 0;
387:
388: pid = pexecute (argv[0], (char * const *) argv, prog_name, temp_base,
389: &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
390:
391: if (pid == -1)
392: {
393: int errno_val = errno;
394:
395: fprintf (stderr, "%s: ", prog_name);
396: fprintf (stderr, errmsg_fmt, errmsg_arg);
397: fprintf (stderr, ": %s\n", strerror (errno_val));
398: return 1;
399: }
400:
401: retcode = 0;
402: pid = pwait (pid, &wait_status, 0);
403: if (pid == -1)
404: {
405: warn ("wait: %s", strerror (errno));
406: retcode = 1;
407: }
408: else if (WIFSIGNALED (wait_status))
409: {
410: warn (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
411: retcode = 1;
412: }
413: else if (WIFEXITED (wait_status))
414: {
415: if (WEXITSTATUS (wait_status) != 0)
416: {
417: warn (_("%s exited with status %d"), what, WEXITSTATUS (wait_status));
418: retcode = 1;
419: }
420: }
421: else
422: retcode = 1;
423:
424: return retcode;
425: }
426:
427: static char *
428: mybasename (const char *name)
429: {
430: const char *base = name;
431:
432: while (*name)
433: {
434: if (*name == '/' || *name == '\\')
435: {
436: base = name + 1;
437: }
438: ++name;
439: }
440: return (char *) base;
441: }
442:
443: static int
444: strhash (const char *str)
445: {
446: const unsigned char *s;
447: unsigned long hash;
448: unsigned int c;
449: unsigned int len;
450:
451: hash = 0;
452: len = 0;
453: s = (const unsigned char *) str;
454: while ((c = *s++) != '\0')
455: {
456: hash += c + (c << 17);
457: hash ^= hash >> 2;
458: ++len;
459: }
460: hash += len + (len << 17);
461: hash ^= hash >> 2;
462:
463: return hash;
464: }
465:
466:
467:
468: static void
469: usage (FILE *file, int status)
470: {
471: fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), prog_name);
472: fprintf (file, _(" Generic options:\n"));
473: fprintf (file, _(" @<file> Read options from <file>\n"));
474: fprintf (file, _(" --quiet, -q Work quietly\n"));
475: fprintf (file, _(" --verbose, -v Verbose\n"));
476: fprintf (file, _(" --version Print dllwrap version\n"));
477: fprintf (file, _(" --implib <outname> Synonym for --output-lib\n"));
478: fprintf (file, _(" Options for %s:\n"), prog_name);
479: fprintf (file, _(" --driver-name <driver> Defaults to \"gcc\"\n"));
480: fprintf (file, _(" --driver-flags <flags> Override default ld flags\n"));
481: fprintf (file, _(" --dlltool-name <dlltool> Defaults to \"dlltool\"\n"));
482: fprintf (file, _(" --entry <entry> Specify alternate DLL entry point\n"));
483: fprintf (file, _(" --image-base <base> Specify image base address\n"));
484: fprintf (file, _(" --target <machine> i386-cygwin32 or i386-mingw32\n"));
485: fprintf (file, _(" --dry-run Show what needs to be run\n"));
486: fprintf (file, _(" --mno-cygwin Create Mingw DLL\n"));
487: fprintf (file, _(" Options passed to DLLTOOL:\n"));
488: fprintf (file, _(" --machine <machine>\n"));
489: fprintf (file, _(" --output-exp <outname> Generate export file.\n"));
490: fprintf (file, _(" --output-lib <outname> Generate input library.\n"));
491: fprintf (file, _(" --add-indirect Add dll indirects to export file.\n"));
492: fprintf (file, _(" --dllname <name> Name of input dll to put into output lib.\n"));
493: fprintf (file, _(" --def <deffile> Name input .def file\n"));
494: fprintf (file, _(" --output-def <deffile> Name output .def file\n"));
495: fprintf (file, _(" --export-all-symbols Export all symbols to .def\n"));
496: fprintf (file, _(" --no-export-all-symbols Only export .drectve symbols\n"));
497: fprintf (file, _(" --exclude-symbols <list> Exclude <list> from .def\n"));
498: fprintf (file, _(" --no-default-excludes Zap default exclude symbols\n"));
499: fprintf (file, _(" --base-file <basefile> Read linker generated base file\n"));
500: fprintf (file, _(" --no-idata4 Don't generate idata$4 section\n"));
501: fprintf (file, _(" --no-idata5 Don't generate idata$5 section\n"));
502: fprintf (file, _(" -U Add underscores to .lib\n"));
503: fprintf (file, _(" -k Kill @<n> from exported names\n"));
504: fprintf (file, _(" --add-stdcall-alias Add aliases without @<n>\n"));
505: fprintf (file, _(" --as <name> Use <name> for assembler\n"));
506: fprintf (file, _(" --nodelete Keep temp files.\n"));
507: fprintf (file, _(" Rest are passed unmodified to the language driver\n"));
508: fprintf (file, "\n\n");
509: if (REPORT_BUGS_TO[0] && status == 0)
510: fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
511: exit (status);
512: }
513:
514: #define OPTION_START 149
515:
516:
517: #define OPTION_QUIET (OPTION_START + 1)
518: #define OPTION_VERBOSE (OPTION_QUIET + 1)
519: #define OPTION_VERSION (OPTION_VERBOSE + 1)
520:
521:
522: #define OPTION_DRY_RUN (OPTION_VERSION + 1)
523: #define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1)
524: #define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1)
525: #define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1)
526: #define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1)
527: #define OPTION_IMAGE_BASE (OPTION_ENTRY + 1)
528: #define OPTION_TARGET (OPTION_IMAGE_BASE + 1)
529: #define OPTION_MNO_CYGWIN (OPTION_TARGET + 1)
530:
531:
532: #define OPTION_NODELETE (OPTION_MNO_CYGWIN + 1)
533: #define OPTION_DLLNAME (OPTION_NODELETE + 1)
534: #define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1)
535: #define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1)
536: #define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1)
537: #define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1)
538: #define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1)
539: #define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1)
540: #define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1)
541: #define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1)
542: #define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1)
543: #define OPTION_DEF (OPTION_OUTPUT_LIB + 1)
544: #define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1)
545: #define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1)
546: #define OPTION_HELP (OPTION_KILLAT + 1)
547: #define OPTION_MACHINE (OPTION_HELP + 1)
548: #define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1)