summaryrefslogtreecommitdiff
path: root/libsanitizer/interception
diff options
context:
space:
mode:
authorMax Ostapenko <m.ostapenko@partner.samsung.com>2015-10-21 10:32:45 +0300
committerMaxim Ostapenko <chefmax@gcc.gnu.org>2015-10-21 10:32:45 +0300
commit696d846a56cc12549f080c6c87e6a0272bdb29f1 (patch)
tree2bdaf703dd35e1806b59bd7d74c7eee290a1054f /libsanitizer/interception
parent013a8899f5d9469a835cf1f6ccb1b29f69344959 (diff)
libsanitizer merge from upstream r250806.
libsanitizer/ 2015-10-20 Maxim Ostapenko <m.ostapenko@partner.samsung.com> * All source files: Merge from upstream r250806. * configure.ac (link_sanitizer_common): Add -lrt flag. * configure.tgt: Enable TSAN and LSAN for aarch64-linux targets. Set CXX_ABI_NEEDED=true for darwin. * asan/Makefile.am (asan_files): Add new files. (DEFS): Add DCAN_SANITIZE_UB=0 and remove unused and legacy DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0. * asan/Makefile.in: Regenerate. * ubsan/Makefile.am (ubsan_files): Add new files. (DEFS): Add DCAN_SANITIZE_UB=1. (libubsan_la_LIBADD): Add -lc++abi if CXX_ABI_NEEDED is true. * ubsan/Makefile.in: Regenerate. * tsan/Makefile.am (tsan_files): Add new files. (DEFS): Add DCAN_SANITIZE_UB=0. * tsan/Makefile.in: Regenerate. * sanitizer_common/Makefile.am (sanitizer_common_files): Add new files. * sanitizer_common/Makefile.in: Regenerate. * asan/libtool-version: Bump the libasan SONAME. From-SVN: r229111
Diffstat (limited to 'libsanitizer/interception')
-rw-r--r--libsanitizer/interception/interception.h1
-rw-r--r--libsanitizer/interception/interception_linux.h10
-rw-r--r--libsanitizer/interception/interception_win.cc72
-rw-r--r--libsanitizer/interception/interception_win.h4
4 files changed, 73 insertions, 14 deletions
diff --git a/libsanitizer/interception/interception.h b/libsanitizer/interception/interception.h
index 458928f14b1..f2d48c9332f 100644
--- a/libsanitizer/interception/interception.h
+++ b/libsanitizer/interception/interception.h
@@ -217,7 +217,6 @@ const interpose_substitution substitution_##func_name[] \
namespace __interception { \
FUNC_TYPE(func) PTR_TO_REAL(func); \
} \
- DECLARE_WRAPPER_WINAPI(ret_type, func, __VA_ARGS__) \
extern "C" \
INTERCEPTOR_ATTRIBUTE \
ret_type __stdcall WRAP(func)(__VA_ARGS__)
diff --git a/libsanitizer/interception/interception_linux.h b/libsanitizer/interception/interception_linux.h
index e2cc4c19dff..61bf48a7233 100644
--- a/libsanitizer/interception/interception_linux.h
+++ b/libsanitizer/interception/interception_linux.h
@@ -33,12 +33,12 @@ void *GetFuncAddrVer(const char *func_name, const char *ver);
(::__interception::uptr) & WRAP(func))
#if !defined(__ANDROID__) // android does not have dlvsym
-# define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
- ::__interception::real_##func = (func##_f)(unsigned long) \
- ::__interception::GetFuncAddrVer(#func, symver)
+#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+ (::__interception::real_##func = (func##_f)( \
+ unsigned long)::__interception::GetFuncAddrVer(#func, symver))
#else
-# define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
- INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
+#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+ INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
#endif // !defined(__ANDROID__)
#endif // INTERCEPTION_LINUX_H
diff --git a/libsanitizer/interception/interception_win.cc b/libsanitizer/interception/interception_win.cc
index f9c2e9b3ad8..24784c73ded 100644
--- a/libsanitizer/interception/interception_win.cc
+++ b/libsanitizer/interception/interception_win.cc
@@ -82,6 +82,7 @@ static size_t RoundUpToInstrBoundary(size_t size, char *code) {
cursor += 2;
continue;
case '\xE9': // E9 XX YY ZZ WW = jmp WWZZYYXX
+ case '\xB8': // B8 XX YY ZZ WW = mov eax, WWZZYYXX
cursor += 5;
continue;
}
@@ -179,11 +180,15 @@ bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func) {
return true;
}
-static const void **InterestingDLLsAvailable() {
- const char *InterestingDLLs[] = {"kernel32.dll",
- "msvcr110.dll", // VS2012
- "msvcr120.dll", // VS2013
- NULL};
+static void **InterestingDLLsAvailable() {
+ const char *InterestingDLLs[] = {
+ "kernel32.dll",
+ "msvcr110.dll", // VS2012
+ "msvcr120.dll", // VS2013
+ // NTDLL should go last as it exports some functions that we should override
+ // in the CRT [presumably only used internally].
+ "ntdll.dll", NULL
+ };
static void *result[ARRAY_SIZE(InterestingDLLs)] = { 0 };
if (!result[0]) {
for (size_t i = 0, j = 0; InterestingDLLs[i]; ++i) {
@@ -191,14 +196,65 @@ static const void **InterestingDLLsAvailable() {
result[j++] = (void *)h;
}
}
- return (const void **)&result[0];
+ return &result[0];
+}
+
+namespace {
+// Utility for reading loaded PE images.
+template <typename T> class RVAPtr {
+ public:
+ RVAPtr(void *module, uptr rva)
+ : ptr_(reinterpret_cast<T *>(reinterpret_cast<char *>(module) + rva)) {}
+ operator T *() { return ptr_; }
+ T *operator->() { return ptr_; }
+ T *operator++() { return ++ptr_; }
+
+ private:
+ T *ptr_;
+};
+} // namespace
+
+// Internal implementation of GetProcAddress. At least since Windows 8,
+// GetProcAddress appears to initialize DLLs before returning function pointers
+// into them. This is problematic for the sanitizers, because they typically
+// want to intercept malloc *before* MSVCRT initializes. Our internal
+// implementation walks the export list manually without doing initialization.
+uptr InternalGetProcAddress(void *module, const char *func_name) {
+ // Check that the module header is full and present.
+ RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
+ RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
+ if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
+ headers->Signature != IMAGE_NT_SIGNATURE || // "PE\0\0"
+ headers->FileHeader.SizeOfOptionalHeader <
+ sizeof(IMAGE_OPTIONAL_HEADER)) {
+ return 0;
+ }
+
+ IMAGE_DATA_DIRECTORY *export_directory =
+ &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+ RVAPtr<IMAGE_EXPORT_DIRECTORY> exports(module,
+ export_directory->VirtualAddress);
+ RVAPtr<DWORD> functions(module, exports->AddressOfFunctions);
+ RVAPtr<DWORD> names(module, exports->AddressOfNames);
+ RVAPtr<WORD> ordinals(module, exports->AddressOfNameOrdinals);
+
+ for (DWORD i = 0; i < exports->NumberOfNames; i++) {
+ RVAPtr<char> name(module, names[i]);
+ if (!strcmp(func_name, name)) {
+ DWORD index = ordinals[i];
+ RVAPtr<char> func(module, functions[index]);
+ return (uptr)(char *)func;
+ }
+ }
+
+ return 0;
}
static bool GetFunctionAddressInDLLs(const char *func_name, uptr *func_addr) {
*func_addr = 0;
- const void **DLLs = InterestingDLLsAvailable();
+ void **DLLs = InterestingDLLsAvailable();
for (size_t i = 0; *func_addr == 0 && DLLs[i]; ++i)
- *func_addr = (uptr)GetProcAddress((HMODULE)DLLs[i], func_name);
+ *func_addr = InternalGetProcAddress(DLLs[i], func_name);
return (*func_addr != 0);
}
diff --git a/libsanitizer/interception/interception_win.h b/libsanitizer/interception/interception_win.h
index e9c6200d1b2..6388209dcc1 100644
--- a/libsanitizer/interception/interception_win.h
+++ b/libsanitizer/interception/interception_win.h
@@ -28,6 +28,10 @@ bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func = 0);
// Overrides a function in a system DLL or DLL CRT by its exported name.
bool OverrideFunction(const char *name, uptr new_func, uptr *orig_old_func = 0);
+
+// Windows-only replacement for GetProcAddress. Useful for some sanitizers.
+uptr InternalGetProcAddress(void *module, const char *func_name);
+
} // namespace __interception
#if defined(INTERCEPTION_DYNAMIC_CRT)