From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- erts/etc/win32/cygwin_tools/vc/ld_wrap.c | 796 +++++++++++++++++++++++++++++++ 1 file changed, 796 insertions(+) create mode 100644 erts/etc/win32/cygwin_tools/vc/ld_wrap.c (limited to 'erts/etc/win32/cygwin_tools/vc/ld_wrap.c') diff --git a/erts/etc/win32/cygwin_tools/vc/ld_wrap.c b/erts/etc/win32/cygwin_tools/vc/ld_wrap.c new file mode 100644 index 0000000000..7fb3c145ee --- /dev/null +++ b/erts/etc/win32/cygwin_tools/vc/ld_wrap.c @@ -0,0 +1,796 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2008-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + + +#ifdef CCP_POSIX_TO_WIN_A +#define NEW_CYGPATH_INTERFACE +#endif + +#ifdef NEW_CYGPATH_INTERFACE +#define GET_WIN32_SIZE(Posix) \ +cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, (Posix), NULL, 0) +#define CONVERT_TO_WIN32(Posix,Win32,Size) \ +cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, (Posix), \ + (Win32), (Size)) +#else +#define GET_WIN32_SIZE(Posix) PATH_MAX +#define CONVERT_TO_WIN32(Posix,Win32,Size) \ +((cygwin32_conv_to_full_win32_path((Posix),(Win32)) >= 0) ? 0 : -1) +#endif + +/*#define HARDDEBUG 1*/ + +#ifdef HARDDEBUG +#define DEBUGF(X) printf X +#else +#define DEBUGF(X) /* noop */ +#endif +char *tmpobjdir = ""; + +char *add_to(char *src,char *add) { + int len = strlen(src)+strlen(add)+1; + char *n; + + if (strlen(src) == 0) { + n = malloc(len); + strcpy(n,add); + return n; + } + n = realloc(src,len); + strcat(n,add); + return n; +} + +void error(char *str) +{ + fprintf(stderr,"%s\n",str); + exit(1); +} + + +char *dyn_get_short(char *longp) +{ + int size; + char *shortp; + size = GetShortPathName(longp,NULL,0); + if (size <= 0) { + return NULL; + } + shortp = malloc(size); + if (GetShortPathName(longp,shortp,size) != size - 1) { + free(shortp); + return NULL; + } + return shortp; +} + +char *do_cyp(char *posix) +{ + ssize_t size; + char *win32; + size = GET_WIN32_SIZE(posix); + char *ret = NULL; + if (size < 0) { + fprintf(stderr,"Could not cygpath %s, errno = %d\n", + posix,errno); + } else { + win32 = (char *) malloc (size); + if (CONVERT_TO_WIN32(posix, + win32, size)) { + fprintf(stderr,"Could not cygpath %s, errno = %d\n", + posix,errno); + } else { + char *w32_short = dyn_get_short(win32); + DEBUGF(("win32 = %s, w32_short = %s\n",win32, (w32_short == NULL) ? "NULL" : w32_short)); + if (w32_short == NULL) { + char *rest = malloc(size); + char *first = malloc(size); + int x = 0; + int y = strlen(win32) - 1; + strcpy(first,win32); + while (w32_short == NULL) { + while ( y > 0 && first[y] != '\\') { + rest[x++] = first[y--]; + } + if (y > 0) { + rest[x++] = first[y]; + first[y--] = '\0'; + } else { + break; + } + w32_short = dyn_get_short(first); + DEBUGF(("first = %s, w32_short = %s\n",first, (w32_short == NULL) ? "NULL" : w32_short)); + } + if (w32_short != NULL) { + y = strlen(w32_short); + w32_short = realloc(w32_short,y+1+x); + /* spool back */ + while ( x > 0) { + w32_short[y++] = rest[--x]; + } + w32_short[y] = '\0'; + } else { + w32_short = malloc(strlen(win32)+1); + strcpy(w32_short,win32); /* last resort */ + } + free(first); + free(rest); + } + ret = w32_short; + while (*ret) { + if (*ret == '\\') { + *ret = '/'; + } + ++ret; + } + ret = w32_short; + } + free(win32); + } + return ret; +} + + + +char *save = ""; + +void save_args(int argc, char **argv) +{ + int i; + for(i = 0; i < argc; ++i) { + save = add_to(save,argv[i]); + save = add_to(save," "); + } +} + +char *progname="ld_wrap"; + +int my_create_pipe(HANDLE *read_p, HANDLE *write_p) +{ + char name_buff[1000]; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + static int counter = 0; + + ++counter; + + sprintf(name_buff,"\\\\.\\pipe\\%s_%d_%d",progname,getpid(),counter); + sa.bInheritHandle = FALSE; + if ((*read_p = CreateNamedPipe(name_buff, + PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, + 1, + 0, + 0, + 2000, + &sa)) == INVALID_HANDLE_VALUE || + *read_p == NULL) { + return 0; + } + sa.bInheritHandle = TRUE; + if ((*write_p = CreateFile(name_buff, + GENERIC_WRITE, + 0, /* No sharing */ + &sa, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL)) == INVALID_HANDLE_VALUE || + *write_p == NULL) { + CloseHandle(*read_p); + return 0; + } + return 1; +} + +void forwardenv(void) +{ + char *(envs[]) = {"LIB","INCLUDE","LIBPATH", NULL}; + char **p = envs; + while (*p != NULL) { + char *val = getenv(*p); + if (val != NULL) { + SetEnvironmentVariable(*p,val); + } + ++p; + } +} + +HANDLE do_run(char *commandline, HANDLE *out, HANDLE *err) +{ + STARTUPINFO start; + HANDLE write_pipe_stdout = NULL, read_pipe_stdout = NULL; + HANDLE write_pipe_stderr = NULL, read_pipe_stderr = NULL; + SECURITY_ATTRIBUTES pipe_security; + SECURITY_ATTRIBUTES attr; + PROCESS_INFORMATION info; + + + memset(&start,0,sizeof(start)); + memset(&pipe_security,0,sizeof(pipe_security)); + memset(&attr,0,sizeof(attr)); + memset(&info,0,sizeof(info)); + + + pipe_security.nLength = sizeof(pipe_security); + pipe_security.lpSecurityDescriptor = NULL; + pipe_security.bInheritHandle = TRUE; + + if(!my_create_pipe(&read_pipe_stdout,&write_pipe_stdout)){ + error("Could not create stdout pipes!"); + } + if(!my_create_pipe(&read_pipe_stderr,&write_pipe_stderr)){ + error("Could not create stderr pipes!"); + } + start.cb = sizeof (start); + start.dwFlags = STARTF_USESHOWWINDOW; + start.wShowWindow = SW_HIDE; + start.hStdOutput = write_pipe_stdout; + start.hStdError = write_pipe_stderr; + start.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + start.dwFlags |= STARTF_USESTDHANDLES; + + attr.nLength = sizeof(attr); + attr.lpSecurityDescriptor = NULL; + attr.bInheritHandle = TRUE; + forwardenv(); /* Cygwin and windows environment variables... sigh... */ + if(!CreateProcess(NULL, + commandline, + &attr, + NULL, + TRUE, + CREATE_DEFAULT_ERROR_MODE, + NULL, + NULL, + &start, + &info)){ + error("Could not create process"); + } + *out = read_pipe_stdout; + *err = read_pipe_stderr; + CloseHandle(write_pipe_stdout); + CloseHandle(write_pipe_stderr); + return info.hProcess; +} +#define HANDLE_STDOUT 0 +#define HANDLE_STDERR 1 +#define HANDLE_PROC 2 + +#ifdef HARDDEBUG +char *prefix = ""; +#endif + +int handle_overlapped(HANDLE fd, OVERLAPPED *ovp, char *buffer, + int bufflen, int get_old, FILE *whereto, int *skip) +{ + DWORD res,read,err; + char *ptr; + + DEBUGF(("In handle_overlapped(%d,0x%08x,0x%08x,%d,%d), prefix = %s\n", + fd,ovp,buffer,bufflen,get_old,prefix)); + /* hämta resultat av gamla först */ + if (get_old) { + res = GetOverlappedResult(fd,ovp,&read,TRUE); + DEBUGF(("read = %d, res = %d, GetLastError() = %d\n",read,res,GetLastError())); + if (!res) { + return 0; + } + buffer[read] = '\0'; + ptr = buffer; + while(*skip && *ptr != '\0') { + if (*ptr == '\n') { + --(*skip); + } + ++ptr; + } + if(*ptr != '\0') { + fprintf(whereto,"%s",ptr); + } + } + + ResetEvent(ovp->hEvent); + + for(;;) { + res = ReadFile(fd,buffer,bufflen-1,&read,ovp); + + if (!res) { + err = GetLastError(); + if (err == ERROR_IO_PENDING) { + DEBUGF(("Error I/O Pending\n")); + return 1; + } + DEBUGF(("ReadFileFailed for %s, %d\n",prefix,err)); + return 0; + } + buffer[read] = '\0'; + ptr = buffer; + while(*skip && *ptr != '\0') { + if (*ptr == '\n') { + --(*skip); + } + ++ptr; + } + if(*ptr != '\0') { + fprintf(whereto,"%s",ptr); + } + } +} + + +int run(char *commandline,int skipout,int skiperr) +{ + HANDLE harr[3]; + HANDLE real_stdout,real_stderr; + OVERLAPPED ov_out,ov_err; + char outbuff[1024],errbuff[1024]; + DWORD ret,exitcode; + HANDLE wait[3]; + int map[3]; + DWORD nwait = 3; + int i,j; + unsigned living_handles = 0x7; + + harr[HANDLE_STDOUT] = CreateEvent(NULL, + TRUE, + FALSE, /*not signalled */ + NULL); + harr[HANDLE_STDERR] = CreateEvent(NULL, + TRUE, + FALSE,/*not signalled */ + NULL); + + memset(&ov_out,0,sizeof(ov_out)); + memset(&ov_err,0,sizeof(ov_err)); + + ov_out.hEvent = harr[HANDLE_STDOUT]; + ov_err.hEvent = harr[HANDLE_STDERR]; + + harr[HANDLE_PROC] = do_run(commandline,&real_stdout,&real_stderr); + +#ifdef HARDDEBUG + prefix = "STDOUT"; +#endif + handle_overlapped(real_stdout,&ov_out,outbuff,1024,0,stdout,&skipout); +#ifdef HARDDEBUG + prefix = "STDERR"; +#endif + handle_overlapped(real_stderr,&ov_err,errbuff,1024,0,stderr,&skiperr); + + for(;;) { + nwait = 0; + for(i=0;i<3;++i) { + if ((living_handles & (1U << i))) { + map[nwait] = i; + wait[nwait++] = harr[i]; + } + } + + ret = WaitForMultipleObjects(nwait, + wait, + FALSE, + INFINITE); + DEBUGF(("Wait returned %d\n",ret)); + + if (ret == WAIT_FAILED) { + error("Wait failed"); + } + + ret -= WAIT_OBJECT_0; + + switch (map[ret]) { + case HANDLE_PROC: + + DEBUGF(("Process died!\n")); + GetExitCodeProcess(harr[HANDLE_PROC],&exitcode); + if ((living_handles &= (~(1U<= argc) { + error("-o without filename"); + } + output_filename = do_cyp(argv[i]); + } else { + output_filename = do_cyp(opt+1); + } + break; + default: + goto filename; + } + continue; + } + filename: + s = argv[i]; + if (*s == '/') { + mpath = do_cyp(s); + cmd = add_to(cmd," \""); + cmd = add_to(cmd,mpath); + cmd = add_to(cmd,"\""); + free(mpath); + } else { + cmd = add_to(cmd," \""); + cmd = add_to(cmd,s); + cmd = add_to(cmd,"\""); + } + } + if ((debuglog = getenv("LD_SH_DEBUG_LOG")) != NULL) { + debugfile = fopen(debuglog,"wb+"); + if (debugfile) { + fprintf(debugfile,"----------------\n"); + } + } else { + debugfile = NULL; + } + + if (debug_build) { + if (!stdlib_forced) { + stdlib = "MSVCRTD.LIB"; + } + } + + s = add_to("",output_filename); + x = strlen(s); + + if (x >= 4 && (!strcmp(s+x-4,".exe") || !strcmp(s+x-4,".EXE") || + !strcmp(s+x-4,".dll") || !strcmp(s+x-4,".DLL"))) { + *(s+x-3) = '\0'; + linkadd_pdb = add_to(linkadd_pdb,"-pdb:\""); + linkadd_pdb = add_to(linkadd_pdb,s); + linkadd_pdb = add_to(linkadd_pdb,"pdb\""); + } else if (!x) { + linkadd_pdb = add_to(linkadd_pdb,"-pdb:\"a.pdb\""); + } else { + linkadd_pdb = add_to(linkadd_pdb,"-pdb:\""); + linkadd_pdb = add_to(linkadd_pdb,s); + linkadd_pdb = add_to(linkadd_pdb,".pdb\""); + } + free(s); + + + linktype = add_to(linktype,"-debug "); + linktype = add_to(linktype,linkadd_pdb); + + free(linkadd_pdb); + + s = add_to("",output_filename); + x = strlen(s); + + if (build_dll) { + if (x >= 4 && (!strcmp(s+x-4,".exe") || !strcmp(s+x-4,".EXE") || + !strcmp(s+x-4,".dll") || !strcmp(s+x-4,".DLL"))) { + + if (!strcmp(s+x-4,".exe") || !strcmp(s+x-4,".EXE")) { + fprintf(stderr,"Warning, output set to .exe when building DLL"); + } + mpath = cmd; + cmd = add_to("","-dll -out:\""); + cmd = add_to(cmd,s); + cmd = add_to(cmd,"\" "); + cmd = add_to(cmd,mpath); + if (*mpath) { + free(mpath); + } + + outputres = add_to(outputres,output_filename); + outputres = add_to(outputres,";2"); + manifest = add_to(manifest,output_filename); + manifest = add_to(manifest,".manifest"); + } else if (x == 0) { + mpath = cmd; + cmd = add_to("","-dll -out:\"a.dll\" "); + cmd = add_to(cmd,mpath); + if (*mpath) { + free(mpath); + } + + outputres = add_to(outputres,"a.dll;2"); + manifest = add_to(manifest,"a.dll.manifest"); + } else { + mpath = cmd; + cmd = add_to("","-dll -out:\""); + cmd = add_to(cmd,s); + cmd = add_to(cmd,".dll\" "); + cmd = add_to(cmd,mpath); + if (*mpath) { + free(mpath); + } + + outputres = add_to(outputres,output_filename); + outputres = add_to(outputres,".dll;2"); + manifest = add_to(manifest,output_filename); + manifest = add_to(manifest,".dll.manifest"); + } + } else { + if (x >= 4 && (!strcmp(s+x-4,".exe") || !strcmp(s+x-4,".EXE") || + !strcmp(s+x-4,".dll") || !strcmp(s+x-4,".DLL"))) { + + if (!strcmp(s+x-4,".dll") || !strcmp(s+x-4,".DLL")) { + fprintf(stderr,"Warning, output set to .exe when building DLL"); + } + mpath = cmd; + cmd = add_to("","-out:\""); + cmd = add_to(cmd,s); + cmd = add_to(cmd,"\" "); + cmd = add_to(cmd,mpath); + if (*mpath) { + free(mpath); + } + + outputres = add_to(outputres,output_filename); + outputres = add_to(outputres,";1"); + manifest = add_to(manifest,output_filename); + manifest = add_to(manifest,".manifest"); + } else if (x == 0) { + mpath = cmd; + cmd = add_to("","-out:\"a.exe\" "); + cmd = add_to(cmd,mpath); + if (*mpath) { + free(mpath); + } + + outputres = add_to(outputres,"a.exe;1"); + manifest = add_to(manifest,"a.exe.manifest"); + } else { + mpath = cmd; + cmd = add_to("","-out:\""); + cmd = add_to(cmd,s); + cmd = add_to(cmd,".exe\" "); + cmd = add_to(cmd,mpath); + if (*mpath) { + free(mpath); + } + + outputres = add_to(outputres,output_filename); + outputres = add_to(outputres,".exe;1"); + manifest = add_to(manifest,output_filename); + manifest = add_to(manifest,".exe.manifest"); + } + } + + s = cmd; + cmd = add_to("","link.exe "); + cmd = add_to(cmd,linktype); + cmd = add_to(cmd," -nologo -incremental:no "); + cmd = add_to(cmd,s); + cmd = add_to(cmd," "); + cmd = add_to(cmd,stdlib); + cmd = add_to(cmd," "); + cmd = add_to(cmd,default_libraries); + + if (*s) { + free(s); + } + + + if (debugfile) { + fprintf(debugfile,"%s\n",save); + fprintf(debugfile,"%s\n",cmd); + } + + retval = run(cmd,0,0); + + + mpath = do_cyp(manifest); + filefound = 0; + tmpfile = fopen(mpath,"rb"); + if (tmpfile != NULL) { + filefound = 1; + fclose(tmpfile); + } + if (retval == 0 && filefound) { + s = add_to("","mt.exe -nologo -manifest \""); + s = add_to(s,manifest); + s = add_to(s,"\" -outputresource:\""); + s = add_to(s,outputres); + s = add_to(s,"\""); + if (debugfile) { + fprintf(debugfile,"%s\n",s); + } + retval = run(s,0,0); + if (*s) { + free(s); + } + if (retval) { + /* cleanup needed */ + remove = add_to("",outputres); + x = strlen(remove); + remove[x-2] = '\0'; + if (debugfile) { + fprintf(debugfile,"remove %s\n",remove); + } + DeleteFile(remove); + free(remove); + } + if (debugfile) { + fprintf(debugfile,"remove %s\n",manifest); + } + DeleteFile(manifest); + } + return retval; +} + + + + + + + + + + + + + + + + + + -- cgit v1.2.3