Recovery of release 990110 after disk crash.
[wine] / relay32 / relay386.c
1 /*
2  * 386-specific Win32 relay functions
3  *
4  * Copyright 1997 Alexandre Julliard
5  */
6
7 #ifdef __i386__
8
9 #include <assert.h>
10 #include <string.h>
11 #include "winnt.h"
12 #include "windows.h"
13 #include "builtin32.h"
14 #include "selectors.h"
15 #include "debugstr.h"
16 #include "debug.h"
17 #include "main.h"
18
19 char **debug_relay_excludelist = NULL, **debug_relay_includelist = NULL;
20
21 /***********************************************************************
22  *           RELAY_ShowDebugmsgRelay
23  *
24  * Simple function to decide if a particular debugging message is
25  * wanted.  Called from RELAY_CallFrom32 and from in if1632/relay.c
26  */
27 int RELAY_ShowDebugmsgRelay(const char *func) {
28
29   if(debug_relay_excludelist || debug_relay_includelist) {
30     const char *term = strchr(func, ':');
31     char **listitem;
32     int len, len2, itemlen, show;
33
34     if(debug_relay_excludelist) {
35       show = 1;
36       listitem = debug_relay_excludelist;
37     } else {
38       show = 0;
39       listitem = debug_relay_includelist;
40     }
41     assert(term);
42     assert(strlen(term) > 2);
43     len = term - func;
44     len2 = strchr(func, '.') - func;
45     assert(len2 && len2 > 0 && len2 < 64);
46     term += 2;
47     for(; *listitem; listitem++) {
48       itemlen = strlen(*listitem);
49       if((itemlen == len && !strncmp(*listitem, func, len)) ||
50          (itemlen == len2 && !strncmp(*listitem, func, len2)) ||
51          !strcmp(*listitem, term)) {
52         show = !show;
53        break;
54       }
55     }
56     return show;
57   }
58   return 1;
59 }
60
61 /***********************************************************************
62  *           RELAY_CallFrom32
63  *
64  * Stack layout on entry to this function:
65  *  ...      ...
66  * (esp+12)  arg2
67  * (esp+8)   arg1
68  * (esp+4)   ret_addr
69  * (esp)     return addr to relay code
70  */
71 int RELAY_CallFrom32( int ret_addr, ... )
72 {
73     int i, ret;
74     char buffer[80];
75     FARPROC32 func;
76     unsigned int mask, typemask;
77     WORD fs;
78
79     int *args = &ret_addr;
80     /* Relay addr is the return address for this function */
81     BYTE *relay_addr = (BYTE *)args[-1];
82     WORD nb_args = *(WORD *)(relay_addr + 1) / sizeof(int);
83
84     assert(TRACE_ON(relay));
85     func = (FARPROC32)BUILTIN32_GetEntryPoint( buffer, relay_addr - 5,
86                                                &typemask );
87       DPRINTF( "Call %s(", buffer );
88       args++;
89       for (i = 0, mask = 3; i < nb_args; i++, mask <<= 2)
90       {
91         if (i) DPRINTF( "," );
92         if ((typemask & mask) && HIWORD(args[i]))
93         {
94             if (typemask & (2<<(2*i)))
95                 DPRINTF( "%08x L%s", args[i], debugstr_w((LPWSTR)args[i]) );
96             else
97                 DPRINTF( "%08x %s", args[i], debugstr_a((LPCSTR)args[i]) );
98         }
99         else DPRINTF( "%08x", args[i] );
100       }
101       GET_FS( fs );
102       DPRINTF( ") ret=%08x fs=%04x\n", ret_addr, fs );
103
104     if (*relay_addr == 0xc3) /* cdecl */
105     {
106         LRESULT (*cfunc)() = (LRESULT(*)())func;
107         switch(nb_args)
108         {
109         case 0: ret = cfunc(); break;
110         case 1: ret = cfunc(args[0]); break;
111         case 2: ret = cfunc(args[0],args[1]); break;
112         case 3: ret = cfunc(args[0],args[1],args[2]); break;
113         case 4: ret = cfunc(args[0],args[1],args[2],args[3]); break;
114         case 5: ret = cfunc(args[0],args[1],args[2],args[3],args[4]); break;
115         case 6: ret = cfunc(args[0],args[1],args[2],args[3],args[4],
116                             args[5]); break;
117         case 7: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
118                             args[6]); break;
119         case 8: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
120                             args[6],args[7]); break;
121         case 9: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
122                             args[6],args[7],args[8]); break;
123         case 10: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
124                              args[6],args[7],args[8],args[9]); break;
125         case 11: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
126                              args[6],args[7],args[8],args[9],args[10]); break;
127         case 12: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
128                              args[6],args[7],args[8],args[9],args[10],
129                              args[11]); break;
130         case 13: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
131                              args[6],args[7],args[8],args[9],args[10],args[11],
132                              args[12]); break;
133         case 14: ret = cfunc(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],args[13]); break;
136         case 15: ret = cfunc(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],args[14]); break;
139         default:
140             ERR(relay, "Unsupported nb args %d\n",
141                      nb_args );
142             assert(FALSE);
143         }
144     }
145     else  /* stdcall */
146     {
147         switch(nb_args)
148         {
149         case 0: ret = func(); break;
150         case 1: ret = func(args[0]); break;
151         case 2: ret = func(args[0],args[1]); break;
152         case 3: ret = func(args[0],args[1],args[2]); break;
153         case 4: ret = func(args[0],args[1],args[2],args[3]); break;
154         case 5: ret = func(args[0],args[1],args[2],args[3],args[4]); break;
155         case 6: ret = func(args[0],args[1],args[2],args[3],args[4],
156                            args[5]); break;
157         case 7: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
158                            args[6]); break;
159         case 8: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
160                            args[6],args[7]); break;
161         case 9: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
162                            args[6],args[7],args[8]); break;
163         case 10: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
164                             args[6],args[7],args[8],args[9]); break;
165         case 11: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
166                             args[6],args[7],args[8],args[9],args[10]); break;
167         case 12: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
168                             args[6],args[7],args[8],args[9],args[10],
169                             args[11]); break;
170         case 13: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
171                             args[6],args[7],args[8],args[9],args[10],args[11],
172                             args[12]); break;
173         case 14: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
174                             args[6],args[7],args[8],args[9],args[10],args[11],
175                             args[12],args[13]); break;
176         case 15: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
177                             args[6],args[7],args[8],args[9],args[10],args[11],
178                             args[12],args[13],args[14]); break;
179         default:
180             ERR(relay, "Unsupported nb args %d\n",nb_args );
181             assert(FALSE);
182         }
183     }
184     DPRINTF( "Ret  %s() retval=%08x ret=%08x fs=%04x\n",
185              buffer, ret, ret_addr, fs );
186     return ret;
187 }
188
189
190 /***********************************************************************
191  *           RELAY_CallFrom32Regs
192  *
193  * 'context' contains the register contents at the point of call of
194  * the REG_ENTRY_POINT. The stack layout of the stack pointed to by
195  * ESP_reg(&context) is as follows:
196  *
197  * If debugmsg(relay) is OFF:
198  *  ...    ...
199  * (esp+4) args
200  * (esp)   return addr to caller
201  * (esp-4) function entry point
202  *
203  * If debugmsg(relay) is ON:
204  *  ...    ...
205  * (esp+8) args
206  * (esp+4) return addr to caller
207  * (esp)   return addr to DEBUG_ENTRY_POINT
208  * (esp-4) function entry point
209  *
210  * As the called function might change the stack layout
211  * (e.g. FT_Prolog, FT_ExitNN), we remove all modifications to the stack,
212  * so that the called function sees (in both cases):
213  *
214  *  ...    ...
215  * (esp+4) args
216  * (esp)   return addr to caller
217  *  ...    >128 bytes space free to be modified (ensured by the assembly glue)
218  *
219  * NOTE: This routine makes no assumption about the relative position of
220  *       its own stack to the stack pointed to by ESP_reg(&context),
221  *       except that the latter must have >128 bytes space to grow.
222  *       This means the assembly glue could even switch stacks completely
223  *       (e.g. to allow for large stacks).
224  *
225  */
226
227 void RELAY_CallFrom32Regs( CONTEXT context )
228 {
229     typedef void (CALLBACK *entry_point_t)(CONTEXT *);
230     entry_point_t entry_point = *(entry_point_t*) (ESP_reg(&context) - 4);
231
232     __RESTORE_ES;
233
234     if (!TRACE_ON(relay))
235     {
236         /* Simply call the entry point */
237         entry_point( &context );
238     }
239     else
240     {
241         char buffer[80];
242         unsigned int typemask;
243         BYTE *relay_addr;
244
245         /*
246          * Fixup the context structure because of the extra parameter
247          * pushed by the relay debugging code.
248          * Note that this implicitly does a RET on the CALL from the
249          * DEBUG_ENTRY_POINT to the REG_ENTRY_POINT;  setting the EIP register
250          * ensures that the assembly glue will directly return to the
251          * caller, just as in the non-debugging case.
252          */
253
254         relay_addr = *(BYTE **) ESP_reg(&context); 
255         if (BUILTIN32_GetEntryPoint( buffer, relay_addr - 5, &typemask )) {
256             /* correct win32 spec generated register function found. 
257              * remove extra call stuff from stack
258              */
259             ESP_reg(&context) += sizeof(BYTE *);
260             EIP_reg(&context) = *(DWORD *)ESP_reg(&context);
261             DPRINTF("Call %s(regs) ret=%08x\n", buffer, *(int *)ESP_reg(&context) );
262             DPRINTF(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
263                     EAX_reg(&context), EBX_reg(&context), ECX_reg(&context),
264                     EDX_reg(&context), ESI_reg(&context), EDI_reg(&context) );
265             DPRINTF(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
266                     EBP_reg(&context), ESP_reg(&context), EIP_reg(&context),
267                     DS_reg(&context), ES_reg(&context), FS_reg(&context),
268                     GS_reg(&context), EFL_reg(&context) );
269
270             /* Now call the real function */
271             entry_point( &context );
272
273
274             DPRINTF("Ret  %s() retval=regs ret=%08x\n", buffer, *(int *)ESP_reg(&context) );
275             DPRINTF(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
276                     EAX_reg(&context), EBX_reg(&context), ECX_reg(&context),
277                     EDX_reg(&context), ESI_reg(&context), EDI_reg(&context) );
278             DPRINTF(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
279                     EBP_reg(&context), ESP_reg(&context), EIP_reg(&context),
280                     DS_reg(&context), ES_reg(&context), FS_reg(&context),
281                     GS_reg(&context), EFL_reg(&context) );
282         } else
283             /* WINE internal register function found. Do not remove anything.
284              * Do not print any debuginfo (it is not a normal relayed one).
285              * Currently only used for snooping.
286              */
287            entry_point( &context );
288     }
289 }
290 #endif  /* __i386__ */