1//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7//===----------------------------------------------------------------------===// 9// This file defines an API used to indicate fatal error conditions. Non-fatal 10// errors (most of them) should be handled through LLVMContext. 12//===----------------------------------------------------------------------===// 18#include "llvm/Config/config.h" 19#include "llvm/Config/llvm-config.h"// for LLVM_ENABLE_THREADS 33#if defined(HAVE_UNISTD_H) 49#if LLVM_ENABLE_THREADS == 1 50// Mutexes to synchronize installing error handlers and calling error handlers. 51// Do not use ManagedStatic, or that may allocate memory while attempting to 54// This usage of std::mutex has to be conditionalized behind ifdefs because 56// compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh 57// That script attempts to statically link the LLVM symbolizer library with the 58// STL and hide all of its symbols with 'opt -internalize'. To reduce size, it 59// cuts out the threading portions of the hermetic copy of libc++ that it 60// builds. We can remove these ifdefs if that script goes away. 61static std::mutex ErrorHandlerMutex;
62static std::mutex BadAllocErrorHandlerMutex;
67#if LLVM_ENABLE_THREADS == 1 68 std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
76#if LLVM_ENABLE_THREADS == 1 77 std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
93void* handlerData =
nullptr;
95// Only acquire the mutex while reading the handler, so as not to invoke a 96// user-supplied callback under a lock. 97#if LLVM_ENABLE_THREADS == 1 98 std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
105 handler(handlerData, Reason.
str().c_str(), GenCrashDiag);
107// Blast the result out to stderr. We don't try hard to make sure this 108// succeeds (e.g. handling EINTR) and we can't use errs() here because 109// raw ostreams can call report_fatal_error. 112OS <<
"LLVM ERROR: " << Reason <<
"\n";
115 (void)written;
// If something went wrong, we deliberately just give up. 118// If we reached here, we are failing ungracefully. Run the interrupt handlers 119// to make sure any special cleanups get done, in particular that we remove 120// files registered with RemoveFileOnSignal. 131#if LLVM_ENABLE_THREADS == 1 132 std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
135"Bad alloc error handler already registered!\n");
141#if LLVM_ENABLE_THREADS == 1 142 std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
150void *HandlerData =
nullptr;
152// Only acquire the mutex while reading the handler, so as not to invoke a 153// user-supplied callback under a lock. 154#if LLVM_ENABLE_THREADS == 1 155 std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
162 Handler(HandlerData, Reason, GenCrashDiag);
166#ifdef LLVM_ENABLE_EXCEPTIONS 167// If exceptions are enabled, make OOM in malloc look like OOM in new. 168throw std::bad_alloc();
170// Don't call the normal error handler. It may allocate memory. Directly write 171// an OOM to stderr and abort. 172constchar *OOMMessage =
"LLVM ERROR: out of memory\n";
173constchar *Newline =
"\n";
174 (void)!
::write(2, OOMMessage, strlen(OOMMessage));
175 (void)!
::write(2, Reason, strlen(Reason));
176 (void)!
::write(2, Newline, strlen(Newline));
181#ifdef LLVM_ENABLE_EXCEPTIONS 182// Do not set custom new handler if exceptions are enabled. In this case OOM 183// errors are handled by throwing 'std::bad_alloc'. 187// Causes crash on allocation failure. It is called prior to the handler set by 188// 'install_bad_alloc_error_handler'. 193// Installs new handler that causes crash on allocation failure. It is called by 199"new-handler already installed");
205// This code intentionally doesn't call the ErrorHandler callback, because 206// llvm_unreachable is intended to be used to indicate "impossible" 207// situations, and not legitimate runtime errors. 210dbgs() <<
"UNREACHABLE executed";
212dbgs() <<
" at " <<
file <<
":" << line;
215#ifdef LLVM_BUILTIN_UNREACHABLE 216// Windows systems and possibly others don't declare abort() to be noreturn, 217// so use the unreachable builtin to avoid a Clang self-host warning. 218 LLVM_BUILTIN_UNREACHABLE;
223bool gen_crash_diag) {
240#define WIN32_NO_STATUS 242#undef WIN32_NO_STATUS 246// This is equivalent to NtCurrentTeb()->LastStatusValue, but the public 247// _TEB definition does not expose the LastStatusValue field directly. 248// Avoid offsetting into this structure by calling RtlGetLastNtStatus 251// The return of this function will roughly match that of 252// GetLastError, but this lower level API disambiguates some cases 253// that GetLastError does not. 255// For more information, see: 256// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/teb/index.htm 257// https://github.com/llvm/llvm-project/issues/89137 258extern"C" NTSYSAPI NTSTATUS NTAPI RtlGetLastNtStatus();
260// This function obtains the last error code and maps it. It may call 261// RtlGetLastNtStatus, which is a lower level API that can return a 262// more specific error code than GetLastError. 264unsigned EV = ::GetLastError();
265// The mapping of NTSTATUS to Win32 error loses some information; special 266// case the generic ERROR_ACCESS_DENIED code to check the underlying 267// NTSTATUS and potentially return a more accurate error code. 268if (EV == ERROR_ACCESS_DENIED) {
269llvm::errc code = RtlGetLastNtStatus() == STATUS_DELETE_PENDING
270 ? errc::delete_pending
271 : errc::permission_denied;
277// I'd rather not double the line count of the following. 278#define MAP_ERR_TO_COND(x, y) \ 280 return make_error_code(errc::y) 294 MAP_ERR_TO_COND(ERROR_CANTOPEN,
io_error);
295 MAP_ERR_TO_COND(ERROR_CANTREAD,
io_error);
296 MAP_ERR_TO_COND(ERROR_CANTWRITE,
io_error);
319 MAP_ERR_TO_COND(ERROR_OPEN_FAILED,
io_error);
323 MAP_ERR_TO_COND(ERROR_READ_FAULT,
io_error);
326 MAP_ERR_TO_COND(ERROR_SEEK,
io_error);
329 MAP_ERR_TO_COND(ERROR_WRITE_FAULT,
io_error);
339return std::error_code(EV, std::system_category());
#define LLVM_EXTENSION
LLVM_EXTENSION - Support compilers where we have a keyword to suppress pedantic diagnostics.
static fatal_error_handler_t ErrorHandler
static void out_of_memory_new_handler()
static void bindingsErrorHandler(void *user_data, const char *reason, bool gen_crash_diag)
static fatal_error_handler_t BadAllocErrorHandler
static void * BadAllocErrorHandlerUserData
static void * ErrorHandlerUserData
Provides a library for accessing information about this process and other processes on the operating ...
dot regions Print regions of function to dot file(with no function bodies)"
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
A raw_ostream that writes to an SmallVector or SmallString.
void LLVMResetFatalErrorHandler()
Reset the fatal error handler.
void(* LLVMFatalErrorHandler)(const char *Reason)
void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler)
Install a fatal error handler.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void RunInterruptHandlers()
This function runs all the registered interrupt handlers, including the removal of files registered b...
This is an optimization pass for GlobalISel generic memory operations.
std::error_code make_error_code(BitcodeError E)
std::error_code mapLastWindowsError()
void(* fatal_error_handler_t)(void *user_data, const char *reason, bool gen_crash_diag)
An error handler callback.
void install_fatal_error_handler(fatal_error_handler_t handler, void *user_data=nullptr)
install_fatal_error_handler - Installs a new error handler to be used whenever a serious (non-recover...
void install_bad_alloc_error_handler(fatal_error_handler_t handler, void *user_data=nullptr)
Installs a new bad alloc error handler that should be used whenever a bad alloc error,...
void remove_bad_alloc_error_handler()
Restores default bad alloc error handling behavior.
@ no_such_file_or_directory
@ device_or_resource_busy
@ resource_unavailable_try_again
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
void install_out_of_memory_new_handler()
void llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, unsigned line=0)
This function calls abort(), and prints the optional message to stderr.
void remove_fatal_error_handler()
Restores default error handling behaviour.
std::error_code mapWindowsError(unsigned EV)
void report_bad_alloc_error(const char *Reason, bool GenCrashDiag=true)
Reports a bad alloc error, calling any user defined bad alloc error handler.