summaryrefslogtreecommitdiff
path: root/compiler-rt/lib/interception/interception_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/interception/interception_win.cpp')
-rw-r--r--compiler-rt/lib/interception/interception_win.cpp56
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;
}
}