Skip to content

Commit 00ac450

Browse files
committed
Reduce clr startup noise when using Clang sanitizers
1 parent 2d2e591 commit 00ac450

7 files changed

+57
-24
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ if (CLR_CMAKE_PLATFORM_UNIX)
321321
string(FIND "$ENV{DEBUG_SANITIZERS}" "asan" __ASAN_POS)
322322
string(FIND "$ENV{DEBUG_SANITIZERS}" "ubsan" __UBSAN_POS)
323323
if ((${__ASAN_POS} GREATER -1) OR (${__UBSAN_POS} GREATER -1))
324-
set(CLR_SANITIZE_CXX_FLAGS "${CLR_SANITIZE_CXX_FLAGS} -fsanitize=")
324+
set(CLR_SANITIZE_CXX_FLAGS "${CLR_SANITIZE_CXX_FLAGS} -fsanitize-blacklist=${CMAKE_CURRENT_SOURCE_DIR}/sanitizerblacklist.txt -fsanitize=")
325325
set(CLR_SANITIZE_LINK_FLAGS "${CLR_SANITIZE_LINK_FLAGS} -fsanitize=")
326326
if (${__ASAN_POS} GREATER -1)
327327
set(CLR_SANITIZE_CXX_FLAGS "${CLR_SANITIZE_CXX_FLAGS}address,")

enablesanitizers.sh

