| 1 |
|
| 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 |
|
| 33 | #define DECLARE_RC_STRUCT(struct_name) \
|
| 34 | struct struct_name
|
| 35 |
|
| 36 |
|
| 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 |
|
| 46 | #define RC_CHK_ACCESS(object) object
|
| 47 |
|
| 48 |
|
| 49 | #define RC_CHK_FREE(object) free(object)
|
| 50 |
|
| 51 |
|
| 52 | #define RC_CHK_GET(result, object) ADD_RC_CHK(result, object)
|
| 53 |
|
| 54 |
|
| 55 | #define RC_CHK_PUT(object) {}
|
| 56 |
|
| 57 |
|
| 58 | #define RC_CHK_EQUAL(object1, object2) (object1 == object2)
|
| 59 |
|
| 60 | #else
|
| 61 |
|
| 62 |
|
| 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 |
|
| 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 |
|
| 86 | #define RC_CHK_ACCESS(object) object->orig
|
| 87 |
|
| 88 |
|
| 89 | #define RC_CHK_FREE(object) \
|
| 90 | do { \
|
| 91 | zfree(&object->orig); \
|
| 92 | free(object); \
|
| 93 | } while(0)
|
| 94 |
|
| 95 |
|
| 96 | #define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL))
|
| 97 |
|
| 98 |
|
| 99 | #define RC_CHK_PUT(object) \
|
| 100 | do { \
|
| 101 | if (object) { \
|
| 102 | object->orig = NULL; \
|
| 103 | free(object); \
|
| 104 | } \
|
| 105 | } while(0)
|
| 106 |
|
| 107 |
|
| 108 | #define RC_CHK_EQUAL(object1, object2) (object1 == object2 || \
|
| 109 | (object1 && object2 && object1->orig == object2->orig))
|
| 110 |
|
| 111 | #endif
|
| 112 |
|
| 113 | #endif
|