[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