Release 951003
[wine/hacks.git] / loader / ne_image.c
blob9167a999d74a2af493b9fcf5080da97f57143261
1 /*
2 * NE modules
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <ctype.h>
15 #include <string.h>
16 #include <errno.h>
17 #include "neexe.h"
18 #include "dlls.h"
19 #include "windows.h"
20 #include "arch.h"
21 #include "selectors.h"
22 #include "callback.h"
23 #include "module.h"
24 #include "stackframe.h"
25 #include "stddebug.h"
26 #include "debug.h"
29 /***********************************************************************
30 * NE_LoadSegment
32 BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
34 NE_MODULE *pModule;
35 SEGTABLEENTRY *pSegTable, *pSeg;
36 WORD *pModuleTable;
37 WORD count, i, offset;
38 HMODULE module;
39 DWORD address;
40 int fd;
41 struct relocation_entry_s *rep, *reloc_entries;
42 BYTE *func_name;
43 int size;
44 char* mem;
46 char buffer[100];
47 int ordinal, additive;
48 unsigned short *sp;
50 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
51 pSegTable = NE_SEG_TABLE( pModule );
52 pSeg = pSegTable + segnum - 1;
53 pModuleTable = NE_MODULE_TABLE( pModule );
55 if (!pSeg->filepos) return TRUE; /* No file image, just return */
57 fd = MODULE_OpenFile( hModule );
58 dprintf_module( stddeb, "Loading segment %d, selector="NPFMT"\n",
59 segnum, pSeg->selector );
60 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
61 size = pSeg->size ? pSeg->size : 0x10000;
62 mem = GlobalLock(pSeg->selector);
63 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1) {
64 #ifndef WINELIB
65 /* Implement self loading segments */
66 SELFLOADHEADER *selfloadheader;
67 WORD oldss, oldsp, oldselector, newselector;
68 selfloadheader = (SELFLOADHEADER *)
69 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
70 oldss = IF1632_Saved16_ss;
71 oldsp = IF1632_Saved16_sp;
72 oldselector = pSeg->selector;
73 IF1632_Saved16_ss = pModule->self_loading_sel;
74 IF1632_Saved16_sp = 0xFF00;
75 newselector = CallTo16_word_www(selfloadheader->LoadAppSeg,
76 pModule->self_loading_sel, hModule, fd, segnum);
77 if (newselector != oldselector) {
78 /* Self loaders like creating their own selectors;
79 * they love asking for trouble to Wine developers
81 if (segnum == pModule->dgroup) {
82 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
83 PTR_SEG_OFF_TO_LIN(newselector,0),
84 pSeg->minsize ? pSeg->minsize : 0x10000);
85 FreeSelector(newselector);
86 pSeg->selector = oldselector;
87 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
88 "Old selector is %d, new one is %d", oldselector, newselector);
89 } else {
90 FreeSelector(pSeg->selector);
91 pSeg->selector = newselector;
95 IF1632_Saved16_ss = oldss;
96 IF1632_Saved16_sp = oldsp;
97 #else
98 fprintf(stderr,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
99 #endif
101 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
102 read(fd, mem, size);
103 else {
105 The following bit of code for "iterated segments" was written without
106 any documentation on the format of these segments. It seems to work,
107 but may be missing something. If you have any doco please either send
108 it to me or fix the code yourself. gfm@werple.mira.net.au
110 char* buff = malloc(size);
111 char* curr = buff;
112 read(fd, buff, size);
113 while(curr < buff + size) {
114 unsigned int rept = *((short*) curr)++;
115 unsigned int len = *((short*) curr)++;
116 for(; rept > 0; rept--) {
117 char* bytes = curr;
118 unsigned int byte;
119 for(byte = 0; byte < len; byte++)
120 *mem++ = *bytes++;
122 curr += len;
124 free(buff);
127 pSeg->flags |= NE_SEGFLAGS_LOADED;
128 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
129 return TRUE; /* No relocation data, we are done */
131 read( fd, &count, sizeof(count) );
132 if (!count) return TRUE;
134 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector "NPFMT"\n",
135 *((BYTE *)pModule + pModule->name_table),
136 *((BYTE *)pModule + pModule->name_table),
137 (char *)pModule + pModule->name_table + 1,
138 segnum, pSeg->selector );
140 reloc_entries = (struct relocation_entry_s *)malloc(count * sizeof(struct relocation_entry_s));
141 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
142 count * sizeof(struct relocation_entry_s))
144 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
145 return FALSE;
149 * Go through the relocation table on entry at a time.
151 rep = reloc_entries;
152 for (i = 0; i < count; i++, rep++)
155 * Get the target address corresponding to this entry.
158 /* If additive, there is no target chain list. Instead, add source
159 and target */
160 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
161 rep->relocation_type &= 0x3;
163 switch (rep->relocation_type)
165 case NE_RELTYPE_ORDINAL:
166 module = pModuleTable[rep->target1-1];
167 ordinal = rep->target2;
168 address = MODULE_GetEntryPoint( module, ordinal );
169 if (!address)
171 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
172 if (!pTarget)
173 fprintf( stderr, "Module not found: "NPFMT", reference %d of module %*.*s\n",
174 module, rep->target1,
175 *((BYTE *)pModule + pModule->name_table),
176 *((BYTE *)pModule + pModule->name_table),
177 (char *)pModule + pModule->name_table + 1 );
178 else
179 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
180 *((BYTE *)pTarget + pTarget->name_table),
181 *((BYTE *)pTarget + pTarget->name_table),
182 (char *)pTarget + pTarget->name_table + 1,
183 ordinal );
185 if (debugging_fixup)
187 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
188 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
189 *((BYTE *)pTarget + pTarget->name_table),
190 *((BYTE *)pTarget + pTarget->name_table),
191 (char *)pTarget + pTarget->name_table + 1,
192 ordinal, HIWORD(address), LOWORD(address) );
194 break;
196 case NE_RELTYPE_NAME:
197 module = pModuleTable[rep->target1-1];
198 func_name = (char *)pModule + pModule->import_table + rep->target2;
199 memcpy( buffer, func_name+1, *func_name );
200 buffer[*func_name] = '\0';
201 func_name = buffer;
202 ordinal = MODULE_GetOrdinal( module, func_name );
204 address = MODULE_GetEntryPoint( module, ordinal );
206 if (!address)
208 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
209 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
210 *((BYTE *)pTarget + pTarget->name_table),
211 *((BYTE *)pTarget + pTarget->name_table),
212 (char *)pTarget + pTarget->name_table + 1, func_name );
214 if (debugging_fixup)
216 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
217 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1,
218 *((BYTE *)pTarget + pTarget->name_table),
219 *((BYTE *)pTarget + pTarget->name_table),
220 (char *)pTarget + pTarget->name_table + 1,
221 func_name, HIWORD(address), LOWORD(address) );
223 break;
225 case NE_RELTYPE_INTERNAL:
226 if (rep->target1 == 0x00ff)
228 address = MODULE_GetEntryPoint( hModule, rep->target2 );
230 else
232 address = MAKELONG( rep->target2, pSegTable[rep->target1-1].selector );
235 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
236 i + 1, HIWORD(address), LOWORD(address) );
237 break;
239 case NE_RELTYPE_OSFIXUP:
240 /* Relocation type 7:
242 * These appear to be used as fixups for the Windows
243 * floating point emulator. Let's just ignore them and
244 * try to use the hardware floating point. Linux should
245 * successfully emulate the coprocessor if it doesn't
246 * exist.
248 dprintf_fixup(stddeb,
249 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
250 i + 1, rep->address_type, rep->relocation_type,
251 rep->offset);
252 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
253 rep->target1, rep->target2);
254 continue;
256 default:
257 dprintf_fixup(stddeb,
258 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
259 i + 1, rep->address_type, rep->relocation_type,
260 rep->offset);
261 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
262 rep->target1, rep->target2);
263 free(reloc_entries);
264 return FALSE;
267 offset = rep->offset;
269 switch (rep->address_type)
271 case NE_RADDR_LOWBYTE:
272 do {
273 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
274 dprintf_fixup(stddeb," "NPFMT":%04x:%04x BYTE%s\n",
275 pSeg->selector, offset, *sp, additive ? " additive":"");
276 offset = *sp;
277 if(additive)
278 *(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
279 else
280 *(unsigned char*)sp = (unsigned char)(address & 0xFF);
282 while (offset != 0xffff && !additive);
283 break;
285 case NE_RADDR_OFFSET16:
286 do {
287 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
288 dprintf_fixup(stddeb," "NPFMT":%04x:%04x OFFSET16%s\n",
289 pSeg->selector, offset, *sp, additive ? " additive" : "" );
290 offset = *sp;
291 *sp = LOWORD(address);
292 if (additive) *sp += offset;
294 while (offset != 0xffff && !additive);
295 break;
297 case NE_RADDR_POINTER32:
298 do {
299 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
300 dprintf_fixup(stddeb," "NPFMT":%04x:%04x POINTER32%s\n",
301 pSeg->selector, offset, *sp, additive ? " additive" : "" );
302 offset = *sp;
303 *sp = LOWORD(address);
304 if (additive) *sp += offset;
305 *(sp+1) = HIWORD(address);
307 while (offset != 0xffff && !additive);
308 break;
310 case NE_RADDR_SELECTOR:
311 do {
312 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
313 dprintf_fixup(stddeb," "NPFMT":%04x:%04x SELECTOR%s\n",
314 pSeg->selector, offset, *sp, additive ? " additive" : "" );
315 offset = *sp;
316 *sp = HIWORD(address);
317 /* Borland creates additive records with offset zero. Strange, but OK */
318 if(additive && offset)
319 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
321 while (offset != 0xffff && !additive);
322 break;
324 default:
325 dprintf_fixup(stddeb,
326 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
327 i + 1, rep->address_type, rep->relocation_type,
328 rep->offset);
329 dprintf_fixup(stddeb,
330 "TARGET %04x %04x\n", rep->target1, rep->target2);
331 free(reloc_entries);
332 return FALSE;
336 free(reloc_entries);
337 return TRUE;
341 /***********************************************************************
342 * NE_FixupPrologs
344 * Fixup the exported functions prologs.
346 void NE_FixupPrologs( HMODULE hModule )
348 #ifdef WINELIB
349 fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
350 #else
351 NE_MODULE *pModule;
352 SEGTABLEENTRY *pSegTable;
353 WORD dgroup = 0;
354 WORD sel;
355 BYTE *p, *fixup_ptr, count;
357 pModule = (NE_MODULE *)GlobalLock( hModule );
358 pSegTable = NE_SEG_TABLE(pModule);
359 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
360 dgroup = pSegTable[pModule->dgroup-1].selector;
362 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule );
363 p = (BYTE *)pModule + pModule->entry_table;
364 while (*p)
366 if (p[1] == 0) /* Unused entry */
368 p += 2; /* Skip it */
369 continue;
371 if (p[1] == 0xfe) /* Constant entry */
373 p += 2 + *p * 3; /* Skip it */
374 continue;
377 /* Now fixup the entries of this bundle */
378 count = *p;
379 sel = p[1];
380 p += 2;
381 while (count-- > 0)
383 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
384 /* According to the output generated by TDUMP, the flags mean:
385 * 0x0001 function is exported
386 * 0x0002 Single data (seems to occur only in DLLs)
388 if (sel == 0xff) { /* moveable */
389 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
390 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
391 } else { /* fixed */
392 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
393 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
395 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
396 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
397 pModule->flags );
398 if (*p & 0x0001)
400 /* Verify the signature */
401 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
402 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
403 && fixup_ptr[2] == 0x90)
405 if (*p & 0x0002)
407 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
408 /* can this happen? */
409 fprintf( stderr, "FixupPrologs got confused\n" );
411 *fixup_ptr = 0xb8; /* MOV AX, */
412 *(WORD *)(fixup_ptr+1) = dgroup;
414 else
416 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
417 fixup_ptr[0] = 0x90; /* non-library: NOPs */
418 fixup_ptr[1] = 0x90;
419 fixup_ptr[2] = 0x90;
422 } else {
423 dprintf_fixup( stddeb, "Unknown signature\n" );
426 else
427 dprintf_module( stddeb,"\n");
428 p += (sel == 0xff) ? 6 : 3;
431 #endif
435 /***********************************************************************
436 * NE_InitDLL
438 * Call the DLL initialization code
440 static BOOL NE_InitDLL( HMODULE hModule )
442 #ifndef WINELIB
443 int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
444 NE_MODULE *pModule;
445 SEGTABLEENTRY *pSegTable;
447 /* Registers at initialization must be:
448 * cx heap size
449 * di library instance
450 * ds data segment if any
451 * es:si command line (always 0)
454 pModule = (NE_MODULE *)GlobalLock( hModule );
455 pSegTable = NE_SEG_TABLE( pModule );
457 if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/
458 if (!pModule->cs) return TRUE; /* no initialization code */
460 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
462 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
464 /* Not SINGLEDATA */
465 fprintf(stderr, "Library is not marked SINGLEDATA\n");
466 exit(1);
468 else /* DATA NONE DLL */
470 ds_reg = 0;
471 cx_reg = 0;
474 else /* DATA SINGLE DLL */
476 ds_reg = pSegTable[pModule->dgroup-1].selector;
477 cx_reg = pModule->heap_size;
480 cs_reg = pSegTable[pModule->cs-1].selector;
481 ip_reg = pModule->ip;
482 di_reg = ds_reg ? ds_reg : hModule;
483 bp_reg = IF1632_Saved16_sp + ((WORD)&((STACK16FRAME*)1)->bp - 1);
485 pModule->cs = 0; /* Don't initialize it twice */
486 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
487 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
488 return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
489 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
490 cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
491 #else
492 fprintf( stderr,"JBP: Ignoring call to LibMain\n" );
493 return FALSE;
494 #endif
498 /***********************************************************************
499 * NE_InitializeDLLs
501 * Initialize the loaded DLLs.
503 void NE_InitializeDLLs( HMODULE hModule )
505 NE_MODULE *pModule;
506 HMODULE *pDLL;
508 pModule = (NE_MODULE *)GlobalLock( hModule );
509 if (pModule->dlls_to_init)
511 HANDLE to_init = pModule->dlls_to_init;
512 pModule->dlls_to_init = 0;
513 for (pDLL = (HMODULE *)GlobalLock( to_init ); *pDLL; pDLL++)
515 NE_InitializeDLLs( *pDLL );
516 NE_InitDLL( *pDLL );
518 GlobalFree( to_init );
520 NE_InitDLL( hModule );
524 /***********************************************************************
525 * NE_PatchCodeHandle
527 * Needed for self-loading modules.
530 /* It does nothing */
531 void PatchCodeHandle(HANDLE hSel)