[compiler-rt] r200733 - [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

Dmitri Gribenko gribozavr at gmail.com
Sun Mar 2 07:08:41 PST 2014


On Tue, Feb 4, 2014 at 4:09 AM, Kostya Serebryany <kcc at google.com> wrote:
> Author: kcc
> Date: Mon Feb  3 22:09:38 2014
> New Revision: 200733
>
> URL: http://llvm.org/viewvc/llvm-project?rev=200733&view=rev
> Log:
> [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
>
> Modified:
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
>
> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc?rev=200733&r1=200732&r2=200733&view=diff
> ==============================================================================
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc (original)
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc Mon Feb  3 22:09:38 2014
> @@ -21,6 +21,7 @@
>  #include "sanitizer_placement_new.h"
>  #include "sanitizer_procmaps.h"
>  #include "sanitizer_stacktrace.h"
> +#include "sanitizer_atomic.h"
>
>  #include <dlfcn.h>
>  #include <pthread.h>
> @@ -32,6 +33,7 @@
>  #if !SANITIZER_ANDROID
>  #include <elf.h>
>  #include <link.h>
> +#include <unistd.h>
>  #endif
>
>  #ifndef SANITIZER_GO
> @@ -226,16 +228,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;
> +  }

The hardcoded value seems to be incorrect for CentOS 6.5 (glib 2.12).
Here's what the test says:

$ ./projects/compiler-rt/lib/sanitizer_common/tests/Sanitizer-x86_64-Test
--gtest_filter=SanitizerLinux.ThreadDescriptorSize
Note: Google Test filter = SanitizerLinux.ThreadDescriptorSize
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from SanitizerLinux
[ RUN      ] SanitizerLinux.ThreadDescriptorSize
/home/llvmbb/clang/llvm/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:230:
Failure
Value of: ThreadDescriptorSize()
  Actual: 2288
Expected: (uptr)result
Which is: 2304
[  FAILED  ] SanitizerLinux.ThreadDescriptorSize (1 ms)
[----------] 1 test from SanitizerLinux (1 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] SanitizerLinux.ThreadDescriptorSize

 1 FAILED TEST

Interestingly, the struct size on this system (2304) matches the
hardcoded size for glibc 2.13+.  I am not sure if this is caused by
patches for glibc or not.

Dmitri

-- 
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/



More information about the llvm-commits mailing list