diff options
Diffstat (limited to 'libsanitizer/interception')
-rw-r--r-- | libsanitizer/interception/interception.h | 22 | ||||
-rw-r--r-- | libsanitizer/interception/interception_win.cc | 47 | ||||
-rw-r--r-- | libsanitizer/interception/interception_win.h | 32 |
3 files changed, 62 insertions, 39 deletions
diff --git a/libsanitizer/interception/interception.h b/libsanitizer/interception/interception.h index 51505e1..458928f 100644 --- a/libsanitizer/interception/interception.h +++ b/libsanitizer/interception/interception.h @@ -120,19 +120,23 @@ const interpose_substitution substitution_##func_name[] \ # define DECLARE_WRAPPER(ret_type, func, ...) #elif defined(_WIN32) -# if defined(_DLL) // DLL CRT -# define WRAP(x) x -# define WRAPPER_NAME(x) #x -# define INTERCEPTOR_ATTRIBUTE -# else // Static CRT -# define WRAP(x) wrap_##x -# define WRAPPER_NAME(x) "wrap_"#x -# define INTERCEPTOR_ATTRIBUTE -# endif +# define WRAP(x) __asan_wrap_##x +# define WRAPPER_NAME(x) "__asan_wrap_"#x +# define INTERCEPTOR_ATTRIBUTE __declspec(dllexport) # define DECLARE_WRAPPER(ret_type, func, ...) \ extern "C" ret_type func(__VA_ARGS__); # define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \ extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__); +#elif defined(__FreeBSD__) +# define WRAP(x) __interceptor_ ## x +# define WRAPPER_NAME(x) "__interceptor_" #x +# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) +// FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher +// priority than weak ones so weak aliases won't work for indirect calls +// in position-independent (-fPIC / -fPIE) mode. +# define DECLARE_WRAPPER(ret_type, func, ...) \ + extern "C" ret_type func(__VA_ARGS__) \ + __attribute__((alias("__interceptor_" #func), visibility("default"))); #else # define WRAP(x) __interceptor_ ## x # define WRAPPER_NAME(x) "__interceptor_" #x diff --git a/libsanitizer/interception/interception_win.cc b/libsanitizer/interception/interception_win.cc index 9cd7175..1642bd1 100644 --- a/libsanitizer/interception/interception_win.cc +++ b/libsanitizer/interception/interception_win.cc @@ -17,20 +17,6 @@ namespace __interception { -bool GetRealFunctionAddress(const char *func_name, uptr *func_addr) { - const char *DLLS[] = { - "msvcr80.dll", - "msvcr90.dll", - "kernel32.dll", - NULL - }; - *func_addr = 0; - for (size_t i = 0; *func_addr == 0 && DLLS[i]; ++i) { - *func_addr = (uptr)GetProcAddress(GetModuleHandleA(DLLS[i]), func_name); - } - return (*func_addr != 0); -} - // FIXME: internal_str* and internal_mem* functions should be moved from the // ASan sources into interception/. @@ -108,9 +94,11 @@ static size_t RoundUpToInstrBoundary(size_t size, char *code) { case 0x458B: // 8B 45 XX = mov eax, dword ptr [ebp+XXh] case 0x5D8B: // 8B 5D XX = mov ebx, dword ptr [ebp+XXh] case 0xEC83: // 83 EC XX = sub esp, XX + case 0x75FF: // FF 75 XX = push dword ptr [ebp+XXh] cursor += 3; continue; case 0xC1F7: // F7 C1 XX YY ZZ WW = test ecx, WWZZYYXX + case 0x25FF: // FF 25 XX YY ZZ WW = jmp dword ptr ds:[WWZZYYXX] cursor += 6; continue; case 0x3D83: // 83 3D XX YY ZZ WW TT = cmp TT, WWZZYYXX @@ -119,6 +107,7 @@ static size_t RoundUpToInstrBoundary(size_t size, char *code) { } switch (0x00FFFFFF & *(unsigned int*)(code + cursor)) { case 0x24448A: // 8A 44 24 XX = mov eal, dword ptr [esp+XXh] + case 0x24448B: // 8B 44 24 XX = mov eax, dword ptr [esp+XXh] case 0x244C8B: // 8B 4C 24 XX = mov ecx, dword ptr [esp+XXh] case 0x24548B: // 8B 54 24 XX = mov edx, dword ptr [esp+XXh] case 0x24748B: // 8B 74 24 XX = mov esi, dword ptr [esp+XXh] @@ -131,8 +120,9 @@ static size_t RoundUpToInstrBoundary(size_t size, char *code) { // FIXME: Unknown instruction failures might happen when we add a new // interceptor or a new compiler version. In either case, they should result // in visible and readable error messages. However, merely calling abort() - // or __debugbreak() leads to an infinite recursion in CheckFailed. + // leads to an infinite recursion in CheckFailed. // Do we have a good way to abort with an error message here? + __debugbreak(); return 0; } @@ -189,6 +179,33 @@ bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func) { return true; } +static const void **InterestingDLLsAvailable() { + const char *InterestingDLLs[] = { "kernel32.dll", "msvcr120.dll", NULL }; + static void *result[ARRAY_SIZE(InterestingDLLs)] = { 0 }; + if (!result[0]) { + for (size_t i = 0, j = 0; InterestingDLLs[i]; ++i) { + if (HMODULE h = GetModuleHandleA(InterestingDLLs[i])) + result[j++] = (void *)h; + } + } + return (const void **)&result[0]; +} + +static bool GetFunctionAddressInDLLs(const char *func_name, uptr *func_addr) { + *func_addr = 0; + const void **DLLs = InterestingDLLsAvailable(); + for (size_t i = 0; *func_addr == 0 && DLLs[i]; ++i) + *func_addr = (uptr)GetProcAddress((HMODULE)DLLs[i], func_name); + return (*func_addr != 0); +} + +bool OverrideFunction(const char *name, uptr new_func, uptr *orig_old_func) { + uptr orig_func; + if (!GetFunctionAddressInDLLs(name, &orig_func)) + return false; + return OverrideFunction(orig_func, new_func, orig_old_func); +} + } // namespace __interception #endif // _WIN32 diff --git a/libsanitizer/interception/interception_win.h b/libsanitizer/interception/interception_win.h index b46ad0d..e9c6200 100644 --- a/libsanitizer/interception/interception_win.h +++ b/libsanitizer/interception/interception_win.h @@ -20,27 +20,29 @@ #define INTERCEPTION_WIN_H namespace __interception { -// returns true if a function with the given name was found. -bool GetRealFunctionAddress(const char *func_name, uptr *func_addr); +// All the functions in the OverrideFunction() family return true on success, +// false on failure (including "couldn't find the function"). -// returns true if the old function existed, false on failure. -bool OverrideFunction(uptr old_func, uptr new_func, uptr *orig_old_func); +// Overrides a function by its address. +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); } // namespace __interception -#if defined(_DLL) -# define INTERCEPT_FUNCTION_WIN(func) \ - ::__interception::GetRealFunctionAddress( \ - #func, (::__interception::uptr*)&REAL(func)) +#if defined(INTERCEPTION_DYNAMIC_CRT) +#define INTERCEPT_FUNCTION_WIN(func) \ + ::__interception::OverrideFunction(#func, \ + (::__interception::uptr)WRAP(func), \ + (::__interception::uptr *)&REAL(func)) #else -# define INTERCEPT_FUNCTION_WIN(func) \ - ::__interception::OverrideFunction( \ - (::__interception::uptr)func, \ - (::__interception::uptr)WRAP(func), \ - (::__interception::uptr*)&REAL(func)) +#define INTERCEPT_FUNCTION_WIN(func) \ + ::__interception::OverrideFunction((::__interception::uptr)func, \ + (::__interception::uptr)WRAP(func), \ + (::__interception::uptr *)&REAL(func)) #endif -#define INTERCEPT_FUNCTION_VER_WIN(func, symver) \ - INTERCEPT_FUNCTION_WIN(func) +#define INTERCEPT_FUNCTION_VER_WIN(func, symver) INTERCEPT_FUNCTION_WIN(func) #endif // INTERCEPTION_WIN_H #endif // _WIN32 |