forked from OSchip/llvm-project
[ASan] Intercept CreateThread on Windows
llvm-svn: 151366
This commit is contained in:
parent
926d101640
commit
0f9c9a5332
compiler-rt/lib/asan
|
@ -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 thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) {
|
||||
AsanThread *t = (AsanThread*)arg;
|
||||
asanThreadRegistry().SetCurrent(t);
|
||||
return t->ThreadStart();
|
||||
|
@ -579,6 +579,27 @@ INTERCEPTOR(size_t, strnlen, const char *s, size_t maxlen) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
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 __asan
|
||||
#endif
|
||||
|
||||
// ---------------------- InitializeAsanInterceptors ---------------- {{{1
|
||||
namespace __asan {
|
||||
void InitializeAsanInterceptors() {
|
||||
|
@ -654,6 +675,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));
|
||||
|
|
|
@ -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)
|
||||
|
@ -265,6 +266,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 THREAD_CALLING_CONV
|
||||
typedef void* thread_return_t;
|
||||
#else
|
||||
const size_t kMmapGranularity = 1UL << 16;
|
||||
# define GET_CALLER_PC() (uintptr_t)_ReturnAddress()
|
||||
|
@ -272,6 +275,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 THREAD_CALLING_CONV __stdcall
|
||||
typedef DWORD thread_return_t;
|
||||
|
||||
# ifndef ASAN_USE_EXTERNAL_SYMBOLIZER
|
||||
# define ASAN_USE_EXTERNAL_SYMBOLIZER __asan::WinSymbolize
|
||||
|
@ -279,6 +284,8 @@ bool WinSymbolize(const void *addr, char *out_buffer, int buffer_size);
|
|||
# endif
|
||||
#endif
|
||||
|
||||
typedef thread_return_t (THREAD_CALLING_CONV *thread_callback_t)(void* arg);
|
||||
|
||||
#define GET_BP_PC_SP \
|
||||
uintptr_t bp = GET_CURRENT_FRAME(); \
|
||||
uintptr_t pc = GET_CALLER_PC(); \
|
||||
|
|
|
@ -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, thread_callback_t 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() {
|
||||
thread_return_t AsanThread::ThreadStart() {
|
||||
Init();
|
||||
|
||||
if (!start_routine_) {
|
||||
|
@ -91,7 +91,7 @@ void *AsanThread::ThreadStart() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void *res = start_routine_(arg_);
|
||||
thread_return_t res = start_routine_(arg_);
|
||||
malloc_storage().CommitBack();
|
||||
|
||||
this->Destroy();
|
||||
|
|
|
@ -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, thread_callback_t start_routine,
|
||||
void *arg, AsanStackTrace *stack);
|
||||
void Destroy();
|
||||
|
||||
void Init(); // Should be called from the thread itself.
|
||||
void *ThreadStart();
|
||||
thread_return_t 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);
|
||||
thread_callback_t start_routine_;
|
||||
void *arg_;
|
||||
uintptr_t stack_top_;
|
||||
uintptr_t stack_bottom_;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -100,21 +100,37 @@
|
|||
DECLARE_REAL(ret_type, func, ##__VA_ARGS__); \
|
||||
extern "C" ret_type WRAP(func)(__VA_ARGS__);
|
||||
|
||||
// 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__); \
|
||||
// FIXME(timurrrr): We might need to add DECLARE_REAL_EX etc to support
|
||||
// different calling conventions later.
|
||||
|
||||
#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__); \
|
||||
// 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 DEFAULT_CONVENTION
|
||||
|
||||
#define DEFINE_REAL(ret_type, func, ...); \
|
||||
DEFINE_REAL_EX(ret_type, DEFAULT_CONVENTION, 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, DEFAULT_CONVENTION, func, __VA_ARGS__)
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define INTERCEPTOR_WINAPI(ret_type, func, ...) \
|
||||
INTERCEPTOR_EX(ret_type, __stdcall, func, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define INCLUDED_FROM_INTERCEPTION_LIB
|
||||
|
||||
|
@ -127,7 +143,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
|
||||
|
|
Loading…
Reference in New Issue