[compiler-rt] r182853 - [sanitizer] Change the way GetThreadStackAndTls() obtains the thread descriptor address.
Sergey Matveev
earthdok at google.com
Wed May 29 06:07:42 PDT 2013
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.
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());
}
More information about the llvm-commits
mailing list