• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************/
2 #ifdef JEMALLOC_H_TYPES
3 
4 #ifdef JEMALLOC_VALGRIND
5 #include <valgrind/valgrind.h>
6 
7 /*
8  * The size that is reported to Valgrind must be consistent through a chain of
9  * malloc..realloc..realloc calls.  Request size isn't recorded anywhere in
10  * jemalloc, so it is critical that all callers of these macros provide usize
11  * rather than request size.  As a result, buffer overflow detection is
12  * technically weakened for the standard API, though it is generally accepted
13  * practice to consider any extra bytes reported by malloc_usable_size() as
14  * usable space.
15  */
16 #define	JEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(ptr, usize) do {		\
17 	if (unlikely(in_valgrind))					\
18 		valgrind_make_mem_noaccess(ptr, usize);			\
19 } while (0)
20 #define	JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize) do {		\
21 	if (unlikely(in_valgrind))					\
22 		valgrind_make_mem_undefined(ptr, usize);		\
23 } while (0)
24 #define	JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ptr, usize) do {		\
25 	if (unlikely(in_valgrind))					\
26 		valgrind_make_mem_defined(ptr, usize);			\
27 } while (0)
28 /*
29  * The VALGRIND_MALLOCLIKE_BLOCK() and VALGRIND_RESIZEINPLACE_BLOCK() macro
30  * calls must be embedded in macros rather than in functions so that when
31  * Valgrind reports errors, there are no extra stack frames in the backtraces.
32  */
33 #define	JEMALLOC_VALGRIND_MALLOC(cond, tsdn, ptr, usize, zero) do {	\
34 	if (unlikely(in_valgrind && cond)) {				\
35 		VALGRIND_MALLOCLIKE_BLOCK(ptr, usize, p2rz(tsdn, ptr),	\
36 		    zero);						\
37 	}								\
38 } while (0)
39 #define	JEMALLOC_VALGRIND_REALLOC_MOVED_no(ptr, old_ptr)		\
40     (false)
41 #define	JEMALLOC_VALGRIND_REALLOC_MOVED_maybe(ptr, old_ptr)		\
42     ((ptr) != (old_ptr))
43 #define	JEMALLOC_VALGRIND_REALLOC_PTR_NULL_no(ptr)			\
44     (false)
45 #define	JEMALLOC_VALGRIND_REALLOC_PTR_NULL_maybe(ptr)			\
46     (ptr == NULL)
47 #define	JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_no(old_ptr)		\
48     (false)
49 #define	JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_maybe(old_ptr)		\
50     (old_ptr == NULL)
51 #define	JEMALLOC_VALGRIND_REALLOC(moved, tsdn, ptr, usize, ptr_null,	\
52     old_ptr, old_usize, old_rzsize, old_ptr_null, zero) do {		\
53 	if (unlikely(in_valgrind)) {					\
54 		size_t rzsize = p2rz(tsdn, ptr);			\
55 									\
56 		if (!JEMALLOC_VALGRIND_REALLOC_MOVED_##moved(ptr,	\
57 		    old_ptr)) {						\
58 			VALGRIND_RESIZEINPLACE_BLOCK(ptr, old_usize,	\
59 			    usize, rzsize);				\
60 			if (zero && old_usize < usize) {		\
61 				valgrind_make_mem_defined(		\
62 				    (void *)((uintptr_t)ptr +		\
63 				    old_usize), usize - old_usize);	\
64 			}						\
65 		} else {						\
66 			if (!JEMALLOC_VALGRIND_REALLOC_OLD_PTR_NULL_##	\
67 			    old_ptr_null(old_ptr)) {			\
68 				valgrind_freelike_block(old_ptr,	\
69 				    old_rzsize);			\
70 			}						\
71 			if (!JEMALLOC_VALGRIND_REALLOC_PTR_NULL_##	\
72 			    ptr_null(ptr)) {				\
73 				size_t copy_size = (old_usize < usize)	\
74 				    ?  old_usize : usize;		\
75 				size_t tail_size = usize - copy_size;	\
76 				VALGRIND_MALLOCLIKE_BLOCK(ptr, usize,	\
77 				    rzsize, false);			\
78 				if (copy_size > 0) {			\
79 					valgrind_make_mem_defined(ptr,	\
80 					copy_size);			\
81 				}					\
82 				if (zero && tail_size > 0) {		\
83 					valgrind_make_mem_defined(	\
84 					    (void *)((uintptr_t)ptr +	\
85 					    copy_size), tail_size);	\
86 				}					\
87 			}						\
88 		}							\
89 	}								\
90 } while (0)
91 #define	JEMALLOC_VALGRIND_FREE(ptr, rzsize) do {			\
92 	if (unlikely(in_valgrind))					\
93 		valgrind_freelike_block(ptr, rzsize);			\
94 } while (0)
95 #else
96 #define	RUNNING_ON_VALGRIND	((unsigned)0)
97 #define	JEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(ptr, usize) do {} while (0)
98 #define	JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize) do {} while (0)
99 #define	JEMALLOC_VALGRIND_MAKE_MEM_DEFINED(ptr, usize) do {} while (0)
100 #define	JEMALLOC_VALGRIND_MALLOC(cond, tsdn, ptr, usize, zero) do {} while (0)
101 #define	JEMALLOC_VALGRIND_REALLOC(maybe_moved, tsdn, ptr, usize,	\
102     ptr_maybe_null, old_ptr, old_usize, old_rzsize, old_ptr_maybe_null,	\
103     zero) do {} while (0)
104 #define	JEMALLOC_VALGRIND_FREE(ptr, rzsize) do {} while (0)
105 #endif
106 
107 #endif /* JEMALLOC_H_TYPES */
108 /******************************************************************************/
109 #ifdef JEMALLOC_H_STRUCTS
110 
111 #endif /* JEMALLOC_H_STRUCTS */
112 /******************************************************************************/
113 #ifdef JEMALLOC_H_EXTERNS
114 
115 #ifdef JEMALLOC_VALGRIND
116 void	valgrind_make_mem_noaccess(void *ptr, size_t usize);
117 void	valgrind_make_mem_undefined(void *ptr, size_t usize);
118 void	valgrind_make_mem_defined(void *ptr, size_t usize);
119 void	valgrind_freelike_block(void *ptr, size_t usize);
120 #endif
121 
122 #endif /* JEMALLOC_H_EXTERNS */
123 /******************************************************************************/
124 #ifdef JEMALLOC_H_INLINES
125 
126 #endif /* JEMALLOC_H_INLINES */
127 /******************************************************************************/
128 
129