Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
13#define REFCNT_CHECKING 1
14#endif
15
16/*
17 * Shared reference count checking macros.
18 *
19 * Reference count checking is an approach to sanitizing the use of reference
20 * counted structs. It leverages address and leak sanitizers to make sure gets
21 * are paired with a put. Reference count checking adds a malloc-ed layer of
22 * indirection on a get, and frees it on a put. A missed put will be reported as
23 * a memory leak. A double put will be reported as a double free. Accessing
24 * after a put will cause a use-after-free and/or a segfault.
25 */
26
27#ifndef REFCNT_CHECKING
28/* Replaces "struct foo" so that the pointer may be interposed. */
29#define DECLARE_RC_STRUCT(struct_name) \
30 struct struct_name
31
32/* Declare a reference counted struct variable. */
33#define RC_STRUCT(struct_name) struct struct_name
34
35/*
36 * Interpose the indirection. Result will hold the indirection and object is the
37 * reference counted struct.
38 */
39#define ADD_RC_CHK(result, object) (result = object, object)
40
41/* Strip the indirection layer. */
42#define RC_CHK_ACCESS(object) object
43
44/* Frees the object and the indirection layer. */
45#define RC_CHK_FREE(object) free(object)
46
47/* A get operation adding the indirection layer. */
48#define RC_CHK_GET(result, object) ADD_RC_CHK(result, object)
49
50/* A put operation removing the indirection layer. */
51#define RC_CHK_PUT(object) {}
52
53#else
54
55/* Replaces "struct foo" so that the pointer may be interposed. */
56#define DECLARE_RC_STRUCT(struct_name) \
57 struct original_##struct_name; \
58 struct struct_name { \
59 struct original_##struct_name *orig; \
60 }; \
61 struct original_##struct_name
62
63/* Declare a reference counted struct variable. */
64#define RC_STRUCT(struct_name) struct original_##struct_name
65
66/*
67 * Interpose the indirection. Result will hold the indirection and object is the
68 * reference counted struct.
69 */
70#define ADD_RC_CHK(result, object) \
71 ( \
72 object ? (result = malloc(sizeof(*result)), \
73 result ? (result->orig = object, result) \
74 : (result = NULL, NULL)) \
75 : (result = NULL, NULL) \
76 )
77
78/* Strip the indirection layer. */
79#define RC_CHK_ACCESS(object) object->orig
80
81/* Frees the object and the indirection layer. */
82#define RC_CHK_FREE(object) \
83 do { \
84 zfree(&object->orig); \
85 free(object); \
86 } while(0)
87
88/* A get operation adding the indirection layer. */
89#define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL))
90
91/* A put operation removing the indirection layer. */
92#define RC_CHK_PUT(object) \
93 do { \
94 if (object) { \
95 object->orig = NULL; \
96 free(object); \
97 } \
98 } while(0)
99
100#endif
101
102#endif /* __LIBPERF_INTERNAL_RC_CHECK_H */