Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#define DXX_VG_DECLARE_EXTERN_C(F)      \
2
        decltype(F) __real_##F, __wrap_##F
3
 
4
#define DXX_VG_DEFINE_READ(F,V) \
5
        __attribute__((__used__,__noinline__,__noclone__))      \
6
        int __wrap_##F(PHYSFS_File *const file, V *const val) { \
7
                dxx_vg_wrap_poison_value(*val); \
8
                return __real_##F(file, val);   \
9
        }
10
 
11
#define DXX_VG_DEFINE_WRITE(F,V)        \
12
        __attribute__((__used__,__noinline__,__noclone__))      \
13
        int __wrap_##F(PHYSFS_File *const file, V val) {        \
14
                dxx_vg_wrap_check_value(__builtin_return_address(0), &val, sizeof(val));        \
15
                return __real_##F(file, val);   \
16
        }
17
 
18
#define DXX_VG_DECLARE_READ_HELPER      \
19
template <typename T>   \
20
static void dxx_vg_wrap_poison_value(T &);
21
 
22
#define DXX_VG_DECLARE_WRITE_HELPER     \
23
static void dxx_vg_wrap_check_value(const void *, const void *, unsigned long);
24
 
25
#include "vg-wrap-physfs.h"
26
 
27
/*
28
 * This pattern is required due to a limitation in the PCH scanning
29
 * logic.  That logic will copy preprocessor guard directives along with
30
 * the include lines, but does not copy other lines.  Thus, writing:
31
 *
32
 * ```
33
 *              #ifndef PREPROCESSOR_SYMBOL
34
 *              #define PREPROCESSOR_SYMBOL     1
35
 *              #endif
36
 *
37
 *              #if PREPROCESSOR_SYMBOL
38
 *              #include <header>
39
 *              #endif
40
 * ```
41
 *
42
 * will cause it to copy only the second block into the generated PCH
43
 * CPP file.  Since the generated CPP will not set a value for
44
 * PREPROCESSOR_SYMBOL, the #if generates an error.
45
 *
46
 * This limitation is often hidden by a special-case that drops the
47
 * guards if an unguarded include exists.  In this case, this file
48
 * includes a header (`<cstring>`) not included unguarded in any source
49
 * file, so the special case does not apply.
50
 *
51
 * Compensate for this limitation by using only defined() checks, not
52
 * value checks, for the header includes.  This causes the guarded
53
 * headers not to be included in the PCH.  Omission from the PCH
54
 * should never affect correctness.  It can affect performance, but only
55
 * if the omission causes multiple source files to pay the performance
56
 * penalty of parsing the file individually instead of using a parsed
57
 * copy from the PCH.  In this instance, no other source files include
58
 * the headers without a guard, so no other files would benefit from
59
 * including it in the PCH.
60
 */
61
#if defined(DXX_ENABLE_wrap_PHYSFS_read) && !DXX_ENABLE_wrap_PHYSFS_read
62
#undef DXX_ENABLE_wrap_PHYSFS_read
63
#endif
64
 
65
#if defined(DXX_ENABLE_wrap_PHYSFS_write) && !DXX_ENABLE_wrap_PHYSFS_write
66
#undef DXX_ENABLE_wrap_PHYSFS_write
67
#endif
68
 
69
#if defined(DXX_ENABLE_wrap_PHYSFS_read) || defined(DXX_ENABLE_wrap_PHYSFS_write)
70
#include "console.h"
71
#include "dxxerror.h"
72
#include "compiler-poison.h"
73
 
74
#ifdef DXX_ENABLE_wrap_PHYSFS_read
75
#include <cstring>
76
 
77
template <typename T>
78
static void dxx_vg_wrap_poison_value(T &val)
79
{
80
        DXX_POISON_VAR(val, 0xbd);
81
}
82
 
83
__attribute__((__used__,__noinline__,__noclone__))
84
PHYSFS_sint64 __wrap_PHYSFS_read(PHYSFS_File *const handle, void *const buffer, const PHYSFS_uint32 objSize, const PHYSFS_uint32 objCount)
85
{
86
        {
87
                auto p = reinterpret_cast<uint8_t *>(buffer);
88
#if DXX_HAVE_POISON_OVERWRITE
89
                std::memset(p, 0xbd, static_cast<size_t>(objSize) * static_cast<size_t>(objCount));
90
#endif
91
                /* Mark each object individually so that any diagnosed errors are
92
                 * more precise.
93
                 */
94
                for (PHYSFS_uint32 i = objCount; i--; p += objSize)
95
                        DXX_MAKE_MEM_UNDEFINED(p, objSize);
96
        }
97
        return __real_PHYSFS_read(handle, buffer, objSize, objCount);
98
}
99
#endif
100
 
101
#ifdef DXX_ENABLE_wrap_PHYSFS_write
102
static void dxx_vg_wrap_check_value(const void *const ret, const void *const val, const unsigned long vlen)
103
{
104
        if (const auto o = VALGRIND_CHECK_MEM_IS_DEFINED(val, vlen))
105
                con_printf(CON_URGENT, DXX_STRINGIZE_FL(__FILE__, __LINE__, "BUG: ret=%p VALGRIND_CHECK_MEM_IS_DEFINED(%p, %lu)=%p (offset=%p)"), ret, val, vlen, reinterpret_cast<void *>(o), reinterpret_cast<void *>(o - reinterpret_cast<uintptr_t>(val)));
106
}
107
 
108
__attribute__((__used__,__noinline__,__noclone__))
109
PHYSFS_sint64 __wrap_PHYSFS_write(PHYSFS_File *const handle, const void *const buffer, const PHYSFS_uint32 objSize, const PHYSFS_uint32 objCount)
110
{
111
        auto p = reinterpret_cast<const uint8_t *>(buffer);
112
        /* Check each object individually so that any diagnosed errors are
113
         * more precise.
114
         */
115
        for (PHYSFS_uint32 i = 0; i != objCount; ++i, p += objSize)
116
        {
117
                if (const auto o = VALGRIND_CHECK_MEM_IS_DEFINED(p, objSize))
118
                        con_printf(CON_URGENT, DXX_STRINGIZE_FL(__FILE__, __LINE__, "BUG: ret=%p buffer=%p i=%.3u/%.3u VALGRIND_CHECK_MEM_IS_DEFINED(%p, %u)=%p (offset=%p)"), __builtin_return_address(0), buffer, i, objCount, p, objSize, reinterpret_cast<void *>(o), reinterpret_cast<void *>(o - reinterpret_cast<uintptr_t>(p)));
119
        }
120
        return __real_PHYSFS_write(handle, buffer, objSize, objCount);
121
}
122
#endif
123
#endif