Subversion Repositories Games.Descent

Rev

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

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