mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-07 13:14:51 +00:00
Vendor import of compiler-rt trunk r291476:
https://llvm.org/svn/llvm-project/compiler-rt/trunk@291476
This commit is contained in:
parent
91d212a4a6
commit
3bce7d2fca
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/compiler-rt/dist/; revision=311822 svn path=/vendor/compiler-rt/compiler-rt-trunk-r291476/; revision=311823; tag=vendor/compiler-rt/compiler-rt-trunk-r291476
@ -46,6 +46,17 @@ macro(add_sanitizer_rt_symbols name)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# This function is only used on Darwin, where undefined symbols must be specified
|
||||
# in the linker invocation.
|
||||
function(add_weak_symbols libname linkflags)
|
||||
file(STRINGS "${COMPILER_RT_SOURCE_DIR}/lib/${libname}/weak_symbols.txt" WEAK_SYMBOLS)
|
||||
set(local_linkflags ${${linkflags}})
|
||||
foreach(SYMBOL ${WEAK_SYMBOLS})
|
||||
set(local_linkflags ${local_linkflags} -Wl,-U,${SYMBOL})
|
||||
endforeach()
|
||||
set(${linkflags} ${local_linkflags} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
macro(add_sanitizer_rt_version_list name)
|
||||
set(vers ${CMAKE_CURRENT_BINARY_DIR}/${name}.vers)
|
||||
cmake_parse_arguments(ARG "" "" "LIBS;EXTRA" ${ARGN})
|
||||
|
@ -106,6 +106,10 @@ endif()
|
||||
add_compiler_rt_component(asan)
|
||||
|
||||
if(APPLE)
|
||||
add_weak_symbols("asan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("ubsan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINKFLAGS)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan
|
||||
SHARED
|
||||
OS ${SANITIZER_COMMON_SUPPORTED_OS}
|
||||
@ -117,6 +121,7 @@ if(APPLE)
|
||||
RTLSanCommon
|
||||
RTUbsan
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
LINKFLAGS ${WEAK_SYMBOL_LINKFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS}
|
||||
PARENT_TARGET asan)
|
||||
else()
|
||||
|
@ -179,6 +179,8 @@ class ScopedInErrorReport {
|
||||
if (common_flags()->print_cmdline)
|
||||
PrintCmdline();
|
||||
|
||||
if (common_flags()->print_module_map == 2) PrintModuleMap();
|
||||
|
||||
// Copy the message buffer so that we could start logging without holding a
|
||||
// lock that gets aquired during printing.
|
||||
InternalScopedBuffer<char> buffer_copy(kErrorMessageBufferSize);
|
||||
|
@ -46,6 +46,7 @@ static void AsanDie() {
|
||||
// Don't die twice - run a busy loop.
|
||||
while (1) { }
|
||||
}
|
||||
if (common_flags()->print_module_map >= 1) PrintModuleMap();
|
||||
if (flags()->sleep_before_dying) {
|
||||
Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying);
|
||||
SleepForSeconds(flags()->sleep_before_dying);
|
||||
|
@ -24,6 +24,7 @@
|
||||
fix_filename_patterns = None
|
||||
logfile = sys.stdin
|
||||
allow_system_symbolizer = True
|
||||
force_system_symbolizer = False
|
||||
|
||||
# FIXME: merge the code that calls fix_filename().
|
||||
def fix_filename(file_name):
|
||||
@ -37,6 +38,10 @@ def fix_filename(file_name):
|
||||
def sysroot_path_filter(binary_name):
|
||||
return sysroot_path + binary_name
|
||||
|
||||
def is_valid_arch(s):
|
||||
return s in ["i386", "x86_64", "x86_64h", "arm", "armv6", "armv7", "armv7s",
|
||||
"armv7k", "arm64", "powerpc64", "powerpc64le", "s390x", "s390"]
|
||||
|
||||
def guess_arch(addr):
|
||||
# Guess which arch we're running. 10 = len('0x') + 8 hex digits.
|
||||
if len(addr) > 10:
|
||||
@ -206,10 +211,10 @@ def readline(self):
|
||||
|
||||
|
||||
class DarwinSymbolizer(Symbolizer):
|
||||
def __init__(self, addr, binary):
|
||||
def __init__(self, addr, binary, arch):
|
||||
super(DarwinSymbolizer, self).__init__()
|
||||
self.binary = binary
|
||||
self.arch = guess_arch(addr)
|
||||
self.arch = arch
|
||||
self.open_atos()
|
||||
|
||||
def open_atos(self):
|
||||
@ -268,9 +273,9 @@ def BreakpadSymbolizerFactory(binary):
|
||||
return None
|
||||
|
||||
|
||||
def SystemSymbolizerFactory(system, addr, binary):
|
||||
def SystemSymbolizerFactory(system, addr, binary, arch):
|
||||
if system == 'Darwin':
|
||||
return DarwinSymbolizer(addr, binary)
|
||||
return DarwinSymbolizer(addr, binary, arch)
|
||||
elif system == 'Linux' or system == 'FreeBSD':
|
||||
return Addr2LineSymbolizer(binary)
|
||||
|
||||
@ -369,7 +374,7 @@ def __init__(self, binary_name_filter=None, dsym_hint_producer=None):
|
||||
self.frame_no = 0
|
||||
self.process_line = self.process_line_posix
|
||||
|
||||
def symbolize_address(self, addr, binary, offset):
|
||||
def symbolize_address(self, addr, binary, offset, arch):
|
||||
# On non-Darwin (i.e. on platforms without .dSYM debug info) always use
|
||||
# a single symbolizer binary.
|
||||
# On Darwin, if the dsym hint producer is present:
|
||||
@ -381,31 +386,35 @@ def symbolize_address(self, addr, binary, offset):
|
||||
# if so, reuse |last_llvm_symbolizer| which has the full set of hints;
|
||||
# 3. otherwise create a new symbolizer and pass all currently known
|
||||
# .dSYM hints to it.
|
||||
if not binary in self.llvm_symbolizers:
|
||||
use_new_symbolizer = True
|
||||
if self.system == 'Darwin' and self.dsym_hint_producer:
|
||||
dsym_hints_for_binary = set(self.dsym_hint_producer(binary))
|
||||
use_new_symbolizer = bool(dsym_hints_for_binary - self.dsym_hints)
|
||||
self.dsym_hints |= dsym_hints_for_binary
|
||||
if self.last_llvm_symbolizer and not use_new_symbolizer:
|
||||
result = None
|
||||
if not force_system_symbolizer:
|
||||
if not binary in self.llvm_symbolizers:
|
||||
use_new_symbolizer = True
|
||||
if self.system == 'Darwin' and self.dsym_hint_producer:
|
||||
dsym_hints_for_binary = set(self.dsym_hint_producer(binary))
|
||||
use_new_symbolizer = bool(dsym_hints_for_binary - self.dsym_hints)
|
||||
self.dsym_hints |= dsym_hints_for_binary
|
||||
if self.last_llvm_symbolizer and not use_new_symbolizer:
|
||||
self.llvm_symbolizers[binary] = self.last_llvm_symbolizer
|
||||
else:
|
||||
self.last_llvm_symbolizer = LLVMSymbolizerFactory(
|
||||
self.system, arch, self.dsym_hints)
|
||||
self.llvm_symbolizers[binary] = self.last_llvm_symbolizer
|
||||
else:
|
||||
self.last_llvm_symbolizer = LLVMSymbolizerFactory(
|
||||
self.system, guess_arch(addr), self.dsym_hints)
|
||||
self.llvm_symbolizers[binary] = self.last_llvm_symbolizer
|
||||
# Use the chain of symbolizers:
|
||||
# Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos
|
||||
# (fall back to next symbolizer if the previous one fails).
|
||||
if not binary in symbolizers:
|
||||
symbolizers[binary] = ChainSymbolizer(
|
||||
[BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]])
|
||||
result = symbolizers[binary].symbolize(addr, binary, offset)
|
||||
# Use the chain of symbolizers:
|
||||
# Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos
|
||||
# (fall back to next symbolizer if the previous one fails).
|
||||
if not binary in symbolizers:
|
||||
symbolizers[binary] = ChainSymbolizer(
|
||||
[BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]])
|
||||
result = symbolizers[binary].symbolize(addr, binary, offset)
|
||||
else:
|
||||
symbolizers[binary] = ChainSymbolizer([])
|
||||
if result is None:
|
||||
if not allow_system_symbolizer:
|
||||
raise Exception('Failed to launch or use llvm-symbolizer.')
|
||||
# Initialize system symbolizer only if other symbolizers failed.
|
||||
symbolizers[binary].append_symbolizer(
|
||||
SystemSymbolizerFactory(self.system, addr, binary))
|
||||
SystemSymbolizerFactory(self.system, addr, binary, arch))
|
||||
result = symbolizers[binary].symbolize(addr, binary, offset)
|
||||
# The system symbolizer must produce some result.
|
||||
assert result
|
||||
@ -441,16 +450,26 @@ def process_line_posix(self, line):
|
||||
if DEBUG:
|
||||
print line
|
||||
_, frameno_str, addr, binary, offset = match.groups()
|
||||
arch = ""
|
||||
# Arch can be embedded in the filename, e.g.: "libabc.dylib:x86_64h"
|
||||
colon_pos = binary.rfind(":")
|
||||
if colon_pos != -1:
|
||||
maybe_arch = binary[colon_pos+1:]
|
||||
if is_valid_arch(maybe_arch):
|
||||
arch = maybe_arch
|
||||
binary = binary[0:colon_pos]
|
||||
if arch == "":
|
||||
arch = guess_arch(addr)
|
||||
if frameno_str == '0':
|
||||
# Assume that frame #0 is the first frame of new stack trace.
|
||||
self.frame_no = 0
|
||||
original_binary = binary
|
||||
if self.binary_name_filter:
|
||||
binary = self.binary_name_filter(binary)
|
||||
symbolized_line = self.symbolize_address(addr, binary, offset)
|
||||
symbolized_line = self.symbolize_address(addr, binary, offset, arch)
|
||||
if not symbolized_line:
|
||||
if original_binary != binary:
|
||||
symbolized_line = self.symbolize_address(addr, binary, offset)
|
||||
symbolized_line = self.symbolize_address(addr, binary, offset, arch)
|
||||
return self.get_symbolized_lines(symbolized_line)
|
||||
|
||||
|
||||
@ -472,6 +491,8 @@ def process_line_posix(self, line):
|
||||
parser.add_argument('-l','--logfile', default=sys.stdin,
|
||||
type=argparse.FileType('r'),
|
||||
help='set log file name to parse, default is stdin')
|
||||
parser.add_argument('--force-system-symbolizer', action='store_true',
|
||||
help='don\'t use llvm-symbolizer')
|
||||
args = parser.parse_args()
|
||||
if args.path_to_cut:
|
||||
fix_filename_patterns = args.path_to_cut
|
||||
@ -486,5 +507,9 @@ def process_line_posix(self, line):
|
||||
logfile = args.logfile
|
||||
else:
|
||||
logfile = sys.stdin
|
||||
if args.force_system_symbolizer:
|
||||
force_system_symbolizer = True
|
||||
if force_system_symbolizer:
|
||||
assert(allow_system_symbolizer)
|
||||
loop = SymbolizationLoop(binary_name_filter)
|
||||
loop.process_logfile()
|
||||
|
@ -59,6 +59,11 @@ list(APPEND ASAN_UNITTEST_COMMON_CFLAGS
|
||||
if(APPLE)
|
||||
list(APPEND ASAN_UNITTEST_COMMON_CFLAGS ${DARWIN_osx_CFLAGS})
|
||||
list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS ${DARWIN_osx_LINKFLAGS})
|
||||
|
||||
add_weak_symbols("asan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("ubsan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINKFLAGS)
|
||||
list(APPEND ASAN_UNITTEST_COMMON_LINKFLAGS ${WEAK_SYMBOL_LINKFLAGS})
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
|
3
lib/asan/weak_symbols.txt
Normal file
3
lib/asan/weak_symbols.txt
Normal file
@ -0,0 +1,3 @@
|
||||
___asan_default_options
|
||||
___asan_default_suppressions
|
||||
___asan_on_error
|
@ -26,10 +26,10 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) \
|
||||
bl SYMBOL_NAME(__ ## cond ## sf2) SEPARATOR \
|
||||
cmp r0, #0 SEPARATOR \
|
||||
b ## cond 1f SEPARATOR \
|
||||
mov r0, #0 SEPARATOR \
|
||||
movs r0, #0 SEPARATOR \
|
||||
pop { r4, pc } SEPARATOR \
|
||||
1: SEPARATOR \
|
||||
mov r0, #1 SEPARATOR \
|
||||
movs r0, #1 SEPARATOR \
|
||||
pop { r4, pc } SEPARATOR \
|
||||
END_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond)
|
||||
|
||||
|
@ -47,27 +47,50 @@
|
||||
DEFINE_COMPILERRT_FUNCTION(__eqsf2)
|
||||
// Make copies of a and b with the sign bit shifted off the top. These will
|
||||
// be used to detect zeros and NaNs.
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
push {r6, lr}
|
||||
lsls r2, r0, #1
|
||||
lsls r3, r1, #1
|
||||
#else
|
||||
mov r2, r0, lsl #1
|
||||
mov r3, r1, lsl #1
|
||||
#endif
|
||||
|
||||
// We do the comparison in three stages (ignoring NaN values for the time
|
||||
// being). First, we orr the absolute values of a and b; this sets the Z
|
||||
// flag if both a and b are zero (of either sign). The shift of r3 doesn't
|
||||
// effect this at all, but it *does* make sure that the C flag is clear for
|
||||
// the subsequent operations.
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
lsrs r6, r3, #1
|
||||
orrs r6, r2, r6
|
||||
#else
|
||||
orrs r12, r2, r3, lsr #1
|
||||
|
||||
#endif
|
||||
// Next, we check if a and b have the same or different signs. If they have
|
||||
// opposite signs, this eor will set the N flag.
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
beq 1f
|
||||
movs r6, r0
|
||||
eors r6, r1
|
||||
1:
|
||||
#else
|
||||
it ne
|
||||
eorsne r12, r0, r1
|
||||
#endif
|
||||
|
||||
// If a and b are equal (either both zeros or bit identical; again, we're
|
||||
// ignoring NaNs for now), this subtract will zero out r0. If they have the
|
||||
// same sign, the flags are updated as they would be for a comparison of the
|
||||
// absolute values of a and b.
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
bmi 1f
|
||||
subs r0, r2, r3
|
||||
1:
|
||||
#else
|
||||
it pl
|
||||
subspl r0, r2, r3
|
||||
#endif
|
||||
|
||||
// If a is smaller in magnitude than b and both have the same sign, place
|
||||
// the negation of the sign of b in r0. Thus, if both are negative and
|
||||
@ -79,30 +102,69 @@ DEFINE_COMPILERRT_FUNCTION(__eqsf2)
|
||||
// still clear from the shift argument in orrs; if a is positive and b
|
||||
// negative, this places 0 in r0; if a is negative and b positive, -1 is
|
||||
// placed in r0.
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
bhs 1f
|
||||
// Here if a and b have the same sign and absA < absB, the result is thus
|
||||
// b < 0 ? 1 : -1. Same if a and b have the opposite sign (ignoring Nan).
|
||||
movs r0, #1
|
||||
lsrs r1, #31
|
||||
bne LOCAL_LABEL(CHECK_NAN)
|
||||
negs r0, r0
|
||||
b LOCAL_LABEL(CHECK_NAN)
|
||||
1:
|
||||
#else
|
||||
it lo
|
||||
mvnlo r0, r1, asr #31
|
||||
#endif
|
||||
|
||||
// If a is greater in magnitude than b and both have the same sign, place
|
||||
// the sign of b in r0. Thus, if both are negative and a < b, -1 is placed
|
||||
// in r0, which is the desired result. Conversely, if both are positive
|
||||
// and a > b, zero is placed in r0.
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
bls 1f
|
||||
// Here both have the same sign and absA > absB.
|
||||
movs r0, #1
|
||||
lsrs r1, #31
|
||||
beq LOCAL_LABEL(CHECK_NAN)
|
||||
negs r0, r0
|
||||
1:
|
||||
#else
|
||||
it hi
|
||||
movhi r0, r1, asr #31
|
||||
#endif
|
||||
|
||||
// If you've been keeping track, at this point r0 contains -1 if a < b and
|
||||
// 0 if a >= b. All that remains to be done is to set it to 1 if a > b.
|
||||
// If a == b, then the Z flag is set, so we can get the correct final value
|
||||
// into r0 by simply or'ing with 1 if Z is clear.
|
||||
// For Thumb-1, r0 contains -1 if a < b, 0 if a > b and 0 if a == b.
|
||||
#if __ARM_ARCH_ISA_THUMB != 1
|
||||
it ne
|
||||
orrne r0, r0, #1
|
||||
#endif
|
||||
|
||||
// Finally, we need to deal with NaNs. If either argument is NaN, replace
|
||||
// the value in r0 with 1.
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
LOCAL_LABEL(CHECK_NAN):
|
||||
movs r6, #0xff
|
||||
lsls r6, #24
|
||||
cmp r2, r6
|
||||
bhi 1f
|
||||
cmp r3, r6
|
||||
1:
|
||||
bls 2f
|
||||
movs r0, #1
|
||||
2:
|
||||
pop {r6, pc}
|
||||
#else
|
||||
cmp r2, #0xff000000
|
||||
ite ls
|
||||
cmpls r3, #0xff000000
|
||||
movhi r0, #1
|
||||
JMP(lr)
|
||||
#endif
|
||||
END_COMPILERRT_FUNCTION(__eqsf2)
|
||||
DEFINE_COMPILERRT_FUNCTION_ALIAS(__lesf2, __eqsf2)
|
||||
DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltsf2, __eqsf2)
|
||||
@ -111,11 +173,48 @@ DEFINE_COMPILERRT_FUNCTION_ALIAS(__nesf2, __eqsf2)
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__gtsf2)
|
||||
// Identical to the preceding except in that we return -1 for NaN values.
|
||||
// Given that the two paths share so much code, one might be tempted to
|
||||
// Given that the two paths share so much code, one might be tempted to
|
||||
// unify them; however, the extra code needed to do so makes the code size
|
||||
// to performance tradeoff very hard to justify for such small functions.
|
||||
mov r2, r0, lsl #1
|
||||
mov r3, r1, lsl #1
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
push {r6, lr}
|
||||
lsls r2, r0, #1
|
||||
lsls r3, r1, #1
|
||||
lsrs r6, r3, #1
|
||||
orrs r6, r2, r6
|
||||
beq 1f
|
||||
movs r6, r0
|
||||
eors r6, r1
|
||||
1:
|
||||
bmi 2f
|
||||
subs r0, r2, r3
|
||||
2:
|
||||
bhs 3f
|
||||
movs r0, #1
|
||||
lsrs r1, #31
|
||||
bne LOCAL_LABEL(CHECK_NAN_2)
|
||||
negs r0, r0
|
||||
b LOCAL_LABEL(CHECK_NAN_2)
|
||||
3:
|
||||
bls 4f
|
||||
movs r0, #1
|
||||
lsrs r1, #31
|
||||
beq LOCAL_LABEL(CHECK_NAN_2)
|
||||
negs r0, r0
|
||||
4:
|
||||
LOCAL_LABEL(CHECK_NAN_2):
|
||||
movs r6, #0xff
|
||||
lsls r6, #24
|
||||
cmp r2, r6
|
||||
bhi 5f
|
||||
cmp r3, r6
|
||||
5:
|
||||
bls 6f
|
||||
movs r0, #1
|
||||
negs r0, r0
|
||||
6:
|
||||
pop {r6, pc}
|
||||
#else
|
||||
orrs r12, r2, r3, lsr #1
|
||||
it ne
|
||||
eorsne r12, r0, r1
|
||||
@ -132,19 +231,32 @@ DEFINE_COMPILERRT_FUNCTION(__gtsf2)
|
||||
cmpls r3, #0xff000000
|
||||
movhi r0, #-1
|
||||
JMP(lr)
|
||||
#endif
|
||||
END_COMPILERRT_FUNCTION(__gtsf2)
|
||||
DEFINE_COMPILERRT_FUNCTION_ALIAS(__gesf2, __gtsf2)
|
||||
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__unordsf2)
|
||||
// Return 1 for NaN values, 0 otherwise.
|
||||
mov r2, r0, lsl #1
|
||||
mov r3, r1, lsl #1
|
||||
mov r0, #0
|
||||
lsls r2, r0, #1
|
||||
lsls r3, r1, #1
|
||||
movs r0, #0
|
||||
#if __ARM_ARCH_ISA_THUMB == 1
|
||||
movs r1, #0xff
|
||||
lsls r1, #24
|
||||
cmp r2, r1
|
||||
bhi 1f
|
||||
cmp r3, r1
|
||||
1:
|
||||
bls 2f
|
||||
movs r0, #1
|
||||
2:
|
||||
#else
|
||||
cmp r2, #0xff000000
|
||||
ite ls
|
||||
cmpls r3, #0xff000000
|
||||
movhi r0, #1
|
||||
#endif
|
||||
JMP(lr)
|
||||
END_COMPILERRT_FUNCTION(__unordsf2)
|
||||
|
||||
|
@ -23,9 +23,8 @@ add_compiler_rt_object_libraries(RTLSanCommon
|
||||
CFLAGS ${LSAN_CFLAGS})
|
||||
|
||||
if(COMPILER_RT_HAS_LSAN)
|
||||
add_compiler_rt_component(lsan)
|
||||
foreach(arch ${LSAN_SUPPORTED_ARCH})
|
||||
add_compiler_rt_component(lsan)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.lsan
|
||||
STATIC
|
||||
ARCHS ${arch}
|
||||
|
@ -258,4 +258,17 @@ SANITIZER_INTERFACE_ATTRIBUTE
|
||||
uptr __sanitizer_get_allocated_size(const void *p) {
|
||||
return GetMallocUsableSize(p);
|
||||
}
|
||||
|
||||
#if !SANITIZER_SUPPORTS_WEAK_HOOKS
|
||||
// Provide default (no-op) implementation of malloc hooks.
|
||||
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||
void __sanitizer_malloc_hook(void *ptr, uptr size) {
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
}
|
||||
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||
void __sanitizer_free_hook(void *ptr) {
|
||||
(void)ptr;
|
||||
}
|
||||
#endif
|
||||
} // extern "C"
|
||||
|
@ -758,5 +758,10 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||
int __lsan_is_turned_off() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
|
||||
const char *__lsan_default_suppressions() {
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
} // extern "C"
|
||||
|
@ -270,6 +270,8 @@ void LoadedModule::set(const char *module_name, uptr base_address,
|
||||
|
||||
void LoadedModule::clear() {
|
||||
InternalFree(full_name_);
|
||||
base_address_ = 0;
|
||||
max_executable_address_ = 0;
|
||||
full_name_ = nullptr;
|
||||
arch_ = kModuleArchUnknown;
|
||||
internal_memset(uuid_, 0, kModuleUUIDSize);
|
||||
@ -285,6 +287,8 @@ void LoadedModule::addAddressRange(uptr beg, uptr end, bool executable) {
|
||||
void *mem = InternalAlloc(sizeof(AddressRange));
|
||||
AddressRange *r = new(mem) AddressRange(beg, end, executable);
|
||||
ranges_.push_back(r);
|
||||
if (executable && end > max_executable_address_)
|
||||
max_executable_address_ = end;
|
||||
}
|
||||
|
||||
bool LoadedModule::containsAddress(uptr address) const {
|
||||
|
@ -283,6 +283,7 @@ void UpdateProcessName();
|
||||
void CacheBinaryName();
|
||||
void DisableCoreDumperIfNecessary();
|
||||
void DumpProcessMap();
|
||||
void PrintModuleMap();
|
||||
bool FileExists(const char *filename);
|
||||
const char *GetEnv(const char *name);
|
||||
bool SetEnv(const char *name, const char *value);
|
||||
@ -665,6 +666,32 @@ enum ModuleArch {
|
||||
kModuleArchARM64
|
||||
};
|
||||
|
||||
// When adding a new architecture, don't forget to also update
|
||||
// script/asan_symbolize.py and sanitizer_symbolizer_libcdep.cc.
|
||||
inline const char *ModuleArchToString(ModuleArch arch) {
|
||||
switch (arch) {
|
||||
case kModuleArchUnknown:
|
||||
return "";
|
||||
case kModuleArchI386:
|
||||
return "i386";
|
||||
case kModuleArchX86_64:
|
||||
return "x86_64";
|
||||
case kModuleArchX86_64H:
|
||||
return "x86_64h";
|
||||
case kModuleArchARMV6:
|
||||
return "armv6";
|
||||
case kModuleArchARMV7:
|
||||
return "armv7";
|
||||
case kModuleArchARMV7S:
|
||||
return "armv7s";
|
||||
case kModuleArchARMV7K:
|
||||
return "armv7k";
|
||||
case kModuleArchARM64:
|
||||
return "arm64";
|
||||
}
|
||||
CHECK(0 && "Invalid module arch");
|
||||
}
|
||||
|
||||
const uptr kModuleUUIDSize = 16;
|
||||
|
||||
// Represents a binary loaded into virtual memory (e.g. this can be an
|
||||
@ -674,6 +701,7 @@ class LoadedModule {
|
||||
LoadedModule()
|
||||
: full_name_(nullptr),
|
||||
base_address_(0),
|
||||
max_executable_address_(0),
|
||||
arch_(kModuleArchUnknown),
|
||||
instrumented_(false) {
|
||||
internal_memset(uuid_, 0, kModuleUUIDSize);
|
||||
@ -688,6 +716,7 @@ class LoadedModule {
|
||||
|
||||
const char *full_name() const { return full_name_; }
|
||||
uptr base_address() const { return base_address_; }
|
||||
uptr max_executable_address() const { return max_executable_address_; }
|
||||
ModuleArch arch() const { return arch_; }
|
||||
const u8 *uuid() const { return uuid_; }
|
||||
bool instrumented() const { return instrumented_; }
|
||||
@ -707,6 +736,7 @@ class LoadedModule {
|
||||
private:
|
||||
char *full_name_; // Owned.
|
||||
uptr base_address_;
|
||||
uptr max_executable_address_;
|
||||
ModuleArch arch_;
|
||||
u8 uuid_[kModuleUUIDSize];
|
||||
bool instrumented_;
|
||||
|
@ -74,6 +74,9 @@ COMMON_FLAG(bool, allocator_may_return_null, false,
|
||||
COMMON_FLAG(bool, print_summary, true,
|
||||
"If false, disable printing error summaries in addition to error "
|
||||
"reports.")
|
||||
COMMON_FLAG(int, print_module_map, 0,
|
||||
"OS X only. 0 = don't print, 1 = print only once before process "
|
||||
"exits, 2 = print after each report.")
|
||||
COMMON_FLAG(bool, check_printf, true, "Check printf arguments.")
|
||||
COMMON_FLAG(bool, handle_segv, true,
|
||||
"If set, registers the tool's custom SIGSEGV/SIGBUS handler.")
|
||||
|
@ -32,7 +32,7 @@
|
||||
# define SANITIZER_WEAK_ATTRIBUTE __attribute__((weak))
|
||||
#endif
|
||||
|
||||
#if (SANITIZER_LINUX || SANITIZER_WINDOWS) && !SANITIZER_GO
|
||||
#if (SANITIZER_LINUX || SANITIZER_MAC || SANITIZER_WINDOWS) && !SANITIZER_GO
|
||||
# define SANITIZER_SUPPORTS_WEAK_HOOKS 1
|
||||
#else
|
||||
# define SANITIZER_SUPPORTS_WEAK_HOOKS 0
|
||||
|
@ -1393,6 +1393,8 @@ void MaybeReexec() {
|
||||
// No need to re-exec on Linux.
|
||||
}
|
||||
|
||||
void PrintModuleMap() { }
|
||||
|
||||
uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) {
|
||||
UNREACHABLE("FindAvailableMemoryRange is not available");
|
||||
return 0;
|
||||
|
@ -26,10 +26,7 @@
|
||||
#include "sanitizer_procmaps.h"
|
||||
#include "sanitizer_stacktrace.h"
|
||||
|
||||
#if SANITIZER_ANDROID || SANITIZER_FREEBSD
|
||||
#include <dlfcn.h> // for dlsym()
|
||||
#endif
|
||||
|
||||
#include <link.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
@ -854,6 +854,36 @@ void SignalContext::DumpAllRegisters(void *context) {
|
||||
# undef DUMPREG
|
||||
}
|
||||
|
||||
static inline bool CompareBaseAddress(const LoadedModule &a,
|
||||
const LoadedModule &b) {
|
||||
return a.base_address() < b.base_address();
|
||||
}
|
||||
|
||||
void FormatUUID(char *out, uptr size, const u8 *uuid) {
|
||||
internal_snprintf(out, size,
|
||||
"<%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-"
|
||||
"%02X%02X%02X%02X%02X%02X>",
|
||||
uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5],
|
||||
uuid[6], uuid[7], uuid[8], uuid[9], uuid[10], uuid[11],
|
||||
uuid[12], uuid[13], uuid[14], uuid[15]);
|
||||
}
|
||||
|
||||
void PrintModuleMap() {
|
||||
Printf("Process module map:\n");
|
||||
MemoryMappingLayout memory_mapping(false);
|
||||
InternalMmapVector<LoadedModule> modules(/*initial_capacity*/ 128);
|
||||
memory_mapping.DumpListOfModules(&modules);
|
||||
InternalSort(&modules, modules.size(), CompareBaseAddress);
|
||||
for (uptr i = 0; i < modules.size(); ++i) {
|
||||
char uuid_str[128];
|
||||
FormatUUID(uuid_str, sizeof(uuid_str), modules[i].uuid());
|
||||
Printf("0x%zx-0x%zx %s (%s) %s\n", modules[i].base_address(),
|
||||
modules[i].max_executable_address(), modules[i].full_name(),
|
||||
ModuleArchToString(modules[i].arch()), uuid_str);
|
||||
}
|
||||
Printf("End of module map.\n");
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif // SANITIZER_MAC
|
||||
|
@ -43,7 +43,7 @@ static int AppendChar(char **buff, const char *buff_end, char c) {
|
||||
// on the value of |pad_with_zero|.
|
||||
static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
|
||||
u8 base, u8 minimal_num_length, bool pad_with_zero,
|
||||
bool negative) {
|
||||
bool negative, bool uppercase) {
|
||||
uptr const kMaxLen = 30;
|
||||
RAW_CHECK(base == 10 || base == 16);
|
||||
RAW_CHECK(base == 10 || !negative);
|
||||
@ -76,23 +76,25 @@ static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
|
||||
if (negative && !pad_with_zero) result += AppendChar(buff, buff_end, '-');
|
||||
for (; pos >= 0; pos--) {
|
||||
char digit = static_cast<char>(num_buffer[pos]);
|
||||
result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit
|
||||
: 'a' + digit - 10);
|
||||
digit = (digit < 10) ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10;
|
||||
result += AppendChar(buff, buff_end, digit);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int AppendUnsigned(char **buff, const char *buff_end, u64 num, u8 base,
|
||||
u8 minimal_num_length, bool pad_with_zero) {
|
||||
u8 minimal_num_length, bool pad_with_zero,
|
||||
bool uppercase) {
|
||||
return AppendNumber(buff, buff_end, num, base, minimal_num_length,
|
||||
pad_with_zero, false /* negative */);
|
||||
pad_with_zero, false /* negative */, uppercase);
|
||||
}
|
||||
|
||||
static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
|
||||
u8 minimal_num_length, bool pad_with_zero) {
|
||||
bool negative = (num < 0);
|
||||
return AppendNumber(buff, buff_end, (u64)(negative ? -num : num), 10,
|
||||
minimal_num_length, pad_with_zero, negative);
|
||||
minimal_num_length, pad_with_zero, negative,
|
||||
false /* uppercase */);
|
||||
}
|
||||
|
||||
static int AppendString(char **buff, const char *buff_end, int precision,
|
||||
@ -112,14 +114,16 @@ static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
|
||||
int result = 0;
|
||||
result += AppendString(buff, buff_end, -1, "0x");
|
||||
result += AppendUnsigned(buff, buff_end, ptr_value, 16,
|
||||
SANITIZER_POINTER_FORMAT_LENGTH, true);
|
||||
SANITIZER_POINTER_FORMAT_LENGTH,
|
||||
true /* pad_with_zero */, false /* uppercase */);
|
||||
return result;
|
||||
}
|
||||
|
||||
int VSNPrintf(char *buff, int buff_length,
|
||||
const char *format, va_list args) {
|
||||
static const char *kPrintfFormatsHelp =
|
||||
"Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x}; %p; %(\\.\\*)?s; %c\n";
|
||||
"Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; %(\\.\\*)?s; "
|
||||
"%c\n";
|
||||
RAW_CHECK(format);
|
||||
RAW_CHECK(buff_length > 0);
|
||||
const char *buff_end = &buff[buff_length - 1];
|
||||
@ -164,12 +168,14 @@ int VSNPrintf(char *buff, int buff_length,
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
case 'x': {
|
||||
case 'x':
|
||||
case 'X': {
|
||||
uval = have_ll ? va_arg(args, u64)
|
||||
: have_z ? va_arg(args, uptr)
|
||||
: va_arg(args, unsigned);
|
||||
result += AppendUnsigned(&buff, buff_end, uval,
|
||||
(*cur == 'u') ? 10 : 16, width, pad_with_zero);
|
||||
bool uppercase = (*cur == 'X');
|
||||
result += AppendUnsigned(&buff, buff_end, uval, (*cur == 'u') ? 10 : 16,
|
||||
width, pad_with_zero, uppercase);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
|
@ -93,7 +93,7 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
|
||||
vs_style, strip_path_prefix);
|
||||
} else if (info.module) {
|
||||
RenderModuleLocation(buffer, info.module, info.module_offset,
|
||||
strip_path_prefix);
|
||||
info.module_arch, strip_path_prefix);
|
||||
} else {
|
||||
buffer->append("(<unknown module>)");
|
||||
}
|
||||
@ -103,8 +103,9 @@ void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no,
|
||||
if (info.address & kExternalPCBit)
|
||||
{} // There PCs are not meaningful.
|
||||
else if (info.module)
|
||||
buffer->append("(%s+%p)", StripModuleName(info.module),
|
||||
(void *)info.module_offset);
|
||||
// Always strip the module name for %M.
|
||||
RenderModuleLocation(buffer, StripModuleName(info.module),
|
||||
info.module_offset, info.module_arch, "");
|
||||
else
|
||||
buffer->append("(%p)", (void *)info.address);
|
||||
break;
|
||||
@ -165,9 +166,13 @@ void RenderSourceLocation(InternalScopedString *buffer, const char *file,
|
||||
}
|
||||
|
||||
void RenderModuleLocation(InternalScopedString *buffer, const char *module,
|
||||
uptr offset, const char *strip_path_prefix) {
|
||||
buffer->append("(%s+0x%zx)", StripPathPrefix(module, strip_path_prefix),
|
||||
offset);
|
||||
uptr offset, ModuleArch arch,
|
||||
const char *strip_path_prefix) {
|
||||
buffer->append("(%s", StripPathPrefix(module, strip_path_prefix));
|
||||
if (arch != kModuleArchUnknown) {
|
||||
buffer->append(":%s", ModuleArchToString(arch));
|
||||
}
|
||||
buffer->append("+0x%zx)", offset);
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
@ -57,7 +57,8 @@ void RenderSourceLocation(InternalScopedString *buffer, const char *file,
|
||||
const char *strip_path_prefix);
|
||||
|
||||
void RenderModuleLocation(InternalScopedString *buffer, const char *module,
|
||||
uptr offset, const char *strip_path_prefix);
|
||||
uptr offset, ModuleArch arch,
|
||||
const char *strip_path_prefix);
|
||||
|
||||
// Same as RenderFrame, but for data section (global variables).
|
||||
// Accepts %s, %l from above.
|
||||
|
@ -33,9 +33,11 @@ void AddressInfo::Clear() {
|
||||
function_offset = kUnknown;
|
||||
}
|
||||
|
||||
void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset) {
|
||||
void AddressInfo::FillModuleInfo(const char *mod_name, uptr mod_offset,
|
||||
ModuleArch mod_arch) {
|
||||
module = internal_strdup(mod_name);
|
||||
module_offset = mod_offset;
|
||||
module_arch = mod_arch;
|
||||
}
|
||||
|
||||
SymbolizedStack::SymbolizedStack() : next(nullptr), info() {}
|
||||
|
@ -31,6 +31,7 @@ struct AddressInfo {
|
||||
|
||||
char *module;
|
||||
uptr module_offset;
|
||||
ModuleArch module_arch;
|
||||
|
||||
static const uptr kUnknown = ~(uptr)0;
|
||||
char *function;
|
||||
@ -43,7 +44,7 @@ struct AddressInfo {
|
||||
AddressInfo();
|
||||
// Deletes all strings and resets all fields.
|
||||
void Clear();
|
||||
void FillModuleInfo(const char *mod_name, uptr mod_offset);
|
||||
void FillModuleInfo(const char *mod_name, uptr mod_offset, ModuleArch arch);
|
||||
};
|
||||
|
||||
// Linked list of symbolized frames (each frame is described by AddressInfo).
|
||||
@ -65,6 +66,8 @@ struct DataInfo {
|
||||
// (de)allocated using sanitizer internal allocator.
|
||||
char *module;
|
||||
uptr module_offset;
|
||||
ModuleArch module_arch;
|
||||
|
||||
char *file;
|
||||
uptr line;
|
||||
char *name;
|
||||
@ -143,7 +146,8 @@ class Symbolizer final {
|
||||
static Symbolizer *PlatformInit();
|
||||
|
||||
bool FindModuleNameAndOffsetForAddress(uptr address, const char **module_name,
|
||||
uptr *module_offset);
|
||||
uptr *module_offset,
|
||||
ModuleArch *module_arch);
|
||||
ListOfModules modules_;
|
||||
// If stale, need to reload the modules before looking up addresses.
|
||||
bool modules_fresh_;
|
||||
|
@ -124,8 +124,8 @@ class LLVMSymbolizer : public SymbolizerTool {
|
||||
bool SymbolizeData(uptr addr, DataInfo *info) override;
|
||||
|
||||
private:
|
||||
const char *SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset);
|
||||
const char *FormatAndSendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset, ModuleArch arch);
|
||||
|
||||
LLVMSymbolizerProcess *symbolizer_process_;
|
||||
static const uptr kBufferSize = 16 * 1024;
|
||||
|
@ -64,11 +64,13 @@ SymbolizedStack *Symbolizer::SymbolizePC(uptr addr) {
|
||||
BlockingMutexLock l(&mu_);
|
||||
const char *module_name;
|
||||
uptr module_offset;
|
||||
ModuleArch arch;
|
||||
SymbolizedStack *res = SymbolizedStack::New(addr);
|
||||
if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
|
||||
if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset,
|
||||
&arch))
|
||||
return res;
|
||||
// Always fill data about module name and offset.
|
||||
res->info.FillModuleInfo(module_name, module_offset);
|
||||
res->info.FillModuleInfo(module_name, module_offset, arch);
|
||||
for (auto &tool : tools_) {
|
||||
SymbolizerScope sym_scope(this);
|
||||
if (tool.SymbolizePC(addr, res)) {
|
||||
@ -82,11 +84,14 @@ bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
|
||||
BlockingMutexLock l(&mu_);
|
||||
const char *module_name;
|
||||
uptr module_offset;
|
||||
if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset))
|
||||
ModuleArch arch;
|
||||
if (!FindModuleNameAndOffsetForAddress(addr, &module_name, &module_offset,
|
||||
&arch))
|
||||
return false;
|
||||
info->Clear();
|
||||
info->module = internal_strdup(module_name);
|
||||
info->module_offset = module_offset;
|
||||
info->module_arch = arch;
|
||||
for (auto &tool : tools_) {
|
||||
SymbolizerScope sym_scope(this);
|
||||
if (tool.SymbolizeData(addr, info)) {
|
||||
@ -100,8 +105,9 @@ bool Symbolizer::GetModuleNameAndOffsetForPC(uptr pc, const char **module_name,
|
||||
uptr *module_address) {
|
||||
BlockingMutexLock l(&mu_);
|
||||
const char *internal_module_name = nullptr;
|
||||
ModuleArch arch;
|
||||
if (!FindModuleNameAndOffsetForAddress(pc, &internal_module_name,
|
||||
module_address))
|
||||
module_address, &arch))
|
||||
return false;
|
||||
|
||||
if (module_name)
|
||||
@ -134,12 +140,14 @@ void Symbolizer::PrepareForSandboxing() {
|
||||
|
||||
bool Symbolizer::FindModuleNameAndOffsetForAddress(uptr address,
|
||||
const char **module_name,
|
||||
uptr *module_offset) {
|
||||
uptr *module_offset,
|
||||
ModuleArch *module_arch) {
|
||||
const LoadedModule *module = FindModuleForAddress(address);
|
||||
if (module == nullptr)
|
||||
return false;
|
||||
*module_name = module->full_name();
|
||||
*module_offset = address - module->base_address();
|
||||
*module_arch = module->arch();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -197,6 +205,8 @@ class LLVMSymbolizerProcess : public SymbolizerProcess {
|
||||
buffer[length - 2] == '\n';
|
||||
}
|
||||
|
||||
// When adding a new architecture, don't forget to also update
|
||||
// script/asan_symbolize.py and sanitizer_common.h.
|
||||
void GetArgV(const char *path_to_binary,
|
||||
const char *(&argv)[kArgVMax]) const override {
|
||||
#if defined(__x86_64h__)
|
||||
@ -284,7 +294,8 @@ void ParseSymbolizePCOutput(const char *str, SymbolizedStack *res) {
|
||||
top_frame = false;
|
||||
} else {
|
||||
cur = SymbolizedStack::New(res->info.address);
|
||||
cur->info.FillModuleInfo(res->info.module, res->info.module_offset);
|
||||
cur->info.FillModuleInfo(res->info.module, res->info.module_offset,
|
||||
res->info.module_arch);
|
||||
last->next = cur;
|
||||
last = cur;
|
||||
}
|
||||
@ -317,8 +328,10 @@ void ParseSymbolizeDataOutput(const char *str, DataInfo *info) {
|
||||
}
|
||||
|
||||
bool LLVMSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
|
||||
if (const char *buf = SendCommand(/*is_data*/ false, stack->info.module,
|
||||
stack->info.module_offset)) {
|
||||
AddressInfo *info = &stack->info;
|
||||
const char *buf = FormatAndSendCommand(
|
||||
/*is_data*/ false, info->module, info->module_offset, info->module_arch);
|
||||
if (buf) {
|
||||
ParseSymbolizePCOutput(buf, stack);
|
||||
return true;
|
||||
}
|
||||
@ -326,8 +339,9 @@ bool LLVMSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
|
||||
}
|
||||
|
||||
bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
|
||||
if (const char *buf =
|
||||
SendCommand(/*is_data*/ true, info->module, info->module_offset)) {
|
||||
const char *buf = FormatAndSendCommand(
|
||||
/*is_data*/ true, info->module, info->module_offset, info->module_arch);
|
||||
if (buf) {
|
||||
ParseSymbolizeDataOutput(buf, info);
|
||||
info->start += (addr - info->module_offset); // Add the base address.
|
||||
return true;
|
||||
@ -335,11 +349,19 @@ bool LLVMSymbolizer::SymbolizeData(uptr addr, DataInfo *info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *LLVMSymbolizer::SendCommand(bool is_data, const char *module_name,
|
||||
uptr module_offset) {
|
||||
const char *LLVMSymbolizer::FormatAndSendCommand(bool is_data,
|
||||
const char *module_name,
|
||||
uptr module_offset,
|
||||
ModuleArch arch) {
|
||||
CHECK(module_name);
|
||||
internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n",
|
||||
is_data ? "DATA " : "", module_name, module_offset);
|
||||
const char *is_data_str = is_data ? "DATA " : "";
|
||||
if (arch == kModuleArchUnknown) {
|
||||
internal_snprintf(buffer_, kBufferSize, "%s\"%s\" 0x%zx\n", is_data_str,
|
||||
module_name, module_offset);
|
||||
} else {
|
||||
internal_snprintf(buffer_, kBufferSize, "%s\"%s:%s\" 0x%zx\n", is_data_str,
|
||||
module_name, ModuleArchToString(arch), module_offset);
|
||||
}
|
||||
return symbolizer_process_->SendCommand(buffer_);
|
||||
}
|
||||
|
||||
|
@ -388,6 +388,8 @@ void DumpProcessMap() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void PrintModuleMap() { }
|
||||
|
||||
void DisableCoreDumperIfNecessary() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
@ -81,6 +81,9 @@ endif()
|
||||
if(APPLE)
|
||||
list(APPEND SANITIZER_TEST_CFLAGS_COMMON ${DARWIN_osx_CFLAGS})
|
||||
list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON ${DARWIN_osx_LINKFLAGS})
|
||||
|
||||
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINKFLAGS)
|
||||
list(APPEND SANITIZER_TEST_LINK_FLAGS_COMMON ${WEAK_SYMBOL_LINKFLAGS})
|
||||
endif()
|
||||
|
||||
# MSVC linker is allocating 1M for the stack by default, which is not
|
||||
|
@ -52,13 +52,18 @@ TEST(SanitizerStacktracePrinter, RenderSourceLocation) {
|
||||
|
||||
TEST(SanitizerStacktracePrinter, RenderModuleLocation) {
|
||||
InternalScopedString str(128);
|
||||
RenderModuleLocation(&str, "/dir/exe", 0x123, "");
|
||||
RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchUnknown, "");
|
||||
EXPECT_STREQ("(/dir/exe+0x123)", str.data());
|
||||
|
||||
// Check that we strip file prefix if necessary.
|
||||
str.clear();
|
||||
RenderModuleLocation(&str, "/dir/exe", 0x123, "/dir/");
|
||||
RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchUnknown, "/dir/");
|
||||
EXPECT_STREQ("(exe+0x123)", str.data());
|
||||
|
||||
// Check that we render the arch.
|
||||
str.clear();
|
||||
RenderModuleLocation(&str, "/dir/exe", 0x123, kModuleArchX86_64H, "/dir/");
|
||||
EXPECT_STREQ("(exe:x86_64h+0x123)", str.data());
|
||||
}
|
||||
|
||||
TEST(SanitizerStacktracePrinter, RenderFrame) {
|
||||
|
6
lib/sanitizer_common/weak_symbols.txt
Normal file
6
lib/sanitizer_common/weak_symbols.txt
Normal file
@ -0,0 +1,6 @@
|
||||
___sanitizer_free_hook
|
||||
___sanitizer_malloc_hook
|
||||
___sanitizer_symbolize_code
|
||||
___sanitizer_symbolize_data
|
||||
___sanitizer_symbolize_demangle
|
||||
___sanitizer_symbolize_flush
|
@ -5,8 +5,14 @@ set_target_properties(stats PROPERTIES FOLDER "Compiler-RT Misc")
|
||||
|
||||
if(APPLE)
|
||||
set(STATS_LIB_FLAVOR SHARED)
|
||||
|
||||
add_weak_symbols("asan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("ubsan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINKFLAGS)
|
||||
else()
|
||||
set(STATS_LIB_FLAVOR STATIC)
|
||||
|
||||
set(WEAK_SYMBOL_LINKFLAGS)
|
||||
endif()
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.stats
|
||||
@ -17,6 +23,7 @@ add_compiler_rt_runtime(clang_rt.stats
|
||||
OBJECT_LIBS RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
CFLAGS ${SANITIZER_COMMON_CFLAGS}
|
||||
LINKFLAGS ${WEAK_SYMBOL_LINKFLAGS}
|
||||
PARENT_TARGET stats)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.stats_client
|
||||
@ -25,4 +32,5 @@ add_compiler_rt_runtime(clang_rt.stats_client
|
||||
OS ${SANITIZER_COMMON_SUPPORTED_OS}
|
||||
SOURCES stats_client.cc
|
||||
CFLAGS ${SANITIZER_COMMON_CFLAGS}
|
||||
LINKFLAGS ${WEAK_SYMBOL_LINKFLAGS}
|
||||
PARENT_TARGET stats)
|
||||
|
@ -107,6 +107,10 @@ if(APPLE)
|
||||
# Pass ASM file directly to the C++ compiler.
|
||||
set_source_files_properties(${TSAN_ASM_SOURCES} PROPERTIES LANGUAGE C)
|
||||
endif()
|
||||
|
||||
add_weak_symbols("ubsan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINKFLAGS)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.tsan
|
||||
SHARED
|
||||
OS ${TSAN_SUPPORTED_OS}
|
||||
@ -117,6 +121,7 @@ if(APPLE)
|
||||
RTSanitizerCommonLibc
|
||||
RTUbsan
|
||||
CFLAGS ${TSAN_RTL_CFLAGS}
|
||||
LINKFLAGS ${WEAK_SYMBOL_LINKFLAGS}
|
||||
PARENT_TARGET tsan)
|
||||
add_compiler_rt_object_libraries(RTTsan_dynamic
|
||||
OS ${TSAN_SUPPORTED_OS}
|
||||
|
@ -1,4 +1,5 @@
|
||||
__tsan_init
|
||||
__tsan_flush_memory
|
||||
__tsan_read*
|
||||
__tsan_write*
|
||||
__tsan_vptr*
|
||||
|
@ -28,6 +28,10 @@ void __tsan_init() {
|
||||
Initialize(cur_thread());
|
||||
}
|
||||
|
||||
void __tsan_flush_memory() {
|
||||
FlushShadowMemory();
|
||||
}
|
||||
|
||||
void __tsan_read16(void *addr) {
|
||||
MemoryRead(cur_thread(), CALLERPC, (uptr)addr, kSizeLog8);
|
||||
MemoryRead(cur_thread(), CALLERPC, (uptr)addr + 8, kSizeLog8);
|
||||
|
@ -32,6 +32,8 @@ extern "C" {
|
||||
// before any instrumented code is executed and before any call to malloc.
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_init();
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_flush_memory();
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read1(void *addr);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read2(void *addr);
|
||||
SANITIZER_INTERFACE_ATTRIBUTE void __tsan_read4(void *addr);
|
||||
|
@ -358,6 +358,8 @@ void PrintReport(const ReportDesc *rep) {
|
||||
ReportErrorSummary(rep_typ_str, frame->info);
|
||||
}
|
||||
|
||||
if (common_flags()->print_module_map == 2) PrintModuleMap();
|
||||
|
||||
Printf("==================\n");
|
||||
}
|
||||
|
||||
|
@ -404,6 +404,8 @@ void Initialize(ThreadState *thr) {
|
||||
int Finalize(ThreadState *thr) {
|
||||
bool failed = false;
|
||||
|
||||
if (common_flags()->print_module_map == 1) PrintModuleMap();
|
||||
|
||||
if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
|
||||
SleepForMillis(flags()->atexit_sleep_ms);
|
||||
|
||||
|
@ -76,14 +76,18 @@ macro(add_tsan_unittest testname)
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
list(APPEND TEST_OBJECTS lib${TSAN_TEST_RUNTIME}.a)
|
||||
list(APPEND TEST_DEPS ${TSAN_TEST_RUNTIME})
|
||||
|
||||
add_weak_symbols("ubsan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINKFLAGS)
|
||||
|
||||
# Intentionally do *not* link with `-fsanitize=thread`. We already link
|
||||
# against a static version of the runtime, and we don't want the dynamic
|
||||
# one.
|
||||
add_compiler_rt_test(TsanUnitTests "${testname}-${arch}-Test"
|
||||
OBJECTS ${TEST_OBJECTS}
|
||||
DEPS ${TEST_DEPS}
|
||||
LINK_FLAGS ${TARGET_LINK_FLAGS} ${DARWIN_osx_LINKFLAGS}
|
||||
-lc++)
|
||||
LINK_FLAGS ${TARGET_LINK_FLAGS} ${DARWIN_osx_LINK_FLAGS}
|
||||
${WEAK_SYMBOL_LINKFLAGS} -lc++)
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
@ -56,6 +56,9 @@ if(APPLE)
|
||||
SOURCES ${UBSAN_STANDALONE_SOURCES}
|
||||
CFLAGS ${UBSAN_STANDALONE_CFLAGS})
|
||||
|
||||
add_weak_symbols("ubsan" WEAK_SYMBOL_LINKFLAGS)
|
||||
add_weak_symbols("sanitizer_common" WEAK_SYMBOL_LINKFLAGS)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.ubsan
|
||||
SHARED
|
||||
OS ${SANITIZER_COMMON_SUPPORTED_OS}
|
||||
@ -64,6 +67,7 @@ if(APPLE)
|
||||
RTUbsan_standalone
|
||||
RTSanitizerCommon
|
||||
RTSanitizerCommonLibc
|
||||
LINKFLAGS ${WEAK_SYMBOL_LINKFLAGS}
|
||||
PARENT_TARGET ubsan)
|
||||
endif()
|
||||
|
||||
|
@ -157,7 +157,7 @@ static void RenderLocation(InternalScopedString *Buffer, Location Loc) {
|
||||
common_flags()->strip_path_prefix);
|
||||
else if (Info.module)
|
||||
RenderModuleLocation(Buffer, Info.module, Info.module_offset,
|
||||
common_flags()->strip_path_prefix);
|
||||
Info.module_arch, common_flags()->strip_path_prefix);
|
||||
else
|
||||
Buffer->append("%p", Info.address);
|
||||
return;
|
||||
|
1
lib/ubsan/weak_symbols.txt
Normal file
1
lib/ubsan/weak_symbols.txt
Normal file
@ -0,0 +1 @@
|
||||
___ubsan_default_options
|
99
test/asan/TestCases/Darwin/haswell-symbolication.cc
Normal file
99
test/asan/TestCases/Darwin/haswell-symbolication.cc
Normal file
@ -0,0 +1,99 @@
|
||||
// RUN: %clangxx_asan -arch x86_64 -arch x86_64h -g -O0 %s -c -o %t.o.fat
|
||||
// RUN: %clangxx_asan -arch x86_64 -arch x86_64h -g %t.o.fat -o %t.fat
|
||||
|
||||
// RUN: lipo %t.fat -thin x86_64 -output %t.thin.x86_64 && lipo %t.thin.x86_64 -info | FileCheck %s --check-prefix=CHECK-LIPO-THIN-X86_64
|
||||
// RUN: lipo %t.fat -thin x86_64h -output %t.thin.x86_64h && lipo %t.thin.x86_64h -info | FileCheck %s --check-prefix=CHECK-LIPO-THIN-X86_64H
|
||||
// RUN: lipo %t.fat -extract x86_64 -output %t.fat.x86_64 && lipo %t.fat.x86_64 -info | FileCheck %s --check-prefix=CHECK-LIPO-FAT-X86_64
|
||||
// RUN: lipo %t.fat -extract x86_64h -output %t.fat.x86_64h && lipo %t.fat.x86_64h -info | FileCheck %s --check-prefix=CHECK-LIPO-FAT-X86_64H
|
||||
|
||||
// CHECK-LIPO-THIN-X86_64: Non-fat file: {{.*}} is architecture: x86_64
|
||||
// CHECK-LIPO-THIN-X86_64H: Non-fat file: {{.*}} is architecture: x86_64h
|
||||
// CHECK-LIPO-FAT-X86_64: Architectures in the fat file: {{.*}} are: x86_64
|
||||
// CHECK-LIPO-FAT-X86_64H: Architectures in the fat file: {{.*}} are: x86_64h
|
||||
|
||||
// RUN: dsymutil %t.thin.x86_64
|
||||
// RUN: dsymutil %t.thin.x86_64h
|
||||
// RUN: dsymutil %t.fat.x86_64
|
||||
// RUN: dsymutil %t.fat.x86_64h
|
||||
|
||||
// Check LLVM symbolizer
|
||||
// RUN: %env_asan_opts=external_symbolizer_path=$(which llvm-symbolizer) not %run %t.thin.x86_64 2>&1 | FileCheck %s --check-prefixes CHECK,CHECK-LI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path=$(which llvm-symbolizer) not %run %t.thin.x86_64h 2>&1 | FileCheck %s --check-prefixes CHECK,CHECK-LI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path=$(which llvm-symbolizer) not %run %t.fat.x86_64 2>&1 | FileCheck %s --check-prefixes CHECK,CHECK-LI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path=$(which llvm-symbolizer) not %run %t.fat.x86_64h 2>&1 | FileCheck %s --check-prefixes CHECK,CHECK-LI,CHECK-DATA
|
||||
|
||||
// Check atos
|
||||
// RUN: %env_asan_opts=external_symbolizer_path=$(which atos) not %run %t.thin.x86_64 2>&1 | FileCheck %s --check-prefixes CHECK,CHECK-LI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path=$(which atos) not %run %t.thin.x86_64h 2>&1 | FileCheck %s --check-prefixes CHECK,CHECK-LI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path=$(which atos) not %run %t.fat.x86_64 2>&1 | FileCheck %s --check-prefixes CHECK,CHECK-LI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path=$(which atos) not %run %t.fat.x86_64h 2>&1 | FileCheck %s --check-prefixes CHECK,CHECK-LI,CHECK-DATA
|
||||
|
||||
// Check dladdr
|
||||
// RUN: %env_asan_opts=external_symbolizer_path= not %run %t.thin.x86_64 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-NOLI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path= not %run %t.thin.x86_64h 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-NOLI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path= not %run %t.fat.x86_64 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-NOLI,CHECK-DATA
|
||||
// RUN: %env_asan_opts=external_symbolizer_path= not %run %t.fat.x86_64h 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-NOLI,CHECK-DATA
|
||||
|
||||
// Check asan_symbolize.py with llvm-symbolizer
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t.thin.x86_64 2>&1 | %asan_symbolize | FileCheck %s --check-prefixes CHECK,CHECK-LI
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t.thin.x86_64h 2>&1 | %asan_symbolize | FileCheck %s --check-prefixes CHECK,CHECK-LI
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t.fat.x86_64 2>&1 | %asan_symbolize | FileCheck %s --check-prefixes CHECK,CHECK-LI
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t.fat.x86_64h 2>&1 | %asan_symbolize | FileCheck %s --check-prefixes CHECK,CHECK-LI
|
||||
|
||||
// Check asan_symbolize.py with atos
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t.thin.x86_64 2>&1 | %asan_symbolize --force-system-symbolizer | FileCheck %s --check-prefixes CHECK,CHECK-LI
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t.thin.x86_64h 2>&1 | %asan_symbolize --force-system-symbolizer | FileCheck %s --check-prefixes CHECK,CHECK-LI
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t.fat.x86_64 2>&1 | %asan_symbolize --force-system-symbolizer | FileCheck %s --check-prefixes CHECK,CHECK-LI
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t.fat.x86_64h 2>&1 | %asan_symbolize --force-system-symbolizer | FileCheck %s --check-prefixes CHECK,CHECK-LI
|
||||
|
||||
// REQUIRES: x86-target-arch
|
||||
// REQUIRES: x86_64h
|
||||
|
||||
#include <sanitizer/common_interface_defs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if __x86_64h__
|
||||
// Unused functions and globals, just to mess up the offsets in x86_64h.
|
||||
void dummy(char *a, char *b) {
|
||||
while (*a == *b) {
|
||||
a[0] = b[0];
|
||||
a[1] = b[1];
|
||||
a[2] = b[2];
|
||||
a[3] = b[3];
|
||||
fprintf(stderr, "dummy\n");
|
||||
}
|
||||
fprintf(stderr, "dummy\n");
|
||||
}
|
||||
long dummy_global;
|
||||
long dummy_global2[100];
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
long faulty_global = 10;
|
||||
|
||||
void check_data_symbolication() {
|
||||
char data[100];
|
||||
__sanitizer_symbolize_global(&faulty_global, "%g", data, sizeof(data));
|
||||
fprintf(stderr, "symbolized global: %s\n", data);
|
||||
// CHECK-DATA: symbolized global: faulty_global
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void faulty_func(char *p) {
|
||||
*p = 'x'; // BOOM
|
||||
// CHECK: AddressSanitizer: global-buffer-overflow
|
||||
// CHECK-LI: #0 0x{{.*}} in faulty_func{{.*}} {{.*}}haswell-symbolication.cc:[[@LINE-2]]
|
||||
// CHECK-NOLI: #0 0x{{.*}} in faulty_func{{.*}} {{.*}}haswell-symbolication
|
||||
// CHECK: is located 2 bytes to the right of global variable 'faulty_global'
|
||||
// CHECK-NOT: LLVMSymbolizer: error reading file
|
||||
}
|
||||
|
||||
int main() {
|
||||
check_data_symbolication();
|
||||
|
||||
char *p = (char *)(void *)&faulty_global;
|
||||
p += 10;
|
||||
faulty_func(p);
|
||||
return 0;
|
||||
}
|
28
test/asan/TestCases/Darwin/uuid.cc
Normal file
28
test/asan/TestCases/Darwin/uuid.cc
Normal file
@ -0,0 +1,28 @@
|
||||
// RUN: %clangxx_asan %s -o %t
|
||||
// RUN: %env_asan_opts=print_module_map=1 not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %env_asan_opts=print_module_map=2 not %run %t 2>&1 | FileCheck %s
|
||||
// RUN: %clangxx_asan %s -o %t -fsanitize-recover=address
|
||||
// RUN: %env_asan_opts=print_module_map=2:halt_on_error=0 %run %t 2>&1 | FileCheck %s
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char buf[2048];
|
||||
snprintf(buf, sizeof(buf), "otool -l %s 1>&2", argv[0]);
|
||||
system(buf);
|
||||
// CHECK: cmd LC_UUID
|
||||
// CHECK-NEXT: cmdsize 24
|
||||
// CHECK-NEXT: uuid [[UUID:[0-9A-F-]{36}]]
|
||||
|
||||
char *x = (char*)malloc(10 * sizeof(char));
|
||||
free(x);
|
||||
char mybuf[10];
|
||||
memcpy(mybuf, x, 10);
|
||||
// CHECK: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
|
||||
// CHECK: Process module map:
|
||||
// CHECK: uuid.cc.tmp {{.*}} <[[UUID]]>
|
||||
|
||||
fprintf(stderr, "Done.\n");
|
||||
}
|
@ -7,7 +7,6 @@
|
||||
// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so
|
||||
// RUN: %clangxx_asan -O0 %s %libdl -o %t
|
||||
// RUN: %env_asan_opts=symbolize=0 not %run %t 2>&1 | %asan_symbolize | FileCheck %s
|
||||
// UNSUPPORTED: x86_64h-darwin,x86_64-darwin
|
||||
// REQUIRES: stable-runtime
|
||||
|
||||
#if !defined(SHARED_LIB)
|
||||
|
@ -141,6 +141,17 @@ if config.host_os == 'Darwin':
|
||||
except:
|
||||
pass
|
||||
|
||||
# Detect x86_64h
|
||||
try:
|
||||
output = subprocess.check_output(["sysctl", "hw.cpusubtype"])
|
||||
output_re = re.match("^hw.cpusubtype: ([0-9]+)$", output)
|
||||
if output_re:
|
||||
cpu_subtype = int(output_re.group(1))
|
||||
if cpu_subtype == 8: # x86_64h
|
||||
config.available_features.add('x86_64h')
|
||||
except:
|
||||
pass
|
||||
|
||||
config.substitutions.append( ("%macos_min_target_10_11", "-mmacosx-version-min=10.11") )
|
||||
else:
|
||||
config.substitutions.append( ("%macos_min_target_10_11", "") )
|
||||
|
@ -44,10 +44,10 @@ int main() {
|
||||
|
||||
// CHECK: WARNING: ThreadSanitizer: data race
|
||||
// CHECK-NEXT: Write of size 4 at {{.*}} by thread T1:
|
||||
// CHECK-NEXT: #0 foo1{{.*}} {{.*}}simple_stack2.cc:7{{(:10)?}} (simple_stack2.cc.exe+{{.*}})
|
||||
// CHECK-NEXT: #1 bar1{{.*}} {{.*}}simple_stack2.cc:14{{(:3)?}} (simple_stack2.cc.exe+{{.*}})
|
||||
// CHECK-NEXT: #2 Thread1{{.*}} {{.*}}simple_stack2.cc:32{{(:3)?}} (simple_stack2.cc.exe+{{.*}})
|
||||
// CHECK-NEXT: #0 foo1{{.*}} {{.*}}simple_stack2.cc:7{{(:10)?}} ({{.*}})
|
||||
// CHECK-NEXT: #1 bar1{{.*}} {{.*}}simple_stack2.cc:14{{(:3)?}} ({{.*}})
|
||||
// CHECK-NEXT: #2 Thread1{{.*}} {{.*}}simple_stack2.cc:32{{(:3)?}} ({{.*}})
|
||||
// CHECK: Previous read of size 4 at {{.*}} by main thread:
|
||||
// CHECK-NEXT: #0 foo2{{.*}} {{.*}}simple_stack2.cc:18{{(:22)?}} (simple_stack2.cc.exe+{{.*}})
|
||||
// CHECK-NEXT: #1 bar2{{.*}} {{.*}}simple_stack2.cc:27{{(:3)?}} (simple_stack2.cc.exe+{{.*}})
|
||||
// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack2.cc:40{{(:3)?}} (simple_stack2.cc.exe+{{.*}})
|
||||
// CHECK-NEXT: #0 foo2{{.*}} {{.*}}simple_stack2.cc:18{{(:22)?}} ({{.*}})
|
||||
// CHECK-NEXT: #1 bar2{{.*}} {{.*}}simple_stack2.cc:27{{(:3)?}} ({{.*}})
|
||||
// CHECK-NEXT: #2 main{{.*}} {{.*}}simple_stack2.cc:40{{(:3)?}} ({{.*}})
|
||||
|
Loading…
Reference in New Issue
Block a user