5 * Copyright 1993 Robert J. Amstadt
6 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
22 #include "selectors.h"
25 #include "stackframe.h"
31 /***********************************************************************
34 BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
37 SEGTABLEENTRY *pSegTable, *pSeg;
39 WORD count, i, offset;
43 struct relocation_entry_s *rep, *reloc_entries;
49 int ordinal, additive;
52 if (!(pModule = (NE_MODULE *)GlobalLock( 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="NPFMT"\n",
61 segnum, pSeg->selector );
62 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
63 size = pSeg->size ? pSeg->size : 0x10000;
64 mem = GlobalLock(pSeg->selector);
65 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1) {
67 /* Implement self loading segments */
68 SELFLOADHEADER *selfloadheader;
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;
77 newselector = CallTo16_word_www(selfloadheader->LoadAppSeg,
78 pModule->self_loading_sel, hModule, fd, segnum);
79 if (newselector != oldselector) {
80 /* Self loaders like creating their own selectors;
81 * they love asking for trouble to Wine developers
83 if (segnum == pModule->dgroup) {
84 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
85 PTR_SEG_OFF_TO_LIN(newselector,0),
86 pSeg->minsize ? pSeg->minsize : 0x10000);
87 FreeSelector(newselector);
88 pSeg->selector = oldselector;
89 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
90 "Old selector is %d, new one is %d", oldselector, newselector);
92 FreeSelector(pSeg->selector);
93 pSeg->selector = newselector;
97 IF1632_Saved16_ss = oldss;
98 IF1632_Saved16_sp = oldsp;
100 fprintf(stderr,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
103 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
107 The following bit of code for "iterated segments" was written without
108 any documentation on the format of these segments. It seems to work,
109 but may be missing something. If you have any doco please either send
110 it to me or fix the code yourself. gfm@werple.mira.net.au
112 char* buff = xmalloc(size);
114 read(fd, buff, size);
115 while(curr < buff + size) {
116 unsigned int rept = *((short*) curr)++;
117 unsigned int len = *((short*) curr)++;
118 for(; rept > 0; rept--) {
121 for(byte = 0; byte < len; byte++)
129 pSeg->flags |= NE_SEGFLAGS_LOADED;
130 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
131 return TRUE; /* No relocation data, we are done */
133 read( fd, &count, sizeof(count) );
134 if (!count) return TRUE;
136 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector "NPFMT"\n",
137 *((BYTE *)pModule + pModule->name_table),
138 *((BYTE *)pModule + pModule->name_table),
139 (char *)pModule + pModule->name_table + 1,
140 segnum, pSeg->selector );
142 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
143 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
144 count * sizeof(struct relocation_entry_s))
146 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
151 * Go through the relocation table on entry at a time.
154 for (i = 0; i < count; i++, rep++)
157 * Get the target address corresponding to this entry.
160 /* If additive, there is no target chain list. Instead, add source
162 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
163 rep->relocation_type &= 0x3;
165 switch (rep->relocation_type)
167 case NE_RELTYPE_ORDINAL:
168 module = pModuleTable[rep->target1-1];
169 ordinal = rep->target2;
170 address = MODULE_GetEntryPoint( module, ordinal );
173 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
175 fprintf( stderr, "Module not found: "NPFMT", reference %d of module %*.*s\n",
176 module, rep->target1,
177 *((BYTE *)pModule + pModule->name_table),
178 *((BYTE *)pModule + pModule->name_table),
179 (char *)pModule + pModule->name_table + 1 );
181 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
182 *((BYTE *)pTarget + pTarget->name_table),
183 *((BYTE *)pTarget + pTarget->name_table),
184 (char *)pTarget + pTarget->name_table + 1,
189 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
190 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
191 *((BYTE *)pTarget + pTarget->name_table),
192 *((BYTE *)pTarget + pTarget->name_table),
193 (char *)pTarget + pTarget->name_table + 1,
194 ordinal, HIWORD(address), LOWORD(address) );
198 case NE_RELTYPE_NAME:
199 module = pModuleTable[rep->target1-1];
200 func_name = (char *)pModule + pModule->import_table + rep->target2;
201 memcpy( buffer, func_name+1, *func_name );
202 buffer[*func_name] = '\0';
204 ordinal = MODULE_GetOrdinal( module, func_name );
206 address = MODULE_GetEntryPoint( module, ordinal );
210 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
211 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
212 *((BYTE *)pTarget + pTarget->name_table),
213 *((BYTE *)pTarget + pTarget->name_table),
214 (char *)pTarget + pTarget->name_table + 1, func_name );
218 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
219 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1,
220 *((BYTE *)pTarget + pTarget->name_table),
221 *((BYTE *)pTarget + pTarget->name_table),
222 (char *)pTarget + pTarget->name_table + 1,
223 func_name, HIWORD(address), LOWORD(address) );
227 case NE_RELTYPE_INTERNAL:
228 if (rep->target1 == 0x00ff)
230 address = MODULE_GetEntryPoint( hModule, rep->target2 );
234 address = MAKELONG( rep->target2, pSegTable[rep->target1-1].selector );
237 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
238 i + 1, HIWORD(address), LOWORD(address) );
241 case NE_RELTYPE_OSFIXUP:
242 /* Relocation type 7:
244 * These appear to be used as fixups for the Windows
245 * floating point emulator. Let's just ignore them and
246 * try to use the hardware floating point. Linux should
247 * successfully emulate the coprocessor if it doesn't
250 dprintf_fixup(stddeb,
251 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
252 i + 1, rep->address_type, rep->relocation_type,
254 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
255 rep->target1, rep->target2);
259 dprintf_fixup(stddeb,
260 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
261 i + 1, rep->address_type, rep->relocation_type,
263 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
264 rep->target1, rep->target2);
269 offset = rep->offset;
271 switch (rep->address_type)
273 case NE_RADDR_LOWBYTE:
275 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
276 dprintf_fixup(stddeb," "NPFMT":%04x:%04x BYTE%s\n",
277 pSeg->selector, offset, *sp, additive ? " additive":"");
280 *(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
282 *(unsigned char*)sp = (unsigned char)(address & 0xFF);
284 while (offset != 0xffff && !additive);
287 case NE_RADDR_OFFSET16:
289 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
290 dprintf_fixup(stddeb," "NPFMT":%04x:%04x OFFSET16%s\n",
291 pSeg->selector, offset, *sp, additive ? " additive" : "" );
293 *sp = LOWORD(address);
294 if (additive) *sp += offset;
296 while (offset != 0xffff && !additive);
299 case NE_RADDR_POINTER32:
301 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
302 dprintf_fixup(stddeb," "NPFMT":%04x:%04x POINTER32%s\n",
303 pSeg->selector, offset, *sp, additive ? " additive" : "" );
305 *sp = LOWORD(address);
306 if (additive) *sp += offset;
307 *(sp+1) = HIWORD(address);
309 while (offset != 0xffff && !additive);
312 case NE_RADDR_SELECTOR:
314 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
315 dprintf_fixup(stddeb," "NPFMT":%04x:%04x SELECTOR%s\n",
316 pSeg->selector, offset, *sp, additive ? " additive" : "" );
318 *sp = HIWORD(address);
319 /* Borland creates additive records with offset zero. Strange, but OK */
320 if(additive && offset)
321 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
323 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
324 while (offset && offset != 0xffff && !additive);
328 dprintf_fixup(stddeb,
329 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
330 i + 1, rep->address_type, rep->relocation_type,
332 dprintf_fixup(stddeb,
333 "TARGET %04x %04x\n", rep->target1, rep->target2);
344 /***********************************************************************
347 * Fixup the exported functions prologs.
349 void NE_FixupPrologs( HMODULE hModule )
352 fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
355 SEGTABLEENTRY *pSegTable;
358 BYTE *p, *fixup_ptr, count;
360 pModule = (NE_MODULE *)GlobalLock( hModule );
361 pSegTable = NE_SEG_TABLE(pModule);
362 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
363 dgroup = pSegTable[pModule->dgroup-1].selector;
365 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule );
366 p = (BYTE *)pModule + pModule->entry_table;
369 if (p[1] == 0) /* Unused entry */
371 p += 2; /* Skip it */
374 if (p[1] == 0xfe) /* Constant entry */
376 p += 2 + *p * 3; /* Skip it */
380 /* Now fixup the entries of this bundle */
386 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
387 /* According to the output generated by TDUMP, the flags mean:
388 * 0x0001 function is exported
389 * 0x0002 Single data (seems to occur only in DLLs)
391 if (sel == 0xff) { /* moveable */
392 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
393 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
395 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
396 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
398 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
399 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
403 /* Verify the signature */
404 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
405 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
406 && fixup_ptr[2] == 0x90)
410 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
411 /* can this happen? */
412 fprintf( stderr, "FixupPrologs got confused\n" );
414 *fixup_ptr = 0xb8; /* MOV AX, */
415 *(WORD *)(fixup_ptr+1) = dgroup;
419 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
420 fixup_ptr[0] = 0x90; /* non-library: NOPs */
426 dprintf_fixup( stddeb, "Unknown signature\n" );
430 dprintf_module( stddeb,"\n");
431 p += (sel == 0xff) ? 6 : 3;
438 /***********************************************************************
441 * Call the DLL initialization code
443 static BOOL NE_InitDLL( HMODULE hModule )
446 int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
448 SEGTABLEENTRY *pSegTable;
450 /* Registers at initialization must be:
452 * di library instance
453 * ds data segment if any
454 * es:si command line (always 0)
457 pModule = (NE_MODULE *)GlobalLock( hModule );
458 pSegTable = NE_SEG_TABLE( pModule );
460 if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/
461 if (!pModule->cs) return TRUE; /* no initialization code */
463 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
465 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
468 fprintf(stderr, "Library is not marked SINGLEDATA\n");
471 else /* DATA NONE DLL */
477 else /* DATA SINGLE DLL */
479 ds_reg = pSegTable[pModule->dgroup-1].selector;
480 cx_reg = pModule->heap_size;
483 cs_reg = pSegTable[pModule->cs-1].selector;
484 ip_reg = pModule->ip;
485 di_reg = ds_reg ? ds_reg : hModule;
486 bp_reg = IF1632_Saved16_sp + ((WORD)&((STACK16FRAME*)1)->bp - 1);
488 pModule->cs = 0; /* Don't initialize it twice */
489 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
490 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
491 return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
492 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
493 cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
495 fprintf( stderr,"JBP: Ignoring call to LibMain\n" );
501 /***********************************************************************
504 * Initialize the loaded DLLs.
506 void NE_InitializeDLLs( HMODULE hModule )
511 pModule = (NE_MODULE *)GlobalLock( hModule );
512 if (pModule->magic == PE_SIGNATURE)
514 PE_InitializeDLLs(hModule);
517 if (pModule->dlls_to_init)
519 HANDLE to_init = pModule->dlls_to_init;
520 pModule->dlls_to_init = 0;
521 for (pDLL = (HMODULE *)GlobalLock( to_init ); *pDLL; pDLL++)
523 NE_InitializeDLLs( *pDLL );
526 GlobalFree( to_init );
528 NE_InitDLL( hModule );
532 /***********************************************************************
535 * Needed for self-loading modules.
538 /* It does nothing */
539 void PatchCodeHandle(HANDLE hSel)