10b57cec5SDimitry Andric //===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines an API used to indicate fatal error conditions. Non-fatal 100b57cec5SDimitry Andric // errors (most of them) should be handled through LLVMContext. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 150b57cec5SDimitry Andric #include "llvm-c/ErrorHandling.h" 160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 170b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 180b57cec5SDimitry Andric #include "llvm/Config/config.h" 190b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 200b57cec5SDimitry Andric #include "llvm/Support/Errc.h" 210b57cec5SDimitry Andric #include "llvm/Support/Error.h" 2213138422SDimitry Andric #include "llvm/Support/Process.h" 230b57cec5SDimitry Andric #include "llvm/Support/Signals.h" 240b57cec5SDimitry Andric #include "llvm/Support/Threading.h" 250b57cec5SDimitry Andric #include "llvm/Support/WindowsError.h" 260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 270b57cec5SDimitry Andric #include <cassert> 280b57cec5SDimitry Andric #include <cstdlib> 290b57cec5SDimitry Andric #include <mutex> 300b57cec5SDimitry Andric #include <new> 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric #if defined(HAVE_UNISTD_H) 330b57cec5SDimitry Andric # include <unistd.h> 340b57cec5SDimitry Andric #endif 350b57cec5SDimitry Andric #if defined(_MSC_VER) 360b57cec5SDimitry Andric # include <io.h> 370b57cec5SDimitry Andric # include <fcntl.h> 380b57cec5SDimitry Andric #endif 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric using namespace llvm; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric static fatal_error_handler_t ErrorHandler = nullptr; 430b57cec5SDimitry Andric static void *ErrorHandlerUserData = nullptr; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric static fatal_error_handler_t BadAllocErrorHandler = nullptr; 460b57cec5SDimitry Andric static void *BadAllocErrorHandlerUserData = nullptr; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS == 1 490b57cec5SDimitry Andric // Mutexes to synchronize installing error handlers and calling error handlers. 500b57cec5SDimitry Andric // Do not use ManagedStatic, or that may allocate memory while attempting to 510b57cec5SDimitry Andric // report an OOM. 520b57cec5SDimitry Andric // 530b57cec5SDimitry Andric // This usage of std::mutex has to be conditionalized behind ifdefs because 540b57cec5SDimitry Andric // of this script: 550b57cec5SDimitry Andric // compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh 560b57cec5SDimitry Andric // That script attempts to statically link the LLVM symbolizer library with the 570b57cec5SDimitry Andric // STL and hide all of its symbols with 'opt -internalize'. To reduce size, it 580b57cec5SDimitry Andric // cuts out the threading portions of the hermetic copy of libc++ that it 590b57cec5SDimitry Andric // builds. We can remove these ifdefs if that script goes away. 600b57cec5SDimitry Andric static std::mutex ErrorHandlerMutex; 610b57cec5SDimitry Andric static std::mutex BadAllocErrorHandlerMutex; 620b57cec5SDimitry Andric #endif 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric void llvm::install_fatal_error_handler(fatal_error_handler_t handler, 650b57cec5SDimitry Andric void *user_data) { 660b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS == 1 670b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(ErrorHandlerMutex); 680b57cec5SDimitry Andric #endif 690b57cec5SDimitry Andric assert(!ErrorHandler && "Error handler already registered!\n"); 700b57cec5SDimitry Andric ErrorHandler = handler; 710b57cec5SDimitry Andric ErrorHandlerUserData = user_data; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric void llvm::remove_fatal_error_handler() { 750b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS == 1 760b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(ErrorHandlerMutex); 770b57cec5SDimitry Andric #endif 780b57cec5SDimitry Andric ErrorHandler = nullptr; 790b57cec5SDimitry Andric ErrorHandlerUserData = nullptr; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric void llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) { 830b57cec5SDimitry Andric report_fatal_error(Twine(Reason), GenCrashDiag); 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) { 870b57cec5SDimitry Andric report_fatal_error(Twine(Reason), GenCrashDiag); 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) { 910b57cec5SDimitry Andric llvm::fatal_error_handler_t handler = nullptr; 920b57cec5SDimitry Andric void* handlerData = nullptr; 930b57cec5SDimitry Andric { 940b57cec5SDimitry Andric // Only acquire the mutex while reading the handler, so as not to invoke a 950b57cec5SDimitry Andric // user-supplied callback under a lock. 960b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS == 1 970b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(ErrorHandlerMutex); 980b57cec5SDimitry Andric #endif 990b57cec5SDimitry Andric handler = ErrorHandler; 1000b57cec5SDimitry Andric handlerData = ErrorHandlerUserData; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric if (handler) { 104349cc55cSDimitry Andric handler(handlerData, Reason.str().c_str(), GenCrashDiag); 1050b57cec5SDimitry Andric } else { 1060b57cec5SDimitry Andric // Blast the result out to stderr. We don't try hard to make sure this 1070b57cec5SDimitry Andric // succeeds (e.g. handling EINTR) and we can't use errs() here because 1080b57cec5SDimitry Andric // raw ostreams can call report_fatal_error. 1090b57cec5SDimitry Andric SmallVector<char, 64> Buffer; 1100b57cec5SDimitry Andric raw_svector_ostream OS(Buffer); 1110b57cec5SDimitry Andric OS << "LLVM ERROR: " << Reason << "\n"; 1120b57cec5SDimitry Andric StringRef MessageStr = OS.str(); 1130b57cec5SDimitry Andric ssize_t written = ::write(2, MessageStr.data(), MessageStr.size()); 1140b57cec5SDimitry Andric (void)written; // If something went wrong, we deliberately just give up. 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric // If we reached here, we are failing ungracefully. Run the interrupt handlers 1180b57cec5SDimitry Andric // to make sure any special cleanups get done, in particular that we remove 1190b57cec5SDimitry Andric // files registered with RemoveFileOnSignal. 1200b57cec5SDimitry Andric sys::RunInterruptHandlers(); 1210b57cec5SDimitry Andric 12281ad6265SDimitry Andric if (GenCrashDiag) 1235ffd83dbSDimitry Andric abort(); 12481ad6265SDimitry Andric else 12581ad6265SDimitry Andric exit(1); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler, 1290b57cec5SDimitry Andric void *user_data) { 1300b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS == 1 1310b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex); 1320b57cec5SDimitry Andric #endif 133*0fca6ea1SDimitry Andric assert(!BadAllocErrorHandler && 134*0fca6ea1SDimitry Andric "Bad alloc error handler already registered!\n"); 1350b57cec5SDimitry Andric BadAllocErrorHandler = handler; 1360b57cec5SDimitry Andric BadAllocErrorHandlerUserData = user_data; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric void llvm::remove_bad_alloc_error_handler() { 1400b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS == 1 1410b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex); 1420b57cec5SDimitry Andric #endif 1430b57cec5SDimitry Andric BadAllocErrorHandler = nullptr; 1440b57cec5SDimitry Andric BadAllocErrorHandlerUserData = nullptr; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) { 1480b57cec5SDimitry Andric fatal_error_handler_t Handler = nullptr; 1490b57cec5SDimitry Andric void *HandlerData = nullptr; 1500b57cec5SDimitry Andric { 1510b57cec5SDimitry Andric // Only acquire the mutex while reading the handler, so as not to invoke a 1520b57cec5SDimitry Andric // user-supplied callback under a lock. 1530b57cec5SDimitry Andric #if LLVM_ENABLE_THREADS == 1 1540b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex); 1550b57cec5SDimitry Andric #endif 1560b57cec5SDimitry Andric Handler = BadAllocErrorHandler; 1570b57cec5SDimitry Andric HandlerData = BadAllocErrorHandlerUserData; 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric if (Handler) { 1610b57cec5SDimitry Andric Handler(HandlerData, Reason, GenCrashDiag); 1620b57cec5SDimitry Andric llvm_unreachable("bad alloc handler should not return"); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric #ifdef LLVM_ENABLE_EXCEPTIONS 1660b57cec5SDimitry Andric // If exceptions are enabled, make OOM in malloc look like OOM in new. 1670b57cec5SDimitry Andric throw std::bad_alloc(); 1680b57cec5SDimitry Andric #else 1690b57cec5SDimitry Andric // Don't call the normal error handler. It may allocate memory. Directly write 1700b57cec5SDimitry Andric // an OOM to stderr and abort. 171e8d8bef9SDimitry Andric const char *OOMMessage = "LLVM ERROR: out of memory\n"; 172e8d8bef9SDimitry Andric const char *Newline = "\n"; 173e8d8bef9SDimitry Andric (void)!::write(2, OOMMessage, strlen(OOMMessage)); 174e8d8bef9SDimitry Andric (void)!::write(2, Reason, strlen(Reason)); 175e8d8bef9SDimitry Andric (void)!::write(2, Newline, strlen(Newline)); 1760b57cec5SDimitry Andric abort(); 1770b57cec5SDimitry Andric #endif 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric #ifdef LLVM_ENABLE_EXCEPTIONS 1810b57cec5SDimitry Andric // Do not set custom new handler if exceptions are enabled. In this case OOM 1820b57cec5SDimitry Andric // errors are handled by throwing 'std::bad_alloc'. 1830b57cec5SDimitry Andric void llvm::install_out_of_memory_new_handler() { 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric #else 1860b57cec5SDimitry Andric // Causes crash on allocation failure. It is called prior to the handler set by 1870b57cec5SDimitry Andric // 'install_bad_alloc_error_handler'. 1880b57cec5SDimitry Andric static void out_of_memory_new_handler() { 1890b57cec5SDimitry Andric llvm::report_bad_alloc_error("Allocation failed"); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric // Installs new handler that causes crash on allocation failure. It is called by 1930b57cec5SDimitry Andric // InitLLVM. 1940b57cec5SDimitry Andric void llvm::install_out_of_memory_new_handler() { 1950b57cec5SDimitry Andric std::new_handler old = std::set_new_handler(out_of_memory_new_handler); 1960b57cec5SDimitry Andric (void)old; 197e8d8bef9SDimitry Andric assert((old == nullptr || old == out_of_memory_new_handler) && 198e8d8bef9SDimitry Andric "new-handler already installed"); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric #endif 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric void llvm::llvm_unreachable_internal(const char *msg, const char *file, 2030b57cec5SDimitry Andric unsigned line) { 2040b57cec5SDimitry Andric // This code intentionally doesn't call the ErrorHandler callback, because 2050b57cec5SDimitry Andric // llvm_unreachable is intended to be used to indicate "impossible" 2060b57cec5SDimitry Andric // situations, and not legitimate runtime errors. 2070b57cec5SDimitry Andric if (msg) 2080b57cec5SDimitry Andric dbgs() << msg << "\n"; 2090b57cec5SDimitry Andric dbgs() << "UNREACHABLE executed"; 2100b57cec5SDimitry Andric if (file) 2110b57cec5SDimitry Andric dbgs() << " at " << file << ":" << line; 2120b57cec5SDimitry Andric dbgs() << "!\n"; 2130b57cec5SDimitry Andric abort(); 2140b57cec5SDimitry Andric #ifdef LLVM_BUILTIN_UNREACHABLE 2150b57cec5SDimitry Andric // Windows systems and possibly others don't declare abort() to be noreturn, 2160b57cec5SDimitry Andric // so use the unreachable builtin to avoid a Clang self-host warning. 2170b57cec5SDimitry Andric LLVM_BUILTIN_UNREACHABLE; 2180b57cec5SDimitry Andric #endif 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 221349cc55cSDimitry Andric static void bindingsErrorHandler(void *user_data, const char *reason, 2220b57cec5SDimitry Andric bool gen_crash_diag) { 2230b57cec5SDimitry Andric LLVMFatalErrorHandler handler = 2240b57cec5SDimitry Andric LLVM_EXTENSION reinterpret_cast<LLVMFatalErrorHandler>(user_data); 225349cc55cSDimitry Andric handler(reason); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler) { 2290b57cec5SDimitry Andric install_fatal_error_handler(bindingsErrorHandler, 2300b57cec5SDimitry Andric LLVM_EXTENSION reinterpret_cast<void *>(Handler)); 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric void LLVMResetFatalErrorHandler() { 2340b57cec5SDimitry Andric remove_fatal_error_handler(); 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric #ifdef _WIN32 2380b57cec5SDimitry Andric 239*0fca6ea1SDimitry Andric #define WIN32_NO_STATUS 240*0fca6ea1SDimitry Andric #include "llvm/Support/Windows/WindowsSupport.h" 241*0fca6ea1SDimitry Andric #undef WIN32_NO_STATUS 242*0fca6ea1SDimitry Andric #include <ntstatus.h> 2430b57cec5SDimitry Andric #include <winerror.h> 2440b57cec5SDimitry Andric 245*0fca6ea1SDimitry Andric // This is equivalent to NtCurrentTeb()->LastStatusValue, but the public 246*0fca6ea1SDimitry Andric // _TEB definition does not expose the LastStatusValue field directly. 247*0fca6ea1SDimitry Andric // Avoid offsetting into this structure by calling RtlGetLastNtStatus 248*0fca6ea1SDimitry Andric // from ntdll.dll. 249*0fca6ea1SDimitry Andric // 250*0fca6ea1SDimitry Andric // The return of this function will roughly match that of 251*0fca6ea1SDimitry Andric // GetLastError, but this lower level API disambiguates some cases 252*0fca6ea1SDimitry Andric // that GetLastError does not. 253*0fca6ea1SDimitry Andric // 254*0fca6ea1SDimitry Andric // For more information, see: 255*0fca6ea1SDimitry Andric // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/teb/index.htm 256*0fca6ea1SDimitry Andric // https://github.com/llvm/llvm-project/issues/89137 257*0fca6ea1SDimitry Andric extern "C" NTSYSAPI NTSTATUS NTAPI RtlGetLastNtStatus(); 258*0fca6ea1SDimitry Andric 259*0fca6ea1SDimitry Andric // This function obtains the last error code and maps it. It may call 260*0fca6ea1SDimitry Andric // RtlGetLastNtStatus, which is a lower level API that can return a 261*0fca6ea1SDimitry Andric // more specific error code than GetLastError. 262*0fca6ea1SDimitry Andric std::error_code llvm::mapLastWindowsError() { 263*0fca6ea1SDimitry Andric unsigned EV = ::GetLastError(); 264*0fca6ea1SDimitry Andric // The mapping of NTSTATUS to Win32 error loses some information; special 265*0fca6ea1SDimitry Andric // case the generic ERROR_ACCESS_DENIED code to check the underlying 266*0fca6ea1SDimitry Andric // NTSTATUS and potentially return a more accurate error code. 267*0fca6ea1SDimitry Andric if (EV == ERROR_ACCESS_DENIED) { 268*0fca6ea1SDimitry Andric llvm::errc code = RtlGetLastNtStatus() == STATUS_DELETE_PENDING 269*0fca6ea1SDimitry Andric ? errc::delete_pending 270*0fca6ea1SDimitry Andric : errc::permission_denied; 271*0fca6ea1SDimitry Andric return make_error_code(code); 272*0fca6ea1SDimitry Andric } 273*0fca6ea1SDimitry Andric return mapWindowsError(EV); 274*0fca6ea1SDimitry Andric } 275*0fca6ea1SDimitry Andric 2760b57cec5SDimitry Andric // I'd rather not double the line count of the following. 2770b57cec5SDimitry Andric #define MAP_ERR_TO_COND(x, y) \ 2780b57cec5SDimitry Andric case x: \ 2790b57cec5SDimitry Andric return make_error_code(errc::y) 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric std::error_code llvm::mapWindowsError(unsigned EV) { 2820b57cec5SDimitry Andric switch (EV) { 2830b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied); 2840b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists); 285349cc55cSDimitry Andric MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory); 286349cc55cSDimitry Andric MAP_ERR_TO_COND(ERROR_BAD_PATHNAME, no_such_file_or_directory); 2870b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device); 288349cc55cSDimitry Andric MAP_ERR_TO_COND(ERROR_BROKEN_PIPE, broken_pipe); 2890b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long); 2900b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy); 2910b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy); 2920b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied); 2930b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error); 2940b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_CANTREAD, io_error); 2950b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error); 2960b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied); 2970b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device); 2980b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy); 2990b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty); 3000b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument); 3010b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device); 3020b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists); 3030b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory); 3040b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device); 3050b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied); 3060b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device); 3070b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported); 3080b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument); 3090b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument); 310349cc55cSDimitry Andric MAP_ERR_TO_COND(ERROR_INVALID_PARAMETER, invalid_argument); 3110b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available); 3120b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available); 3130b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument); 3140b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied); 3150b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory); 3160b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again); 317349cc55cSDimitry Andric MAP_ERR_TO_COND(ERROR_NOT_SUPPORTED, not_supported); 3180b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error); 3190b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy); 3200b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory); 3210b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory); 3220b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error); 323349cc55cSDimitry Andric MAP_ERR_TO_COND(ERROR_REPARSE_TAG_INVALID, invalid_argument); 3240b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again); 3250b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_SEEK, io_error); 3260b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied); 3270b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open); 3280b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error); 3290b57cec5SDimitry Andric MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied); 3300b57cec5SDimitry Andric MAP_ERR_TO_COND(WSAEACCES, permission_denied); 3310b57cec5SDimitry Andric MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor); 3320b57cec5SDimitry Andric MAP_ERR_TO_COND(WSAEFAULT, bad_address); 3330b57cec5SDimitry Andric MAP_ERR_TO_COND(WSAEINTR, interrupted); 3340b57cec5SDimitry Andric MAP_ERR_TO_COND(WSAEINVAL, invalid_argument); 3350b57cec5SDimitry Andric MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open); 3360b57cec5SDimitry Andric MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long); 3370b57cec5SDimitry Andric default: 3380b57cec5SDimitry Andric return std::error_code(EV, std::system_category()); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric #endif 343