Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 1 | /* |
| 2 | * 386-specific Win32 relay functions |
| 3 | * |
| 4 | * Copyright 1997 Alexandre Julliard |
| 5 | */ |
| 6 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 7 | |
| 8 | #include <assert.h> |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 9 | #include <string.h> |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 10 | #include <stdio.h> |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 11 | #include "winnt.h" |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 12 | #include "selectors.h" |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 13 | #include "stackframe.h" |
Ulrich Weigand | 6cd829b | 1999-05-22 16:29:39 +0000 | [diff] [blame] | 14 | #include "syslevel.h" |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 15 | #include "main.h" |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 16 | #include "module.h" |
| 17 | #include "process.h" |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 18 | #include "debugtools.h" |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 19 | |
Alexandre Julliard | 0dd3655 | 2000-01-29 19:49:58 +0000 | [diff] [blame] | 20 | DEFAULT_DEBUG_CHANNEL(relay); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 21 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 22 | char **debug_relay_excludelist = NULL, **debug_relay_includelist = NULL; |
| 23 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 24 | /*********************************************************************** |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 25 | * RELAY_ShowDebugmsgRelay |
| 26 | * |
| 27 | * Simple function to decide if a particular debugging message is |
| 28 | * wanted. Called from RELAY_CallFrom32 and from in if1632/relay.c |
| 29 | */ |
| 30 | int RELAY_ShowDebugmsgRelay(const char *func) { |
| 31 | |
| 32 | if(debug_relay_excludelist || debug_relay_includelist) { |
| 33 | const char *term = strchr(func, ':'); |
| 34 | char **listitem; |
| 35 | int len, len2, itemlen, show; |
| 36 | |
| 37 | if(debug_relay_excludelist) { |
| 38 | show = 1; |
| 39 | listitem = debug_relay_excludelist; |
| 40 | } else { |
| 41 | show = 0; |
| 42 | listitem = debug_relay_includelist; |
| 43 | } |
| 44 | assert(term); |
| 45 | assert(strlen(term) > 2); |
| 46 | len = term - func; |
| 47 | len2 = strchr(func, '.') - func; |
| 48 | assert(len2 && len2 > 0 && len2 < 64); |
| 49 | term += 2; |
| 50 | for(; *listitem; listitem++) { |
| 51 | itemlen = strlen(*listitem); |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 52 | if((itemlen == len && !strncasecmp(*listitem, func, len)) || |
| 53 | (itemlen == len2 && !strncasecmp(*listitem, func, len2)) || |
Alexandre Julliard | cb10fda | 2000-08-06 02:41:16 +0000 | [diff] [blame] | 54 | !strcasecmp(*listitem, term)) { |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 55 | show = !show; |
| 56 | break; |
| 57 | } |
| 58 | } |
| 59 | return show; |
| 60 | } |
| 61 | return 1; |
| 62 | } |
| 63 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 64 | |
Ulrich Weigand | 6ca85a5 | 1999-11-14 21:28:57 +0000 | [diff] [blame] | 65 | #ifdef __i386__ |
| 66 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 67 | typedef struct |
| 68 | { |
| 69 | BYTE call; /* 0xe8 call callfrom32 (relative) */ |
| 70 | DWORD callfrom32 WINE_PACKED; /* RELAY_CallFrom32 relative addr */ |
| 71 | BYTE ret; /* 0xc2 ret $n or 0xc3 ret */ |
| 72 | WORD args; /* nb of args to remove from the stack */ |
Alexandre Julliard | a837849 | 2000-10-01 01:33:50 +0000 | [diff] [blame] | 73 | void *orig; /* original entry point */ |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 74 | DWORD argtypes; /* argument types */ |
| 75 | } DEBUG_ENTRY_POINT; |
| 76 | |
| 77 | |
| 78 | /*********************************************************************** |
| 79 | * find_exported_name |
| 80 | * |
| 81 | * Find the name of an exported function. |
| 82 | */ |
| 83 | static const char *find_exported_name( const char *module, |
| 84 | IMAGE_EXPORT_DIRECTORY *exp, int ordinal ) |
| 85 | { |
| 86 | int i; |
| 87 | const char *ret = NULL; |
| 88 | |
| 89 | WORD *ordptr = (WORD *)(module + exp->AddressOfNameOrdinals); |
| 90 | for (i = 0; i < exp->NumberOfNames; i++, ordptr++) |
| 91 | if (*ordptr + exp->Base == ordinal) break; |
| 92 | if (i < exp->NumberOfNames) |
| 93 | ret = module + ((DWORD*)(module + exp->AddressOfNames))[i]; |
| 94 | return ret; |
| 95 | } |
| 96 | |
| 97 | |
| 98 | /*********************************************************************** |
| 99 | * get_entry_point |
| 100 | * |
| 101 | * Get the name of the DLL entry point corresponding to a relay address. |
| 102 | */ |
| 103 | static void get_entry_point( char *buffer, DEBUG_ENTRY_POINT *relay ) |
| 104 | { |
| 105 | IMAGE_DATA_DIRECTORY *dir; |
| 106 | IMAGE_EXPORT_DIRECTORY *exp = NULL; |
| 107 | DEBUG_ENTRY_POINT *debug; |
| 108 | char *base = NULL; |
| 109 | const char *name; |
| 110 | int ordinal = 0; |
| 111 | WINE_MODREF *wm; |
| 112 | |
| 113 | /* First find the module */ |
| 114 | |
| 115 | for (wm = PROCESS_Current()->modref_list; wm; wm = wm->next) |
| 116 | { |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 117 | if (!(wm->flags & WINE_MODREF_INTERNAL)) continue; |
| 118 | base = (char *)wm->module; |
| 119 | dir = &PE_HEADER(base)->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY]; |
| 120 | if (!dir->Size) continue; |
| 121 | exp = (IMAGE_EXPORT_DIRECTORY *)(base + dir->VirtualAddress); |
| 122 | debug = (DEBUG_ENTRY_POINT *)((char *)exp + dir->Size); |
| 123 | if (debug <= relay && relay < debug + exp->NumberOfFunctions) |
| 124 | { |
| 125 | ordinal = relay - debug; |
| 126 | break; |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | /* Now find the function */ |
| 131 | |
| 132 | name = find_exported_name( base, exp, ordinal + exp->Base ); |
| 133 | sprintf( buffer, "%s.%ld: %s", base + exp->Name, ordinal + exp->Base, name ? name : "@" ); |
| 134 | } |
| 135 | |
| 136 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 137 | /*********************************************************************** |
| 138 | * RELAY_PrintArgs |
| 139 | */ |
| 140 | static inline void RELAY_PrintArgs( int *args, int nb_args, unsigned int typemask ) |
| 141 | { |
| 142 | while (nb_args--) |
| 143 | { |
| 144 | if ((typemask & 3) && HIWORD(*args)) |
| 145 | { |
| 146 | if (typemask & 2) |
Francois Gouget | e73b8b8 | 1999-12-26 00:40:37 +0000 | [diff] [blame] | 147 | DPRINTF( "%08x %s", *args, debugstr_w((LPWSTR)*args) ); |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 148 | else |
| 149 | DPRINTF( "%08x %s", *args, debugstr_a((LPCSTR)*args) ); |
| 150 | } |
| 151 | else DPRINTF( "%08x", *args ); |
| 152 | if (nb_args) DPRINTF( "," ); |
| 153 | args++; |
| 154 | typemask >>= 2; |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | |
Alexandre Julliard | 3f2b2d5 | 2000-10-12 20:55:26 +0000 | [diff] [blame^] | 159 | typedef LONGLONG WINAPI (*LONGLONG_FARPROC)(); |
| 160 | |
Alexandre Julliard | ebfc0fe | 1998-06-28 18:40:26 +0000 | [diff] [blame] | 161 | /*********************************************************************** |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 162 | * RELAY_CallFrom32 |
| 163 | * |
| 164 | * Stack layout on entry to this function: |
| 165 | * ... ... |
| 166 | * (esp+12) arg2 |
| 167 | * (esp+8) arg1 |
| 168 | * (esp+4) ret_addr |
| 169 | * (esp) return addr to relay code |
| 170 | */ |
Alexandre Julliard | a837849 | 2000-10-01 01:33:50 +0000 | [diff] [blame] | 171 | static LONGLONG RELAY_CallFrom32( int ret_addr, ... ) |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 172 | { |
Alexandre Julliard | a837849 | 2000-10-01 01:33:50 +0000 | [diff] [blame] | 173 | LONGLONG ret; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 174 | char buffer[80]; |
Alexandre Julliard | a837849 | 2000-10-01 01:33:50 +0000 | [diff] [blame] | 175 | BOOL ret64; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 176 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 177 | int *args = &ret_addr + 1; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 178 | /* Relay addr is the return address for this function */ |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 179 | BYTE *relay_addr = (BYTE *)__builtin_return_address(0); |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 180 | DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5); |
| 181 | WORD nb_args = relay->args / sizeof(int); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 182 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 183 | get_entry_point( buffer, relay ); |
| 184 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 185 | DPRINTF( "Call %s(", buffer ); |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 186 | RELAY_PrintArgs( args, nb_args, relay->argtypes ); |
Alexandre Julliard | 916f975 | 2000-02-26 16:51:13 +0000 | [diff] [blame] | 187 | DPRINTF( ") ret=%08x fs=%04x\n", ret_addr, __get_fs() ); |
Alexandre Julliard | a837849 | 2000-10-01 01:33:50 +0000 | [diff] [blame] | 188 | ret64 = (relay->argtypes & 0x80000000) && (nb_args < 16); |
Marcus Meissner | 38980e4 | 1998-11-22 14:12:36 +0000 | [diff] [blame] | 189 | |
Peter Ganten | 331f80e | 2000-08-11 12:52:56 +0000 | [diff] [blame] | 190 | /* the user driver functions may be called with the window lock held */ |
| 191 | if (memcmp( buffer, "x11drv.", 7 ) && memcmp( buffer, "ttydrv.", 7 )) |
| 192 | SYSLEVEL_CheckNotLevel( 2 ); |
Ulrich Weigand | 6cd829b | 1999-05-22 16:29:39 +0000 | [diff] [blame] | 193 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 194 | if (relay->ret == 0xc3) /* cdecl */ |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 195 | { |
Alexandre Julliard | a837849 | 2000-10-01 01:33:50 +0000 | [diff] [blame] | 196 | LONGLONG (*cfunc)() = relay->orig; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 197 | switch(nb_args) |
| 198 | { |
| 199 | case 0: ret = cfunc(); break; |
| 200 | case 1: ret = cfunc(args[0]); break; |
| 201 | case 2: ret = cfunc(args[0],args[1]); break; |
| 202 | case 3: ret = cfunc(args[0],args[1],args[2]); break; |
| 203 | case 4: ret = cfunc(args[0],args[1],args[2],args[3]); break; |
| 204 | case 5: ret = cfunc(args[0],args[1],args[2],args[3],args[4]); break; |
| 205 | case 6: ret = cfunc(args[0],args[1],args[2],args[3],args[4], |
| 206 | args[5]); break; |
| 207 | case 7: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 208 | args[6]); break; |
| 209 | case 8: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 210 | args[6],args[7]); break; |
| 211 | case 9: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 212 | args[6],args[7],args[8]); break; |
| 213 | case 10: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 214 | args[6],args[7],args[8],args[9]); break; |
| 215 | case 11: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 216 | args[6],args[7],args[8],args[9],args[10]); break; |
| 217 | case 12: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 218 | args[6],args[7],args[8],args[9],args[10], |
| 219 | args[11]); break; |
| 220 | case 13: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 221 | args[6],args[7],args[8],args[9],args[10],args[11], |
| 222 | args[12]); break; |
| 223 | case 14: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 224 | args[6],args[7],args[8],args[9],args[10],args[11], |
| 225 | args[12],args[13]); break; |
| 226 | case 15: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 227 | args[6],args[7],args[8],args[9],args[10],args[11], |
| 228 | args[12],args[13],args[14]); break; |
Marcus Meissner | 219cfd8 | 1999-02-24 13:05:13 +0000 | [diff] [blame] | 229 | case 16: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5], |
| 230 | args[6],args[7],args[8],args[9],args[10],args[11], |
| 231 | args[12],args[13],args[14],args[15]); break; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 232 | default: |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 233 | ERR( "Unsupported nb of args %d\n", nb_args ); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 234 | assert(FALSE); |
| 235 | } |
| 236 | } |
| 237 | else /* stdcall */ |
| 238 | { |
Alexandre Julliard | 3f2b2d5 | 2000-10-12 20:55:26 +0000 | [diff] [blame^] | 239 | LONGLONG_FARPROC func = relay->orig; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 240 | switch(nb_args) |
| 241 | { |
| 242 | case 0: ret = func(); break; |
| 243 | case 1: ret = func(args[0]); break; |
| 244 | case 2: ret = func(args[0],args[1]); break; |
| 245 | case 3: ret = func(args[0],args[1],args[2]); break; |
| 246 | case 4: ret = func(args[0],args[1],args[2],args[3]); break; |
| 247 | case 5: ret = func(args[0],args[1],args[2],args[3],args[4]); break; |
| 248 | case 6: ret = func(args[0],args[1],args[2],args[3],args[4], |
| 249 | args[5]); break; |
| 250 | case 7: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 251 | args[6]); break; |
| 252 | case 8: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 253 | args[6],args[7]); break; |
| 254 | case 9: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 255 | args[6],args[7],args[8]); break; |
| 256 | case 10: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 257 | args[6],args[7],args[8],args[9]); break; |
| 258 | case 11: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 259 | args[6],args[7],args[8],args[9],args[10]); break; |
| 260 | case 12: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 261 | args[6],args[7],args[8],args[9],args[10], |
| 262 | args[11]); break; |
| 263 | case 13: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 264 | args[6],args[7],args[8],args[9],args[10],args[11], |
| 265 | args[12]); break; |
| 266 | case 14: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 267 | args[6],args[7],args[8],args[9],args[10],args[11], |
| 268 | args[12],args[13]); break; |
| 269 | case 15: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 270 | args[6],args[7],args[8],args[9],args[10],args[11], |
| 271 | args[12],args[13],args[14]); break; |
Marcus Meissner | 219cfd8 | 1999-02-24 13:05:13 +0000 | [diff] [blame] | 272 | case 16: ret = func(args[0],args[1],args[2],args[3],args[4],args[5], |
| 273 | args[6],args[7],args[8],args[9],args[10],args[11], |
| 274 | args[12],args[13],args[14],args[15]); break; |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 275 | default: |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 276 | ERR( "Unsupported nb of args %d\n", nb_args ); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 277 | assert(FALSE); |
| 278 | } |
| 279 | } |
Alexandre Julliard | a837849 | 2000-10-01 01:33:50 +0000 | [diff] [blame] | 280 | if (ret64) |
| 281 | DPRINTF( "Ret %s() retval=%08x%08x ret=%08x fs=%04x\n", |
| 282 | buffer, (UINT)(ret >> 32), (UINT)ret, ret_addr, __get_fs() ); |
| 283 | else |
| 284 | DPRINTF( "Ret %s() retval=%08x ret=%08x fs=%04x\n", |
| 285 | buffer, (UINT)ret, ret_addr, __get_fs() ); |
Ulrich Weigand | 6cd829b | 1999-05-22 16:29:39 +0000 | [diff] [blame] | 286 | |
Peter Ganten | 331f80e | 2000-08-11 12:52:56 +0000 | [diff] [blame] | 287 | if (memcmp( buffer, "x11drv.", 7 ) && memcmp( buffer, "ttydrv.", 7 )) |
| 288 | SYSLEVEL_CheckNotLevel( 2 ); |
Ulrich Weigand | 6cd829b | 1999-05-22 16:29:39 +0000 | [diff] [blame] | 289 | |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 290 | return ret; |
| 291 | } |
| 292 | |
| 293 | |
| 294 | /*********************************************************************** |
| 295 | * RELAY_CallFrom32Regs |
| 296 | * |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 297 | * Stack layout (esp is context->Esp, not the current %esp): |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 298 | * |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 299 | * ... |
| 300 | * (esp+4) first arg |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 301 | * (esp) return addr to caller |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 302 | * (esp-4) return addr to DEBUG_ENTRY_POINT |
| 303 | * (esp-8) ptr to relay entry code for RELAY_CallFrom32Regs |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 304 | * ... >128 bytes space free to be modified (ensured by the assembly glue) |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 305 | */ |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 306 | |
Ulrich Weigand | 6ca85a5 | 1999-11-14 21:28:57 +0000 | [diff] [blame] | 307 | void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context ); |
| 308 | DEFINE_REGS_ENTRYPOINT_0( RELAY_CallFrom32Regs, RELAY_DoCallFrom32Regs ) |
| 309 | void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context ) |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 310 | { |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 311 | char buffer[80]; |
| 312 | int* args; |
| 313 | FARPROC func; |
| 314 | BYTE *entry_point; |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 315 | |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 316 | BYTE *relay_addr = *((BYTE **)context->Esp - 1); |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 317 | DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5); |
| 318 | WORD nb_args = (relay->args & ~0x8000) / sizeof(int); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 319 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 320 | /* remove extra stuff from the stack */ |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 321 | context->Eip = stack32_pop(context); |
| 322 | args = (int *)context->Esp; |
| 323 | context->Esp += 4 * nb_args; |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 324 | |
| 325 | assert(TRACE_ON(relay)); |
| 326 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 327 | entry_point = (BYTE *)relay->orig; |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 328 | assert( *entry_point == 0xe8 /* lcall */ ); |
| 329 | func = *(FARPROC *)(entry_point + 5); |
| 330 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 331 | get_entry_point( buffer, relay ); |
| 332 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 333 | DPRINTF( "Call %s(", buffer ); |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 334 | RELAY_PrintArgs( args, nb_args, relay->argtypes ); |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 335 | DPRINTF( ") ret=%08lx fs=%04lx\n", context->Eip, context->SegFs ); |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 336 | |
| 337 | DPRINTF(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n", |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 338 | context->Eax, context->Ebx, context->Ecx, |
| 339 | context->Edx, context->Esi, context->Edi ); |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 340 | DPRINTF(" ebp=%08lx esp=%08lx ds=%04lx es=%04lx gs=%04lx flags=%08lx\n", |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 341 | context->Ebp, context->Esp, context->SegDs, |
| 342 | context->SegEs, context->SegGs, context->EFlags ); |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 343 | |
Ulrich Weigand | ac8cbe6 | 1999-05-23 09:17:48 +0000 | [diff] [blame] | 344 | SYSLEVEL_CheckNotLevel( 2 ); |
Ulrich Weigand | 6cd829b | 1999-05-22 16:29:39 +0000 | [diff] [blame] | 345 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 346 | /* Now call the real function */ |
| 347 | switch(nb_args) |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 348 | { |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 349 | case 0: func(context); break; |
| 350 | case 1: func(args[0],context); break; |
| 351 | case 2: func(args[0],args[1],context); break; |
| 352 | case 3: func(args[0],args[1],args[2],context); break; |
| 353 | case 4: func(args[0],args[1],args[2],args[3],context); break; |
| 354 | case 5: func(args[0],args[1],args[2],args[3],args[4],context); break; |
| 355 | case 6: func(args[0],args[1],args[2],args[3],args[4],args[5],context); break; |
| 356 | case 7: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],context); break; |
| 357 | case 8: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],context); break; |
| 358 | case 9: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8], |
| 359 | context); break; |
| 360 | case 10: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8], |
| 361 | args[9],context); break; |
| 362 | case 11: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8], |
| 363 | args[9],args[10],context); break; |
| 364 | case 12: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8], |
| 365 | args[9],args[10],args[11],context); break; |
| 366 | case 13: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8], |
| 367 | args[9],args[10],args[11],args[12],context); break; |
| 368 | case 14: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8], |
| 369 | args[9],args[10],args[11],args[12],args[13],context); break; |
| 370 | case 15: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8], |
| 371 | args[9],args[10],args[11],args[12],args[13],args[14],context); break; |
| 372 | case 16: func(args[0],args[1],args[2],args[3],args[4],args[5], args[6],args[7],args[8], |
| 373 | args[9],args[10],args[11],args[12],args[13],args[14],args[15],context); break; |
| 374 | default: |
| 375 | ERR( "Unsupported nb of args %d\n", nb_args ); |
| 376 | assert(FALSE); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 377 | } |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 378 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 379 | DPRINTF( "Ret %s() retval=%08lx ret=%08lx fs=%04lx\n", |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 380 | buffer, context->Eax, context->Eip, context->SegFs ); |
| 381 | |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 382 | DPRINTF(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n", |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 383 | context->Eax, context->Ebx, context->Ecx, |
| 384 | context->Edx, context->Esi, context->Edi ); |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 385 | DPRINTF(" ebp=%08lx esp=%08lx ds=%04lx es=%04lx gs=%04lx flags=%08lx\n", |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 386 | context->Ebp, context->Esp, context->SegDs, |
| 387 | context->SegEs, context->SegGs, context->EFlags ); |
Ulrich Weigand | 6cd829b | 1999-05-22 16:29:39 +0000 | [diff] [blame] | 388 | |
Ulrich Weigand | ac8cbe6 | 1999-05-23 09:17:48 +0000 | [diff] [blame] | 389 | SYSLEVEL_CheckNotLevel( 2 ); |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 390 | } |
Alexandre Julliard | 06b9789 | 1999-05-13 16:13:17 +0000 | [diff] [blame] | 391 | |
Alexandre Julliard | 246c360 | 2000-05-10 03:48:00 +0000 | [diff] [blame] | 392 | |
| 393 | /*********************************************************************** |
| 394 | * RELAY_SetupDLL |
| 395 | * |
| 396 | * Setup relay debugging for a built-in dll. |
| 397 | */ |
| 398 | void RELAY_SetupDLL( const char *module ) |
| 399 | { |
| 400 | IMAGE_DATA_DIRECTORY *dir; |
| 401 | IMAGE_EXPORT_DIRECTORY *exports; |
| 402 | DEBUG_ENTRY_POINT *debug; |
| 403 | DWORD *funcs; |
| 404 | int i; |
| 405 | const char *name, *dllname; |
| 406 | |
| 407 | dir = &PE_HEADER(module)->OptionalHeader.DataDirectory[IMAGE_FILE_EXPORT_DIRECTORY]; |
| 408 | if (!dir->Size) return; |
| 409 | exports = (IMAGE_EXPORT_DIRECTORY *)(module + dir->VirtualAddress); |
| 410 | debug = (DEBUG_ENTRY_POINT *)((char *)exports + dir->Size); |
| 411 | funcs = (DWORD *)(module + exports->AddressOfFunctions); |
| 412 | dllname = module + exports->Name; |
| 413 | |
| 414 | for (i = 0; i < exports->NumberOfFunctions; i++, funcs++, debug++) |
| 415 | { |
| 416 | int on = 1; |
| 417 | |
| 418 | if (!debug->call) continue; /* not a normal function */ |
| 419 | |
| 420 | if ((name = find_exported_name( module, exports, i + exports->Base ))) |
| 421 | { |
| 422 | char buffer[200]; |
| 423 | sprintf( buffer, "%s.%d: %s", dllname, i, name ); |
| 424 | on = RELAY_ShowDebugmsgRelay(buffer); |
| 425 | } |
| 426 | |
| 427 | if (on) |
| 428 | { |
| 429 | debug->call = 0xe8; /* call relative */ |
| 430 | if (debug->args & 0x8000) /* register func */ |
| 431 | debug->callfrom32 = (char *)RELAY_CallFrom32Regs - (char *)&debug->ret; |
| 432 | else |
| 433 | debug->callfrom32 = (char *)RELAY_CallFrom32 - (char *)&debug->ret; |
| 434 | } |
| 435 | else |
| 436 | { |
| 437 | debug->call = 0xe9; /* jmp relative */ |
| 438 | debug->callfrom32 = (char *)debug->orig - (char *)&debug->ret; |
| 439 | } |
| 440 | |
| 441 | debug->orig = (FARPROC)(module + (DWORD)*funcs); |
| 442 | *funcs = (char *)debug - module; |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | #else /* __i386__ */ |
| 447 | |
| 448 | void RELAY_SetupDLL( const char *module ) |
| 449 | { |
| 450 | } |
| 451 | |
| 452 | #endif /* __i386__ */ |