Movatterモバイル変換


[0]ホーム

URL:


LLVM 20.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
14#include "llvm/Support/ErrorHandling.h"
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/Config/llvm-config.h"// for LLVM_ENABLE_THREADS
20#include "llvm/Support/Debug.h"
21#include "llvm/Support/Errc.h"
22#include "llvm/Support/Error.h"
23#include "llvm/Support/Process.h"
24#include "llvm/Support/Signals.h"
25#include "llvm/Support/Threading.h"
26#include "llvm/Support/WindowsError.h"
27#include "llvm/Support/raw_ostream.h"
28#include <cassert>
29#include <cstdlib>
30#include <mutex>
31#include <new>
32
33#if defined(HAVE_UNISTD_H)
34# include <unistd.h>
35#endif
36#if defined(_WIN32)
37# include <io.h>
38# include <fcntl.h>
39#endif
40
41using namespacellvm;
42
43staticfatal_error_handler_tErrorHandler =nullptr;
44staticvoid *ErrorHandlerUserData =nullptr;
45
46staticfatal_error_handler_tBadAllocErrorHandler =nullptr;
47staticvoid *BadAllocErrorHandlerUserData =nullptr;
48
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
52// report an OOM.
53//
54// This usage of std::mutex has to be conditionalized behind ifdefs because
55// of this script:
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;
63#endif
64
65voidllvm::install_fatal_error_handler(fatal_error_handler_t handler,
66void *user_data) {
67#if LLVM_ENABLE_THREADS == 1
68 std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
69#endif
70assert(!ErrorHandler &&"Error handler already registered!\n");
71ErrorHandler = handler;
72ErrorHandlerUserData = user_data;
73}
74
75voidllvm::remove_fatal_error_handler() {
76#if LLVM_ENABLE_THREADS == 1
77 std::lock_guard<std::mutex> Lock(ErrorHandlerMutex);
78#endif
79ErrorHandler =nullptr;
80ErrorHandlerUserData =nullptr;
81}
82
83voidllvm::report_fatal_error(constchar *Reason,bool GenCrashDiag) {
84report_fatal_error(Twine(Reason), GenCrashDiag);
85}
86
87voidllvm::report_fatal_error(StringRef Reason,bool GenCrashDiag) {
88report_fatal_error(Twine(Reason), GenCrashDiag);
89}
90
91voidllvm::report_fatal_error(constTwine &Reason,bool GenCrashDiag) {
92llvm::fatal_error_handler_t handler =nullptr;
93void* handlerData =nullptr;
94 {
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);
99#endif
100 handler =ErrorHandler;
101 handlerData =ErrorHandlerUserData;
102 }
103
104if (handler) {
105 handler(handlerData, Reason.str().c_str(), GenCrashDiag);
106 }else {
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.
110SmallVector<char, 64> Buffer;
111raw_svector_ostreamOS(Buffer);
112OS <<"LLVM ERROR: " << Reason <<"\n";
113StringRef MessageStr =OS.str();
114 ssize_t written =::write(2, MessageStr.data(), MessageStr.size());
115 (void)written;// If something went wrong, we deliberately just give up.
116 }
117
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.
121sys::RunInterruptHandlers();
122
123if (GenCrashDiag)
124 abort();
125else
126 exit(1);
127}
128
129voidllvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,
130void *user_data) {
131#if LLVM_ENABLE_THREADS == 1
132 std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
133#endif
134assert(!BadAllocErrorHandler &&
135"Bad alloc error handler already registered!\n");
136BadAllocErrorHandler = handler;
137BadAllocErrorHandlerUserData = user_data;
138}
139
140voidllvm::remove_bad_alloc_error_handler() {
141#if LLVM_ENABLE_THREADS == 1
142 std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
143#endif
144BadAllocErrorHandler =nullptr;
145BadAllocErrorHandlerUserData =nullptr;
146}
147
148voidllvm::report_bad_alloc_error(constchar *Reason,bool GenCrashDiag) {
149fatal_error_handler_t Handler =nullptr;
150void *HandlerData =nullptr;
151 {
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);
156#endif
157 Handler =BadAllocErrorHandler;
158 HandlerData =BadAllocErrorHandlerUserData;
159 }
160
161if (Handler) {
162 Handler(HandlerData, Reason, GenCrashDiag);
163llvm_unreachable("bad alloc handler should not return");
164 }
165
166#ifdef LLVM_ENABLE_EXCEPTIONS
167// If exceptions are enabled, make OOM in malloc look like OOM in new.
168throw std::bad_alloc();
169#else
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));
177 abort();
178#endif
179}
180
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'.
184voidllvm::install_out_of_memory_new_handler() {
185}
186#else
187// Causes crash on allocation failure. It is called prior to the handler set by
188// 'install_bad_alloc_error_handler'.
189staticvoidout_of_memory_new_handler() {
190llvm::report_bad_alloc_error("Allocation failed");
191}
192
193// Installs new handler that causes crash on allocation failure. It is called by
194// InitLLVM.
195voidllvm::install_out_of_memory_new_handler() {
196 std::new_handler old = std::set_new_handler(out_of_memory_new_handler);
197 (void)old;
198assert((old ==nullptr || old ==out_of_memory_new_handler) &&
199"new-handler already installed");
200}
201#endif
202
203voidllvm::llvm_unreachable_internal(constchar *msg,constchar *file,
204unsigned line) {
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.
208if (msg)
209dbgs() << msg <<"\n";
210dbgs() <<"UNREACHABLE executed";
211if (file)
212dbgs() <<" at " <<file <<":" << line;
213dbgs() <<"!\n";
214 abort();
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;
219#endif
220}
221
222staticvoidbindingsErrorHandler(void *user_data,constchar *reason,
223bool gen_crash_diag) {
224LLVMFatalErrorHandler handler =
225LLVM_EXTENSIONreinterpret_cast<LLVMFatalErrorHandler>(user_data);
226 handler(reason);
227}
228
229voidLLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler) {
230install_fatal_error_handler(bindingsErrorHandler,
231LLVM_EXTENSIONreinterpret_cast<void *>(Handler));
232}
233
234voidLLVMResetFatalErrorHandler() {
235remove_fatal_error_handler();
236}
237
238#ifdef _WIN32
239
240#define WIN32_NO_STATUS
241#include "llvm/Support/Windows/WindowsSupport.h"
242#undef WIN32_NO_STATUS
243#include <ntstatus.h>
244#include <winerror.h>
245
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
249// from ntdll.dll.
250//
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.
254//
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();
259
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.
263std::error_codellvm::mapLastWindowsError() {
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;
272returnmake_error_code(code);
273 }
274returnmapWindowsError(EV);
275}
276
277// I'd rather not double the line count of the following.
278#define MAP_ERR_TO_COND(x, y) \
279 case x: \
280 return make_error_code(errc::y)
281
282std::error_codellvm::mapWindowsError(unsigned EV) {
283switch (EV) {
284 MAP_ERR_TO_COND(ERROR_ACCESS_DENIED,permission_denied);
285 MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS,file_exists);
286 MAP_ERR_TO_COND(ERROR_BAD_NETPATH,no_such_file_or_directory);
287 MAP_ERR_TO_COND(ERROR_BAD_PATHNAME,no_such_file_or_directory);
288 MAP_ERR_TO_COND(ERROR_BAD_UNIT,no_such_device);
289 MAP_ERR_TO_COND(ERROR_BROKEN_PIPE,broken_pipe);
290 MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW,filename_too_long);
291 MAP_ERR_TO_COND(ERROR_BUSY,device_or_resource_busy);
292 MAP_ERR_TO_COND(ERROR_BUSY_DRIVE,device_or_resource_busy);
293 MAP_ERR_TO_COND(ERROR_CANNOT_MAKE,permission_denied);
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);
297 MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY,permission_denied);
298 MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST,no_such_device);
299 MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE,device_or_resource_busy);
300 MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY,directory_not_empty);
301 MAP_ERR_TO_COND(ERROR_DIRECTORY,invalid_argument);
302 MAP_ERR_TO_COND(ERROR_DISK_FULL,no_space_on_device);
303 MAP_ERR_TO_COND(ERROR_FILE_EXISTS,file_exists);
304 MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND,no_such_file_or_directory);
305 MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL,no_space_on_device);
306 MAP_ERR_TO_COND(ERROR_INVALID_ACCESS,permission_denied);
307 MAP_ERR_TO_COND(ERROR_INVALID_DRIVE,no_such_device);
308 MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION,function_not_supported);
309 MAP_ERR_TO_COND(ERROR_INVALID_HANDLE,invalid_argument);
310 MAP_ERR_TO_COND(ERROR_INVALID_NAME,invalid_argument);
311 MAP_ERR_TO_COND(ERROR_INVALID_PARAMETER,invalid_argument);
312 MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION,no_lock_available);
313 MAP_ERR_TO_COND(ERROR_LOCKED,no_lock_available);
314 MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK,invalid_argument);
315 MAP_ERR_TO_COND(ERROR_NOACCESS,permission_denied);
316 MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY,not_enough_memory);
317 MAP_ERR_TO_COND(ERROR_NOT_READY,resource_unavailable_try_again);
318 MAP_ERR_TO_COND(ERROR_NOT_SUPPORTED,not_supported);
319 MAP_ERR_TO_COND(ERROR_OPEN_FAILED,io_error);
320 MAP_ERR_TO_COND(ERROR_OPEN_FILES,device_or_resource_busy);
321 MAP_ERR_TO_COND(ERROR_OUTOFMEMORY,not_enough_memory);
322 MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND,no_such_file_or_directory);
323 MAP_ERR_TO_COND(ERROR_READ_FAULT,io_error);
324 MAP_ERR_TO_COND(ERROR_REPARSE_TAG_INVALID,invalid_argument);
325 MAP_ERR_TO_COND(ERROR_RETRY,resource_unavailable_try_again);
326 MAP_ERR_TO_COND(ERROR_SEEK,io_error);
327 MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION,permission_denied);
328 MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES,too_many_files_open);
329 MAP_ERR_TO_COND(ERROR_WRITE_FAULT,io_error);
330 MAP_ERR_TO_COND(ERROR_WRITE_PROTECT,permission_denied);
331 MAP_ERR_TO_COND(WSAEACCES,permission_denied);
332 MAP_ERR_TO_COND(WSAEBADF,bad_file_descriptor);
333 MAP_ERR_TO_COND(WSAEFAULT,bad_address);
334 MAP_ERR_TO_COND(WSAEINTR,interrupted);
335 MAP_ERR_TO_COND(WSAEINVAL,invalid_argument);
336 MAP_ERR_TO_COND(WSAEMFILE,too_many_files_open);
337 MAP_ERR_TO_COND(WSAENAMETOOLONG,filename_too_long);
338default:
339return std::error_code(EV, std::system_category());
340 }
341}
342
343#endif
LLVM_EXTENSION
#define LLVM_EXTENSION
LLVM_EXTENSION - Support compilers where we have a keyword to suppress pedantic diagnostics.
Definition:Compiler.h:433
Debug.h
Errc.h
ErrorHandler
static fatal_error_handler_t ErrorHandler
Definition:ErrorHandling.cpp:43
out_of_memory_new_handler
static void out_of_memory_new_handler()
Definition:ErrorHandling.cpp:189
bindingsErrorHandler
static void bindingsErrorHandler(void *user_data, const char *reason, bool gen_crash_diag)
Definition:ErrorHandling.cpp:222
BadAllocErrorHandler
static fatal_error_handler_t BadAllocErrorHandler
Definition:ErrorHandling.cpp:46
BadAllocErrorHandlerUserData
static void * BadAllocErrorHandlerUserData
Definition:ErrorHandling.cpp:47
ErrorHandlerUserData
static void * ErrorHandlerUserData
Definition:ErrorHandling.cpp:44
Process.h
Provides a library for accessing information about this process and other processes on the operating ...
file
dot regions Print regions of function to dot file(with no function bodies)"
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OS
raw_pwrite_stream & OS
Definition:SampleProfWriter.cpp:51
Signals.h
SmallVector.h
This file defines the SmallVector class.
Threading.h
Twine.h
WindowsError.h
WindowsSupport.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition:StringRef.h:51
llvm::StringRef::size
constexpr size_t size() const
size - Get the string size.
Definition:StringRef.h:150
llvm::StringRef::data
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition:StringRef.h:144
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition:Twine.h:81
llvm::Twine::str
std::string str() const
Return the twine contents as a std::string.
Definition:Twine.cpp:17
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition:raw_ostream.h:691
LLVMResetFatalErrorHandler
void LLVMResetFatalErrorHandler()
Reset the fatal error handler.
Definition:ErrorHandling.cpp:234
LLVMFatalErrorHandler
void(* LLVMFatalErrorHandler)(const char *Reason)
Definition:ErrorHandling.h:27
LLVMInstallFatalErrorHandler
void LLVMInstallFatalErrorHandler(LLVMFatalErrorHandler Handler)
Install a fatal error handler.
Definition:ErrorHandling.cpp:229
ErrorHandling.h
ErrorHandling.h
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition:ErrorHandling.h:143
Error.h
llvm::sys::RunInterruptHandlers
void RunInterruptHandlers()
This function runs all the registered interrupt handlers, including the removal of files registered b...
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::make_error_code
std::error_code make_error_code(BitcodeError E)
Definition:BitcodeReader.h:310
llvm::mapLastWindowsError
std::error_code mapLastWindowsError()
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
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:65
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::remove_bad_alloc_error_handler
void remove_bad_alloc_error_handler()
Restores default bad alloc error handling behavior.
Definition:ErrorHandling.cpp:140
llvm::errc
errc
Definition:Errc.h:35
llvm::errc::no_space_on_device
@ no_space_on_device
llvm::errc::no_such_file_or_directory
@ no_such_file_or_directory
llvm::errc::broken_pipe
@ broken_pipe
llvm::errc::file_exists
@ file_exists
llvm::errc::no_lock_available
@ no_lock_available
llvm::errc::directory_not_empty
@ directory_not_empty
llvm::errc::filename_too_long
@ filename_too_long
llvm::errc::bad_file_descriptor
@ bad_file_descriptor
llvm::errc::function_not_supported
@ function_not_supported
llvm::errc::not_supported
@ not_supported
llvm::errc::bad_address
@ bad_address
llvm::errc::not_enough_memory
@ not_enough_memory
llvm::errc::device_or_resource_busy
@ device_or_resource_busy
llvm::errc::io_error
@ io_error
llvm::errc::resource_unavailable_try_again
@ resource_unavailable_try_again
llvm::errc::invalid_argument
@ invalid_argument
llvm::errc::permission_denied
@ permission_denied
llvm::errc::too_many_files_open
@ too_many_files_open
llvm::errc::no_such_device
@ no_such_device
llvm::errc::interrupted
@ interrupted
llvm::write
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)
Definition:DWP.cpp:625
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition:Debug.cpp:163
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:167
llvm::install_out_of_memory_new_handler
void install_out_of_memory_new_handler()
Definition:ErrorHandling.cpp:195
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:203
llvm::remove_fatal_error_handler
void remove_fatal_error_handler()
Restores default error handling behaviour.
Definition:ErrorHandling.cpp:75
llvm::mapWindowsError
std::error_code mapWindowsError(unsigned EV)
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:148
raw_ostream.h

Generated on Thu Jul 17 2025 12:39:54 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp