LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

SystemUtils.cpp

Go to the documentation of this file.
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