Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/lib/perf/include/internal/rc_check.h
26302 views
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
115