brintos

brintos / linux-shallow public Read only

0
0
Text · 3.4 KiB · f80ddfc Raw
114 lines · c
1/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */2#ifndef __LIBPERF_INTERNAL_RC_CHECK_H3#define __LIBPERF_INTERNAL_RC_CHECK_H4 5#include <stdlib.h>6#include <linux/zalloc.h>7 8/*9 * Enable reference count checking implicitly with leak checking, which is10 * integrated into address sanitizer.11 */12#if defined(__SANITIZE_ADDRESS__) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)13#define REFCNT_CHECKING 114#elif defined(__has_feature)15#if __has_feature(address_sanitizer) || __has_feature(leak_sanitizer)16#define REFCNT_CHECKING 117#endif18#endif19 20/*21 * Shared reference count checking macros.22 *23 * Reference count checking is an approach to sanitizing the use of reference24 * counted structs. It leverages address and leak sanitizers to make sure gets25 * are paired with a put. Reference count checking adds a malloc-ed layer of26 * indirection on a get, and frees it on a put. A missed put will be reported as27 * a memory leak. A double put will be reported as a double free. Accessing28 * after a put will cause a use-after-free and/or a segfault.29 */30 31#ifndef REFCNT_CHECKING32/* Replaces "struct foo" so that the pointer may be interposed. */33#define DECLARE_RC_STRUCT(struct_name)		\34	struct struct_name35 36/* Declare a reference counted struct variable. */37#define RC_STRUCT(struct_name) struct struct_name38 39/*40 * Interpose the indirection. Result will hold the indirection and object is the41 * 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) object47 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#else61 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_name69 70/* Declare a reference counted struct variable. */71#define RC_STRUCT(struct_name) struct original_##struct_name72 73/*74 * Interpose the indirection. Result will hold the indirection and object is the75 * 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->orig87 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#endif112 113#endif /* __LIBPERF_INTERNAL_RC_CHECK_H */114