LLVM  14.0.0git
ErrorHandling.cpp
Go to the documentation of this file.
1 //===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines an API used to indicate fatal error conditions. Non-fatal
10 // errors (most of them) should be handled through LLVMContext.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm-c/ErrorHandling.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/Config/config.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/Errc.h"
21 #include "llvm/Support/Error.h"
22 #include "llvm/Support/Process.h"
23 #include "llvm/Support/Signals.h"
24 #include "llvm/Support/Threading.h"
27 #include <cassert>
28 #include <cstdlib>
29 #include <mutex>
30 #include <new>
31 
32 #if defined(HAVE_UNISTD_H)
33 # include <unistd.h>
34 #endif
35 #if defined(_MSC_VER)
36 # include <io.h>
37 # include <fcntl.h>
38 #endif
39 
40 using namespace llvm;
41 
43 static void *ErrorHandlerUserData = nullptr;
44 
46 static void *BadAllocErrorHandlerUserData = nullptr;
47 
48 #if LLVM_ENABLE_THREADS == 1
49 // Mutexes to synchronize installing error handlers and calling error handlers.
50 // Do not use ManagedStatic, or that may allocate memory while attempting to
51 // report an OOM.
52 //
53 // This usage of std::mutex has to be conditionalized behind ifdefs because
54 // of this script:
55 // compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh
56 // That script attempts to statically link the LLVM symbolizer library with the
57 // STL and hide all of its symbols with 'opt -internalize'. To reduce size, it
58 // cuts out the threading portions of the hermetic copy of libc++ that it
59 // builds. We can remove these ifdefs if that script goes away.
60 static std::mutex ErrorHandlerMutex;
61 static std::mutex BadAllocErrorHandlerMutex;
62 #endif
63 
65  void *user_data) {
66 #if LLVM_ENABLE_THREADS == 1
67  std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
68 #endif
69  assert(!ErrorHandler && "Error handler already registered!\n");
70  ErrorHandler = handler;
71  ErrorHandlerUserData = user_data;
72 }
73 
75 #if LLVM_ENABLE_THREADS == 1
76  std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
77 #endif
78  ErrorHandler = nullptr;
79  ErrorHandlerUserData = nullptr;
80 }
81 
82 void llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) {
83  report_fatal_error(Twine(Reason), GenCrashDiag);
84 }
85 
86 void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) {
87  report_fatal_error(Twine(Reason), GenCrashDiag);
88 }
89 
90 void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
91  llvm::fatal_error_handler_t handler = nullptr;
92  void* handlerData = nullptr;
93  {
94  // Only acquire the mutex while reading the handler, so as not to invoke a
95  // user-supplied callback under a lock.
96 #if LLVM_ENABLE_THREADS == 1
97  std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
98 #endif
99  handler = ErrorHandler;
100  handlerData = ErrorHandlerUserData;
101  }
102 
103  if (handler) {
104  handler(handlerData, Reason.str().c_str(), GenCrashDiag);
105  } else {
106  // Blast the result out to stderr. We don't try hard to make sure this
107  // succeeds (e.g. handling EINTR) and we can't use errs() here because
108  // raw ostreams can call report_fatal_error.
109  SmallVector<char, 64> Buffer;
110  raw_svector_ostream OS(Buffer);
111  OS << "LLVM ERROR: " << Reason << "\n";
112  StringRef MessageStr = OS.str();
113  ssize_t written = ::write(2, MessageStr.data(), MessageStr.size());
114  (void)written; // If something went wrong, we deliberately just give up.
115  }
116 
117  // If we reached here, we are failing ungracefully. Run the interrupt handlers
118  // to make sure any special cleanups get done, in particular that we remove
119  // files registered with RemoveFileOnSignal.
121 
122  abort();
123 }
124 
126  void *user_data) {
127 #if LLVM_ENABLE_THREADS == 1
128  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
129 #endif
130  assert(!ErrorHandler && "Bad alloc error handler already registered!\n");
131  BadAllocErrorHandler = handler;
132  BadAllocErrorHandlerUserData = user_data;
133 }
134 
136 #if LLVM_ENABLE_THREADS == 1
137  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
138 #endif
139  BadAllocErrorHandler = nullptr;
141 }
142 
143 void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
144  fatal_error_handler_t Handler = nullptr;
145  void *HandlerData = nullptr;
146  {
147  // Only acquire the mutex while reading the handler, so as not to invoke a
148  // user-supplied callback under a lock.
149 #if LLVM_ENABLE_THREADS == 1
150  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
151 #endif
152  Handler = BadAllocErrorHandler;
153  HandlerData = BadAllocErrorHandlerUserData;
154  }
155 
156  if (Handler) {
157  Handler(HandlerData, Reason, GenCrashDiag);
158  llvm_unreachable("bad alloc handler should not return");
159  }
160 
161 #ifdef LLVM_ENABLE_EXCEPTIONS
162  // If exceptions are enabled, make OOM in malloc look like OOM in new.
163  throw std::bad_alloc();
164 #else
165  // Don't call the normal error handler. It may allocate memory. Directly write
166  // an OOM to stderr and abort.
167  const char *OOMMessage = "LLVM ERROR: out of memory\n";
168  const char *Newline = "\n";
169  (void)!::write(2, OOMMessage, strlen(OOMMessage));
170  (void)!::write(2, Reason, strlen(Reason));
171  (void)!::write(2, Newline, strlen(Newline));
172  abort();
173 #endif
174 }
175 
176 #ifdef LLVM_ENABLE_EXCEPTIONS
177 // Do not set custom new handler if exceptions are enabled. In this case OOM
178 // errors are handled by throwing 'std::bad_alloc'.
180 }
181 #else
182 // Causes crash on allocation failure. It is called prior to the handler set by
183 // 'install_bad_alloc_error_handler'.
185  llvm::report_bad_alloc_error("Allocation failed");
186 }
187 
188 // Installs new handler that causes crash on allocation failure. It is called by
189 // InitLLVM.
191  std::new_handler old = std::set_new_handler(out_of_memory_new_handler);
192  (void)old;
193  assert((old == nullptr || old == out_of_memory_new_handler) &&
194  "new-handler already installed");
195 }
196 #endif
197 
198 void llvm::llvm_unreachable_internal(const char *msg, const char *file,
199  unsigned line) {
200  // This code intentionally doesn't call the ErrorHandler callback, because
201  // llvm_unreachable is intended to be used to indicate "impossible"
202  // situations, and not legitimate runtime errors.
203  if (msg)
204  dbgs() << msg << "\n";
205  dbgs() << "UNREACHABLE executed";
206  if (file)
207  dbgs() << " at " << file << ":" << line;
208  dbgs() << "!\n";
209  abort();
210 #ifdef LLVM_BUILTIN_UNREACHABLE
211  // Windows systems and possibly others don't declare abort() to be noreturn,
212  // so use the unreachable builtin to avoid a Clang self-host warning.
214 #endif
215 }
216 
217 static void bindingsErrorHandler(void *user_data, const char *reason,
218  bool gen_crash_diag) {
219  LLVMFatalErrorHandler handler =
220  LLVM_EXTENSION reinterpret_cast<LLVMFatalErrorHandler>(user_data);
221  handler(reason);
222 }
223 
226  LLVM_EXTENSION reinterpret_cast<void *>(Handler));
227 }
228 
231 }
232 
233 #ifdef _WIN32
234 
235 #include <winerror.h>
236 
237 // I'd rather not double the line count of the following.
238 #define MAP_ERR_TO_COND(x, y) \
239  case x: \
240  return make_error_code(errc::y)
241 
242 std::error_code llvm::mapWindowsError(unsigned EV) {
243  switch (EV) {
244  MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
245  MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
246  MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
247  MAP_ERR_TO_COND(ERROR_BAD_PATHNAME, no_such_file_or_directory);
248  MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
249  MAP_ERR_TO_COND(ERROR_BROKEN_PIPE, broken_pipe);
250  MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
251  MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
252  MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
253  MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
254  MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
255  MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
256  MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
257  MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
258  MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
259  MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
260  MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
261  MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
262  MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
263  MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
264  MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
265  MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
266  MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
267  MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
268  MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
269  MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
270  MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
271  MAP_ERR_TO_COND(ERROR_INVALID_PARAMETER, invalid_argument);
272  MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
273  MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
274  MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
275  MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
276  MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
277  MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
278  MAP_ERR_TO_COND(ERROR_NOT_SUPPORTED, not_supported);
279  MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
280  MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
281  MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
282  MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
283  MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
284  MAP_ERR_TO_COND(ERROR_REPARSE_TAG_INVALID, invalid_argument);
285  MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
286  MAP_ERR_TO_COND(ERROR_SEEK, io_error);
287  MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
288  MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
289  MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
290  MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
291  MAP_ERR_TO_COND(WSAEACCES, permission_denied);
292  MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
293  MAP_ERR_TO_COND(WSAEFAULT, bad_address);
294  MAP_ERR_TO_COND(WSAEINTR, interrupted);
295  MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
296  MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
297  MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
298  default:
299  return std::error_code(EV, std::system_category());
300  }
301 }
302 
303 #endif
BadAllocErrorHandler
static fatal_error_handler_t BadAllocErrorHandler
Definition: ErrorHandling.cpp:45
llvm::remove_bad_alloc_error_handler
void remove_bad_alloc_error_handler()
Restores default bad alloc error handling behavior.
Definition: ErrorHandling.cpp:135
Signals.h
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::install_bad_alloc_error_handler
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,...
Definition: ErrorHandling.cpp:125
llvm::install_out_of_memory_new_handler
void install_out_of_memory_new_handler()
Definition: ErrorHandling.cpp:190
llvm::write
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs)
Definition: DWP.cpp:535
llvm::llvm_unreachable_internal
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.
Definition: ErrorHandling.cpp:198
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::remove_fatal_error_handler
void remove_fatal_error_handler()
Restores default error handling behaviour.
Definition: ErrorHandling.cpp:74
ErrorHandling.h
Error.h
Errc.h
BadAllocErrorHandlerUserData
static void * BadAllocErrorHandlerUserData
Definition: ErrorHandling.cpp:46
llvm::sys::RunInterruptHandlers
void RunInterruptHandlers()
This function runs all the registered interrupt handlers, including the removal of files registered b...
llvm::install_fatal_error_handler
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...
Definition: ErrorHandling.cpp:64
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::Lock
static sys::Mutex Lock
Definition: NVPTXUtilities.cpp:39
ErrorHandler
static fatal_error_handler_t ErrorHandler
Definition: ErrorHandling.cpp:42
Process.h
Twine.h
old
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM ID Predecessors according to mbb< bb27, 0x8b0a7c0 > Note ADDri is not a two address instruction its result reg1037 is an operand of the PHI node in bb76 and its operand reg1039 is the result of the PHI node We should treat it as a two address code and make sure the ADDri is scheduled after any node that reads reg1039 Use info(i.e. register scavenger) to assign it a free register to allow reuse the collector could move the objects and invalidate the derived pointer This is bad enough in the first but safe points can crop up unpredictably **array_addr i32 n old
Definition: README.txt:123
LLVM_EXTENSION
#define LLVM_EXTENSION
LLVM_EXTENSION - Support compilers where we have a keyword to suppress pedantic diagnostics.
Definition: Compiler.h:319
llvm::mapWindowsError
std::error_code mapWindowsError(unsigned EV)
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
LLVMInstallFatalErrorHandler
void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler)
Install a fatal error handler.
Definition: ErrorHandling.cpp:224
llvm::Twine::str
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
BadAllocErrorHandlerMutex
static std::mutex BadAllocErrorHandlerMutex
Definition: ErrorHandling.cpp:61
llvm::report_bad_alloc_error
void report_bad_alloc_error(const char *Reason, bool GenCrashDiag=true)
Reports a bad alloc error, calling any user defined bad alloc error handler.
Definition: ErrorHandling.cpp:143
out_of_memory_new_handler
static void out_of_memory_new_handler()
Definition: ErrorHandling.cpp:184
file
dot regions Print regions of function to dot file(with no function bodies)"
ErrorHandlerMutex
static std::mutex ErrorHandlerMutex
Definition: ErrorHandling.cpp:60
Threading.h
bindingsErrorHandler
static void bindingsErrorHandler(void *user_data, const char *reason, bool gen_crash_diag)
Definition: ErrorHandling.cpp:217
LLVMFatalErrorHandler
LLVM_C_EXTERN_C_BEGIN typedef void(* LLVMFatalErrorHandler)(const char *Reason)
Definition: ErrorHandling.h:21
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVMResetFatalErrorHandler
void LLVMResetFatalErrorHandler()
Reset the fatal error handler.
Definition: ErrorHandling.cpp:229
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::raw_svector_ostream::str
StringRef str() const
Return a StringRef for the vector contents.
Definition: raw_ostream.h:683
ErrorHandlerUserData
static void * ErrorHandlerUserData
Definition: ErrorHandling.cpp:43
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
LLVM_BUILTIN_UNREACHABLE
#define LLVM_BUILTIN_UNREACHABLE
LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands to an expression which states that ...
Definition: Compiler.h:335
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
ErrorHandling.h
SmallVector.h
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:658
llvm::StringRef::data
const LLVM_NODISCARD char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:149
abort
*Add support for compiling functions in both ARM and Thumb then taking the smallest *Add support for compiling individual basic blocks in thumb when in a larger ARM function This can be used for presumed cold like paths to abort(failure path of asserts)
raw_ostream.h
llvm::StringRef::size
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::fatal_error_handler_t
void(* fatal_error_handler_t)(void *user_data, const char *reason, bool gen_crash_diag)
An error handler callback.
Definition: ErrorHandling.h:24
Debug.h
WindowsError.h