From 35e1c97297c747c6e07b224629626ee5a3531181 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Fri, 20 Jul 2018 18:17:42 +0000 Subject: [PATCH] extra/compiler-rt to 6.0.1-2 --- extra/compiler-rt/PKGBUILD | 11 +- extra/compiler-rt/glibc-2.27.patch | 195 +++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 extra/compiler-rt/glibc-2.27.patch diff --git a/extra/compiler-rt/PKGBUILD b/extra/compiler-rt/PKGBUILD index d388add24..1f26da434 100644 --- a/extra/compiler-rt/PKGBUILD +++ b/extra/compiler-rt/PKGBUILD @@ -7,7 +7,7 @@ pkgname=compiler-rt pkgver=6.0.1 -pkgrel=1 +pkgrel=2 pkgdesc="Compiler runtime libraries for clang" arch=('x86_64') url="https://compiler-rt.llvm.org/" @@ -17,15 +17,20 @@ makedepends=('llvm' 'cmake' 'ninja' 'python') # Build 32-bit compiler-rt libraries on x86_64 (FS#41911) makedepends_x86_64=('lib32-gcc-libs') options=('staticlibs') -source=(https://releases.llvm.org/$pkgver/$pkgname-$pkgver.src.tar.xz{,.sig}) +source=(https://releases.llvm.org/$pkgver/$pkgname-$pkgver.src.tar.xz{,.sig} + glibc-2.27.patch) sha256sums=('f4cd1e15e7d5cb708f9931d4844524e4904867240c306b06a4287b22ac1c99b9' - 'SKIP') + 'SKIP' + 'acfba6a38cf3b40dc4f2edca2f1d487e1b287db71d6a6ca9f27657c5f90f876b') validpgpkeys+=('B6C8F98282B944E3B0D5C2530FC3042E345AD05D') # Hans Wennborg validpgpkeys+=('474E22316ABF4785A88C6E8EA2C794A986419D8A') # Tom Stellard prepare() { cd "$srcdir/$pkgname-$pkgver.src" mkdir build + + # Fixes for glibc 2.27 + patch -Np1 -i ../glibc-2.27.patch } build() { diff --git a/extra/compiler-rt/glibc-2.27.patch b/extra/compiler-rt/glibc-2.27.patch new file mode 100644 index 000000000..1a995fd58 --- /dev/null +++ b/extra/compiler-rt/glibc-2.27.patch @@ -0,0 +1,195 @@ +From 80dc25a213216b31f981b80f74c94a757eb3b8c1 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Sun, 10 Jun 2018 11:17:47 +0000 +Subject: [PATCH 1/2] [ASAN] Fix crash on i?86-linux (32-bit) against glibc + 2.27 and later + +Summary: +Running sanitized 32-bit x86 programs on glibc 2.27 crashes at startup, with: + + ERROR: AddressSanitizer: SEGV on unknown address 0xf7a8a250 (pc 0xf7f807f4 bp 0xff969fc8 sp 0xff969f7c T16777215) + The signal is caused by a WRITE memory access. + #0 0xf7f807f3 in _dl_get_tls_static_info (/lib/ld-linux.so.2+0x127f3) + #1 0xf7a92599 (/lib/libasan.so.5+0x112599) + #2 0xf7a80737 (/lib/libasan.so.5+0x100737) + #3 0xf7f7e14f in _dl_init (/lib/ld-linux.so.2+0x1014f) + #4 0xf7f6eb49 (/lib/ld-linux.so.2+0xb49) + +The problem is that glibc changed the calling convention for the GLIBC_PRIVATE +symbol that sanitizer uses (even when it should not, GLIBC_PRIVATE is exactly +for symbols that can change at any time, be removed etc.), see +https://sourceware.org/ml/libc-alpha/2017-08/msg00497.html + +Fixes https://github.com/google/sanitizers/issues/954 + +Patch By: Jakub Jelinek + +Reviewed By: vitalybuka, Lekensteyn + +Differential Revison: https://reviews.llvm.org/D44623 + +git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@334363 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + .../sanitizer_linux_libcdep.cc | 45 ++++++++++++++++--- + 1 file changed, 38 insertions(+), 7 deletions(-) + +diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc +index 56fdfc870..5d543622f 100644 +--- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc ++++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc +@@ -178,24 +178,55 @@ bool SanitizerGetThreadName(char *name, int max_len) { + static uptr g_tls_size; + + #ifdef __i386__ ++# ifndef __GLIBC_PREREQ ++# define CHECK_GET_TLS_STATIC_INFO_VERSION 1 ++# else ++# define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27)) ++# endif ++#else ++# define CHECK_GET_TLS_STATIC_INFO_VERSION 0 ++#endif ++ ++#if CHECK_GET_TLS_STATIC_INFO_VERSION + # define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall)) + #else + # define DL_INTERNAL_FUNCTION + #endif + ++namespace { ++struct GetTlsStaticInfoCall { ++ typedef void (*get_tls_func)(size_t*, size_t*); ++}; ++struct GetTlsStaticInfoRegparmCall { ++ typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION; ++}; ++ ++template ++void CallGetTls(void* ptr, size_t* size, size_t* align) { ++ typename T::get_tls_func get_tls; ++ CHECK_EQ(sizeof(get_tls), sizeof(ptr)); ++ internal_memcpy(&get_tls, &ptr, sizeof(ptr)); ++ CHECK_NE(get_tls, 0); ++ get_tls(size, align); ++} ++} // namespace ++ + void InitTlsSize() { + // all current supported platforms have 16 bytes stack alignment + const size_t kStackAlign = 16; +- typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION; +- get_tls_func get_tls; + void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); +- CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr)); +- internal_memcpy(&get_tls, &get_tls_static_info_ptr, +- sizeof(get_tls_static_info_ptr)); +- CHECK_NE(get_tls, 0); + size_t tls_size = 0; + size_t tls_align = 0; +- get_tls(&tls_size, &tls_align); ++ // On i?86, _dl_get_tls_static_info used to be internal_function, i.e. ++ // __attribute__((regparm(3), stdcall)) before glibc 2.27 and is normal ++ // function in 2.27 and later. ++ if (CHECK_GET_TLS_STATIC_INFO_VERSION && ++ !dlvsym(RTLD_NEXT, "glob", "GLIBC_2.27")) ++ CallGetTls(get_tls_static_info_ptr, ++ &tls_size, &tls_align); ++ else ++ CallGetTls(get_tls_static_info_ptr, ++ &tls_size, &tls_align); + if (tls_align < kStackAlign) + tls_align = kStackAlign; + g_tls_size = RoundUpTo(tls_size, tls_align); + +From 05ecff3cb7a0898de0d709a495f229ab611f3ca4 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Thu, 14 Jun 2018 10:42:54 +0000 +Subject: [PATCH 2/2] [ASAN] fix startup crash in dlsym for long paths since + glibc 2.27 + +Summary: +Error messages for dlsym used to be stored on the stack, but since +commit 2449ae7b ("ld.so: Introduce struct dl_exception") in glibc 2.27 +these are now stored on the heap (and thus use the dlsym alloc pool). + +Messages look like "undefined symbol: __isoc99_printf\0/path/to/a.out". +With many missing library functions and long object paths, the pool is +quickly exhausted. Implement a simple mechanism to return freed memory +to the pool (clear it in case it is used for calloc). + +Fixes https://github.com/google/sanitizers/issues/957 + +Reviewed By: vitalybuka + +Differential Revision: https://reviews.llvm.org/D47995 + +git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@334703 91177308-0d34-0410-b5e6-96231b3b80d8 +--- + lib/asan/asan_malloc_linux.cc | 19 ++++++++++++++++++- + test/asan/TestCases/long-object-path.cc | 7 +++++++ + 2 files changed, 25 insertions(+), 1 deletion(-) + create mode 100644 test/asan/TestCases/long-object-path.cc + +diff --git a/lib/asan/asan_malloc_linux.cc b/lib/asan/asan_malloc_linux.cc +index 6697ff876..af05af9d6 100644 +--- a/lib/asan/asan_malloc_linux.cc ++++ b/lib/asan/asan_malloc_linux.cc +@@ -28,6 +28,7 @@ + using namespace __asan; // NOLINT + + static uptr allocated_for_dlsym; ++static uptr last_dlsym_alloc_size_in_words; + static const uptr kDlsymAllocPoolSize = 1024; + static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize]; + +@@ -39,11 +40,25 @@ static INLINE bool IsInDlsymAllocPool(const void *ptr) { + static void *AllocateFromLocalPool(uptr size_in_bytes) { + uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize; + void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym]; ++ last_dlsym_alloc_size_in_words = size_in_words; + allocated_for_dlsym += size_in_words; + CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize); + return mem; + } + ++static void DeallocateFromLocalPool(const void *ptr) { ++ // Hack: since glibc 2.27, dlsym longer use stack-allocated memory to store ++ // error messages and instead use malloc followed by free. To avoid pool ++ // exhaustion due to long object filenames, handle that special case here. ++ uptr prev_offset = allocated_for_dlsym - last_dlsym_alloc_size_in_words; ++ void *prev_mem = (void*)&alloc_memory_for_dlsym[prev_offset]; ++ if (prev_mem == ptr) { ++ REAL(memset)(prev_mem, 0, last_dlsym_alloc_size_in_words * kWordSize); ++ allocated_for_dlsym = prev_offset; ++ last_dlsym_alloc_size_in_words = 0; ++ } ++} ++ + static INLINE bool MaybeInDlsym() { + // Fuchsia doesn't use dlsym-based interceptors. + return !SANITIZER_FUCHSIA && asan_init_is_running; +@@ -66,8 +81,10 @@ static void *ReallocFromLocalPool(void *ptr, uptr size) { + + INTERCEPTOR(void, free, void *ptr) { + GET_STACK_TRACE_FREE; +- if (UNLIKELY(IsInDlsymAllocPool(ptr))) ++ if (UNLIKELY(IsInDlsymAllocPool(ptr))) { ++ DeallocateFromLocalPool(ptr); + return; ++ } + asan_free(ptr, &stack, FROM_MALLOC); + } + +diff --git a/test/asan/TestCases/long-object-path.cc b/test/asan/TestCases/long-object-path.cc +new file mode 100644 +index 000000000..592b0abb0 +--- /dev/null ++++ b/test/asan/TestCases/long-object-path.cc +@@ -0,0 +1,7 @@ ++// RUN: mkdir -p %T/a-long-directory-name-to-test-allocations-for-exceptions-in-_dl_lookup_symbol_x-since-glibc-2.27 ++// RUN: %clangxx_asan -g %s -o %T/long-object-path ++// RUN: %run %T/a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../long-object-path ++ ++int main(void) { ++ return 0; ++}