diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-02-15 14:58:40 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-02-15 14:58:40 +0000 |
commit | 13138422bc354a1ec35f53a27c4efeccdffc5639 (patch) | |
tree | 8948a8a0aadc77afefcbe0f84abe732eece4aaa0 /contrib/llvm-project/llvm/lib/Support | |
parent | c246b3930d394722a836a9e724bd5ffba7c4a9b7 (diff) | |
parent | d75c7debad4509ece98792074e64b8a650a27bdb (diff) |
Notes
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support')
5 files changed, 86 insertions, 34 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/CRC.cpp b/contrib/llvm-project/llvm/lib/Support/CRC.cpp index a3dba1a3aa10..2bc668beed32 100644 --- a/contrib/llvm-project/llvm/lib/Support/CRC.cpp +++ b/contrib/llvm-project/llvm/lib/Support/CRC.cpp @@ -85,7 +85,15 @@ uint32_t llvm::crc32(uint32_t CRC, ArrayRef<uint8_t> Data) { #include <zlib.h> uint32_t llvm::crc32(uint32_t CRC, ArrayRef<uint8_t> Data) { - return ::crc32(CRC, (const Bytef *)Data.data(), Data.size()); + // Zlib's crc32() only takes a 32-bit length, so we have to iterate for larger + // sizes. One could use crc32_z() instead, but that's a recent (2017) addition + // and may not be available on all systems. + do { + ArrayRef<uint8_t> Slice = Data.take_front(UINT32_MAX); + CRC = ::crc32(CRC, (const Bytef *)Slice.data(), (uInt)Slice.size()); + Data = Data.drop_front(Slice.size()); + } while (Data.size() > 0); + return CRC; } #endif diff --git a/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp b/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp index b9031f52375c..356835609830 100644 --- a/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp +++ b/contrib/llvm-project/llvm/lib/Support/CrashRecoveryContext.cpp @@ -14,9 +14,6 @@ #include "llvm/Support/ThreadLocal.h" #include <mutex> #include <setjmp.h> -#ifdef _WIN32 -#include <excpt.h> // for GetExceptionInformation -#endif #if LLVM_ON_UNIX #include <sysexits.h> // EX_IOERR #endif @@ -41,11 +38,11 @@ struct CrashRecoveryContextImpl { ::jmp_buf JumpBuffer; volatile unsigned Failed : 1; unsigned SwitchedThread : 1; + unsigned ValidJumpBuffer : 1; public: - CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC), - Failed(false), - SwitchedThread(false) { + CrashRecoveryContextImpl(CrashRecoveryContext *CRC) noexcept + : CRC(CRC), Failed(false), SwitchedThread(false), ValidJumpBuffer(false) { Next = CurrentContext->get(); CurrentContext->set(this); } @@ -80,10 +77,13 @@ public: CRC->RetCode = RetCode; // Jump back to the RunSafely we were called under. - longjmp(JumpBuffer, 1); + if (ValidJumpBuffer) + longjmp(JumpBuffer, 1); + + // Otherwise let the caller decide of the outcome of the crash. Currently + // this occurs when using SEH on Windows with MSVC or clang-cl. } }; - } static ManagedStatic<std::mutex> gCrashRecoveryContextMutex; @@ -175,6 +175,9 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) { } #if defined(_MSC_VER) + +#include <windows.h> // for GetExceptionInformation + // If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way // better than VEH. Vectored exception handling catches all exceptions happening // on the thread with installed exception handlers, so it can interfere with @@ -188,30 +191,45 @@ static void uninstallExceptionOrSignalHandlers() {} // We need this function because the call to GetExceptionInformation() can only // occur inside the __except evaluation block -static int ExceptionFilter(bool DumpStackAndCleanup, - _EXCEPTION_POINTERS *Except) { - if (DumpStackAndCleanup) - sys::CleanupOnSignal((uintptr_t)Except); - return EXCEPTION_EXECUTE_HANDLER; -} +static int ExceptionFilter(_EXCEPTION_POINTERS *Except) { + // Lookup the current thread local recovery object. + const CrashRecoveryContextImpl *CRCI = CurrentContext->get(); -static bool InvokeFunctionCall(function_ref<void()> Fn, - bool DumpStackAndCleanup, int &RetCode) { - __try { - Fn(); - } __except (ExceptionFilter(DumpStackAndCleanup, GetExceptionInformation())) { - RetCode = GetExceptionCode(); - return false; + if (!CRCI) { + // Something has gone horribly wrong, so let's just tell everyone + // to keep searching + CrashRecoveryContext::Disable(); + return EXCEPTION_CONTINUE_SEARCH; } - return true; + + int RetCode = (int)Except->ExceptionRecord->ExceptionCode; + if ((RetCode & 0xF0000000) == 0xE0000000) + RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit + + // Handle the crash + const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash( + RetCode, reinterpret_cast<uintptr_t>(Except)); + + return EXCEPTION_EXECUTE_HANDLER; } +#if defined(__clang__) && defined(_M_IX86) +// Work around PR44697. +__attribute__((optnone)) +#endif bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { if (!gCrashRecoveryEnabled) { Fn(); return true; } - return InvokeFunctionCall(Fn, DumpStackAndCleanupOnFailure, RetCode); + assert(!Impl && "Crash recovery context already initialized!"); + Impl = new CrashRecoveryContextImpl(this); + __try { + Fn(); + } __except (ExceptionFilter(GetExceptionInformation())) { + return false; + } + return true; } #else // !_MSC_VER @@ -264,10 +282,13 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) // TODO: We can capture the stack backtrace here and store it on the // implementation if we so choose. + int RetCode = (int)ExceptionInfo->ExceptionRecord->ExceptionCode; + if ((RetCode & 0xF0000000) == 0xE0000000) + RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit + // Handle the crash const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash( - (int)ExceptionInfo->ExceptionRecord->ExceptionCode, - reinterpret_cast<uintptr_t>(ExceptionInfo)); + RetCode, reinterpret_cast<uintptr_t>(ExceptionInfo)); // Note that we don't actually get here because HandleCrash calls // longjmp, which means the HandleCrash function never returns. @@ -388,6 +409,7 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this); Impl = CRCI; + CRCI->ValidJumpBuffer = true; if (setjmp(CRCI->JumpBuffer) != 0) { return false; } @@ -399,12 +421,19 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) { #endif // !_MSC_VER -void CrashRecoveryContext::HandleCrash() { - CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl; +LLVM_ATTRIBUTE_NORETURN +void CrashRecoveryContext::HandleExit(int RetCode) { +#if defined(_WIN32) + // SEH and VEH + ::RaiseException(0xE0000000 | RetCode, 0, 0, NULL); +#else + // On Unix we don't need to raise an exception, we go directly to + // HandleCrash(), then longjmp will unwind the stack for us. + CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *)Impl; assert(CRCI && "Crash recovery context never initialized!"); - // As per convention, -2 indicates a crash or timeout as opposed to failure to - // execute (see llvm/include/llvm/Support/Program.h) - CRCI->HandleCrash(-2, 0); + CRCI->HandleCrash(RetCode, 0 /*no sig num*/); +#endif + llvm_unreachable("Most likely setjmp wasn't called!"); } // FIXME: Portability. diff --git a/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp b/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp index 0f13f7a536f1..a9463024c420 100644 --- a/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp +++ b/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" +#include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/Threading.h" #include "llvm/Support/WindowsError.h" @@ -122,7 +123,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) { // files registered with RemoveFileOnSignal. sys::RunInterruptHandlers(); - exit(1); + sys::Process::Exit(1); } void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler, diff --git a/contrib/llvm-project/llvm/lib/Support/Process.cpp b/contrib/llvm-project/llvm/lib/Support/Process.cpp index 5b6471008159..509512f643d3 100644 --- a/contrib/llvm-project/llvm/lib/Support/Process.cpp +++ b/contrib/llvm-project/llvm/lib/Support/Process.cpp @@ -13,8 +13,9 @@ #include "llvm/Support/Process.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Config/llvm-config.h" #include "llvm/Config/config.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" @@ -88,6 +89,13 @@ static bool coreFilesPrevented = !LLVM_ENABLE_CRASH_DUMPS; bool Process::AreCoreFilesPrevented() { return coreFilesPrevented; } +LLVM_ATTRIBUTE_NORETURN +void Process::Exit(int RetCode) { + if (CrashRecoveryContext *CRC = CrashRecoveryContext::GetCurrent()) + CRC->HandleExit(RetCode); + ::exit(RetCode); +} + // Include the platform-specific parts of this class. #ifdef LLVM_ON_UNIX #include "Unix/Process.inc" diff --git a/contrib/llvm-project/llvm/lib/Support/Windows/Signals.inc b/contrib/llvm-project/llvm/lib/Support/Windows/Signals.inc index 8b525f1bd4ac..09e19ae41f1a 100644 --- a/contrib/llvm-project/llvm/lib/Support/Windows/Signals.inc +++ b/contrib/llvm-project/llvm/lib/Support/Windows/Signals.inc @@ -820,7 +820,13 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { << "\n"; } - LocalPrintStackTrace(llvm::errs(), ep ? ep->ContextRecord : nullptr); + // Stack unwinding appears to modify the context. Copy it to preserve the + // caller's context. + CONTEXT ContextCopy; + if (ep) + memcpy(&ContextCopy, ep->ContextRecord, sizeof(ContextCopy)); + + LocalPrintStackTrace(llvm::errs(), ep ? &ContextCopy : nullptr); return EXCEPTION_EXECUTE_HANDLER; } |