1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 #ifndef __LIBPERF_INTERNAL_RC_CHECK_H 3 #define __LIBPERF_INTERNAL_RC_CHECK_H 4 5 #include <stdlib.h> 6 #include <linux/zalloc.h> 7 8 /* 9 * Enable reference count checking implicitly with leak checking, which is 10 * integrated into address sanitizer. 11 */ 12 #if defined(__SANITIZE_ADDRESS__) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) 13 #define REFCNT_CHECKING 1 14 #elif defined(__has_feature) 15 #if __has_feature(address_sanitizer) || __has_feature(leak_sanitizer) 16 #define REFCNT_CHECKING 1 17 #endif 18 #endif 19 20 /* 21 * Shared reference count checking macros. 22 * 23 * Reference count checking is an approach to sanitizing the use of reference 24 * counted structs. It leverages address and leak sanitizers to make sure gets 25 * are paired with a put. Reference count checking adds a malloc-ed layer of 26 * indirection on a get, and frees it on a put. A missed put will be reported as 27 * a memory leak. A double put will be reported as a double free. Accessing 28 * after a put will cause a use-after-free and/or a segfault. 29 */ 30 31 #ifndef REFCNT_CHECKING 32 /* Replaces "struct foo" so that the pointer may be interposed. */ 33 #define DECLARE_RC_STRUCT(struct_name) \ 34 struct struct_name 35 36 /* Declare a reference counted struct variable. */ 37 #define RC_STRUCT(struct_name) struct struct_name 38 39 /* 40 * Interpose the indirection. Result will hold the indirection and object is the 41 * reference counted struct. 42 */ 43 #define ADD_RC_CHK(result, object) (result = object, object) 44 45 /* Strip the indirection layer. */ 46 #define RC_CHK_ACCESS(object) object 47 48 /* Frees the object and the indirection layer. */ 49 #define RC_CHK_FREE(object) free(object) 50 51 /* A get operation adding the indirection layer. */ 52 #define RC_CHK_GET(result, object) ADD_RC_CHK(result, object) 53 54 /* A put operation removing the indirection layer. */ 55 #define RC_CHK_PUT(object) {} 56 57 #else 58 59 /* Replaces "struct foo" so that the pointer may be interposed. */ 60 #define DECLARE_RC_STRUCT(struct_name) \ 61 struct original_##struct_name; \ 62 struct struct_name { \ 63 struct original_##struct_name *orig; \ 64 }; \ 65 struct original_##struct_name 66 67 /* Declare a reference counted struct variable. */ 68 #define RC_STRUCT(struct_name) struct original_##struct_name 69 70 /* 71 * Interpose the indirection. Result will hold the indirection and object is the 72 * reference counted struct. 73 */ 74 #define ADD_RC_CHK(result, object) \ 75 ( \ 76 object ? (result = malloc(sizeof(*result)), \ 77 result ? (result->orig = object, result) \ 78 : (result = NULL, NULL)) \ 79 : (result = NULL, NULL) \ 80 ) 81 82 /* Strip the indirection layer. */ 83 #define RC_CHK_ACCESS(object) object->orig 84 85 /* Frees the object and the indirection layer. */ 86 #define RC_CHK_FREE(object) \ 87 do { \ 88 zfree(&object->orig); \ 89 free(object); \ 90 } while(0) 91 92 /* A get operation adding the indirection layer. */ 93 #define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL)) 94 95 /* A put operation removing the indirection layer. */ 96 #define RC_CHK_PUT(object) \ 97 do { \ 98 if (object) { \ 99 object->orig = NULL; \ 100 free(object); \ 101 } \ 102 } while(0) 103 104 #endif 105 106 #endif /* __LIBPERF_INTERNAL_RC_CHECK_H */ 107