aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Support/Unix
diff options
context:
space:
mode:
authorShih-wei Liao <sliao@google.com>2012-08-03 00:11:18 -0700
committerShih-wei Liao <sliao@google.com>2012-08-03 00:11:18 -0700
commit7744acd1ab73b3eec6f1449f47083abe3fb1b527 (patch)
tree17ef28b6d1034fdea7f42a19bebe7ad834901d62 /lib/Support/Unix
parent4a05ed708aed4c7a099d924ed3feb604d3e44074 (diff)
parenta94d6e87c4c49f2e81b01d66d8bfb591277f8f96 (diff)
downloadexternal_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.inc3
-rw-r--r--lib/Support/Unix/PathV2.inc128
-rw-r--r--lib/Support/Unix/Process.inc46
-rw-r--r--lib/Support/Unix/Signals.inc50
-rw-r--r--lib/Support/Unix/Unix.h10
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>