Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#pragma once
2
 
3
#if DXX_HAVE_POISON
4
#include <algorithm>
5
#endif
6
 
7
#include <memory>
8
 
9
#if DXX_HAVE_POISON_VALGRIND
10
#include <valgrind/memcheck.h>
11
#endif
12
 
13
/* Inform Valgrind that the memory range contains writable but
14
 * unreadable bytes.
15
 *
16
 * On non-Valgrind runs, this is a no-op.
17
 */
18
template <typename T>
19
static inline void DXX_MAKE_MEM_UNDEFINED(T *b, unsigned long l)
20
{
21
        (void)b;(void)l;
22
#if DXX_HAVE_POISON_VALGRIND
23
        VALGRIND_MAKE_MEM_UNDEFINED(b, l);
24
#define DXX_HAVE_POISON_UNDEFINED 1
25
#endif
26
}
27
 
28
template <typename T>
29
static inline void DXX_CHECK_MEM_IS_DEFINED(const T *const b, unsigned long l)
30
{
31
        (void)b;(void)l;
32
#if DXX_HAVE_POISON_VALGRIND
33
        VALGRIND_CHECK_MEM_IS_DEFINED(b, l);
34
#endif
35
}
36
 
37
/* Convenience function to invoke
38
 * `DXX_MAKE_MEM_UNDEFINED(T *, unsigned long)`
39
 */
40
template <typename T>
41
static inline void DXX_MAKE_MEM_UNDEFINED(T *b, T *e)
42
{
43
        unsigned char *bc = reinterpret_cast<unsigned char *>(b);
44
        DXX_MAKE_MEM_UNDEFINED(bc, reinterpret_cast<unsigned char *>(e) - bc);
45
}
46
 
47
/* Convenience function to invoke
48
 * `DXX_CHECK_MEM_IS_DEFINED(T *, unsigned long)` for exactly one instance
49
 * of `T`.
50
 */
51
template <typename T>
52
static inline void DXX_CHECK_VAR_IS_DEFINED(const T &b)
53
{
54
        const unsigned char *const bc = reinterpret_cast<const unsigned char *>(std::addressof(b));
55
        DXX_CHECK_MEM_IS_DEFINED(bc, sizeof(T));
56
}
57
 
58
/* Convenience function to invoke
59
 * `DXX_MAKE_MEM_UNDEFINED(T *, unsigned long)` for exactly one instance
60
 * of `T`.
61
 */
62
template <typename T>
63
static inline void DXX_MAKE_VAR_UNDEFINED(T &b)
64
{
65
        unsigned char *const bc = reinterpret_cast<unsigned char *>(std::addressof(b));
66
        DXX_MAKE_MEM_UNDEFINED(bc, sizeof(T));
67
}
68
 
69
/* If enabled, overwrite the specified memory range with copies of value `v`.
70
 * In poison=overwrite builds, this is always enabled.
71
 * In poison=valgrind builds, this is enabled if running under Valgrind.
72
 *
73
 * If disabled, this is a no-op.
74
 */
75
template <typename T, typename V>
76
static inline void DXX_POISON_MEMORY_RANGE(T b, T e, const V &v)
77
{
78
#if DXX_HAVE_POISON
79
        int store = DXX_HAVE_POISON_OVERWRITE;
80
#if DXX_HAVE_POISON_VALGRIND
81
        if (!store)
82
                store |= RUNNING_ON_VALGRIND;
83
#endif
84
        if (!store)
85
                return;
86
        std::fill(b, e, v);
87
#else
88
        (void)b;(void)e;(void)v;
89
#endif
90
}
91
 
92
/* Poison a memory range, but do not mark it as unreadable.  This is
93
 * necessary when poisoning a buffer that will be written to the file or
94
 * to a network peer and some of the poisoned fields are expected not to
95
 * be updated (but cannot be removed from the source because the layout
96
 * is mandatory).
97
 */
98
template <typename T, typename V>
99
static inline void DXX_POISON_DEFINED_MEMORY(T b, unsigned long l, const V &v)
100
{
101
        DXX_POISON_MEMORY_RANGE(b, b + l, v);
102
}
103
 
104
/* Poison a memory range, then mark it unreadable.
105
 */
106
template <typename T>
107
static inline void DXX_POISON_MEMORY(T b, unsigned long l, const uint8_t v)
108
{
109
        DXX_POISON_DEFINED_MEMORY(b, l, v);
110
        DXX_MAKE_MEM_UNDEFINED(b, l);
111
}
112
 
113
/* Convenience function to invoke
114
 * `DXX_POISON_MEMORY(T &, unsigned long, V)`
115
 */
116
template <typename T>
117
static inline void DXX_POISON_MEMORY(T b, T e, const uint8_t &&v)
118
{
119
        DXX_POISON_MEMORY_RANGE(b, e, v);
120
        DXX_MAKE_MEM_UNDEFINED(b, e);
121
}
122
 
123
/* Convenience function to invoke
124
 * `DXX_POISON_MEMORY(T &, unsigned long, V)` for exactly one instance
125
 * of `T`.
126
 */
127
template <typename T>
128
static inline void DXX_POISON_VAR(T &b, const uint8_t v)
129
{
130
        DXX_POISON_MEMORY(reinterpret_cast<unsigned char *>(std::addressof(b)), sizeof(T), v);
131
}
132
 
133
/* Convenience function to invoke
134
 * `DXX_POISON_DEFINED_MEMORY(T &, unsigned long, V)` for exactly one
135
 * instance of `T`.
136
 */
137
template <typename T>
138
static inline void DXX_POISON_DEFINED_VAR(T &b, const unsigned char v)
139
{
140
        DXX_POISON_DEFINED_MEMORY(reinterpret_cast<unsigned char *>(std::addressof(b)), sizeof(T), v);
141
}
142
 
143
#ifndef DXX_HAVE_POISON_UNDEFINED
144
#define DXX_HAVE_POISON_UNDEFINED       0
145
#endif