+18-8
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@ if [ $# -eq 0 ]; then
1010
echo " cd $(dirname $0);. enablesanitizers.sh [options]; cd -"
1111
fi
1212
echo "Usage: [asan] [ubsan] [lsan] [all] [off] [clangx.y]"
13-
echo "asan: optional argument to enable Address Sanitizer."
14-
echo "ubsan: optional argument to enable Undefined Behavior Sanitizer."
15-
echo "lsan - optional argument to enable memory Leak Sanitizer."
16-
echo "all - optional argument to enable asan, ubsan and lsan."
17-
echo "off - optional argument to turn off all sanitizers."
18-
echo "clangx.y - optional argument to specify clang version x.y. which is used to resolve stack traces."
13+
echo " asan: optional argument to enable Address Sanitizer."
14+
echo " ubsan: optional argument to enable Undefined Behavior Sanitizer."
15+
echo " lsan - optional argument to enable memory Leak Sanitizer."
16+
echo " all - optional argument to enable asan, ubsan and lsan."
17+
echo " off - optional argument to turn off all sanitizers."
18+
echo " clangx.y - optional argument to specify clang version x.y. which is used to resolve stack traces. Default is 3.6"
1919
else
20+
# default to clang 3.6 instead of 3.5 because it supports print_stacktrace (otherwise only one stack frame)
2021
__ClangMajorVersion=3
21-
__ClangMinorVersion=5
22+
__ClangMinorVersion=6
23+
2224
__EnableASan=0
2325
__EnableUBSan=0
2426
__EnableLSan=0
@@ -69,7 +71,10 @@ else
6971
unset DEBUG_SANITIZERS
7072
echo "Setting DEBUG_SANITIZERS="
7173
else
72-
ASAN_OPTIONS="symbolize=1"
74+
# for now, specify alloc_dealloc_mismatch=0 as there are too many error reports that are not an issue
75+
ASAN_OPTIONS="symbolize=1 alloc_dealloc_mismatch=0"
76+
# when Clang 3.8 available, add: suppressions=$(readlink -f sanitizersuppressions.txt)
77+
UBSAN_OPTIONS="print_stacktrace=1"
7378

7479
if [ $__EnableASan == 1 ]; then
7580
__Options="$__Options asan"
@@ -91,10 +96,15 @@ else
9196
export ASAN_OPTIONS
9297
echo "Setting ASAN_OPTIONS=$ASAN_OPTIONS"
9398

99+
UBSAN_OPTIONS="\"$UBSAN_OPTIONS\""
100+
export UBSAN_OPTIONS
101+
echo "Setting UBSAN_OPTIONS=$UBSAN_OPTIONS"
102+
94103
# used by ASan at run-time
95104
ASAN_SYMBOLIZER_PATH="/usr/bin/llvm-symbolizer-$__ClangMajorVersion.$__ClangMinorVersion"
96105
export ASAN_SYMBOLIZER_PATH
97106
echo "Setting ASAN_SYMBOLIZER_PATH=$ASAN_SYMBOLIZER_PATH"
107+
echo "Done. You can now run: build.sh Debug clang$__ClangMajorVersion.$__ClangMinorVersion"
98108
fi
99109

100110
unset __ClangMajorVersion

sanitizerblacklist.txt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# This file has exclusions to the Clang address sanitizer to suppress error reports
2+
# When Clang 3.8 is available, convert these to suppression list instead as that is preferred for internal code
3+
4+
# CMiniMdBase::UsesAllocatedMemory - suppress stack-buffer-underflow (code backs up pointer by -1 to check allocation ownership)
5+
fun:_ZN11CMiniMdBase19UsesAllocatedMemoryEP11CMiniColDef
6+
7+
# JIT_InitPInvokeFrame - suppress unknown sanitizer issue causing SEGV on unknown address 0x000000000000
8+
# 0 0x4e8a0c in __ubsan::checkDynamicType(void*, void*, unsigned long)
9+
# 1 0x4e807f in HandleDynamicTypeCacheMiss(__ubsan::DynamicTypeCacheMissData*, unsigned long, unsigned long, __ubsan::ReportOptions)
10+
# 2 0x4e8051 in __ubsan_handle_dynamic_type_cache_miss
11+
# 3 0x7f02ce676cd8 in JIT_InitPInvokeFrame(InlinedCallFrame*, void*) /home/steveharter/git/dotnet_coreclr/src/vm/jithelpers.cpp:6491:9
12+
# 4 0x7f0252bbceb2 (<unknown module>)
13+
fun:_Z20JIT_InitPInvokeFrameP16InlinedCallFramePv
14+

src/gc/handletable.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,11 @@ void ValidateFetchObjrefForHandle(OBJECTREF objref, ADIndex appDomainIndex)
391391
_ASSERTE(!pDomain->NoAccessToHandleTable());
392392

393393
#if CHECK_APP_DOMAIN_LEAKS
394-
if (g_pConfig->AppDomainLeaks())
394+
if (g_pConfig->AppDomainLeaks() && objref != NULL)
395395
{
396396
if (appDomainIndex.m_dwIndex)
397397
objref->TryAssignAppDomain(pDomain);
398-
else if (objref != 0)
398+
else
399399
objref->TrySetAppDomainAgile();
400400
}
401401
#endif
@@ -421,11 +421,11 @@ void ValidateAssignObjrefForHandle(OBJECTREF objref, ADIndex appDomainIndex)
421421
_ASSERTE(!pDomain->NoAccessToHandleTable());
422422

423423
#if CHECK_APP_DOMAIN_LEAKS
424-
if (g_pConfig->AppDomainLeaks())
424+
if (g_pConfig->AppDomainLeaks() && objref != NULL)
425425
{
426426
if (appDomainIndex.m_dwIndex)
427427
objref->TryAssignAppDomain(pDomain);
428-
else if (objref != 0)
428+
else
429429
objref->TrySetAppDomainAgile();
430430
}
431431
#endif

src/gc/handletablecore.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -1984,15 +1984,17 @@ uint32_t BlockAllocHandlesInitial(TableSegment *pSegment, uint32_t uType, uint32
19841984
uint32_t uAlloc = uRemain;
19851985

19861986
// compute the default mask based on that count
1987-
uint32_t dwNewMask = (MASK_EMPTY << uAlloc);
1988-
1987+
uint32_t dwNewMask;
19891988
// are we allocating all of them?
19901989
if (uAlloc >= HANDLE_HANDLES_PER_MASK)
19911990
{
1992-
// shift above has unpredictable results in this case
1993-
dwNewMask = MASK_FULL;
1991+
dwNewMask = MASK_FULL; // avoid unpredictable shift
19941992
uAlloc = HANDLE_HANDLES_PER_MASK;
19951993
}
1994+
else
1995+
{
1996+
dwNewMask = (MASK_EMPTY << uAlloc);
1997+
}
19961998

19971999
// set the free mask
19982000
*pdwMask = dwNewMask;

src/inc/clrhost.h

+11-5
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ void ClrFlsAssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback);
8585
// Function pointer for fast TLS fetch - do not use directly
8686
typedef LPVOID (*POPTIMIZEDTLSGETTER)();
8787

88+
typedef LPVOID* (*CLRFLSGETBLOCK)();
89+
8890
extern POPTIMIZEDTLSGETTER __ClrFlsGetBlock;
8991

9092
#ifndef CLR_STANDALONE_BINDER
@@ -98,8 +100,9 @@ inline void ClrFlsIncrementValue(DWORD slot, int increment)
98100
STATIC_CONTRACT_SO_TOLERANT;
99101

100102
_ASSERTE(increment != 0);
101-
102-
void **block = (void **) (*__ClrFlsGetBlock)();
103+
104+
CLRFLSGETBLOCK clrFlsGetBlockFn = (CLRFLSGETBLOCK)__ClrFlsGetBlock;
105+
void **block = (*clrFlsGetBlockFn)();
103106
size_t value;
104107

105108
if (block != NULL)
@@ -134,7 +137,8 @@ inline void * ClrFlsGetValue (DWORD slot)
134137
STATIC_CONTRACT_CANNOT_TAKE_LOCK;
135138
STATIC_CONTRACT_SO_TOLERANT;
136139

137-
void **block = (void **) (*__ClrFlsGetBlock)();
140+
CLRFLSGETBLOCK clrFlsGetBlockFn = (CLRFLSGETBLOCK)__ClrFlsGetBlock;
141+
void **block = (*clrFlsGetBlockFn)();
138142
if (block != NULL)
139143
{
140144
return block[slot];
@@ -159,7 +163,8 @@ inline BOOL ClrFlsCheckValue(DWORD slot, void ** pValue)
159163
#ifdef _DEBUG
160164
*pValue = ULongToPtr(0xcccccccc);
161165
#endif //_DEBUG
162-
void **block = (void **) (*__ClrFlsGetBlock)();
166+
CLRFLSGETBLOCK clrFlsGetBlockFn = (CLRFLSGETBLOCK)__ClrFlsGetBlock;
167+
void **block = (*clrFlsGetBlockFn)();
163168
if (block != NULL)
164169
{
165170
*pValue = block[slot];
@@ -181,7 +186,8 @@ inline void ClrFlsSetValue(DWORD slot, void *pData)
181186
STATIC_CONTRACT_CANNOT_TAKE_LOCK;
182187
STATIC_CONTRACT_SO_TOLERANT;
183188

184-
void **block = (void **) (*__ClrFlsGetBlock)();
189+
CLRFLSGETBLOCK clrFlsGetBlockFn = (CLRFLSGETBLOCK)__ClrFlsGetBlock;
190+
void **block = (*clrFlsGetBlockFn)();
185191
if (block != NULL)
186192
{
187193
block[slot] = pData;

src/vm/vars.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,9 @@ class REF : public OBJECTREF
341341

342342
};
343343

344-
#define VALIDATEOBJECTREF(objref) ((objref).Validate())
345-
#define VALIDATEOBJECT(obj) obj->Validate()
344+
// the while (0) syntax below is to force a trailing semicolon on users of the macro
345+
#define VALIDATEOBJECTREF(objref) do {if ((objref) != NULL) (objref).Validate();} while (0)
346+
#define VALIDATEOBJECT(obj) do {if ((obj) != NULL) (obj)->Validate();} while (0)
346347

347348
#define ObjectToOBJECTREF(obj) (OBJECTREF(obj))
348349
#define OBJECTREFToObject(objref) ((objref).operator-> ())

0 commit comments

Comments
 (0)