Release 960717
[wine/multimedia.git] / loader / ne_image.c
blobad5af2fedbcd68157f692722b196d3037a92ad08
1 #ifndef WINELIB
2 /*
3 * NE modules
5 * Copyright 1993 Robert J. Amstadt
6 * Copyright 1995 Alexandre Julliard
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <errno.h>
18 #include "neexe.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"
27 #include "xmalloc.h"
30 /***********************************************************************
31 * NE_LoadSegment
33 BOOL NE_LoadSegment( HMODULE16 hModule, WORD segnum )
35 NE_MODULE *pModule;
36 SEGTABLEENTRY *pSegTable, *pSeg;
37 WORD *pModuleTable;
38 WORD count, i, offset;
39 HMODULE16 module;
40 FARPROC16 address;
41 int fd;
42 struct relocation_entry_s *rep, *reloc_entries;
43 BYTE *func_name;
44 int size;
45 char* mem;
47 char buffer[100];
48 int ordinal, additive;
49 unsigned short *sp;
51 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
52 pSegTable = NE_SEG_TABLE( pModule );
53 pSeg = pSegTable + segnum - 1;
54 pModuleTable = NE_MODULE_TABLE( pModule );
56 if (!pSeg->filepos) return TRUE; /* No file image, just return */
58 fd = MODULE_OpenFile( hModule );
59 dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
60 segnum, pSeg->selector );
61 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
62 size = pSeg->size ? pSeg->size : 0x10000;
63 mem = GlobalLock16(pSeg->selector);
64 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1) {
65 #ifndef WINELIB
66 /* Implement self loading segments */
67 SELFLOADHEADER *selfloadheader;
68 STACK16FRAME *stack16Top;
69 WORD oldss, oldsp, oldselector, newselector;
70 selfloadheader = (SELFLOADHEADER *)
71 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
72 oldss = IF1632_Saved16_ss;
73 oldsp = IF1632_Saved16_sp;
74 oldselector = pSeg->selector;
75 IF1632_Saved16_ss = pModule->self_loading_sel;
76 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
77 stack16Top = CURRENT_STACK16;
78 stack16Top->saved_ss = 0;
79 stack16Top->saved_sp = 0;
80 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
81 stack16Top->entry_point = 0;
82 stack16Top->entry_ip = 0;
83 stack16Top->entry_cs = 0;
84 stack16Top->bp = 0;
85 stack16Top->ip = 0;
86 stack16Top->cs = 0;
87 /* FIXME: we probably need to pass a DOS file handle here */
88 newselector = CallTo16_word_www(selfloadheader->LoadAppSeg,
89 pModule->self_loading_sel, hModule, fd, segnum);
90 if (newselector != oldselector) {
91 /* Self loaders like creating their own selectors;
92 * they love asking for trouble to Wine developers
94 if (segnum == pModule->dgroup) {
95 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
96 PTR_SEG_OFF_TO_LIN(newselector,0),
97 pSeg->minsize ? pSeg->minsize : 0x10000);
98 FreeSelector(newselector);
99 pSeg->selector = oldselector;
100 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
101 "Old selector is %d, new one is %d", oldselector, newselector);
102 } else {
103 FreeSelector(pSeg->selector);
104 pSeg->selector = newselector;
108 IF1632_Saved16_ss = oldss;
109 IF1632_Saved16_sp = oldsp;
110 #else
111 fprintf(stderr,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
112 #endif
114 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
115 read(fd, mem, size);
116 else {
118 The following bit of code for "iterated segments" was written without
119 any documentation on the format of these segments. It seems to work,
120 but may be missing something. If you have any doco please either send
121 it to me or fix the code yourself. gfm@werple.mira.net.au
123 char* buff = xmalloc(size);
124 char* curr = buff;
125 read(fd, buff, size);
126 while(curr < buff + size) {
127 unsigned int rept = *((short*) curr)++;
128 unsigned int len = *((short*) curr)++;
129 for(; rept > 0; rept--) {
130 char* bytes = curr;
131 unsigned int byte;
132 for(byte = 0; byte < len; byte++)
133 *mem++ = *bytes++;
135 curr += len;
137 free(buff);
140 pSeg->flags |= NE_SEGFLAGS_LOADED;
141 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
142 return TRUE; /* No relocation data, we are done */
144 read( fd, &count, sizeof(count) );
145 if (!count) return TRUE;
147 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector %04x\n",
148 *((BYTE *)pModule + pModule->name_table),
149 *((BYTE *)pModule + pModule->name_table),
150 (char *)pModule + pModule->name_table + 1,
151 segnum, pSeg->selector );
153 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
154 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
155 count * sizeof(struct relocation_entry_s))
157 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
158 return FALSE;
162 * Go through the relocation table on entry at a time.
164 rep = reloc_entries;
165 for (i = 0; i < count; i++, rep++)
168 * Get the target address corresponding to this entry.
171 /* If additive, there is no target chain list. Instead, add source
172 and target */
173 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
174 rep->relocation_type &= 0x3;
176 switch (rep->relocation_type)
178 case NE_RELTYPE_ORDINAL:
179 module = pModuleTable[rep->target1-1];
180 ordinal = rep->target2;
181 address = MODULE_GetEntryPoint( module, ordinal );
182 if (!address)
184 NE_MODULE *pTarget = MODULE_GetPtr( module );
185 if (!pTarget)
186 fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
187 module, rep->target1,
188 *((BYTE *)pModule + pModule->name_table),
189 *((BYTE *)pModule + pModule->name_table),
190 (char *)pModule + pModule->name_table + 1 );
191 else
192 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
193 *((BYTE *)pTarget + pTarget->name_table),
194 *((BYTE *)pTarget + pTarget->name_table),
195 (char *)pTarget + pTarget->name_table + 1,
196 ordinal );
198 if (debugging_fixup)
200 NE_MODULE *pTarget = MODULE_GetPtr( module );
201 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
202 *((BYTE *)pTarget + pTarget->name_table),
203 *((BYTE *)pTarget + pTarget->name_table),
204 (char *)pTarget + pTarget->name_table + 1,
205 ordinal, HIWORD(address), LOWORD(address) );
207 break;
209 case NE_RELTYPE_NAME:
210 module = pModuleTable[rep->target1-1];
211 func_name = (char *)pModule + pModule->import_table + rep->target2;
212 memcpy( buffer, func_name+1, *func_name );
213 buffer[*func_name] = '\0';
214 func_name = buffer;
215 ordinal = MODULE_GetOrdinal( module, func_name );
217 address = MODULE_GetEntryPoint( module, ordinal );
219 if (!address)
221 NE_MODULE *pTarget = MODULE_GetPtr( module );
222 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
223 *((BYTE *)pTarget + pTarget->name_table),
224 *((BYTE *)pTarget + pTarget->name_table),
225 (char *)pTarget + pTarget->name_table + 1, func_name );
227 if (debugging_fixup)
229 NE_MODULE *pTarget = MODULE_GetPtr( module );
230 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1,
231 *((BYTE *)pTarget + pTarget->name_table),
232 *((BYTE *)pTarget + pTarget->name_table),
233 (char *)pTarget + pTarget->name_table + 1,
234 func_name, HIWORD(address), LOWORD(address) );
236 break;
238 case NE_RELTYPE_INTERNAL:
239 if (rep->target1 == 0x00ff)
241 address = MODULE_GetEntryPoint( hModule, rep->target2 );
243 else
245 address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( pSegTable[rep->target1-1].selector, rep->target2 );
248 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
249 i + 1, HIWORD(address), LOWORD(address) );
250 break;
252 case NE_RELTYPE_OSFIXUP:
253 /* Relocation type 7:
255 * These appear to be used as fixups for the Windows
256 * floating point emulator. Let's just ignore them and
257 * try to use the hardware floating point. Linux should
258 * successfully emulate the coprocessor if it doesn't
259 * exist.
261 dprintf_fixup(stddeb,
262 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
263 i + 1, rep->address_type, rep->relocation_type,
264 rep->offset);
265 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
266 rep->target1, rep->target2);
267 continue;
269 default:
270 dprintf_fixup(stddeb,
271 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
272 i + 1, rep->address_type, rep->relocation_type,
273 rep->offset);
274 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
275 rep->target1, rep->target2);
276 free(reloc_entries);
277 return FALSE;
280 offset = rep->offset;
282 switch (rep->address_type)
284 case NE_RADDR_LOWBYTE:
285 do {
286 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
287 dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
288 pSeg->selector, offset, *sp, additive ? " additive":"");
289 offset = *sp;
290 if(additive)
291 *(unsigned char*)sp = (unsigned char)(((int)address+offset) & 0xFF);
292 else
293 *(unsigned char*)sp = (unsigned char)((int)address & 0xFF);
295 while (offset != 0xffff && !additive);
296 break;
298 case NE_RADDR_OFFSET16:
299 do {
300 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
301 dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
302 pSeg->selector, offset, *sp, additive ? " additive" : "" );
303 offset = *sp;
304 *sp = LOWORD(address);
305 if (additive) *sp += offset;
307 while (offset != 0xffff && !additive);
308 break;
310 case NE_RADDR_POINTER32:
311 do {
312 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
313 dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
314 pSeg->selector, offset, *sp, additive ? " additive" : "" );
315 offset = *sp;
316 *sp = LOWORD(address);
317 if (additive) *sp += offset;
318 *(sp+1) = HIWORD(address);
320 while (offset != 0xffff && !additive);
321 break;
323 case NE_RADDR_SELECTOR:
324 do {
325 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
326 dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
327 pSeg->selector, offset, *sp, additive ? " additive" : "" );
328 offset = *sp;
329 *sp = HIWORD(address);
330 /* Borland creates additive records with offset zero. Strange, but OK */
331 if(additive && offset)
332 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
334 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
335 while (offset && offset != 0xffff && !additive);
336 break;
338 default:
339 dprintf_fixup(stddeb,
340 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
341 i + 1, rep->address_type, rep->relocation_type,
342 rep->offset);
343 dprintf_fixup(stddeb,
344 "TARGET %04x %04x\n", rep->target1, rep->target2);
345 free(reloc_entries);
346 return FALSE;
350 free(reloc_entries);
351 return TRUE;
355 /***********************************************************************
356 * NE_FixupPrologs
358 * Fixup the exported functions prologs.
360 void NE_FixupPrologs( NE_MODULE *pModule )
362 #ifdef WINELIB
363 fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
364 #else
365 SEGTABLEENTRY *pSegTable;
366 WORD dgroup = 0;
367 WORD sel;
368 BYTE *p, *fixup_ptr, count;
370 pSegTable = NE_SEG_TABLE(pModule);
371 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
372 dgroup = pSegTable[pModule->dgroup-1].selector;
374 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self );
375 p = (BYTE *)pModule + pModule->entry_table;
376 while (*p)
378 if (p[1] == 0) /* Unused entry */
380 p += 2; /* Skip it */
381 continue;
383 if (p[1] == 0xfe) /* Constant entry */
385 p += 2 + *p * 3; /* Skip it */
386 continue;
389 /* Now fixup the entries of this bundle */
390 count = *p;
391 sel = p[1];
392 p += 2;
393 while (count-- > 0)
395 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
396 /* According to the output generated by TDUMP, the flags mean:
397 * 0x0001 function is exported
398 * 0x0002 Single data (seems to occur only in DLLs)
400 if (sel == 0xff) { /* moveable */
401 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
402 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
403 } else { /* fixed */
404 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
405 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
407 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
408 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
409 pModule->flags );
410 if (*p & 0x0001)
412 /* Verify the signature */
413 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
414 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
415 && fixup_ptr[2] == 0x90)
417 if (*p & 0x0002)
419 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
420 /* can this happen? */
421 fprintf( stderr, "FixupPrologs got confused\n" );
423 *fixup_ptr = 0xb8; /* MOV AX, */
424 *(WORD *)(fixup_ptr+1) = dgroup;
426 else
428 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
429 fixup_ptr[0] = 0x90; /* non-library: NOPs */
430 fixup_ptr[1] = 0x90;
431 fixup_ptr[2] = 0x90;
434 } else {
435 dprintf_fixup( stddeb, "Unknown signature\n" );
438 else
439 dprintf_module( stddeb,"\n");
440 p += (sel == 0xff) ? 6 : 3;
443 #endif
447 /***********************************************************************
448 * NE_InitDLL
450 * Call the DLL initialization code
452 static BOOL NE_InitDLL( HMODULE16 hModule )
454 #ifndef WINELIB
455 int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
456 NE_MODULE *pModule;
457 SEGTABLEENTRY *pSegTable;
459 /* Registers at initialization must be:
460 * cx heap size
461 * di library instance
462 * ds data segment if any
463 * es:si command line (always 0)
466 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
467 pSegTable = NE_SEG_TABLE( pModule );
469 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
470 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
471 if (!pModule->cs) return TRUE; /* no initialization code */
473 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
475 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
477 /* Not SINGLEDATA */
478 fprintf(stderr, "Library is not marked SINGLEDATA\n");
479 exit(1);
481 else /* DATA NONE DLL */
483 ds_reg = 0;
484 cx_reg = 0;
487 else /* DATA SINGLE DLL */
489 ds_reg = pSegTable[pModule->dgroup-1].selector;
490 cx_reg = pModule->heap_size;
493 cs_reg = pSegTable[pModule->cs-1].selector;
494 ip_reg = pModule->ip;
495 di_reg = ds_reg ? ds_reg : hModule;
496 bp_reg = IF1632_Saved16_sp + ((WORD)&((STACK16FRAME*)1)->bp - 1);
498 pModule->cs = 0; /* Don't initialize it twice */
499 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
500 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
501 return CallTo16_regs_( (FARPROC16)(cs_reg << 16 | ip_reg), ds_reg,
502 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
503 cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
504 #else
505 fprintf( stderr,"JBP: Ignoring call to LibMain\n" );
506 return FALSE;
507 #endif
511 /***********************************************************************
512 * NE_InitializeDLLs
514 * Initialize the loaded DLLs.
516 void NE_InitializeDLLs( HMODULE16 hModule )
518 NE_MODULE *pModule;
519 HMODULE16 *pDLL;
521 if (!(pModule = MODULE_GetPtr( hModule ))) return;
522 if (pModule->flags & NE_FFLAGS_WIN32)
524 PE_InitializeDLLs(hModule);
525 return;
527 if (pModule->dlls_to_init)
529 HANDLE to_init = pModule->dlls_to_init;
530 pModule->dlls_to_init = 0;
531 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
533 NE_InitializeDLLs( *pDLL );
534 NE_InitDLL( *pDLL );
536 GlobalFree16( to_init );
538 NE_InitDLL( hModule );
542 /***********************************************************************
543 * NE_PatchCodeHandle
545 * Needed for self-loading modules.
548 /* It does nothing */
549 void PatchCodeHandle(HANDLE hSel)
552 #endif /* WINELIB */