2 * 386-specific Win32 relay functions
4 * Copyright 1997 Alexandre Julliard
11 #include "builtin32.h"
12 #include "selectors.h"
17 DEFAULT_DEBUG_CHANNEL(relay
)
19 char **debug_relay_excludelist
= NULL
, **debug_relay_includelist
= NULL
;
22 /***********************************************************************
23 * RELAY_ShowDebugmsgRelay
25 * Simple function to decide if a particular debugging message is
26 * wanted. Called from RELAY_CallFrom32 and from in if1632/relay.c
28 int RELAY_ShowDebugmsgRelay(const char *func
) {
30 if(debug_relay_excludelist
|| debug_relay_includelist
) {
31 const char *term
= strchr(func
, ':');
33 int len
, len2
, itemlen
, show
;
35 if(debug_relay_excludelist
) {
37 listitem
= debug_relay_excludelist
;
40 listitem
= debug_relay_includelist
;
43 assert(strlen(term
) > 2);
45 len2
= strchr(func
, '.') - func
;
46 assert(len2
&& len2
> 0 && len2
< 64);
48 for(; *listitem
; listitem
++) {
49 itemlen
= strlen(*listitem
);
50 if((itemlen
== len
&& !strncmp(*listitem
, func
, len
)) ||
51 (itemlen
== len2
&& !strncmp(*listitem
, func
, len2
)) ||
52 !strcmp(*listitem
, term
)) {
62 /***********************************************************************
65 * Stack layout on entry to this function:
70 * (esp) return addr to relay code
72 int RELAY_CallFrom32( int ret_addr
, ... )
77 unsigned int mask
, typemask
;
80 int *args
= &ret_addr
;
81 /* Relay addr is the return address for this function */
82 BYTE
*relay_addr
= (BYTE
*)args
[-1];
83 WORD nb_args
= *(WORD
*)(relay_addr
+ 1) / sizeof(int);
85 assert(TRACE_ON(relay
));
86 func
= (FARPROC
)BUILTIN32_GetEntryPoint( buffer
, relay_addr
- 5,
88 DPRINTF( "Call %s(", buffer
);
90 for (i
= 0, mask
= 3; i
< nb_args
; i
++, mask
<<= 2)
92 if (i
) DPRINTF( "," );
93 if ((typemask
& mask
) && HIWORD(args
[i
]))
95 if (typemask
& (2<<(2*i
)))
96 DPRINTF( "%08x L%s", args
[i
], debugstr_w((LPWSTR
)args
[i
]) );
98 DPRINTF( "%08x %s", args
[i
], debugstr_a((LPCSTR
)args
[i
]) );
100 else DPRINTF( "%08x", args
[i
] );
103 DPRINTF( ") ret=%08x fs=%04x\n", ret_addr
, fs
);
105 if (*relay_addr
== 0xc3) /* cdecl */
107 LRESULT (*cfunc
)() = (LRESULT(*)())func
;
110 case 0: ret
= cfunc(); break;
111 case 1: ret
= cfunc(args
[0]); break;
112 case 2: ret
= cfunc(args
[0],args
[1]); break;
113 case 3: ret
= cfunc(args
[0],args
[1],args
[2]); break;
114 case 4: ret
= cfunc(args
[0],args
[1],args
[2],args
[3]); break;
115 case 5: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4]); break;
116 case 6: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],
118 case 7: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
120 case 8: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
121 args
[6],args
[7]); break;
122 case 9: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
123 args
[6],args
[7],args
[8]); break;
124 case 10: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
125 args
[6],args
[7],args
[8],args
[9]); break;
126 case 11: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
127 args
[6],args
[7],args
[8],args
[9],args
[10]); break;
128 case 12: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
129 args
[6],args
[7],args
[8],args
[9],args
[10],
131 case 13: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
132 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
134 case 14: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
135 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
136 args
[12],args
[13]); break;
137 case 15: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
138 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
139 args
[12],args
[13],args
[14]); break;
140 case 16: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
141 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
142 args
[12],args
[13],args
[14],args
[15]); break;
144 ERR(relay
, "Unsupported nb args %d\n",
153 case 0: ret
= func(); break;
154 case 1: ret
= func(args
[0]); break;
155 case 2: ret
= func(args
[0],args
[1]); break;
156 case 3: ret
= func(args
[0],args
[1],args
[2]); break;
157 case 4: ret
= func(args
[0],args
[1],args
[2],args
[3]); break;
158 case 5: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4]); break;
159 case 6: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],
161 case 7: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
163 case 8: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
164 args
[6],args
[7]); break;
165 case 9: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
166 args
[6],args
[7],args
[8]); break;
167 case 10: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
168 args
[6],args
[7],args
[8],args
[9]); break;
169 case 11: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
170 args
[6],args
[7],args
[8],args
[9],args
[10]); break;
171 case 12: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
172 args
[6],args
[7],args
[8],args
[9],args
[10],
174 case 13: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
175 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
177 case 14: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
178 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
179 args
[12],args
[13]); break;
180 case 15: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
181 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
182 args
[12],args
[13],args
[14]); break;
183 case 16: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
184 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
185 args
[12],args
[13],args
[14],args
[15]); break;
187 ERR(relay
, "Unsupported nb args %d\n",nb_args
);
191 DPRINTF( "Ret %s() retval=%08x ret=%08x fs=%04x\n",
192 buffer
, ret
, ret_addr
, fs
);
197 /***********************************************************************
198 * RELAY_CallFrom32Regs
200 * 'context' contains the register contents at the point of call of
201 * the REG_ENTRY_POINT. The stack layout of the stack pointed to by
202 * ESP_reg(&context) is as follows:
204 * If debugmsg(relay) is OFF:
207 * (esp) return addr to caller
208 * (esp-4) function entry point
210 * If debugmsg(relay) is ON:
213 * (esp+4) return addr to caller
214 * (esp) return addr to DEBUG_ENTRY_POINT
215 * (esp-4) function entry point
217 * As the called function might change the stack layout
218 * (e.g. FT_Prolog, FT_ExitNN), we remove all modifications to the stack,
219 * so that the called function sees (in both cases):
223 * (esp) return addr to caller
224 * ... >128 bytes space free to be modified (ensured by the assembly glue)
226 * NOTE: This routine makes no assumption about the relative position of
227 * its own stack to the stack pointed to by ESP_reg(&context),
228 * except that the latter must have >128 bytes space to grow.
229 * This means the assembly glue could even switch stacks completely
230 * (e.g. to allow for large stacks).
234 void RELAY_CallFrom32Regs( CONTEXT context
)
236 typedef void (CALLBACK
*entry_point_t
)(CONTEXT
*);
237 entry_point_t entry_point
= *(entry_point_t
*) (ESP_reg(&context
) - 4);
241 if (!TRACE_ON(relay
))
243 /* Simply call the entry point */
244 entry_point( &context
);
249 unsigned int typemask
;
253 * Fixup the context structure because of the extra parameter
254 * pushed by the relay debugging code.
255 * Note that this implicitly does a RET on the CALL from the
256 * DEBUG_ENTRY_POINT to the REG_ENTRY_POINT; setting the EIP register
257 * ensures that the assembly glue will directly return to the
258 * caller, just as in the non-debugging case.
261 relay_addr
= *(BYTE
**) ESP_reg(&context
);
262 if (BUILTIN32_GetEntryPoint( buffer
, relay_addr
- 5, &typemask
)) {
263 /* correct win32 spec generated register function found.
264 * remove extra call stuff from stack
266 ESP_reg(&context
) += sizeof(BYTE
*);
267 EIP_reg(&context
) = *(DWORD
*)ESP_reg(&context
);
268 DPRINTF("Call %s(regs) ret=%08x\n", buffer
, *(int *)ESP_reg(&context
) );
269 DPRINTF(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
270 EAX_reg(&context
), EBX_reg(&context
), ECX_reg(&context
),
271 EDX_reg(&context
), ESI_reg(&context
), EDI_reg(&context
) );
272 DPRINTF(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
273 EBP_reg(&context
), ESP_reg(&context
), EIP_reg(&context
),
274 DS_reg(&context
), ES_reg(&context
), FS_reg(&context
),
275 GS_reg(&context
), EFL_reg(&context
) );
277 /* Now call the real function */
278 entry_point( &context
);
281 DPRINTF("Ret %s() retval=regs ret=%08x\n", buffer
, *(int *)ESP_reg(&context
) );
282 DPRINTF(" EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx ESI=%08lx EDI=%08lx\n",
283 EAX_reg(&context
), EBX_reg(&context
), ECX_reg(&context
),
284 EDX_reg(&context
), ESI_reg(&context
), EDI_reg(&context
) );
285 DPRINTF(" EBP=%08lx ESP=%08lx EIP=%08lx DS=%04lx ES=%04lx FS=%04lx GS=%04lx EFL=%08lx\n",
286 EBP_reg(&context
), ESP_reg(&context
), EIP_reg(&context
),
287 DS_reg(&context
), ES_reg(&context
), FS_reg(&context
),
288 GS_reg(&context
), EFL_reg(&context
) );
290 /* WINE internal register function found. Do not remove anything.
291 * Do not print any debuginfo (it is not a normal relayed one).
292 * Currently only used for snooping.
294 entry_point( &context
);
297 #endif /* __i386__ */