diff options
Diffstat (limited to 'contrib/llvm/lib/Support/Unix')
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Memory.inc | 15 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Path.inc | 120 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Process.inc | 13 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Program.inc | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Signals.inc | 151 | ||||
-rw-r--r-- | contrib/llvm/lib/Support/Unix/Unix.h | 13 |
6 files changed, 111 insertions, 208 deletions
diff --git a/contrib/llvm/lib/Support/Unix/Memory.inc b/contrib/llvm/lib/Support/Unix/Memory.inc index c421ee84c2b7..d70319168b84 100644 --- a/contrib/llvm/lib/Support/Unix/Memory.inc +++ b/contrib/llvm/lib/Support/Unix/Memory.inc @@ -50,9 +50,8 @@ int getPosixProtectionFlags(unsigned Flags) { return PROT_READ | PROT_WRITE; case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC: return PROT_READ | PROT_EXEC; - case llvm::sys::Memory::MF_READ | - llvm::sys::Memory::MF_WRITE | - llvm::sys::Memory::MF_EXEC: + case llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE | + llvm::sys::Memory::MF_EXEC: return PROT_READ | PROT_WRITE | PROT_EXEC; case llvm::sys::Memory::MF_EXEC: #if defined(__FreeBSD__) @@ -153,6 +152,7 @@ Memory::releaseMappedMemory(MemoryBlock &M) { std::error_code Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { + static const size_t PageSize = Process::getPageSize(); if (M.Address == nullptr || M.Size == 0) return std::error_code(); @@ -161,7 +161,7 @@ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) { int Protect = getPosixProtectionFlags(Flags); - int Result = ::mprotect(M.Address, M.Size, Protect); + int Result = ::mprotect((void*)((uintptr_t)M.Address & ~(PageSize-1)), PageSize*((M.Size+PageSize-1)/PageSize), Protect); if (Result != 0) return std::error_code(errno, std::generic_category()); @@ -181,7 +181,7 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, std::string *ErrMsg) { if (NumBytes == 0) return MemoryBlock(); - size_t PageSize = Process::getPageSize(); + static const size_t PageSize = Process::getPageSize(); size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; @@ -265,15 +265,12 @@ bool Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) { } bool Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { -#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) if (M.Address == 0 || M.Size == 0) return false; Memory::InvalidateInstructionCache(M.Address, M.Size); +#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__)) kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); return KERN_SUCCESS == kr; -#elif defined(__arm__) || defined(__aarch64__) - Memory::InvalidateInstructionCache(M.Address, M.Size); - return true; #else return true; #endif diff --git a/contrib/llvm/lib/Support/Unix/Path.inc b/contrib/llvm/lib/Support/Unix/Path.inc index 973d010dcac1..d85c37ab3bfa 100644 --- a/contrib/llvm/lib/Support/Unix/Path.inc +++ b/contrib/llvm/lib/Support/Unix/Path.inc @@ -75,12 +75,12 @@ test_dir(char ret[PATH_MAX], const char *dir, const char *bin) char fullpath[PATH_MAX]; snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); - if (realpath(fullpath, ret) == NULL) - return (1); + if (!realpath(fullpath, ret)) + return 1; if (stat(fullpath, &sb) != 0) - return (1); + return 1; - return (0); + return 0; } static char * @@ -91,34 +91,34 @@ getprogpath(char ret[PATH_MAX], const char *bin) /* First approach: absolute path. */ if (bin[0] == '/') { if (test_dir(ret, "/", bin) == 0) - return (ret); - return (NULL); + return ret; + return nullptr; } /* Second approach: relative path. */ - if (strchr(bin, '/') != NULL) { + if (strchr(bin, '/')) { char cwd[PATH_MAX]; - if (getcwd(cwd, PATH_MAX) == NULL) - return (NULL); + if (!getcwd(cwd, PATH_MAX)) + return nullptr; if (test_dir(ret, cwd, bin) == 0) - return (ret); - return (NULL); + return ret; + return nullptr; } /* Third approach: $PATH */ - if ((pv = getenv("PATH")) == NULL) - return (NULL); + if ((pv = getenv("PATH")) == nullptr) + return nullptr; s = pv = strdup(pv); - if (pv == NULL) - return (NULL); - while ((t = strsep(&s, ":")) != NULL) { + if (!pv) + return nullptr; + while ((t = strsep(&s, ":")) != nullptr) { if (test_dir(ret, t, bin) == 0) { free(pv); - return (ret); + return ret; } } free(pv); - return (NULL); + return nullptr; } #endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ @@ -153,8 +153,8 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) { return std::string(exe_path, len); } else { // Fall back to the classical detection. - if (getprogpath(exe_path, argv0) != NULL) - return exe_path; + if (getprogpath(exe_path, argv0)) + return exe_path; } #elif defined(HAVE_DLFCN_H) // Use dladdr to get executable path if available. @@ -219,11 +219,12 @@ std::error_code current_path(SmallVectorImpl<char> &result) { return std::error_code(); } -std::error_code create_directory(const Twine &path, bool IgnoreExisting) { +std::error_code create_directory(const Twine &path, bool IgnoreExisting, + perms Perms) { SmallString<128> path_storage; StringRef p = path.toNullTerminatedStringRef(path_storage); - if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) { + if (::mkdir(p.begin(), Perms) == -1) { if (errno != EEXIST || !IgnoreExisting) return std::error_code(errno, std::generic_category()); } @@ -324,6 +325,10 @@ std::error_code access(const Twine &Path, AccessMode Mode) { return std::error_code(); } +bool can_execute(const Twine &Path) { + return !access(Path, AccessMode::Execute); +} + bool equivalent(file_status A, file_status B) { assert(status_known(A) && status_known(B)); return A.fs_st_dev == B.fs_st_dev && @@ -555,6 +560,54 @@ bool home_directory(SmallVectorImpl<char> &result) { return false; } +static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) { + #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) + // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. + // macros defined in <unistd.h> on darwin >= 9 + int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR + : _CS_DARWIN_USER_CACHE_DIR; + size_t ConfLen = confstr(ConfName, nullptr, 0); + if (ConfLen > 0) { + do { + Result.resize(ConfLen); + ConfLen = confstr(ConfName, Result.data(), Result.size()); + } while (ConfLen > 0 && ConfLen != Result.size()); + + if (ConfLen > 0) { + assert(Result.back() == 0); + Result.pop_back(); + return true; + } + + Result.clear(); + } + #endif + return false; +} + +static bool getUserCacheDir(SmallVectorImpl<char> &Result) { + // First try using XDS_CACHE_HOME env variable, + // as specified in XDG Base Directory Specification at + // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + if (const char *XdsCacheDir = std::getenv("XDS_CACHE_HOME")) { + Result.clear(); + Result.append(XdsCacheDir, XdsCacheDir + strlen(XdsCacheDir)); + return true; + } + + // Try Darwin configuration query + if (getDarwinConfDir(false, Result)) + return true; + + // Use "$HOME/.cache" if $HOME is available + if (home_directory(Result)) { + append(Result, ".cache"); + return true; + } + + return false; +} + static const char *getEnvTempDir() { // Check whether the temporary directory is specified by an environment // variable. @@ -589,27 +642,8 @@ void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { } } -#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) - // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. - // macros defined in <unistd.h> on darwin >= 9 - int ConfName = ErasedOnReboot? _CS_DARWIN_USER_TEMP_DIR - : _CS_DARWIN_USER_CACHE_DIR; - size_t ConfLen = confstr(ConfName, nullptr, 0); - if (ConfLen > 0) { - do { - Result.resize(ConfLen); - ConfLen = confstr(ConfName, Result.data(), Result.size()); - } while (ConfLen > 0 && ConfLen != Result.size()); - - if (ConfLen > 0) { - assert(Result.back() == 0); - Result.pop_back(); - return; - } - - Result.clear(); - } -#endif + if (getDarwinConfDir(ErasedOnReboot, Result)) + return; const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); diff --git a/contrib/llvm/lib/Support/Unix/Process.inc b/contrib/llvm/lib/Support/Unix/Process.inc index df13bd221739..27083eeb072d 100644 --- a/contrib/llvm/lib/Support/Unix/Process.inc +++ b/contrib/llvm/lib/Support/Unix/Process.inc @@ -430,13 +430,18 @@ const char *Process::ResetColor() { #if !defined(HAVE_DECL_ARC4RANDOM) || !HAVE_DECL_ARC4RANDOM static unsigned GetRandomNumberSeed() { // Attempt to get the initial seed from /dev/urandom, if possible. - if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) { + int urandomFD = open("/dev/urandom", O_RDONLY); + + if (urandomFD != -1) { unsigned seed; - int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource); - ::fclose(RandomSource); + // Don't use a buffered read to avoid reading more data + // from /dev/urandom than we need. + int count = read(urandomFD, (void *)&seed, sizeof(seed)); + + close(urandomFD); // Return the seed if the read was successful. - if (count == 1) + if (count == sizeof(seed)) return seed; } diff --git a/contrib/llvm/lib/Support/Unix/Program.inc b/contrib/llvm/lib/Support/Unix/Program.inc index 8947b62e4dc2..a8d1fe3c07d0 100644 --- a/contrib/llvm/lib/Support/Unix/Program.inc +++ b/contrib/llvm/lib/Support/Unix/Program.inc @@ -323,7 +323,6 @@ namespace llvm { ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, bool WaitUntilTerminates, std::string *ErrMsg) { -#ifdef HAVE_SYS_WAIT_H struct sigaction Act, Old; assert(PI.Pid && "invalid pid to wait on, process not started?"); @@ -417,12 +416,6 @@ ProcessInfo sys::Wait(const ProcessInfo &PI, unsigned SecondsToWait, // signal during execution as opposed to failing to execute. WaitResult.ReturnCode = -2; } -#else - if (ErrMsg) - *ErrMsg = "Program::Wait is not implemented on this platform yet!"; - ProcessInfo WaitResult; - WaitResult.ReturnCode = -2; -#endif return WaitResult; } diff --git a/contrib/llvm/lib/Support/Unix/Signals.inc b/contrib/llvm/lib/Support/Unix/Signals.inc index bfe2a3a380ed..061cdb3da216 100644 --- a/contrib/llvm/lib/Support/Unix/Signals.inc +++ b/contrib/llvm/lib/Support/Unix/Signals.inc @@ -17,7 +17,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/Program.h" @@ -25,7 +24,6 @@ #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <string> -#include <vector> #if HAVE_EXECINFO_H # include <execinfo.h> // For backtrace(). #endif @@ -58,8 +56,6 @@ static ManagedStatic<SmartMutex<true> > SignalsMutex; static void (*InterruptFunction)() = nullptr; static ManagedStatic<std::vector<std::string>> FilesToRemove; -static ManagedStatic<std::vector<std::pair<void (*)(void *), void *>>> - CallBacksToRun; // IntSigs - Signals that represent requested termination. There's no bug // or failure, or if there is, it's not our direct responsibility. For whatever @@ -90,12 +86,11 @@ static unsigned NumRegisteredSignals = 0; static struct { struct sigaction SA; int SigNo; -} RegisteredSignalInfo[(sizeof(IntSigs)+sizeof(KillSigs))/sizeof(KillSigs[0])]; +} RegisteredSignalInfo[array_lengthof(IntSigs) + array_lengthof(KillSigs)]; static void RegisterHandler(int Signal) { - assert(NumRegisteredSignals < - sizeof(RegisteredSignalInfo)/sizeof(RegisteredSignalInfo[0]) && + assert(NumRegisteredSignals < array_lengthof(RegisteredSignalInfo) && "Out of space for signal handlers!"); struct sigaction NewHandler; @@ -117,7 +112,7 @@ static void RegisterHandlers() { // during handling an actual signal because you can't safely call new in a // signal handler. *SignalsMutex; - + // If the handlers are already registered, we're done. if (NumRegisteredSignals != 0) return; @@ -148,9 +143,6 @@ static void RemoveFilesToRemove() { // memory. std::vector<std::string>& FilesToRemoveRef = *FilesToRemove; for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) { - // We 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. const char *path = FilesToRemoveRef[i].c_str(); // Get the status so we can determine if it's a file or directory. If we @@ -164,7 +156,7 @@ static void RemoveFilesToRemove() { // super-user permissions. if (!S_ISREG(buf.st_mode)) continue; - + // Otherwise, remove the file. We ignore any errors here as there is nothing // else we can do. unlink(path); @@ -205,11 +197,7 @@ static RETSIGTYPE SignalHandler(int Sig) { } // Otherwise if it is a fault (like SEGV) run any handler. - if (CallBacksToRun.isConstructed()) { - auto &CallBacksToRunRef = *CallBacksToRun; - for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) - CallBacksToRunRef[i].first(CallBacksToRunRef[i].second); - } + llvm::sys::RunSignalHandlers(); #ifdef __s390__ // On S/390, certain signals are delivered with PSW Address pointing to @@ -239,21 +227,7 @@ bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { { sys::SmartScopedLock<true> Guard(*SignalsMutex); - std::vector<std::string>& FilesToRemoveRef = *FilesToRemove; - std::string *OldPtr = - FilesToRemoveRef.empty() ? nullptr : &FilesToRemoveRef[0]; - FilesToRemoveRef.push_back(Filename); - - // 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 == &FilesToRemoveRef[0]) - FilesToRemoveRef.back().c_str(); - else - for (unsigned i = 0, e = FilesToRemoveRef.size(); i != e; ++i) - FilesToRemoveRef[i].c_str(); + FilesToRemove->push_back(Filename); } RegisterHandlers(); @@ -268,13 +242,6 @@ void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) { 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(); } /// AddSignalHandler - Add a function to be called when a signal is delivered @@ -285,10 +252,9 @@ void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { RegisterHandlers(); } -#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) - -#if HAVE_LINK_H && (defined(__linux__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__NetBSD__)) +#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && HAVE_LINK_H && \ + (defined(__linux__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__NetBSD__)) struct DlIteratePhdrData { void **StackTrace; int depth; @@ -321,108 +287,27 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { return 0; } +/// If this is an ELF platform, we can find all loaded modules and their virtual +/// addresses with dl_iterate_phdr. static bool findModulesAndOffsets(void **StackTrace, int Depth, const char **Modules, intptr_t *Offsets, - const char *MainExecutableName) { + const char *MainExecutableName, + StringSaver &StrPool) { DlIteratePhdrData data = {StackTrace, Depth, true, Modules, Offsets, MainExecutableName}; dl_iterate_phdr(dl_iterate_phdr_cb, &data); return true; } #else +/// This platform does not have dl_iterate_phdr, so we do not yet know how to +/// find all loaded DSOs. static bool findModulesAndOffsets(void **StackTrace, int Depth, const char **Modules, intptr_t *Offsets, - const char *MainExecutableName) { + const char *MainExecutableName, + StringSaver &StrPool) { return false; } -#endif - -static bool printSymbolizedStackTrace(void **StackTrace, int Depth, - llvm::raw_ostream &OS) { - // FIXME: Subtract necessary number from StackTrace entries to turn return addresses - // into actual instruction addresses. - // Use llvm-symbolizer tool to symbolize the stack traces. - ErrorOr<std::string> LLVMSymbolizerPathOrErr = - sys::findProgramByName("llvm-symbolizer"); - if (!LLVMSymbolizerPathOrErr) - return false; - const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; - // We don't know argv0 or the address of main() at this point, but try - // to guess it anyway (it's possible on some platforms). - std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); - if (MainExecutableName.empty() || - MainExecutableName.find("llvm-symbolizer") != std::string::npos) - return false; - - std::vector<const char *> Modules(Depth, nullptr); - std::vector<intptr_t> Offsets(Depth, 0); - if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(), - MainExecutableName.c_str())) - return false; - int InputFD; - SmallString<32> InputFile, OutputFile; - sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile); - sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile); - FileRemover InputRemover(InputFile.c_str()); - FileRemover OutputRemover(OutputFile.c_str()); - - { - raw_fd_ostream Input(InputFD, true); - for (int i = 0; i < Depth; i++) { - if (Modules[i]) - Input << Modules[i] << " " << (void*)Offsets[i] << "\n"; - } - } - - StringRef InputFileStr(InputFile); - StringRef OutputFileStr(OutputFile); - StringRef StderrFileStr; - const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr, - &StderrFileStr}; - const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", - "--demangle", nullptr}; - int RunResult = - sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); - if (RunResult != 0) - return false; - - auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); - if (!OutputBuf) - return false; - StringRef Output = OutputBuf.get()->getBuffer(); - SmallVector<StringRef, 32> Lines; - Output.split(Lines, "\n"); - auto CurLine = Lines.begin(); - int frame_no = 0; - for (int i = 0; i < Depth; i++) { - if (!Modules[i]) { - OS << format("#%d %p\n", frame_no++, StackTrace[i]); - continue; - } - // Read pairs of lines (function name and file/line info) until we - // encounter empty line. - for (;;) { - if (CurLine == Lines.end()) - return false; - StringRef FunctionName = *CurLine++; - if (FunctionName.empty()) - break; - OS << format("#%d %p ", frame_no++, StackTrace[i]); - if (!FunctionName.startswith("??")) - OS << format("%s ", FunctionName.str().c_str()); - if (CurLine == Lines.end()) - return false; - StringRef FileLineInfo = *CurLine++; - if (!FileLineInfo.startswith("??")) - OS << format("%s", FileLineInfo.str().c_str()); - else - OS << format("(%s+%p)", Modules[i], (void *)Offsets[i]); - OS << "\n"; - } - } - return true; -} -#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) +#endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && ... // PrintStackTrace - In the case of a program crash or fault, print out a stack // trace so that the user has an indication of why and where we died. diff --git a/contrib/llvm/lib/Support/Unix/Unix.h b/contrib/llvm/lib/Support/Unix/Unix.h index e16a226a8eaf..871e612f6c16 100644 --- a/contrib/llvm/lib/Support/Unix/Unix.h +++ b/contrib/llvm/lib/Support/Unix/Unix.h @@ -29,6 +29,7 @@ #include <cstring> #include <string> #include <sys/types.h> +#include <sys/wait.h> #ifdef HAVE_UNISTD_H #include <unistd.h> @@ -43,22 +44,10 @@ #endif #include <time.h> -#ifdef HAVE_SYS_WAIT_H -# include <sys/wait.h> -#endif - #ifdef HAVE_DLFCN_H # include <dlfcn.h> #endif -#ifndef WEXITSTATUS -# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) -#endif - -#ifndef WIFEXITED -# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) -#endif - /// This function builds an error message into \p ErrMsg using the \p prefix /// string and the Unix error number given by \p errnum. If errnum is -1, the /// default then the value of errno is used. |