Fix MSVC ASan compilation by avoiding GCC/Clang specific stack instrumentation
PiperOrigin-RevId: 951656966 Change-Id: I51294e6a95c39f4037e8feb2aee45e69cb51beb0
This commit is contained in:
committed by
Copybara-Service
parent
8ccd2b6db5
commit
259e6c4dc6
+10
-3
@@ -26,8 +26,15 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Define mjUSEASAN if ADDRESS_SANITIZER is active and we are not on MSVC.
|
||||
// MSVC asan (/fsanitize=address defines ADDRESS_SANITIZER via EnableASAN) cannot use the GCC/clang
|
||||
// attribute+asm instrumentation below, so we exclude it.
|
||||
#if defined(ADDRESS_SANITIZER) && !defined(_MSC_VER)
|
||||
#define mjUSEASAN
|
||||
#endif
|
||||
|
||||
// Include asan interface header, or provide stubs for poison/unpoison macros when not using asan.
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#elif defined(_MSC_VER)
|
||||
#define ASAN_POISON_MEMORY_REGION(addr, size)
|
||||
@@ -42,7 +49,7 @@
|
||||
// into mark/free into the same function, this instrumentation requires that the compiler retains
|
||||
// separate mark/free calls for each original callee. The memory-clobbered asm blocks act as a
|
||||
// barrier to prevent mark/free calls from being combined under optimization.
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -64,6 +71,6 @@ static inline void mj_freeStack(mjData* d) __attribute__((always_inline)) {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // ADDRESS_SANITIZER
|
||||
#endif // mjUSEASAN
|
||||
|
||||
#endif // MUJOCO_INCLUDE_MJSAN_H_
|
||||
|
||||
@@ -267,7 +267,7 @@ MJAPI void mj_resetDataDebug(const mjModel* m, mjData* d, unsigned char debug_va
|
||||
// Reset data. If 0 <= key < nkey, set fields from specified keyframe.
|
||||
MJAPI void mj_resetDataKeyframe(const mjModel* m, mjData* d, int key);
|
||||
|
||||
#ifndef ADDRESS_SANITIZER // Stack management functions declared in mjsan.h if ASAN is active.
|
||||
#ifndef mjUSEASAN // Stack management functions declared in mjsan.h if ASAN is active.
|
||||
|
||||
// Mark a new frame on the mjData stack.
|
||||
MJAPI void mj_markStack(mjData* d);
|
||||
|
||||
@@ -178,7 +178,7 @@ static inline mjtNum getGap(const mjModel* m, int g1, int g2, int ipair) {
|
||||
// move arena pointer back to the end of the contact array
|
||||
static inline void resetArena(mjData* d) {
|
||||
d->parena = d->ncon * sizeof(mjContact);
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
ASAN_POISON_MEMORY_REGION(
|
||||
(char*)d->arena + d->parena, d->narena - d->pstack - d->parena);
|
||||
#endif
|
||||
|
||||
@@ -137,7 +137,7 @@ static int arenaAllocEfc(const mjModel* m, mjData* d) {
|
||||
d->parena = d->ncon * sizeof(mjContact);
|
||||
|
||||
// poison remaining memory
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
ASAN_POISON_MEMORY_REGION(
|
||||
(char*)d->arena + d->parena, d->narena - d->pstack - d->parena);
|
||||
#endif
|
||||
@@ -390,7 +390,7 @@ static int mj_vertBodyWeight(const mjModel* m, const mjData* d, int f, int* v,
|
||||
int mj_addContact(const mjModel* m, mjData* d, const mjContact* con) {
|
||||
// move arena pointer back to the end of the existing contact array and invalidate efc_ arrays
|
||||
d->parena = d->ncon * sizeof(mjContact);
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
ASAN_POISON_MEMORY_REGION(
|
||||
(char*)d->arena + d->parena, d->narena - d->pstack - d->parena);
|
||||
#endif
|
||||
|
||||
@@ -43,7 +43,7 @@ void CheckRosetta() {
|
||||
} // namespace
|
||||
#endif // defined(__APPLE__) && defined(__AVX__)
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
@@ -75,6 +75,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ADDRESS_SANITIZER) && !defined(_MSC_VER)
|
||||
#define mjUSEASAN
|
||||
#endif
|
||||
|
||||
// Atomics helper for size_t.
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#include <intrin.h>
|
||||
@@ -103,7 +107,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
int mj__comparePcFuncName(void* pc1, void* pc2);
|
||||
const char* mj__getPcDebugInfo(void* pc);
|
||||
#endif
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "engine/engine_util_errmem.h"
|
||||
#include "engine/engine_util_misc.h"
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
#endif
|
||||
@@ -1037,7 +1037,7 @@ void mj_initPlugin(const mjModel* m, mjData* d) {
|
||||
|
||||
// free mjData memory without destroying the struct
|
||||
static void freeDataBuffers(mjData* d) {
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
// raise an error if there's a dangling stack frame
|
||||
mj_freeStack(d);
|
||||
#endif
|
||||
@@ -1315,7 +1315,7 @@ static void _resetData(const mjModel* m, mjData* d, unsigned char debug_value) {
|
||||
d->parena = 0;
|
||||
|
||||
// poison the entire arena+stack memory region when built with asan
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
ASAN_POISON_MEMORY_REGION(d->arena, d->narena);
|
||||
#endif
|
||||
|
||||
@@ -1371,7 +1371,7 @@ static void _resetData(const mjModel* m, mjData* d, unsigned char debug_value) {
|
||||
//------------------------------ clear buffer, set defaults
|
||||
|
||||
// fill buffer with debug_value (normally 0)
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
{
|
||||
#define X(type, name, nr, nc) memset(d->name, (int)debug_value, sizeof(type)*(m->nr)*(nc));
|
||||
MJDATA_POINTERS
|
||||
|
||||
@@ -45,7 +45,7 @@ static void clearIsland(mjData* d, size_t parena) {
|
||||
d->parena = parena;
|
||||
|
||||
// poison remaining memory
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
ASAN_POISON_MEMORY_REGION(
|
||||
(char*)d->arena + d->parena, d->narena - d->pstack - d->parena);
|
||||
#endif
|
||||
|
||||
+13
-13
@@ -28,7 +28,7 @@
|
||||
#include "engine/engine_util_errmem.h"
|
||||
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
#endif
|
||||
@@ -42,7 +42,7 @@
|
||||
#endif
|
||||
|
||||
// add red zone padding when built with asan, to detect out-of-bound accesses
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
#define mjREDZONE 32
|
||||
#else
|
||||
#define mjREDZONE 0
|
||||
@@ -82,7 +82,7 @@ static inline mjStackInfo get_stack_info_from_data(const mjData* d) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
// get stack usage from red-zone (under ASAN)
|
||||
static size_t stack_usage_redzone(const mjStackInfo* stack_info) {
|
||||
size_t usage = 0;
|
||||
@@ -117,7 +117,7 @@ void* mj_arenaAllocByte(mjData* d, size_t bytes, size_t alignment) {
|
||||
size_t stack_usage = d->pstack;
|
||||
|
||||
// under ASAN, get stack usage from red zone
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
mjStackInfo stack_info = get_stack_info_from_data(d);
|
||||
stack_usage = stack_usage_redzone(&stack_info);
|
||||
#endif
|
||||
@@ -127,7 +127,7 @@ void* mj_arenaAllocByte(mjData* d, size_t bytes, size_t alignment) {
|
||||
d->parena += padding + bytes;
|
||||
d->maxuse_arena = mjMAX(d->maxuse_arena, stack_usage + d->parena);
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
ASAN_UNPOISON_MEMORY_REGION(result, bytes);
|
||||
#endif
|
||||
|
||||
@@ -179,7 +179,7 @@ static inline void* stackallocinternal(mjData* d, mjStackInfo* stack_info, size_
|
||||
stack_required_bytes, d->nefc, d->ncon);
|
||||
}
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
usage = current_alloc_usage + stack_usage_redzone(stack_info);
|
||||
|
||||
// store new stack usage in the red zone
|
||||
@@ -250,7 +250,7 @@ static inline void* stackalloc(mjData* d, size_t size, size_t alignment,
|
||||
|
||||
|
||||
// mjStackInfo mark stack frame, inline so ASAN errors point to correct code unit
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
__attribute__((always_inline))
|
||||
#endif
|
||||
static inline void markstackinternal(mjData* d, mjStackInfo* stack_info) {
|
||||
@@ -259,7 +259,7 @@ static inline void markstackinternal(mjData* d, mjStackInfo* stack_info) {
|
||||
(mjStackFrame*) stackallocinternal(d, stack_info, sizeof(mjStackFrame), _Alignof(mjStackFrame), NULL, 0);
|
||||
s->pbase = stack_info->stack_base;
|
||||
s->pstack = top_old;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
// store the program counter to the caller so that we can compare against mj_freeStack later
|
||||
s->pc = __sanitizer_return_address();
|
||||
#endif
|
||||
@@ -268,7 +268,7 @@ static inline void markstackinternal(mjData* d, mjStackInfo* stack_info) {
|
||||
|
||||
|
||||
// mjData mark stack frame
|
||||
#ifndef ADDRESS_SANITIZER
|
||||
#ifndef mjUSEASAN
|
||||
void mj_markStack(mjData* d)
|
||||
#else
|
||||
void mj__markStack(mjData* d)
|
||||
@@ -286,7 +286,7 @@ void mj__markStack(mjData* d)
|
||||
}
|
||||
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
__attribute__((always_inline))
|
||||
#endif
|
||||
static inline void freestackinternal(mjStackInfo* stack_info) {
|
||||
@@ -295,7 +295,7 @@ static inline void freestackinternal(mjStackInfo* stack_info) {
|
||||
}
|
||||
|
||||
mjStackFrame* s = (mjStackFrame*) stack_info->stack_base;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
// raise an error if caller function name doesn't match the most recent caller of mj_markStack
|
||||
if (!mj__comparePcFuncName(s->pc, __sanitizer_return_address())) {
|
||||
mjERROR("mj_markStack %s has no corresponding mj_freeStack (detected %s)",
|
||||
@@ -310,14 +310,14 @@ static inline void freestackinternal(mjStackInfo* stack_info) {
|
||||
stack_info->top = s->pstack;
|
||||
|
||||
// if running under asan, poison the newly freed memory region
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
ASAN_POISON_MEMORY_REGION((char*)old_top, stack_info->top - old_top);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// mjData free stack frame
|
||||
#ifndef ADDRESS_SANITIZER
|
||||
#ifndef mjUSEASAN
|
||||
void mj_freeStack(mjData* d)
|
||||
#else
|
||||
void mj__freeStack(mjData* d)
|
||||
|
||||
@@ -34,7 +34,7 @@ extern "C" {
|
||||
// mjData arena allocate
|
||||
MJAPI void* mj_arenaAllocByte(mjData* d, size_t bytes, size_t alignment);
|
||||
|
||||
#ifndef ADDRESS_SANITIZER
|
||||
#ifndef mjUSEASAN
|
||||
|
||||
// mjData mark stack frame
|
||||
MJAPI void mj_markStack(mjData* d);
|
||||
|
||||
@@ -812,7 +812,7 @@ TEST_F(EngineIoTest, TestStackShardingForThreads) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#ifdef mjUSEASAN
|
||||
void MarkFreeStack(mjData* d, bool free) {
|
||||
mj_markStack(d);
|
||||
if (free) {
|
||||
|
||||
@@ -65,6 +65,7 @@ public const int mjMAXMATERIAL = 1000;
|
||||
public const bool THIRD_PARTY_MUJOCO_MJRFILAMENT_H_ = true;
|
||||
public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJSAN_H_ = true;
|
||||
public const bool ADDRESS_SANITIZER = true;
|
||||
public const bool mjUSEASAN = true;
|
||||
public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJSPEC_H_ = true;
|
||||
public const bool THIRD_PARTY_MUJOCO_MJSPECMACRO_H_ = true;
|
||||
public const bool THIRD_PARTY_MUJOCO_INCLUDE_MJTYPE_H_ = true;
|
||||
|
||||
Reference in New Issue
Block a user