diff options
Diffstat (limited to 'compiler-rt/lib/interception/interception_win.cpp')
| -rw-r--r-- | compiler-rt/lib/interception/interception_win.cpp | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index dc3018a675de..bd85c50a083a 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -213,6 +213,18 @@ static char* _strchr(char* str, char c) { return nullptr; } +static int _strcmp(const char *s1, const char *s2) { + while (true) { + unsigned c1 = *s1; + unsigned c2 = *s2; + if (c1 != c2) return (c1 < c2) ? -1 : 1; + if (c1 == 0) break; + s1++; + s2++; + } + return 0; +} + static void _memset(void *p, int value, size_t sz) { for (size_t i = 0; i < sz; ++i) ((char*)p)[i] = (char)value; @@ -418,7 +430,7 @@ static void *AllocateTrampolineRegion(uptr min_addr, uptr max_addr, ReportError( "interception_win: AllocateTrampolineRegion failed to find free memory; " "min_addr: %p, max_addr: %p, func_addr: %p, granularity: %zu\n", - (void *)min_addr, (void *)max_addr, granularity); + (void *)min_addr, (void *)max_addr, (void *)func_addr, granularity); return nullptr; #else return ::VirtualAlloc(nullptr, @@ -634,15 +646,17 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0xD284: // 84 D2 : test dl,dl return 2; + case 0xE483: // 83 E4 XX : and esp, XX + case 0xEC83: // 83 EC XX : sub esp, XX + case 0xC1F6: // F6 C1 XX : test cl, XX + return 3; + // Cannot overwrite control-instruction. Return 0 to indicate failure. case 0x25FF: // FF 25 XX YY ZZ WW : jmp dword ptr ds:[WWZZYYXX] return 0; } - switch (0x00FFFFFF & *(u32*)address) { - case 0xF8E483: // 83 E4 F8 : and esp, 0xFFFFFFF8 - case 0x64EC83: // 83 EC 64 : sub esp, 64h - return 3; + switch (0x00FFFFFF & *(u32 *)address) { case 0x24A48D: // 8D A4 24 XX XX XX XX : lea esp, [esp + XX XX XX XX] return 7; } @@ -723,8 +737,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { return 7; } - switch (0x00FFFFFF & *(u32*)address) { - case 0x07c1f6: // f6 c1 07 : test cl, 0x7 + switch (0x00FFFFFF & *(u32 *)address) { case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax] case 0xc00b4d: // 4d 0b c0 : or r8, r8 case 0xc03345: // 45 33 c0 : xor r8d, r8d @@ -772,7 +785,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0xdb8548: // 48 85 db : test rbx, rbx case 0xdb854d: // 4d 85 db : test r11, r11 case 0xdc8b4c: // 4c 8b dc : mov r11, rsp - case 0xe0e483: // 83 e4 e0 : and esp, 0xFFFFFFE0 case 0xe48548: // 48 85 e4 : test rsp, rsp case 0xe4854d: // 4d 85 e4 : test r12, r12 case 0xe58948: // 48 89 e5 : mov rbp, rsp @@ -808,7 +820,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x798141: // 41 81 79 XX YY YY YY YY : cmp DWORD PTR [r9+YY], XX XX XX XX case 0x7a8141: // 41 81 7a XX YY YY YY YY : cmp DWORD PTR [r10+YY], XX XX XX XX case 0x7b8141: // 41 81 7b XX YY YY YY YY : cmp DWORD PTR [r11+YY], XX XX XX XX - case 0x7c8141: // 41 81 7c XX YY YY YY YY : cmp DWORD PTR [r12+YY], XX XX XX XX case 0x7d8141: // 41 81 7d XX YY YY YY YY : cmp DWORD PTR [r13+YY], XX XX XX XX case 0x7e8141: // 41 81 7e XX YY YY YY YY : cmp DWORD PTR [r14+YY], XX XX XX XX case 0x7f8141: // 41 81 7f YY XX XX XX XX : cmp DWORD PTR [r15+YY], XX XX XX XX @@ -835,6 +846,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x2444c7: // C7 44 24 XX YY YY YY YY // mov dword ptr [rsp + XX], YYYYYYYY return 8; + + case 0x7c8141: // 41 81 7c ZZ YY XX XX XX XX + // cmp DWORD PTR [reg+reg*n+YY], XX XX XX XX + return 9; } switch (*(u32*)(address)) { @@ -868,7 +883,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x5D8B: // 8B 5D XX : mov ebx, dword ptr [ebp + XX] case 0x7D8B: // 8B 7D XX : mov edi, dword ptr [ebp + XX] case 0x758B: // 8B 75 XX : mov esi, dword ptr [ebp + XX] - case 0xEC83: // 83 EC XX : sub esp, XX case 0x75FF: // FF 75 XX : push dword ptr [ebp + XX] return 3; case 0xC1F7: // F7 C1 XX YY ZZ WW : test ecx, WWZZYYXX @@ -1175,8 +1189,7 @@ static void **InterestingDLLsAvailable() { "libc++.dll", // libc++ "libunwind.dll", // libunwind # endif - // NTDLL should go last as it exports some functions that we should - // override in the CRT [presumably only used internally]. + // NTDLL must go last as it gets special treatment in OverrideFunction. "ntdll.dll", NULL }; @@ -1233,7 +1246,7 @@ uptr InternalGetProcAddress(void *module, const char *func_name) { for (DWORD i = 0; i < exports->NumberOfNames; i++) { RVAPtr<char> name(module, names[i]); - if (!strcmp(func_name, name)) { + if (!_strcmp(func_name, name)) { DWORD index = ordinals[i]; RVAPtr<char> func(module, functions[index]); @@ -1247,7 +1260,7 @@ uptr InternalGetProcAddress(void *module, const char *func_name) { char function_name[256]; size_t funtion_name_length = _strlen(func); if (funtion_name_length >= sizeof(function_name) - 1) { - ReportError("interception_win: func too long: '%s'\n", func); + ReportError("interception_win: func too long: '%s'\n", (char *)func); InterceptionFailed(); } @@ -1279,9 +1292,22 @@ uptr InternalGetProcAddress(void *module, const char *func_name) { bool OverrideFunction( const char *func_name, uptr new_func, uptr *orig_old_func) { + static const char *kNtDllIgnore[] = { + "memcmp", "memcpy", "memmove", "memset" + }; + bool hooked = false; void **DLLs = InterestingDLLsAvailable(); for (size_t i = 0; DLLs[i]; ++i) { + if (DLLs[i + 1] == nullptr) { + // This is the last DLL, i.e. NTDLL. It exports some functions that + // we only want to override in the CRT. + for (const char *ignored : kNtDllIgnore) { + if (_strcmp(func_name, ignored) == 0) + return hooked; + } + } + uptr func_addr = InternalGetProcAddress(DLLs[i], func_name); if (func_addr && OverrideFunction(func_addr, new_func, orig_old_func)) { @@ -1335,7 +1361,7 @@ bool OverrideImportedFunction(const char *module_to_patch, RVAPtr<IMAGE_IMPORT_BY_NAME> import_by_name( module, name_table->u1.ForwarderString); const char *funcname = &import_by_name->Name[0]; - if (strcmp(funcname, function_name) == 0) + if (_strcmp(funcname, function_name) == 0) break; } } |
