1 //===-- crash_handler_interface.cpp -----------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "gwp_asan/common.h"
10 #include "gwp_asan/stack_trace_compressor.h"
14 using AllocationMetadata = gwp_asan::AllocationMetadata;
15 using Error = gwp_asan::Error;
21 bool __gwp_asan_error_is_mine(const gwp_asan::AllocatorState *State,
23 assert(State && "State should not be nullptr.");
24 if (State->FailureType != Error::UNKNOWN && State->FailureAddress != 0)
27 return ErrorPtr < State->GuardedPagePoolEnd &&
28 State->GuardedPagePool <= ErrorPtr;
32 __gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State) {
33 return State->FailureAddress;
36 static const AllocationMetadata *
37 addrToMetadata(const gwp_asan::AllocatorState *State,
38 const AllocationMetadata *Metadata, uintptr_t Ptr) {
39 // Note - Similar implementation in guarded_pool_allocator.cpp.
40 return &Metadata[State->getNearestSlot(Ptr)];
44 __gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State,
45 const gwp_asan::AllocationMetadata *Metadata,
47 if (!__gwp_asan_error_is_mine(State, ErrorPtr))
48 return Error::UNKNOWN;
50 if (State->FailureType != Error::UNKNOWN)
51 return State->FailureType;
53 // Let's try and figure out what the source of this error is.
54 if (State->isGuardPage(ErrorPtr)) {
55 size_t Slot = State->getNearestSlot(ErrorPtr);
56 const AllocationMetadata *SlotMeta =
57 addrToMetadata(State, Metadata, State->slotToAddr(Slot));
59 // Ensure that this slot was allocated once upon a time.
61 return Error::UNKNOWN;
63 if (SlotMeta->Addr < ErrorPtr)
64 return Error::BUFFER_OVERFLOW;
65 return Error::BUFFER_UNDERFLOW;
68 // Access wasn't a guard page, check for use-after-free.
69 const AllocationMetadata *SlotMeta =
70 addrToMetadata(State, Metadata, ErrorPtr);
71 if (SlotMeta->IsDeallocated) {
72 return Error::USE_AFTER_FREE;
75 // If we have reached here, the error is still unknown.
76 return Error::UNKNOWN;
79 const gwp_asan::AllocationMetadata *
80 __gwp_asan_get_metadata(const gwp_asan::AllocatorState *State,
81 const gwp_asan::AllocationMetadata *Metadata,
83 if (!__gwp_asan_error_is_mine(State, ErrorPtr))
86 if (ErrorPtr >= State->GuardedPagePoolEnd ||
87 State->GuardedPagePool > ErrorPtr)
90 const AllocationMetadata *Meta = addrToMetadata(State, Metadata, ErrorPtr);
97 uintptr_t __gwp_asan_get_allocation_address(
98 const gwp_asan::AllocationMetadata *AllocationMeta) {
99 return AllocationMeta->Addr;
102 size_t __gwp_asan_get_allocation_size(
103 const gwp_asan::AllocationMetadata *AllocationMeta) {
104 return AllocationMeta->Size;
107 uint64_t __gwp_asan_get_allocation_thread_id(
108 const gwp_asan::AllocationMetadata *AllocationMeta) {
109 return AllocationMeta->AllocationTrace.ThreadID;
112 size_t __gwp_asan_get_allocation_trace(
113 const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
115 return gwp_asan::compression::unpack(
116 AllocationMeta->AllocationTrace.CompressedTrace,
117 AllocationMeta->AllocationTrace.TraceSize, Buffer, BufferLen);
120 bool __gwp_asan_is_deallocated(
121 const gwp_asan::AllocationMetadata *AllocationMeta) {
122 return AllocationMeta->IsDeallocated;
125 uint64_t __gwp_asan_get_deallocation_thread_id(
126 const gwp_asan::AllocationMetadata *AllocationMeta) {
127 return AllocationMeta->DeallocationTrace.ThreadID;
130 size_t __gwp_asan_get_deallocation_trace(
131 const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
133 return gwp_asan::compression::unpack(
134 AllocationMeta->DeallocationTrace.CompressedTrace,
135 AllocationMeta->DeallocationTrace.TraceSize, Buffer, BufferLen);