Follow unconditional JMP chains in MSVC vmethod ptr detection.

develop
Alexander Gavrilov 2012-08-30 19:28:53 +04:00
parent c414aafc59
commit 750eefe48a
1 changed files with 22 additions and 2 deletions

@ -48,6 +48,26 @@ struct MSVC_MPTR {
intptr_t this_shift; 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) bool DFHack::is_vmethod_pointer_(void *pptr)
{ {
auto pobj = (MSVC_MPTR*)pptr; auto pobj = (MSVC_MPTR*)pptr;
@ -55,7 +75,7 @@ bool DFHack::is_vmethod_pointer_(void *pptr)
// MSVC implements pointers to vmethods via thunks. // MSVC implements pointers to vmethods via thunks.
// This expects that they all follow a very specific pattern. // This expects that they all follow a very specific pattern.
auto pval = (unsigned*)pobj->method; auto pval = follow_jmp(pobj->method);
switch (pval[0]) { switch (pval[0]) {
case 0x20FF018BU: // mov eax, [ecx]; jmp [eax] case 0x20FF018BU: // mov eax, [ecx]; jmp [eax]
case 0x60FF018BU: // mov eax, [ecx]; jmp [eax+0x??] 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; auto pobj = (MSVC_MPTR*)pptr;
if (!pobj->method || pobj->this_shift != 0) return -1; if (!pobj->method || pobj->this_shift != 0) return -1;
auto pval = (unsigned*)pobj->method; auto pval = follow_jmp(pobj->method);
switch (pval[0]) { switch (pval[0]) {
case 0x20FF018BU: // mov eax, [ecx]; jmp [eax] case 0x20FF018BU: // mov eax, [ecx]; jmp [eax]
return 0; return 0;