[llvm-commits] [ASan] Intercept CreateThread on Windows (issue 5699064)

timurrrr at google.com timurrrr at google.com
Fri Feb 24 06:14:28 PST 2012


Reviewers: glider, samsonov,

Message:
Hi Alexander, Alexey,

Can you please review this patch?

Thanks!


http://codereview.appspot.com/5699064/diff/1/lib/asan/asan_interceptors_win.h
File lib/asan/asan_interceptors_win.h (right):

http://codereview.appspot.com/5699064/diff/1/lib/asan/asan_interceptors_win.h#newcode16
lib/asan/asan_interceptors_win.h:16: // Reverse include guard.
Please pay special attention to this part.
Alternative suggestions are welcome!

Please note that we do want to re-use some of the macros defined in
asan_interceptors.cc but don't want to move them to asan_interceptors.h

http://codereview.appspot.com/5699064/diff/1/lib/asan/asan_win.cc
File lib/asan/asan_win.cc (right):

http://codereview.appspot.com/5699064/diff/1/lib/asan/asan_win.cc#newcode50
lib/asan/asan_win.cc:50: CHECK(VirtualFree(addr, size, MEM_DECOMMIT));
Threaded tests fail if we have CreateThread but not AsanUnmap

Description:
[ASan] Intercept CreateThread on Windows

Please review this at http://codereview.appspot.com/5699064/

Affected files:
   M lib/asan/asan_interceptors.cc
   A lib/asan/asan_interceptors_win.h
   M lib/asan/asan_internal.h
   M lib/asan/asan_thread.cc
   M lib/asan/asan_thread.h
   M lib/asan/asan_win.cc
   M lib/asan/interception/interception.h


Index: lib/asan/asan_interceptors.cc
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc
index  
cd824452ff3234b6d1de28839dc01694c6cdad9c..cbb943e24a020d6c1292924340b4a44135094186  
100644
--- a/lib/asan/asan_interceptors.cc
+++ b/lib/asan/asan_interceptors.cc
@@ -254,7 +254,7 @@ void operator delete(void *ptr, std::nothrow_t const&)  
throw()
  void operator delete[](void *ptr, std::nothrow_t const&) throw()
  { OPERATOR_DELETE_BODY;}

