| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
- #ifndef __LIBPERF_INTERNAL_RC_CHECK_H
- #define __LIBPERF_INTERNAL_RC_CHECK_H
- #include <stdlib.h>
- #include <linux/zalloc.h>
- /*
- * Enable reference count checking implicitly with leak checking, which is
- * integrated into address sanitizer.
- */
- #if defined(__SANITIZE_ADDRESS__) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
- #define REFCNT_CHECKING 1
- #elif defined(__has_feature)
- #if __has_feature(address_sanitizer) || __has_feature(leak_sanitizer)
- #define REFCNT_CHECKING 1
- #endif
- #endif
- /*
- * Shared reference count checking macros.
- *
- * Reference count checking is an approach to sanitizing the use of reference
- * counted structs. It leverages address and leak sanitizers to make sure gets
- * are paired with a put. Reference count checking adds a malloc-ed layer of
- * indirection on a get, and frees it on a put. A missed put will be reported as
- * a memory leak. A double put will be reported as a double free. Accessing
- * after a put will cause a use-after-free and/or a segfault.
- */
- #ifndef REFCNT_CHECKING
- /* Replaces "struct foo" so that the pointer may be interposed. */
- #define DECLARE_RC_STRUCT(struct_name) \
- struct struct_name
- /* Declare a reference counted struct variable. */
- #define RC_STRUCT(struct_name) struct struct_name
- /*
- * Interpose the indirection. Result will hold the indirection and object is the
- * reference counted struct.
- */
- #define ADD_RC_CHK(result, object) (result = object, object)
- /* Strip the indirection layer. */
- #define RC_CHK_ACCESS(object) object
- /* Frees the object and the indirection layer. */
- #define RC_CHK_FREE(object) free(object)
- /* A get operation adding the indirection layer. */
- #define RC_CHK_GET(result, object) ADD_RC_CHK(result, object)
- /* A put operation removing the indirection layer. */
- #define RC_CHK_PUT(object) {}
- /* Pointer equality when the indirection may or may not be there. */
- #define RC_CHK_EQUAL(object1, object2) (object1 == object2)
- #else
- /* Replaces "struct foo" so that the pointer may be interposed. */
- #define DECLARE_RC_STRUCT(struct_name) \
- struct original_##struct_name; \
- struct struct_name { \
- struct original_##struct_name *orig; \
- }; \
- struct original_##struct_name
- /* Declare a reference counted struct variable. */
- #define RC_STRUCT(struct_name) struct original_##struct_name
- /*
- * Interpose the indirection. Result will hold the indirection and object is the
- * reference counted struct.
- */
- #define ADD_RC_CHK(result, object) \
- ( \
- object ? (result = malloc(sizeof(*result)), \
- result ? (result->orig = object, result) \
- : (result = NULL, NULL)) \
- : (result = NULL, NULL) \
- )
- /* Strip the indirection layer. */
- #define RC_CHK_ACCESS(object) object->orig
- /* Frees the object and the indirection layer. */
- #define RC_CHK_FREE(object) \
- do { \
- zfree(&object->orig); \
- free(object); \
- } while(0)
- /* A get operation adding the indirection layer. */
- #define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL))
- /* A put operation removing the indirection layer. */
- #define RC_CHK_PUT(object) \
- do { \
- if (object) { \
- object->orig = NULL; \
- free(object); \
- } \
- } while(0)
- /* Pointer equality when the indirection may or may not be there. */
- #define RC_CHK_EQUAL(object1, object2) (object1 == object2 || \
- (object1 && object2 && object1->orig == object2->orig))
- #endif
- #endif /* __LIBPERF_INTERNAL_RC_CHECK_H */
|