xref: /freebsd/contrib/llvm-project/compiler-rt/lib/scudo/standalone/include/scudo/interface.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1 //===-- scudo/interface.h ---------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef SCUDO_INTERFACE_H_
10 #define SCUDO_INTERFACE_H_
11 
12 #include <stddef.h>
13 #include <stdint.h>
14 
15 extern "C" {
16 
17 __attribute__((weak)) const char *__scudo_default_options(void);
18 
19 // Post-allocation & pre-deallocation hooks.
20 __attribute__((weak)) void __scudo_allocate_hook(void *ptr, size_t size);
21 __attribute__((weak)) void __scudo_deallocate_hook(void *ptr);
22 
23 // `realloc` involves both deallocation and allocation but they are not reported
24 // atomically. In one specific case which may keep taking a snapshot right in
25 // the middle of `realloc` reporting the deallocation and allocation, it may
26 // confuse the user by missing memory from `realloc`. To alleviate that case,
27 // define the two `realloc` hooks to get the knowledge of the bundled hook
28 // calls. These hooks are optional and should only be used when a hooks user
29 // wants to track reallocs more closely.
30 //
31 // See more details in the comment of `realloc` in wrapper_c.inc.
32 __attribute__((weak)) void
33 __scudo_realloc_allocate_hook(void *old_ptr, void *new_ptr, size_t size);
34 __attribute__((weak)) void __scudo_realloc_deallocate_hook(void *old_ptr);
35 
36 void __scudo_print_stats(void);
37 
38 typedef void (*iterate_callback)(uintptr_t base, size_t size, void *arg);
39 
40 // Determine the likely cause of a tag check fault or other memory protection
41 // error on a system with memory tagging support. The results are returned via
42 // the error_info data structure. Up to three possible causes are returned in
43 // the reports array, in decreasing order of probability. The remaining elements
44 // of reports are zero-initialized.
45 //
46 // This function may be called from a different process from the one that
47 // crashed. In this case, various data structures must be copied from the
48 // crashing process to the process that analyzes the crash.
49 //
50 // This interface is not guaranteed to be stable and may change at any time.
51 // Furthermore, the version of scudo in the crashing process must be the same as
52 // the version in the process that analyzes the crash.
53 //
54 // fault_addr is the fault address. On aarch64 this is available in the system
55 // register FAR_ELx, or siginfo.si_addr in Linux 5.11 or above. This address
56 // must include the pointer tag; this is available if SA_EXPOSE_TAGBITS was set
57 // in sigaction.sa_flags when the signal handler was registered. Note that the
58 // kernel strips the tag from the field sigcontext.fault_address, so this
59 // address is not suitable to be passed as fault_addr.
60 //
61 // stack_depot is a pointer to the stack depot data structure, which may be
62 // obtained by calling the function __scudo_get_stack_depot_addr() in the
63 // crashing process. The size of the stack depot is available by calling the
64 // function __scudo_get_stack_depot_size().
65 //
66 // region_info is a pointer to the region info data structure, which may be
67 // obtained by calling the function __scudo_get_region_info_addr() in the
68 // crashing process. The size of the region info is available by calling the
69 // function __scudo_get_region_info_size().
70 //
71 // memory is a pointer to a region of memory surrounding the fault address.
72 // The more memory available via this pointer, the more likely it is that the
73 // function will be able to analyze a crash correctly. It is recommended to
74 // provide an amount of memory equal to 16 * the primary allocator's largest
75 // size class either side of the fault address.
76 //
77 // memory_tags is a pointer to an array of memory tags for the memory accessed
78 // via memory. Each byte of this array corresponds to a region of memory of size
79 // equal to the architecturally defined memory tag granule size (16 on aarch64).
80 //
81 // memory_addr is the start address of memory in the crashing process's address
82 // space.
83 //
84 // memory_size is the size of the memory region referred to by the memory
85 // pointer.
86 void __scudo_get_error_info(struct scudo_error_info *error_info,
87                             uintptr_t fault_addr, const char *stack_depot,
88                             size_t stack_depot_size, const char *region_info,
89                             const char *ring_buffer, size_t ring_buffer_size,
90                             const char *memory, const char *memory_tags,
91                             uintptr_t memory_addr, size_t memory_size);
92 
93 enum scudo_error_type {
94   UNKNOWN,
95   USE_AFTER_FREE,
96   BUFFER_OVERFLOW,
97   BUFFER_UNDERFLOW,
98 };
99 
100 struct scudo_error_report {
101   enum scudo_error_type error_type;
102 
103   uintptr_t allocation_address;
104   uintptr_t allocation_size;
105 
106   uint32_t allocation_tid;
107   uintptr_t allocation_trace[64];
108 
109   uint32_t deallocation_tid;
110   uintptr_t deallocation_trace[64];
111 };
112 
113 struct scudo_error_info {
114   struct scudo_error_report reports[3];
115 };
116 
117 const char *__scudo_get_stack_depot_addr(void);
118 size_t __scudo_get_stack_depot_size(void);
119 
120 const char *__scudo_get_region_info_addr(void);
121 size_t __scudo_get_region_info_size(void);
122 
123 const char *__scudo_get_ring_buffer_addr(void);
124 size_t __scudo_get_ring_buffer_size(void);
125 
126 #ifndef M_DECAY_TIME
127 #define M_DECAY_TIME -100
128 #endif
129 
130 #ifndef M_PURGE
131 #define M_PURGE -101
132 #endif
133 
134 #ifndef M_PURGE_ALL
135 #define M_PURGE_ALL -104
136 #endif
137 
138 // Tune the allocator's choice of memory tags to make it more likely that
139 // a certain class of memory errors will be detected. The value argument should
140 // be one of the M_MEMTAG_TUNING_* constants below.
141 #ifndef M_MEMTAG_TUNING
142 #define M_MEMTAG_TUNING -102
143 #endif
144 
145 // Per-thread memory initialization tuning. The value argument should be one of:
146 // 1: Disable automatic heap initialization and, where possible, memory tagging,
147 //    on this thread.
148 // 0: Normal behavior.
149 #ifndef M_THREAD_DISABLE_MEM_INIT
150 #define M_THREAD_DISABLE_MEM_INIT -103
151 #endif
152 
153 #ifndef M_CACHE_COUNT_MAX
154 #define M_CACHE_COUNT_MAX -200
155 #endif
156 
157 #ifndef M_CACHE_SIZE_MAX
158 #define M_CACHE_SIZE_MAX -201
159 #endif
160 
161 #ifndef M_TSDS_COUNT_MAX
162 #define M_TSDS_COUNT_MAX -202
163 #endif
164 
165 // Tune for buffer overflows.
166 #ifndef M_MEMTAG_TUNING_BUFFER_OVERFLOW
167 #define M_MEMTAG_TUNING_BUFFER_OVERFLOW 0
168 #endif
169 
170 // Tune for use-after-free.
171 #ifndef M_MEMTAG_TUNING_UAF
172 #define M_MEMTAG_TUNING_UAF 1
173 #endif
174 
175 // Print internal stats to the log.
176 #ifndef M_LOG_STATS
177 #define M_LOG_STATS -205
178 #endif
179 
180 } // extern "C"
181 
182 #endif // SCUDO_INTERFACE_H_
183