-static void *asan_thread_start(void *arg) {
+static ThreadReturnType THREADPROC asan_thread_start(void *arg) {
    AsanThread *t = (AsanThread*)arg;
    asanThreadRegistry().SetCurrent(t);
    return t->ThreadStart();
@@ -579,6 +579,10 @@ INTERCEPTOR(size_t, strnlen, const char *s, size_t  
maxlen) {
  }
  #endif

+#if defined(_WIN32)
+# include "asan_interceptors_win.h"
+#endif
+
  // ---------------------- InitializeAsanInterceptors ---------------- {{{1
  namespace __asan {
  void InitializeAsanInterceptors() {
@@ -654,6 +658,11 @@ void InitializeAsanInterceptors() {
  # endif
  #endif

+  // Some Windows-specific interceptors.
+#if defined(_WIN32)
+  InitializeWindowsInterceptors();
+#endif
+
    // Some Mac-specific interceptors.
  #if defined(__APPLE__)
    CHECK(INTERCEPT_FUNCTION(dispatch_async_f));
Index: lib/asan/asan_interceptors_win.h
diff --git a/lib/asan/asan_interceptors_win.h  
b/lib/asan/asan_interceptors_win.h
new file mode 100644
index  
0000000000000000000000000000000000000000..7ab0a0624e2e15adf5311f7d10cf018bea4f76c9
--- /dev/null
+++ b/lib/asan/asan_interceptors_win.h
@@ -0,0 +1,39 @@
+//===-- asan_interceptors_win.h ---------------------------------*- C++  
-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Intercept various Windows-specific functions.
+//===----------------------------------------------------------------------===//
+
+#ifdef ASAN_INTERCEPTORS_WIN_H
+// Reverse include guard.
+// This is an "include from one .cc file" rather than a common header to  
use.
+# error Do not include this file anywhere except from asan_interceptors.cc
+#endif
+#define ASAN_INTERCEPTORS_WIN_H
+
+INTERCEPTOR_WINAPI(DWORD, CreateThread,
+                   void* security, size_t stack_size,
+                   DWORD (__stdcall *start_routine)(void*), void* arg,
+                   DWORD flags, void* tid) {
+  GET_STACK_TRACE_HERE(kStackTraceMax);
+  int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
+  AsanThread *t = AsanThread::Create(current_tid, start_routine, arg,  
&stack);
+  asanThreadRegistry().RegisterThread(t);
+  return REAL(CreateThread)(security, stack_size,
+                            asan_thread_start, t, flags, tid);
+}
+
+namespace __asan {
+void InitializeWindowsInterceptors() {
+  CHECK(INTERCEPT_FUNCTION(CreateThread));
+}
+
+}  // namespace
Index: lib/asan/asan_internal.h
diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h
index  
8891e3af48ccde1e804bec64e07d825a723dce3d..7c592953754de964cf9bde137b69013d67cadcdf  
100644
--- a/lib/asan/asan_internal.h
+++ b/lib/asan/asan_internal.h
@@ -30,6 +30,7 @@ typedef __int8           int8_t;
  typedef __int16          int16_t;
  typedef __int32          int32_t;
  typedef __int64          int64_t;
+typedef unsigned long    DWORD;  // NOLINT

  extern "C" void* _ReturnAddress(void);
  # pragma intrinsic(_ReturnAddress)
@@ -259,6 +260,8 @@ const size_t kPageSize = 1UL << kPageSizeBits;
  const size_t kMmapGranularity = kPageSize;
  # define GET_CALLER_PC() (uintptr_t)__builtin_return_address(0)
  # define GET_CURRENT_FRAME() (uintptr_t)__builtin_frame_address(0)
+# define THREADPROC
+typedef void* ThreadReturnType;
  #else
  const size_t kMmapGranularity = 1UL << 16;
  # define GET_CALLER_PC() (uintptr_t)_ReturnAddress()
@@ -266,6 +269,8 @@ const size_t kMmapGranularity = 1UL << 16;
  // FIXME: This macro is still used when printing error reports though it's  
not
  // clear if the BP value is needed in the ASan reports on Windows.
  # define GET_CURRENT_FRAME() (uintptr_t)0xDEADBEEF
+# define THREADPROC __stdcall
+typedef DWORD ThreadReturnType;

  # ifndef ASAN_USE_EXTERNAL_SYMBOLIZER
  #  define ASAN_USE_EXTERNAL_SYMBOLIZER __asan::WinSymbolize
@@ -273,6 +278,8 @@ bool WinSymbolize(const void *addr, char *out_buffer,  
int buffer_size);
  # endif
  #endif

+typedef ThreadReturnType (THREADPROC *ThreadProc)(void* param);
+
  #define GET_BP_PC_SP \
    uintptr_t bp = GET_CURRENT_FRAME();              \
    uintptr_t pc = GET_CALLER_PC();                  \
Index: lib/asan/asan_thread.cc
diff --git a/lib/asan/asan_thread.cc b/lib/asan/asan_thread.cc
index  
6e6436b81449b997dbafcb857fa449a4e12881b8..60a9fa1a41f018e82c39018635a42a961673a7f1  
100644
--- a/lib/asan/asan_thread.cc
+++ b/lib/asan/asan_thread.cc
@@ -26,7 +26,7 @@ AsanThread::AsanThread(LinkerInitialized x)
        malloc_storage_(x),
        stats_(x) { }

-AsanThread *AsanThread::Create(int parent_tid, void *(*start_routine)  
(void *),
+AsanThread *AsanThread::Create(int parent_tid, ThreadProc start_routine,
                                 void *arg, AsanStackTrace *stack) {
    size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
    AsanThread *thread = (AsanThread*)AsanMmapSomewhereOrDie(size,  
__FUNCTION__);
@@ -80,7 +80,7 @@ void AsanThread::Init() {
    fake_stack_.Init(stack_size());
  }

-void *AsanThread::ThreadStart() {
+ThreadReturnType AsanThread::ThreadStart() {
    Init();

    if (!start_routine_) {
@@ -91,7 +91,7 @@ void *AsanThread::ThreadStart() {
      return 0;
    }

-  void *res = start_routine_(arg_);
+  ThreadReturnType res = start_routine_(arg_);
    malloc_storage().CommitBack();

    this->Destroy();
Index: lib/asan/asan_thread.h
diff --git a/lib/asan/asan_thread.h b/lib/asan/asan_thread.h
index  
9fc1e26ca6b829cea87e7fcda6d073a5e878793e..15fe2c026b88ba3878f693d70ecd674ea49da228  
100644
--- a/lib/asan/asan_thread.h
+++ b/lib/asan/asan_thread.h
@@ -65,12 +65,12 @@ class AsanThreadSummary {
  class AsanThread {
   public:
    explicit AsanThread(LinkerInitialized);  // for T0.
-  static AsanThread *Create(int parent_tid, void *(*start_routine) (void  
*),
+  static AsanThread *Create(int parent_tid, ThreadProc start_routine,
                              void *arg, AsanStackTrace *stack);
    void Destroy();

    void Init();  // Should be called from the thread itself.
-  void *ThreadStart();
+  ThreadReturnType ThreadStart();

    uintptr_t stack_top() { return stack_top_; }
    uintptr_t stack_bottom() { return stack_bottom_; }
@@ -96,7 +96,7 @@ class AsanThread {
    void SetThreadStackTopAndBottom();
    void ClearShadowForThreadStack();
    AsanThreadSummary *summary_;
-  void *(*start_routine_) (void *param);
+  ThreadProc start_routine_;
    void *arg_;
    uintptr_t  stack_top_;
    uintptr_t  stack_bottom_;
Index: lib/asan/asan_win.cc
diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc
index  
2692b0db5b77743133776861567d4a123d5e1198..d47ff08e9e0c016cdb63013ac5ae56000593c479  
100644
--- a/lib/asan/asan_win.cc
+++ b/lib/asan/asan_win.cc
@@ -47,7 +47,7 @@ void *AsanMprotect(uintptr_t fixed_addr, size_t size) {
  }

  void AsanUnmapOrDie(void *addr, size_t size) {
-  UNIMPLEMENTED();
+  CHECK(VirtualFree(addr, size, MEM_DECOMMIT));
  }

  // ---------------------- IO ---------------- {{{1
Index: lib/asan/interception/interception.h
diff --git a/lib/asan/interception/interception.h  
b/lib/asan/interception/interception.h
index  
ae56af32f0e5de70a9798d5cfd12f0c498ee2be3..348f121c668afe5fc4f50023ea7f89dc46baa50f  
100644
--- a/lib/asan/interception/interception.h
+++ b/lib/asan/interception/interception.h
@@ -100,21 +100,33 @@
    DECLARE_REAL(ret_type, func, ##__VA_ARGS__); \
    extern "C" ret_type WRAP(func)(__VA_ARGS__);

+// FIXME(timurrrr): We might need to add DECLARE_REAL_EX etc to support
+// different calling conventions later.
+
  // Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR
  // macros does its job. In exceptional cases you may need to call REAL(foo)
  // without defining INTERCEPTOR(..., foo, ...). For example, if you  
override
  // foo with an interceptor for other function.
-#define DEFINE_REAL(ret_type, func, ...); \
-  typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
+#define DEFINE_REAL_EX(ret_type, convention, func, ...); \
+  typedef ret_type (convention *FUNC_TYPE(func))(__VA_ARGS__); \
    namespace __interception { \
      FUNC_TYPE(func) PTR_TO_REAL(func); \
    }

-#define INTERCEPTOR(ret_type, func, ...) \
-  DEFINE_REAL(ret_type, func, __VA_ARGS__); \
+#define DEFINE_REAL(ret_type, func, ...); \
+  DEFINE_REAL_EX(ret_type, , func, __VA_ARGS__);
+
+#define INTERCEPTOR_EX(ret_type, convention, func, ...) \
+  DEFINE_REAL_EX(ret_type, convention, func, __VA_ARGS__); \
    extern "C" \
    INTERCEPTOR_ATTRIBUTE \
-  ret_type WRAP(func)(__VA_ARGS__)
+  ret_type convention WRAP(func)(__VA_ARGS__)
+
+#define INTERCEPTOR(ret_type, func, ...) \
+  INTERCEPTOR_EX(ret_type, , func, __VA_ARGS__)
+
+#define INTERCEPTOR_WINAPI(ret_type, func, ...) \
+  INTERCEPTOR_EX(ret_type, __stdcall, func, __VA_ARGS__)

  #define INCLUDED_FROM_INTERCEPTION_LIB

@@ -127,7 +139,6 @@
      OVERRIDE_FUNCTION_MAC(old_func, new_func)
  # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
  #else  // defined(_WIN32)
-  // FIXME: deal with interception on Win.
  # include "interception_win.h"
  # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_WIN(func)
  #endif





More information about the llvm-commits mailing list