LLVM API Documentation
00001 //===- SystemUtils.cpp - Utilities for low-level system tasks -------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains functions used to do a variety of low-level, often 00011 // system-specific, tasks. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #define _POSIX_MAPPED_FILES 00016 #include "llvm/Support/SystemUtils.h" 00017 #include "llvm/Config/fcntl.h" 00018 #include "llvm/Config/pagesize.h" 00019 #include "llvm/Config/unistd.h" 00020 #include "llvm/Config/windows.h" 00021 #include "llvm/Config/sys/mman.h" 00022 #include "llvm/Config/sys/stat.h" 00023 #include "llvm/Config/sys/types.h" 00024 #include "llvm/Config/sys/wait.h" 00025 #include <algorithm> 00026 #include <cerrno> 00027 #include <cstdlib> 00028 #include <fstream> 00029 #include <iostream> 00030 #include <signal.h> 00031 using namespace llvm; 00032 00033 /// isExecutableFile - This function returns true if the filename specified 00034 /// exists and is executable. 00035 /// 00036 bool llvm::isExecutableFile(const std::string &ExeFileName) { 00037 struct stat Buf; 00038 if (stat(ExeFileName.c_str(), &Buf)) 00039 return false; // Must not be executable! 00040 00041 if (!(Buf.st_mode & S_IFREG)) 00042 return false; // Not a regular file? 00043 00044 if (Buf.st_uid == getuid()) // Owner of file? 00045 return Buf.st_mode & S_IXUSR; 00046 else if (Buf.st_gid == getgid()) // In group of file? 00047 return Buf.st_mode & S_IXGRP; 00048 else // Unrelated to file? 00049 return Buf.st_mode & S_IXOTH; 00050 } 00051 00052 /// isStandardOutAConsole - Return true if we can tell that the standard output 00053 /// stream goes to a terminal window or console. 00054 bool llvm::isStandardOutAConsole() { 00055 #if HAVE_ISATTY 00056 return isatty(1); 00057 #endif 00058 // If we don't have isatty, just return false. 00059 return false; 00060 } 00061 00062 00063 /// FindExecutable - Find a named executable, giving the argv[0] of program 00064 /// being executed. This allows us to find another LLVM tool if it is built 00065 /// into the same directory, but that directory is neither the current 00066 /// directory, nor in the PATH. If the executable cannot be found, return an 00067 /// empty string. 00068 /// 00069 #undef FindExecutable // needed on windows :( 00070 std::string llvm::FindExecutable(const std::string &ExeName, 00071 const std::string &ProgramPath) { 00072 // First check the directory that bugpoint is in. We can do this if 00073 // BugPointPath contains at least one / character, indicating that it is a 00074 // relative path to bugpoint itself. 00075 // 00076 std::string Result = ProgramPath; 00077 while (!Result.empty() && Result[Result.size()-1] != '/') 00078 Result.erase(Result.size()-1, 1); 00079 00080 if (!Result.empty()) { 00081 Result += ExeName; 00082 if (isExecutableFile(Result)) return Result; // Found it? 00083 } 00084 00085 // Okay, if the path to the program didn't tell us anything, try using the 00086 // PATH environment variable. 00087 const char *PathStr = getenv("PATH"); 00088 if (PathStr == 0) return ""; 00089 00090 // Now we have a colon separated list of directories to search... try them... 00091 unsigned PathLen = strlen(PathStr); 00092 while (PathLen) { 00093 // Find the first colon... 00094 const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); 00095 00096 // Check to see if this first directory contains the executable... 00097 std::string FilePath = std::string(PathStr, Colon) + '/' + ExeName; 00098 if (isExecutableFile(FilePath)) 00099 return FilePath; // Found the executable! 00100 00101 // Nope it wasn't in this directory, check the next range! 00102 PathLen -= Colon-PathStr; 00103 PathStr = Colon; 00104 while (*PathStr == ':') { // Advance past colons 00105 PathStr++; 00106 PathLen--; 00107 } 00108 } 00109 00110 // If we fell out, we ran out of directories in PATH to search, return failure 00111 return ""; 00112 } 00113 00114 static void RedirectFD(const std::string &File, int FD) { 00115 if (File.empty()) return; // Noop 00116 00117 // Open the file 00118 int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); 00119 if (InFD == -1) { 00120 std::cerr << "Error opening file '" << File << "' for " 00121 << (FD == 0 ? "input" : "output") << "!\n"; 00122 exit(1); 00123 } 00124 00125 dup2(InFD, FD); // Install it as the requested FD 00126 close(InFD); // Close the original FD 00127 } 00128 00129 static bool Timeout = false; 00130 static void TimeOutHandler(int Sig) { 00131 Timeout = true; 00132 } 00133 00134 /// RunProgramWithTimeout - This function executes the specified program, with 00135 /// the specified null-terminated argument array, with the stdin/out/err fd's 00136 /// redirected, with a timeout specified by the last argument. This terminates 00137 /// the calling program if there is an error executing the specified program. 00138 /// It returns the return value of the program, or -1 if a timeout is detected. 00139 /// 00140 int llvm::RunProgramWithTimeout(const std::string &ProgramPath, 00141 const char **Args, 00142 const std::string &StdInFile, 00143 const std::string &StdOutFile, 00144 const std::string &StdErrFile, 00145 unsigned NumSeconds) { 00146 #ifdef HAVE_SYS_WAIT_H 00147 int Child = fork(); 00148 switch (Child) { 00149 case -1: 00150 std::cerr << "ERROR forking!\n"; 00151 exit(1); 00152 case 0: // Child 00153 RedirectFD(StdInFile, 0); // Redirect file descriptors... 00154 RedirectFD(StdOutFile, 1); 00155 if (StdOutFile != StdErrFile) 00156 RedirectFD(StdErrFile, 2); 00157 else 00158 dup2(1, 2); 00159 00160 execv(ProgramPath.c_str(), (char *const *)Args); 00161 std::cerr << "Error executing program: '" << ProgramPath; 00162 for (; *Args; ++Args) 00163 std::cerr << " " << *Args; 00164 std::cerr << "'\n"; 00165 exit(1); 00166 00167 default: break; 00168 } 00169 00170 // Make sure all output has been written while waiting 00171 std::cout << std::flush; 00172 00173 // Install a timeout handler. 00174 Timeout = false; 00175 struct sigaction Act, Old; 00176 Act.sa_sigaction = 0; 00177 Act.sa_handler = TimeOutHandler; 00178 sigemptyset(&Act.sa_mask); 00179 Act.sa_flags = 0; 00180 sigaction(SIGALRM, &Act, &Old); 00181 00182 // Set the timeout if one is set. 00183 if (NumSeconds) 00184 alarm(NumSeconds); 00185 00186 int Status; 00187 while (wait(&Status) != Child) 00188 if (errno == EINTR) { 00189 if (Timeout) { 00190 // Kill the child. 00191 kill(Child, SIGKILL); 00192 00193 if (wait(&Status) != Child) 00194 std::cerr << "Something funny happened waiting for the child!\n"; 00195 00196 alarm(0); 00197 sigaction(SIGALRM, &Old, 0); 00198 return -1; // Timeout detected 00199 } else { 00200 std::cerr << "Error waiting for child process!\n"; 00201 exit(1); 00202 } 00203 } 00204 00205 alarm(0); 00206 sigaction(SIGALRM, &Old, 0); 00207 return Status; 00208 00209 #else 00210 std::cerr << "RunProgramWithTimeout not implemented on this platform!\n"; 00211 return -1; 00212 #endif 00213 } 00214 00215 00216 // ExecWait - executes a program with the specified arguments and environment. 00217 // It then waits for the progarm to termiante and then returns to the caller. 00218 // 00219 // Inputs: 00220 // argv - The arguments to the program as an array of C strings. The first 00221 // argument should be the name of the program to execute, and the 00222 // last argument should be a pointer to NULL. 00223 // 00224 // envp - The environment passes to the program as an array of C strings in 00225 // the form of "name=value" pairs. The last element should be a 00226 // pointer to NULL. 00227 // 00228 // Outputs: 00229 // None. 00230 // 00231 // Return value: 00232 // 0 - No errors. 00233 // 1 - The program could not be executed. 00234 // 1 - The program returned a non-zero exit status. 00235 // 1 - The program terminated abnormally. 00236 // 00237 // Notes: 00238 // The program will inherit the stdin, stdout, and stderr file descriptors 00239 // as well as other various configuration settings (umask). 00240 // 00241 // This function should not print anything to stdout/stderr on its own. It is 00242 // a generic library function. The caller or executed program should report 00243 // errors in the way it sees fit. 00244 // 00245 // This function does not use $PATH to find programs. 00246 // 00247 int llvm::ExecWait(const char * const old_argv[], 00248 const char * const old_envp[]) { 00249 #ifdef HAVE_SYS_WAIT_H 00250 // Create local versions of the parameters that can be passed into execve() 00251 // without creating const problems. 00252 char ** const argv = (char ** const) old_argv; 00253 char ** const envp = (char ** const) old_envp; 00254 00255 // Create a child process. 00256 switch (fork()) { 00257 // An error occured: Return to the caller. 00258 case -1: 00259 return 1; 00260 break; 00261 00262 // Child process: Execute the program. 00263 case 0: 00264 execve (argv[0], argv, envp); 00265 // If the execve() failed, we should exit and let the parent pick up 00266 // our non-zero exit status. 00267 exit (1); 00268 00269 // Parent process: Break out of the switch to do our processing. 00270 default: 00271 break; 00272 } 00273 00274 // Parent process: Wait for the child process to terminate. 00275 int status; 00276 if ((wait (&status)) == -1) 00277 return 1; 00278 00279 // If the program exited normally with a zero exit status, return success! 00280 if (WIFEXITED (status) && (WEXITSTATUS(status) == 0)) 00281 return 0; 00282 #else 00283 std::cerr << "llvm::ExecWait not implemented on this platform!\n"; 00284 #endif 00285 00286 // Otherwise, return failure. 00287 return 1; 00288 } 00289 00290 /// AllocateRWXMemory - Allocate a slab of memory with read/write/execute 00291 /// permissions. This is typically used for JIT applications where we want 00292 /// to emit code to the memory then jump to it. Getting this type of memory 00293 /// is very OS specific. 00294 /// 00295 void *llvm::AllocateRWXMemory(unsigned NumBytes) { 00296 if (NumBytes == 0) return 0; 00297 00298 #if defined(HAVE_WINDOWS_H) 00299 // On windows we use VirtualAlloc. 00300 void *P = VirtualAlloc(0, NumBytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 00301 if (P == 0) { 00302 std::cerr << "Error allocating executable memory!\n"; 00303 abort(); 00304 } 00305 return P; 00306 00307 #elif defined(HAVE_MMAP) 00308 static const long pageSize = GetPageSize(); 00309 unsigned NumPages = (NumBytes+pageSize-1)/pageSize; 00310 00311 /* FIXME: This should use the proper autoconf flags */ 00312 #if defined(i386) || defined(__i386__) || defined(__x86__) 00313 /* Linux and *BSD tend to have these flags named differently. */ 00314 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) 00315 # define MAP_ANONYMOUS MAP_ANON 00316 #endif /* defined(MAP_ANON) && !defined(MAP_ANONYMOUS) */ 00317 #elif defined(sparc) || defined(__sparc__) || defined(__sparcv9) 00318 /* nothing */ 00319 #else 00320 std::cerr << "This architecture has an unknown MMAP implementation!\n"; 00321 abort(); 00322 return 0; 00323 #endif 00324 00325 int fd = -1; 00326 #if defined(__linux__) 00327 fd = 0; 00328 #endif 00329 00330 unsigned mmapFlags = MAP_PRIVATE|MAP_ANONYMOUS; 00331 #ifdef MAP_NORESERVE 00332 mmapFlags |= MAP_NORESERVE; 00333 #endif 00334 00335 void *pa = mmap(0, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, 00336 mmapFlags, fd, 0); 00337 if (pa == MAP_FAILED) { 00338 perror("mmap"); 00339 abort(); 00340 } 00341 return pa; 00342 #else 00343 std::cerr << "Do not know how to allocate mem for the JIT without mmap!\n"; 00344 abort(); 00345 return 0; 00346 #endif 00347 } 00348 00349