5 * Copyright 1993 Robert J. Amstadt
6 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
21 #include "selectors.h"
24 #include "stackframe.h"
30 /***********************************************************************
33 BOOL NE_LoadSegment( HMODULE16 hModule, WORD segnum )
36 SEGTABLEENTRY *pSegTable, *pSeg;
38 WORD count, i, offset;
42 struct relocation_entry_s *rep, *reloc_entries;
48 int ordinal, additive;
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) {
66 /* Implement self loading segments */
67 SELFLOADHEADER *selfloadheader;
68 STACK16FRAME *stack16Top;
69 WORD oldss, oldsp, oldselector, newselector;
70 HFILE hf = FILE_DupUnixHandle( fd );
72 selfloadheader = (SELFLOADHEADER *)
73 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
74 oldss = IF1632_Saved16_ss;
75 oldsp = IF1632_Saved16_sp;
76 oldselector = pSeg->selector;
77 IF1632_Saved16_ss = pModule->self_loading_sel;
78 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
79 stack16Top = CURRENT_STACK16;
80 stack16Top->saved_ss = 0;
81 stack16Top->saved_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 = CallTo16_word_www( selfloadheader->LoadAppSeg,
90 hModule, 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 = oldss;
111 IF1632_Saved16_sp = oldsp;
113 fprintf(stderr,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
116 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
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);
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--) {
134 for(byte = 0; byte < len; byte++)
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" );
164 * Go through the relocation table on entry at a time.
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
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 );
186 NE_MODULE *pTarget = MODULE_GetPtr( module );
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 );
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,
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) );
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';
217 ordinal = MODULE_GetOrdinal( module, func_name );
219 address = MODULE_GetEntryPoint( module, ordinal );
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 );
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) );
240 case NE_RELTYPE_INTERNAL:
241 if (rep->target1 == 0x00ff)
243 address = MODULE_GetEntryPoint( hModule, rep->target2 );
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) );
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
263 dprintf_fixup(stddeb,
264 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
265 i + 1, rep->address_type, rep->relocation_type,
267 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
268 rep->target1, rep->target2);
272 dprintf_fixup(stddeb,
273 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
274 i + 1, rep->address_type, rep->relocation_type,
276 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
277 rep->target1, rep->target2);
282 offset = rep->offset;
284 switch (rep->address_type)
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 "%d: 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 * Fixup the exported functions prologs.
362 void NE_FixupPrologs( NE_MODULE *pModule )
365 fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
367 SEGTABLEENTRY *pSegTable;
370 BYTE *p, *fixup_ptr, count;
372 pSegTable = NE_SEG_TABLE(pModule);
373 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
374 dgroup = pSegTable[pModule->dgroup-1].selector;
376 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self );
377 p = (BYTE *)pModule + pModule->entry_table;
380 if (p[1] == 0) /* Unused entry */
382 p += 2; /* Skip it */
385 if (p[1] == 0xfe) /* Constant entry */
387 p += 2 + *p * 3; /* Skip it */
391 /* Now fixup the entries of this bundle */
397 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
398 /* According to the output generated by TDUMP, the flags mean:
399 * 0x0001 function is exported
400 * 0x0002 Single data (seems to occur only in DLLs)
402 if (sel == 0xff) { /* moveable */
403 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
404 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
406 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
407 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
409 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
410 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
414 /* Verify the signature */
415 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
416 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
417 && fixup_ptr[2] == 0x90)
421 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
422 /* can this happen? */
423 fprintf( stderr, "FixupPrologs got confused\n" );
425 *fixup_ptr = 0xb8; /* MOV AX, */
426 *(WORD *)(fixup_ptr+1) = dgroup;
430 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
431 fixup_ptr[0] = 0x90; /* non-library: NOPs */
437 dprintf_fixup( stddeb, "Unknown signature\n" );
441 dprintf_module( stddeb,"\n");
442 p += (sel == 0xff) ? 6 : 3;
449 /***********************************************************************
452 * Call the DLL initialization code
454 static BOOL NE_InitDLL( HMODULE16 hModule )
457 int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
459 SEGTABLEENTRY *pSegTable;
461 /* Registers at initialization must be:
463 * di library instance
464 * ds data segment if any
465 * es:si command line (always 0)
468 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
469 pSegTable = NE_SEG_TABLE( pModule );
471 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
472 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
473 if (!pModule->cs) return TRUE; /* no initialization code */
475 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
477 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
480 fprintf(stderr, "Library is not marked SINGLEDATA\n");
483 else /* DATA NONE DLL */
489 else /* DATA SINGLE DLL */
491 ds_reg = pSegTable[pModule->dgroup-1].selector;
492 cx_reg = pModule->heap_size;
495 cs_reg = pSegTable[pModule->cs-1].selector;
496 ip_reg = pModule->ip;
497 di_reg = ds_reg ? ds_reg : hModule;
498 bp_reg = IF1632_Saved16_sp + ((WORD)&((STACK16FRAME*)1)->bp - 1);
500 pModule->cs = 0; /* Don't initialize it twice */
501 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
502 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
503 return CallTo16_regs_( (FARPROC16)(cs_reg << 16 | ip_reg), ds_reg,
504 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
505 cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
507 fprintf( stderr,"JBP: Ignoring call to LibMain\n" );
513 /***********************************************************************
516 * Initialize the loaded DLLs.
518 void NE_InitializeDLLs( HMODULE16 hModule )
523 if (!(pModule = MODULE_GetPtr( hModule ))) return;
524 if (pModule->flags & NE_FFLAGS_WIN32)
526 PE_InitializeDLLs(hModule);
529 if (pModule->dlls_to_init)
531 HANDLE to_init = pModule->dlls_to_init;
532 pModule->dlls_to_init = 0;
533 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
535 NE_InitializeDLLs( *pDLL );
538 GlobalFree16( to_init );
540 NE_InitDLL( hModule );
544 /***********************************************************************
547 * Needed for self-loading modules.
550 /* It does nothing */
551 void PatchCodeHandle(HANDLE hSel)