Release 980503
[wine/hacks.git] / relay32 / relay386.c
blob8203e407016a2922bc8ed53427a00d278a6ecc5e
1 /*
2 * 386-specific Win32 relay functions
4 * Copyright 1997 Alexandre Julliard
5 */
7 #ifdef __i386__
9 #include <assert.h>
10 #include "winnt.h"
11 #include "windows.h"
12 #include "builtin32.h"
13 #include "selectors.h"
14 #include "debugstr.h"
15 #include "debug.h"
17 /***********************************************************************
18 * RELAY_CallFrom32
20 * Stack layout on entry to this function:
21 * ... ...
22 * (esp+12) arg2
23 * (esp+8) arg1
24 * (esp+4) ret_addr
25 * (esp) return addr to relay code
27 int RELAY_CallFrom32( int ret_addr, ... )
29 int i, ret;
30 char buffer[80];
31 FARPROC32 func;
32 unsigned int mask, typemask;
33 WORD fs;
35 int *args = &ret_addr;
36 /* Relay addr is the return address for this function */
37 BYTE *relay_addr = (BYTE *)args[-1];
38 WORD nb_args = *(WORD *)(relay_addr + 1) / sizeof(int);
40 assert(TRACE_ON(relay));
41 func = (FARPROC32)BUILTIN32_GetEntryPoint( buffer, relay_addr - 5,
42 &typemask );
43 printf( "Call %s(", buffer );
44 args++;
45 for (i = 0, mask = 3; i < nb_args; i++, mask <<= 2)
47 if (i) printf( "," );
48 if ((typemask & mask) && HIWORD(args[i]))
50 if (typemask & (2<<(2*i)))
52 char buff[80];
53 lstrcpynWtoA( buff, (LPWSTR)args[i], sizeof(buff) );
54 buff[sizeof(buff)-1]='\0';
55 printf( "%08x L", args[i] );
56 debug_dumpstr( buff );
58 else {
59 printf( "%08x ", args[i] );
60 debug_dumpstr((LPCSTR)args[i]);
63 else printf( "%08x", args[i] );
65 GET_FS( fs );
66 printf( ") ret=%08x fs=%04x\n", ret_addr, fs );
67 if (*relay_addr == 0xc3) /* cdecl */
69 LRESULT (*cfunc)() = (LRESULT(*)())func;
70 switch(nb_args)
72 case 0: ret = cfunc(); break;
73 case 1: ret = cfunc(args[0]); break;
74 case 2: ret = cfunc(args[0],args[1]); break;
75 case 3: ret = cfunc(args[0],args[1],args[2]); break;
76 case 4: ret = cfunc(args[0],args[1],args[2],args[3]); break;
77 case 5: ret = cfunc(args[0],args[1],args[2],args[3],args[4]); break;
78 case 6: ret = cfunc(args[0],args[1],args[2],args[3],args[4],
79 args[5]); break;
80 case 7: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
81 args[6]); break;
82 case 8: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
83 args[6],args[7]); break;
84 case 9: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
85 args[6],args[7],args[8]); break;
86 case 10: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
87 args[6],args[7],args[8],args[9]); break;
88 case 11: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
89 args[6],args[7],args[8],args[9],args[10]); break;
90 case 12: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
91 args[6],args[7],args[8],args[9],args[10],
92 args[11]); break;
93 case 13: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
94 args[6],args[7],args[8],args[9],args[10],args[11],
95 args[12]); break;
96 case 14: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
97 args[6],args[7],args[8],args[9],args[10],args[11],
98 args[12],args[13]); break;
99 case 15: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
100 args[6],args[7],args[8],args[9],args[10],args[11],
101 args[12],args[13],args[14]); break;
102 default:
103 fprintf( stderr, "RELAY_CallFrom32: Unsupported nb args %d\n",
104 nb_args );
105 assert(FALSE);
108 else /* stdcall */
110 switch(nb_args)
112 case 0: ret = func(); break;
113 case 1: ret = func(args[0]); break;
114 case 2: ret = func(args[0],args[1]); break;
115 case 3: ret = func(args[0],args[1],args[2]); break;
116 case 4: ret = func(args[0],args[1],args[2],args[3]); break;
117 case 5: ret = func(args[0],args[1],args[2],args[3],args[4]); break;
118 case 6: ret = func(args[0],args[1],args[2],args[3],args[4],
119 args[5]); break;
120 case 7: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
121 args[6]); break;
122 case 8: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
123 args[6],args[7]); break;
124 case 9: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
125 args[6],args[7],args[8]); break;
126 case 10: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
127 args[6],args[7],args[8],args[9]); break;
128 case 11: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
129 args[6],args[7],args[8],args[9],args[10]); break;
130 case 12: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
131 args[6],args[7],args[8],args[9],args[10],
132 args[11]); break;
133 case 13: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
134 args[6],args[7],args[8],args[9],args[10],args[11],
135 args[12]); break;
136 case 14: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
137 args[6],args[7],args[8],args[9],args[10],args[11],
138 args[12],args[13]); break;
139 case 15: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
140 args[6],args[7],args[8],args[9],args[10],args[11],
141 args[12],args[13],args[14]); break;
142 default:
143 fprintf( stderr, "RELAY_CallFrom32: Unsupported nb args %d\n",
144 nb_args );
145 assert(FALSE);
148 printf( "Ret %s() retval=%08x ret=%08x fs=%04x\n",
149 buffer, ret, ret_addr, fs );
150 return ret;
154 /***********************************************************************
155 * RELAY_CallFrom32Regs
157 * 'context' contains the register contents at the point of call of
158 * the REG_ENTRY_POINT. The stack layout of the stack pointed to by
159 * ESP_reg(&context) is as follows:
161 * If debugmsg(relay) is OFF:
162 * ... ...
163 * (esp+4) args
164 * (esp) return addr to caller
165 * (esp-4) function entry point
167 * If debugmsg(relay) is ON:
168 * ... ...
169 * (esp+8) args
170 * (esp+4) return addr to caller
171 * (esp) return addr to DEBUG_ENTRY_POINT
172 * (esp-4) function entry point
174 * As the called function might change the stack layout
175 * (e.g. FT_Prolog, FT_ExitNN), we remove all modifications to the stack,
176 * so that the called function sees (in both cases):
178 * ... ...
179 * (esp+4) args
180 * (esp) return addr to caller
181 * ... >128 bytes space free to be modified (ensured by the assembly glue)
183 * NOTE: This routine makes no assumption about the relative position of
184 * its own stack to the stack pointed to by ESP_reg(&context),
185 * except that the latter must have >128 bytes space to grow.
186 * This means the assembly glue could even switch stacks completely
187 * (e.g. to allow for large stacks).
191 void RELAY_CallFrom32Regs( CONTEXT context )
193 typedef void (CALLBACK *entry_point_t)(CONTEXT *);
194 entry_point_t entry_point = *(entry_point_t*) (ESP_reg(&context) - 4);
196 if (!TRACE_ON(relay))
198 /* Simply call the entry point */
199 entry_point( &context );
201 else
203 char buffer[80];
204 unsigned int typemask;
205 BYTE *relay_addr;
207 __RESTORE_ES;
210 * Fixup the context structure because of the extra parameter
211 * pushed by the relay debugging code.
212 * Note that this implicitly does a RET on the CALL from the
213 * DEBUG_ENTRY_POINT to the REG_ENTRY_POINT; setting the EIP register
214 * ensures that the assembly glue will directly return to the
215 * caller, just as in the non-debugging case.
218 relay_addr = *(BYTE **) ESP_reg(&context);
219 ESP_reg(&context) += sizeof(BYTE *);
220 EIP_reg(&context) = *(DWORD *)ESP_reg(&context);
222 BUILTIN32_GetEntryPoint( buffer, relay_addr - 5, &typemask );
223 printf("Call %s(regs) ret=%08x\n", buffer, *(int *)ESP_reg(&context) );
224 printf(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
225 EAX_reg(&context), EBX_reg(&context), ECX_reg(&context),
226 EDX_reg(&context), ESI_reg(&context), EDI_reg(&context) );
227 printf(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
228 EBP_reg(&context), ESP_reg(&context), EIP_reg(&context),
229 DS_reg(&context), ES_reg(&context), FS_reg(&context),
230 GS_reg(&context), EFL_reg(&context) );
232 /* Now call the real function */
233 entry_point( &context );
235 printf("Ret %s() retval=regs ret=%08x\n", buffer, *(int *)ESP_reg(&context) );
236 printf(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
237 EAX_reg(&context), EBX_reg(&context), ECX_reg(&context),
238 EDX_reg(&context), ESI_reg(&context), EDI_reg(&context) );
239 printf(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
240 EBP_reg(&context), ESP_reg(&context), EIP_reg(&context),
241 DS_reg(&context), ES_reg(&context), FS_reg(&context),
242 GS_reg(&context), EFL_reg(&context) );
246 #endif /* __i386__ */