LLVM API Documentation
00001 //===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file provides the Win32 specific implementation of the Program class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "WindowsSupport.h" 00015 #include "llvm/Support/ConvertUTF.h" 00016 #include "llvm/Support/FileSystem.h" 00017 #include "llvm/Support/raw_ostream.h" 00018 #include <cstdio> 00019 #include <fcntl.h> 00020 #include <io.h> 00021 #include <malloc.h> 00022 00023 //===----------------------------------------------------------------------===// 00024 //=== WARNING: Implementation here must contain only Win32 specific code 00025 //=== and must not be UNIX code 00026 //===----------------------------------------------------------------------===// 00027 00028 namespace llvm { 00029 using namespace sys; 00030 00031 ProcessInfo::ProcessInfo() : ProcessHandle(0), Pid(0), ReturnCode(0) {} 00032 00033 // This function just uses the PATH environment variable to find the program. 00034 std::string sys::FindProgramByName(const std::string &progName) { 00035 // Check some degenerate cases 00036 if (progName.length() == 0) // no program 00037 return ""; 00038 std::string temp = progName; 00039 // Return paths with slashes verbatim. 00040 if (progName.find('\\') != std::string::npos || 00041 progName.find('/') != std::string::npos) 00042 return temp; 00043 00044 // At this point, the file name is valid and does not contain slashes. 00045 // Let Windows search for it. 00046 SmallVector<wchar_t, MAX_PATH> progNameUnicode; 00047 if (windows::UTF8ToUTF16(progName, progNameUnicode)) 00048 return ""; 00049 00050 SmallVector<wchar_t, MAX_PATH> buffer; 00051 DWORD len = MAX_PATH; 00052 do { 00053 buffer.reserve(len); 00054 len = ::SearchPathW(NULL, progNameUnicode.data(), L".exe", 00055 buffer.capacity(), buffer.data(), NULL); 00056 00057 // See if it wasn't found. 00058 if (len == 0) 00059 return ""; 00060 00061 // Buffer was too small; grow and retry. 00062 } while (len > buffer.capacity()); 00063 00064 buffer.set_size(len); 00065 SmallVector<char, MAX_PATH> result; 00066 if (windows::UTF16ToUTF8(buffer.begin(), buffer.size(), result)) 00067 return ""; 00068 00069 return std::string(result.data(), result.size()); 00070 } 00071 00072 static HANDLE RedirectIO(const StringRef *path, int fd, std::string* ErrMsg) { 00073 HANDLE h; 00074 if (path == 0) { 00075 if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd), 00076 GetCurrentProcess(), &h, 00077 0, TRUE, DUPLICATE_SAME_ACCESS)) 00078 return INVALID_HANDLE_VALUE; 00079 return h; 00080 } 00081 00082 std::string fname; 00083 if (path->empty()) 00084 fname = "NUL"; 00085 else 00086 fname = *path; 00087 00088 SECURITY_ATTRIBUTES sa; 00089 sa.nLength = sizeof(sa); 00090 sa.lpSecurityDescriptor = 0; 00091 sa.bInheritHandle = TRUE; 00092 00093 SmallVector<wchar_t, 128> fnameUnicode; 00094 if (windows::UTF8ToUTF16(fname, fnameUnicode)) 00095 return INVALID_HANDLE_VALUE; 00096 00097 h = CreateFileW(fnameUnicode.data(), fd ? GENERIC_WRITE : GENERIC_READ, 00098 FILE_SHARE_READ, &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS, 00099 FILE_ATTRIBUTE_NORMAL, NULL); 00100 if (h == INVALID_HANDLE_VALUE) { 00101 MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " + 00102 (fd ? "input: " : "output: ")); 00103 } 00104 00105 return h; 00106 } 00107 00108 /// ArgNeedsQuotes - Check whether argument needs to be quoted when calling 00109 /// CreateProcess. 00110 static bool ArgNeedsQuotes(const char *Str) { 00111 return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0; 00112 } 00113 00114 /// CountPrecedingBackslashes - Returns the number of backslashes preceding Cur 00115 /// in the C string Start. 00116 static unsigned int CountPrecedingBackslashes(const char *Start, 00117 const char *Cur) { 00118 unsigned int Count = 0; 00119 --Cur; 00120 while (Cur >= Start && *Cur == '\\') { 00121 ++Count; 00122 --Cur; 00123 } 00124 return Count; 00125 } 00126 00127 /// EscapePrecedingEscapes - Append a backslash to Dst for every backslash 00128 /// preceding Cur in the Start string. Assumes Dst has enough space. 00129 static char *EscapePrecedingEscapes(char *Dst, const char *Start, 00130 const char *Cur) { 00131 unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Cur); 00132 while (PrecedingEscapes > 0) { 00133 *Dst++ = '\\'; 00134 --PrecedingEscapes; 00135 } 00136 return Dst; 00137 } 00138 00139 /// ArgLenWithQuotes - Check whether argument needs to be quoted when calling 00140 /// CreateProcess and returns length of quoted arg with escaped quotes 00141 static unsigned int ArgLenWithQuotes(const char *Str) { 00142 const char *Start = Str; 00143 bool Quoted = ArgNeedsQuotes(Str); 00144 unsigned int len = Quoted ? 2 : 0; 00145 00146 while (*Str != '\0') { 00147 if (*Str == '\"') { 00148 // We need to add a backslash, but ensure that it isn't escaped. 00149 unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str); 00150 len += PrecedingEscapes + 1; 00151 } 00152 // Note that we *don't* need to escape runs of backslashes that don't 00153 // precede a double quote! See MSDN: 00154 // http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx 00155 00156 ++len; 00157 ++Str; 00158 } 00159 00160 if (Quoted) { 00161 // Make sure the closing quote doesn't get escaped by a trailing backslash. 00162 unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str); 00163 len += PrecedingEscapes + 1; 00164 } 00165 00166 return len; 00167 } 00168 00169 } 00170 00171 static std::unique_ptr<char[]> flattenArgs(const char **args) { 00172 // First, determine the length of the command line. 00173 unsigned len = 0; 00174 for (unsigned i = 0; args[i]; i++) { 00175 len += ArgLenWithQuotes(args[i]) + 1; 00176 } 00177 00178 // Now build the command line. 00179 std::unique_ptr<char[]> command(new char[len+1]); 00180 char *p = command.get(); 00181 00182 for (unsigned i = 0; args[i]; i++) { 00183 const char *arg = args[i]; 00184 const char *start = arg; 00185 00186 bool needsQuoting = ArgNeedsQuotes(arg); 00187 if (needsQuoting) 00188 *p++ = '"'; 00189 00190 while (*arg != '\0') { 00191 if (*arg == '\"') { 00192 // Escape all preceding escapes (if any), and then escape the quote. 00193 p = EscapePrecedingEscapes(p, start, arg); 00194 *p++ = '\\'; 00195 } 00196 00197 *p++ = *arg++; 00198 } 00199 00200 if (needsQuoting) { 00201 // Make sure our quote doesn't get escaped by a trailing backslash. 00202 p = EscapePrecedingEscapes(p, start, arg); 00203 *p++ = '"'; 00204 } 00205 *p++ = ' '; 00206 } 00207 00208 *p = 0; 00209 return command; 00210 } 00211 00212 static bool Execute(ProcessInfo &PI, StringRef Program, const char **args, 00213 const char **envp, const StringRef **redirects, 00214 unsigned memoryLimit, std::string *ErrMsg) { 00215 if (!sys::fs::can_execute(Program)) { 00216 if (ErrMsg) 00217 *ErrMsg = "program not executable"; 00218 return false; 00219 } 00220 00221 // Windows wants a command line, not an array of args, to pass to the new 00222 // process. We have to concatenate them all, while quoting the args that 00223 // have embedded spaces (or are empty). 00224 std::unique_ptr<char[]> command = flattenArgs(args); 00225 00226 // The pointer to the environment block for the new process. 00227 std::vector<wchar_t> EnvBlock; 00228 00229 if (envp) { 00230 // An environment block consists of a null-terminated block of 00231 // null-terminated strings. Convert the array of environment variables to 00232 // an environment block by concatenating them. 00233 for (unsigned i = 0; envp[i]; ++i) { 00234 SmallVector<wchar_t, MAX_PATH> EnvString; 00235 if (std::error_code ec = windows::UTF8ToUTF16(envp[i], EnvString)) { 00236 SetLastError(ec.value()); 00237 MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16"); 00238 return false; 00239 } 00240 00241 EnvBlock.insert(EnvBlock.end(), EnvString.begin(), EnvString.end()); 00242 EnvBlock.push_back(0); 00243 } 00244 EnvBlock.push_back(0); 00245 } 00246 00247 // Create a child process. 00248 STARTUPINFOW si; 00249 memset(&si, 0, sizeof(si)); 00250 si.cb = sizeof(si); 00251 si.hStdInput = INVALID_HANDLE_VALUE; 00252 si.hStdOutput = INVALID_HANDLE_VALUE; 00253 si.hStdError = INVALID_HANDLE_VALUE; 00254 00255 if (redirects) { 00256 si.dwFlags = STARTF_USESTDHANDLES; 00257 00258 si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg); 00259 if (si.hStdInput == INVALID_HANDLE_VALUE) { 00260 MakeErrMsg(ErrMsg, "can't redirect stdin"); 00261 return false; 00262 } 00263 si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg); 00264 if (si.hStdOutput == INVALID_HANDLE_VALUE) { 00265 CloseHandle(si.hStdInput); 00266 MakeErrMsg(ErrMsg, "can't redirect stdout"); 00267 return false; 00268 } 00269 if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) { 00270 // If stdout and stderr should go to the same place, redirect stderr 00271 // to the handle already open for stdout. 00272 if (!DuplicateHandle(GetCurrentProcess(), si.hStdOutput, 00273 GetCurrentProcess(), &si.hStdError, 00274 0, TRUE, DUPLICATE_SAME_ACCESS)) { 00275 CloseHandle(si.hStdInput); 00276 CloseHandle(si.hStdOutput); 00277 MakeErrMsg(ErrMsg, "can't dup stderr to stdout"); 00278 return false; 00279 } 00280 } else { 00281 // Just redirect stderr 00282 si.hStdError = RedirectIO(redirects[2], 2, ErrMsg); 00283 if (si.hStdError == INVALID_HANDLE_VALUE) { 00284 CloseHandle(si.hStdInput); 00285 CloseHandle(si.hStdOutput); 00286 MakeErrMsg(ErrMsg, "can't redirect stderr"); 00287 return false; 00288 } 00289 } 00290 } 00291 00292 PROCESS_INFORMATION pi; 00293 memset(&pi, 0, sizeof(pi)); 00294 00295 fflush(stdout); 00296 fflush(stderr); 00297 00298 SmallVector<wchar_t, MAX_PATH> ProgramUtf16; 00299 if (std::error_code ec = windows::UTF8ToUTF16(Program, ProgramUtf16)) { 00300 SetLastError(ec.value()); 00301 MakeErrMsg(ErrMsg, 00302 std::string("Unable to convert application name to UTF-16")); 00303 return false; 00304 } 00305 00306 SmallVector<wchar_t, MAX_PATH> CommandUtf16; 00307 if (std::error_code ec = windows::UTF8ToUTF16(command.get(), CommandUtf16)) { 00308 SetLastError(ec.value()); 00309 MakeErrMsg(ErrMsg, 00310 std::string("Unable to convert command-line to UTF-16")); 00311 return false; 00312 } 00313 00314 BOOL rc = CreateProcessW(ProgramUtf16.data(), CommandUtf16.data(), 0, 0, 00315 TRUE, CREATE_UNICODE_ENVIRONMENT, 00316 EnvBlock.empty() ? 0 : EnvBlock.data(), 0, &si, 00317 &pi); 00318 DWORD err = GetLastError(); 00319 00320 // Regardless of whether the process got created or not, we are done with 00321 // the handles we created for it to inherit. 00322 CloseHandle(si.hStdInput); 00323 CloseHandle(si.hStdOutput); 00324 CloseHandle(si.hStdError); 00325 00326 // Now return an error if the process didn't get created. 00327 if (!rc) { 00328 SetLastError(err); 00329 MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") + 00330 Program.str() + "'"); 00331 return false; 00332 } 00333 00334 PI.Pid = pi.dwProcessId; 00335 PI.ProcessHandle = pi.hProcess; 00336 00337 // Make sure these get closed no matter what. 00338 ScopedCommonHandle hThread(pi.hThread); 00339 00340 // Assign the process to a job if a memory limit is defined. 00341 ScopedJobHandle hJob; 00342 if (memoryLimit != 0) { 00343 hJob = CreateJobObjectW(0, 0); 00344 bool success = false; 00345 if (hJob) { 00346 JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli; 00347 memset(&jeli, 0, sizeof(jeli)); 00348 jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY; 00349 jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576; 00350 if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, 00351 &jeli, sizeof(jeli))) { 00352 if (AssignProcessToJobObject(hJob, pi.hProcess)) 00353 success = true; 00354 } 00355 } 00356 if (!success) { 00357 SetLastError(GetLastError()); 00358 MakeErrMsg(ErrMsg, std::string("Unable to set memory limit")); 00359 TerminateProcess(pi.hProcess, 1); 00360 WaitForSingleObject(pi.hProcess, INFINITE); 00361 return false; 00362 } 00363 } 00364 00365 return true; 00366 } 00367 00368 namespace llvm { 00369 ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, 00370 bool WaitUntilChildTerminates, std::string *ErrMsg) { 00371 assert(PI.Pid && "invalid pid to wait on, process not started?"); 00372 assert(PI.ProcessHandle && 00373 "invalid process handle to wait on, process not started?"); 00374 DWORD milliSecondsToWait = 0; 00375 if (WaitUntilChildTerminates) 00376 milliSecondsToWait = INFINITE; 00377 else if (SecondsToWait > 0) 00378 milliSecondsToWait = SecondsToWait * 1000; 00379 00380 ProcessInfo WaitResult = PI; 00381 DWORD WaitStatus = WaitForSingleObject(PI.ProcessHandle, milliSecondsToWait); 00382 if (WaitStatus == WAIT_TIMEOUT) { 00383 if (SecondsToWait) { 00384 if (!TerminateProcess(PI.ProcessHandle, 1)) { 00385 if (ErrMsg) 00386 MakeErrMsg(ErrMsg, "Failed to terminate timed-out program."); 00387 00388 // -2 indicates a crash or timeout as opposed to failure to execute. 00389 WaitResult.ReturnCode = -2; 00390 CloseHandle(PI.ProcessHandle); 00391 return WaitResult; 00392 } 00393 WaitForSingleObject(PI.ProcessHandle, INFINITE); 00394 CloseHandle(PI.ProcessHandle); 00395 } else { 00396 // Non-blocking wait. 00397 return ProcessInfo(); 00398 } 00399 } 00400 00401 // Get its exit status. 00402 DWORD status; 00403 BOOL rc = GetExitCodeProcess(PI.ProcessHandle, &status); 00404 DWORD err = GetLastError(); 00405 CloseHandle(PI.ProcessHandle); 00406 00407 if (!rc) { 00408 SetLastError(err); 00409 if (ErrMsg) 00410 MakeErrMsg(ErrMsg, "Failed getting status for program."); 00411 00412 // -2 indicates a crash or timeout as opposed to failure to execute. 00413 WaitResult.ReturnCode = -2; 00414 return WaitResult; 00415 } 00416 00417 if (!status) 00418 return WaitResult; 00419 00420 // Pass 10(Warning) and 11(Error) to the callee as negative value. 00421 if ((status & 0xBFFF0000U) == 0x80000000U) 00422 WaitResult.ReturnCode = static_cast<int>(status); 00423 else if (status & 0xFF) 00424 WaitResult.ReturnCode = status & 0x7FFFFFFF; 00425 else 00426 WaitResult.ReturnCode = 1; 00427 00428 return WaitResult; 00429 } 00430 00431 std::error_code sys::ChangeStdinToBinary(){ 00432 int result = _setmode( _fileno(stdin), _O_BINARY ); 00433 if (result == -1) 00434 return std::error_code(errno, std::generic_category()); 00435 return std::error_code(); 00436 } 00437 00438 std::error_code sys::ChangeStdoutToBinary(){ 00439 int result = _setmode( _fileno(stdout), _O_BINARY ); 00440 if (result == -1) 00441 return std::error_code(errno, std::generic_category()); 00442 return std::error_code(); 00443 } 00444 00445 std::error_code 00446 llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents, 00447 WindowsEncodingMethod Encoding) { 00448 std::error_code EC; 00449 llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text); 00450 if (EC) 00451 return EC; 00452 00453 if (Encoding == WEM_UTF8) { 00454 OS << Contents; 00455 } else if (Encoding == WEM_CurrentCodePage) { 00456 SmallVector<wchar_t, 1> ArgsUTF16; 00457 SmallVector<char, 1> ArgsCurCP; 00458 00459 if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16))) 00460 return EC; 00461 00462 if ((EC = windows::UTF16ToCurCP( 00463 ArgsUTF16.data(), ArgsUTF16.size(), ArgsCurCP))) 00464 return EC; 00465 00466 OS.write(ArgsCurCP.data(), ArgsCurCP.size()); 00467 } else if (Encoding == WEM_UTF16) { 00468 SmallVector<wchar_t, 1> ArgsUTF16; 00469 00470 if ((EC = windows::UTF8ToUTF16(Contents, ArgsUTF16))) 00471 return EC; 00472 00473 // Endianness guessing 00474 char BOM[2]; 00475 uint16_t src = UNI_UTF16_BYTE_ORDER_MARK_NATIVE; 00476 memcpy(BOM, &src, 2); 00477 OS.write(BOM, 2); 00478 OS.write((char *)ArgsUTF16.data(), ArgsUTF16.size() << 1); 00479 } else { 00480 llvm_unreachable("Unknown encoding"); 00481 } 00482 00483 if (OS.has_error()) 00484 return std::make_error_code(std::errc::io_error); 00485 00486 return EC; 00487 } 00488 00489 bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) { 00490 // The documented max length of the command line passed to CreateProcess. 00491 static const size_t MaxCommandStringLength = 32768; 00492 size_t ArgLength = 0; 00493 for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end(); 00494 I != E; ++I) { 00495 // Account for the trailing space for every arg but the last one and the 00496 // trailing NULL of the last argument. 00497 ArgLength += ArgLenWithQuotes(*I) + 1; 00498 if (ArgLength > MaxCommandStringLength) { 00499 return false; 00500 } 00501 } 00502 return true; 00503 } 00504 }