[compiler-rt] r182853 - [sanitizer] Change the way GetThreadStackAndTls() obtains the thread descriptor address.

David Blaikie dblaikie at gmail.com
Wed May 29 10:45:37 PDT 2013


On Wed, May 29, 2013 at 6:07 AM, Sergey Matveev <earthdok at google.com> wrote:

> Author: smatveev
> Date: Wed May 29 08:07:42 2013
> New Revision: 182853
>
> URL: http://llvm.org/viewvc/llvm-project?rev=182853&view=rev
> Log:
> [sanitizer] Change the way GetThreadStackAndTls() obtains the thread
> descriptor address.
>
> Instead of using arch_prctl(ARCH_GET_FS), read the address from the
> tread descriptor itself. This lets us avoid sandboxing issues. Also,
> GetThreadStackAndTls() can now be implemented on i386.
>

This seems like it might've broken the compiler_rt cmake (& Ninja,
specifically) build:

FAILED: cd
/usr/local/google/home/blaikie/dev/llvm/build/clang/debug/projects/compiler-rt/lib/sanitizer_common/tests
&& /usr/local/google/home/blaikie/dev/llvm/build/clang/debug/bin/clang
sanitizer_allocator_test.cc.i386.o sanitizer_atomic_test.cc.i386.o
sanitizer_common_test.cc.i386.o sanitizer_flags_test.cc.i386.o
sanitizer_libc_test.cc.i386.o sanitizer_linux_test.cc.i386.o
sanitizer_list_test.cc.i386.o sanitizer_mutex_test.cc.i386.o
sanitizer_nolibc_test.cc.i386.o sanitizer_printf_test.cc.i386.o
sanitizer_scanf_interceptor_test.cc.i386.o
sanitizer_stackdepot_test.cc.i386.o sanitizer_stacktrace_test.cc.i386.o
sanitizer_stoptheworld_test.cc.i386.o sanitizer_test_main.cc.i386.o
sanitizer_thread_registry_test.cc.i386.o gtest-all.cc.i386.o
libRTSanitizerCommon.test.i386.a -o
/usr/local/google/home/blaikie/dev/llvm/build/clang/debug/projects/compiler-rt/lib/sanitizer_common/tests/Sanitizer-i386-Test
-lstdc++ -ldl -lpthread -m32
sanitizer_linux_test.cc.i386.o: In function
`__sanitizer::thread_self_offset_test_func(void*)':
/usr/local/google/home/blaikie/dev/llvm/src/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:201:
undefined reference to `__sanitizer::ThreadSelf()'
/usr/local/google/home/blaikie/dev/llvm/src/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:201:
undefined reference to `__sanitizer::ThreadSelfOffset()'
/usr/local/google/home/blaikie/dev/llvm/src/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:201:
undefined reference to `__sanitizer::ThreadSelf()'
/usr/local/google/home/blaikie/dev/llvm/src/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:201:
undefined reference to `__sanitizer::ThreadSelf()'
/usr/local/google/home/blaikie/dev/llvm/src/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:201:
undefined reference to `__sanitizer::ThreadSelfOffset()'
/usr/local/google/home/blaikie/dev/llvm/src/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:201:
undefined reference to `__sanitizer::ThreadSelf()'
sanitizer_linux_test.cc.i386.o: In function
`__sanitizer::thread_descriptor_size_test_func(void*)':
/usr/local/google/home/blaikie/dev/llvm/src/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:216:
undefined reference to `__sanitizer::ThreadSelf()'
sanitizer_linux_test.cc.i386.o: In function
`__sanitizer::SanitizerLinux_ThreadDescriptorSize_Test::TestBody()':
/usr/local/google/home/blaikie/dev/llvm/src/projects/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cc:230:
undefined reference to `__sanitizer::ThreadDescriptorSize()'
clang-3.3: error: linker command failed with exit code 1 (use -v to see
invocation)



>
> Modified:
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
>     compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc
>
> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=182853&r1=182852&r2=182853&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h (original)
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h Wed May 29
> 08:07:42 2013
> @@ -55,6 +55,8 @@ void AdjustStackSizeLinux(void *attr, in
>
>  // Exposed for testing.
>  uptr ThreadDescriptorSize();
> +uptr ThreadSelf();
> +uptr ThreadSelfOffset();
>
>  // Matches a library's file name against a base name (stripping path and
> version
>  // information).
>
> 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=182853&r1=182852&r2=182853&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
> (original)
> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc Wed
> May 29 08:07:42 2013
> @@ -19,19 +19,12 @@
>  #include "sanitizer_procmaps.h"
>  #include "sanitizer_stacktrace.h"
>
> -#ifdef __x86_64__
> -#include <asm/prctl.h>
> -#endif
>  #include <dlfcn.h>
>  #include <pthread.h>
>  #include <sys/prctl.h>
>  #include <sys/resource.h>
>  #include <unwind.h>
>
> -#ifdef __x86_64__
> -extern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
> -#endif
> -
>  namespace __sanitizer {
>
>  void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
> @@ -200,20 +193,37 @@ uptr GetTlsSize() {
>    return g_tls_size;
>  }
>
> +#if defined(__x86_64__) || defined(i386)
>  // sizeof(struct thread) from glibc.
> -#ifdef __x86_64__
> -const uptr kThreadDescriptorSize = 2304;
> +const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1216, 2304);
>
>  uptr ThreadDescriptorSize() {
>    return kThreadDescriptorSize;
>  }
> +
> +// The offset at which pointer to self is located in the thread
> descriptor.
> +const uptr kThreadSelfOffset = FIRST_32_SECOND_64(8, 16);
> +
> +uptr ThreadSelfOffset() {
> +  return kThreadSelfOffset;
> +}
> +
> +uptr ThreadSelf() {
> +  uptr descr_addr;
> +#ifdef __i386__
> +  asm("mov %%gs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
> +#else
> +  asm("mov %%fs:%c1,%0" : "=r"(descr_addr) : "i"(kThreadSelfOffset));
>  #endif
> +  return descr_addr;
> +}
> +#endif  // defined(__x86_64__) || defined(i386)
>
>  void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
>                            uptr *tls_addr, uptr *tls_size) {
>  #ifndef SANITIZER_GO
> -#ifdef __x86_64__
> -  arch_prctl(ARCH_GET_FS, tls_addr);
> +#if defined(__x86_64__) || defined(i386)
> +  *tls_addr = ThreadSelf();
>    *tls_size = GetTlsSize();
>    *tls_addr -= *tls_size;
>    *tls_addr += kThreadDescriptorSize;
>
> Modified:
> compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc
> URL:
> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc?rev=182853&r1=182852&r2=182853&view=diff
>
> ==============================================================================
> --- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc
> (original)
> +++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc
> Wed May 29 08:07:42 2013
> @@ -19,9 +19,6 @@
>  #include "sanitizer_common/sanitizer_common.h"
>  #include "gtest/gtest.h"
>
> -#ifdef __x86_64__
> -#include <asm/prctl.h>
> -#endif
>  #include <pthread.h>
>  #include <sched.h>
>  #include <stdlib.h>
> @@ -29,10 +26,6 @@
>  #include <algorithm>
>  #include <vector>
>
> -#ifdef __x86_64__
> -extern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
> -#endif
> -
>  namespace __sanitizer {
>
>  struct TidReporterArgument {
> @@ -202,23 +195,37 @@ TEST(SanitizerCommon, SetEnvTest) {
>    EXPECT_EQ(0, getenv(kEnvName));
>  }
>
> -#ifdef __x86_64__
> -// libpthread puts the thread descriptor (%fs:0x0) at the end of stack
> space.
> -void *thread_descriptor_test_func(void *arg) {
> -  uptr fs;
> -  arch_prctl(ARCH_GET_FS, &fs);
> +#if defined(__x86_64__) || defined(i386)
> +void *thread_self_offset_test_func(void *arg) {
> +  bool result =
> +      *(uptr *)((char *)ThreadSelf() + ThreadSelfOffset()) ==
> ThreadSelf();
> +  return (void *)result;
> +}
> +
> +TEST(SanitizerLinux, ThreadSelfOffset) {
> +  EXPECT_TRUE((bool)thread_self_offset_test_func(0));
> +  pthread_t tid;
> +  void *result;
> +  ASSERT_EQ(0, pthread_create(&tid, 0, thread_self_offset_test_func, 0));
> +  ASSERT_EQ(0, pthread_join(tid, &result));
> +  EXPECT_TRUE((bool)result);
> +}
> +
> +// libpthread puts the thread descriptor at the end of stack space.
> +void *thread_descriptor_size_test_func(void *arg) {
> +  uptr descr_addr = ThreadSelf();
>    pthread_attr_t attr;
>    pthread_getattr_np(pthread_self(), &attr);
>    void *stackaddr;
> -  uptr stacksize;
> +  size_t stacksize;
>    pthread_attr_getstack(&attr, &stackaddr, &stacksize);
> -  return (void *)((uptr)stackaddr + stacksize - fs);
> +  return (void *)((uptr)stackaddr + stacksize - descr_addr);
>  }
>
>  TEST(SanitizerLinux, ThreadDescriptorSize) {
>    pthread_t tid;
>    void *result;
> -  pthread_create(&tid, 0, thread_descriptor_test_func, 0);
> +  ASSERT_EQ(0, pthread_create(&tid, 0, thread_descriptor_size_test_func,
> 0));
>    ASSERT_EQ(0, pthread_join(tid, &result));
>    EXPECT_EQ((uptr)result, ThreadDescriptorSize());
>  }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130529/0e871651/attachment.html>


More information about the llvm-commits mailing list