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/* Pointer equality when the indirection may or may not be there. */ 58#define RC_CHK_EQUAL(object1, object2) (object1 == object2) 59 60#else 61 62/* Replaces "struct foo" so that the pointer may be interposed. */ 63#define DECLARE_RC_STRUCT(struct_name) \ 64 struct original_##struct_name; \ 65 struct struct_name { \ 66 struct original_##struct_name *orig; \ 67 }; \ 68 struct original_##struct_name 69 70/* Declare a reference counted struct variable. */ 71#define RC_STRUCT(struct_name) struct original_##struct_name 72 73/* 74 * Interpose the indirection. Result will hold the indirection and object is the 75 * reference counted struct. 76 */ 77#define ADD_RC_CHK(result, object) \ 78 ( \ 79 object ? (result = malloc(sizeof(*result)), \ 80 result ? (result->orig = object, result) \ 81 : (result = NULL, NULL)) \ 82 : (result = NULL, NULL) \ 83 ) 84 85/* Strip the indirection layer. */ 86#define RC_CHK_ACCESS(object) object->orig 87 88/* Frees the object and the indirection layer. */ 89#define RC_CHK_FREE(object) \ 90 do { \ 91 zfree(&object->orig); \ 92 free(object); \ 93 } while(0) 94 95/* A get operation adding the indirection layer. */ 96#define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL)) 97 98/* A put operation removing the indirection layer. */ 99#define RC_CHK_PUT(object) \ 100 do { \ 101 if (object) { \ 102 object->orig = NULL; \ 103 free(object); \ 104 } \ 105 } while(0) 106 107/* Pointer equality when the indirection may or may not be there. */ 108#define RC_CHK_EQUAL(object1, object2) (object1 == object2 || \ 109 (object1 && object2 && object1->orig == object2->orig)) 110 111#endif 112 113#endif /* __LIBPERF_INTERNAL_RC_CHECK_H */ 114