diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2021-01-02 17:10:12 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2021-01-02 17:10:12 +0000 |
commit | ac63a3868d0079ed93660b89b2c6e6dbf67aea16 (patch) | |
tree | 7f055322abddaf10c9dbd7cbeb91c8f83d78e301 /gnu/llvm/compiler-rt/lib/gwp_asan/crash_handler.cpp | |
parent | becf90779831a234f9200480d6009ecb39ebb192 (diff) |
Import compiler-rt 11.0.0 release.
ok kettenis@
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.cpp | 140 |
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 |