diff options
author | Shih-wei Liao <sliao@google.com> | 2012-08-03 00:11:18 -0700 |
---|---|---|
committer | Shih-wei Liao <sliao@google.com> | 2012-08-03 00:11:18 -0700 |
commit | 7744acd1ab73b3eec6f1449f47083abe3fb1b527 (patch) | |
tree | 17ef28b6d1034fdea7f42a19bebe7ad834901d62 /lib/Support/Unix | |
parent | 4a05ed708aed4c7a099d924ed3feb604d3e44074 (diff) | |
parent | a94d6e87c4c49f2e81b01d66d8bfb591277f8f96 (diff) | |
download | external_llvm-7744acd1ab73b3eec6f1449f47083abe3fb1b527.zip external_llvm-7744acd1ab73b3eec6f1449f47083abe3fb1b527.tar.gz external_llvm-7744acd1ab73b3eec6f1449f47083abe3fb1b527.tar.bz2 |
Merge with LLVM upstream r160668 (Jul 24th 2012)
Conflicts:
include/llvm/Support/ELF.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/Support/Memory.cpp
lib/Transforms/Instrumentation/AddressSanitizer.cpp
Change-Id: Iddd658cf2eadc7165b2805b446d31af2c5c9917f
Diffstat (limited to 'lib/Support/Unix')
-rw-r--r-- | lib/Support/Unix/Path.inc | 3 | ||||
-rw-r--r-- | lib/Support/Unix/PathV2.inc | 128 | ||||
-rw-r--r-- | lib/Support/Unix/Process.inc | 46 | ||||
-rw-r--r-- | lib/Support/Unix/Signals.inc | 50 | ||||
-rw-r--r-- | lib/Support/Unix/Unix.h | 10 |
5 files changed, 173 insertions, 64 deletions
diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index ddc1e0f..b41390a 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -884,7 +884,8 @@ const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) { } void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) { - ::munmap((void*)BasePtr, FileSize); + const void *Addr = static_cast<const void *>(BasePtr); + ::munmap(const_cast<void *>(Addr), FileSize); } } // end llvm namespace diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index 7d259a3..93ccd1a 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -17,12 +17,16 @@ //===----------------------------------------------------------------------===// #include "Unix.h" +#include "llvm/Support/Process.h" #if HAVE_SYS_STAT_H #include <sys/stat.h> #endif #if HAVE_FCNTL_H #include <fcntl.h> #endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif #if HAVE_DIRENT_H # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) @@ -274,8 +278,7 @@ error_code exists(const Twine &path, bool &result) { SmallString<128> path_storage; StringRef p = path.toNullTerminatedStringRef(path_storage); - struct stat status; - if (::stat(p.begin(), &status) == -1) { + if (::access(p.begin(), F_OK) == -1) { if (errno != errc::no_such_file_or_directory) return error_code(errno, system_category()); result = false; @@ -287,8 +290,8 @@ error_code exists(const Twine &path, bool &result) { bool equivalent(file_status A, file_status B) { assert(status_known(A) && status_known(B)); - return A.st_dev == B.st_dev && - A.st_ino == B.st_ino; + return A.fs_st_dev == B.fs_st_dev && + A.fs_st_ino == B.fs_st_ino; } error_code equivalent(const Twine &A, const Twine &B, bool &result) { @@ -327,30 +330,62 @@ error_code status(const Twine &path, file_status &result) { return ec; } + perms prms = static_cast<perms>(status.st_mode & perms_mask); + if (S_ISDIR(status.st_mode)) - result = file_status(file_type::directory_file); + result = file_status(file_type::directory_file, prms); else if (S_ISREG(status.st_mode)) - result = file_status(file_type::regular_file); + result = file_status(file_type::regular_file, prms); else if (S_ISBLK(status.st_mode)) - result = file_status(file_type::block_file); + result = file_status(file_type::block_file, prms); else if (S_ISCHR(status.st_mode)) - result = file_status(file_type::character_file); + result = file_status(file_type::character_file, prms); else if (S_ISFIFO(status.st_mode)) - result = file_status(file_type::fifo_file); + result = file_status(file_type::fifo_file, prms); else if (S_ISSOCK(status.st_mode)) - result = file_status(file_type::socket_file); + result = file_status(file_type::socket_file, prms); else - result = file_status(file_type::type_unknown); + result = file_status(file_type::type_unknown, prms); + + result.fs_st_dev = status.st_dev; + result.fs_st_ino = status.st_ino; + + return error_code::success(); +} + +// Modifies permissions on a file. +error_code permissions(const Twine &path, perms prms) { + if ((prms & add_perms) && (prms & remove_perms)) + llvm_unreachable("add_perms and remove_perms are mutually exclusive"); - result.st_dev = status.st_dev; - result.st_ino = status.st_ino; + // Get current permissions + file_status info; + if (error_code ec = status(path, info)) { + return ec; + } + + // Set updated permissions. + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + perms permsToSet; + if (prms & add_perms) { + permsToSet = (info.permissions() | prms) & perms_mask; + } else if (prms & remove_perms) { + permsToSet = (info.permissions() & ~prms) & perms_mask; + } else { + permsToSet = prms & perms_mask; + } + if (::chmod(p.begin(), static_cast<mode_t>(permsToSet))) { + return error_code(errno, system_category()); + } return error_code::success(); } +// Since this is most often used for temporary files, mode defaults to 0600. error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl<char> &result_path, - bool makeAbsolute) { + SmallVectorImpl<char> &result_path, + bool makeAbsolute, unsigned mode) { SmallString<128> Model; model.toVector(Model); // Null terminate. @@ -367,37 +402,20 @@ error_code unique_file(const Twine &model, int &result_fd, } } - // Replace '%' with random chars. From here on, DO NOT modify model. It may be - // needed if the randomly chosen path already exists. - SmallString<128> RandomPath; - RandomPath.reserve(Model.size() + 1); - ::srand(::time(NULL)); + // From here on, DO NOT modify model. It may be needed if the randomly chosen + // path already exists. + SmallString<128> RandomPath = Model; retry_random_path: - // This is opened here instead of above to make it easier to track when to - // close it. Collisions should be rare enough for the possible extra syscalls - // not to matter. - FILE *RandomSource = ::fopen("/dev/urandom", "r"); - RandomPath.set_size(0); - for (SmallVectorImpl<char>::const_iterator i = Model.begin(), - e = Model.end(); i != e; ++i) { - if (*i == '%') { - char val = 0; - if (RandomSource) - val = fgetc(RandomSource); - else - val = ::rand(); - RandomPath.push_back("0123456789abcdef"[val & 15]); - } else - RandomPath.push_back(*i); + // Replace '%' with random chars. + for (unsigned i = 0, e = Model.size(); i != e; ++i) { + if (Model[i] == '%') + RandomPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; } - if (RandomSource) - ::fclose(RandomSource); - // Try to open + create the file. rety_open_create: - int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); + int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, mode); if (RandomFD == -1) { // If the file existed, try again, otherwise, error. if (errno == errc::file_exists) @@ -513,6 +531,36 @@ error_code get_magic(const Twine &path, uint32_t len, return error_code::success(); } +error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, + bool map_writable, void *&result) { + SmallString<128> path_storage; + StringRef name = path.toNullTerminatedStringRef(path_storage); + int oflags = map_writable ? O_RDWR : O_RDONLY; + int ofd = ::open(name.begin(), oflags); + if ( ofd == -1 ) + return error_code(errno, system_category()); + AutoFD fd(ofd); + int flags = map_writable ? MAP_SHARED : MAP_PRIVATE; + int prot = map_writable ? (PROT_READ|PROT_WRITE) : PROT_READ; +#ifdef MAP_FILE + flags |= MAP_FILE; +#endif + result = ::mmap(0, size, prot, flags, fd, file_offset); + if (result == MAP_FAILED) { + return error_code(errno, system_category()); + } + + return error_code::success(); +} + +error_code unmap_file_pages(void *base, size_t size) { + if ( ::munmap(base, size) == -1 ) + return error_code(errno, system_category()); + + return error_code::success(); +} + + } // end namespace fs } // end namespace sys } // end namespace llvm diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index f640462..174112e 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "Unix.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/Support/TimeValue.h" #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif @@ -247,16 +249,18 @@ static bool terminalHasColors() { return false; } +bool Process::FileDescriptorHasColors(int fd) { + // A file descriptor has colors if it is displayed and the terminal has + // colors. + return FileDescriptorIsDisplayed(fd) && terminalHasColors(); +} + bool Process::StandardOutHasColors() { - if (!StandardOutIsDisplayed()) - return false; - return terminalHasColors(); + return FileDescriptorHasColors(STDOUT_FILENO); } bool Process::StandardErrHasColors() { - if (!StandardErrIsDisplayed()) - return false; - return terminalHasColors(); + return FileDescriptorHasColors(STDERR_FILENO); } bool Process::ColorNeedsFlush() { @@ -297,3 +301,33 @@ const char *Process::OutputReverse() { const char *Process::ResetColor() { return "\033[0m"; } + +#if !defined(HAVE_ARC4RANDOM) +static unsigned GetRandomNumberSeed() { + // Attempt to get the initial seed from /dev/urandom, if possible. + if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) { + unsigned seed; + int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource); + ::fclose(RandomSource); + + // Return the seed if the read was successful. + if (count == 1) + return seed; + } + + // Otherwise, swizzle the current time and the process ID to form a reasonable + // seed. + TimeValue Now = llvm::TimeValue::now(); + return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid()); +} +#endif + +unsigned llvm::sys::Process::GetRandomNumber() { +#if defined(HAVE_ARC4RANDOM) + return arc4random(); +#else + static int x = (::srand(GetRandomNumberSeed()), 0); + (void)x; + return ::rand(); +#endif +} diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc index f5454cf..1d667ab 100644 --- a/lib/Support/Unix/Signals.inc +++ b/lib/Support/Unix/Signals.inc @@ -15,6 +15,7 @@ #include "Unix.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Mutex.h" +#include <string> #include <vector> #include <algorithm> #if HAVE_EXECINFO_H @@ -43,7 +44,7 @@ static SmartMutex<true> SignalsMutex; /// InterruptFunction - The function to call if ctrl-c is pressed. static void (*InterruptFunction)() = 0; -static std::vector<sys::Path> FilesToRemove; +static std::vector<std::string> FilesToRemove; static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun; // IntSigs - Signals that may interrupt the program at any time. @@ -117,10 +118,20 @@ static void UnregisterHandlers() { /// RemoveFilesToRemove - Process the FilesToRemove list. This function /// should be called with the SignalsMutex lock held. +/// NB: This must be an async signal safe function. It cannot allocate or free +/// memory, even in debug builds. static void RemoveFilesToRemove() { - while (!FilesToRemove.empty()) { - FilesToRemove.back().eraseFromDisk(true); - FilesToRemove.pop_back(); + // Note: avoid iterators in case of debug iterators that allocate or release + // memory. + for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) { + // Note that we don't want to use any external code here, and we don't care + // about errors. We're going to try as hard as we can as often as we need + // to to make these files go away. If these aren't files, too bad. + // + // We do however rely on a std::string implementation for which repeated + // calls to 'c_str()' don't allocate memory. We pre-call 'c_str()' on all + // of these strings to try to ensure this is safe. + unlink(FilesToRemove[i].c_str()); } } @@ -178,7 +189,19 @@ void llvm::sys::SetInterruptFunction(void (*IF)()) { bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename, std::string* ErrMsg) { SignalsMutex.acquire(); - FilesToRemove.push_back(Filename); + std::string *OldPtr = FilesToRemove.empty() ? 0 : &FilesToRemove[0]; + FilesToRemove.push_back(Filename.str()); + + // We want to call 'c_str()' on every std::string in this vector so that if + // the underlying implementation requires a re-allocation, it happens here + // rather than inside of the signal handler. If we see the vector grow, we + // have to call it on every entry. If it remains in place, we only need to + // call it on the latest one. + if (OldPtr == &FilesToRemove[0]) + FilesToRemove.back().c_str(); + else + for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) + FilesToRemove[i].c_str(); SignalsMutex.release(); @@ -189,10 +212,19 @@ bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename, // DontRemoveFileOnSignal - The public API void llvm::sys::DontRemoveFileOnSignal(const sys::Path &Filename) { SignalsMutex.acquire(); - std::vector<sys::Path>::reverse_iterator I = - std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename); - if (I != FilesToRemove.rend()) - FilesToRemove.erase(I.base()-1); + std::vector<std::string>::reverse_iterator RI = + std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename.str()); + std::vector<std::string>::iterator I = FilesToRemove.end(); + if (RI != FilesToRemove.rend()) + I = FilesToRemove.erase(RI.base()-1); + + // We need to call c_str() on every element which would have been moved by + // the erase. These elements, in a C++98 implementation where c_str() + // requires a reallocation on the first call may have had the call to c_str() + // made on insertion become invalid by being copied down an element. + for (std::vector<std::string>::iterator E = FilesToRemove.end(); I != E; ++I) + I->c_str(); + SignalsMutex.release(); } diff --git a/lib/Support/Unix/Unix.h b/lib/Support/Unix/Unix.h index b7be311..361f297 100644 --- a/lib/Support/Unix/Unix.h +++ b/lib/Support/Unix/Unix.h @@ -44,16 +44,10 @@ #include <assert.h> #endif -#ifdef TIME_WITH_SYS_TIME +#ifdef HAVE_SYS_TIME_H # include <sys/time.h> -# include <time.h> -#else -# ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -# else -# include <time.h> -# endif #endif +#include <time.h> #ifdef HAVE_SYS_WAIT_H # include <sys/wait.h> |