Home | History | Annotate | Download | only in internal
      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