re PR sanitizer/60038 (AddressSanitizer CHECK failed ... "((*tls_addr + *tls_size)) <= ((*stk_addr + *stk_size))" on CentOS 5.10)

PR sanitizer/60038
	* sanitizer_common/sanitizer_linux_libcdep.cc: Include
	sanitizer_atomic.h and unistd.h.
	(kThreadDescriptorSize): Made static, remove initializer and const,
	change type to atomic_uintptr_t.
	(ThreadDescriptorSize): Use confstr(_CS_GNU_LIBC_VERSION, ...) to
	query glibc version, compute kThreadDescriptorSize depending on
	glibc version minor number.
	(GetThreadStackAndTls): Use ThreadDescriptorSize() instead of
	kThreadDescriptorSize directly.

From-SVN: r207452
This commit is contained in:
Jakub Jelinek 2014-02-04 08:37:44 +01:00 committed by Jakub Jelinek
parent 39960d1cfa
commit 5ab39ec3b0
2 changed files with 49 additions and 9 deletions

View file

@ -1,3 +1,16 @@
2014-02-04 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/60038
* sanitizer_common/sanitizer_linux_libcdep.cc: Include
sanitizer_atomic.h and unistd.h.
(kThreadDescriptorSize): Made static, remove initializer and const,
change type to atomic_uintptr_t.
(ThreadDescriptorSize): Use confstr(_CS_GNU_LIBC_VERSION, ...) to
query glibc version, compute kThreadDescriptorSize depending on
glibc version minor number.
(GetThreadStackAndTls): Use ThreadDescriptorSize() instead of
kThreadDescriptorSize directly.
2014-01-23 Yury Gribov <y.gribov@samsung.com>
Jakub Jelinek <jakub@redhat.com>

View file

@ -19,6 +19,7 @@
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
#include "sanitizer_atomic.h"
#include <dlfcn.h>
#include <pthread.h>
@ -29,6 +30,7 @@
#if !SANITIZER_ANDROID
#include <elf.h>
#include <link.h>
#include <unistd.h>
#endif
// This function is defined elsewhere if we intercepted pthread_attr_getstack.
@ -205,16 +207,41 @@ uptr GetTlsSize() {
#if defined(__x86_64__) || defined(__i386__)
// sizeof(struct thread) from glibc.
// There has been a report of this being different on glibc 2.11 and 2.13. We
// don't know when this change happened, so 2.14 is a conservative estimate.
#if __GLIBC_PREREQ(2, 14)
const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1216, 2304);
#else
const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1168, 2304);
#endif
static atomic_uintptr_t kThreadDescriptorSize;
uptr ThreadDescriptorSize() {
return kThreadDescriptorSize;
char buf[64];
uptr val = atomic_load(&kThreadDescriptorSize, memory_order_relaxed);
if (val)
return val;
#ifdef _CS_GNU_LIBC_VERSION
uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
if (len < sizeof(buf) && internal_strncmp(buf, "glibc 2.", 8) == 0) {
char *end;
int minor = internal_simple_strtoll(buf + 8, &end, 10);
if (end != buf + 8 && (*end == '\0' || *end == '.')) {
/* sizeof(struct thread) values from various glibc versions. */
if (minor <= 3)
val = FIRST_32_SECOND_64(1104, 1696);
else if (minor == 4)
val = FIRST_32_SECOND_64(1120, 1728);
else if (minor == 5)
val = FIRST_32_SECOND_64(1136, 1728);
else if (minor <= 9)
val = FIRST_32_SECOND_64(1136, 1712);
else if (minor == 10)
val = FIRST_32_SECOND_64(1168, 1776);
else if (minor <= 12)
val = FIRST_32_SECOND_64(1168, 2288);
else
val = FIRST_32_SECOND_64(1216, 2304);
}
if (val)
atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
return val;
}
#endif
return 0;
}
// The offset at which pointer to self is located in the thread descriptor.
@ -242,7 +269,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
*tls_addr = ThreadSelf();
*tls_size = GetTlsSize();
*tls_addr -= *tls_size;
*tls_addr += kThreadDescriptorSize;
*tls_addr += ThreadDescriptorSize();
#else
*tls_addr = 0;
*tls_size = 0;