diff --git a/SConstruct b/SConstruct index 2f5edad3e..b3d383796 100644 --- a/SConstruct +++ b/SConstruct @@ -3563,6 +3563,8 @@ class DXXArchive(DXXCommon): 'misc/hmp.cpp', 'misc/ignorecase.cpp', 'misc/strutil.cpp', +'misc/vgrphys.cpp', +'misc/vgwphys.cpp', 'texmap/ntmap.cpp', 'texmap/scanline.cpp' ] diff --git a/common/misc/vg-wrap-physfs.h b/common/misc/vg-wrap-physfs.h new file mode 100644 index 000000000..55b07faf5 --- /dev/null +++ b/common/misc/vg-wrap-physfs.h @@ -0,0 +1,26 @@ +#include +#include "dxxsconf.h" + +#ifndef DXX_ENABLE_wrap_PHYSFS_write +#define DXX_ENABLE_wrap_PHYSFS_write DXX_HAVE_POISON_VALGRIND +#endif + +#if DXX_ENABLE_wrap_PHYSFS_write +extern "C" { + DXX_VG_DECLARE_EXTERN_C(PHYSFS_write); + DXX_VG_DECLARE_EXTERN_C(PHYSFS_writeSBE16); + DXX_VG_DECLARE_EXTERN_C(PHYSFS_writeSBE32); + DXX_VG_DECLARE_EXTERN_C(PHYSFS_writeSLE16); + DXX_VG_DECLARE_EXTERN_C(PHYSFS_writeSLE32); + DXX_VG_DECLARE_EXTERN_C(PHYSFS_writeULE16); + DXX_VG_DECLARE_EXTERN_C(PHYSFS_writeULE32); +} + +DXX_VG_DEFINE_WRITE(PHYSFS_writeSBE16, PHYSFS_sint16); +DXX_VG_DEFINE_WRITE(PHYSFS_writeSBE32, PHYSFS_sint32); +DXX_VG_DEFINE_WRITE(PHYSFS_writeSLE16, PHYSFS_sint16); +DXX_VG_DEFINE_WRITE(PHYSFS_writeSLE32, PHYSFS_sint32); +DXX_VG_DEFINE_WRITE(PHYSFS_writeULE16, PHYSFS_uint16); +DXX_VG_DEFINE_WRITE(PHYSFS_writeULE32, PHYSFS_uint32); + +#endif diff --git a/common/misc/vgrphys.cpp b/common/misc/vgrphys.cpp new file mode 100644 index 000000000..beac5d177 --- /dev/null +++ b/common/misc/vgrphys.cpp @@ -0,0 +1,16 @@ +#define DXX_VG_DECLARE_EXTERN_C(F) \ + decltype(F) __real_##F + +#define DXX_VG_DEFINE_WRITE(F,V) \ + int __real_##F(PHYSFS_File *const file, V val) { \ + return F(file, val); \ + } + +#include "vg-wrap-physfs.h" + +#if DXX_ENABLE_wrap_PHYSFS_write +PHYSFS_sint64 __real_PHYSFS_write(PHYSFS_File *const handle, const void *const buffer, const PHYSFS_uint32 objSize, const PHYSFS_uint32 objCount) +{ + return PHYSFS_write(handle, buffer, objSize, objCount); +} +#endif diff --git a/common/misc/vgwphys.cpp b/common/misc/vgwphys.cpp new file mode 100644 index 000000000..43887a2b8 --- /dev/null +++ b/common/misc/vgwphys.cpp @@ -0,0 +1,35 @@ +#define DXX_VG_DECLARE_EXTERN_C(F) \ + decltype(F) __real_##F, __wrap_##F + +#define DXX_VG_DEFINE_WRITE(F,V) \ + int __wrap_##F(PHYSFS_File *const file, V val) { \ + dxx_vg_wrap_check_value(__builtin_return_address(0), &val, sizeof(val)); \ + return __real_##F(file, val); \ + } + +static void dxx_vg_wrap_check_value(const void *, const void *, unsigned long); + +#include "vg-wrap-physfs.h" + +#if DXX_ENABLE_wrap_PHYSFS_write +#include "console.h" +#include "dxxerror.h" +#include "poison.h" + +static void dxx_vg_wrap_check_value(const void *const ret, const void *const val, const unsigned long vlen) +{ + if (const auto o = VALGRIND_CHECK_MEM_IS_DEFINED(val, vlen)) + 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(o), reinterpret_cast(o - reinterpret_cast(val))); +} + +PHYSFS_sint64 __wrap_PHYSFS_write(PHYSFS_File *const handle, const void *const buffer, const PHYSFS_uint32 objSize, const PHYSFS_uint32 objCount) +{ + const uint8_t *p = reinterpret_cast(buffer); + for (PHYSFS_uint32 i = 0; i != objCount; ++i, p += objSize) + { + if (const auto o = VALGRIND_CHECK_MEM_IS_DEFINED(p, objSize)) + 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(o), reinterpret_cast(o - reinterpret_cast(p))); + } + return __real_PHYSFS_write(handle, buffer, objSize, objCount); +} +#endif