rc_check.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. #include <stdlib.h>
  5. #include <linux/zalloc.h>
  6. /*
  7. * Enable reference count checking implicitly with leak checking, which is
  8. * integrated into address sanitizer.
  9. */
  10. #if defined(__SANITIZE_ADDRESS__) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
  11. #define REFCNT_CHECKING 1
  12. #elif defined(__has_feature)
  13. #if __has_feature(address_sanitizer) || __has_feature(leak_sanitizer)
  14. #define REFCNT_CHECKING 1
  15. #endif
  16. #endif
  17. /*
  18. * Shared reference count checking macros.
  19. *
  20. * Reference count checking is an approach to sanitizing the use of reference
  21. * counted structs. It leverages address and leak sanitizers to make sure gets
  22. * are paired with a put. Reference count checking adds a malloc-ed layer of
  23. * indirection on a get, and frees it on a put. A missed put will be reported as
  24. * a memory leak. A double put will be reported as a double free. Accessing
  25. * after a put will cause a use-after-free and/or a segfault.
  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. /* Declare a reference counted struct variable. */
  32. #define RC_STRUCT(struct_name) struct struct_name
  33. /*
  34. * Interpose the indirection. Result will hold the indirection and object is the
  35. * reference counted struct.
  36. */
  37. #define ADD_RC_CHK(result, object) (result = object, object)
  38. /* Strip the indirection layer. */
  39. #define RC_CHK_ACCESS(object) object
  40. /* Frees the object and the indirection layer. */
  41. #define RC_CHK_FREE(object) free(object)
  42. /* A get operation adding the indirection layer. */
  43. #define RC_CHK_GET(result, object) ADD_RC_CHK(result, object)
  44. /* A put operation removing the indirection layer. */
  45. #define RC_CHK_PUT(object) {}
  46. /* Pointer equality when the indirection may or may not be there. */
  47. #define RC_CHK_EQUAL(object1, object2) (object1 == object2)
  48. #else
  49. /* Replaces "struct foo" so that the pointer may be interposed. */
  50. #define DECLARE_RC_STRUCT(struct_name) \
  51. struct original_##struct_name; \
  52. struct struct_name { \
  53. struct original_##struct_name *orig; \
  54. }; \
  55. struct original_##struct_name
  56. /* Declare a reference counted struct variable. */
  57. #define RC_STRUCT(struct_name) struct original_##struct_name
  58. /*
  59. * Interpose the indirection. Result will hold the indirection and object is the
  60. * reference counted struct.
  61. */
  62. #define ADD_RC_CHK(result, object) \
  63. ( \
  64. object ? (result = malloc(sizeof(*result)), \
  65. result ? (result->orig = object, result) \
  66. : (result = NULL, NULL)) \
  67. : (result = NULL, NULL) \
  68. )
  69. /* Strip the indirection layer. */
  70. #define RC_CHK_ACCESS(object) object->orig
  71. /* Frees the object and the indirection layer. */
  72. #define RC_CHK_FREE(object) \
  73. do { \
  74. zfree(&object->orig); \
  75. free(object); \
  76. } while(0)
  77. /* A get operation adding the indirection layer. */
  78. #define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL))
  79. /* A put operation removing the indirection layer. */
  80. #define RC_CHK_PUT(object) \
  81. do { \
  82. if (object) { \
  83. object->orig = NULL; \
  84. free(object); \
  85. } \
  86. } while(0)
  87. /* Pointer equality when the indirection may or may not be there. */
  88. #define RC_CHK_EQUAL(object1, object2) (object1 == object2 || \
  89. (object1 && object2 && object1->orig == object2->orig))
  90. #endif
  91. #endif /* __LIBPERF_INTERNAL_RC_CHECK_H */