dllwrap.c revision 77298
160484Sobrien/* dllwrap.c -- wrapper for DLLTOOL and GCC to generate PE style DLLs 260484Sobrien Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. 360484Sobrien Contributed by Mumit Khan (khan@xraylith.wisc.edu). 460484Sobrien 560484Sobrien This file is part of GNU Binutils. 660484Sobrien 760484Sobrien This program is free software; you can redistribute it and/or modify 860484Sobrien it under the terms of the GNU General Public License as published by 960484Sobrien the Free Software Foundation; either version 2 of the License, or 1060484Sobrien (at your option) any later version. 1160484Sobrien 1260484Sobrien This program is distributed in the hope that it will be useful, 1360484Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1460484Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1560484Sobrien GNU General Public License for more details. 1660484Sobrien 1760484Sobrien You should have received a copy of the GNU General Public License 1860484Sobrien along with this program; if not, write to the Free Software 1960484Sobrien Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 2060484Sobrien 02111-1307, USA. */ 2160484Sobrien 2260484Sobrien/* AIX requires this to be the first thing in the file. */ 2360484Sobrien#ifndef __GNUC__ 2460484Sobrien# ifdef _AIX 2560484Sobrien #pragma alloca 2660484Sobrien#endif 2760484Sobrien#endif 2860484Sobrien 2960484Sobrien#ifdef HAVE_CONFIG_H 3060484Sobrien#include "config.h" 3160484Sobrien#endif 3260484Sobrien 3360484Sobrien#include "bfd.h" 3460484Sobrien#include "libiberty.h" 3560484Sobrien#include "bucomm.h" 3660484Sobrien#include "getopt.h" 3760484Sobrien#include "dyn-string.h" 3860484Sobrien 3960484Sobrien#include <ctype.h> 4060484Sobrien#include <time.h> 4160484Sobrien#include <sys/stat.h> 4260484Sobrien 4360484Sobrien#ifdef ANSI_PROTOTYPES 4460484Sobrien#include <stdarg.h> 4560484Sobrien#else 4660484Sobrien#include <varargs.h> 4760484Sobrien#endif 4860484Sobrien 4960484Sobrien#ifdef HAVE_SYS_WAIT_H 5060484Sobrien#include <sys/wait.h> 5160484Sobrien#else /* ! HAVE_SYS_WAIT_H */ 5260484Sobrien#if ! defined (_WIN32) || defined (__CYGWIN32__) 5360484Sobrien#ifndef WIFEXITED 5460484Sobrien#define WIFEXITED(w) (((w)&0377) == 0) 5560484Sobrien#endif 5660484Sobrien#ifndef WIFSIGNALED 5760484Sobrien#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0) 5860484Sobrien#endif 5960484Sobrien#ifndef WTERMSIG 6060484Sobrien#define WTERMSIG(w) ((w) & 0177) 6160484Sobrien#endif 6260484Sobrien#ifndef WEXITSTATUS 6360484Sobrien#define WEXITSTATUS(w) (((w) >> 8) & 0377) 6460484Sobrien#endif 6560484Sobrien#else /* defined (_WIN32) && ! defined (__CYGWIN32__) */ 6660484Sobrien#ifndef WIFEXITED 6760484Sobrien#define WIFEXITED(w) (((w) & 0xff) == 0) 6860484Sobrien#endif 6960484Sobrien#ifndef WIFSIGNALED 7060484Sobrien#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f) 7160484Sobrien#endif 7260484Sobrien#ifndef WTERMSIG 7360484Sobrien#define WTERMSIG(w) ((w) & 0x7f) 7460484Sobrien#endif 7560484Sobrien#ifndef WEXITSTATUS 7660484Sobrien#define WEXITSTATUS(w) (((w) & 0xff00) >> 8) 7760484Sobrien#endif 7860484Sobrien#endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */ 7960484Sobrien#endif /* ! HAVE_SYS_WAIT_H */ 8060484Sobrien 8160484Sobrienstatic char *driver_name = NULL; 8260484Sobrienstatic char *cygwin_driver_flags = 8360484Sobrien "-Wl,--dll -nostartfiles"; 8460484Sobrienstatic char *mingw32_driver_flags = "-mdll"; 8560484Sobrienstatic char *generic_driver_flags = "-Wl,--dll"; 8660484Sobrien 8760484Sobrienstatic char *entry_point; 8860484Sobrien 8960484Sobrienstatic char *dlltool_name = NULL; 9060484Sobrien 9160484Sobrienstatic char *target = TARGET; 9260484Sobrien 9360484Sobrientypedef enum { 9460484Sobrien UNKNOWN_TARGET, 9560484Sobrien CYGWIN_TARGET, 9660484Sobrien MINGW_TARGET 9760484Sobrien} 9860484Sobrientarget_type; 9960484Sobrien 10060484Sobrienstatic target_type which_target = UNKNOWN_TARGET; 10160484Sobrien 10260484Sobrienstatic int dontdeltemps = 0; 10360484Sobrienstatic int dry_run = 0; 10460484Sobrien 10560484Sobrienstatic char *program_name; 10660484Sobrien 10760484Sobrienstatic int verbose = 0; 10860484Sobrien 10960484Sobrienstatic char *dll_file_name; 11060484Sobrienstatic char *dll_name; 11160484Sobrienstatic char *base_file_name; 11260484Sobrienstatic char *exp_file_name; 11360484Sobrienstatic char *def_file_name; 11460484Sobrienstatic int delete_base_file = 1; 11560484Sobrienstatic int delete_exp_file = 1; 11660484Sobrienstatic int delete_def_file = 1; 11760484Sobrien 11860484Sobrienstatic int run PARAMS ((const char *, char *)); 11960484Sobrienstatic void usage PARAMS ((FILE *, int)); 12060484Sobrienstatic void display PARAMS ((const char *, va_list)); 12160484Sobrienstatic void inform PARAMS ((const char *, ...)); 12260484Sobrienstatic void warn PARAMS ((const char *format, ...)); 12360484Sobrienstatic char *look_for_prog PARAMS ((const char *, const char *, int)); 12460484Sobrienstatic char *deduce_name PARAMS ((const char *)); 12560484Sobrienstatic void delete_temp_files PARAMS ((void)); 12660484Sobrienstatic void cleanup_and_exit PARAMS ((int status)); 12760484Sobrien 12860484Sobrien/**********************************************************************/ 12960484Sobrien 13060484Sobrien/* Please keep the following 4 routines in sync with dlltool.c: 13160484Sobrien display () 13260484Sobrien inform () 13360484Sobrien look_for_prog () 13460484Sobrien deduce_name () 13560484Sobrien It's not worth the hassle to break these out since dllwrap will 13660484Sobrien (hopefully) soon be retired in favor of `ld --shared. */ 13760484Sobrien 13860484Sobrienstatic void 13960484Sobriendisplay (message, args) 14060484Sobrien const char * message; 14160484Sobrien va_list args; 14260484Sobrien{ 14360484Sobrien if (program_name != NULL) 14460484Sobrien fprintf (stderr, "%s: ", program_name); 14560484Sobrien 14660484Sobrien vfprintf (stderr, message, args); 14760484Sobrien fputc ('\n', stderr); 14860484Sobrien} 14960484Sobrien 15060484Sobrien 15160484Sobrien#ifdef __STDC__ 15260484Sobrienstatic void 15360484Sobrieninform (const char * message, ...) 15460484Sobrien{ 15560484Sobrien va_list args; 15660484Sobrien 15760484Sobrien if (!verbose) 15860484Sobrien return; 15960484Sobrien 16060484Sobrien va_start (args, message); 16160484Sobrien display (message, args); 16260484Sobrien va_end (args); 16360484Sobrien} 16460484Sobrien 16560484Sobrienstatic void 16660484Sobrienwarn (const char *format, ...) 16760484Sobrien{ 16860484Sobrien va_list args; 16960484Sobrien 17060484Sobrien va_start (args, format); 17160484Sobrien display (format, args); 17260484Sobrien va_end (args); 17360484Sobrien} 17460484Sobrien#else 17560484Sobrien 17660484Sobrienstatic void 17760484Sobrieninform (message, va_alist) 17860484Sobrien const char * message; 17960484Sobrien va_dcl 18060484Sobrien{ 18160484Sobrien va_list args; 18260484Sobrien 18360484Sobrien if (!verbose) 18460484Sobrien return; 18560484Sobrien 18660484Sobrien va_start (args); 18760484Sobrien display (message, args); 18860484Sobrien va_end (args); 18960484Sobrien} 19060484Sobrien 19160484Sobrienstatic void 19260484Sobrienwarn (format, va_alist) 19360484Sobrien const char *format; 19460484Sobrien va_dcl 19560484Sobrien{ 19660484Sobrien va_list args; 19760484Sobrien 19860484Sobrien va_start (args); 19960484Sobrien display (format, args); 20060484Sobrien va_end (args); 20160484Sobrien} 20260484Sobrien#endif 20360484Sobrien 20460484Sobrien/* Look for the program formed by concatenating PROG_NAME and the 20560484Sobrien string running from PREFIX to END_PREFIX. If the concatenated 20660484Sobrien string contains a '/', try appending EXECUTABLE_SUFFIX if it is 20760484Sobrien appropriate. */ 20860484Sobrien 20960484Sobrienstatic char * 21060484Sobrienlook_for_prog (prog_name, prefix, end_prefix) 21160484Sobrien const char *prog_name; 21260484Sobrien const char *prefix; 21360484Sobrien int end_prefix; 21460484Sobrien{ 21560484Sobrien struct stat s; 21660484Sobrien char *cmd; 21760484Sobrien 21860484Sobrien cmd = xmalloc (strlen (prefix) 21960484Sobrien + strlen (prog_name) 22060484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 22160484Sobrien + strlen (EXECUTABLE_SUFFIX) 22260484Sobrien#endif 22360484Sobrien + 10); 22460484Sobrien strcpy (cmd, prefix); 22560484Sobrien 22660484Sobrien sprintf (cmd + end_prefix, "%s", prog_name); 22760484Sobrien 22860484Sobrien if (strchr (cmd, '/') != NULL) 22960484Sobrien { 23060484Sobrien int found; 23160484Sobrien 23260484Sobrien found = (stat (cmd, &s) == 0 23360484Sobrien#ifdef HAVE_EXECUTABLE_SUFFIX 23460484Sobrien || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0 23560484Sobrien#endif 23660484Sobrien ); 23760484Sobrien 23860484Sobrien if (! found) 23960484Sobrien { 24060484Sobrien /* xgettext:c-format */ 24160484Sobrien inform (_("Tried file: %s"), cmd); 24260484Sobrien free (cmd); 24360484Sobrien return NULL; 24460484Sobrien } 24560484Sobrien } 24660484Sobrien 24760484Sobrien /* xgettext:c-format */ 24860484Sobrien inform (_("Using file: %s"), cmd); 24960484Sobrien 25060484Sobrien return cmd; 25160484Sobrien} 25260484Sobrien 25360484Sobrien/* Deduce the name of the program we are want to invoke. 25460484Sobrien PROG_NAME is the basic name of the program we want to run, 25560484Sobrien eg "as" or "ld". The catch is that we might want actually 25660484Sobrien run "i386-pe-as" or "ppc-pe-ld". 25760484Sobrien 25860484Sobrien If argv[0] contains the full path, then try to find the program 25960484Sobrien in the same place, with and then without a target-like prefix. 26060484Sobrien 26160484Sobrien Given, argv[0] = /usr/local/bin/i586-cygwin32-dlltool, 26260484Sobrien deduce_name("as") uses the following search order: 26360484Sobrien 26460484Sobrien /usr/local/bin/i586-cygwin32-as 26560484Sobrien /usr/local/bin/as 26660484Sobrien as 26760484Sobrien 26860484Sobrien If there's an EXECUTABLE_SUFFIX, it'll use that as well; for each 26960484Sobrien name, it'll try without and then with EXECUTABLE_SUFFIX. 27060484Sobrien 27160484Sobrien Given, argv[0] = i586-cygwin32-dlltool, it will not even try "as" 27260484Sobrien as the fallback, but rather return i586-cygwin32-as. 27360484Sobrien 27460484Sobrien Oh, and given, argv[0] = dlltool, it'll return "as". 27560484Sobrien 27660484Sobrien Returns a dynamically allocated string. */ 27760484Sobrien 27860484Sobrienstatic char * 27960484Sobriendeduce_name (prog_name) 28060484Sobrien const char *prog_name; 28160484Sobrien{ 28260484Sobrien char *cmd; 28360484Sobrien char *dash, *slash, *cp; 28460484Sobrien 28560484Sobrien dash = NULL; 28660484Sobrien slash = NULL; 28760484Sobrien for (cp = program_name; *cp != '\0'; ++cp) 28860484Sobrien { 28960484Sobrien if (*cp == '-') 29060484Sobrien dash = cp; 29160484Sobrien if ( 29260484Sobrien#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) 29360484Sobrien *cp == ':' || *cp == '\\' || 29460484Sobrien#endif 29560484Sobrien *cp == '/') 29660484Sobrien { 29760484Sobrien slash = cp; 29860484Sobrien dash = NULL; 29960484Sobrien } 30060484Sobrien } 30160484Sobrien 30260484Sobrien cmd = NULL; 30360484Sobrien 30460484Sobrien if (dash != NULL) 30560484Sobrien { 30660484Sobrien /* First, try looking for a prefixed PROG_NAME in the 30760484Sobrien PROGRAM_NAME directory, with the same prefix as PROGRAM_NAME. */ 30860484Sobrien cmd = look_for_prog (prog_name, program_name, dash - program_name + 1); 30960484Sobrien } 31060484Sobrien 31160484Sobrien if (slash != NULL && cmd == NULL) 31260484Sobrien { 31360484Sobrien /* Next, try looking for a PROG_NAME in the same directory as 31460484Sobrien that of this program. */ 31560484Sobrien cmd = look_for_prog (prog_name, program_name, slash - program_name + 1); 31660484Sobrien } 31760484Sobrien 31860484Sobrien if (cmd == NULL) 31960484Sobrien { 32060484Sobrien /* Just return PROG_NAME as is. */ 32160484Sobrien cmd = xstrdup (prog_name); 32260484Sobrien } 32360484Sobrien 32460484Sobrien return cmd; 32560484Sobrien} 32660484Sobrien 32760484Sobrienstatic void 32860484Sobriendelete_temp_files () 32960484Sobrien{ 33060484Sobrien if (delete_base_file && base_file_name) 33160484Sobrien { 33260484Sobrien if (verbose) 33360484Sobrien { 33460484Sobrien if (dontdeltemps) 33560484Sobrien warn (_("Keeping temporary base file %s"), base_file_name); 33660484Sobrien else 33760484Sobrien warn (_("Deleting temporary base file %s"), base_file_name); 33860484Sobrien } 33960484Sobrien if (! dontdeltemps) 34060484Sobrien { 34160484Sobrien unlink (base_file_name); 34260484Sobrien free (base_file_name); 34360484Sobrien } 34460484Sobrien } 34560484Sobrien 34660484Sobrien if (delete_exp_file && exp_file_name) 34760484Sobrien { 34860484Sobrien if (verbose) 34960484Sobrien { 35060484Sobrien if (dontdeltemps) 35160484Sobrien warn (_("Keeping temporary exp file %s"), exp_file_name); 35260484Sobrien else 35360484Sobrien warn (_("Deleting temporary exp file %s"), exp_file_name); 35460484Sobrien } 35560484Sobrien if (! dontdeltemps) 35660484Sobrien { 35760484Sobrien unlink (exp_file_name); 35860484Sobrien free (exp_file_name); 35960484Sobrien } 36060484Sobrien } 36160484Sobrien if (delete_def_file && def_file_name) 36260484Sobrien { 36360484Sobrien if (verbose) 36460484Sobrien { 36560484Sobrien if (dontdeltemps) 36660484Sobrien warn (_("Keeping temporary def file %s"), def_file_name); 36760484Sobrien else 36860484Sobrien warn (_("Deleting temporary def file %s"), def_file_name); 36960484Sobrien } 37060484Sobrien if (! dontdeltemps) 37160484Sobrien { 37260484Sobrien unlink (def_file_name); 37360484Sobrien free (def_file_name); 37460484Sobrien } 37560484Sobrien } 37660484Sobrien} 37760484Sobrien 37860484Sobrienstatic void 37960484Sobriencleanup_and_exit (int status) 38060484Sobrien{ 38160484Sobrien delete_temp_files (); 38260484Sobrien exit (status); 38360484Sobrien} 38460484Sobrien 38560484Sobrienstatic int 38660484Sobrienrun (what, args) 38760484Sobrien const char *what; 38860484Sobrien char *args; 38960484Sobrien{ 39060484Sobrien char *s; 39160484Sobrien int pid, wait_status, retcode; 39260484Sobrien int i; 39360484Sobrien const char **argv; 39460484Sobrien char *errmsg_fmt, *errmsg_arg; 39560484Sobrien char *temp_base = choose_temp_base (); 39660484Sobrien int in_quote; 39760484Sobrien char sep; 39860484Sobrien 39960484Sobrien if (verbose || dry_run) 40060484Sobrien fprintf (stderr, "%s %s\n", what, args); 40160484Sobrien 40260484Sobrien /* Count the args */ 40360484Sobrien i = 0; 40460484Sobrien for (s = args; *s; s++) 40560484Sobrien if (*s == ' ') 40660484Sobrien i++; 40760484Sobrien i++; 40860484Sobrien argv = alloca (sizeof (char *) * (i + 3)); 40960484Sobrien i = 0; 41060484Sobrien argv[i++] = what; 41160484Sobrien s = args; 41260484Sobrien while (1) 41360484Sobrien { 41460484Sobrien while (*s == ' ' && *s != 0) 41560484Sobrien s++; 41660484Sobrien if (*s == 0) 41760484Sobrien break; 41860484Sobrien in_quote = (*s == '\'' || *s == '"'); 41960484Sobrien sep = (in_quote) ? *s++ : ' '; 42060484Sobrien argv[i++] = s; 42160484Sobrien while (*s != sep && *s != 0) 42260484Sobrien s++; 42360484Sobrien if (*s == 0) 42460484Sobrien break; 42560484Sobrien *s++ = 0; 42660484Sobrien if (in_quote) 42760484Sobrien s++; 42860484Sobrien } 42960484Sobrien argv[i++] = NULL; 43060484Sobrien 43160484Sobrien if (dry_run) 43260484Sobrien return 0; 43360484Sobrien 43460484Sobrien pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base, 43560484Sobrien &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH); 43660484Sobrien 43760484Sobrien if (pid == -1) 43860484Sobrien { 43960484Sobrien int errno_val = errno; 44060484Sobrien 44160484Sobrien fprintf (stderr, "%s: ", program_name); 44260484Sobrien fprintf (stderr, errmsg_fmt, errmsg_arg); 44360484Sobrien fprintf (stderr, ": %s\n", strerror (errno_val)); 44460484Sobrien return 1; 44560484Sobrien } 44660484Sobrien 44760484Sobrien retcode = 0; 44860484Sobrien pid = pwait (pid, &wait_status, 0); 44960484Sobrien if (pid == -1) 45060484Sobrien { 45160484Sobrien warn ("wait: %s", strerror (errno)); 45260484Sobrien retcode = 1; 45360484Sobrien } 45460484Sobrien else if (WIFSIGNALED (wait_status)) 45560484Sobrien { 45660484Sobrien warn (_("subprocess got fatal signal %d"), WTERMSIG (wait_status)); 45760484Sobrien retcode = 1; 45860484Sobrien } 45960484Sobrien else if (WIFEXITED (wait_status)) 46060484Sobrien { 46160484Sobrien if (WEXITSTATUS (wait_status) != 0) 46260484Sobrien { 46360484Sobrien warn (_("%s exited with status %d"), what, WEXITSTATUS (wait_status)); 46460484Sobrien retcode = 1; 46560484Sobrien } 46660484Sobrien } 46760484Sobrien else 46860484Sobrien retcode = 1; 46960484Sobrien 47060484Sobrien return retcode; 47160484Sobrien} 47260484Sobrien 47360484Sobrienstatic char * 47460484Sobrienmybasename (name) 47560484Sobrien const char *name; 47660484Sobrien{ 47760484Sobrien const char *base = name; 47860484Sobrien 47960484Sobrien while (*name) 48060484Sobrien { 48160484Sobrien if (*name == '/' || *name == '\\') 48260484Sobrien { 48360484Sobrien base = name + 1; 48460484Sobrien } 48560484Sobrien ++name; 48660484Sobrien } 48760484Sobrien return (char *) base; 48860484Sobrien} 48960484Sobrien 49060484Sobrienstatic int 49160484Sobrienstrhash (const char *str) 49260484Sobrien{ 49360484Sobrien const unsigned char *s; 49460484Sobrien unsigned long hash; 49560484Sobrien unsigned int c; 49660484Sobrien unsigned int len; 49760484Sobrien 49860484Sobrien hash = 0; 49960484Sobrien len = 0; 50060484Sobrien s = (const unsigned char *) str; 50160484Sobrien while ((c = *s++) != '\0') 50260484Sobrien { 50360484Sobrien hash += c + (c << 17); 50460484Sobrien hash ^= hash >> 2; 50560484Sobrien ++len; 50660484Sobrien } 50760484Sobrien hash += len + (len << 17); 50860484Sobrien hash ^= hash >> 2; 50960484Sobrien 51060484Sobrien return hash; 51160484Sobrien} 51260484Sobrien 51360484Sobrien/**********************************************************************/ 51460484Sobrien 51560484Sobrienstatic void 51660484Sobrienusage (file, status) 51760484Sobrien FILE *file; 51860484Sobrien int status; 51960484Sobrien{ 52060484Sobrien fprintf (file, _("Usage %s <options> <object-files>\n"), program_name); 52160484Sobrien fprintf (file, _(" Generic options:\n")); 52260484Sobrien fprintf (file, _(" --quiet, -q Work quietly\n")); 52360484Sobrien fprintf (file, _(" --verbose, -v Verbose\n")); 52460484Sobrien fprintf (file, _(" --version Print dllwrap version\n")); 52560484Sobrien fprintf (file, _(" --implib <outname> Synonym for --output-lib\n")); 52660484Sobrien fprintf (file, _(" Options for %s:\n"), program_name); 52760484Sobrien fprintf (file, _(" --driver-name <driver> Defaults to \"gcc\"\n")); 52860484Sobrien fprintf (file, _(" --driver-flags <flags> Override default ld flags\n")); 52960484Sobrien fprintf (file, _(" --dlltool-name <dlltool> Defaults to \"dlltool\"\n")); 53060484Sobrien fprintf (file, _(" --entry <entry> Specify alternate DLL entry point\n")); 53160484Sobrien fprintf (file, _(" --image-base <base> Specify image base address\n")); 53260484Sobrien fprintf (file, _(" --target <machine> i386-cygwin32 or i386-mingw32\n")); 53360484Sobrien fprintf (file, _(" --dry-run Show what needs to be run\n")); 53460484Sobrien fprintf (file, _(" --mno-cygwin Create Mingw DLL\n")); 53560484Sobrien fprintf (file, _(" Options passed to DLLTOOL:\n")); 53660484Sobrien fprintf (file, _(" --machine <machine>\n")); 53760484Sobrien fprintf (file, _(" --output-exp <outname> Generate export file.\n")); 53860484Sobrien fprintf (file, _(" --output-lib <outname> Generate input library.\n")); 53960484Sobrien fprintf (file, _(" --add-indirect Add dll indirects to export file.\n")); 54060484Sobrien fprintf (file, _(" --dllname <name> Name of input dll to put into output lib.\n")); 54160484Sobrien fprintf (file, _(" --def <deffile> Name input .def file\n")); 54260484Sobrien fprintf (file, _(" --output-def <deffile> Name output .def file\n")); 54360484Sobrien fprintf (file, _(" --export-all-symbols Export all symbols to .def\n")); 54460484Sobrien fprintf (file, _(" --no-export-all-symbols Only export .drectve symbols\n")); 54560484Sobrien fprintf (file, _(" --exclude-symbols <list> Exclude <list> from .def\n")); 54660484Sobrien fprintf (file, _(" --no-default-excludes Zap default exclude symbols\n")); 54760484Sobrien fprintf (file, _(" --base-file <basefile> Read linker generated base file\n")); 54860484Sobrien fprintf (file, _(" --no-idata4 Don't generate idata$4 section\n")); 54960484Sobrien fprintf (file, _(" --no-idata5 Don't generate idata$5 section\n")); 55060484Sobrien fprintf (file, _(" -U Add underscores to .lib\n")); 55160484Sobrien fprintf (file, _(" -k Kill @<n> from exported names\n")); 55260484Sobrien fprintf (file, _(" --add-stdcall-alias Add aliases without @<n>\n")); 55360484Sobrien fprintf (file, _(" --as <name> Use <name> for assembler\n")); 55460484Sobrien fprintf (file, _(" --nodelete Keep temp files.\n")); 55560484Sobrien fprintf (file, _(" Rest are passed unmodified to the language driver\n")); 55660484Sobrien fprintf (file, "\n\n"); 55760484Sobrien exit (status); 55860484Sobrien} 55960484Sobrien 56060484Sobrien#define OPTION_START 149 56160484Sobrien 56260484Sobrien/* GENERIC options. */ 56360484Sobrien#define OPTION_QUIET (OPTION_START + 1) 56460484Sobrien#define OPTION_VERBOSE (OPTION_QUIET + 1) 56560484Sobrien#define OPTION_VERSION (OPTION_VERBOSE + 1) 56660484Sobrien 56760484Sobrien/* DLLWRAP options. */ 56860484Sobrien#define OPTION_DRY_RUN (OPTION_VERSION + 1) 56960484Sobrien#define OPTION_DRIVER_NAME (OPTION_DRY_RUN + 1) 57060484Sobrien#define OPTION_DRIVER_FLAGS (OPTION_DRIVER_NAME + 1) 57160484Sobrien#define OPTION_DLLTOOL_NAME (OPTION_DRIVER_FLAGS + 1) 57260484Sobrien#define OPTION_ENTRY (OPTION_DLLTOOL_NAME + 1) 57360484Sobrien#define OPTION_IMAGE_BASE (OPTION_ENTRY + 1) 57460484Sobrien#define OPTION_TARGET (OPTION_IMAGE_BASE + 1) 57560484Sobrien#define OPTION_MNO_CYGWIN (OPTION_TARGET + 1) 57660484Sobrien 57760484Sobrien/* DLLTOOL options. */ 57860484Sobrien#define OPTION_NODELETE (OPTION_MNO_CYGWIN + 1) 57960484Sobrien#define OPTION_DLLNAME (OPTION_NODELETE + 1) 58060484Sobrien#define OPTION_NO_IDATA4 (OPTION_DLLNAME + 1) 58160484Sobrien#define OPTION_NO_IDATA5 (OPTION_NO_IDATA4 + 1) 58260484Sobrien#define OPTION_OUTPUT_EXP (OPTION_NO_IDATA5 + 1) 58360484Sobrien#define OPTION_OUTPUT_DEF (OPTION_OUTPUT_EXP + 1) 58460484Sobrien#define OPTION_EXPORT_ALL_SYMS (OPTION_OUTPUT_DEF + 1) 58560484Sobrien#define OPTION_NO_EXPORT_ALL_SYMS (OPTION_EXPORT_ALL_SYMS + 1) 58660484Sobrien#define OPTION_EXCLUDE_SYMS (OPTION_NO_EXPORT_ALL_SYMS + 1) 58760484Sobrien#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_EXCLUDE_SYMS + 1) 58860484Sobrien#define OPTION_OUTPUT_LIB (OPTION_NO_DEFAULT_EXCLUDES + 1) 58960484Sobrien#define OPTION_DEF (OPTION_OUTPUT_LIB + 1) 59060484Sobrien#define OPTION_ADD_UNDERSCORE (OPTION_DEF + 1) 59160484Sobrien#define OPTION_KILLAT (OPTION_ADD_UNDERSCORE + 1) 59260484Sobrien#define OPTION_HELP (OPTION_KILLAT + 1) 59360484Sobrien#define OPTION_MACHINE (OPTION_HELP + 1) 59460484Sobrien#define OPTION_ADD_INDIRECT (OPTION_MACHINE + 1) 59560484Sobrien#define OPTION_BASE_FILE (OPTION_ADD_INDIRECT + 1) 59660484Sobrien#define OPTION_AS (OPTION_BASE_FILE + 1) 59760484Sobrien 59860484Sobrienstatic const struct option long_options[] = 59960484Sobrien{ 60060484Sobrien /* generic options. */ 60160484Sobrien {"quiet", no_argument, NULL, 'q'}, 60260484Sobrien {"verbose", no_argument, NULL, 'v'}, 60360484Sobrien {"version", no_argument, NULL, OPTION_VERSION}, 60460484Sobrien {"implib", required_argument, NULL, OPTION_OUTPUT_LIB}, 60560484Sobrien 60660484Sobrien /* dllwrap options. */ 60760484Sobrien {"dry-run", no_argument, NULL, OPTION_DRY_RUN}, 60860484Sobrien {"driver-name", required_argument, NULL, OPTION_DRIVER_NAME}, 60960484Sobrien {"driver-flags", required_argument, NULL, OPTION_DRIVER_FLAGS}, 61060484Sobrien {"dlltool-name", required_argument, NULL, OPTION_DLLTOOL_NAME}, 61160484Sobrien {"entry", required_argument, NULL, 'e'}, 61260484Sobrien {"image-base", required_argument, NULL, OPTION_IMAGE_BASE}, 61360484Sobrien {"target", required_argument, NULL, OPTION_TARGET}, 61460484Sobrien 61560484Sobrien /* dlltool options. */ 61660484Sobrien {"no-delete", no_argument, NULL, 'n'}, 61760484Sobrien {"dllname", required_argument, NULL, OPTION_DLLNAME}, 61860484Sobrien {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4}, 61960484Sobrien {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5}, 62060484Sobrien {"output-exp", required_argument, NULL, OPTION_OUTPUT_EXP}, 62160484Sobrien {"output-def", required_argument, NULL, OPTION_OUTPUT_DEF}, 62260484Sobrien {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL_SYMS}, 62360484Sobrien {"no-export-all-symbols", no_argument, NULL, OPTION_NO_EXPORT_ALL_SYMS}, 62460484Sobrien {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMS}, 62560484Sobrien {"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES}, 62660484Sobrien {"output-lib", required_argument, NULL, OPTION_OUTPUT_LIB}, 62760484Sobrien {"def", required_argument, NULL, OPTION_DEF}, 62860484Sobrien {"add-underscore", no_argument, NULL, 'U'}, 62960484Sobrien {"killat", no_argument, NULL, 'k'}, 63060484Sobrien {"add-stdcall-alias", no_argument, NULL, 'A'}, 63160484Sobrien {"help", no_argument, NULL, 'h'}, 63260484Sobrien {"machine", required_argument, NULL, OPTION_MACHINE}, 63360484Sobrien {"add-indirect", no_argument, NULL, OPTION_ADD_INDIRECT}, 63460484Sobrien {"base-file", required_argument, NULL, OPTION_BASE_FILE}, 63560484Sobrien {"as", required_argument, NULL, OPTION_AS}, 63660484Sobrien {0, 0, 0, 0} 63760484Sobrien}; 63860484Sobrien 63960484Sobrienint 64060484Sobrienmain (argc, argv) 64160484Sobrien int argc; 64260484Sobrien char **argv; 64360484Sobrien{ 64460484Sobrien int c; 64560484Sobrien int i; 64660484Sobrien 64760484Sobrien char **saved_argv = 0; 64860484Sobrien int cmdline_len = 0; 64960484Sobrien 65060484Sobrien int export_all = 0; 65160484Sobrien 65260484Sobrien int *dlltool_arg_indices; 65360484Sobrien int *driver_arg_indices; 65460484Sobrien 65560484Sobrien char *driver_flags = 0; 65660484Sobrien char *output_lib_file_name = 0; 65760484Sobrien 65860484Sobrien dyn_string_t dlltool_cmdline; 65960484Sobrien dyn_string_t driver_cmdline; 66060484Sobrien 66160484Sobrien int def_file_seen = 0; 66260484Sobrien 66360484Sobrien char *image_base_str = 0; 66460484Sobrien 66560484Sobrien program_name = argv[0]; 66660484Sobrien 66760484Sobrien saved_argv = (char **) xmalloc (argc * sizeof (char*)); 66860484Sobrien dlltool_arg_indices = (int *) xmalloc (argc * sizeof (int)); 66960484Sobrien driver_arg_indices = (int *) xmalloc (argc * sizeof (int)); 67060484Sobrien for (i = 0; i < argc; ++i) 67160484Sobrien { 67260484Sobrien size_t len = strlen (argv[i]); 67360484Sobrien char *arg = (char *) xmalloc (len + 1); 67460484Sobrien strcpy (arg, argv[i]); 67560484Sobrien cmdline_len += len; 67660484Sobrien saved_argv[i] = arg; 67760484Sobrien dlltool_arg_indices[i] = 0; 67860484Sobrien driver_arg_indices[i] = 1; 67960484Sobrien } 68060484Sobrien cmdline_len++; 68160484Sobrien 68260484Sobrien /* We recognize dllwrap and dlltool options, and everything else is 68360484Sobrien passed onto the language driver (eg., to GCC). We collect options 68460484Sobrien to dlltool and driver in dlltool_args and driver_args. */ 68560484Sobrien 68660484Sobrien opterr = 0; 68760484Sobrien while ((c = getopt_long_only (argc, argv, "nkAqve:Uho:l:L:I:", 68860484Sobrien long_options, (int *) 0)) != EOF) 68960484Sobrien { 69060484Sobrien int dlltool_arg; 69160484Sobrien int driver_arg; 69260484Sobrien int single_word_option_value_pair; 69360484Sobrien 69460484Sobrien dlltool_arg = 0; 69560484Sobrien driver_arg = 1; 69660484Sobrien single_word_option_value_pair = 0; 69760484Sobrien 69860484Sobrien if (c != '?') 69960484Sobrien { 70060484Sobrien /* We recognize this option, so it has to be either dllwrap or 70160484Sobrien dlltool option. Do not pass to driver unless it's one of the 70260484Sobrien generic options that are passed to all the tools (such as -v) 70360484Sobrien which are dealt with later. */ 70460484Sobrien driver_arg = 0; 70560484Sobrien } 70660484Sobrien 70760484Sobrien /* deal with generic and dllwrap options first. */ 70860484Sobrien switch (c) 70960484Sobrien { 71060484Sobrien case 'h': 71160484Sobrien usage (stdout, 0); 71260484Sobrien break; 71360484Sobrien case 'q': 71460484Sobrien verbose = 0; 71560484Sobrien break; 71660484Sobrien case 'v': 71760484Sobrien verbose = 1; 71860484Sobrien break; 71960484Sobrien case OPTION_VERSION: 72060484Sobrien print_version (program_name); 72160484Sobrien break; 72260484Sobrien case 'e': 72360484Sobrien entry_point = optarg; 72460484Sobrien break; 72560484Sobrien case OPTION_IMAGE_BASE: 72660484Sobrien image_base_str = optarg; 72760484Sobrien break; 72860484Sobrien case OPTION_DEF: 72960484Sobrien def_file_name = optarg; 73060484Sobrien def_file_seen = 1; 73160484Sobrien delete_def_file = 0; 73260484Sobrien break; 73360484Sobrien case 'n': 73460484Sobrien dontdeltemps = 1; 73560484Sobrien dlltool_arg = 1; 73660484Sobrien break; 73760484Sobrien case 'o': 73860484Sobrien dll_file_name = optarg; 73960484Sobrien break; 74060484Sobrien case 'I': 74160484Sobrien case 'l': 74260484Sobrien case 'L': 74360484Sobrien driver_arg = 1; 74460484Sobrien break; 74560484Sobrien case OPTION_DLLNAME: 74660484Sobrien dll_name = optarg; 74760484Sobrien break; 74860484Sobrien case OPTION_DRY_RUN: 74960484Sobrien dry_run = 1; 75060484Sobrien break; 75160484Sobrien case OPTION_DRIVER_NAME: 75260484Sobrien driver_name = optarg; 75360484Sobrien break; 75460484Sobrien case OPTION_DRIVER_FLAGS: 75560484Sobrien driver_flags = optarg; 75660484Sobrien break; 75760484Sobrien case OPTION_DLLTOOL_NAME: 75860484Sobrien dlltool_name = optarg; 75960484Sobrien break; 76060484Sobrien case OPTION_TARGET: 76160484Sobrien target = optarg; 76260484Sobrien break; 76360484Sobrien case OPTION_MNO_CYGWIN: 76460484Sobrien target = "i386-mingw32"; 76560484Sobrien break; 76660484Sobrien case OPTION_BASE_FILE: 76760484Sobrien base_file_name = optarg; 76860484Sobrien delete_base_file = 0; 76960484Sobrien break; 77060484Sobrien case OPTION_OUTPUT_EXP: 77160484Sobrien exp_file_name = optarg; 77260484Sobrien delete_exp_file = 0; 77360484Sobrien break; 77460484Sobrien case OPTION_EXPORT_ALL_SYMS: 77560484Sobrien export_all = 1; 77660484Sobrien break; 77760484Sobrien case OPTION_OUTPUT_LIB: 77860484Sobrien output_lib_file_name = optarg; 77960484Sobrien break; 78060484Sobrien case '?': 78160484Sobrien break; 78260484Sobrien default: 78360484Sobrien dlltool_arg = 1; 78460484Sobrien break; 78560484Sobrien } 78660484Sobrien 78760484Sobrien /* Handle passing through --option=value case. */ 78860484Sobrien if (optarg 78960484Sobrien && saved_argv[optind-1][0] == '-' 79060484Sobrien && saved_argv[optind-1][1] == '-' 79160484Sobrien && strchr (saved_argv[optind-1], '=')) 79260484Sobrien single_word_option_value_pair = 1; 79360484Sobrien 79460484Sobrien if (dlltool_arg) 79560484Sobrien { 79660484Sobrien dlltool_arg_indices[optind-1] = 1; 79760484Sobrien if (optarg && ! single_word_option_value_pair) 79860484Sobrien { 79960484Sobrien dlltool_arg_indices[optind-2] = 1; 80060484Sobrien } 80160484Sobrien } 80260484Sobrien 80360484Sobrien if (! driver_arg) 80460484Sobrien { 80560484Sobrien driver_arg_indices[optind-1] = 0; 80660484Sobrien if (optarg && ! single_word_option_value_pair) 80760484Sobrien { 80860484Sobrien driver_arg_indices[optind-2] = 0; 80960484Sobrien } 81060484Sobrien } 81160484Sobrien } 81260484Sobrien 81360484Sobrien /* sanity checks. */ 81460484Sobrien if (! dll_name && ! dll_file_name) 81560484Sobrien { 81660484Sobrien warn (_("Must provide at least one of -o or --dllname options")); 81760484Sobrien exit (1); 81860484Sobrien } 81960484Sobrien else if (! dll_name) 82060484Sobrien { 82160484Sobrien dll_name = xstrdup (mybasename (dll_file_name)); 82260484Sobrien } 82360484Sobrien else if (! dll_file_name) 82460484Sobrien { 82560484Sobrien dll_file_name = xstrdup (dll_name); 82660484Sobrien } 82760484Sobrien 82860484Sobrien /* Deduce driver-name and dlltool-name from our own. */ 82960484Sobrien if (driver_name == NULL) 83060484Sobrien driver_name = deduce_name ("gcc"); 83160484Sobrien 83260484Sobrien if (dlltool_name == NULL) 83360484Sobrien dlltool_name = deduce_name ("dlltool"); 83460484Sobrien 83560484Sobrien if (! def_file_seen) 83660484Sobrien { 83760484Sobrien char *fileprefix = choose_temp_base (); 83860484Sobrien def_file_name = (char *) xmalloc (strlen (fileprefix) + 5); 83960484Sobrien sprintf (def_file_name, "%s.def", 84060484Sobrien (dontdeltemps) ? mybasename (fileprefix) : fileprefix); 84160484Sobrien delete_def_file = 1; 84260484Sobrien free (fileprefix); 84360484Sobrien delete_def_file = 1; 84460484Sobrien warn (_("no export definition file provided")); 84560484Sobrien warn (_("creating one, but that may not be what you want")); 84660484Sobrien } 84760484Sobrien 84860484Sobrien /* set the target platform. */ 84960484Sobrien if (strstr (target, "cygwin")) 85060484Sobrien which_target = CYGWIN_TARGET; 85160484Sobrien else if (strstr (target, "mingw")) 85260484Sobrien which_target = MINGW_TARGET; 85360484Sobrien else 85460484Sobrien which_target = UNKNOWN_TARGET; 85560484Sobrien 85660484Sobrien /* re-create the command lines as a string, taking care to quote stuff. */ 85760484Sobrien dlltool_cmdline = dyn_string_new (cmdline_len); 85860484Sobrien if (verbose) 85960484Sobrien { 86077298Sobrien dyn_string_append_cstr (dlltool_cmdline, " -v"); 86160484Sobrien } 86277298Sobrien dyn_string_append_cstr (dlltool_cmdline, " --dllname "); 86377298Sobrien dyn_string_append_cstr (dlltool_cmdline, dll_name); 86460484Sobrien 86560484Sobrien for (i = 1; i < argc; ++i) 86660484Sobrien { 86760484Sobrien if (dlltool_arg_indices[i]) 86860484Sobrien { 86960484Sobrien char *arg = saved_argv[i]; 87060484Sobrien int quote = (strchr (arg, ' ') || strchr (arg, '\t')); 87177298Sobrien dyn_string_append_cstr (dlltool_cmdline, 87260484Sobrien (quote) ? " \"" : " "); 87377298Sobrien dyn_string_append_cstr (dlltool_cmdline, arg); 87477298Sobrien dyn_string_append_cstr (dlltool_cmdline, 87560484Sobrien (quote) ? "\"" : ""); 87660484Sobrien } 87760484Sobrien } 87860484Sobrien 87960484Sobrien driver_cmdline = dyn_string_new (cmdline_len); 88060484Sobrien if (! driver_flags || strlen (driver_flags) == 0) 88160484Sobrien { 88260484Sobrien switch (which_target) 88360484Sobrien { 88460484Sobrien case CYGWIN_TARGET: 88560484Sobrien driver_flags = cygwin_driver_flags; 88660484Sobrien break; 88760484Sobrien 88860484Sobrien case MINGW_TARGET: 88960484Sobrien driver_flags = mingw32_driver_flags; 89060484Sobrien break; 89160484Sobrien 89260484Sobrien default: 89360484Sobrien driver_flags = generic_driver_flags; 89460484Sobrien break; 89560484Sobrien } 89660484Sobrien } 89777298Sobrien dyn_string_append_cstr (driver_cmdline, driver_flags); 89877298Sobrien dyn_string_append_cstr (driver_cmdline, " -o "); 89977298Sobrien dyn_string_append_cstr (driver_cmdline, dll_file_name); 90060484Sobrien 90160484Sobrien if (! entry_point || strlen (entry_point) == 0) 90260484Sobrien { 90360484Sobrien switch (which_target) 90460484Sobrien { 90560484Sobrien case CYGWIN_TARGET: 90660484Sobrien entry_point = "__cygwin_dll_entry@12"; 90760484Sobrien break; 90860484Sobrien 90960484Sobrien case MINGW_TARGET: 91060484Sobrien entry_point = "_DllMainCRTStartup@12"; 91160484Sobrien break; 91260484Sobrien 91360484Sobrien default: 91460484Sobrien entry_point = "_DllMain@12"; 91560484Sobrien break; 91660484Sobrien } 91760484Sobrien } 91877298Sobrien dyn_string_append_cstr (driver_cmdline, " -Wl,-e,"); 91977298Sobrien dyn_string_append_cstr (driver_cmdline, entry_point); 92077298Sobrien dyn_string_append_cstr (dlltool_cmdline, " --exclude-symbol="); 92177298Sobrien dyn_string_append_cstr (dlltool_cmdline, 92260484Sobrien (entry_point[0] == '_') ? entry_point+1 : entry_point); 92360484Sobrien 92460484Sobrien if (! image_base_str || strlen (image_base_str) == 0) 92560484Sobrien { 92660484Sobrien char *tmpbuf = (char *) xmalloc (sizeof ("0x12345678") + 1); 92760484Sobrien unsigned long hash = strhash (dll_file_name); 92860484Sobrien sprintf (tmpbuf, "0x%.8lX", 0x60000000|((hash<<16)&0xFFC0000)); 92960484Sobrien image_base_str = tmpbuf; 93060484Sobrien } 93160484Sobrien 93277298Sobrien dyn_string_append_cstr (driver_cmdline, " -Wl,--image-base,"); 93377298Sobrien dyn_string_append_cstr (driver_cmdline, image_base_str); 93460484Sobrien 93560484Sobrien if (verbose) 93660484Sobrien { 93777298Sobrien dyn_string_append_cstr (driver_cmdline, " -v"); 93860484Sobrien } 93960484Sobrien 94060484Sobrien for (i = 1; i < argc; ++i) 94160484Sobrien { 94260484Sobrien if (driver_arg_indices[i]) 94360484Sobrien { 94460484Sobrien char *arg = saved_argv[i]; 94560484Sobrien int quote = (strchr (arg, ' ') || strchr (arg, '\t')); 94677298Sobrien dyn_string_append_cstr (driver_cmdline, 94760484Sobrien (quote) ? " \"" : " "); 94877298Sobrien dyn_string_append_cstr (driver_cmdline, arg); 94977298Sobrien dyn_string_append_cstr (driver_cmdline, 95060484Sobrien (quote) ? "\"" : ""); 95160484Sobrien } 95260484Sobrien } 95360484Sobrien 95460484Sobrien /* 95560484Sobrien * Step pre-1. If no --def <EXPORT_DEF> is specified, then create it 95660484Sobrien * and then pass it on. 95760484Sobrien */ 95860484Sobrien 95960484Sobrien if (! def_file_seen) 96060484Sobrien { 96160484Sobrien int i; 96260484Sobrien dyn_string_t step_pre1; 96360484Sobrien 96460484Sobrien step_pre1 = dyn_string_new (1024); 96560484Sobrien 96677298Sobrien dyn_string_append_cstr (step_pre1, dlltool_cmdline->s); 96760484Sobrien if (export_all) 96860484Sobrien { 96977298Sobrien dyn_string_append_cstr (step_pre1, " --export-all --exclude-symbol="); 97077298Sobrien dyn_string_append_cstr (step_pre1, 97160484Sobrien "_cygwin_dll_entry@12,DllMainCRTStartup@12,DllMain@12,DllEntryPoint@12"); 97260484Sobrien } 97377298Sobrien dyn_string_append_cstr (step_pre1, " --output-def "); 97477298Sobrien dyn_string_append_cstr (step_pre1, def_file_name); 97560484Sobrien 97660484Sobrien for (i = 1; i < argc; ++i) 97760484Sobrien { 97860484Sobrien if (driver_arg_indices[i]) 97960484Sobrien { 98060484Sobrien char *arg = saved_argv[i]; 98160484Sobrien size_t len = strlen (arg); 98260484Sobrien if (len >= 2 && arg[len-2] == '.' 98360484Sobrien && (arg[len-1] == 'o' || arg[len-1] == 'a')) 98460484Sobrien { 98560484Sobrien int quote = (strchr (arg, ' ') || strchr (arg, '\t')); 98677298Sobrien dyn_string_append_cstr (step_pre1, 98760484Sobrien (quote) ? " \"" : " "); 98877298Sobrien dyn_string_append_cstr (step_pre1, arg); 98977298Sobrien dyn_string_append_cstr (step_pre1, 99060484Sobrien (quote) ? "\"" : ""); 99160484Sobrien } 99260484Sobrien } 99360484Sobrien } 99460484Sobrien 99560484Sobrien if (run (dlltool_name, step_pre1->s)) 99660484Sobrien cleanup_and_exit (1); 99760484Sobrien 99860484Sobrien dyn_string_delete (step_pre1); 99960484Sobrien } 100060484Sobrien 100177298Sobrien dyn_string_append_cstr (dlltool_cmdline, " --def "); 100277298Sobrien dyn_string_append_cstr (dlltool_cmdline, def_file_name); 100360484Sobrien 100460484Sobrien if (verbose) 100560484Sobrien { 100660484Sobrien fprintf (stderr, _("DLLTOOL name : %s\n"), dlltool_name); 100760484Sobrien fprintf (stderr, _("DLLTOOL options : %s\n"), dlltool_cmdline->s); 100860484Sobrien fprintf (stderr, _("DRIVER name : %s\n"), driver_name); 100960484Sobrien fprintf (stderr, _("DRIVER options : %s\n"), driver_cmdline->s); 101060484Sobrien } 101160484Sobrien 101260484Sobrien /* 101360484Sobrien * Step 1. Call GCC/LD to create base relocation file. If using GCC, the 101460484Sobrien * driver command line will look like the following: 101560484Sobrien * 101660484Sobrien * % gcc -Wl,--dll --Wl,--base-file,foo.base [rest of command line] 101760484Sobrien * 101860484Sobrien * If the user does not specify a base name, create temporary one that 101960484Sobrien * is deleted at exit. 102060484Sobrien * 102160484Sobrien */ 102260484Sobrien 102360484Sobrien if (! base_file_name) 102460484Sobrien { 102560484Sobrien char *fileprefix = choose_temp_base (); 102660484Sobrien base_file_name = (char *) xmalloc (strlen (fileprefix) + 6); 102760484Sobrien sprintf (base_file_name, "%s.base", 102860484Sobrien (dontdeltemps) ? mybasename (fileprefix) : fileprefix); 102960484Sobrien delete_base_file = 1; 103060484Sobrien free (fileprefix); 103160484Sobrien } 103260484Sobrien 103360484Sobrien { 103460484Sobrien int quote; 103560484Sobrien 103660484Sobrien dyn_string_t step1 = dyn_string_new (driver_cmdline->length 103760484Sobrien + strlen (base_file_name) 103860484Sobrien + 20); 103977298Sobrien dyn_string_append_cstr (step1, "-Wl,--base-file,"); 104060484Sobrien quote = (strchr (base_file_name, ' ') 104160484Sobrien || strchr (base_file_name, '\t')); 104277298Sobrien dyn_string_append_cstr (step1, 104360484Sobrien (quote) ? "\"" : ""); 104477298Sobrien dyn_string_append_cstr (step1, base_file_name); 104577298Sobrien dyn_string_append_cstr (step1, 104660484Sobrien (quote) ? "\"" : ""); 104760484Sobrien if (driver_cmdline->length) 104860484Sobrien { 104977298Sobrien dyn_string_append_cstr (step1, " "); 105077298Sobrien dyn_string_append_cstr (step1, driver_cmdline->s); 105160484Sobrien } 105260484Sobrien 105360484Sobrien if (run (driver_name, step1->s)) 105460484Sobrien cleanup_and_exit (1); 105560484Sobrien 105660484Sobrien dyn_string_delete (step1); 105760484Sobrien } 105860484Sobrien 105960484Sobrien 106060484Sobrien 106160484Sobrien /* 106260484Sobrien * Step 2. generate the exp file by running dlltool. 106360484Sobrien * dlltool command line will look like the following: 106460484Sobrien * 106560484Sobrien * % dlltool -Wl,--dll --Wl,--base-file,foo.base [rest of command line] 106660484Sobrien * 106760484Sobrien * If the user does not specify a base name, create temporary one that 106860484Sobrien * is deleted at exit. 106960484Sobrien * 107060484Sobrien */ 107160484Sobrien 107260484Sobrien if (! exp_file_name) 107360484Sobrien { 107460484Sobrien char *p = strrchr (dll_name, '.'); 107560484Sobrien size_t prefix_len = (p) ? p - dll_name : strlen (dll_name); 107660484Sobrien exp_file_name = (char *) xmalloc (prefix_len + 4 + 1); 107760484Sobrien strncpy (exp_file_name, dll_name, prefix_len); 107860484Sobrien exp_file_name[prefix_len] = '\0'; 107960484Sobrien strcat (exp_file_name, ".exp"); 108060484Sobrien delete_exp_file = 1; 108160484Sobrien } 108260484Sobrien 108360484Sobrien { 108460484Sobrien int quote; 108560484Sobrien dyn_string_t step2 = dyn_string_new (dlltool_cmdline->length 108660484Sobrien + strlen (base_file_name) 108760484Sobrien + strlen (exp_file_name) 108860484Sobrien + 20); 108960484Sobrien 109077298Sobrien dyn_string_append_cstr (step2, "--base-file "); 109160484Sobrien quote = (strchr (base_file_name, ' ') 109260484Sobrien || strchr (base_file_name, '\t')); 109377298Sobrien dyn_string_append_cstr (step2, 109460484Sobrien (quote) ? "\"" : ""); 109577298Sobrien dyn_string_append_cstr (step2, base_file_name); 109677298Sobrien dyn_string_append_cstr (step2, 109760484Sobrien (quote) ? "\" " : " "); 109860484Sobrien 109977298Sobrien dyn_string_append_cstr (step2, "--output-exp "); 110060484Sobrien quote = (strchr (exp_file_name, ' ') 110160484Sobrien || strchr (exp_file_name, '\t')); 110277298Sobrien dyn_string_append_cstr (step2, 110360484Sobrien (quote) ? "\"" : ""); 110477298Sobrien dyn_string_append_cstr (step2, exp_file_name); 110577298Sobrien dyn_string_append_cstr (step2, 110660484Sobrien (quote) ? "\"" : ""); 110760484Sobrien 110860484Sobrien if (dlltool_cmdline->length) 110960484Sobrien { 111077298Sobrien dyn_string_append_cstr (step2, " "); 111177298Sobrien dyn_string_append_cstr (step2, dlltool_cmdline->s); 111260484Sobrien } 111360484Sobrien 111460484Sobrien if (run (dlltool_name, step2->s)) 111560484Sobrien cleanup_and_exit (1); 111660484Sobrien 111760484Sobrien dyn_string_delete (step2); 111860484Sobrien } 111960484Sobrien 112060484Sobrien /* 112160484Sobrien * Step 3. Call GCC/LD to again, adding the exp file this time. 112260484Sobrien * driver command line will look like the following: 112360484Sobrien * 112460484Sobrien * % gcc -Wl,--dll --Wl,--base-file,foo.base foo.exp [rest ...] 112560484Sobrien */ 112660484Sobrien 112760484Sobrien { 112860484Sobrien int quote; 112960484Sobrien 113060484Sobrien dyn_string_t step3 = dyn_string_new (driver_cmdline->length 113160484Sobrien + strlen (exp_file_name) 113260484Sobrien + strlen (base_file_name) 113360484Sobrien + 20); 113477298Sobrien dyn_string_append_cstr (step3, "-Wl,--base-file,"); 113560484Sobrien quote = (strchr (base_file_name, ' ') 113660484Sobrien || strchr (base_file_name, '\t')); 113777298Sobrien dyn_string_append_cstr (step3, 113860484Sobrien (quote) ? "\"" : ""); 113977298Sobrien dyn_string_append_cstr (step3, base_file_name); 114077298Sobrien dyn_string_append_cstr (step3, 114160484Sobrien (quote) ? "\" " : " "); 114260484Sobrien 114360484Sobrien quote = (strchr (exp_file_name, ' ') 114460484Sobrien || strchr (exp_file_name, '\t')); 114577298Sobrien dyn_string_append_cstr (step3, 114660484Sobrien (quote) ? "\"" : ""); 114777298Sobrien dyn_string_append_cstr (step3, exp_file_name); 114877298Sobrien dyn_string_append_cstr (step3, 114960484Sobrien (quote) ? "\"" : ""); 115060484Sobrien 115160484Sobrien if (driver_cmdline->length) 115260484Sobrien { 115377298Sobrien dyn_string_append_cstr (step3, " "); 115477298Sobrien dyn_string_append_cstr (step3, driver_cmdline->s); 115560484Sobrien } 115660484Sobrien 115760484Sobrien if (run (driver_name, step3->s)) 115860484Sobrien cleanup_and_exit (1); 115960484Sobrien 116060484Sobrien dyn_string_delete (step3); 116160484Sobrien } 116260484Sobrien 116360484Sobrien 116460484Sobrien /* 116560484Sobrien * Step 4. Run DLLTOOL again using the same command line. 116660484Sobrien */ 116760484Sobrien 116860484Sobrien { 116960484Sobrien int quote; 117060484Sobrien dyn_string_t step4 = dyn_string_new (dlltool_cmdline->length 117160484Sobrien + strlen (base_file_name) 117260484Sobrien + strlen (exp_file_name) 117360484Sobrien + 20); 117460484Sobrien 117577298Sobrien dyn_string_append_cstr (step4, "--base-file "); 117660484Sobrien quote = (strchr (base_file_name, ' ') 117760484Sobrien || strchr (base_file_name, '\t')); 117877298Sobrien dyn_string_append_cstr (step4, 117960484Sobrien (quote) ? "\"" : ""); 118077298Sobrien dyn_string_append_cstr (step4, base_file_name); 118177298Sobrien dyn_string_append_cstr (step4, 118260484Sobrien (quote) ? "\" " : " "); 118360484Sobrien 118477298Sobrien dyn_string_append_cstr (step4, "--output-exp "); 118560484Sobrien quote = (strchr (exp_file_name, ' ') 118660484Sobrien || strchr (exp_file_name, '\t')); 118777298Sobrien dyn_string_append_cstr (step4, 118860484Sobrien (quote) ? "\"" : ""); 118977298Sobrien dyn_string_append_cstr (step4, exp_file_name); 119077298Sobrien dyn_string_append_cstr (step4, 119160484Sobrien (quote) ? "\"" : ""); 119260484Sobrien 119360484Sobrien if (dlltool_cmdline->length) 119460484Sobrien { 119577298Sobrien dyn_string_append_cstr (step4, " "); 119677298Sobrien dyn_string_append_cstr (step4, dlltool_cmdline->s); 119760484Sobrien } 119860484Sobrien 119960484Sobrien if (output_lib_file_name) 120060484Sobrien { 120177298Sobrien dyn_string_append_cstr (step4, " --output-lib "); 120277298Sobrien dyn_string_append_cstr (step4, output_lib_file_name); 120360484Sobrien } 120460484Sobrien 120560484Sobrien if (run (dlltool_name, step4->s)) 120660484Sobrien cleanup_and_exit (1); 120760484Sobrien 120860484Sobrien dyn_string_delete (step4); 120960484Sobrien } 121060484Sobrien 121160484Sobrien 121260484Sobrien /* 121360484Sobrien * Step 5. Link it all together and be done with it. 121460484Sobrien * driver command line will look like the following: 121560484Sobrien * 121660484Sobrien * % gcc -Wl,--dll foo.exp [rest ...] 121760484Sobrien * 121860484Sobrien */ 121960484Sobrien 122060484Sobrien { 122160484Sobrien int quote; 122260484Sobrien 122360484Sobrien dyn_string_t step5 = dyn_string_new (driver_cmdline->length 122460484Sobrien + strlen (exp_file_name) 122560484Sobrien + 20); 122660484Sobrien quote = (strchr (exp_file_name, ' ') 122760484Sobrien || strchr (exp_file_name, '\t')); 122877298Sobrien dyn_string_append_cstr (step5, 122960484Sobrien (quote) ? "\"" : ""); 123077298Sobrien dyn_string_append_cstr (step5, exp_file_name); 123177298Sobrien dyn_string_append_cstr (step5, 123260484Sobrien (quote) ? "\"" : ""); 123360484Sobrien 123460484Sobrien if (driver_cmdline->length) 123560484Sobrien { 123677298Sobrien dyn_string_append_cstr (step5, " "); 123777298Sobrien dyn_string_append_cstr (step5, driver_cmdline->s); 123860484Sobrien } 123960484Sobrien 124060484Sobrien if (run (driver_name, step5->s)) 124160484Sobrien cleanup_and_exit (1); 124260484Sobrien 124360484Sobrien dyn_string_delete (step5); 124460484Sobrien } 124560484Sobrien 124660484Sobrien cleanup_and_exit (0); 124760484Sobrien 124860484Sobrien return 0; 124960484Sobrien} 1250