diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
commit | b6bc976d7be8ee56d3be4b6dbd2f3ab0a4021c86 (patch) | |
tree | f5ed5db8cb5d237a073ea00c4d4cd63153a16a6c /lib/asan | |
parent | 05342ccc9cff16425c0a831fddd510879544a0bf (diff) | |
parent | 098ca93185735ec3687106d0967a70fc99a85059 (diff) | |
download | compiler-rt-google/stable.tar.gz |
Creating branches/google/stable and tags/google/stable/2019-05-14 from r360103google/stable
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/branches/google/stable@360714 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/asan')
81 files changed, 1169 insertions, 762 deletions
diff --git a/lib/asan/CMakeLists.txt b/lib/asan/CMakeLists.txt index 726da27d0..3c4434690 100644 --- a/lib/asan/CMakeLists.txt +++ b/lib/asan/CMakeLists.txt @@ -32,6 +32,10 @@ set(ASAN_SOURCES asan_thread.cc asan_win.cc) +if (NOT WIN32 AND NOT APPLE) + list(APPEND ASAN_SOURCES asan_interceptors_vfork.S) +endif() + set(ASAN_CXX_SOURCES asan_new_delete.cc) @@ -92,7 +96,7 @@ append_list_if(COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC -ftls-model=initial-exec ASAN_DYNAMIC_CFLAGS) append_list_if(MSVC /DEBUG ASAN_DYNAMIC_LINK_FLAGS) -set(ASAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARY} ${SANITIZER_COMMON_LINK_LIBS}) +set(ASAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARIES} ${SANITIZER_COMMON_LINK_LIBS}) append_list_if(COMPILER_RT_HAS_LIBDL dl ASAN_DYNAMIC_LIBS) append_list_if(COMPILER_RT_HAS_LIBRT rt ASAN_DYNAMIC_LIBS) diff --git a/lib/asan/asan_activation.cc b/lib/asan/asan_activation.cc index d642be934..fc97cbb55 100644 --- a/lib/asan/asan_activation.cc +++ b/lib/asan/asan_activation.cc @@ -1,9 +1,8 @@ //===-- asan_activation.cc --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_activation.h b/lib/asan/asan_activation.h index d5e1ce433..93c290c2a 100644 --- a/lib/asan/asan_activation.h +++ b/lib/asan/asan_activation.h @@ -1,9 +1,8 @@ //===-- asan_activation.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_activation_flags.inc b/lib/asan/asan_activation_flags.inc index 1c66e5bb5..e0fdffc82 100644 --- a/lib/asan/asan_activation_flags.inc +++ b/lib/asan/asan_activation_flags.inc @@ -1,9 +1,8 @@ //===-- asan_activation_flags.inc -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc index c0fad4fa0..2ca6220d8 100644 --- a/lib/asan/asan_allocator.cc +++ b/lib/asan/asan_allocator.cc @@ -1,9 +1,8 @@ //===-- asan_allocator.cc -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -880,6 +879,17 @@ void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) { return SetErrnoOnNull(instance.Calloc(nmemb, size, stack)); } +void *asan_reallocarray(void *p, uptr nmemb, uptr size, + BufferedStackTrace *stack) { + if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { + errno = errno_ENOMEM; + if (AllocatorMayReturnNull()) + return nullptr; + ReportReallocArrayOverflow(nmemb, size, stack); + } + return asan_realloc(p, nmemb * size, stack); +} + void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) { if (!p) return SetErrnoOnNull(instance.Allocate(size, 8, stack, FROM_MALLOC, true)); diff --git a/lib/asan/asan_allocator.h b/lib/asan/asan_allocator.h index c9b37dc7a..6add47be2 100644 --- a/lib/asan/asan_allocator.h +++ b/lib/asan/asan_allocator.h @@ -1,9 +1,8 @@ //===-- asan_allocator.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -134,11 +133,15 @@ const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x2000000000ULL; // 128G. typedef VeryCompactSizeClassMap SizeClassMap; # elif defined(__aarch64__) -// AArch64/SANITIZER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA +// AArch64/SANITIZER_CAN_USE_ALLOCATOR64 is only for 42-bit VMA // so no need to different values for different VMA. const uptr kAllocatorSpace = 0x10000000000ULL; const uptr kAllocatorSize = 0x10000000000ULL; // 3T. typedef DefaultSizeClassMap SizeClassMap; +#elif defined(__sparc__) +const uptr kAllocatorSpace = ~(uptr)0; +const uptr kAllocatorSize = 0x20000000000ULL; // 2T. +typedef DefaultSizeClassMap SizeClassMap; # elif SANITIZER_WINDOWS const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x8000000000ULL; // 500G @@ -163,16 +166,6 @@ template <typename AddressSpaceView> using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; #else // Fallback to SizeClassAllocator32. -static const uptr kRegionSizeLog = 20; -static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; -# if SANITIZER_WORDSIZE == 32 -template <typename AddressSpaceView> -using ByteMapASVT = FlatByteMap<kNumRegions, AddressSpaceView>; -# elif SANITIZER_WORDSIZE == 64 -template <typename AddressSpaceView> -using ByteMapASVT = - TwoLevelByteMap<(kNumRegions >> 12), 1 << 12, AddressSpaceView>; -# endif typedef CompactSizeClassMap SizeClassMap; template <typename AddressSpaceViewTy> struct AP32 { @@ -180,9 +173,8 @@ struct AP32 { static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; static const uptr kMetadataSize = 16; typedef __asan::SizeClassMap SizeClassMap; - static const uptr kRegionSizeLog = __asan::kRegionSizeLog; + static const uptr kRegionSizeLog = 20; using AddressSpaceView = AddressSpaceViewTy; - using ByteMap = __asan::ByteMapASVT<AddressSpaceView>; typedef AsanMapUnmapCallback MapUnmapCallback; static const uptr kFlags = 0; }; @@ -192,21 +184,12 @@ using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; #endif // SANITIZER_CAN_USE_ALLOCATOR64 static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; -template <typename AddressSpaceView> -using AllocatorCacheASVT = - SizeClassAllocatorLocalCache<PrimaryAllocatorASVT<AddressSpaceView>>; -using AllocatorCache = AllocatorCacheASVT<LocalAddressSpaceView>; template <typename AddressSpaceView> -using SecondaryAllocatorASVT = - LargeMmapAllocator<AsanMapUnmapCallback, DefaultLargeMmapAllocatorPtrArray, - AddressSpaceView>; -template <typename AddressSpaceView> using AsanAllocatorASVT = - CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>, - AllocatorCacheASVT<AddressSpaceView>, - SecondaryAllocatorASVT<AddressSpaceView>>; + CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>>; using AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>; +using AllocatorCache = AsanAllocator::AllocatorCache; struct AsanThreadLocalMallocStorage { uptr quarantine_cache[16]; @@ -226,6 +209,8 @@ void asan_delete(void *ptr, uptr size, uptr alignment, void *asan_malloc(uptr size, BufferedStackTrace *stack); void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack); +void *asan_reallocarray(void *p, uptr nmemb, uptr size, + BufferedStackTrace *stack); void *asan_valloc(uptr size, BufferedStackTrace *stack); void *asan_pvalloc(uptr size, BufferedStackTrace *stack); diff --git a/lib/asan/asan_debugging.cc b/lib/asan/asan_debugging.cc index 7c877ded3..7052a371e 100644 --- a/lib/asan/asan_debugging.cc +++ b/lib/asan/asan_debugging.cc @@ -1,9 +1,8 @@ //===-- asan_debugging.cc -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_descriptions.cc b/lib/asan/asan_descriptions.cc index cdb562d97..9b1217a86 100644 --- a/lib/asan/asan_descriptions.cc +++ b/lib/asan/asan_descriptions.cc @@ -1,9 +1,8 @@ //===-- asan_descriptions.cc ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_descriptions.h b/lib/asan/asan_descriptions.h index 5c2d7662a..0226d844a 100644 --- a/lib/asan/asan_descriptions.h +++ b/lib/asan/asan_descriptions.h @@ -1,9 +1,8 @@ //===-- asan_descriptions.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_errors.cc b/lib/asan/asan_errors.cc index 0ecd30dca..d598e37b9 100644 --- a/lib/asan/asan_errors.cc +++ b/lib/asan/asan_errors.cc @@ -1,9 +1,8 @@ //===-- asan_errors.cc ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -36,7 +35,7 @@ static void OnStackUnwind(const SignalContext &sig, // corresponding code in the sanitizer_common and we use this callback to // print it. static_cast<const ScarinessScoreBase *>(callback_context)->Print(); - GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context, fast); + stack->Unwind(sig.pc, sig.bp, sig.context, fast); } void ErrorDeadlySignal::Print() { @@ -178,6 +177,19 @@ void ErrorCallocOverflow::Print() { ReportErrorSummary(scariness.GetDescription(), stack); } +void ErrorReallocArrayOverflow::Print() { + Decorator d; + Printf("%s", d.Error()); + Report( + "ERROR: AddressSanitizer: reallocarray parameters overflow: count * size " + "(%zd * %zd) cannot be represented in type size_t (thread %s)\n", + count, size, AsanThreadIdAndName(tid).c_str()); + Printf("%s", d.Default()); + stack->Print(); + PrintHintAllocatorCannotReturnNull(); + ReportErrorSummary(scariness.GetDescription(), stack); +} + void ErrorPvallocOverflow::Print() { Decorator d; Printf("%s", d.Error()); diff --git a/lib/asan/asan_errors.h b/lib/asan/asan_errors.h index 7ddd7e94e..f0939ae32 100644 --- a/lib/asan/asan_errors.h +++ b/lib/asan/asan_errors.h @@ -1,9 +1,8 @@ //===-- asan_errors.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -164,6 +163,21 @@ struct ErrorCallocOverflow : ErrorBase { void Print(); }; +struct ErrorReallocArrayOverflow : ErrorBase { + const BufferedStackTrace *stack; + uptr count; + uptr size; + + ErrorReallocArrayOverflow() = default; // (*) + ErrorReallocArrayOverflow(u32 tid, BufferedStackTrace *stack_, uptr count_, + uptr size_) + : ErrorBase(tid, 10, "reallocarray-overflow"), + stack(stack_), + count(count_), + size(size_) {} + void Print(); +}; + struct ErrorPvallocOverflow : ErrorBase { const BufferedStackTrace *stack; uptr size; @@ -372,6 +386,7 @@ struct ErrorGeneric : ErrorBase { macro(MallocUsableSizeNotOwned) \ macro(SanitizerGetAllocatedSizeNotOwned) \ macro(CallocOverflow) \ + macro(ReallocArrayOverflow) \ macro(PvallocOverflow) \ macro(InvalidAllocationAlignment) \ macro(InvalidAlignedAllocAlignment) \ diff --git a/lib/asan/asan_fake_stack.cc b/lib/asan/asan_fake_stack.cc index 1c6184e3c..f8e1ac4b7 100644 --- a/lib/asan/asan_fake_stack.cc +++ b/lib/asan/asan_fake_stack.cc @@ -1,9 +1,8 @@ //===-- asan_fake_stack.cc ------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_fake_stack.h b/lib/asan/asan_fake_stack.h index da9a91c23..59ba85218 100644 --- a/lib/asan/asan_fake_stack.h +++ b/lib/asan/asan_fake_stack.h @@ -1,9 +1,8 @@ //===-- asan_fake_stack.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_flags.cc b/lib/asan/asan_flags.cc index 5682ab4eb..69d2a4088 100644 --- a/lib/asan/asan_flags.cc +++ b/lib/asan/asan_flags.cc @@ -1,9 +1,8 @@ //===-- asan_flags.cc -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_flags.h b/lib/asan/asan_flags.h index 4935161c3..b55c81f07 100644 --- a/lib/asan/asan_flags.h +++ b/lib/asan/asan_flags.h @@ -1,9 +1,8 @@ //===-- asan_flags.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_flags.inc b/lib/asan/asan_flags.inc index a9c97d53b..3c30a6283 100644 --- a/lib/asan/asan_flags.inc +++ b/lib/asan/asan_flags.inc @@ -1,9 +1,8 @@ //===-- asan_flags.inc ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_fuchsia.cc b/lib/asan/asan_fuchsia.cc index 34399c923..aebc17f38 100644 --- a/lib/asan/asan_fuchsia.cc +++ b/lib/asan/asan_fuchsia.cc @@ -1,9 +1,8 @@ //===-- asan_fuchsia.cc --------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===---------------------------------------------------------------------===// // @@ -179,7 +178,7 @@ static void ThreadStartHook(void *hook, uptr os_id) { SetCurrentThread(thread); // In lieu of AsanThread::ThreadStart. - asanThreadRegistry().StartThread(thread->tid(), os_id, /*workerthread*/ false, + asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular, nullptr); } diff --git a/lib/asan/asan_globals.cc b/lib/asan/asan_globals.cc index 146234ac6..8b2fdb214 100644 --- a/lib/asan/asan_globals.cc +++ b/lib/asan/asan_globals.cc @@ -1,9 +1,8 @@ //===-- asan_globals.cc ---------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -116,7 +115,11 @@ int GetGlobalsForAddress(uptr addr, Global *globals, u32 *reg_sites, if (flags()->report_globals >= 2) ReportGlobal(g, "Search"); if (IsAddressNearGlobal(addr, g)) { +#if defined(__GNUC__) && defined(__sparc__) + internal_memcpy(&globals[res], &g, sizeof(g)); +#else globals[res] = g; +#endif if (reg_sites) reg_sites[res] = FindRegistrationSite(&g); res++; diff --git a/lib/asan/asan_globals_win.cc b/lib/asan/asan_globals_win.cc index 0e75992bf..bdce37f70 100644 --- a/lib/asan/asan_globals_win.cc +++ b/lib/asan/asan_globals_win.cc @@ -1,9 +1,8 @@ //===-- asan_globals_win.cc -----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_init_version.h b/lib/asan/asan_init_version.h index c49fcd740..b806d794e 100644 --- a/lib/asan/asan_init_version.h +++ b/lib/asan/asan_init_version.h @@ -1,9 +1,8 @@ //===-- asan_init_version.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index aac2bb8a6..234cabce1 100644 --- a/lib/asan/asan_interceptors.cc +++ b/lib/asan/asan_interceptors.cc @@ -1,9 +1,8 @@ //===-- asan_interceptors.cc ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -580,6 +579,11 @@ INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, } #endif // ASAN_INTERCEPT___CXA_ATEXIT +#if ASAN_INTERCEPT_VFORK +DEFINE_REAL(int, vfork); +DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork); +#endif + // ---------------------- InitializeAsanInterceptors ---------------- {{{1 namespace __asan { void InitializeAsanInterceptors() { @@ -657,6 +661,10 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(__cxa_atexit); #endif +#if ASAN_INTERCEPT_VFORK + ASAN_INTERCEPT_FUNC(vfork); +#endif + InitializePlatformInterceptors(); VReport(1, "AddressSanitizer: libc interceptors initialized\n"); diff --git a/lib/asan/asan_interceptors.h b/lib/asan/asan_interceptors.h index 50895b167..2792e2f14 100644 --- a/lib/asan/asan_interceptors.h +++ b/lib/asan/asan_interceptors.h @@ -1,9 +1,8 @@ //===-- asan_interceptors.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -106,6 +105,13 @@ void InitializePlatformInterceptors(); # define ASAN_INTERCEPT___STRDUP 0 #endif +#if SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__) || \ + defined(__i386__) || defined(__x86_64__)) +# define ASAN_INTERCEPT_VFORK 1 +#else +# define ASAN_INTERCEPT_VFORK 0 +#endif + DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size) DECLARE_REAL(char*, strchr, const char *str, int c) DECLARE_REAL(SIZE_T, strlen, const char *s) @@ -116,12 +122,12 @@ DECLARE_REAL(char*, strstr, const char *s1, const char *s2) #if !SANITIZER_MAC #define ASAN_INTERCEPT_FUNC(name) \ do { \ - if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \ + if (!INTERCEPT_FUNCTION(name)) \ VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \ } while (0) #define ASAN_INTERCEPT_FUNC_VER(name, ver) \ do { \ - if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \ + if (!INTERCEPT_FUNCTION_VER(name, ver)) \ VReport( \ 1, "AddressSanitizer: failed to intercept '" #name "@@" #ver "'\n"); \ } while (0) diff --git a/lib/asan/asan_interceptors_memintrinsics.cc b/lib/asan/asan_interceptors_memintrinsics.cc index 39e32cdad..e17f9ba4a 100644 --- a/lib/asan/asan_interceptors_memintrinsics.cc +++ b/lib/asan/asan_interceptors_memintrinsics.cc @@ -1,9 +1,8 @@ //===-- asan_interceptors_memintrinsics.cc --------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===---------------------------------------------------------------------===// // diff --git a/lib/asan/asan_interceptors_memintrinsics.h b/lib/asan/asan_interceptors_memintrinsics.h index a071e8f68..1fd65fe24 100644 --- a/lib/asan/asan_interceptors_memintrinsics.h +++ b/lib/asan/asan_interceptors_memintrinsics.h @@ -1,9 +1,8 @@ //===-- asan_interceptors_memintrinsics.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===---------------------------------------------------------------------===// // diff --git a/lib/asan/asan_interceptors_vfork.S b/lib/asan/asan_interceptors_vfork.S new file mode 100644 index 000000000..90a169d4b --- /dev/null +++ b/lib/asan/asan_interceptors_vfork.S @@ -0,0 +1,12 @@ +#include "sanitizer_common/sanitizer_asm.h" + +#if defined(__linux__) +#define COMMON_INTERCEPTOR_SPILL_AREA __asan_extra_spill_area +#define COMMON_INTERCEPTOR_HANDLE_VFORK __asan_handle_vfork +#include "sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S" +#include "sanitizer_common/sanitizer_common_interceptors_vfork_arm.inc.S" +#include "sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S" +#include "sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S" +#endif + +NO_EXEC_STACK_DIRECTIVE diff --git a/lib/asan/asan_interface.inc b/lib/asan/asan_interface.inc index e65f61722..7c341f22e 100644 --- a/lib/asan/asan_interface.inc +++ b/lib/asan/asan_interface.inc @@ -1,9 +1,8 @@ //===-- asan_interface.inc ------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Asan interface list. @@ -39,6 +38,7 @@ INTERFACE_FUNCTION(__asan_get_report_pc) INTERFACE_FUNCTION(__asan_get_report_sp) INTERFACE_FUNCTION(__asan_get_shadow_mapping) INTERFACE_FUNCTION(__asan_handle_no_return) +INTERFACE_FUNCTION(__asan_handle_vfork) INTERFACE_FUNCTION(__asan_init) INTERFACE_FUNCTION(__asan_load_cxx_array_cookie) INTERFACE_FUNCTION(__asan_load1) diff --git a/lib/asan/asan_interface_internal.h b/lib/asan/asan_interface_internal.h index b974c0cc4..c83aa11d7 100644 --- a/lib/asan/asan_interface_internal.h +++ b/lib/asan/asan_interface_internal.h @@ -1,9 +1,8 @@ //===-- asan_interface_internal.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -250,6 +249,8 @@ extern "C" { SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char* __asan_default_suppressions(); + + SANITIZER_INTERFACE_ATTRIBUTE void __asan_handle_vfork(void *sp); } // extern "C" #endif // ASAN_INTERFACE_INTERNAL_H diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h index 57869497c..e4f771079 100644 --- a/lib/asan/asan_internal.h +++ b/lib/asan/asan_internal.h @@ -1,9 +1,8 @@ //===-- asan_internal.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc index a150b1955..f91823289 100644 --- a/lib/asan/asan_linux.cc +++ b/lib/asan/asan_linux.cc @@ -1,9 +1,8 @@ //===-- asan_linux.cc -----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc index 17a0ec577..e776acd2f 100644 --- a/lib/asan/asan_mac.cc +++ b/lib/asan/asan_mac.cc @@ -1,9 +1,8 @@ //===-- asan_mac.cc -------------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -182,8 +181,8 @@ void asan_register_worker_thread(int parent_tid, StackTrace *stack) { t = AsanThread::Create(/* start_routine */ nullptr, /* arg */ nullptr, parent_tid, stack, /* detached */ true); t->Init(); - asanThreadRegistry().StartThread(t->tid(), GetTid(), - /* workerthread */ true, 0); + asanThreadRegistry().StartThread(t->tid(), GetTid(), ThreadType::Worker, + nullptr); SetCurrentThread(t); } } diff --git a/lib/asan/asan_malloc_linux.cc b/lib/asan/asan_malloc_linux.cc index 0a534fe21..86fcd3b12 100644 --- a/lib/asan/asan_malloc_linux.cc +++ b/lib/asan/asan_malloc_linux.cc @@ -1,9 +1,8 @@ //===-- asan_malloc_linux.cc ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -166,6 +165,14 @@ INTERCEPTOR(void*, realloc, void *ptr, uptr size) { return asan_realloc(ptr, size, &stack); } +#if SANITIZER_INTERCEPT_REALLOCARRAY +INTERCEPTOR(void*, reallocarray, void *ptr, uptr nmemb, uptr size) { + ENSURE_ASAN_INITED(); + GET_STACK_TRACE_MALLOC; + return asan_reallocarray(ptr, nmemb, size, &stack); +} +#endif // SANITIZER_INTERCEPT_REALLOCARRAY + #if SANITIZER_INTERCEPT_MEMALIGN INTERCEPTOR(void*, memalign, uptr boundary, uptr size) { GET_STACK_TRACE_MALLOC; diff --git a/lib/asan/asan_malloc_local.h b/lib/asan/asan_malloc_local.h index 0e8de207d..65e3e5a97 100644 --- a/lib/asan/asan_malloc_local.h +++ b/lib/asan/asan_malloc_local.h @@ -1,9 +1,8 @@ //===-- asan_malloc_local.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_malloc_mac.cc b/lib/asan/asan_malloc_mac.cc index 27281f1bc..06dc1c289 100644 --- a/lib/asan/asan_malloc_mac.cc +++ b/lib/asan/asan_malloc_mac.cc @@ -1,9 +1,8 @@ //===-- asan_malloc_mac.cc ------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ #include "asan_report.h" #include "asan_stack.h" #include "asan_stats.h" +#include "lsan/lsan_common.h" using namespace __asan; #define COMMON_MALLOC_ZONE_NAME "asan" @@ -58,10 +58,13 @@ using namespace __asan; GET_STACK_TRACE_FREE; \ ReportMacMzReallocUnknown((uptr)ptr, (uptr)zone_ptr, zone_name, &stack); #define COMMON_MALLOC_NAMESPACE __asan +#define COMMON_MALLOC_HAS_ZONE_ENUMERATOR 0 +#define COMMON_MALLOC_HAS_EXTRA_INTROSPECTION_INIT 1 #include "sanitizer_common/sanitizer_malloc_mac.inc" namespace COMMON_MALLOC_NAMESPACE { + bool HandleDlopenInit() { static_assert(SANITIZER_SUPPORTS_INIT_FOR_DLOPEN, "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be true"); @@ -82,4 +85,18 @@ bool HandleDlopenInit() { } } // namespace COMMON_MALLOC_NAMESPACE +namespace { + +void mi_extra_init(sanitizer_malloc_introspection_t *mi) { + uptr last_byte_plus_one = 0; + mi->allocator_ptr = 0; + // Range is [begin_ptr, end_ptr) + __lsan::GetAllocatorGlobalRange(&(mi->allocator_ptr), &last_byte_plus_one); + CHECK_NE(mi->allocator_ptr, 0); + CHECK_GT(last_byte_plus_one, mi->allocator_ptr); + mi->allocator_size = last_byte_plus_one - (mi->allocator_ptr); + CHECK_GT(mi->allocator_size, 0); +} +} // namespace + #endif diff --git a/lib/asan/asan_malloc_win.cc b/lib/asan/asan_malloc_win.cc index 887936431..b13d798a3 100644 --- a/lib/asan/asan_malloc_win.cc +++ b/lib/asan/asan_malloc_win.cc @@ -1,9 +1,8 @@ //===-- asan_malloc_win.cc ------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -49,6 +48,18 @@ using namespace __asan; // NOLINT extern "C" { ALLOCATION_FUNCTION_ATTRIBUTE +size_t _msize(void *ptr) { + GET_CURRENT_PC_BP_SP; + (void)sp; + return asan_malloc_usable_size(ptr, pc, bp); +} + +ALLOCATION_FUNCTION_ATTRIBUTE +size_t _msize_base(void *ptr) { + return _msize(ptr); +} + +ALLOCATION_FUNCTION_ATTRIBUTE void free(void *ptr) { GET_STACK_TRACE_FREE; return asan_free(ptr, &stack, FROM_MALLOC); @@ -125,7 +136,16 @@ void *_recalloc(void *p, size_t n, size_t elem_size) { const size_t size = n * elem_size; if (elem_size != 0 && size / elem_size != n) return 0; - return realloc(p, size); + + size_t old_size = _msize(p); + void *new_alloc = malloc(size); + if (new_alloc) { + REAL(memcpy)(new_alloc, p, Min(size, old_size)); + if (old_size < size) + REAL(memset)(((u8 *)new_alloc) + old_size, 0, size - old_size); + free(p); + } + return new_alloc; } ALLOCATION_FUNCTION_ATTRIBUTE @@ -134,18 +154,6 @@ void *_recalloc_base(void *p, size_t n, size_t elem_size) { } ALLOCATION_FUNCTION_ATTRIBUTE -size_t _msize(void *ptr) { - GET_CURRENT_PC_BP_SP; - (void)sp; - return asan_malloc_usable_size(ptr, pc, bp); -} - -ALLOCATION_FUNCTION_ATTRIBUTE -size_t _msize_base(void *ptr) { - return _msize(ptr); -} - -ALLOCATION_FUNCTION_ATTRIBUTE void *_expand(void *memblock, size_t size) { // _expand is used in realloc-like functions to resize the buffer if possible. // We don't want memory to stand still while resizing buffers, so return 0. @@ -199,11 +207,31 @@ INTERCEPTOR_WINAPI(BOOL, HeapFree, HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) { INTERCEPTOR_WINAPI(LPVOID, HeapReAlloc, HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes) { GET_STACK_TRACE_MALLOC; + GET_CURRENT_PC_BP_SP; + (void)sp; // Realloc should never reallocate in place. if (dwFlags & HEAP_REALLOC_IN_PLACE_ONLY) return nullptr; CHECK(dwFlags == 0 && "unsupported heap flags"); - return asan_realloc(lpMem, dwBytes, &stack); + // HeapReAlloc and HeapAlloc both happily accept 0 sized allocations. + // passing a 0 size into asan_realloc will free the allocation. + // To avoid this and keep behavior consistent, fudge the size if 0. + // (asan_malloc already does this) + if (dwBytes == 0) + dwBytes = 1; + size_t old_size; + if (dwFlags & HEAP_ZERO_MEMORY) + old_size = asan_malloc_usable_size(lpMem, pc, bp); + void *ptr = asan_realloc(lpMem, dwBytes, &stack); + if (ptr == nullptr) + return nullptr; + + if (dwFlags & HEAP_ZERO_MEMORY) { + size_t new_size = asan_malloc_usable_size(ptr, pc, bp); + if (old_size < new_size) + REAL(memset)(((u8 *)ptr) + old_size, 0, new_size - old_size); + } + return ptr; } INTERCEPTOR_WINAPI(SIZE_T, HeapSize, HANDLE hHeap, DWORD dwFlags, diff --git a/lib/asan/asan_mapping.h b/lib/asan/asan_mapping.h index f3696da62..2a32a23e1 100644 --- a/lib/asan/asan_mapping.h +++ b/lib/asan/asan_mapping.h @@ -1,9 +1,8 @@ //===-- asan_mapping.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -101,6 +100,13 @@ // || `[0x10000000000000, 0x11ffffffffffff]` || LowShadow || // || `[0x00000000000000, 0x0fffffffffffff]` || LowMem || // +// Default Linux/SPARC64 (52-bit VMA) mapping: +// || `[0x8000000000000, 0xfffffffffffff]` || HighMem || +// || `[0x1080000000000, 0x207ffffffffff]` || HighShadow || +// || `[0x0090000000000, 0x107ffffffffff]` || ShadowGap || +// || `[0x0080000000000, 0x008ffffffffff]` || LowShadow || +// || `[0x0000000000000, 0x007ffffffffff]` || LowMem || +// // Shadow mapping on FreeBSD/x86-64 with SHADOW_OFFSET == 0x400000000000: // || `[0x500000000000, 0x7fffffffffff]` || HighMem || // || `[0x4a0000000000, 0x4fffffffffff]` || HighShadow || @@ -163,6 +169,7 @@ static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000; static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; static const u64 kPPC64_ShadowOffset64 = 1ULL << 44; static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52; +static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43; // 0x80000000000 static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000 static const u64 kFreeBSD_ShadowOffset64 = 1ULL << 46; // 0x400000000000 static const u64 kNetBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000 @@ -225,6 +232,8 @@ static const u64 kMyriadCacheBitMask32 = 0x40000000ULL; # define SHADOW_OFFSET kDefaultShadowOffset64 # elif defined(__mips64) # define SHADOW_OFFSET kMIPS64_ShadowOffset64 +#elif defined(__sparc__) +#define SHADOW_OFFSET kSPARC64_ShadowOffset64 # elif SANITIZER_WINDOWS64 # define SHADOW_OFFSET __asan_shadow_memory_dynamic_address # else @@ -271,6 +280,8 @@ extern uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; // Initialized in __asan_init. #if SANITIZER_MYRIAD2 #include "asan_mapping_myriad.h" +#elif defined(__sparc__) && SANITIZER_WORDSIZE == 64 +#include "asan_mapping_sparc64.h" #else #define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET)) diff --git a/lib/asan/asan_mapping_myriad.h b/lib/asan/asan_mapping_myriad.h index baa3247bd..6969e3a49 100644 --- a/lib/asan/asan_mapping_myriad.h +++ b/lib/asan/asan_mapping_myriad.h @@ -1,9 +1,8 @@ //===-- asan_mapping_myriad.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_mapping_sparc64.h b/lib/asan/asan_mapping_sparc64.h new file mode 100644 index 000000000..432a1816f --- /dev/null +++ b/lib/asan/asan_mapping_sparc64.h @@ -0,0 +1,101 @@ +//===-- asan_mapping_sparc64.h ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// SPARC64-specific definitions for ASan memory mapping. +//===----------------------------------------------------------------------===// +#ifndef ASAN_MAPPING_SPARC64_H +#define ASAN_MAPPING_SPARC64_H + +// This is tailored to the 52-bit VM layout on SPARC-T4 and later. +// The VM space is split into two 51-bit halves at both ends: the low part +// has all the bits above the 51st cleared, while the high part has them set. +// 0xfff8000000000000 - 0xffffffffffffffff +// 0x0000000000000000 - 0x0007ffffffffffff + +#define VMA_BITS 52 +#define HIGH_BITS (64 - VMA_BITS) + +// The idea is to chop the high bits before doing the scaling, so the two +// parts become contiguous again and the usual scheme can be applied. + +#define MEM_TO_SHADOW(mem) \ + ((((mem) << HIGH_BITS) >> (HIGH_BITS + (SHADOW_SCALE))) + (SHADOW_OFFSET)) + +#define kLowMemBeg 0 +#define kLowMemEnd (SHADOW_OFFSET - 1) + +#define kLowShadowBeg SHADOW_OFFSET +#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) + +// But of course there is the huge hole between the high shadow memory, +// which is in the low part, and the beginning of the high part. + +#define kHighMemBeg (-(1ULL << (VMA_BITS - 1))) + +#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) +#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) + +#define kMidShadowBeg 0 +#define kMidShadowEnd 0 + +// With the zero shadow base we can not actually map pages starting from 0. +// This constant is somewhat arbitrary. +#define kZeroBaseShadowStart 0 +#define kZeroBaseMaxShadowStart (1 << 18) + +#define kShadowGapBeg (kLowShadowEnd + 1) +#define kShadowGapEnd (kHighShadowBeg - 1) + +#define kShadowGap2Beg 0 +#define kShadowGap2End 0 + +#define kShadowGap3Beg 0 +#define kShadowGap3End 0 + +namespace __asan { + +static inline bool AddrIsInLowMem(uptr a) { + PROFILE_ASAN_MAPPING(); + return a <= kLowMemEnd; +} + +static inline bool AddrIsInLowShadow(uptr a) { + PROFILE_ASAN_MAPPING(); + return a >= kLowShadowBeg && a <= kLowShadowEnd; +} + +static inline bool AddrIsInMidMem(uptr a) { + PROFILE_ASAN_MAPPING(); + return false; +} + +static inline bool AddrIsInMidShadow(uptr a) { + PROFILE_ASAN_MAPPING(); + return false; +} + +static inline bool AddrIsInHighMem(uptr a) { + PROFILE_ASAN_MAPPING(); + return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd; +} + +static inline bool AddrIsInHighShadow(uptr a) { + PROFILE_ASAN_MAPPING(); + return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd; +} + +static inline bool AddrIsInShadowGap(uptr a) { + PROFILE_ASAN_MAPPING(); + return a >= kShadowGapBeg && a <= kShadowGapEnd; +} + +} // namespace __asan + +#endif // ASAN_MAPPING_SPARC64_H diff --git a/lib/asan/asan_memory_profile.cc b/lib/asan/asan_memory_profile.cc index 8c86d9fe4..87d874d2f 100644 --- a/lib/asan/asan_memory_profile.cc +++ b/lib/asan/asan_memory_profile.cc @@ -1,9 +1,8 @@ //===-- asan_memory_profile.cc.cc -----------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_new_delete.cc b/lib/asan/asan_new_delete.cc index e6053c1fe..8b53ac96e 100644 --- a/lib/asan/asan_new_delete.cc +++ b/lib/asan/asan_new_delete.cc @@ -1,9 +1,8 @@ //===-- asan_interceptors.cc ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_poisoning.cc b/lib/asan/asan_poisoning.cc index 1e9c37a13..44b87c76e 100644 --- a/lib/asan/asan_poisoning.cc +++ b/lib/asan/asan_poisoning.cc @@ -1,9 +1,8 @@ //===-- asan_poisoning.cc -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_poisoning.h b/lib/asan/asan_poisoning.h index c94794cea..ca14d11fd 100644 --- a/lib/asan/asan_poisoning.h +++ b/lib/asan/asan_poisoning.h @@ -1,9 +1,8 @@ //===-- asan_poisoning.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc index ca99c04b3..5c5e0359a 100644 --- a/lib/asan/asan_posix.cc +++ b/lib/asan/asan_posix.cc @@ -1,9 +1,8 @@ //===-- asan_posix.cc -----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_preinit.cc b/lib/asan/asan_preinit.cc index a3986d24f..444998c44 100644 --- a/lib/asan/asan_preinit.cc +++ b/lib/asan/asan_preinit.cc @@ -1,9 +1,8 @@ //===-- asan_preinit.cc ---------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_premap_shadow.cc b/lib/asan/asan_premap_shadow.cc index 229eba99f..6e547718c 100644 --- a/lib/asan/asan_premap_shadow.cc +++ b/lib/asan/asan_premap_shadow.cc @@ -1,9 +1,8 @@ //===-- asan_premap_shadow.cc ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_premap_shadow.h b/lib/asan/asan_premap_shadow.h index 41acbdbbb..c9c886e8d 100644 --- a/lib/asan/asan_premap_shadow.h +++ b/lib/asan/asan_premap_shadow.h @@ -1,9 +1,8 @@ //===-- asan_mapping.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc index 439712350..551753b4a 100644 --- a/lib/asan/asan_report.cc +++ b/lib/asan/asan_report.cc @@ -1,9 +1,8 @@ //===-- asan_report.cc ----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -264,6 +263,13 @@ void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack) { in_report.ReportError(error); } +void ReportReallocArrayOverflow(uptr count, uptr size, + BufferedStackTrace *stack) { + ScopedInErrorReport in_report(/*fatal*/ true); + ErrorReallocArrayOverflow error(GetCurrentTidOrInvalid(), stack, count, size); + in_report.ReportError(error); +} + void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack) { ScopedInErrorReport in_report(/*fatal*/ true); ErrorPvallocOverflow error(GetCurrentTidOrInvalid(), stack, size); diff --git a/lib/asan/asan_report.h b/lib/asan/asan_report.h index b0c167dda..dcf60894e 100644 --- a/lib/asan/asan_report.h +++ b/lib/asan/asan_report.h @@ -1,9 +1,8 @@ //===-- asan_report.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -62,6 +61,8 @@ void ReportMallocUsableSizeNotOwned(uptr addr, BufferedStackTrace *stack); void ReportSanitizerGetAllocatedSizeNotOwned(uptr addr, BufferedStackTrace *stack); void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack); +void ReportReallocArrayOverflow(uptr count, uptr size, + BufferedStackTrace *stack); void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack); void ReportInvalidAllocationAlignment(uptr alignment, BufferedStackTrace *stack); diff --git a/lib/asan/asan_rtems.cc b/lib/asan/asan_rtems.cc index b48cc6a75..4878f4d67 100644 --- a/lib/asan/asan_rtems.cc +++ b/lib/asan/asan_rtems.cc @@ -1,9 +1,8 @@ //===-- asan_rtems.cc -----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -184,8 +183,8 @@ static void ThreadStartHook(void *hook, uptr os_id) { // Determine whether we are starting or restarting the thread. if (status == ThreadStatusCreated) // In lieu of AsanThread::ThreadStart. - asanThreadRegistry().StartThread(thread->tid(), os_id, - /*workerthread*/ false, nullptr); + asanThreadRegistry().StartThread(thread->tid(), os_id, ThreadType::Regular, + nullptr); else { // In a thread restart, a thread may resume execution at an // arbitrary function entry point, with its stack and TLS state diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc index 13344f3b8..db8dcd068 100644 --- a/lib/asan/asan_rtl.cc +++ b/lib/asan/asan_rtl.cc @@ -1,9 +1,8 @@ //===-- asan_rtl.cc -------------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -598,6 +597,19 @@ void NOINLINE __asan_handle_no_return() { curr_thread->fake_stack()->HandleNoReturn(); } +extern "C" void *__asan_extra_spill_area() { + AsanThread *t = GetCurrentThread(); + CHECK(t); + return t->extra_spill_area(); +} + +void __asan_handle_vfork(void *sp) { + AsanThread *t = GetCurrentThread(); + CHECK(t); + uptr bottom = t->stack_bottom(); + PoisonShadow(bottom, (uptr)sp - bottom, 0); +} + void NOINLINE __asan_set_death_callback(void (*callback)(void)) { SetUserDieCallback(callback); } diff --git a/lib/asan/asan_scariness_score.h b/lib/asan/asan_scariness_score.h index 7f095dd29..9e7ba47d8 100644 --- a/lib/asan/asan_scariness_score.h +++ b/lib/asan/asan_scariness_score.h @@ -1,9 +1,8 @@ //===-- asan_scariness_score.h ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_shadow_setup.cc b/lib/asan/asan_shadow_setup.cc index 083926e70..9cfa4e2bd 100644 --- a/lib/asan/asan_shadow_setup.cc +++ b/lib/asan/asan_shadow_setup.cc @@ -1,9 +1,8 @@ //===-- asan_shadow_setup.cc ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_stack.cc b/lib/asan/asan_stack.cc index cf7a587fa..b244da4fa 100644 --- a/lib/asan/asan_stack.cc +++ b/lib/asan/asan_stack.cc @@ -1,9 +1,8 @@ //===-- asan_stack.cc -----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -27,8 +26,57 @@ u32 GetMallocContextSize() { return atomic_load(&malloc_context_size, memory_order_acquire); } +namespace { + +// ScopedUnwinding is a scope for stacktracing member of a context +class ScopedUnwinding { + public: + explicit ScopedUnwinding(AsanThread *t) : thread(t) { + if (thread) { + can_unwind = !thread->isUnwinding(); + thread->setUnwinding(true); + } + } + ~ScopedUnwinding() { + if (thread) + thread->setUnwinding(false); + } + + bool CanUnwind() const { return can_unwind; } + + private: + AsanThread *thread = nullptr; + bool can_unwind = true; +}; + +} // namespace + } // namespace __asan +void __sanitizer::BufferedStackTrace::UnwindImpl( + uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { + using namespace __asan; + size = 0; + if (UNLIKELY(!asan_inited)) + return; + request_fast = StackTrace::WillUseFastUnwind(request_fast); + AsanThread *t = GetCurrentThread(); + ScopedUnwinding unwind_scope(t); + if (!unwind_scope.CanUnwind()) + return; + if (request_fast) { + if (t) { + Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), + true); + } + return; + } + if (SANITIZER_MIPS && t && + !IsValidFrame(bp, t->stack_top(), t->stack_bottom())) + return; + Unwind(max_depth, pc, bp, context, 0, 0, false); +} + // ------------------ Interface -------------- {{{1 extern "C" { diff --git a/lib/asan/asan_stack.h b/lib/asan/asan_stack.h index 8e9df888d..3a4b3cefc 100644 --- a/lib/asan/asan_stack.h +++ b/lib/asan/asan_stack.h @@ -1,9 +1,8 @@ //===-- asan_stack.h --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -27,34 +26,6 @@ static const u32 kDefaultMallocContextSize = 30; void SetMallocContextSize(u32 size); u32 GetMallocContextSize(); -// Get the stack trace with the given pc and bp. -// The pc will be in the position 0 of the resulting stack trace. -// The bp may refer to the current frame or to the caller's frame. -ALWAYS_INLINE -void GetStackTrace(BufferedStackTrace *stack, uptr max_depth, uptr pc, uptr bp, - void *context, bool fast) { -#if SANITIZER_WINDOWS - stack->Unwind(max_depth, pc, bp, context, 0, 0, fast); -#else - AsanThread *t; - stack->size = 0; - if (LIKELY(asan_inited)) { - if ((t = GetCurrentThread()) && !t->isUnwinding()) { - uptr stack_top = t->stack_top(); - uptr stack_bottom = t->stack_bottom(); - ScopedUnwinding unwind_scope(t); - if (!SANITIZER_MIPS || IsValidFrame(bp, stack_top, stack_bottom)) { - stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, - fast); - } - } else if (!t && !fast) { - /* If GetCurrentThread() has failed, try to do slow unwind anyways. */ - stack->Unwind(max_depth, pc, bp, context, 0, 0, false); - } - } -#endif // SANITIZER_WINDOWS -} - } // namespace __asan // NOTE: A Rule of thumb is to retrieve stack trace in the interceptors @@ -71,19 +42,19 @@ void GetStackTrace(BufferedStackTrace *stack, uptr max_depth, uptr pc, uptr bp, if (max_size > 1) stack.trace_buffer[1] = GET_CALLER_PC(); \ } \ } else { \ - GetStackTrace(&stack, max_size, StackTrace::GetCurrentPc(), \ - GET_CURRENT_FRAME(), 0, fast); \ + stack.Unwind(StackTrace::GetCurrentPc(), \ + GET_CURRENT_FRAME(), nullptr, fast, max_size); \ } #define GET_STACK_TRACE_FATAL(pc, bp) \ BufferedStackTrace stack; \ - GetStackTrace(&stack, kStackTraceMax, pc, bp, 0, \ - common_flags()->fast_unwind_on_fatal) + stack.Unwind(pc, bp, nullptr, \ + common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_SIGNAL(sig) \ BufferedStackTrace stack; \ - GetStackTrace(&stack, kStackTraceMax, (sig).pc, (sig).bp, (sig).context, \ - common_flags()->fast_unwind_on_fatal) + stack.Unwind((sig).pc, (sig).bp, (sig).context, \ + common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_FATAL_HERE \ GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal) diff --git a/lib/asan/asan_stats.cc b/lib/asan/asan_stats.cc index b8c68c32d..2f996ce63 100644 --- a/lib/asan/asan_stats.cc +++ b/lib/asan/asan_stats.cc @@ -1,9 +1,8 @@ //===-- asan_stats.cc -----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_stats.h b/lib/asan/asan_stats.h index 4605135e1..d6da65340 100644 --- a/lib/asan/asan_stats.h +++ b/lib/asan/asan_stats.h @@ -1,9 +1,8 @@ //===-- asan_stats.h --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_suppressions.cc b/lib/asan/asan_suppressions.cc index ac8aa023f..118853e61 100644 --- a/lib/asan/asan_suppressions.cc +++ b/lib/asan/asan_suppressions.cc @@ -1,9 +1,8 @@ //===-- asan_suppressions.cc ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_suppressions.h b/lib/asan/asan_suppressions.h index 5246b4b30..9bf297602 100644 --- a/lib/asan/asan_suppressions.h +++ b/lib/asan/asan_suppressions.h @@ -1,9 +1,8 @@ //===-- asan_suppressions.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_thread.cc b/lib/asan/asan_thread.cc index 0895e4ce0..e63561c22 100644 --- a/lib/asan/asan_thread.cc +++ b/lib/asan/asan_thread.cc @@ -1,9 +1,8 @@ //===-- asan_thread.cc ----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -246,8 +245,7 @@ void AsanThread::Init(const InitOptions *options) { thread_return_t AsanThread::ThreadStart( tid_t os_id, atomic_uintptr_t *signal_thread_is_registered) { Init(); - asanThreadRegistry().StartThread(tid(), os_id, /*workerthread*/ false, - nullptr); + asanThreadRegistry().StartThread(tid(), os_id, ThreadType::Regular, nullptr); if (signal_thread_is_registered) atomic_store(signal_thread_is_registered, 1, memory_order_release); diff --git a/lib/asan/asan_thread.h b/lib/asan/asan_thread.h index 660919211..d725e8886 100644 --- a/lib/asan/asan_thread.h +++ b/lib/asan/asan_thread.h @@ -1,9 +1,8 @@ //===-- asan_thread.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -131,6 +130,8 @@ class AsanThread { AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } AsanStats &stats() { return stats_; } + void *extra_spill_area() { return &extra_spill_area_; } + private: // NOTE: There is no AsanThread constructor. It is allocated // via mmap() and *must* be valid in zero-initialized state. @@ -166,18 +167,7 @@ class AsanThread { AsanThreadLocalMallocStorage malloc_storage_; AsanStats stats_; bool unwinding_; -}; - -// ScopedUnwinding is a scope for stacktracing member of a context -class ScopedUnwinding { - public: - explicit ScopedUnwinding(AsanThread *t) : thread(t) { - t->setUnwinding(true); - } - ~ScopedUnwinding() { thread->setUnwinding(false); } - - private: - AsanThread *thread; + uptr extra_spill_area_; }; // Returns a single instance of registry. diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc index 068f4a5d2..c9b81fa8f 100644 --- a/lib/asan/asan_win.cc +++ b/lib/asan/asan_win.cc @@ -1,9 +1,8 @@ //===-- asan_win.cc -------------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -105,7 +104,9 @@ INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) { #ifdef _WIN64 -INTERCEPTOR_WINAPI(int, __C_specific_handler, void *a, void *b, void *c, void *d) { // NOLINT +INTERCEPTOR_WINAPI(EXCEPTION_DISPOSITION, __C_specific_handler, + _EXCEPTION_RECORD *a, void *b, _CONTEXT *c, + _DISPATCHER_CONTEXT *d) { // NOLINT CHECK(REAL(__C_specific_handler)); __asan_handle_no_return(); return REAL(__C_specific_handler)(a, b, c, d); @@ -136,10 +137,9 @@ static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { return t->ThreadStart(GetTid(), /* signal_thread_is_registered */ nullptr); } -INTERCEPTOR_WINAPI(DWORD, CreateThread, - void* security, uptr stack_size, - DWORD (__stdcall *start_routine)(void*), void* arg, - DWORD thr_flags, void* tid) { +INTERCEPTOR_WINAPI(HANDLE, CreateThread, LPSECURITY_ATTRIBUTES security, + SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine, + void *arg, DWORD thr_flags, DWORD *tid) { // Strict init-order checking is thread-hostile. if (flags()->strict_init_order) StopInitOrderChecking(); @@ -149,9 +149,9 @@ INTERCEPTOR_WINAPI(DWORD, CreateThread, bool detached = false; // FIXME: how can we determine it on Windows? u32 current_tid = GetCurrentTidOrInvalid(); AsanThread *t = - AsanThread::Create(start_routine, arg, current_tid, &stack, detached); - return REAL(CreateThread)(security, stack_size, - asan_thread_start, t, thr_flags, tid); + AsanThread::Create(start_routine, arg, current_tid, &stack, detached); + return REAL(CreateThread)(security, stack_size, asan_thread_start, t, + thr_flags, tid); } // }}} @@ -355,6 +355,19 @@ __declspec(allocate(".CRT$XLAB")) void (NTAPI *__asan_tls_init)(void *, unsigned long, void *) = asan_thread_init; #endif +static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) { + if (reason == DLL_THREAD_DETACH) { + // Unpoison the thread's stack because the memory may be re-used. + NT_TIB *tib = (NT_TIB *)NtCurrentTeb(); + uptr stackSize = (uptr)tib->StackBase - (uptr)tib->StackLimit; + __asan_unpoison_memory_region(tib->StackLimit, stackSize); + } +} + +#pragma section(".CRT$XLY", long, read) // NOLINT +__declspec(allocate(".CRT$XLY")) void (NTAPI *__asan_tls_exit)(void *, + unsigned long, void *) = asan_thread_exit; + WIN_FORCE_LINK(__asan_dso_reg_hook) // }}} diff --git a/lib/asan/asan_win_dll_thunk.cc b/lib/asan/asan_win_dll_thunk.cc index df593ab92..47b3948c5 100644 --- a/lib/asan/asan_win_dll_thunk.cc +++ b/lib/asan/asan_win_dll_thunk.cc @@ -1,9 +1,8 @@ //===-- asan_win_dll_thunk.cc ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_win_dynamic_runtime_thunk.cc b/lib/asan/asan_win_dynamic_runtime_thunk.cc index 416c73b23..cf4a59842 100644 --- a/lib/asan/asan_win_dynamic_runtime_thunk.cc +++ b/lib/asan/asan_win_dynamic_runtime_thunk.cc @@ -1,9 +1,8 @@ //===-- asan_win_dynamic_runtime_thunk.cc ---------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/asan_win_weak_interception.cc b/lib/asan/asan_win_weak_interception.cc index ca26f914c..19965ca47 100644 --- a/lib/asan/asan_win_weak_interception.cc +++ b/lib/asan/asan_win_weak_interception.cc @@ -1,9 +1,8 @@ //===-- asan_win_weak_interception.cc -------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // This module should be included in Address Sanitizer when it is implemented as diff --git a/lib/asan/scripts/asan_device_setup b/lib/asan/scripts/asan_device_setup index 5e679e366..041bf92e6 100755 --- a/lib/asan/scripts/asan_device_setup +++ b/lib/asan/scripts/asan_device_setup @@ -1,10 +1,9 @@ #!/bin/bash #===- lib/asan/scripts/asan_device_setup -----------------------------------===# # -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # # Prepare Android device to run ASan applications. # diff --git a/lib/asan/scripts/asan_symbolize.py b/lib/asan/scripts/asan_symbolize.py index 2dbb05283..4fb3355d7 100755 --- a/lib/asan/scripts/asan_symbolize.py +++ b/lib/asan/scripts/asan_symbolize.py @@ -1,26 +1,36 @@ #!/usr/bin/env python #===- lib/asan/scripts/asan_symbolize.py -----------------------------------===# # -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===------------------------------------------------------------------------===# +""" +Example of use: + asan_symbolize.py -c "$HOME/opt/cross/bin/arm-linux-gnueabi-" -s "$HOME/SymbolFiles" < asan.log + +PLUGINS + +This script provides a way for external plug-ins to hook into the behaviour of +various parts of this script (see `--plugins`). This is useful for situations +where it is necessary to handle site-specific quirks (e.g. binaries with debug +symbols only accessible via a remote service) without having to modify the +script itself. + +""" import argparse import bisect import getopt +import logging import os import re import subprocess import sys symbolizers = {} -DEBUG = False demangle = False binutils_prefix = None -sysroot_path = None -binary_name_filter = None fix_filename_patterns = None logfile = sys.stdin allow_system_symbolizer = True @@ -35,9 +45,6 @@ def fix_filename(file_name): file_name = re.sub('.*crtstuff.c:0', '???:0', file_name) return 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"] @@ -88,8 +95,7 @@ class LLVMSymbolizer(Symbolizer): if self.system == 'Darwin': for hint in self.dsym_hints: cmd.append('--dsym-hint=%s' % hint) - if DEBUG: - print(' '.join(cmd)) + logging.debug(' '.join(cmd)) try: result = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, @@ -106,8 +112,7 @@ class LLVMSymbolizer(Symbolizer): result = [] try: symbolizer_input = '"%s" %s' % (binary, offset) - if DEBUG: - print(symbolizer_input) + logging.debug(symbolizer_input) self.pipe.stdin.write("%s\n" % symbolizer_input) while True: function_name = self.pipe.stdout.readline().rstrip() @@ -152,8 +157,7 @@ class Addr2LineSymbolizer(Symbolizer): if demangle: cmd += ['--demangle'] cmd += ['-e', self.binary] - if DEBUG: - print(' '.join(cmd)) + logging.debug(' '.join(cmd)) return subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=0, @@ -222,8 +226,7 @@ class DarwinSymbolizer(Symbolizer): self.open_atos() def open_atos(self): - if DEBUG: - print('atos -o %s -arch %s' % (self.binary, self.arch)) + logging.debug('atos -o %s -arch %s', self.binary, self.arch) cmdline = ['atos', '-o', self.binary, '-arch', self.arch] self.atos = UnbufferedLineConverter(cmdline, close_stderr=True) @@ -241,8 +244,7 @@ class DarwinSymbolizer(Symbolizer): # A well-formed atos response looks like this: # foo(type1, type2) (in object.name) (filename.cc:80) match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line) - if DEBUG: - print('atos_line: ', atos_line) + logging.debug('atos_line: %s', atos_line) if match: function_name = match.group(1) function_name = re.sub('\(.*?\)', '', function_name) @@ -363,7 +365,8 @@ class BreakpadSymbolizer(Symbolizer): class SymbolizationLoop(object): - def __init__(self, binary_name_filter=None, dsym_hint_producer=None): + def __init__(self, plugin_proxy=None, dsym_hint_producer=None): + self.plugin_proxy = plugin_proxy if sys.platform == 'win32': # ASan on Windows uses dbghelp.dll to symbolize in-process, which works # even in sandboxed processes. Nothing needs to be done here. @@ -371,7 +374,6 @@ class SymbolizationLoop(object): else: # Used by clients who may want to supply a different binary name. # E.g. in Chrome several binaries may share a single .dSYM. - self.binary_name_filter = binary_name_filter self.dsym_hint_producer = dsym_hint_producer self.system = os.uname()[0] if self.system not in ['Linux', 'Darwin', 'FreeBSD', 'NetBSD','SunOS']: @@ -455,8 +457,7 @@ class SymbolizationLoop(object): match = re.match(stack_trace_line_format, line) if not match: return [self.current_line] - if DEBUG: - print(line) + logging.debug(line) _, frameno_str, addr, binary, offset = match.groups() arch = "" # Arch can be embedded in the filename, e.g.: "libabc.dylib:x86_64h" @@ -472,52 +473,522 @@ class SymbolizationLoop(object): # 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) + binary = self.plugin_proxy.filter_binary_path(binary) + if binary is None: + # The binary filter has told us this binary can't be symbolized. + logging.debug('Skipping symbolication of binary "%s"', original_binary) + return [self.current_line] symbolized_line = self.symbolize_address(addr, binary, offset, arch) if not symbolized_line: if original_binary != binary: symbolized_line = self.symbolize_address(addr, original_binary, offset, arch) return self.get_symbolized_lines(symbolized_line) +class AsanSymbolizerPlugInProxy(object): + """ + Serves several purposes: + - Manages the lifetime of plugins (must be used a `with` statement). + - Provides interface for calling into plugins from within this script. + """ + def __init__(self): + self._plugins = [ ] + self._plugin_names = set() + + def _load_plugin_from_file_impl_py_gt_2(self, file_path, globals_space): + with open(file_path, 'r') as f: + exec(f.read(), globals_space, None) + + def load_plugin_from_file(self, file_path): + logging.info('Loading plugins from "{}"'.format(file_path)) + globals_space = dict(globals()) + # Provide function to register plugins + def register_plugin(plugin): + logging.info('Registering plugin %s', plugin.get_name()) + self.add_plugin(plugin) + globals_space['register_plugin'] = register_plugin + if sys.version_info.major < 3: + execfile(file_path, globals_space, None) + else: + # Indirection here is to avoid a bug in older Python 2 versions: + # `SyntaxError: unqualified exec is not allowed in function ...` + self._load_plugin_from_file_impl_py_gt_2(file_path, globals_space) + + def add_plugin(self, plugin): + assert isinstance(plugin, AsanSymbolizerPlugIn) + self._plugins.append(plugin) + self._plugin_names.add(plugin.get_name()) + plugin._receive_proxy(self) + + def remove_plugin(self, plugin): + assert isinstance(plugin, AsanSymbolizerPlugIn) + self._plugins.remove(plugin) + self._plugin_names.remove(plugin.get_name()) + logging.debug('Removing plugin %s', plugin.get_name()) + plugin.destroy() + + def has_plugin(self, name): + """ + Returns true iff the plugin name is currently + being managed by AsanSymbolizerPlugInProxy. + """ + return name in self._plugin_names + + def register_cmdline_args(self, parser): + plugins = list(self._plugins) + for plugin in plugins: + plugin.register_cmdline_args(parser) + + def process_cmdline_args(self, pargs): + # Use copy so we can remove items as we iterate. + plugins = list(self._plugins) + for plugin in plugins: + keep = plugin.process_cmdline_args(pargs) + assert isinstance(keep, bool) + if not keep: + self.remove_plugin(plugin) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + for plugin in self._plugins: + plugin.destroy() + # Don't suppress raised exceptions + return False + + def _filter_single_value(self, function_name, input_value): + """ + Helper for filter style plugin functions. + """ + new_value = input_value + for plugin in self._plugins: + result = getattr(plugin, function_name)(new_value) + if result is None: + return None + new_value = result + return new_value + + def filter_binary_path(self, binary_path): + """ + Consult available plugins to filter the path to a binary + to make it suitable for symbolication. -if __name__ == '__main__': - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description='ASan symbolization script', - epilog='Example of use:\n' - 'asan_symbolize.py -c "$HOME/opt/cross/bin/arm-linux-gnueabi-" ' - '-s "$HOME/SymbolFiles" < asan.log') - parser.add_argument('path_to_cut', nargs='*', - help='pattern to be cut from the result file path ') - parser.add_argument('-d','--demangle', action='store_true', - help='demangle function names') - parser.add_argument('-s', metavar='SYSROOT', + Returns `None` if symbolication should not be attempted for this + binary. + """ + return self._filter_single_value('filter_binary_path', binary_path) + + def filter_module_desc(self, module_desc): + """ + Consult available plugins to determine the module + description suitable for symbolication. + + Returns `None` if symbolication should not be attempted for this module. + """ + assert isinstance(module_desc, ModuleDesc) + return self._filter_single_value('filter_module_desc', module_desc) + +class AsanSymbolizerPlugIn(object): + """ + This is the interface the `asan_symbolize.py` code uses to talk + to plugins. + """ + @classmethod + def get_name(cls): + """ + Returns the name of the plugin. + """ + return cls.__name__ + + def _receive_proxy(self, proxy): + assert isinstance(proxy, AsanSymbolizerPlugInProxy) + self.proxy = proxy + + def register_cmdline_args(self, parser): + """ + Hook for registering command line arguments to be + consumed in `process_cmdline_args()`. + + `parser` - Instance of `argparse.ArgumentParser`. + """ + pass + + def process_cmdline_args(self, pargs): + """ + Hook for handling parsed arguments. Implementations + should not modify `pargs`. + + `pargs` - Instance of `argparse.Namespace` containing + parsed command line arguments. + + Return `True` if plug-in should be used, otherwise + return `False`. + """ + return True + + def destroy(self): + """ + Hook called when a plugin is about to be destroyed. + Implementations should free any allocated resources here. + """ + pass + + # Symbolization hooks + def filter_binary_path(self, binary_path): + """ + Given a binary path return a binary path suitable for symbolication. + + Implementations should return `None` if symbolication of this binary + should be skipped. + """ + return binary_path + + def filter_module_desc(self, module_desc): + """ + Given a ModuleDesc object (`module_desc`) return + a ModuleDesc suitable for symbolication. + + Implementations should return `None` if symbolication of this binary + should be skipped. + """ + return module_desc + +class ModuleDesc(object): + def __init__(self, name, arch, start_addr, end_addr, module_path, uuid): + self.name = name + self.arch = arch + self.start_addr = start_addr + self.end_addr = end_addr + # Module path from an ASan report. + self.module_path = module_path + # Module for performing symbolization, by default same as above. + self.module_path_for_symbolization = module_path + self.uuid = uuid + assert self.is_valid() + + def __str__(self): + assert self.is_valid() + return "{name} {arch} {start_addr:#016x}-{end_addr:#016x} {module_path} {uuid}".format( + name=self.name, + arch=self.arch, + start_addr=self.start_addr, + end_addr=self.end_addr, + module_path=self.module_path if self.module_path == self.module_path_for_symbolization else '{} ({})'.format(self.module_path_for_symbolization, self.module_path), + uuid=self.uuid + ) + + def is_valid(self): + if not isinstance(self.name, str): + return False + if not isinstance(self.arch, str): + return False + if not isinstance(self.start_addr, int): + return False + if self.start_addr < 0: + return False + if not isinstance(self.end_addr, int): + return False + if self.end_addr <= self.start_addr: + return False + if not isinstance(self.module_path, str): + return False + if not os.path.isabs(self.module_path): + return False + if not isinstance(self.module_path_for_symbolization, str): + return False + if not os.path.isabs(self.module_path_for_symbolization): + return False + if not isinstance(self.uuid, str): + return False + return True + +class GetUUIDFromBinaryException(Exception): + def __init__(self, msg): + super(GetUUIDFromBinaryException, self).__init__(msg) + +_get_uuid_from_binary_cache = dict() + +def get_uuid_from_binary(path_to_binary, arch=None): + cache_key = (path_to_binary, arch) + cached_value = _get_uuid_from_binary_cache.get(cache_key) + if cached_value: + return cached_value + if not os.path.exists(path_to_binary): + raise GetUUIDFromBinaryException('Binary "{}" does not exist'.format(path_to_binary)) + cmd = [ '/usr/bin/otool', '-l'] + if arch: + cmd.extend(['-arch', arch]) + cmd.append(path_to_binary) + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + # Look for this output: + # cmd LC_UUID + # cmdsize 24 + # uuid 4CA778FE-5BF9-3C45-AE59-7DF01B2BE83F + if isinstance(output, str): + output_str = output + else: + assert isinstance(output, bytes) + output_str = output.decode() + assert isinstance(output_str, str) + lines = output_str.split('\n') + uuid = None + for index, line in enumerate(lines): + stripped_line = line.strip() + if not stripped_line.startswith('cmd LC_UUID'): + continue + uuid_line = lines[index+2].strip() + if not uuid_line.startswith('uuid'): + raise GetUUIDFromBinaryException('Malformed output: "{}"'.format(uuid_line)) + split_uuid_line = uuid_line.split() + uuid = split_uuid_line[1] + break + if uuid is None: + raise GetUUIDFromBinaryException('Failed to retrieve UUID') + else: + # Update cache + _get_uuid_from_binary_cache[cache_key] = uuid + return uuid + +class ModuleMap(object): + def __init__(self): + self._module_name_to_description_map = dict() + + def add_module(self, desc): + assert isinstance(desc, ModuleDesc) + assert desc.name not in self._module_name_to_description_map + self._module_name_to_description_map[desc.name] = desc + + def find_module_by_name(self, name): + return self._module_name_to_description_map.get(name, None) + + def __str__(self): + s = '{} modules:\n'.format(self.num_modules) + for module_desc in sorted(self._module_name_to_description_map.values(), key=lambda v: v.start_addr): + s += str(module_desc) + '\n' + return s + + @property + def num_modules(self): + return len(self._module_name_to_description_map) + + @property + def modules(self): + return set(self._module_name_to_description_map.values()) + + def get_module_path_for_symbolication(self, module_name, proxy): + module_desc = self.find_module_by_name(module_name) + if module_desc is None: + return None + # Allow a plug-in to change the module description to make it + # suitable for symbolication or avoid symbolication altogether. + module_desc = proxy.filter_module_desc(module_desc) + if module_desc is None: + return None + try: + uuid = get_uuid_from_binary(module_desc.module_path_for_symbolization, arch = module_desc.arch) + if uuid != module_desc.uuid: + logging.warning("Detected UUID mismatch {} != {}".format(uuid, module_desc.uuid)) + # UUIDs don't match. Tell client to not symbolize this. + return None + except GetUUIDFromBinaryException as e: + logging.error('Failed to binary from UUID: %s', str(e)) + return None + return module_desc.module_path_for_symbolization + + @staticmethod + def parse_from_file(module_map_path): + if not os.path.exists(module_map_path): + raise Exception('module map "{}" does not exist'.format(module_map_path)) + with open(module_map_path, 'r') as f: + mm = None + # E.g. + # 0x2db4000-0x102ddc000 /path/to (arm64) <0D6BBDE0-FF90-3680-899D-8E6F9528E04C> + hex_regex = lambda name: r'0x(?P<' + name + r'>[0-9a-f]+)' + module_path_regex = r'(?P<path>.+)' + arch_regex = r'\((?P<arch>.+)\)' + uuid_regex = r'<(?P<uuid>[0-9A-Z-]+)>' + line_regex = r'^{}-{}\s+{}\s+{}\s+{}'.format( + hex_regex('start_addr'), + hex_regex('end_addr'), + module_path_regex, + arch_regex, + uuid_regex + ) + matcher = re.compile(line_regex) + line_num = 0 + line = 'dummy' + while line != '': + line = f.readline() + line_num += 1 + if mm is None: + if line.startswith('Process module map:'): + mm = ModuleMap() + continue + if line.startswith('End of module map'): + break + m_obj = matcher.match(line) + if not m_obj: + raise Exception('Failed to parse line {} "{}"'.format(line_num, line)) + arch = m_obj.group('arch') + start_addr = int(m_obj.group('start_addr'), base=16) + end_addr = int(m_obj.group('end_addr'), base=16) + module_path = m_obj.group('path') + uuid = m_obj.group('uuid') + module_desc = ModuleDesc( + name=os.path.basename(module_path), + arch=arch, + start_addr=start_addr, + end_addr=end_addr, + module_path=module_path, + uuid=uuid + ) + mm.add_module(module_desc) + if mm is not None: + logging.debug('Loaded Module map from "{}":\n{}'.format( + f.name, + str(mm)) + ) + return mm + +class SysRootFilterPlugIn(AsanSymbolizerPlugIn): + """ + Simple plug-in to add sys root prefix to all binary paths + used for symbolication. + """ + def __init__(self): + self.sysroot_path = "" + + def register_cmdline_args(self, parser): + parser.add_argument('-s', dest='sys_root', metavar='SYSROOT', help='set path to sysroot for sanitized binaries') - parser.add_argument('-c', metavar='CROSS_COMPILE', - help='set prefix for binutils') - 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 - if args.demangle: - demangle = True - if args.s: - binary_name_filter = sysroot_path_filter - sysroot_path = args.s - if args.c: - binutils_prefix = args.c - if args.logfile: - logfile = args.logfile + + def process_cmdline_args(self, pargs): + if pargs.sys_root is None: + # Not being used so remove ourselves. + return False + self.sysroot_path = pargs.sys_root + return True + + def filter_binary_path(self, path): + return self.sysroot_path + path + +class ModuleMapPlugIn(AsanSymbolizerPlugIn): + def __init__(self): + self._module_map = None + def register_cmdline_args(self, parser): + parser.add_argument('--module-map', + help='Path to text file containing module map' + 'output. See print_module_map ASan option.') + def process_cmdline_args(self, pargs): + if not pargs.module_map: + return False + self._module_map = ModuleMap.parse_from_file(args.module_map) + if self._module_map is None: + msg = 'Failed to find module map' + logging.error(msg) + raise Exception(msg) + return True + def filter_binary_path(self, binary_path): + if os.path.isabs(binary_path): + # This is a binary path so transform into + # a module name + module_name = os.path.basename(binary_path) + else: + module_name = binary_path + return self._module_map.get_module_path_for_symbolication(module_name, self.proxy) + +def add_logging_args(parser): + parser.add_argument('--log-dest', + default=None, + help='Destination path for script logging (default stderr).', + ) + parser.add_argument('--log-level', + choices=['debug', 'info', 'warning', 'error', 'critical'], + default='info', + help='Log level for script (default: %(default)s).' + ) + +def setup_logging(): + # Set up a parser just for parsing the logging arguments. + # This is necessary because logging should be configured before we + # perform the main argument parsing. + parser = argparse.ArgumentParser(add_help=False) + add_logging_args(parser) + pargs, unparsed_args = parser.parse_known_args() + + log_level = getattr(logging, pargs.log_level.upper()) + if log_level == logging.DEBUG: + log_format = '%(levelname)s: [%(funcName)s() %(filename)s:%(lineno)d] %(message)s' 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() + log_format = '%(levelname)s: %(message)s' + basic_config = { + 'level': log_level, + 'format': log_format + } + log_dest = pargs.log_dest + if log_dest: + basic_config['filename'] = log_dest + logging.basicConfig(**basic_config) + logging.debug('Logging level set to "{}" and directing output to "{}"'.format( + pargs.log_level, + 'stderr' if log_dest is None else log_dest) + ) + return unparsed_args + +def add_load_plugin_args(parser): + parser.add_argument('-p', '--plugins', + help='Load plug-in', nargs='+', default=[]) + +def setup_plugins(plugin_proxy, args): + parser = argparse.ArgumentParser(add_help=False) + add_load_plugin_args(parser) + pargs , unparsed_args = parser.parse_known_args() + for plugin_path in pargs.plugins: + plugin_proxy.load_plugin_from_file(plugin_path) + # Add built-in plugins. + plugin_proxy.add_plugin(ModuleMapPlugIn()) + plugin_proxy.add_plugin(SysRootFilterPlugIn()) + return unparsed_args + +if __name__ == '__main__': + remaining_args = setup_logging() + with AsanSymbolizerPlugInProxy() as plugin_proxy: + remaining_args = setup_plugins(plugin_proxy, remaining_args) + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='ASan symbolization script', + epilog=__doc__) + parser.add_argument('path_to_cut', nargs='*', + help='pattern to be cut from the result file path ') + parser.add_argument('-d','--demangle', action='store_true', + help='demangle function names') + parser.add_argument('-c', metavar='CROSS_COMPILE', + help='set prefix for binutils') + 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') + # Add logging arguments so that `--help` shows them. + add_logging_args(parser) + # Add load plugin arguments so that `--help` shows them. + add_load_plugin_args(parser) + plugin_proxy.register_cmdline_args(parser) + args = parser.parse_args(remaining_args) + plugin_proxy.process_cmdline_args(args) + if args.path_to_cut: + fix_filename_patterns = args.path_to_cut + if args.demangle: + demangle = True + if args.c: + binutils_prefix = args.c + if args.logfile: + 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(plugin_proxy) + loop.process_logfile() diff --git a/lib/asan/tests/CMakeLists.txt b/lib/asan/tests/CMakeLists.txt index 9e640d1d8..d7116f7ff 100644 --- a/lib/asan/tests/CMakeLists.txt +++ b/lib/asan/tests/CMakeLists.txt @@ -74,10 +74,6 @@ set(ASAN_UNITTEST_INSTRUMENTED_CFLAGS -fsanitize=address "-fsanitize-blacklist=${ASAN_BLACKLIST_FILE}" ) -if(CAN_TARGET_x86_64 OR CAN_TARGET_i386) - list(APPEND ASAN_UNITTEST_INSTRUMENTED_CFLAGS -mllvm -asan-instrument-assembly) -endif() - if(NOT MSVC) list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS --driver-mode=g++) endif() @@ -142,7 +138,6 @@ set(ASAN_NOINST_TEST_SOURCES set(ASAN_INST_TEST_SOURCES ${COMPILER_RT_GTEST_SOURCE} - asan_asm_test.cc asan_globals_test.cc asan_interface_test.cc asan_internal_interface_test.cc diff --git a/lib/asan/tests/asan_asm_test.cc b/lib/asan/tests/asan_asm_test.cc deleted file mode 100644 index 91f8aacd6..000000000 --- a/lib/asan/tests/asan_asm_test.cc +++ /dev/null @@ -1,274 +0,0 @@ -//===-- asan_asm_test.cc --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -#if defined(__linux__) && \ - (!defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3) - -// Assembly instrumentation is broken on x86 Android (x86 + PIC + shared runtime -// library). See https://github.com/google/sanitizers/issues/353 -#if defined(__x86_64__) || \ - (defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__)) - -#include <emmintrin.h> - -namespace { - -template<typename T> void asm_write(T *ptr, T val); -template<typename T> T asm_read(T *ptr); -template<typename T> void asm_rep_movs(T *dst, T *src, size_t n); - -} // End of anonymous namespace - -#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#if defined(__x86_64__) - -namespace { - -#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg) \ -template<> void asm_write<Type>(Type *ptr, Type val) { \ - __asm__( \ - Mov " %[val], (%[ptr]) \n\t" \ - : \ - : [ptr] "r" (ptr), [val] Reg (val) \ - : "memory" \ - ); \ -} - -#define DECLARE_ASM_READ(Type, Size, Mov, Reg) \ -template<> Type asm_read<Type>(Type *ptr) { \ - Type res; \ - __asm__( \ - Mov " (%[ptr]), %[res] \n\t" \ - : [res] Reg (res) \ - : [ptr] "r" (ptr) \ - : "memory" \ - ); \ - return res; \ -} - -#define DECLARE_ASM_REP_MOVS(Type, Movs) \ - template <> \ - void asm_rep_movs<Type>(Type * dst, Type * src, size_t size) { \ - __asm__("rep " Movs " \n\t" \ - : "+D"(dst), "+S"(src), "+c"(size) \ - : \ - : "memory"); \ - } - -DECLARE_ASM_WRITE(U8, "8", "movq", "r"); -DECLARE_ASM_READ(U8, "8", "movq", "=r"); -DECLARE_ASM_REP_MOVS(U8, "movsq"); - -} // End of anonymous namespace - -#endif // defined(__x86_64__) - -#if defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__) - -namespace { - -#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg) \ -template<> void asm_write<Type>(Type *ptr, Type val) { \ - __asm__( \ - Mov " %[val], (%[ptr]) \n\t" \ - : \ - : [ptr] "r" (ptr), [val] Reg (val) \ - : "memory" \ - ); \ -} - -#define DECLARE_ASM_READ(Type, Size, Mov, Reg) \ -template<> Type asm_read<Type>(Type *ptr) { \ - Type res; \ - __asm__( \ - Mov " (%[ptr]), %[res] \n\t" \ - : [res] Reg (res) \ - : [ptr] "r" (ptr) \ - : "memory" \ - ); \ - return res; \ -} - -#define DECLARE_ASM_REP_MOVS(Type, Movs) \ - template <> \ - void asm_rep_movs<Type>(Type * dst, Type * src, size_t size) { \ - __asm__("rep " Movs " \n\t" \ - : "+D"(dst), "+S"(src), "+c"(size) \ - : \ - : "memory"); \ - } - -} // End of anonymous namespace - -#endif // defined(__i386__) && defined(__SSE2__) - -#if defined(__x86_64__) || \ - (defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__)) - -namespace { - -DECLARE_ASM_WRITE(U1, "1", "movb", "r"); -DECLARE_ASM_WRITE(U2, "2", "movw", "r"); -DECLARE_ASM_WRITE(U4, "4", "movl", "r"); -DECLARE_ASM_WRITE(__m128i, "16", "movaps", "x"); - -DECLARE_ASM_READ(U1, "1", "movb", "=r"); -DECLARE_ASM_READ(U2, "2", "movw", "=r"); -DECLARE_ASM_READ(U4, "4", "movl", "=r"); -DECLARE_ASM_READ(__m128i, "16", "movaps", "=x"); - -DECLARE_ASM_REP_MOVS(U1, "movsb"); -DECLARE_ASM_REP_MOVS(U2, "movsw"); -DECLARE_ASM_REP_MOVS(U4, "movsl"); - -template<typename T> void TestAsmWrite(const char *DeathPattern) { - T *buf = new T; - EXPECT_DEATH(asm_write(&buf[1], static_cast<T>(0)), DeathPattern); - T var = 0x12; - asm_write(&var, static_cast<T>(0x21)); - ASSERT_EQ(static_cast<T>(0x21), var); - delete buf; -} - -template<> void TestAsmWrite<__m128i>(const char *DeathPattern) { - char *buf = new char[16]; - char *p = buf + 16; - if (((uintptr_t) p % 16) != 0) - p = buf + 8; - assert(((uintptr_t) p % 16) == 0); - __m128i val = _mm_set1_epi16(0x1234); - EXPECT_DEATH(asm_write<__m128i>((__m128i*) p, val), DeathPattern); - __m128i var = _mm_set1_epi16(0x4321); - asm_write(&var, val); - ASSERT_EQ(0x1234, _mm_extract_epi16(var, 0)); - delete [] buf; -} - -template<typename T> void TestAsmRead(const char *DeathPattern) { - T *buf = new T; - EXPECT_DEATH(asm_read(&buf[1]), DeathPattern); - T var = 0x12; - ASSERT_EQ(static_cast<T>(0x12), asm_read(&var)); - delete buf; -} - -template<> void TestAsmRead<__m128i>(const char *DeathPattern) { - char *buf = new char[16]; - char *p = buf + 16; - if (((uintptr_t) p % 16) != 0) - p = buf + 8; - assert(((uintptr_t) p % 16) == 0); - EXPECT_DEATH(asm_read<__m128i>((__m128i*) p), DeathPattern); - __m128i val = _mm_set1_epi16(0x1234); - ASSERT_EQ(0x1234, _mm_extract_epi16(asm_read(&val), 0)); - delete [] buf; -} - -U4 AsmLoad(U4 *a) { - U4 r; - __asm__("movl (%[a]), %[r] \n\t" : [r] "=r" (r) : [a] "r" (a) : "memory"); - return r; -} - -void AsmStore(U4 r, U4 *a) { - __asm__("movl %[r], (%[a]) \n\t" : : [a] "r" (a), [r] "r" (r) : "memory"); -} - -template <typename T> -void TestAsmRepMovs(const char *DeathPatternRead, - const char *DeathPatternWrite) { - T src_good[4] = { 0x0, 0x1, 0x2, 0x3 }; - T dst_good[4] = {}; - asm_rep_movs(dst_good, src_good, 4); - ASSERT_EQ(static_cast<T>(0x0), dst_good[0]); - ASSERT_EQ(static_cast<T>(0x1), dst_good[1]); - ASSERT_EQ(static_cast<T>(0x2), dst_good[2]); - ASSERT_EQ(static_cast<T>(0x3), dst_good[3]); - - T dst_bad[3]; - EXPECT_DEATH(asm_rep_movs(dst_bad, src_good, 4), DeathPatternWrite); - - T src_bad[3] = { 0x0, 0x1, 0x2 }; - EXPECT_DEATH(asm_rep_movs(dst_good, src_bad, 4), DeathPatternRead); - - T* dp = dst_bad + 4; - T* sp = src_bad + 4; - asm_rep_movs(dp, sp, 0); -} - -} // End of anonymous namespace - -TEST(AddressSanitizer, asm_load_store) { - U4* buf = new U4[2]; - EXPECT_DEATH(AsmLoad(&buf[3]), "READ of size 4"); - EXPECT_DEATH(AsmStore(0x1234, &buf[3]), "WRITE of size 4"); - delete [] buf; -} - -TEST(AddressSanitizer, asm_rw) { - TestAsmWrite<U1>("WRITE of size 1"); - TestAsmWrite<U2>("WRITE of size 2"); - TestAsmWrite<U4>("WRITE of size 4"); -#if defined(__x86_64__) - TestAsmWrite<U8>("WRITE of size 8"); -#endif // defined(__x86_64__) - TestAsmWrite<__m128i>("WRITE of size 16"); - - TestAsmRead<U1>("READ of size 1"); - TestAsmRead<U2>("READ of size 2"); - TestAsmRead<U4>("READ of size 4"); -#if defined(__x86_64__) - TestAsmRead<U8>("READ of size 8"); -#endif // defined(__x86_64__) - TestAsmRead<__m128i>("READ of size 16"); -} - -TEST(AddressSanitizer, asm_flags) { - long magic = 0x1234; - long r = 0x0; - -#if defined(__x86_64__) && !defined(__ILP32__) - __asm__("xorq %%rax, %%rax \n\t" - "movq (%[p]), %%rax \n\t" - "sete %%al \n\t" - "movzbq %%al, %[r] \n\t" - : [r] "=r"(r) - : [p] "r"(&magic) - : "rax", "memory"); -#else - __asm__("xorl %%eax, %%eax \n\t" - "movl (%[p]), %%eax \n\t" - "sete %%al \n\t" - "movzbl %%al, %[r] \n\t" - : [r] "=r"(r) - : [p] "r"(&magic) - : "eax", "memory"); -#endif // defined(__x86_64__) && !defined(__ILP32__) - - ASSERT_EQ(0x1, r); -} - -TEST(AddressSanitizer, asm_rep_movs) { - TestAsmRepMovs<U1>("READ of size 1", "WRITE of size 1"); - TestAsmRepMovs<U2>("READ of size 2", "WRITE of size 2"); - TestAsmRepMovs<U4>("READ of size 4", "WRITE of size 4"); -#if defined(__x86_64__) - TestAsmRepMovs<U8>("READ of size 8", "WRITE of size 8"); -#endif // defined(__x86_64__) -} - -#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#endif // defined(__linux__) diff --git a/lib/asan/tests/asan_benchmarks_test.cc b/lib/asan/tests/asan_benchmarks_test.cc index fc522de47..9a0ed72d4 100644 --- a/lib/asan/tests/asan_benchmarks_test.cc +++ b/lib/asan/tests/asan_benchmarks_test.cc @@ -1,9 +1,8 @@ //===-- asan_benchmarks_test.cc ----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_fake_stack_test.cc b/lib/asan/tests/asan_fake_stack_test.cc index 516142f0c..13beea8f2 100644 --- a/lib/asan/tests/asan_fake_stack_test.cc +++ b/lib/asan/tests/asan_fake_stack_test.cc @@ -1,9 +1,8 @@ //===-- asan_fake_stack_test.cc -------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_globals_test.cc b/lib/asan/tests/asan_globals_test.cc index 5042ef073..b852b6b5e 100644 --- a/lib/asan/tests/asan_globals_test.cc +++ b/lib/asan/tests/asan_globals_test.cc @@ -1,9 +1,8 @@ //===-- asan_globals_test.cc ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_interface_test.cc b/lib/asan/tests/asan_interface_test.cc index b5c8303cb..8cbe469bf 100644 --- a/lib/asan/tests/asan_interface_test.cc +++ b/lib/asan/tests/asan_interface_test.cc @@ -1,9 +1,8 @@ //===-- asan_interface_test.cc --------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_internal_interface_test.cc b/lib/asan/tests/asan_internal_interface_test.cc index e247bb429..2d3b9c1f5 100644 --- a/lib/asan/tests/asan_internal_interface_test.cc +++ b/lib/asan/tests/asan_internal_interface_test.cc @@ -1,9 +1,8 @@ //===-- asan_internal_interface_test.cc -----------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_mac_test.cc b/lib/asan/tests/asan_mac_test.cc index dfa6d7596..14e105252 100644 --- a/lib/asan/tests/asan_mac_test.cc +++ b/lib/asan/tests/asan_mac_test.cc @@ -1,9 +1,8 @@ //===-- asan_test_mac.cc --------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_mem_test.cc b/lib/asan/tests/asan_mem_test.cc index c32088684..1339c1271 100644 --- a/lib/asan/tests/asan_mem_test.cc +++ b/lib/asan/tests/asan_mem_test.cc @@ -1,16 +1,19 @@ //===-- asan_mem_test.cc --------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file is a part of AddressSanitizer, an address sanity checker. // //===----------------------------------------------------------------------===// +#include <string.h> #include "asan_test_utils.h" +#if defined(_GNU_SOURCE) +#include <strings.h> // for bcmp +#endif #include <vector> template<typename T> @@ -206,37 +209,43 @@ TEST(AddressSanitizer, MemMoveOOBTest) { MemTransferOOBTestTemplate<int, MemMoveWrapper>(1024); } - -TEST(AddressSanitizer, MemCmpOOBTest) { +template <int (*cmpfn)(const void *, const void *, size_t)> +void CmpOOBTestCommon() { size_t size = Ident(100); char *s1 = MallocAndMemsetString(size); char *s2 = MallocAndMemsetString(size); - // Normal memcmp calls. - Ident(memcmp(s1, s2, size)); - Ident(memcmp(s1 + size - 1, s2 + size - 1, 1)); - Ident(memcmp(s1 - 1, s2 - 1, 0)); + // Normal cmpfn calls. + Ident(cmpfn(s1, s2, size)); + Ident(cmpfn(s1 + size - 1, s2 + size - 1, 1)); + Ident(cmpfn(s1 - 1, s2 - 1, 0)); // One of arguments points to not allocated memory. - EXPECT_DEATH(Ident(memcmp)(s1 - 1, s2, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(memcmp)(s1, s2 - 1, 1), LeftOOBReadMessage(1)); - EXPECT_DEATH(Ident(memcmp)(s1 + size, s2, 1), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(memcmp)(s1, s2 + size, 1), RightOOBReadMessage(0)); + EXPECT_DEATH(Ident(cmpfn)(s1 - 1, s2, 1), LeftOOBReadMessage(1)); + EXPECT_DEATH(Ident(cmpfn)(s1, s2 - 1, 1), LeftOOBReadMessage(1)); + EXPECT_DEATH(Ident(cmpfn)(s1 + size, s2, 1), RightOOBReadMessage(0)); + EXPECT_DEATH(Ident(cmpfn)(s1, s2 + size, 1), RightOOBReadMessage(0)); // Hit unallocated memory and die. - EXPECT_DEATH(Ident(memcmp)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0)); - EXPECT_DEATH(Ident(memcmp)(s1 + size - 1, s2, 2), RightOOBReadMessage(0)); + EXPECT_DEATH(Ident(cmpfn)(s1 + 1, s2 + 1, size), RightOOBReadMessage(0)); + EXPECT_DEATH(Ident(cmpfn)(s1 + size - 1, s2, 2), RightOOBReadMessage(0)); // Zero bytes are not terminators and don't prevent from OOB. s1[size - 1] = '\0'; s2[size - 1] = '\0'; - EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0)); + EXPECT_DEATH(Ident(cmpfn)(s1, s2, size + 1), RightOOBReadMessage(0)); // Even if the buffers differ in the first byte, we still assume that - // memcmp may access the whole buffer and thus reporting the overflow here: + // cmpfn may access the whole buffer and thus reporting the overflow here: s1[0] = 1; s2[0] = 123; - EXPECT_DEATH(Ident(memcmp)(s1, s2, size + 1), RightOOBReadMessage(0)); + EXPECT_DEATH(Ident(cmpfn)(s1, s2, size + 1), RightOOBReadMessage(0)); free(s1); free(s2); } +TEST(AddressSanitizer, MemCmpOOBTest) { CmpOOBTestCommon<memcmp>(); } - +TEST(AddressSanitizer, BCmpOOBTest) { +#if (defined(__linux__) && !defined(__ANDROID__) && defined(_GNU_SOURCE)) || \ + defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + CmpOOBTestCommon<bcmp>(); +#endif +} diff --git a/lib/asan/tests/asan_noinst_test.cc b/lib/asan/tests/asan_noinst_test.cc index 3e366842c..8460abf97 100644 --- a/lib/asan/tests/asan_noinst_test.cc +++ b/lib/asan/tests/asan_noinst_test.cc @@ -1,9 +1,8 @@ //===-- asan_noinst_test.cc -----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_oob_test.cc b/lib/asan/tests/asan_oob_test.cc index 0c6bea285..f023ca24b 100644 --- a/lib/asan/tests/asan_oob_test.cc +++ b/lib/asan/tests/asan_oob_test.cc @@ -1,9 +1,8 @@ //===-- asan_oob_test.cc --------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_str_test.cc b/lib/asan/tests/asan_str_test.cc index 5cf4e05c8..8ed451408 100644 --- a/lib/asan/tests/asan_str_test.cc +++ b/lib/asan/tests/asan_str_test.cc @@ -1,9 +1,8 @@ //=-- asan_str_test.cc ----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc index 464e99f61..2795b71cd 100644 --- a/lib/asan/tests/asan_test.cc +++ b/lib/asan/tests/asan_test.cc @@ -1,9 +1,8 @@ //===-- asan_test.cc ------------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_test_config.h b/lib/asan/tests/asan_test_config.h index 8493f41ef..a0fadf8af 100644 --- a/lib/asan/tests/asan_test_config.h +++ b/lib/asan/tests/asan_test_config.h @@ -1,9 +1,8 @@ //===-- asan_test_config.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_test_main.cc b/lib/asan/tests/asan_test_main.cc index 0c1b93c7f..1f94ec287 100644 --- a/lib/asan/tests/asan_test_main.cc +++ b/lib/asan/tests/asan_test_main.cc @@ -1,9 +1,8 @@ //===-- asan_test_main.cc -------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/asan/tests/asan_test_utils.h b/lib/asan/tests/asan_test_utils.h index d7b6f82e2..2ab44855a 100644 --- a/lib/asan/tests/asan_test_utils.h +++ b/lib/asan/tests/asan_test_utils.h @@ -1,9 +1,8 @@ //===-- asan_test_utils.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // |