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

David Blaikie dblaikie at gmail.com
Thu May 30 10:09:39 PDT 2013


On Thu, May 30, 2013 at 2:17 AM, Alexey Samsonov <samsonov at google.com> wrote:
> I was able to reproduce the error locally. I think r182918 should fix this.

Works for me - Thanks!

>
>
> On Wed, May 29, 2013 at 11:18 PM, Sergey Matveev <earthdok at google.com>
> wrote:
>>
>> Yes, I normally build with CMake/ninja (and did a clean build just now).
>> We also have a bunch of bots running CMake builds.
>>
>> On Wed, May 29, 2013 at 10:52 PM, David Blaikie <dblaikie at gmail.com>
>> wrote:
>>>
>>>
>>>
>>>
>>> On Wed, May 29, 2013 at 11:06 AM, Sergey Matveev <earthdok at google.com>
>>> wrote:
>>>>
>>>> It seems to me that you're linking with an outdated RTSanitizerCommon.
>>>
>>>
>>> I just did a clean (ninja -t clean && ninja check-all) build & still
>>> received these linker errors. Have you verified this builds for you with
>>> CMake?
>>>
>>>>
>>>>
>>>>
>>>> On Wed, May 29, 2013 at 9:45 PM, David Blaikie <dblaikie at gmail.com>
>>>> wrote:
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> 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
>>>>>
>>>>>
>>>>
>>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
>
> --
> Alexey Samsonov, MSK



More information about the llvm-commits mailing list