[PATCH] [asan] Make ASan report the correct thread address ranges to LSan.

Sergey Matveev earthdok at google.com
Mon May 27 08:49:42 PDT 2013


    - unpoison the TLS

Hi kcc, glider, samsonov,

http://llvm-reviews.chandlerc.com/D862

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D862?vs=2124&id=2141#toc

Files:
  lib/asan/asan_rtl.cc
  lib/asan/asan_thread.cc
  lib/asan/asan_thread.h
  lib/asan/lit_tests/unpoison_tls.cc

Index: lib/asan/asan_rtl.cc
===================================================================
--- lib/asan/asan_rtl.cc
+++ lib/asan/asan_rtl.cc
@@ -547,6 +547,8 @@
   asan_inited = 1;
   asan_init_is_running = false;
 
+  InitTlsSize();
+
   // Create main thread.
   AsanTSDInit(AsanThread::TSDDtor);
   AsanThread *main_thread = AsanThread::Create(0, 0);
Index: lib/asan/asan_thread.cc
===================================================================
--- lib/asan/asan_thread.cc
+++ lib/asan/asan_thread.cc
@@ -100,17 +100,17 @@
   // We also clear the shadow on thread destruction because
   // some code may still be executing in later TSD destructors
   // and we don't want it to have any poisoned stack.
-  ClearShadowForThreadStack();
+  ClearShadowForThreadStackAndTLS();
   fake_stack().Cleanup();
   uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
   UnmapOrDie(this, size);
 }
 
 void AsanThread::Init() {
-  SetThreadStackTopAndBottom();
+  SetThreadStackAndTls();
   CHECK(AddrIsInMem(stack_bottom_));
   CHECK(AddrIsInMem(stack_top_ - 1));
-  ClearShadowForThreadStack();
+  ClearShadowForThreadStackAndTLS();
   if (flags()->verbosity >= 1) {
     int local = 0;
     Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
@@ -143,14 +143,21 @@
   return res;
 }
 
-void AsanThread::SetThreadStackTopAndBottom() {
-  GetThreadStackTopAndBottom(tid() == 0, &stack_top_, &stack_bottom_);
+void AsanThread::SetThreadStackAndTls() {
+  uptr stack_size = 0, tls_size = 0;
+  GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size, &tls_begin_,
+                       &tls_size);
+  stack_top_ = stack_bottom_ + stack_size;
+  tls_end_ = tls_begin_ + tls_size;
+
   int local;
   CHECK(AddrIsInStack((uptr)&local));
 }
 
-void AsanThread::ClearShadowForThreadStack() {
+void AsanThread::ClearShadowForThreadStackAndTLS() {
   PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
+  if (tls_begin_ != tls_end_)
+    PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0);
 }
 
 const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset,
@@ -251,8 +258,19 @@
 bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
                            uptr *tls_begin, uptr *tls_end,
                            uptr *cache_begin, uptr *cache_end) {
-  // FIXME: Stub.
-  return false;
+  __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
+      __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
+  if (!context) return false;
+  __asan::AsanThread *t = context->thread;
+  if (!t) return false;
+  *stack_begin = t->stack_bottom();
+  *stack_end = t->stack_top();
+  *tls_begin = t->tls_begin();
+  *tls_end = t->tls_end();
+  // ASan doesn't keep allocator caches in TLS, so these are unused.
+  *cache_begin = 0;
+  *cache_end = 0;
+  return true;
 }
 
 void LockThreadRegistry() {
Index: lib/asan/asan_thread.h
===================================================================
--- lib/asan/asan_thread.h
+++ lib/asan/asan_thread.h
@@ -63,6 +63,8 @@
   uptr stack_top() { return stack_top_; }
   uptr stack_bottom() { return stack_bottom_; }
   uptr stack_size() { return stack_top_ - stack_bottom_; }
+  uptr tls_begin() { return tls_begin_; }
+  uptr tls_end() { return tls_end_; }
   u32 tid() { return context_->tid; }
   AsanThreadContext *context() { return context_; }
   void set_context(AsanThreadContext *context) { context_ = context; }
@@ -79,13 +81,15 @@
 
  private:
   AsanThread() {}
-  void SetThreadStackTopAndBottom();
-  void ClearShadowForThreadStack();
+  void SetThreadStackAndTls();
+  void ClearShadowForThreadStackAndTLS();
   AsanThreadContext *context_;
   thread_callback_t start_routine_;
   void *arg_;
   uptr  stack_top_;
   uptr  stack_bottom_;
+  uptr tls_begin_;
+  uptr tls_end_;
 
   FakeStack fake_stack_;
   AsanThreadLocalMallocStorage malloc_storage_;
Index: lib/asan/lit_tests/unpoison_tls.cc
===================================================================
--- /dev/null
+++ lib/asan/lit_tests/unpoison_tls.cc
@@ -0,0 +1,63 @@
+// Test that TLS is unpoisoned on thread death.
+// REQUIRES: x86_64-supported-target,i386-supported-target
+
+// RUN: %clangxx_asan -m64 -O0 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1
+// RUN: %clangxx_asan -m64 -O1 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m64 -O1 %s -o %t && %t 2>&1
+// RUN: %clangxx_asan -m64 -O2 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m64 -O2 %s -o %t && %t 2>&1
+// RUN: %clangxx_asan -m64 -O3 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m64 -O3 %s -o %t && %t 2>&1
+// RUN: %clangxx_asan -m32 -O0 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m32 -O0 %s -o %t && %t 2>&1
+// RUN: %clangxx_asan -m32 -O1 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1
+// RUN: %clangxx_asan -m32 -O2 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1
+// RUN: %clangxx_asan -m32 -O3 %p/SharedLibs/dlclose-test-so.cc \
+// RUN:     -fPIC -shared -o %t-so.so
+// RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1
+
+#include <assert.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#include <sanitizer/asan_interface.h>
+
+__thread char tls_var[16];
+
+void *p_tls_var;
+
+void *first(void *arg) {
+  ASAN_POISON_MEMORY_REGION(&tls_var, sizeof(tls_var));
+  p_tls_var = (void *)tls_var;
+  return 0;
+}
+
+void *second(void *arg) {
+  assert((void *)tls_var == p_tls_var);
+  tls_var[0] = 1;
+  return 0;
+}
+
+int main(int argc, char *argv[]) {
+  pthread_t p;
+  int res;
+  res = pthread_create(&p, 0, first, 0);
+  assert(res == 0);
+  res = pthread_join(p, 0);
+  assert(res == 0);
+  pthread_create(&p, 0, second, 0);
+  assert(res == 0);
+  pthread_join(p, 0);
+  assert(res == 0);
+  return 0;
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D862.2.patch
Type: text/x-patch
Size: 6148 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130527/382c07cf/attachment.bin>


More information about the llvm-commits mailing list