1
+ /* *
2
+ * =============================================================================
3
+ * Source Python
4
+ * Copyright (C) 2012 Source Python Development Team. All rights reserved.
5
+ * =============================================================================
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify it under
8
+ * the terms of the GNU General Public License, version 3.0, as published by the
9
+ * Free Software Foundation.
10
+ *
11
+ * This program is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ * details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License along with
17
+ * this program. If not, see <http://www.gnu.org/licenses/>.
18
+ *
19
+ * As a special exception, the Source Python Team gives you permission
20
+ * to link the code of this program (as well as its derivative works) to
21
+ * "Half-Life 2," the "Source Engine," and any Game MODs that run on software
22
+ * by the Valve Corporation. You must obey the GNU General Public License in
23
+ * all respects for all other code used. Additionally, the Source.Python
24
+ * Development Team grants this exception to all derivative works.
25
+ */
26
+
27
+ // ============================================================================
28
+ // >> INCLUDES
29
+ // ============================================================================
30
+ #include " memory_callback.h"
31
+ #include " utility/wrap_macros.h"
32
+
33
+ #include " AsmJit.h"
34
+ using namespace AsmJit ;
35
+
36
+ #include " utilities.h"
37
+ #include " DynamicHooks.h"
38
+ using namespace DynamicHooks ;
39
+
40
+
41
+ // ============================================================================
42
+ // >> CLASSES
43
+ // ============================================================================
44
+ #define GET_CALLBACK_CALLER (type ) \
45
+ GET_FUNCTION (type, CallbackCaller<type>, CCallback*, unsigned long , unsigned long )
46
+
47
+ CCallback::CCallback(object oCallback, Convention_t eConv, char * szParams)
48
+ : CFunction(NULL , eConv, szParams)
49
+ {
50
+ m_eConv = eConv;
51
+ m_oCallback = oCallback;
52
+
53
+ // Parse the parameter string
54
+ m_pParams = new Param_t;
55
+ m_pRetParam = new Param_t;
56
+ ParseParams (eConv, szParams, m_pParams, m_pRetParam);
57
+
58
+ // Find the proper callback caller function
59
+ void * pCallCallbackFunc = NULL ;
60
+ switch (m_pRetParam->m_cParam )
61
+ {
62
+ case SIGCHAR_VOID: pCallCallbackFunc = GET_CALLBACK_CALLER (void ); break ;
63
+ case SIGCHAR_BOOL: pCallCallbackFunc = GET_CALLBACK_CALLER (bool ); break ;
64
+ case SIGCHAR_CHAR: pCallCallbackFunc = GET_CALLBACK_CALLER (char ); break ;
65
+ case SIGCHAR_UCHAR: pCallCallbackFunc = GET_CALLBACK_CALLER (unsigned char ); break ;
66
+ case SIGCHAR_SHORT: pCallCallbackFunc = GET_CALLBACK_CALLER (short ); break ;
67
+ case SIGCHAR_USHORT: pCallCallbackFunc = GET_CALLBACK_CALLER (unsigned short ); break ;
68
+ case SIGCHAR_INT: pCallCallbackFunc = GET_CALLBACK_CALLER (int ); break ;
69
+ case SIGCHAR_UINT: pCallCallbackFunc = GET_CALLBACK_CALLER (unsigned int ); break ;
70
+ case SIGCHAR_LONG: pCallCallbackFunc = GET_CALLBACK_CALLER (long ); break ;
71
+ case SIGCHAR_ULONG: pCallCallbackFunc = GET_CALLBACK_CALLER (unsigned long ); break ;
72
+ case SIGCHAR_LONGLONG: pCallCallbackFunc = GET_CALLBACK_CALLER (long long ); break ;
73
+ case SIGCHAR_ULONGLONG: pCallCallbackFunc = GET_CALLBACK_CALLER (unsigned long long ); break ;
74
+ case SIGCHAR_FLOAT: pCallCallbackFunc = GET_CALLBACK_CALLER (float ); break ;
75
+ case SIGCHAR_DOUBLE: pCallCallbackFunc = GET_CALLBACK_CALLER (double ); break ;
76
+ case SIGCHAR_POINTER: pCallCallbackFunc = GET_CALLBACK_CALLER (void *); break ;
77
+ case SIGCHAR_STRING: pCallCallbackFunc = GET_CALLBACK_CALLER (char *); break ;
78
+ default : BOOST_RAISE_EXCEPTION (PyExc_ValueError, " Unknown return type." );
79
+ }
80
+
81
+ // Generate the function
82
+ Assembler a;
83
+
84
+ // Epilog
85
+ a.push (ebp);
86
+ a.mov (ebp, esp);
87
+
88
+ // Call callback caller
89
+ a.push (ecx);
90
+ a.push (ebp);
91
+ a.push (imm ((sysint_t ) this ));
92
+ a.call (pCallCallbackFunc);
93
+ a.add (esp, imm (12 ));
94
+
95
+ // Prolog
96
+ a.mov (esp, ebp);
97
+ a.pop (ebp);
98
+
99
+ // Return
100
+ a.ret (imm (GetPopSize ()));
101
+
102
+ m_ulAddr = (unsigned long ) a.make ();
103
+ }
104
+
105
+ CCallback::~CCallback ()
106
+ {
107
+ delete m_pParams;
108
+ delete m_pRetParam;
109
+ }
110
+
111
+ int CCallback::GetPopSize ()
112
+ {
113
+ #ifdef _WIN32
114
+ if (m_eConv == CONV_THISCALL || m_eConv == CONV_STDCALL)
115
+ {
116
+ Param_t* pParam = GetArgument (GetArgumentCount () - 1 );
117
+ return pParam->m_iOffset + pParam->m_iSize ;
118
+ }
119
+ #endif
120
+ return 0 ;
121
+ }
122
+
123
+ int CCallback::GetArgumentCount ()
124
+ {
125
+ int count = 0 ;
126
+ Param_t* temp = m_pParams;
127
+ while (temp)
128
+ {
129
+ count++;
130
+ temp = temp->m_pNext ;
131
+ }
132
+ return count - 1 ;
133
+ }
134
+
135
+ Param_t* CCallback::GetArgument (int iIndex)
136
+ {
137
+ Param_t* temp = m_pParams;
138
+ while (temp && iIndex > 0 )
139
+ {
140
+ iIndex--;
141
+ temp = temp->m_pNext ;
142
+ }
143
+ return temp;
144
+ }
145
+
146
+ void CCallback::Free ()
147
+ {
148
+ // TODO: Figure out how to use std::free() on the generated code, so we can
149
+ // use Dealloc().
150
+ MemoryManager::getGlobal ()->free ((void *) m_ulAddr);
151
+ m_ulAddr = 0 ;
152
+ }
153
+
154
+
155
+ // ============================================================================
156
+ // >> FUNCTIONS
157
+ // ============================================================================
158
+ template <class T >
159
+ T GetArgument (CCallback* pCallback, unsigned long ulEBP, unsigned long ulECX, int iIndex)
160
+ {
161
+ #ifdef _WIN32
162
+ if (pCallback->m_eConv == CONV_THISCALL && iIndex == 0 )
163
+ return *(T *) &ulECX;
164
+ #endif
165
+
166
+ return *(T *) (ulEBP + pCallback->GetArgument (iIndex)->m_iOffset + 8 );
167
+ }
168
+
169
+ object CallCallback (CCallback* pCallback, unsigned long ulEBP, unsigned long ulECX)
170
+ {
171
+ BEGIN_BOOST_PY ()
172
+
173
+ list arg_list;
174
+ for (int i=0 ; i < pCallback->GetArgumentCount (); i++)
175
+ {
176
+ object val;
177
+ switch (pCallback->GetArgument (i)->m_cParam )
178
+ {
179
+ case SIGCHAR_BOOL: val = object (GetArgument<bool >(pCallback, ulEBP, ulECX, i)); break ;
180
+ case SIGCHAR_CHAR: val = object (GetArgument<char >(pCallback, ulEBP, ulECX, i)); break ;
181
+ case SIGCHAR_UCHAR: val = object (GetArgument<unsigned char >(pCallback, ulEBP, ulECX, i)); break ;
182
+ case SIGCHAR_SHORT: val = object (GetArgument<short >(pCallback, ulEBP, ulECX, i)); break ;
183
+ case SIGCHAR_USHORT: val = object (GetArgument<unsigned short >(pCallback, ulEBP, ulECX, i)); break ;
184
+ case SIGCHAR_INT: val = object (GetArgument<int >(pCallback, ulEBP, ulECX, i)); break ;
185
+ case SIGCHAR_UINT: val = object (GetArgument<unsigned int >(pCallback, ulEBP, ulECX, i)); break ;
186
+ case SIGCHAR_LONG: val = object (GetArgument<long >(pCallback, ulEBP, ulECX, i)); break ;
187
+ case SIGCHAR_ULONG: val = object (GetArgument<unsigned long >(pCallback, ulEBP, ulECX, i)); break ;
188
+ case SIGCHAR_LONGLONG: val = object (GetArgument<long long >(pCallback, ulEBP, ulECX, i)); break ;
189
+ case SIGCHAR_ULONGLONG: val = object (GetArgument<unsigned long long >(pCallback, ulEBP, ulECX, i)); break ;
190
+ case SIGCHAR_FLOAT: val = object (GetArgument<float >(pCallback, ulEBP, ulECX, i)); break ;
191
+ case SIGCHAR_DOUBLE: val = object (GetArgument<double >(pCallback, ulEBP, ulECX, i)); break ;
192
+ case SIGCHAR_POINTER: val = object (CPointer (GetArgument<unsigned long >(pCallback, ulEBP, ulECX, i))); break ;
193
+ case SIGCHAR_STRING: val = object (GetArgument<const char *>(pCallback, ulEBP, ulECX, i)); break ;
194
+ default : BOOST_RAISE_EXCEPTION (PyExc_TypeError, " Unknown type." ); break ;
195
+ }
196
+ arg_list.append (val);
197
+ }
198
+ arg_list.append (CPointer ((unsigned long ) ulEBP));
199
+ return eval (" lambda func, args: func(*args)" )(pCallback->m_oCallback , arg_list);
200
+
201
+ END_BOOST_PY_NORET ()
202
+
203
+ // Throw an exception. We will crash now :(
204
+ throw ;
205
+ }
0 commit comments