Reputation: 51
My understanding is that ATL implements its window "thunks" using some clever assembly language hacks (see this question, for example).
I'm wondering whether these thunks (and really any similar thunks, for that matter) will work cross-platform. I've had access only to a x64 machine so far, so I was wondering, in particular, whether ATL would work on ARM64 processors.
Thanks for any insight.
Upvotes: 1
Views: 91
Reputation: 51
Actually, upon further investigation, it appears from the source that ATL does some conditional compilation for various platforms, including ARM64:
#elif defined(_M_ARM64)
PVOID __stdcall __AllocStdCallThunk(VOID);
VOID __stdcall __FreeStdCallThunk(PVOID);
#pragma pack(push,4)
struct _stdcallthunk {
ULONG m_ldr_r16; // ldr x16, [pc, #24]
ULONG m_ldr_r0; // ldr x0, [pc, #12]
ULONG m_br; // br x16
ULONG m_pad;
ULONG64 m_pThis;
ULONG64 m_pFunc;
BOOL Init(DWORD_PTR proc, void* pThis) {
m_ldr_r16 = 0x580000D0;
m_ldr_r0 = 0x58000060;
m_br = 0xd61f0200;
m_pThis = (ULONG64)pThis;
m_pFunc = (ULONG64)proc;
// write block from data cache and
// flush from instruction cache
FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
return TRUE;
}
void* GetCodeAddress() {
return this;
}
void* operator new(size_t)
{
return __AllocStdCallThunk();
}
void operator delete(void* pThunk) {
__FreeStdCallThunk(pThunk);
}
};
Upvotes: 4
Reputation: 365517
It looks like the asm is just overwriting the first arg with a different pointer, then tailcalling another function by jumping to it. This is doable in any calling convention for any ISA.
But of course the machine-code byte sequence for doing that depends on the ISA and the calling convention (e.g. which register or stack location holds the first arg).
Upvotes: 0