[asan] Export new and delete operators on Windows

This is necessary to support the dynamic CRT (/MD) with VS2015. In
VS2015, these symbols are no longer imported from a DLL, they provided
statically by msvcrt.lib. This means our approach of hotpatching the DLL
no longer works.

By exporting the symbols, we end up relying on the same mechanism that
we use to intercept symbols in the static CRT (/MT) case. The ASan
runtime always needs to appear first on the link line, and the linker
searches for symbol definitions from left to right. This means we can
stop hotpatching operator new and delete in the CRT, which is nice.

I think that the only reason we weren't exporting the symbols already is
because MSVC doesn't allow you to do it directly with
__declspec(dllexport). Instead, we can use
`#pragma comment(linker, "/export:foo")`, which is most of what the
attribute does under the hood. It does mean we have to write down the
mangled names of the operators, but that's not too bad.

llvm-svn: 264190
This commit is contained in:
Reid Kleckner 2016-03-23 20:45:52 +00:00
parent fd55fc86ed
commit 03d703bb62
2 changed files with 17 additions and 18 deletions

View File

@ -174,23 +174,6 @@ void ReplaceSystemMalloc() {
__interception::OverrideFunction("_recalloc_crt", (uptr)_recalloc);
__interception::OverrideFunction("_msize", (uptr)_msize);
__interception::OverrideFunction("_expand", (uptr)_expand);
// Override different versions of 'operator new' and 'operator delete'.
// No need to override the nothrow versions as they just wrap the throw
// versions.
// FIXME: Unfortunately, MSVC miscompiles the statements that take the
// addresses of the array versions of these operators,
// see https://connect.microsoft.com/VisualStudio/feedbackdetail/view/946992
// We might want to try to work around this by [inline] assembly or compiling
// parts of the RTL with Clang.
void *(*op_new)(size_t sz) = operator new;
void (*op_delete)(void *p) = operator delete;
void *(*op_array_new)(size_t sz) = operator new[];
void (*op_array_delete)(void *p) = operator delete[];
__interception::OverrideFunction("??2@YAPAXI@Z", (uptr)op_new);
__interception::OverrideFunction("??3@YAXPAX@Z", (uptr)op_delete);
__interception::OverrideFunction("??_U@YAPAXI@Z", (uptr)op_array_new);
__interception::OverrideFunction("??_V@YAXPAX@Z", (uptr)op_array_delete);
#endif
}
} // namespace __asan

View File

@ -20,9 +20,25 @@
#include <stddef.h>
// C++ operators can't have visibility attributes on Windows.
// C++ operators can't have dllexport attributes on Windows. We export them
// anyway by passing extra -export flags to the linker, which is exactly that
// dllexport would normally do. We need to export them in order to make the
// VS2015 dynamic CRT (MD) work.
#if SANITIZER_WINDOWS
# define CXX_OPERATOR_ATTRIBUTE
# ifdef _WIN64
# pragma comment(linker, "/export:??2@YAPEAX_K@Z") // operator new
# pragma comment(linker, "/export:??3@YAXPEAX@Z") // operator delete
# pragma comment(linker, "/export:??3@YAXPEAX_K@Z") // sized operator delete
# pragma comment(linker, "/export:??_U@YAPEAX_K@Z") // operator new[]
# pragma comment(linker, "/export:??_V@YAXPEAX@Z") // operator delete[]
# else
# pragma comment(linker, "/export:??2@YAPAXI@Z") // operator new
# pragma comment(linker, "/export:??3@YAXPAX@Z") // operator delete
# pragma comment(linker, "/export:??3@YAXPAXI@Z") // sized operator delete
# pragma comment(linker, "/export:??_U@YAPAXI@Z") // operator new[]
# pragma comment(linker, "/export:??_V@YAXPAX@Z") // operator delete[]
# endif
#else
# define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
#endif