2019-08-01 02:51:27 +08:00
|
|
|
//===-- sanitizer_win_dll_thunk.cpp ---------------------------------------===//
|
[sanitizer] Split dll_thunks into different sanitizers.
When the sanitizer is implemented as a static library and is included in the
main executable, we need an auxiliary static library dll_thunk that will be
linked to the dlls that have instrumentation, so they can refer to the runtime
in the main executable. Basically, it uses interception to get a pointer the
function in the main executable and override its function with that pointer.
Before this diff, all of the implementation for dll_thunks was included in asan.
In this diff I split it into different sanitizers, so we can use other
sanitizers regardless of whether we include asan or not.
All the sanitizers include a file sanitizer_win_dll_thunk.cc that register
functions to be intercepted in the binary section: DLLTH
When the dll including dll_thunk is initialized, it will execute
__dll_thunk_init() implemented in: sanitizer_common/sanitizer_win_dll_thunk.cc,
which will consider all the CB registered in the section DLLTH. So, all the
functions registered will be intercepted, and redirected to the implementation
in the main executable.
All the files "sanitizer_win_dll_thunk.cc" are independent, so we don't need to
include a specific list of sanitizers. Now, we compile: asan_win_dll_thunk.cc
ubsan_win_dll_thunk.cc, sanitizer_coverage_win_dll_thunk.cc and
sanitizer_win_dll_thunk.cc, to generate asan_dll_thunk, because we include asan,
ubsan and sanitizer coverage in the address sanitizer library.
Differential Revision: https://reviews.llvm.org/D29154
llvm-svn: 293951
2017-02-03 07:01:28 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
[sanitizer] Split dll_thunks into different sanitizers.
When the sanitizer is implemented as a static library and is included in the
main executable, we need an auxiliary static library dll_thunk that will be
linked to the dlls that have instrumentation, so they can refer to the runtime
in the main executable. Basically, it uses interception to get a pointer the
function in the main executable and override its function with that pointer.
Before this diff, all of the implementation for dll_thunks was included in asan.
In this diff I split it into different sanitizers, so we can use other
sanitizers regardless of whether we include asan or not.
All the sanitizers include a file sanitizer_win_dll_thunk.cc that register
functions to be intercepted in the binary section: DLLTH
When the dll including dll_thunk is initialized, it will execute
__dll_thunk_init() implemented in: sanitizer_common/sanitizer_win_dll_thunk.cc,
which will consider all the CB registered in the section DLLTH. So, all the
functions registered will be intercepted, and redirected to the implementation
in the main executable.
All the files "sanitizer_win_dll_thunk.cc" are independent, so we don't need to
include a specific list of sanitizers. Now, we compile: asan_win_dll_thunk.cc
ubsan_win_dll_thunk.cc, sanitizer_coverage_win_dll_thunk.cc and
sanitizer_win_dll_thunk.cc, to generate asan_dll_thunk, because we include asan,
ubsan and sanitizer coverage in the address sanitizer library.
Differential Revision: https://reviews.llvm.org/D29154
llvm-svn: 293951
2017-02-03 07:01:28 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// This file defines a family of thunks that should be statically linked into
|
|
|
|
// the DLLs that have instrumentation in order to delegate the calls to the
|
|
|
|
// shared runtime that lives in the main binary.
|
|
|
|
// See https://github.com/google/sanitizers/issues/209 for the details.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifdef SANITIZER_DLL_THUNK
|
|
|
|
#include "sanitizer_win_defs.h"
|
|
|
|
#include "sanitizer_win_dll_thunk.h"
|
|
|
|
#include "interception/interception.h"
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
void *WINAPI GetModuleHandleA(const char *module_name);
|
|
|
|
void abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace __sanitizer {
|
|
|
|
uptr dllThunkGetRealAddrOrDie(const char *name) {
|
|
|
|
uptr ret =
|
|
|
|
__interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name);
|
|
|
|
if (!ret)
|
|
|
|
abort();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dllThunkIntercept(const char* main_function, uptr dll_function) {
|
|
|
|
uptr wrapper = dllThunkGetRealAddrOrDie(main_function);
|
|
|
|
if (!__interception::OverrideFunction(dll_function, wrapper, 0))
|
|
|
|
abort();
|
|
|
|
return 0;
|
|
|
|
}
|
2017-02-03 07:01:34 +08:00
|
|
|
|
|
|
|
int dllThunkInterceptWhenPossible(const char* main_function,
|
|
|
|
const char* default_function, uptr dll_function) {
|
|
|
|
uptr wrapper = __interception::InternalGetProcAddress(
|
|
|
|
(void *)GetModuleHandleA(0), main_function);
|
|
|
|
if (!wrapper)
|
|
|
|
wrapper = dllThunkGetRealAddrOrDie(default_function);
|
|
|
|
if (!__interception::OverrideFunction(dll_function, wrapper, 0))
|
|
|
|
abort();
|
|
|
|
return 0;
|
|
|
|
}
|
[sanitizer] Split dll_thunks into different sanitizers.
When the sanitizer is implemented as a static library and is included in the
main executable, we need an auxiliary static library dll_thunk that will be
linked to the dlls that have instrumentation, so they can refer to the runtime
in the main executable. Basically, it uses interception to get a pointer the
function in the main executable and override its function with that pointer.
Before this diff, all of the implementation for dll_thunks was included in asan.
In this diff I split it into different sanitizers, so we can use other
sanitizers regardless of whether we include asan or not.
All the sanitizers include a file sanitizer_win_dll_thunk.cc that register
functions to be intercepted in the binary section: DLLTH
When the dll including dll_thunk is initialized, it will execute
__dll_thunk_init() implemented in: sanitizer_common/sanitizer_win_dll_thunk.cc,
which will consider all the CB registered in the section DLLTH. So, all the
functions registered will be intercepted, and redirected to the implementation
in the main executable.
All the files "sanitizer_win_dll_thunk.cc" are independent, so we don't need to
include a specific list of sanitizers. Now, we compile: asan_win_dll_thunk.cc
ubsan_win_dll_thunk.cc, sanitizer_coverage_win_dll_thunk.cc and
sanitizer_win_dll_thunk.cc, to generate asan_dll_thunk, because we include asan,
ubsan and sanitizer coverage in the address sanitizer library.
Differential Revision: https://reviews.llvm.org/D29154
llvm-svn: 293951
2017-02-03 07:01:28 +08:00
|
|
|
} // namespace __sanitizer
|
|
|
|
|
|
|
|
// Include Sanitizer Common interface.
|
|
|
|
#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
|
2017-02-03 07:01:34 +08:00
|
|
|
#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
|
[sanitizer] Split dll_thunks into different sanitizers.
When the sanitizer is implemented as a static library and is included in the
main executable, we need an auxiliary static library dll_thunk that will be
linked to the dlls that have instrumentation, so they can refer to the runtime
in the main executable. Basically, it uses interception to get a pointer the
function in the main executable and override its function with that pointer.
Before this diff, all of the implementation for dll_thunks was included in asan.
In this diff I split it into different sanitizers, so we can use other
sanitizers regardless of whether we include asan or not.
All the sanitizers include a file sanitizer_win_dll_thunk.cc that register
functions to be intercepted in the binary section: DLLTH
When the dll including dll_thunk is initialized, it will execute
__dll_thunk_init() implemented in: sanitizer_common/sanitizer_win_dll_thunk.cc,
which will consider all the CB registered in the section DLLTH. So, all the
functions registered will be intercepted, and redirected to the implementation
in the main executable.
All the files "sanitizer_win_dll_thunk.cc" are independent, so we don't need to
include a specific list of sanitizers. Now, we compile: asan_win_dll_thunk.cc
ubsan_win_dll_thunk.cc, sanitizer_coverage_win_dll_thunk.cc and
sanitizer_win_dll_thunk.cc, to generate asan_dll_thunk, because we include asan,
ubsan and sanitizer coverage in the address sanitizer library.
Differential Revision: https://reviews.llvm.org/D29154
llvm-svn: 293951
2017-02-03 07:01:28 +08:00
|
|
|
#include "sanitizer_common_interface.inc"
|
|
|
|
|
2019-09-12 07:19:48 +08:00
|
|
|
#pragma section(".DLLTH$A", read)
|
|
|
|
#pragma section(".DLLTH$Z", read)
|
[sanitizer] Split dll_thunks into different sanitizers.
When the sanitizer is implemented as a static library and is included in the
main executable, we need an auxiliary static library dll_thunk that will be
linked to the dlls that have instrumentation, so they can refer to the runtime
in the main executable. Basically, it uses interception to get a pointer the
function in the main executable and override its function with that pointer.
Before this diff, all of the implementation for dll_thunks was included in asan.
In this diff I split it into different sanitizers, so we can use other
sanitizers regardless of whether we include asan or not.
All the sanitizers include a file sanitizer_win_dll_thunk.cc that register
functions to be intercepted in the binary section: DLLTH
When the dll including dll_thunk is initialized, it will execute
__dll_thunk_init() implemented in: sanitizer_common/sanitizer_win_dll_thunk.cc,
which will consider all the CB registered in the section DLLTH. So, all the
functions registered will be intercepted, and redirected to the implementation
in the main executable.
All the files "sanitizer_win_dll_thunk.cc" are independent, so we don't need to
include a specific list of sanitizers. Now, we compile: asan_win_dll_thunk.cc
ubsan_win_dll_thunk.cc, sanitizer_coverage_win_dll_thunk.cc and
sanitizer_win_dll_thunk.cc, to generate asan_dll_thunk, because we include asan,
ubsan and sanitizer coverage in the address sanitizer library.
Differential Revision: https://reviews.llvm.org/D29154
llvm-svn: 293951
2017-02-03 07:01:28 +08:00
|
|
|
|
|
|
|
typedef void (*DllThunkCB)();
|
|
|
|
extern "C" {
|
|
|
|
__declspec(allocate(".DLLTH$A")) DllThunkCB __start_dll_thunk;
|
|
|
|
__declspec(allocate(".DLLTH$Z")) DllThunkCB __stop_dll_thunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable compiler warnings that show up if we declare our own version
|
|
|
|
// of a compiler intrinsic (e.g. strlen).
|
|
|
|
#pragma warning(disable: 4391)
|
|
|
|
#pragma warning(disable: 4392)
|
|
|
|
|
|
|
|
extern "C" int __dll_thunk_init() {
|
|
|
|
static bool flag = false;
|
|
|
|
// __dll_thunk_init is expected to be called by only one thread.
|
|
|
|
if (flag) return 0;
|
|
|
|
flag = true;
|
|
|
|
|
|
|
|
for (DllThunkCB *it = &__start_dll_thunk; it < &__stop_dll_thunk; ++it)
|
|
|
|
if (*it)
|
|
|
|
(*it)();
|
|
|
|
|
|
|
|
// In DLLs, the callbacks are expected to return 0,
|
|
|
|
// otherwise CRT initialization fails.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We want to call dll_thunk_init before C/C++ initializers / constructors are
|
|
|
|
// executed, otherwise functions like memset might be invoked.
|
2019-09-12 07:19:48 +08:00
|
|
|
#pragma section(".CRT$XIB", long, read)
|
[sanitizer] Split dll_thunks into different sanitizers.
When the sanitizer is implemented as a static library and is included in the
main executable, we need an auxiliary static library dll_thunk that will be
linked to the dlls that have instrumentation, so they can refer to the runtime
in the main executable. Basically, it uses interception to get a pointer the
function in the main executable and override its function with that pointer.
Before this diff, all of the implementation for dll_thunks was included in asan.
In this diff I split it into different sanitizers, so we can use other
sanitizers regardless of whether we include asan or not.
All the sanitizers include a file sanitizer_win_dll_thunk.cc that register
functions to be intercepted in the binary section: DLLTH
When the dll including dll_thunk is initialized, it will execute
__dll_thunk_init() implemented in: sanitizer_common/sanitizer_win_dll_thunk.cc,
which will consider all the CB registered in the section DLLTH. So, all the
functions registered will be intercepted, and redirected to the implementation
in the main executable.
All the files "sanitizer_win_dll_thunk.cc" are independent, so we don't need to
include a specific list of sanitizers. Now, we compile: asan_win_dll_thunk.cc
ubsan_win_dll_thunk.cc, sanitizer_coverage_win_dll_thunk.cc and
sanitizer_win_dll_thunk.cc, to generate asan_dll_thunk, because we include asan,
ubsan and sanitizer coverage in the address sanitizer library.
Differential Revision: https://reviews.llvm.org/D29154
llvm-svn: 293951
2017-02-03 07:01:28 +08:00
|
|
|
__declspec(allocate(".CRT$XIB")) int (*__dll_thunk_preinit)() =
|
|
|
|
__dll_thunk_init;
|
|
|
|
|
|
|
|
static void WINAPI dll_thunk_thread_init(void *mod, unsigned long reason,
|
|
|
|
void *reserved) {
|
|
|
|
if (reason == /*DLL_PROCESS_ATTACH=*/1) __dll_thunk_init();
|
|
|
|
}
|
|
|
|
|
2019-09-12 07:19:48 +08:00
|
|
|
#pragma section(".CRT$XLAB", long, read)
|
[sanitizer] Split dll_thunks into different sanitizers.
When the sanitizer is implemented as a static library and is included in the
main executable, we need an auxiliary static library dll_thunk that will be
linked to the dlls that have instrumentation, so they can refer to the runtime
in the main executable. Basically, it uses interception to get a pointer the
function in the main executable and override its function with that pointer.
Before this diff, all of the implementation for dll_thunks was included in asan.
In this diff I split it into different sanitizers, so we can use other
sanitizers regardless of whether we include asan or not.
All the sanitizers include a file sanitizer_win_dll_thunk.cc that register
functions to be intercepted in the binary section: DLLTH
When the dll including dll_thunk is initialized, it will execute
__dll_thunk_init() implemented in: sanitizer_common/sanitizer_win_dll_thunk.cc,
which will consider all the CB registered in the section DLLTH. So, all the
functions registered will be intercepted, and redirected to the implementation
in the main executable.
All the files "sanitizer_win_dll_thunk.cc" are independent, so we don't need to
include a specific list of sanitizers. Now, we compile: asan_win_dll_thunk.cc
ubsan_win_dll_thunk.cc, sanitizer_coverage_win_dll_thunk.cc and
sanitizer_win_dll_thunk.cc, to generate asan_dll_thunk, because we include asan,
ubsan and sanitizer coverage in the address sanitizer library.
Differential Revision: https://reviews.llvm.org/D29154
llvm-svn: 293951
2017-02-03 07:01:28 +08:00
|
|
|
__declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *,
|
|
|
|
unsigned long, void *) = dll_thunk_thread_init;
|
|
|
|
|
|
|
|
#endif // SANITIZER_DLL_THUNK
|