Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  124.