1+ /* *
2+ * =============================================================================
3+ * DynamicHooks
4+ * Copyright (C) 2015 Robin Gohmert. All rights reserved.
5+ * =============================================================================
6+ *
7+ * This software is provided 'as-is', without any express or implied warranty.
8+ * In no event will the authors be held liable for any damages arising from
9+ * the use of this software.
10+ *
11+ * Permission is granted to anyone to use this software for any purpose,
12+ * including commercial applications, and to alter it and redistribute it
13+ * freely, subject to the following restrictions:
14+ *
15+ * 1. The origin of this software must not be misrepresented; you must not
16+ * claim that you wrote the original software. If you use this software in a
17+ * product, an acknowledgment in the product documentation would be
18+ * appreciated but is not required.
19+ *
20+ * 2. Altered source versions must be plainly marked as such, and must not be
21+ * misrepresented as being the original software.
22+ *
23+ * 3. This notice may not be removed or altered from any source distribution.
24+ *
25+ * asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc
26+ * -fPIC thunks correctly
27+ *
28+ * Idea and trampoline code taken from DynDetours (thanks your-name-here).
29+ */
30+
31+ // ============================================================================
32+ // >> INCLUDES
33+ // ============================================================================
34+ #include " x86MsFastcall.h"
35+ #include < string.h>
36+
37+
38+ // ============================================================================
39+ // >> x86MsFastcall
40+ // ============================================================================
41+ x86MsFastcall::x86MsFastcall (std::vector<DataType_t> vecArgTypes, DataType_t returnType, int iAlignment) :
42+ ICallingConvention(vecArgTypes, returnType, iAlignment)
43+ {
44+ int iSize = GetDataTypeSize (m_returnType);
45+ if (iSize > 4 )
46+ {
47+ m_pReturnBuffer = malloc (iSize);
48+ }
49+ else
50+ {
51+ m_pReturnBuffer = NULL ;
52+ }
53+ }
54+
55+ x86MsFastcall::~x86MsFastcall ()
56+ {
57+ if (m_pReturnBuffer)
58+ {
59+ free (m_pReturnBuffer);
60+ }
61+ }
62+
63+ std::list<Register_t> x86MsFastcall::GetRegisters ()
64+ {
65+ std::list<Register_t> registers;
66+
67+ registers.push_back (ESP );
68+
69+ int iArgSize = m_vecArgTypes.size ();
70+
71+ if (iArgSize > 0 )
72+ {
73+ registers.push_back (ECX );
74+ }
75+
76+ if (iArgSize > 1 )
77+ {
78+ registers.push_back (EDX );
79+ }
80+
81+ if (m_returnType == DATA_TYPE_FLOAT || m_returnType == DATA_TYPE_DOUBLE )
82+ {
83+ registers.push_back (ST0 );
84+ }
85+ else
86+ {
87+ registers.push_back (EAX );
88+ if (m_pReturnBuffer && iArgSize <= 1 )
89+ {
90+ registers.push_back (EDX );
91+ }
92+ }
93+
94+ return registers;
95+ }
96+
97+ int x86MsFastcall::GetPopSize ()
98+ {
99+ int iPopSize = 0 ;
100+
101+ for (unsigned int i=2 ; i <= m_vecArgTypes.size () - 1 ; i++)
102+ {
103+ iPopSize += GetDataTypeSize (m_vecArgTypes[i], m_iAlignment);
104+ }
105+
106+ return iPopSize;
107+ }
108+
109+ void * x86MsFastcall::GetArgumentPtr (int iIndex, CRegisters* pRegisters)
110+ {
111+ if (iIndex == 0 )
112+ {
113+ return pRegisters->m_ecx ->m_pAddress ;
114+ }
115+
116+ if (iIndex == 1 )
117+ {
118+ return pRegisters->m_edx ->m_pAddress ;
119+ }
120+
121+ int iOffset = 4 ;
122+ for (int i=2 ; i < iIndex; i++)
123+ {
124+ iOffset += GetDataTypeSize (m_vecArgTypes[i], m_iAlignment);
125+ }
126+
127+ return (void *) (pRegisters->m_esp ->GetValue <unsigned long >() + iOffset);
128+ }
129+
130+ void x86MsFastcall::ArgumentPtrChanged (int iIndex, CRegisters* pRegisters, void * pArgumentPtr)
131+ {
132+ }
133+
134+ void * x86MsFastcall::GetReturnPtr (CRegisters* pRegisters)
135+ {
136+ if (m_returnType == DATA_TYPE_FLOAT || m_returnType == DATA_TYPE_DOUBLE )
137+ return pRegisters->m_st0 ->m_pAddress ;
138+
139+ if (m_pReturnBuffer)
140+ {
141+ // First half in eax, second half in edx
142+ memcpy (m_pReturnBuffer, pRegisters->m_eax , 4 );
143+ memcpy ((void *) ((unsigned long ) m_pReturnBuffer + 4 ), pRegisters->m_edx , 4 );
144+ return m_pReturnBuffer;
145+ }
146+
147+ return pRegisters->m_eax ->m_pAddress ;
148+ }
149+
150+ void x86MsFastcall::ReturnPtrChanged (CRegisters* pRegisters, void * pReturnPtr)
151+ {
152+ if (m_returnType == DATA_TYPE_FLOAT || m_returnType == DATA_TYPE_DOUBLE )
153+ return ;
154+
155+ if (m_pReturnBuffer)
156+ {
157+ // First half in eax, second half in edx
158+ memcpy (pRegisters->m_eax , m_pReturnBuffer, 4 );
159+ memcpy (pRegisters->m_edx , (void *) ((unsigned long ) m_pReturnBuffer + 4 ), 4 );
160+ }
161+ }
0 commit comments