I've been looking around at various DLLs on my computer lately and I thought a decent place to start was the image entry point (typically _DllMainCRTStartup).
From what I can see of the CRT source code (MSVC) this calls another function (__DllMainCRTStartup) with the same arguments (HMODULE, DWORD, LPVOID). However many of the binaries I've looked at seem to deviate from this:
push dword ptr [ebp+8]
mov ecx,dword ptr [ebp+10h]
mov edx,dword ptr [ebp+0Ch]
call 10024E5B // __DllMainCRTStartup
This looks to be pushing on the first parameter (HMODULE) and then passing the other two via registers ecx/edx. The function being called expects them to be there as well. What I expected to see was all three being pushed on the stack which I believe is how the _cdecl convention works. This is an example:
push dword ptr [ebp+10h]
push dword ptr [ebp+0Ch]
push dword ptr [ebp+8]
call 3DC40E2E // __DllMainCRTStartup
Does anyone know where the first variant is coming from? Is it an older version of the CRT? Or maybe a different compiler entirely? Bonus if you know what kind of calling convention it is as well, looks like a strange cousin of __fastcall to me!
Thanks very much!
Edit:
Thought I'd add the function prototype from the CRT source code (the version that comes with VS 2012 at least)
__declspec(noinline)
BOOL __cdecl
__DllMainCRTStartup(
HANDLE hDllHandle,
DWORD dwReason,
LPVOID lpreserved
)
Editx2:
I've just seen the 'Related' link: What x86 calling convention passes first parameter via ESI?
It seems this might be a result of LTCG and the linker basically just deciding to do whatever it likes because it knows about all the components!