4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
10 #include <sys/types.h>
21 #include "selectors.h"
25 #include "stackframe.h"
31 /***********************************************************************
34 BOOL32 NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
36 SEGTABLEENTRY *pSegTable, *pSeg;
38 WORD count, i, offset;
42 struct relocation_entry_s *rep, *reloc_entries;
48 int ordinal, additive;
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( pModule->self );
58 dprintf_module( stddeb, "Loading segment %d, selector=%04x, flags=%04x\n",
59 segnum, pSeg->selector, pSeg->flags );
60 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
61 if (pSeg->size) size = pSeg->size;
62 else if (pSeg->minsize) size = pSeg->minsize;
64 mem = GlobalLock16(pSeg->selector);
65 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
67 /* Implement self loading segments */
68 SELFLOADHEADER *selfloadheader;
69 STACK16FRAME *stack16Top;
71 WORD oldselector, newselector;
72 HFILE32 hf = FILE_DupUnixHandle( fd );
74 selfloadheader = (SELFLOADHEADER *)
75 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
76 oldstack = IF1632_Saved16_ss_sp;
77 oldselector = pSeg->selector;
78 IF1632_Saved16_ss_sp = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
79 0xff00 - sizeof(*stack16Top));
80 stack16Top = CURRENT_STACK16;
81 stack16Top->saved_ss_sp = 0;
82 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
83 stack16Top->entry_point = 0;
84 stack16Top->entry_ip = 0;
85 stack16Top->entry_cs = 0;
89 newselector = Callbacks->CallLoadAppSegProc(selfloadheader->LoadAppSeg,
90 pModule->self, hf, segnum );
92 if (newselector != oldselector) {
93 /* Self loaders like creating their own selectors;
94 * they love asking for trouble to Wine developers
96 if (segnum == pModule->dgroup) {
97 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
98 PTR_SEG_OFF_TO_LIN(newselector,0),
99 pSeg->minsize ? pSeg->minsize : 0x10000);
100 FreeSelector(newselector);
101 pSeg->selector = oldselector;
102 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
103 "Old selector is %d, new one is %d", oldselector, newselector);
105 FreeSelector(pSeg->selector);
106 pSeg->selector = newselector;
110 IF1632_Saved16_ss_sp = oldstack;
112 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
116 The following bit of code for "iterated segments" was written without
117 any documentation on the format of these segments. It seems to work,
118 but may be missing something. If you have any doco please either send
119 it to me or fix the code yourself. gfm@werple.mira.net.au
121 char* buff = xmalloc(size);
123 read(fd, buff, size);
124 while(curr < buff + size) {
125 unsigned int rept = *((short*) curr)++;
126 unsigned int len = *((short*) curr)++;
127 for(; rept > 0; rept--) {
130 for(byte = 0; byte < len; byte++)
138 pSeg->flags |= NE_SEGFLAGS_LOADED;
139 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
140 return TRUE; /* No relocation data, we are done */
142 read( fd, &count, sizeof(count) );
143 if (!count) return TRUE;
145 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector %04x\n",
146 *((BYTE *)pModule + pModule->name_table),
147 *((BYTE *)pModule + pModule->name_table),
148 (char *)pModule + pModule->name_table + 1,
149 segnum, pSeg->selector );
151 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
152 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
153 count * sizeof(struct relocation_entry_s))
155 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
160 * Go through the relocation table on entry at a time.
163 for (i = 0; i < count; i++, rep++)
166 * Get the target address corresponding to this entry.
169 /* If additive, there is no target chain list. Instead, add source
171 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
172 rep->relocation_type &= 0x3;
174 switch (rep->relocation_type)
176 case NE_RELTYPE_ORDINAL:
177 module = pModuleTable[rep->target1-1];
178 ordinal = rep->target2;
179 address = MODULE_GetEntryPoint( module, ordinal );
182 NE_MODULE *pTarget = MODULE_GetPtr( module );
184 fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
185 module, rep->target1,
186 *((BYTE *)pModule + pModule->name_table),
187 *((BYTE *)pModule + pModule->name_table),
188 (char *)pModule + pModule->name_table + 1 );
190 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
191 *((BYTE *)pTarget + pTarget->name_table),
192 *((BYTE *)pTarget + pTarget->name_table),
193 (char *)pTarget + pTarget->name_table + 1,
198 NE_MODULE *pTarget = MODULE_GetPtr( module );
199 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
200 *((BYTE *)pTarget + pTarget->name_table),
201 *((BYTE *)pTarget + pTarget->name_table),
202 (char *)pTarget + pTarget->name_table + 1,
203 ordinal, HIWORD(address), LOWORD(address) );
207 case NE_RELTYPE_NAME:
208 module = pModuleTable[rep->target1-1];
209 func_name = (char *)pModule + pModule->import_table + rep->target2;
210 memcpy( buffer, func_name+1, *func_name );
211 buffer[*func_name] = '\0';
213 ordinal = MODULE_GetOrdinal( module, func_name );
215 address = MODULE_GetEntryPoint( module, ordinal );
219 NE_MODULE *pTarget = MODULE_GetPtr( module );
220 fprintf( stderr, "Warning: no handler for %.*s.%s, setting to 0:0\n",
221 *((BYTE *)pTarget + pTarget->name_table),
222 (char *)pTarget + pTarget->name_table + 1, func_name );
226 NE_MODULE *pTarget = MODULE_GetPtr( module );
227 fprintf( stddeb,"%d: %.*s.%s=%04x:%04x\n", i + 1,
228 *((BYTE *)pTarget + pTarget->name_table),
229 (char *)pTarget + pTarget->name_table + 1,
230 func_name, HIWORD(address), LOWORD(address) );
234 case NE_RELTYPE_INTERNAL:
235 if ((rep->target1 & 0xff) == 0xff)
237 address = MODULE_GetEntryPoint( pModule->self, rep->target2 );
241 address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( pSegTable[rep->target1-1].selector, rep->target2 );
244 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
245 i + 1, HIWORD(address), LOWORD(address) );
248 case NE_RELTYPE_OSFIXUP:
249 /* Relocation type 7:
251 * These appear to be used as fixups for the Windows
252 * floating point emulator. Let's just ignore them and
253 * try to use the hardware floating point. Linux should
254 * successfully emulate the coprocessor if it doesn't
257 dprintf_fixup(stddeb,
258 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
259 i + 1, rep->address_type, rep->relocation_type,
261 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
262 rep->target1, rep->target2);
266 dprintf_fixup(stddeb,
267 "WARNING: %d: ADDR TYPE %d, unknown TYPE %d, OFFSET %04x, ",
268 i + 1, rep->address_type, rep->relocation_type,
270 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
271 rep->target1, rep->target2);
276 offset = rep->offset;
278 /* Apparently, high bit of address_type is sometimes set; */
279 /* we ignore it for now */
280 if (rep->address_type > NE_RADDR_OFFSET32)
281 fprintf( stderr, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
282 MODULE_GetModuleName(pModule->self), rep->address_type );
284 switch (rep->address_type & 0x7f)
286 case NE_RADDR_LOWBYTE:
288 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
289 dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
290 pSeg->selector, offset, *sp, additive ? " additive":"");
293 *(unsigned char*)sp = (unsigned char)(((int)address+offset) & 0xFF);
295 *(unsigned char*)sp = (unsigned char)((int)address & 0xFF);
297 while (offset != 0xffff && !additive);
300 case NE_RADDR_OFFSET16:
302 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
303 dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
304 pSeg->selector, offset, *sp, additive ? " additive" : "" );
306 *sp = LOWORD(address);
307 if (additive) *sp += offset;
309 while (offset != 0xffff && !additive);
312 case NE_RADDR_POINTER32:
314 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
315 dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
316 pSeg->selector, offset, *sp, additive ? " additive" : "" );
318 *sp = LOWORD(address);
319 if (additive) *sp += offset;
320 *(sp+1) = HIWORD(address);
322 while (offset != 0xffff && !additive);
325 case NE_RADDR_SELECTOR:
327 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
328 dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
329 pSeg->selector, offset, *sp, additive ? " additive" : "" );
331 *sp = HIWORD(address);
332 /* Borland creates additive records with offset zero. Strange, but OK */
333 if(additive && offset)
334 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
336 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
337 while (offset && offset != 0xffff && !additive);
341 dprintf_fixup(stddeb,
342 "WARNING: %d: unknown ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
343 i + 1, rep->address_type, rep->relocation_type,
345 dprintf_fixup(stddeb,
346 "TARGET %04x %04x\n", rep->target1, rep->target2);
357 /***********************************************************************
360 BOOL32 NE_LoadAllSegments( NE_MODULE *pModule )
364 if (pModule->flags & NE_FFLAGS_SELFLOAD)
367 /* Handle self loading modules */
368 SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
369 SELFLOADHEADER *selfloadheader;
370 STACK16FRAME *stack16Top;
371 HMODULE16 hselfload = GetModuleHandle16("WPROCS");
373 WORD saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
375 dprintf_module(stddeb, "MODULE_Load: %.*s is a self-loading module!\n",
376 *((BYTE*)pModule + pModule->name_table),
377 (char *)pModule + pModule->name_table + 1);
378 if (!NE_LoadSegment( pModule, 1 )) return FALSE;
379 selfloadheader = (SELFLOADHEADER *)
380 PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
381 selfloadheader->EntryAddrProc = MODULE_GetEntryPoint(hselfload,27);
382 selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
383 selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
384 pModule->self_loading_sel = GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
385 oldstack = IF1632_Saved16_ss_sp;
386 IF1632_Saved16_ss_sp = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
387 0xff00 - sizeof(*stack16Top) );
388 stack16Top = CURRENT_STACK16;
389 stack16Top->saved_ss_sp = 0;
391 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
392 stack16Top->entry_point = 0;
393 stack16Top->entry_ip = 0;
394 stack16Top->entry_cs = 0;
399 hf = FILE_DupUnixHandle( MODULE_OpenFile( pModule->self ) );
400 Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self, hf);
402 /* some BootApp procs overwrite the selector of dgroup */
403 pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
404 IF1632_Saved16_ss_sp = oldstack;
405 for (i = 2; i <= pModule->seg_count; i++)
406 if (!NE_LoadSegment( pModule, i )) return FALSE;
410 for (i = 1; i <= pModule->seg_count; i++)
411 if (!NE_LoadSegment( pModule, i )) return FALSE;
417 /***********************************************************************
420 BOOL32 NE_LoadDLLs( NE_MODULE *pModule )
423 WORD *pModRef = (WORD *)((char *)pModule + pModule->modref_table);
424 WORD *pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
426 for (i = 0; i < pModule->modref_count; i++, pModRef++)
429 BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
430 memcpy( buffer, pstr + 1, *pstr );
431 strcpy( buffer + *pstr, ".dll" );
432 dprintf_module( stddeb, "Loading '%s'\n", buffer );
433 if (!(*pModRef = MODULE_FindModule( buffer )))
435 /* If the DLL is not loaded yet, load it and store */
436 /* its handle in the list of DLLs to initialize. */
439 if ((hDLL = MODULE_Load( buffer, (LPVOID)-1, NE_FFLAGS_IMPLICIT )) == 2)
444 /* Try with prepending the path of the current module */
445 GetModuleFileName16( pModule->self, buffer, sizeof(buffer) );
446 if (!(p = strrchr( buffer, '\\' ))) p = buffer;
447 memcpy( p + 1, pstr + 1, *pstr );
448 strcpy( p + 1 + *pstr, ".dll" );
449 hDLL = MODULE_Load( buffer, (LPVOID)-1, NE_FFLAGS_IMPLICIT );
453 /* FIXME: cleanup what was done */
455 fprintf( stderr, "Could not load '%s' required by '%.*s', error = %d\n",
456 buffer, *((BYTE*)pModule + pModule->name_table),
457 (char *)pModule + pModule->name_table + 1, hDLL );
460 *pModRef = MODULE_HANDLEtoHMODULE16( hDLL );
463 else /* Increment the reference count of the DLL */
465 NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
466 if (pOldDLL) pOldDLL->count++;
473 /***********************************************************************
476 * Fixup the exported functions prologs.
478 void NE_FixupPrologs( NE_MODULE *pModule )
480 SEGTABLEENTRY *pSegTable;
483 BYTE *p, *fixup_ptr, count;
485 pSegTable = NE_SEG_TABLE(pModule);
486 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
487 dgroup = pSegTable[pModule->dgroup-1].selector;
489 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self );
490 p = (BYTE *)pModule + pModule->entry_table;
493 if (p[1] == 0) /* Unused entry */
495 p += 2; /* Skip it */
498 if (p[1] == 0xfe) /* Constant entry */
500 p += 2 + *p * 3; /* Skip it */
504 /* Now fixup the entries of this bundle */
510 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
511 /* According to the output generated by TDUMP, the flags mean:
512 * 0x0001 function is exported
513 * 0x0002 Single data (seems to occur only in DLLs)
515 if (sel == 0xff) { /* moveable */
516 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
517 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
519 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
520 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
522 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
523 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
527 /* Verify the signature */
528 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
529 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
530 && fixup_ptr[2] == 0x90)
534 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
536 /* can this happen? */
537 fprintf( stderr, "FixupPrologs got confused\n" );
539 else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
541 *fixup_ptr = 0xb8; /* MOV AX, */
542 *(WORD *)(fixup_ptr+1) = dgroup;
547 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
548 fixup_ptr[0] = 0x90; /* non-library: NOPs */
554 dprintf_fixup( stddeb, "Unknown signature\n" );
558 dprintf_module( stddeb,"\n");
559 p += (sel == 0xff) ? 6 : 3;
565 /***********************************************************************
568 * Call the DLL initialization code
570 static BOOL32 NE_InitDLL( TDB* pTask, HMODULE16 hModule )
573 SEGTABLEENTRY *pSegTable;
576 /* Registers at initialization must be:
578 * di library instance
579 * ds data segment if any
580 * es:si command line (always 0)
583 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
584 pSegTable = NE_SEG_TABLE( pModule );
586 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
587 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
589 /* Call USER signal handler. This is necessary to install a
590 * proper loader for HICON and HCURSOR resources that this DLL
591 * may contain. InitApp() does this for task modules. */
593 if (pTask && pTask->userhandler)
595 pTask->userhandler( hModule, USIG_DLL_LOAD, 0, pTask->hInstance,
599 if (!pModule->cs) return TRUE; /* no initialization code */
601 memset( &context, 0, sizeof(context) );
603 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
605 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
608 fprintf(stderr, "Library is not marked SINGLEDATA\n");
611 else /* DATA NONE DLL */
613 DS_reg(&context) = 0;
614 ECX_reg(&context) = 0;
617 else /* DATA SINGLE DLL */
619 DS_reg(&context) = pSegTable[pModule->dgroup-1].selector;
620 ECX_reg(&context) = pModule->heap_size;
623 CS_reg(&context) = pSegTable[pModule->cs-1].selector;
624 EIP_reg(&context) = pModule->ip;
625 EBP_reg(&context) = OFFSETOF(IF1632_Saved16_ss_sp)
626 + (WORD)&((STACK16FRAME*)0)->bp;
627 EDI_reg(&context) = DS_reg(&context) ? DS_reg(&context) : hModule;
630 pModule->cs = 0; /* Don't initialize it twice */
631 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
632 CS_reg(&context), IP_reg(&context), DS_reg(&context),
633 DI_reg(&context), CX_reg(&context) );
634 Callbacks->CallRegisterShortProc( &context, 0 );
639 /***********************************************************************
642 * Recursively initialize all DLLs (according to the order in which
643 * they where loaded).
645 void NE_InitializeDLLs( HMODULE16 hModule )
647 TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
651 if (!(pModule = MODULE_GetPtr( hModule ))) return;
652 if (pModule->flags & NE_FFLAGS_WIN32) return;
654 if (pModule->dlls_to_init)
656 HGLOBAL16 to_init = pModule->dlls_to_init;
657 pModule->dlls_to_init = 0;
658 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
660 NE_InitializeDLLs( *pDLL );
662 GlobalFree16( to_init );
664 NE_InitDLL( pTask, hModule );
668 /***********************************************************************
671 * Needed for self-loading modules.
674 /* It does nothing */
675 void WINAPI PatchCodeHandle(HANDLE16 hSel)
677 fprintf(stderr,"PatchCodeHandle(%04x),stub!\n",hSel);