Loading...
Note: File does not exist in v3.15.
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 */