16#if defined CUSTOM_MEMORY_TRACKING
19 #if defined __has_feature
20 #if __has_feature(address_sanitizer)
23 #if __has_feature(memory_sanitizer)
31 #if defined __SANITIZE_ADDRESS__
37 #if defined DC_MSAN_ON
38 #error "cannot support asan and msan simultaneously"
40 #include <sanitizer/asan_interface.h>
41#elif defined DC_MSAN_ON
42 #include <sanitizer/msan_interface.h>
65#if defined CUSTOM_MEMORY_TRACKING
78 const volatile void* addr,
size_t size) {
80#if defined(DC_MSAN_ON)
85 __msan_poison(addr,
size);
89 __msan_unpoison(addr,
size);
94#elif defined(DC_ASAN_ON)
97 __asan_poison_memory_region(addr,
size);
102 __asan_unpoison_memory_region(addr,
size);
120#if defined(DC_MSAN_ON)
125 for (
size_t offset = 0; offset <
size; offset++) {
126 const unsigned char* p = (
const unsigned char*)addr + offset;
131 if (__msan_test_shadow(p, 1) == -1) {
132 DC_PANIC(
"Memory region %p (%zu bytes) is not fully uninitialised: "
133 "byte %zu (%p) is unpoisoned",
134 addr,
size, offset, p);
140 for (
size_t offset = 0; offset <
size; offset++) {
141 const unsigned char* p = (
const unsigned char*)addr + offset;
142 if (__msan_test_shadow(p, 1) != -1) {
143 DC_PANIC(
"Memory region %p (%zu bytes) is not initialised: "
144 "byte %zu (%p) is poisoned",
145 addr,
size, offset, p);
152#elif defined(DC_ASAN_ON)
153 bool const region_is_poisoned = __asan_region_is_poisoned((
void*)(uintptr_t)addr,
size);
156 if (!region_is_poisoned) {
157 const char* addr_char = (
const char*)addr;
159 bool const is_next_byte_poisoned =
160 __asan_region_is_poisoned((
void*)(uintptr_t)(addr_char + 1), 1);
170 if (is_at_end_of_granule || is_next_byte_poisoned) {
172 DC_PANIC(
"Memory region %p (%zu bytes) is not poisoned, but should be", addr,
180 if (region_is_poisoned) {
181 DC_PANIC(
"Memory region %p (%zu bytes) is poisoned, but should be accessible", addr,
197 fprintf(
stream,
"memory tracker debug (%zu bytes) at %p ",
size, addr);
198#if defined DC_MSAN_ON
199 fprintf(
stream,
"[MSAN]:");
201 for (
size_t i = 0; i <
size; i++) {
202 char const* ptr = (
char const*)addr + i;
203 fprintf(
stream,
"\n%p: ", ptr);
204 if (__msan_test_shadow(ptr, 1) != -1) {
205 __msan_unpoison(ptr, 1);
206 fprintf(
stream,
"U [%02x]", *((
unsigned char*)ptr));
207 __msan_poison(ptr, 1);
209 fprintf(
stream,
"I [%02x]", *((
unsigned char*)ptr));
212#elif defined DC_ASAN_ON
214 const char* addr_start = (
const char*)addr;
215 const char* addr_end = addr_start +
size;
216 const char* granule_base =
217 (
const char*)((uintptr_t)addr & ~(uintptr_t)0x7U);
218 const char* granule_end = (
const char*)(((uintptr_t)addr +
size + 7U) &
221 fprintf(
stream,
"[ASAN]:");
223 "\ndisplaying each 8 byte grandule (asan tracks poisoning as 0-8 bytes from the end)");
226 for (
size_t b = 0; b < 8; b++) {
227 fprintf(
stream,
" %lu ", b);
230 for (
const char* p = granule_base; p < granule_end; p += 8) {
231 fprintf(
stream,
"%p: ", p);
232 for (
const char* b = p; b < p + 8; b++) {
233 bool const poisoned = __asan_region_is_poisoned((
void*)(uintptr_t)b, 1);
234 bool const in_selected = (b >= addr_start && b < addr_end);
237 __asan_unpoison_memory_region((
void*)(uintptr_t)b, 1);
239 __asan_poison_memory_region((
void*)(uintptr_t)b, 1);
244 char const status = poisoned ?
'P' :
'U';
247 fprintf(
stream,
"[%c|%02x] ", status, value);
249 fprintf(
stream,
"|%c|%02x| ", status, value);
255 fprintf(
stream,
"[NO TRACKING]");
static DC_PUBLIC size_t size(SELF const *self)
static DC_PUBLIC bool DC_INLINE DC_CONST dc_math_is_aligned_pow2(const void *ptr, unsigned alignment)
static DC_PUBLIC void dc_memory_tracker_set(dc_memory_tracker_level level, dc_memory_tracker_capability cap, const volatile void *addr, size_t size)
static const dc_memory_tracker_level dc_memory_tracker_global_level
static DC_PUBLIC void dc_memory_tracker_check(dc_memory_tracker_level level, dc_memory_tracker_capability cap, const void *addr, size_t size)
static DC_PUBLIC void dc_memory_tracker_debug(FILE *stream, const void *addr, size_t size)
@ DC_MEMORY_TRACKER_LVL_CONTAINER
@ DC_MEMORY_TRACKER_LVL_ALLOC
@ DC_MEMORY_TRACKER_LVL_NONE
dc_memory_tracker_capability
a wrapper over asan & msan Containers and allocators can use this for custom asan & msan poisoning,...
@ DC_MEMORY_TRACKER_CAP_WRITE
@ DC_MEMORY_TRACKER_CAP_NONE
@ DC_MEMORY_TRACKER_CAP_READ_WRITE
#define DC_PANIC(str,...)
#define DC_UNREACHABLE(...)
#define DC_ASSERT(expr,...)
static DC_PUBLIC FILE * stream(SELF *self)