[llvm-dev] [PATCH compiler-rt 1/5] asan: make getcontext() and swapcontext() write stack description

Paweł Dziepak via llvm-dev
2016-02-02T14:42:39Z

Normally, ucontext_t::uc_stack is only used by makecontext() and not
written to or read from any other *context() functions. However, if
making sure that it contains proper stack description can make improving
support for swapcontext() much easier.
---
 lib/asan/asan_interceptors.cc | 16 ++++++++++++++++
 lib/asan/asan_internal.h      |  1 +
 lib/asan/asan_linux.cc        | 10 ++++++++++
 lib/asan/asan_mac.cc          |  4 ++++
 lib/asan/asan_win.cc          |  4 ++++
 5 files changed, 35 insertions(+)

diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc
index faac15b..6b1aa00 100644
--- a/lib/asan/asan_interceptors.cc
+++ b/lib/asan/asan_interceptors.cc
@@ -346,6 +346,11 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
   uptr stack, ssize;
   ReadContextStack(ucp, &stack, &ssize);
   ClearShadowMemoryForContextStack(stack, ssize);
+  AsanThread *curr_thread = GetCurrentThread();
+  if (curr_thread) {
+    WriteContextStack(oucp, curr_thread->stack_bottom(),
+                      curr_thread->stack_size());
+  }
   int res = REAL(swapcontext)(oucp, ucp);
   // swapcontext technically does not return, but program may swap context to
   // "oucp" later, that would look as if swapcontext() returned 0.
@@ -354,6 +359,16 @@ INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp,
   ClearShadowMemoryForContextStack(stack, ssize);
   return res;
 }
+
+INTERCEPTOR(int, getcontext, struct ucontext_t *ucp) {
+  int res = REAL(getcontext)(ucp);
+  AsanThread *curr_thread = GetCurrentThread();
+  if (!res && curr_thread) {
+    WriteContextStack(ucp, curr_thread->stack_bottom(),
+                      curr_thread->stack_size());
+  }
+  return res;
+}
 #endif  // ASAN_INTERCEPT_SWAPCONTEXT

 INTERCEPTOR(void, longjmp, void *env, int val) {
@@ -796,6 +811,7 @@ void InitializeAsanInterceptors() {
 #endif
 #if ASAN_INTERCEPT_SWAPCONTEXT
   ASAN_INTERCEPT_FUNC(swapcontext);
+  ASAN_INTERCEPT_FUNC(getcontext);
 #endif
 #if ASAN_INTERCEPT__LONGJMP
   ASAN_INTERCEPT_FUNC(_longjmp);
diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h
index 9391475..5d417eb 100644
--- a/lib/asan/asan_internal.h
+++ b/lib/asan/asan_internal.h
@@ -76,6 +76,7 @@ void AsanCheckIncompatibleRT();
 void AsanOnDeadlySignal(int, void *siginfo, void *context);

 void ReadContextStack(void *context, uptr *stack, uptr *ssize);
+void WriteContextStack(void *context, uptr stack, uptr ssize);
 void StopInitOrderChecking();

 // Wrapper for TLS/TSD.
diff --git a/lib/asan/asan_linux.cc b/lib/asan/asan_linux.cc
index e26b400..f157e48 100644
--- a/lib/asan/asan_linux.cc
+++ b/lib/asan/asan_linux.cc
@@ -156,10 +156,20 @@ void ReadContextStack(void *context, uptr *stack, uptr
*ssize) {
   *stack = (uptr)ucp->uc_stack.ss_sp;
   *ssize = ucp->uc_stack.ss_size;
 }
+
+void WriteContextStack(void *context, uptr stack, uptr ssize) {
+  ucontext_t *ucp = (ucontext_t*)context;
+  ucp->uc_stack.ss_sp = (void*)stack;
+  ucp->uc_stack.ss_size = ssize;
+}
 #else
 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
   UNIMPLEMENTED();
 }
+
+void WriteContextStack(void *context, uptr stack, uptr ssize) {
+  UNIMPLEMENTED();
+}
 #endif

 void *AsanDlSymNext(const char *sym) {
diff --git a/lib/asan/asan_mac.cc b/lib/asan/asan_mac.cc
index 6975b03..d6a4bc3 100644
--- a/lib/asan/asan_mac.cc
+++ b/lib/asan/asan_mac.cc
@@ -70,6 +70,10 @@ void ReadContextStack(void *context, uptr *stack, uptr
*ssize) {
   UNIMPLEMENTED();
 }

+void WriteContextStack(void *context, uptr stack, uptr ssize) {
+  UNIMPLEMENTED();
+}
+
 // Support for the following functions from libdispatch on Mac OS:
 //   dispatch_async_f()
 //   dispatch_async()
diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc
index 92bd893..2cae8dd 100644
--- a/lib/asan/asan_win.cc
+++ b/lib/asan/asan_win.cc
@@ -190,6 +190,10 @@ void ReadContextStack(void *context, uptr *stack, uptr
*ssize) {
   UNIMPLEMENTED();
 }

+void WriteContextStack(void *context, uptr stack, uptr ssize) {
+  UNIMPLEMENTED();
+}
+
 void AsanOnDeadlySignal(int, void *siginfo, void *context) {
   UNIMPLEMENTED();
 }
--
2.5.0