2 * 386-specific Win32 relay functions
4 * Copyright 1997 Alexandre Julliard
11 #include "builtin32.h"
12 #include "selectors.h"
13 #include "stackframe.h"
16 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(relay
);
20 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
&& !lstrncmpiA(*listitem
, func
, len
)) ||
51 (itemlen
== len2
&& !lstrncmpiA(*listitem
, func
, len2
)) ||
52 !lstrcmpiA(*listitem
, term
)) {
65 /***********************************************************************
68 static inline void RELAY_PrintArgs( int *args
, int nb_args
, unsigned int typemask
)
72 if ((typemask
& 3) && HIWORD(*args
))
75 DPRINTF( "%08x %s", *args
, debugstr_w((LPWSTR
)*args
) );
77 DPRINTF( "%08x %s", *args
, debugstr_a((LPCSTR
)*args
) );
79 else DPRINTF( "%08x", *args
);
80 if (nb_args
) DPRINTF( "," );
87 /***********************************************************************
90 * Stack layout on entry to this function:
95 * (esp) return addr to relay code
97 int RELAY_CallFrom32( int ret_addr
, ... )
101 unsigned int typemask
;
104 int *args
= &ret_addr
+ 1;
105 /* Relay addr is the return address for this function */
106 BYTE
*relay_addr
= (BYTE
*)__builtin_return_address(0);
107 WORD nb_args
= *(WORD
*)(relay_addr
+ 1) / sizeof(int);
109 assert(TRACE_ON(relay
));
110 func
= (FARPROC
)BUILTIN32_GetEntryPoint( buffer
, relay_addr
- 5, &typemask
);
111 DPRINTF( "Call %s(", buffer
);
112 RELAY_PrintArgs( args
, nb_args
, typemask
);
113 DPRINTF( ") ret=%08x fs=%04x\n", ret_addr
, __get_fs() );
115 SYSLEVEL_CheckNotLevel( 2 );
117 if (*relay_addr
== 0xc3) /* cdecl */
119 LRESULT (*cfunc
)() = (LRESULT(*)())func
;
122 case 0: ret
= cfunc(); break;
123 case 1: ret
= cfunc(args
[0]); break;
124 case 2: ret
= cfunc(args
[0],args
[1]); break;
125 case 3: ret
= cfunc(args
[0],args
[1],args
[2]); break;
126 case 4: ret
= cfunc(args
[0],args
[1],args
[2],args
[3]); break;
127 case 5: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4]); break;
128 case 6: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],
130 case 7: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
132 case 8: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
133 args
[6],args
[7]); break;
134 case 9: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
135 args
[6],args
[7],args
[8]); break;
136 case 10: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
137 args
[6],args
[7],args
[8],args
[9]); break;
138 case 11: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
139 args
[6],args
[7],args
[8],args
[9],args
[10]); break;
140 case 12: 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],
143 case 13: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
144 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
146 case 14: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
147 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
148 args
[12],args
[13]); break;
149 case 15: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
150 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
151 args
[12],args
[13],args
[14]); break;
152 case 16: ret
= cfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
153 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
154 args
[12],args
[13],args
[14],args
[15]); break;
156 ERR( "Unsupported nb of args %d\n", nb_args
);
164 case 0: ret
= func(); break;
165 case 1: ret
= func(args
[0]); break;
166 case 2: ret
= func(args
[0],args
[1]); break;
167 case 3: ret
= func(args
[0],args
[1],args
[2]); break;
168 case 4: ret
= func(args
[0],args
[1],args
[2],args
[3]); break;
169 case 5: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4]); break;
170 case 6: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],
172 case 7: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
174 case 8: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
175 args
[6],args
[7]); break;
176 case 9: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
177 args
[6],args
[7],args
[8]); break;
178 case 10: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
179 args
[6],args
[7],args
[8],args
[9]); break;
180 case 11: 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]); break;
182 case 12: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
183 args
[6],args
[7],args
[8],args
[9],args
[10],
185 case 13: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
186 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
188 case 14: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
189 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
190 args
[12],args
[13]); break;
191 case 15: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
192 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
193 args
[12],args
[13],args
[14]); break;
194 case 16: ret
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],
195 args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],
196 args
[12],args
[13],args
[14],args
[15]); break;
198 ERR( "Unsupported nb of args %d\n", nb_args
);
202 DPRINTF( "Ret %s() retval=%08x ret=%08x fs=%04x\n",
203 buffer
, ret
, ret_addr
, __get_fs() );
205 SYSLEVEL_CheckNotLevel( 2 );
211 /***********************************************************************
212 * RELAY_CallFrom32Regs
214 * Stack layout (esp is ESP_reg(context), not the current %esp):
218 * (esp) return addr to caller
219 * (esp-4) return addr to DEBUG_ENTRY_POINT
220 * (esp-8) ptr to relay entry code for RELAY_CallFrom32Regs
221 * ... >128 bytes space free to be modified (ensured by the assembly glue)
224 void WINAPI
RELAY_DoCallFrom32Regs( CONTEXT86
*context
);
225 DEFINE_REGS_ENTRYPOINT_0( RELAY_CallFrom32Regs
, RELAY_DoCallFrom32Regs
)
226 void WINAPI
RELAY_DoCallFrom32Regs( CONTEXT86
*context
)
228 unsigned int typemask
;
234 BYTE
*relay_addr
= *((BYTE
**)ESP_reg(context
) - 1);
235 WORD nb_args
= *(WORD
*)(relay_addr
+ 1) / sizeof(int);
237 /* remove extra stuff from the stack */
238 EIP_reg(context
) = stack32_pop(context
);
239 args
= (int *)ESP_reg(context
);
240 ESP_reg(context
) += 4 * nb_args
;
242 assert(TRACE_ON(relay
));
244 entry_point
= (BYTE
*)BUILTIN32_GetEntryPoint( buffer
, relay_addr
- 5, &typemask
);
245 assert( *entry_point
== 0xe8 /* lcall */ );
246 func
= *(FARPROC
*)(entry_point
+ 5);
248 DPRINTF( "Call %s(", buffer
);
249 RELAY_PrintArgs( args
, nb_args
, typemask
);
250 DPRINTF( ") ret=%08lx fs=%04lx\n", EIP_reg(context
), FS_reg(context
) );
252 DPRINTF(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
253 EAX_reg(context
), EBX_reg(context
), ECX_reg(context
),
254 EDX_reg(context
), ESI_reg(context
), EDI_reg(context
) );
255 DPRINTF(" ebp=%08lx esp=%08lx ds=%04lx es=%04lx gs=%04lx flags=%08lx\n",
256 EBP_reg(context
), ESP_reg(context
), DS_reg(context
),
257 ES_reg(context
), GS_reg(context
), EFL_reg(context
) );
259 SYSLEVEL_CheckNotLevel( 2 );
261 /* Now call the real function */
264 case 0: func(context
); break;
265 case 1: func(args
[0],context
); break;
266 case 2: func(args
[0],args
[1],context
); break;
267 case 3: func(args
[0],args
[1],args
[2],context
); break;
268 case 4: func(args
[0],args
[1],args
[2],args
[3],context
); break;
269 case 5: func(args
[0],args
[1],args
[2],args
[3],args
[4],context
); break;
270 case 6: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],context
); break;
271 case 7: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],context
); break;
272 case 8: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],context
); break;
273 case 9: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],
275 case 10: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],
276 args
[9],context
); break;
277 case 11: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],
278 args
[9],args
[10],context
); break;
279 case 12: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],
280 args
[9],args
[10],args
[11],context
); break;
281 case 13: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],
282 args
[9],args
[10],args
[11],args
[12],context
); break;
283 case 14: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],
284 args
[9],args
[10],args
[11],args
[12],args
[13],context
); break;
285 case 15: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],
286 args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],context
); break;
287 case 16: func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5], args
[6],args
[7],args
[8],
288 args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],context
); break;
290 ERR( "Unsupported nb of args %d\n", nb_args
);
294 DPRINTF( "Ret %s() retval=%08lx ret=%08lx fs=%04lx\n",
295 buffer
, EAX_reg(context
), EIP_reg(context
), FS_reg(context
) );
296 DPRINTF(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
297 EAX_reg(context
), EBX_reg(context
), ECX_reg(context
),
298 EDX_reg(context
), ESI_reg(context
), EDI_reg(context
) );
299 DPRINTF(" ebp=%08lx esp=%08lx ds=%04lx es=%04lx gs=%04lx flags=%08lx\n",
300 EBP_reg(context
), ESP_reg(context
), DS_reg(context
),
301 ES_reg(context
), GS_reg(context
), EFL_reg(context
) );
303 SYSLEVEL_CheckNotLevel( 2 );
305 #endif /* __i386__ */