summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-08-30 19:28:53 +0400
committerAlexander Gavrilov2012-08-30 19:28:53 +0400
commit750eefe48ad3250cc51682508cc30e78accff7e1 (patch)
tree31c8696b98db360815131b9efa7f781a84f1e909 /library
parentc414aafc593acf7a4a2b6f38297667c6f06f7ede (diff)
downloaddfhack-750eefe48ad3250cc51682508cc30e78accff7e1.tar.gz
dfhack-750eefe48ad3250cc51682508cc30e78accff7e1.tar.bz2
dfhack-750eefe48ad3250cc51682508cc30e78accff7e1.tar.xz
Follow unconditional JMP chains in MSVC vmethod ptr detection.
Diffstat (limited to 'library')
-rw-r--r--library/VTableInterpose.cpp24
1 files changed, 22 insertions, 2 deletions
diff --git a/library/VTableInterpose.cpp b/library/VTableInterpose.cpp
index 04c436ba..079890fe 100644
--- a/library/VTableInterpose.cpp
+++ b/library/VTableInterpose.cpp
@@ -48,6 +48,26 @@ struct MSVC_MPTR {
intptr_t this_shift;
};
+static uint32_t *follow_jmp(void *ptr)
+{
+ uint8_t *p = (uint8_t*)ptr;
+
+ for (;;)
+ {
+ switch (*p)
+ {
+ case 0xE9:
+ p += 5 + *(int32_t*)(p+1);
+ break;
+ case 0xEB:
+ p += 2 + *(int8_t*)(p+1);
+ break;
+ default:
+ return (uint32_t*)p;
+ }
+ }
+}
+
bool DFHack::is_vmethod_pointer_(void *pptr)
{
auto pobj = (MSVC_MPTR*)pptr;
@@ -55,7 +75,7 @@ bool DFHack::is_vmethod_pointer_(void *pptr)
// MSVC implements pointers to vmethods via thunks.
// This expects that they all follow a very specific pattern.
- auto pval = (unsigned*)pobj->method;
+ auto pval = follow_jmp(pobj->method);
switch (pval[0]) {
case 0x20FF018BU: // mov eax, [ecx]; jmp [eax]
case 0x60FF018BU: // mov eax, [ecx]; jmp [eax+0x??]
@@ -71,7 +91,7 @@ int DFHack::vmethod_pointer_to_idx_(void *pptr)
auto pobj = (MSVC_MPTR*)pptr;
if (!pobj->method || pobj->this_shift != 0) return -1;
- auto pval = (unsigned*)pobj->method;
+ auto pval = follow_jmp(pobj->method);
switch (pval[0]) {
case 0x20FF018BU: // mov eax, [ecx]; jmp [eax]
return 0;