summaryrefslogtreecommitdiff
path: root/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp')
-rw-r--r--gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp b/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp
new file mode 100644
index 00000000000..c3b9e1467bd
--- /dev/null
+++ b/gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp
@@ -0,0 +1,140 @@
+//===-- crash_handler_interface.cpp -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/common.h"
+#include "gwp_asan/stack_trace_compressor.h"
+
+#include <assert.h>
+
+using AllocationMetadata = gwp_asan::AllocationMetadata;
+using Error = gwp_asan::Error;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool __gwp_asan_error_is_mine(const gwp_asan::AllocatorState *State,
+ uintptr_t ErrorPtr) {
+ assert(State && "State should not be nullptr.");
+ if (State->FailureType != Error::UNKNOWN && State->FailureAddress != 0)
+ return true;
+
+ return ErrorPtr < State->GuardedPagePoolEnd &&
+ State->GuardedPagePool <= ErrorPtr;
+}
+
+uintptr_t
+__gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State) {
+ return State->FailureAddress;
+}
+
+static const AllocationMetadata *
+addrToMetadata(const gwp_asan::AllocatorState *State,
+ const AllocationMetadata *Metadata, uintptr_t Ptr) {
+ // Note - Similar implementation in guarded_pool_allocator.cpp.
+ return &Metadata[State->getNearestSlot(Ptr)];
+}
+
+gwp_asan::Error
+__gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State,
+ const gwp_asan::AllocationMetadata *Metadata,
+ uintptr_t ErrorPtr) {
+ if (!__gwp_asan_error_is_mine(State, ErrorPtr))
+ return Error::UNKNOWN;
+
+ if (State->FailureType != Error::UNKNOWN)
+ return State->FailureType;
+
+ // Let's try and figure out what the source of this error is.
+ if (State->isGuardPage(ErrorPtr)) {
+ size_t Slot = State->getNearestSlot(ErrorPtr);
+ const AllocationMetadata *SlotMeta =
+ addrToMetadata(State, Metadata, State->slotToAddr(Slot));
+
+ // Ensure that this slot was allocated once upon a time.
+ if (!SlotMeta->Addr)
+ return Error::UNKNOWN;
+
+ if (SlotMeta->Addr < ErrorPtr)
+ return Error::BUFFER_OVERFLOW;
+ return Error::BUFFER_UNDERFLOW;
+ }
+
+ // Access wasn't a guard page, check for use-after-free.
+ const AllocationMetadata *SlotMeta =
+ addrToMetadata(State, Metadata, ErrorPtr);
+ if (SlotMeta->IsDeallocated) {
+ return Error::USE_AFTER_FREE;
+ }
+
+ // If we have reached here, the error is still unknown.
+ return Error::UNKNOWN;
+}
+
+const gwp_asan::AllocationMetadata *
+__gwp_asan_get_metadata(const gwp_asan::AllocatorState *State,
+ const gwp_asan::AllocationMetadata *Metadata,
+ uintptr_t ErrorPtr) {
+ if (!__gwp_asan_error_is_mine(State, ErrorPtr))
+ return nullptr;
+
+ if (ErrorPtr >= State->GuardedPagePoolEnd ||
+ State->GuardedPagePool > ErrorPtr)
+ return nullptr;
+
+ const AllocationMetadata *Meta = addrToMetadata(State, Metadata, ErrorPtr);
+ if (Meta->Addr == 0)
+ return nullptr;
+
+ return Meta;
+}
+
+uintptr_t __gwp_asan_get_allocation_address(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->Addr;
+}
+
+size_t __gwp_asan_get_allocation_size(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->Size;
+}
+
+uint64_t __gwp_asan_get_allocation_thread_id(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->AllocationTrace.ThreadID;
+}
+
+size_t __gwp_asan_get_allocation_trace(
+ const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
+ size_t BufferLen) {
+ return gwp_asan::compression::unpack(
+ AllocationMeta->AllocationTrace.CompressedTrace,
+ AllocationMeta->AllocationTrace.TraceSize, Buffer, BufferLen);
+}
+
+bool __gwp_asan_is_deallocated(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->IsDeallocated;
+}
+
+uint64_t __gwp_asan_get_deallocation_thread_id(
+ const gwp_asan::AllocationMetadata *AllocationMeta) {
+ return AllocationMeta->DeallocationTrace.ThreadID;
+}
+
+size_t __gwp_asan_get_deallocation_trace(
+ const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
+ size_t BufferLen) {
+ return gwp_asan::compression::unpack(
+ AllocationMeta->DeallocationTrace.CompressedTrace,
+ AllocationMeta->DeallocationTrace.TraceSize, Buffer, BufferLen);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif