LLVM  15.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  if (GenCrashDiag)
123  abort();
124  else
125  exit(1);
126 }
127 
129  void *user_data) {
130 #if LLVM_ENABLE_THREADS == 1
131  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
132 #endif
133  assert(!ErrorHandler && "Bad alloc error handler already registered!\n");
134  BadAllocErrorHandler = handler;
135  BadAllocErrorHandlerUserData = user_data;
136 }
137 
139 #if LLVM_ENABLE_THREADS == 1
140  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
141 #endif
142  BadAllocErrorHandler = nullptr;
144 }
145 
146 void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
147  fatal_error_handler_t Handler = nullptr;
148  void *HandlerData = nullptr;
149  {
150  // Only acquire the mutex while reading the handler, so as not to invoke a
151  // user-supplied callback under a lock.
152 #if LLVM_ENABLE_THREADS == 1
153  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
154 #endif
155  Handler = BadAllocErrorHandler;
156  HandlerData = BadAllocErrorHandlerUserData;
157  }
158 
159  if (Handler) {
160  Handler(HandlerData, Reason, GenCrashDiag);
161  llvm_unreachable("bad alloc handler should not return");
162  }
163 
164 #ifdef LLVM_ENABLE_EXCEPTIONS
165  // If exceptions are enabled, make OOM in malloc look like OOM in new.
166  throw std::bad_alloc();
167 #else
168  // Don't call the normal error handler. It may allocate memory. Directly write
169  // an OOM to stderr and abort.
170  const char *OOMMessage = "LLVM ERROR: out of memory\n";
171  const char *Newline = "\n";
172  (void)!::write(2, OOMMessage, strlen(OOMMessage));
173  (void)!::write(2, Reason, strlen(Reason));
174  (void)!::write(2, Newline, strlen(Newline));
175  abort();
176 #endif
177 }
178 
179 #ifdef LLVM_ENABLE_EXCEPTIONS
180 // Do not set custom new handler if exceptions are enabled. In this case OOM
181 // errors are handled by throwing 'std::bad_alloc'.
183 }
184 #else
185 // Causes crash on allocation failure. It is called prior to the handler set by
186 // 'install_bad_alloc_error_handler'.
188  llvm::report_bad_alloc_error("Allocation failed");
189 }
190 
191 // Installs new handler that causes crash on allocation failure. It is called by
192 // InitLLVM.
194  std::new_handler old = std::set_new_handler(out_of_memory_new_handler);
195  (void)old;
196  assert((old == nullptr || old == out_of_memory_new_handler) &&
197  "new-handler already installed");
198 }
199 #endif
200 
201 void llvm::llvm_unreachable_internal(const char *msg, const char *file,
202  unsigned line) {
203  // This code intentionally doesn't call the ErrorHandler callback, because
204  // llvm_unreachable is intended to be used to indicate "impossible"
205  // situations, and not legitimate runtime errors.
206  if (msg)
207  dbgs() << msg << "\n";
208  dbgs() << "UNREACHABLE executed";
209  if (file)
210  dbgs() << " at " << file << ":" << line;
211  dbgs() << "!\n";
212  abort();
213 #ifdef LLVM_BUILTIN_UNREACHABLE
214  // Windows systems and possibly others don't declare abort() to be noreturn,
215  // so use the unreachable builtin to avoid a Clang self-host warning.
216  LLVM_BUILTIN_UNREACHABLE;
217 #endif
218 }
219 
220 static void bindingsErrorHandler(void *user_data, const char *reason,
221  bool gen_crash_diag) {
222  LLVMFatalErrorHandler handler =
223  LLVM_EXTENSION reinterpret_cast<LLVMFatalErrorHandler>(user_data);
224  handler(reason);
225 }
226 
229  LLVM_EXTENSION reinterpret_cast<void *>(Handler));
230 }
231 
234 }
235 
236 #ifdef _WIN32
237 
238 #include <winerror.h>
239 
240 // I'd rather not double the line count of the following.
241 #define MAP_ERR_TO_COND(x, y) \
242  case x: \
243  return make_error_code(errc::y)
244 
245 std::error_code llvm::mapWindowsError(unsigned EV) {
246  switch (EV) {
247  MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
248  MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
249  MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
250  MAP_ERR_TO_COND(ERROR_BAD_PATHNAME, no_such_file_or_directory);
251  MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
252  MAP_ERR_TO_COND(ERROR_BROKEN_PIPE, broken_pipe);
253  MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
254  MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
255  MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
256  MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
257  MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
258  MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
259  MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
260  MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
261  MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
262  MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
263  MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
264  MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
265  MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
266  MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
267  MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
268  MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
269  MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
270  MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
271  MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
272  MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
273  MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
274  MAP_ERR_TO_COND(ERROR_INVALID_PARAMETER, invalid_argument);
275  MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
276  MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
277  MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
278  MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
279  MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
280  MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
281  MAP_ERR_TO_COND(ERROR_NOT_SUPPORTED, not_supported);
282  MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
283  MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
284  MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
285  MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
286  MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
287  MAP_ERR_TO_COND(ERROR_REPARSE_TAG_INVALID, invalid_argument);
288  MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
289  MAP_ERR_TO_COND(ERROR_SEEK, io_error);
290  MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
291  MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
292  MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
293  MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
294  MAP_ERR_TO_COND(WSAEACCES, permission_denied);
295  MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
296  MAP_ERR_TO_COND(WSAEFAULT, bad_address);
297  MAP_ERR_TO_COND(WSAEINTR, interrupted);
298  MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
299  MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
300  MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
301  default:
302  return std::error_code(EV, std::system_category());
303  }
304 }
305 
306 #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:138
Signals.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:128
llvm::install_out_of_memory_new_handler
void install_out_of_memory_new_handler()
Definition: ErrorHandling.cpp:193
llvm::write
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs)
Definition: DWP.cpp:536
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:201
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
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
LLVMResetFatalErrorHandler
void LLVMResetFatalErrorHandler()
Reset the fatal error handler.
Definition: ErrorHandling.cpp:232
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:313
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:143
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:146
out_of_memory_new_handler
static void out_of_memory_new_handler()
Definition: ErrorHandling.cpp:187
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:220
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVMFatalErrorHandler
void(* LLVMFatalErrorHandler)(const char *Reason)
Definition: ErrorHandling.h:27
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:687
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:143
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
ErrorHandling.h
SmallVector.h
exit
declare void exit(i32) noreturn nounwind This compiles into
Definition: README.txt:1072
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:662
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::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
LLVMInstallFatalErrorHandler
void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler)
Install a fatal error handler.
Definition: ErrorHandling.cpp:227
WindowsError.h