LLVM  13.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(const std::string &Reason, bool GenCrashDiag) {
87  report_fatal_error(Twine(Reason), GenCrashDiag);
88 }
89 
90 void llvm::report_fatal_error(StringRef Reason, bool GenCrashDiag) {
91  report_fatal_error(Twine(Reason), GenCrashDiag);
92 }
93 
94 void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
95  llvm::fatal_error_handler_t handler = nullptr;
96  void* handlerData = nullptr;
97  {
98  // Only acquire the mutex while reading the handler, so as not to invoke a
99  // user-supplied callback under a lock.
100 #if LLVM_ENABLE_THREADS == 1
101  std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
102 #endif
103  handler = ErrorHandler;
104  handlerData = ErrorHandlerUserData;
105  }
106 
107  if (handler) {
108  handler(handlerData, Reason.str(), GenCrashDiag);
109  } else {
110  // Blast the result out to stderr. We don't try hard to make sure this
111  // succeeds (e.g. handling EINTR) and we can't use errs() here because
112  // raw ostreams can call report_fatal_error.
113  SmallVector<char, 64> Buffer;
114  raw_svector_ostream OS(Buffer);
115  OS << "LLVM ERROR: " << Reason << "\n";
116  StringRef MessageStr = OS.str();
117  ssize_t written = ::write(2, MessageStr.data(), MessageStr.size());
118  (void)written; // If something went wrong, we deliberately just give up.
119  }
120 
121  // If we reached here, we are failing ungracefully. Run the interrupt handlers
122  // to make sure any special cleanups get done, in particular that we remove
123  // files registered with RemoveFileOnSignal.
125 
126  abort();
127 }
128 
130  void *user_data) {
131 #if LLVM_ENABLE_THREADS == 1
132  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
133 #endif
134  assert(!ErrorHandler && "Bad alloc error handler already registered!\n");
135  BadAllocErrorHandler = handler;
136  BadAllocErrorHandlerUserData = user_data;
137 }
138 
140 #if LLVM_ENABLE_THREADS == 1
141  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
142 #endif
143  BadAllocErrorHandler = nullptr;
145 }
146 
147 void llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) {
148  fatal_error_handler_t Handler = nullptr;
149  void *HandlerData = nullptr;
150  {
151  // Only acquire the mutex while reading the handler, so as not to invoke a
152  // user-supplied callback under a lock.
153 #if LLVM_ENABLE_THREADS == 1
154  std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
155 #endif
156  Handler = BadAllocErrorHandler;
157  HandlerData = BadAllocErrorHandlerUserData;
158  }
159 
160  if (Handler) {
161  Handler(HandlerData, Reason, GenCrashDiag);
162  llvm_unreachable("bad alloc handler should not return");
163  }
164 
165 #ifdef LLVM_ENABLE_EXCEPTIONS
166  // If exceptions are enabled, make OOM in malloc look like OOM in new.
167  throw std::bad_alloc();
168 #else
169  // Don't call the normal error handler. It may allocate memory. Directly write
170  // an OOM to stderr and abort.
171  const char *OOMMessage = "LLVM ERROR: out of memory\n";
172  const char *Newline = "\n";
173  (void)!::write(2, OOMMessage, strlen(OOMMessage));
174  (void)!::write(2, Reason, strlen(Reason));
175  (void)!::write(2, Newline, strlen(Newline));
176  abort();
177 #endif
178 }
179 
180 #ifdef LLVM_ENABLE_EXCEPTIONS
181 // Do not set custom new handler if exceptions are enabled. In this case OOM
182 // errors are handled by throwing 'std::bad_alloc'.
184 }
185 #else
186 // Causes crash on allocation failure. It is called prior to the handler set by
187 // 'install_bad_alloc_error_handler'.
189  llvm::report_bad_alloc_error("Allocation failed");
190 }
191 
192 // Installs new handler that causes crash on allocation failure. It is called by
193 // InitLLVM.
195  std::new_handler old = std::set_new_handler(out_of_memory_new_handler);
196  (void)old;
197  assert((old == nullptr || old == out_of_memory_new_handler) &&
198  "new-handler already installed");
199 }
200 #endif
201 
202 void llvm::llvm_unreachable_internal(const char *msg, const char *file,
203  unsigned line) {
204  // This code intentionally doesn't call the ErrorHandler callback, because
205  // llvm_unreachable is intended to be used to indicate "impossible"
206  // situations, and not legitimate runtime errors.
207  if (msg)
208  dbgs() << msg << "\n";
209  dbgs() << "UNREACHABLE executed";
210  if (file)
211  dbgs() << " at " << file << ":" << line;
212  dbgs() << "!\n";
213  abort();
214 #ifdef LLVM_BUILTIN_UNREACHABLE
215  // Windows systems and possibly others don't declare abort() to be noreturn,
216  // so use the unreachable builtin to avoid a Clang self-host warning.
217  LLVM_BUILTIN_UNREACHABLE;
218 #endif
219 }
220 
221 static void bindingsErrorHandler(void *user_data, const std::string& reason,
222  bool gen_crash_diag) {
223  LLVMFatalErrorHandler handler =
224  LLVM_EXTENSION reinterpret_cast<LLVMFatalErrorHandler>(user_data);
225  handler(reason.c_str());
226 }
227 
230  LLVM_EXTENSION reinterpret_cast<void *>(Handler));
231 }
232 
235 }
236 
237 #ifdef _WIN32
238 
239 #include <winerror.h>
240 
241 // I'd rather not double the line count of the following.
242 #define MAP_ERR_TO_COND(x, y) \
243  case x: \
244  return make_error_code(errc::y)
245 
246 std::error_code llvm::mapWindowsError(unsigned EV) {
247  switch (EV) {
248  MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
249  MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
250  MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
251  MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
252  MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
253  MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
254  MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
255  MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
256  MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
257  MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
258  MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
259  MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
260  MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
261  MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
262  MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
263  MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
264  MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
265  MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
266  MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
267  MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
268  MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
269  MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
270  MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
271  MAP_ERR_TO_COND(ERROR_INVALID_NAME, 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_OPEN_FAILED, io_error);
279  MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
280  MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
281  MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
282  MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
283  MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
284  MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
285  MAP_ERR_TO_COND(ERROR_SEEK, io_error);
286  MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
287  MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
288  MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
289  MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
290  MAP_ERR_TO_COND(WSAEACCES, permission_denied);
291  MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
292  MAP_ERR_TO_COND(WSAEFAULT, bad_address);
293  MAP_ERR_TO_COND(WSAEINTR, interrupted);
294  MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
295  MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
296  MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
297  default:
298  return std::error_code(EV, std::system_category());
299  }
300 }
301 
302 #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:139
Signals.h
llvm
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:129
llvm::install_out_of_memory_new_handler
void install_out_of_memory_new_handler()
Definition: ErrorHandling.cpp:194
llvm::llvm_unreachable_internal
LLVM_ATTRIBUTE_NORETURN 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:202
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1167
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:132
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:314
llvm::mapWindowsError
std::error_code mapWindowsError(unsigned EV)
llvm::report_fatal_error
LLVM_ATTRIBUTE_NORETURN 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:228
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
LLVM_ATTRIBUTE_NORETURN 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:147
out_of_memory_new_handler
static void out_of_memory_new_handler()
Definition: ErrorHandling.cpp:188
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
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:233
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:672
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:136
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
ErrorHandling.h
llvm::fatal_error_handler_t
void(* fatal_error_handler_t)(void *user_data, const std::string &reason, bool gen_crash_diag)
An error handler callback.
Definition: ErrorHandling.h:25
bindingsErrorHandler
static void bindingsErrorHandler(void *user_data, const std::string &reason, bool gen_crash_diag)
Definition: ErrorHandling.cpp:221
SmallVector.h
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:647
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
Debug.h
write
static void write(bool isBE, void *P, T V)
Definition: RuntimeDyldELF.cpp:37
WindowsError.h