llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_win_weak_intercep...

33 lines
1.6 KiB
C
Raw Normal View History

[sanitizer] Use interception to access to strong definitions in the executable. In Windows, when sanitizers are implemented as a shared library (DLL), users can redefine and export a new definition for weak functions, in the main executable, for example: extern "C" __declspec(dllexport) void __sanitizer_cov_trace_pc_guard(u32* guard) { // Different implementation provided by the client. } However, other dlls, will continue using the default implementation imported from the sanitizer dll. This is different in linux, where all the shared libraries will consider the strong definition. With the implementation in this diff, when the dll is initialized, it will check if the main executable exports the definition for some weak function (for example __sanitizer_cov_trace_pc_guard). If it finds that function, then it will override the function in the dll with that pointer. So, all the dlls with instrumentation that import __sanitizer_cov_trace_pc_guard__dll() from asan dll, will be using the function provided by the main executable. In other words, when the main executable exports a strong definition for a weak function, we ensure all the dlls use that implementation instead of the default weak implementation. The behavior is similar to linux. Now, every user that want to override a weak function, only has to define and export it. The same for Linux and Windows, and it will work fine. So, there is no difference on the user's side. All the sanitizers will include a file sanitizer_win_weak_interception.cc that register sanitizer's weak functions to be intercepted in the binary section WEAK When the sanitizer dll is initialized, it will execute weak_intercept_init() which will consider all the CB registered in the section WEAK. So, for all the weak functions registered, we will check if a strong definition is provided in the main executable. All the files sanitizer_win_weak_interception.cc are independent, so we do not need to include a specific list of sanitizers. Now, we include [asan|ubsan|sanitizer_coverage]_win_weak_interception.cc and sanitizer_win_weak_interception.cc in asan dll, so when it is initialized, it will consider all the weak functions from asan, ubsan and sanitizer coverage. After this diff, sanitizer coverage is fixed for MD on Windows. In particular libFuzzer can provide custom implementation for all sanitizer coverage's weak functions, and they will be considered by asan dll. Differential Revision: https://reviews.llvm.org/D29168 llvm-svn: 293958
2017-02-03 07:02:11 +08:00
//===-- sanitizer_win_weak_interception.h ---------------------------------===//
//
// 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] Use interception to access to strong definitions in the executable. In Windows, when sanitizers are implemented as a shared library (DLL), users can redefine and export a new definition for weak functions, in the main executable, for example: extern "C" __declspec(dllexport) void __sanitizer_cov_trace_pc_guard(u32* guard) { // Different implementation provided by the client. } However, other dlls, will continue using the default implementation imported from the sanitizer dll. This is different in linux, where all the shared libraries will consider the strong definition. With the implementation in this diff, when the dll is initialized, it will check if the main executable exports the definition for some weak function (for example __sanitizer_cov_trace_pc_guard). If it finds that function, then it will override the function in the dll with that pointer. So, all the dlls with instrumentation that import __sanitizer_cov_trace_pc_guard__dll() from asan dll, will be using the function provided by the main executable. In other words, when the main executable exports a strong definition for a weak function, we ensure all the dlls use that implementation instead of the default weak implementation. The behavior is similar to linux. Now, every user that want to override a weak function, only has to define and export it. The same for Linux and Windows, and it will work fine. So, there is no difference on the user's side. All the sanitizers will include a file sanitizer_win_weak_interception.cc that register sanitizer's weak functions to be intercepted in the binary section WEAK When the sanitizer dll is initialized, it will execute weak_intercept_init() which will consider all the CB registered in the section WEAK. So, for all the weak functions registered, we will check if a strong definition is provided in the main executable. All the files sanitizer_win_weak_interception.cc are independent, so we do not need to include a specific list of sanitizers. Now, we include [asan|ubsan|sanitizer_coverage]_win_weak_interception.cc and sanitizer_win_weak_interception.cc in asan dll, so when it is initialized, it will consider all the weak functions from asan, ubsan and sanitizer coverage. After this diff, sanitizer coverage is fixed for MD on Windows. In particular libFuzzer can provide custom implementation for all sanitizer coverage's weak functions, and they will be considered by asan dll. Differential Revision: https://reviews.llvm.org/D29168 llvm-svn: 293958
2017-02-03 07:02:11 +08:00
//
//===----------------------------------------------------------------------===//
// This header provide helper macros to delegate calls of weak functions to the
// implementation in the main executable when a strong definition is present.
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_WIN_WEAK_INTERCEPTION_H
#define SANITIZER_WIN_WEAK_INTERCEPTION_H
#include "sanitizer_internal_defs.h"
namespace __sanitizer {
int interceptWhenPossible(uptr dll_function, const char *real_function);
}
// ----------------- Function interception helper macros -------------------- //
// Weak functions, could be redefined in the main executable, but that is not
// necessary, so we shouldn't die if we can not find a reference.
#define INTERCEPT_WEAK(Name) interceptWhenPossible((uptr) Name, #Name);
#define INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) \
static int intercept_##Name() { \
return __sanitizer::interceptWhenPossible((__sanitizer::uptr) Name, #Name);\
} \
__pragma(section(".WEAK$M", long, read)) \
__declspec(allocate(".WEAK$M")) int (*__weak_intercept_##Name)() = \
intercept_##Name;
#endif // SANITIZER_WIN_WEAK_INTERCEPTION_H