aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2024-07-27 23:34:35 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-10-23 18:26:01 +0000
commit0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583 (patch)
tree6cf5ab1f05330c6773b1f3f64799d56a9c7a1faa /contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp
parent6b9f7133aba44189d9625c352bc2c2a59baf18ef (diff)
parentac9a064cb179f3425b310fa2847f8764ac970a4d (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp38
1 files changed, 37 insertions, 1 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp b/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp
index b8b3b7424ac6..cb42e28c04a8 100644
--- a/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp
+++ b/contrib/llvm-project/llvm/lib/Support/ErrorHandling.cpp
@@ -130,7 +130,8 @@ void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,
#if LLVM_ENABLE_THREADS == 1
std::lock_guard<std::mutex> Lock(BadAllocErrorHandlerMutex);
#endif
- assert(!ErrorHandler && "Bad alloc error handler already registered!\n");
+ assert(!BadAllocErrorHandler &&
+ "Bad alloc error handler already registered!\n");
BadAllocErrorHandler = handler;
BadAllocErrorHandlerUserData = user_data;
}
@@ -235,8 +236,43 @@ void LLVMResetFatalErrorHandler() {
#ifdef _WIN32
+#define WIN32_NO_STATUS
+#include "llvm/Support/Windows/WindowsSupport.h"
+#undef WIN32_NO_STATUS
+#include <ntstatus.h>
#include <winerror.h>
+// This is equivalent to NtCurrentTeb()->LastStatusValue, but the public
+// _TEB definition does not expose the LastStatusValue field directly.
+// Avoid offsetting into this structure by calling RtlGetLastNtStatus
+// from ntdll.dll.
+//
+// The return of this function will roughly match that of
+// GetLastError, but this lower level API disambiguates some cases
+// that GetLastError does not.
+//
+// For more information, see:
+// https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/teb/index.htm
+// https://github.com/llvm/llvm-project/issues/89137
+extern "C" NTSYSAPI NTSTATUS NTAPI RtlGetLastNtStatus();
+
+// This function obtains the last error code and maps it. It may call
+// RtlGetLastNtStatus, which is a lower level API that can return a
+// more specific error code than GetLastError.
+std::error_code llvm::mapLastWindowsError() {
+ unsigned EV = ::GetLastError();
+ // The mapping of NTSTATUS to Win32 error loses some information; special
+ // case the generic ERROR_ACCESS_DENIED code to check the underlying
+ // NTSTATUS and potentially return a more accurate error code.
+ if (EV == ERROR_ACCESS_DENIED) {
+ llvm::errc code = RtlGetLastNtStatus() == STATUS_DELETE_PENDING
+ ? errc::delete_pending
+ : errc::permission_denied;
+ return make_error_code(code);
+ }
+ return mapWindowsError(EV);
+}
+
// I'd rather not double the line count of the following.
#define MAP_ERR_TO_COND(x, y) \
case x: \