Release 970616
[wine/multimedia.git] / loader / ne_image.c
blob1937fdde2145dc355de76058ce61683e6a550981
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 "file.h"
24 #include "module.h"
25 #include "stackframe.h"
26 #include "stddebug.h"
27 #include "debug.h"
28 #include "xmalloc.h"
31 /***********************************************************************
32 * NE_LoadSegment
34 BOOL32 NE_LoadSegment( HMODULE16 hModule, WORD segnum )
36 NE_MODULE *pModule;
37 SEGTABLEENTRY *pSegTable, *pSeg;
38 WORD *pModuleTable;
39 WORD count, i, offset;
40 HMODULE16 module;
41 FARPROC16 address;
42 int fd;
43 struct relocation_entry_s *rep, *reloc_entries;
44 BYTE *func_name;
45 int size;
46 char* mem;
48 char buffer[100];
49 int ordinal, additive;
50 unsigned short *sp;
52 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
53 pSegTable = NE_SEG_TABLE( pModule );
54 pSeg = pSegTable + segnum - 1;
55 pModuleTable = NE_MODULE_TABLE( pModule );
57 if (!pSeg->filepos) return TRUE; /* No file image, just return */
59 fd = MODULE_OpenFile( hModule );
60 dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
61 segnum, pSeg->selector );
62 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
63 if (pSeg->size) size = pSeg->size;
64 else if (pSeg->minsize) size = pSeg->minsize;
65 else size = 0x10000;
66 mem = GlobalLock16(pSeg->selector);
67 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
69 /* Implement self loading segments */
70 SELFLOADHEADER *selfloadheader;
71 STACK16FRAME *stack16Top;
72 WORD oldss, oldsp, oldselector, newselector;
73 HFILE32 hf = FILE_DupUnixHandle( fd );
75 selfloadheader = (SELFLOADHEADER *)
76 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
77 oldss = IF1632_Saved16_ss;
78 oldsp = IF1632_Saved16_sp;
79 oldselector = pSeg->selector;
80 IF1632_Saved16_ss = pModule->self_loading_sel;
81 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
82 stack16Top = CURRENT_STACK16;
83 stack16Top->saved_ss = 0;
84 stack16Top->saved_sp = 0;
85 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
86 stack16Top->entry_point = 0;
87 stack16Top->entry_ip = 0;
88 stack16Top->entry_cs = 0;
89 stack16Top->bp = 0;
90 stack16Top->ip = 0;
91 stack16Top->cs = 0;
92 newselector = CallTo16_word_www( selfloadheader->LoadAppSeg,
93 hModule, hf, segnum );
94 _lclose32( hf );
95 if (newselector != oldselector) {
96 /* Self loaders like creating their own selectors;
97 * they love asking for trouble to Wine developers
99 if (segnum == pModule->dgroup) {
100 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
101 PTR_SEG_OFF_TO_LIN(newselector,0),
102 pSeg->minsize ? pSeg->minsize : 0x10000);
103 FreeSelector(newselector);
104 pSeg->selector = oldselector;
105 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
106 "Old selector is %d, new one is %d", oldselector, newselector);
107 } else {
108 FreeSelector(pSeg->selector);
109 pSeg->selector = newselector;
113 IF1632_Saved16_ss = oldss;
114 IF1632_Saved16_sp = oldsp;
116 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
117 read(fd, mem, size);
118 else {
120 The following bit of code for "iterated segments" was written without
121 any documentation on the format of these segments. It seems to work,
122 but may be missing something. If you have any doco please either send
123 it to me or fix the code yourself. gfm@werple.mira.net.au
125 char* buff = xmalloc(size);
126 char* curr = buff;
127 read(fd, buff, size);
128 while(curr < buff + size) {
129 unsigned int rept = *((short*) curr)++;
130 unsigned int len = *((short*) curr)++;
131 for(; rept > 0; rept--) {
132 char* bytes = curr;
133 unsigned int byte;
134 for(byte = 0; byte < len; byte++)
135 *mem++ = *bytes++;
137 curr += len;
139 free(buff);
142 pSeg->flags |= NE_SEGFLAGS_LOADED;
143 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
144 return TRUE; /* No relocation data, we are done */
146 read( fd, &count, sizeof(count) );
147 if (!count) return TRUE;
149 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector %04x\n",
150 *((BYTE *)pModule + pModule->name_table),
151 *((BYTE *)pModule + pModule->name_table),
152 (char *)pModule + pModule->name_table + 1,
153 segnum, pSeg->selector );
155 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
156 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
157 count * sizeof(struct relocation_entry_s))
159 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
160 return FALSE;
164 * Go through the relocation table on entry at a time.
166 rep = reloc_entries;
167 for (i = 0; i < count; i++, rep++)
170 * Get the target address corresponding to this entry.
173 /* If additive, there is no target chain list. Instead, add source
174 and target */
175 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
176 rep->relocation_type &= 0x3;
178 switch (rep->relocation_type)
180 case NE_RELTYPE_ORDINAL:
181 module = pModuleTable[rep->target1-1];
182 ordinal = rep->target2;
183 address = MODULE_GetEntryPoint( module, ordinal );
184 if (!address)
186 NE_MODULE *pTarget = MODULE_GetPtr( module );
187 if (!pTarget)
188 fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
189 module, rep->target1,
190 *((BYTE *)pModule + pModule->name_table),
191 *((BYTE *)pModule + pModule->name_table),
192 (char *)pModule + pModule->name_table + 1 );
193 else
194 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
195 *((BYTE *)pTarget + pTarget->name_table),
196 *((BYTE *)pTarget + pTarget->name_table),
197 (char *)pTarget + pTarget->name_table + 1,
198 ordinal );
200 if (debugging_fixup)
202 NE_MODULE *pTarget = MODULE_GetPtr( module );
203 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
204 *((BYTE *)pTarget + pTarget->name_table),
205 *((BYTE *)pTarget + pTarget->name_table),
206 (char *)pTarget + pTarget->name_table + 1,
207 ordinal, HIWORD(address), LOWORD(address) );
209 break;
211 case NE_RELTYPE_NAME:
212 module = pModuleTable[rep->target1-1];
213 func_name = (char *)pModule + pModule->import_table + rep->target2;
214 memcpy( buffer, func_name+1, *func_name );
215 buffer[*func_name] = '\0';
216 func_name = buffer;
217 ordinal = MODULE_GetOrdinal( module, func_name );
219 address = MODULE_GetEntryPoint( module, ordinal );
221 if (!address)
223 NE_MODULE *pTarget = MODULE_GetPtr( module );
224 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
225 *((BYTE *)pTarget + pTarget->name_table),
226 *((BYTE *)pTarget + pTarget->name_table),
227 (char *)pTarget + pTarget->name_table + 1, func_name );
229 if (debugging_fixup)
231 NE_MODULE *pTarget = MODULE_GetPtr( module );
232 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1,
233 *((BYTE *)pTarget + pTarget->name_table),
234 *((BYTE *)pTarget + pTarget->name_table),
235 (char *)pTarget + pTarget->name_table + 1,
236 func_name, HIWORD(address), LOWORD(address) );
238 break;
240 case NE_RELTYPE_INTERNAL:
241 if ((rep->target1 & 0xff) == 0xff)
243 address = MODULE_GetEntryPoint( hModule, rep->target2 );
245 else
247 address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( pSegTable[rep->target1-1].selector, rep->target2 );
250 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
251 i + 1, HIWORD(address), LOWORD(address) );
252 break;
254 case NE_RELTYPE_OSFIXUP:
255 /* Relocation type 7:
257 * These appear to be used as fixups for the Windows
258 * floating point emulator. Let's just ignore them and
259 * try to use the hardware floating point. Linux should
260 * successfully emulate the coprocessor if it doesn't
261 * exist.
263 dprintf_fixup(stddeb,
264 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
265 i + 1, rep->address_type, rep->relocation_type,
266 rep->offset);
267 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
268 rep->target1, rep->target2);
269 continue;
271 default:
272 dprintf_fixup(stddeb,
273 "WARNING: %d: ADDR TYPE %d, unknown TYPE %d, OFFSET %04x, ",
274 i + 1, rep->address_type, rep->relocation_type,
275 rep->offset);
276 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
277 rep->target1, rep->target2);
278 free(reloc_entries);
279 return FALSE;
282 offset = rep->offset;
284 /* Apparently, high bit of address_type is sometimes set; */
285 /* we ignore it for now */
286 if (rep->address_type > NE_RADDR_OFFSET32)
287 fprintf( stderr, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
288 MODULE_GetModuleName(hModule), rep->address_type );
290 switch (rep->address_type & 0x7f)
292 case NE_RADDR_LOWBYTE:
293 do {
294 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
295 dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
296 pSeg->selector, offset, *sp, additive ? " additive":"");
297 offset = *sp;
298 if(additive)
299 *(unsigned char*)sp = (unsigned char)(((int)address+offset) & 0xFF);
300 else
301 *(unsigned char*)sp = (unsigned char)((int)address & 0xFF);
303 while (offset != 0xffff && !additive);
304 break;
306 case NE_RADDR_OFFSET16:
307 do {
308 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
309 dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
310 pSeg->selector, offset, *sp, additive ? " additive" : "" );
311 offset = *sp;
312 *sp = LOWORD(address);
313 if (additive) *sp += offset;
315 while (offset != 0xffff && !additive);
316 break;
318 case NE_RADDR_POINTER32:
319 do {
320 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
321 dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
322 pSeg->selector, offset, *sp, additive ? " additive" : "" );
323 offset = *sp;
324 *sp = LOWORD(address);
325 if (additive) *sp += offset;
326 *(sp+1) = HIWORD(address);
328 while (offset != 0xffff && !additive);
329 break;
331 case NE_RADDR_SELECTOR:
332 do {
333 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
334 dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
335 pSeg->selector, offset, *sp, additive ? " additive" : "" );
336 offset = *sp;
337 *sp = HIWORD(address);
338 /* Borland creates additive records with offset zero. Strange, but OK */
339 if(additive && offset)
340 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
342 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
343 while (offset && offset != 0xffff && !additive);
344 break;
346 default:
347 dprintf_fixup(stddeb,
348 "WARNING: %d: unknown ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
349 i + 1, rep->address_type, rep->relocation_type,
350 rep->offset);
351 dprintf_fixup(stddeb,
352 "TARGET %04x %04x\n", rep->target1, rep->target2);
353 free(reloc_entries);
354 return FALSE;
358 free(reloc_entries);
359 return TRUE;
363 /***********************************************************************
364 * NE_FixupPrologs
366 * Fixup the exported functions prologs.
368 void NE_FixupPrologs( NE_MODULE *pModule )
370 SEGTABLEENTRY *pSegTable;
371 WORD dgroup = 0;
372 WORD sel;
373 BYTE *p, *fixup_ptr, count;
375 pSegTable = NE_SEG_TABLE(pModule);
376 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
377 dgroup = pSegTable[pModule->dgroup-1].selector;
379 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self );
380 p = (BYTE *)pModule + pModule->entry_table;
381 while (*p)
383 if (p[1] == 0) /* Unused entry */
385 p += 2; /* Skip it */
386 continue;
388 if (p[1] == 0xfe) /* Constant entry */
390 p += 2 + *p * 3; /* Skip it */
391 continue;
394 /* Now fixup the entries of this bundle */
395 count = *p;
396 sel = p[1];
397 p += 2;
398 while (count-- > 0)
400 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
401 /* According to the output generated by TDUMP, the flags mean:
402 * 0x0001 function is exported
403 * 0x0002 Single data (seems to occur only in DLLs)
405 if (sel == 0xff) { /* moveable */
406 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
407 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
408 } else { /* fixed */
409 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
410 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
412 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
413 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
414 pModule->flags );
415 if (*p & 0x0001)
417 /* Verify the signature */
418 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
419 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
420 && fixup_ptr[2] == 0x90)
422 if (*p & 0x0002)
424 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
426 /* can this happen? */
427 fprintf( stderr, "FixupPrologs got confused\n" );
429 else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
431 *fixup_ptr = 0xb8; /* MOV AX, */
432 *(WORD *)(fixup_ptr+1) = dgroup;
435 else
437 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
438 fixup_ptr[0] = 0x90; /* non-library: NOPs */
439 fixup_ptr[1] = 0x90;
440 fixup_ptr[2] = 0x90;
443 } else {
444 dprintf_fixup( stddeb, "Unknown signature\n" );
447 else
448 dprintf_module( stddeb,"\n");
449 p += (sel == 0xff) ? 6 : 3;
455 /***********************************************************************
456 * NE_InitDLL
458 * Call the DLL initialization code
460 static BOOL32 NE_InitDLL( HMODULE16 hModule )
462 NE_MODULE *pModule;
463 SEGTABLEENTRY *pSegTable;
464 CONTEXT context;
466 /* Registers at initialization must be:
467 * cx heap size
468 * di library instance
469 * ds data segment if any
470 * es:si command line (always 0)
473 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
474 pSegTable = NE_SEG_TABLE( pModule );
476 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
477 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
478 if (!pModule->cs) return TRUE; /* no initialization code */
480 memset( &context, 0, sizeof(context) );
482 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
484 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
486 /* Not SINGLEDATA */
487 fprintf(stderr, "Library is not marked SINGLEDATA\n");
488 exit(1);
490 else /* DATA NONE DLL */
492 DS_reg(&context) = 0;
493 ECX_reg(&context) = 0;
496 else /* DATA SINGLE DLL */
498 DS_reg(&context) = pSegTable[pModule->dgroup-1].selector;
499 ECX_reg(&context) = pModule->heap_size;
502 CS_reg(&context) = pSegTable[pModule->cs-1].selector;
503 EIP_reg(&context) = pModule->ip;
504 EBP_reg(&context) = IF1632_Saved16_sp + (WORD)&((STACK16FRAME*)0)->bp;
505 EDI_reg(&context) = DS_reg(&context) ? DS_reg(&context) : hModule;
508 pModule->cs = 0; /* Don't initialize it twice */
509 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
510 CS_reg(&context), IP_reg(&context), DS_reg(&context),
511 DI_reg(&context), CX_reg(&context) );
512 CallTo16_regs_( &context );
513 return TRUE;
517 /***********************************************************************
518 * NE_InitializeDLLs
520 * Initialize the loaded DLLs.
522 void NE_InitializeDLLs( HMODULE16 hModule )
524 NE_MODULE *pModule;
525 HMODULE16 *pDLL;
527 if (!(pModule = MODULE_GetPtr( hModule ))) return;
528 if (pModule->flags & NE_FFLAGS_WIN32)
530 /* PE_InitializeDLLs(hModule); */
531 return;
533 if (pModule->dlls_to_init)
535 HGLOBAL16 to_init = pModule->dlls_to_init;
536 pModule->dlls_to_init = 0;
537 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
539 NE_InitializeDLLs( *pDLL );
541 GlobalFree16( to_init );
543 NE_InitDLL( hModule );
547 /***********************************************************************
548 * NE_PatchCodeHandle
550 * Needed for self-loading modules.
553 /* It does nothing */
554 void PatchCodeHandle(HANDLE16 hSel)
557 #endif /* WINELIB */