Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.

Commit 46081ed

Browse files
committed
[sanitizer] Handle TLS sizes for glibc < 2.13; As discussed in http://gcc.gnu.org/PR60038, the hardcoded sizeof(struct thread); patch by Jakub Jelinek
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@200733 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent b69ac7d commit 46081ed

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

lib/sanitizer_common/sanitizer_linux_libcdep.cc

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "sanitizer_placement_new.h"
2222
#include "sanitizer_procmaps.h"
2323
#include "sanitizer_stacktrace.h"
24+
#include "sanitizer_atomic.h"
2425

2526
#include <dlfcn.h>
2627
#include <pthread.h>
@@ -32,6 +33,7 @@
3233
#if !SANITIZER_ANDROID
3334
#include <elf.h>
3435
#include <link.h>
36+
#include <unistd.h>
3537
#endif
3638

3739
#ifndef SANITIZER_GO
@@ -226,16 +228,41 @@ uptr GetTlsSize() {
226228

227229
#if defined(__x86_64__) || defined(__i386__)
228230
// sizeof(struct thread) from glibc.
229-
// There has been a report of this being different on glibc 2.11 and 2.13. We
230-
// don't know when this change happened, so 2.14 is a conservative estimate.
231-
#if __GLIBC_PREREQ(2, 14)
232-
const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1216, 2304);
233-
#else
234-
const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1168, 2304);
235-
#endif
231+
static atomic_uintptr_t kThreadDescriptorSize;
236232

237233
uptr ThreadDescriptorSize() {
238-
return kThreadDescriptorSize;
234+
char buf[64];
235+
uptr val = atomic_load(&kThreadDescriptorSize, memory_order_relaxed);
236+
if (val)
237+
return val;
238+
#ifdef _CS_GNU_LIBC_VERSION
239+
uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
240+
if (len < sizeof(buf) && internal_strncmp(buf, "glibc 2.", 8) == 0) {
241+
char *end;
242+
int minor = internal_simple_strtoll(buf + 8, &end, 10);
243+
if (end != buf + 8 && (*end == '\0' || *end == '.')) {
244+
/* sizeof(struct thread) values from various glibc versions. */
245+
if (minor <= 3)
246+
val = FIRST_32_SECOND_64(1104, 1696);
247+
else if (minor == 4)
248+
val = FIRST_32_SECOND_64(1120, 1728);
249+
else if (minor == 5)
250+
val = FIRST_32_SECOND_64(1136, 1728);
251+
else if (minor <= 9)
252+
val = FIRST_32_SECOND_64(1136, 1712);
253+
else if (minor == 10)
254+
val = FIRST_32_SECOND_64(1168, 1776);
255+
else if (minor <= 12)
256+
val = FIRST_32_SECOND_64(1168, 2288);
257+
else
258+
val = FIRST_32_SECOND_64(1216, 2304);
259+
}
260+
if (val)
261+
atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
262+
return val;
263+
}
264+
#endif
265+
return 0;
239266
}
240267

241268
// The offset at which pointer to self is located in the thread descriptor.
@@ -263,7 +290,7 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
263290
*tls_addr = ThreadSelf();
264291
*tls_size = GetTlsSize();
265292
*tls_addr -= *tls_size;
266-
*tls_addr += kThreadDescriptorSize;
293+
*tls_addr += ThreadDescriptorSize();
267294
#else
268295
*tls_addr = 0;
269296
*tls_size = 0;

0 commit comments

Comments
 (0)