1 /* Copyright (C) 2010, 2020, MariaDB Corporation.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 of the License.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
15 
16 #ifndef MY_VALGRIND_INCLUDED
17 #define MY_VALGRIND_INCLUDED
18 
19 /* clang -> gcc */
20 #ifndef __has_feature
21 # define __has_feature(x) 0
22 #endif
23 #if __has_feature(address_sanitizer)
24 # define __SANITIZE_ADDRESS__ 1
25 #endif
26 
27 #if __has_feature(memory_sanitizer)
28 # include <sanitizer/msan_interface.h>
29 # define HAVE_valgrind
30 # define HAVE_MEM_CHECK
31 # define MEM_UNDEFINED(a,len) __msan_allocated_memory(a,len)
32 # define MEM_MAKE_ADDRESSABLE(a,len) MEM_UNDEFINED(a,len)
33 # define MEM_MAKE_DEFINED(a,len) __msan_unpoison(a,len)
34 # define MEM_NOACCESS(a,len) ((void) 0)
35 # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0)
36 # define MEM_CHECK_DEFINED(a,len) __msan_check_mem_is_initialized(a,len)
37 # define MEM_GET_VBITS(a,b,len) __msan_copy_shadow(b,a,len)
38 # define MEM_SET_VBITS(a,b,len) __msan_copy_shadow(a,b,len)
39 # define REDZONE_SIZE 8
40 #elif defined(HAVE_VALGRIND_MEMCHECK_H) && defined(HAVE_valgrind)
41 # include <valgrind/memcheck.h>
42 # define HAVE_MEM_CHECK
43 # define MEM_UNDEFINED(a,len) VALGRIND_MAKE_MEM_UNDEFINED(a,len)
44 # define MEM_MAKE_ADDRESSABLE(a,len) MEM_UNDEFINED(a,len)
45 # define MEM_MAKE_DEFINED(a,len) VALGRIND_MAKE_MEM_DEFINED(a,len)
46 # define MEM_NOACCESS(a,len) VALGRIND_MAKE_MEM_NOACCESS(a,len)
47 # define MEM_CHECK_ADDRESSABLE(a,len) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,len)
48 # define MEM_CHECK_DEFINED(a,len) VALGRIND_CHECK_MEM_IS_DEFINED(a,len)
49 # define MEM_GET_VBITS(a,b,len) VALGRIND_GET_VBITS(a,b,len)
50 # define MEM_SET_VBITS(a,b,len) VALGRIND_SET_VBITS(a,b,len)
51 # define REDZONE_SIZE 8
52 #elif defined(__SANITIZE_ADDRESS__) && (!defined(_MSC_VER) || defined (__clang__))
53 # include <sanitizer/asan_interface.h>
54 /* How to do manual poisoning:
55 https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */
56 # define MEM_UNDEFINED(a,len) ((void) 0)
57 # define MEM_MAKE_ADDRESSABLE(a,len) ASAN_UNPOISON_MEMORY_REGION(a,len)
58 # define MEM_MAKE_DEFINED(a,len) ((void) 0)
59 # define MEM_NOACCESS(a,len) ASAN_POISON_MEMORY_REGION(a,len)
60 # define MEM_CHECK_ADDRESSABLE(a,len) \
61   assert(!__asan_region_is_poisoned((void*) a,len))
62 # define MEM_CHECK_DEFINED(a,len) ((void) 0)
63 # define MEM_GET_VBITS(a,b,len) ((void) 0)
64 # define MEM_SET_VBITS(a,b,len) ((void) 0)
65 # define REDZONE_SIZE 8
66 #else
67 # define MEM_UNDEFINED(a,len) ((void) 0)
68 # define MEM_MAKE_ADDRESSABLE(a,len) ((void) 0)
69 # define MEM_MAKE_DEFINED(a,len) ((void) 0)
70 # define MEM_NOACCESS(a,len) ((void) 0)
71 # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0)
72 # define MEM_CHECK_DEFINED(a,len) ((void) 0)
73 # define MEM_GET_VBITS(a,b,len) ((void) 0)
74 # define MEM_SET_VBITS(a,b,len) ((void) 0)
75 # define REDZONE_SIZE 0
76 #endif /* __has_feature(memory_sanitizer) */
77 
78 #ifdef HAVE_valgrind
79 #define IF_VALGRIND(A,B) A
80 #else
81 #define IF_VALGRIND(A,B) B
82 #endif
83 
84 #ifdef TRASH_FREED_MEMORY
85 /*
86   _TRASH_FILL() has to call MEM_MAKE_ADDRESSABLE() to cancel any effect of
87   TRASH_FREE().
88   This can happen in the case one does
89   TRASH_ALLOC(A,B) ; TRASH_FREE(A,B) ; TRASH_ALLOC(A,B)
90   to reuse the same memory in an internal memory allocator like MEM_ROOT.
91   _TRASH_FILL() is an internal function and should not be used externally.
92 */
93 #define _TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_MAKE_ADDRESSABLE(A, trash_tmp); memset(A, C, trash_tmp); } while (0)
94 #else
95 #define _TRASH_FILL(A,B,C) do { MEM_UNDEFINED((A), (B)); } while (0)
96 #endif
97 /** Note that some memory became allocated and/or uninitialized. */
98 #define TRASH_ALLOC(A,B) do { _TRASH_FILL(A,B,0xA5); MEM_MAKE_ADDRESSABLE(A,B); } while(0)
99 /** Note that some memory became freed. (Prohibit further access to it.) */
100 #define TRASH_FREE(A,B) do { _TRASH_FILL(A,B,0x8F); MEM_NOACCESS(A,B); } while(0)
101 
102 #endif /* MY_VALGRIND_INCLUDED */
103