xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/gwp_asan/crash_handler.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1e8d8bef9SDimitry Andric //===-- crash_handler.h -----------------------------------------*- C++ -*-===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric // This file contains interface functions that can be called by an in-process or
105ffd83dbSDimitry Andric // out-of-process crash handler after the process has terminated. Functions in
115ffd83dbSDimitry Andric // this interface are never thread safe. For an in-process crash handler, the
125ffd83dbSDimitry Andric // handler should call GuardedPoolAllocator::disable() to stop any other threads
135ffd83dbSDimitry Andric // from retrieving new GWP-ASan allocations, which may corrupt the metadata.
145ffd83dbSDimitry Andric #ifndef GWP_ASAN_INTERFACE_H_
155ffd83dbSDimitry Andric #define GWP_ASAN_INTERFACE_H_
165ffd83dbSDimitry Andric 
175ffd83dbSDimitry Andric #include "gwp_asan/common.h"
185ffd83dbSDimitry Andric 
195ffd83dbSDimitry Andric #ifdef __cplusplus
205ffd83dbSDimitry Andric extern "C" {
215ffd83dbSDimitry Andric #endif
225ffd83dbSDimitry Andric 
235ffd83dbSDimitry Andric // When a process crashes, there are three possible outcomes:
245ffd83dbSDimitry Andric //  1. The crash is unrelated to GWP-ASan - in which case this function returns
255ffd83dbSDimitry Andric //     false.
265ffd83dbSDimitry Andric //  2. The crash is internally detected within GWP-ASan itself (e.g. a
275ffd83dbSDimitry Andric //     double-free bug is caught in GuardedPoolAllocator::deallocate(), and
285ffd83dbSDimitry Andric //     GWP-ASan will terminate the process). In this case - this function
295ffd83dbSDimitry Andric //     returns true.
305ffd83dbSDimitry Andric //  3. The crash is caused by a memory error at `AccessPtr` that's caught by the
315ffd83dbSDimitry Andric //     system, but GWP-ASan is responsible for the allocation. In this case -
325ffd83dbSDimitry Andric //     the function also returns true.
335ffd83dbSDimitry Andric // This function takes an optional `AccessPtr` parameter. If the pointer that
345ffd83dbSDimitry Andric // was attempted to be accessed is available, you should provide it here. In the
355ffd83dbSDimitry Andric // case of some internally-detected errors, the crash may manifest as an abort
365ffd83dbSDimitry Andric // or trap may or may not have an associated pointer. In these cases, the
375ffd83dbSDimitry Andric // pointer can be obtained by a call to __gwp_asan_get_internal_crash_address.
385ffd83dbSDimitry Andric bool __gwp_asan_error_is_mine(const gwp_asan::AllocatorState *State,
395ffd83dbSDimitry Andric                               uintptr_t ErrorPtr = 0u);
405ffd83dbSDimitry Andric 
415ffd83dbSDimitry Andric // Diagnose and return the type of error that occurred at `ErrorPtr`. If
425ffd83dbSDimitry Andric // `ErrorPtr` is unrelated to GWP-ASan, or if the error type cannot be deduced,
435ffd83dbSDimitry Andric // this function returns Error::UNKNOWN.
445ffd83dbSDimitry Andric gwp_asan::Error
455ffd83dbSDimitry Andric __gwp_asan_diagnose_error(const gwp_asan::AllocatorState *State,
465ffd83dbSDimitry Andric                           const gwp_asan::AllocationMetadata *Metadata,
475ffd83dbSDimitry Andric                           uintptr_t ErrorPtr);
485ffd83dbSDimitry Andric 
49*bdd1243dSDimitry Andric // This function, provided the fault address from the signal handler, returns
50*bdd1243dSDimitry Andric // the following values:
51*bdd1243dSDimitry Andric //  1. If the crash was caused by an internally-detected error (invalid free,
52*bdd1243dSDimitry Andric //     double free), this function returns the pointer that was used for the
53*bdd1243dSDimitry Andric //     internally-detected bad operation (i.e. the pointer given to free()).
54*bdd1243dSDimitry Andric //  2. For externally-detected crashes (use-after-free, buffer-overflow), this
55*bdd1243dSDimitry Andric //     function returns zero.
56*bdd1243dSDimitry Andric //  3. If GWP-ASan wasn't responsible for the crash at all, this function also
57*bdd1243dSDimitry Andric //     returns zero.
585ffd83dbSDimitry Andric uintptr_t
59*bdd1243dSDimitry Andric __gwp_asan_get_internal_crash_address(const gwp_asan::AllocatorState *State,
60*bdd1243dSDimitry Andric                                       uintptr_t ErrorPtr);
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric // Returns a pointer to the metadata for the allocation that's responsible for
635ffd83dbSDimitry Andric // the crash. This metadata should not be dereferenced directly due to API
645ffd83dbSDimitry Andric // compatibility issues, but should be instead passed to functions below for
655ffd83dbSDimitry Andric // information retrieval. Returns nullptr if there is no metadata available for
665ffd83dbSDimitry Andric // this crash.
675ffd83dbSDimitry Andric const gwp_asan::AllocationMetadata *
685ffd83dbSDimitry Andric __gwp_asan_get_metadata(const gwp_asan::AllocatorState *State,
695ffd83dbSDimitry Andric                         const gwp_asan::AllocationMetadata *Metadata,
705ffd83dbSDimitry Andric                         uintptr_t ErrorPtr);
715ffd83dbSDimitry Andric 
725ffd83dbSDimitry Andric // +---------------------------------------------------------------------------+
735ffd83dbSDimitry Andric // | Error Information Functions                                               |
745ffd83dbSDimitry Andric // +---------------------------------------------------------------------------+
755ffd83dbSDimitry Andric // Functions below return information about the type of error that was caught by
765ffd83dbSDimitry Andric // GWP-ASan, or information about the allocation that caused the error. These
775ffd83dbSDimitry Andric // functions generally take an `AllocationMeta` argument, which should be
785ffd83dbSDimitry Andric // retrieved via. __gwp_asan_get_metadata.
795ffd83dbSDimitry Andric 
805ffd83dbSDimitry Andric // Returns the start of the allocation whose metadata is in `AllocationMeta`.
815ffd83dbSDimitry Andric uintptr_t __gwp_asan_get_allocation_address(
825ffd83dbSDimitry Andric     const gwp_asan::AllocationMetadata *AllocationMeta);
835ffd83dbSDimitry Andric 
845ffd83dbSDimitry Andric // Returns the size of the allocation whose metadata is in `AllocationMeta`
855ffd83dbSDimitry Andric size_t __gwp_asan_get_allocation_size(
865ffd83dbSDimitry Andric     const gwp_asan::AllocationMetadata *AllocationMeta);
875ffd83dbSDimitry Andric 
885ffd83dbSDimitry Andric // Returns the Thread ID that allocated the memory that caused the error at
895ffd83dbSDimitry Andric // `ErrorPtr`. This function may not be called if __gwp_asan_has_metadata()
905ffd83dbSDimitry Andric // returns false.
915ffd83dbSDimitry Andric uint64_t __gwp_asan_get_allocation_thread_id(
925ffd83dbSDimitry Andric     const gwp_asan::AllocationMetadata *AllocationMeta);
935ffd83dbSDimitry Andric 
945ffd83dbSDimitry Andric // Retrieve the allocation trace for the allocation whose metadata is in
955ffd83dbSDimitry Andric // `AllocationMeta`, and place it into the provided `Buffer` that has at least
965ffd83dbSDimitry Andric // `BufferLen` elements. This function returns the number of frames that would
975ffd83dbSDimitry Andric // have been written into `Buffer` if the space was available (i.e. however many
985ffd83dbSDimitry Andric // frames were stored by GWP-ASan). A return value greater than `BufferLen`
995ffd83dbSDimitry Andric // indicates that the trace was truncated when storing to `Buffer`.
1005ffd83dbSDimitry Andric size_t __gwp_asan_get_allocation_trace(
1015ffd83dbSDimitry Andric     const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
1025ffd83dbSDimitry Andric     size_t BufferLen);
1035ffd83dbSDimitry Andric 
1045ffd83dbSDimitry Andric // Returns whether the allocation whose metadata is in `AllocationMeta` has been
1055ffd83dbSDimitry Andric // deallocated. This function may not be called if __gwp_asan_has_metadata()
1065ffd83dbSDimitry Andric // returns false.
1075ffd83dbSDimitry Andric bool __gwp_asan_is_deallocated(
1085ffd83dbSDimitry Andric     const gwp_asan::AllocationMetadata *AllocationMeta);
1095ffd83dbSDimitry Andric 
1105ffd83dbSDimitry Andric // Returns the Thread ID that deallocated the memory whose metadata is in
1115ffd83dbSDimitry Andric // `AllocationMeta`. This function may not be called if
1125ffd83dbSDimitry Andric // __gwp_asan_is_deallocated() returns false.
1135ffd83dbSDimitry Andric uint64_t __gwp_asan_get_deallocation_thread_id(
1145ffd83dbSDimitry Andric     const gwp_asan::AllocationMetadata *AllocationMeta);
1155ffd83dbSDimitry Andric 
1165ffd83dbSDimitry Andric // Retrieve the deallocation trace for the allocation whose metadata is in
1175ffd83dbSDimitry Andric // `AllocationMeta`, and place it into the provided `Buffer` that has at least
1185ffd83dbSDimitry Andric // `BufferLen` elements. This function returns the number of frames that would
1195ffd83dbSDimitry Andric // have been written into `Buffer` if the space was available (i.e. however many
1205ffd83dbSDimitry Andric // frames were stored by GWP-ASan). A return value greater than `BufferLen`
1215ffd83dbSDimitry Andric // indicates that the trace was truncated when storing to `Buffer`. This
1225ffd83dbSDimitry Andric // function may not be called if __gwp_asan_is_deallocated() returns false.
1235ffd83dbSDimitry Andric size_t __gwp_asan_get_deallocation_trace(
1245ffd83dbSDimitry Andric     const gwp_asan::AllocationMetadata *AllocationMeta, uintptr_t *Buffer,
1255ffd83dbSDimitry Andric     size_t BufferLen);
1265ffd83dbSDimitry Andric 
1275ffd83dbSDimitry Andric #ifdef __cplusplus
1285ffd83dbSDimitry Andric } // extern "C"
1295ffd83dbSDimitry Andric #endif
1305ffd83dbSDimitry Andric 
1315ffd83dbSDimitry Andric #endif // GWP_ASAN_INTERFACE_H_
132