4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
10 #include <sys/types.h>
21 #include "selectors.h"
24 #include "stackframe.h"
29 /***********************************************************************
32 BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
35 SEGTABLEENTRY *pSegTable, *pSeg;
37 WORD count, i, module, offset;
40 struct relocation_entry_s *rep, *reloc_entries;
46 int ordinal, additive;
49 if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
50 pSegTable = NE_SEG_TABLE( pModule );
51 pSeg = pSegTable + segnum - 1;
52 pModuleTable = NE_MODULE_TABLE( pModule );
54 if (!pSeg->filepos) return TRUE; /* No file image, just return */
56 fd = MODULE_OpenFile( hModule );
57 dprintf_module( stddeb, "Loading segment %d, selector=%04x\n",
58 segnum, pSeg->selector );
59 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
60 size = pSeg->size ? pSeg->size : 0x10000;
61 mem = GlobalLock(pSeg->selector);
62 if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
66 The following bit of code for "iterated segments" was written without
67 any documentation on the format of these segments. It seems to work,
68 but may be missing something. If you have any doco please either send
69 it to me or fix the code yourself. gfm@werple.mira.net.au
71 char* buff = malloc(size);
74 while(curr < buff + size) {
75 unsigned int rept = *((short*) curr)++;
76 unsigned int len = *((short*) curr)++;
77 for(; rept > 0; rept--) {
80 for(byte = 0; byte < len; byte++)
88 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
89 return TRUE; /* No relocation data, we are done */
91 read( fd, &count, sizeof(count) );
92 if (!count) return TRUE;
94 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector %04x\n",
95 *((BYTE *)pModule + pModule->name_table),
96 *((BYTE *)pModule + pModule->name_table),
97 (char *)pModule + pModule->name_table + 1,
98 segnum, pSeg->selector );
100 reloc_entries = (struct relocation_entry_s *)malloc(count * sizeof(struct relocation_entry_s));
101 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
102 count * sizeof(struct relocation_entry_s))
104 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
109 * Go through the relocation table on entry at a time.
112 for (i = 0; i < count; i++, rep++)
115 * Get the target address corresponding to this entry.
118 /* If additive, there is no target chain list. Instead, add source
120 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
121 rep->relocation_type &= 0x3;
123 switch (rep->relocation_type)
125 case NE_RELTYPE_ORDINAL:
126 module = pModuleTable[rep->target1-1];
127 ordinal = rep->target2;
128 address = MODULE_GetEntryPoint( module, ordinal );
131 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
133 fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
134 module, rep->target1,
135 *((BYTE *)pModule + pModule->name_table),
136 *((BYTE *)pModule + pModule->name_table),
137 (char *)pModule + pModule->name_table + 1 );
139 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
140 *((BYTE *)pTarget + pTarget->name_table),
141 *((BYTE *)pTarget + pTarget->name_table),
142 (char *)pTarget + pTarget->name_table + 1,
147 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
148 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
149 *((BYTE *)pTarget + pTarget->name_table),
150 *((BYTE *)pTarget + pTarget->name_table),
151 (char *)pTarget + pTarget->name_table + 1,
152 ordinal, HIWORD(address), LOWORD(address) );
156 case NE_RELTYPE_NAME:
157 module = pModuleTable[rep->target1-1];
158 func_name = (char *)pModule + pModule->import_table + rep->target2;
159 memcpy( buffer, func_name+1, *func_name );
160 buffer[*func_name] = '\0';
162 ordinal = MODULE_GetOrdinal( module, func_name );
164 address = MODULE_GetEntryPoint( module, ordinal );
168 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
169 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
170 *((BYTE *)pTarget + pTarget->name_table),
171 *((BYTE *)pTarget + pTarget->name_table),
172 (char *)pTarget + pTarget->name_table + 1, func_name );
176 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
177 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1,
178 *((BYTE *)pTarget + pTarget->name_table),
179 *((BYTE *)pTarget + pTarget->name_table),
180 (char *)pTarget + pTarget->name_table + 1,
181 func_name, HIWORD(address), LOWORD(address) );
185 case NE_RELTYPE_INTERNAL:
186 if (rep->target1 == 0x00ff)
188 address = MODULE_GetEntryPoint( hModule, rep->target2 );
192 address = MAKELONG( rep->target2, pSegTable[rep->target1-1].selector );
195 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
196 i + 1, HIWORD(address), LOWORD(address) );
199 case NE_RELTYPE_OSFIXUP:
200 /* Relocation type 7:
202 * These appear to be used as fixups for the Windows
203 * floating point emulator. Let's just ignore them and
204 * try to use the hardware floating point. Linux should
205 * successfully emulate the coprocessor if it doesn't
208 dprintf_fixup(stddeb,
209 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
210 i + 1, rep->address_type, rep->relocation_type,
212 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
213 rep->target1, rep->target2);
217 dprintf_fixup(stddeb,
218 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
219 i + 1, rep->address_type, rep->relocation_type,
221 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
222 rep->target1, rep->target2);
227 offset = rep->offset;
229 switch (rep->address_type)
231 case NE_RADDR_LOWBYTE:
233 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
234 dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
235 pSeg->selector, offset, *sp, additive ? " additive":"");
238 *(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
240 *(unsigned char*)sp = (unsigned char)(address & 0xFF);
242 while (offset != 0xffff && !additive);
245 case NE_RADDR_OFFSET16:
247 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
248 dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
249 pSeg->selector, offset, *sp, additive ? " additive" : "" );
251 *sp = LOWORD(address);
252 if (additive) *sp += offset;
254 while (offset != 0xffff && !additive);
257 case NE_RADDR_POINTER32:
259 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
260 dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
261 pSeg->selector, offset, *sp, additive ? " additive" : "" );
263 *sp = LOWORD(address);
264 if (additive) *sp += offset;
265 *(sp+1) = HIWORD(address);
267 while (offset != 0xffff && !additive);
270 case NE_RADDR_SELECTOR:
272 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
273 dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
274 pSeg->selector, offset, *sp, additive ? " additive" : "" );
276 *sp = HIWORD(address);
277 /* Borland creates additive records with offset zero. Strange, but OK */
278 if(additive && offset)
279 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
281 while (offset != 0xffff && !additive);
285 dprintf_fixup(stddeb,
286 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
287 i + 1, rep->address_type, rep->relocation_type,
289 dprintf_fixup(stddeb,
290 "TARGET %04x %04x\n", rep->target1, rep->target2);
301 /***********************************************************************
304 * Fixup the exported functions prologs.
306 void NE_FixupPrologs( HMODULE hModule )
309 fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
312 SEGTABLEENTRY *pSegTable;
315 BYTE *p, *fixup_ptr, count;
317 pModule = (NE_MODULE *)GlobalLock( hModule );
318 pSegTable = NE_SEG_TABLE(pModule);
319 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
320 dgroup = pSegTable[pModule->dgroup-1].selector;
322 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule );
323 p = (BYTE *)pModule + pModule->entry_table;
326 if (p[1] == 0) /* Unused entry */
328 p += 2; /* Skip it */
331 if (p[1] == 0xfe) /* Constant entry */
333 p += 2 + *p * 3; /* Skip it */
337 /* Now fixup the entries of this bundle */
343 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
344 /* According to the output generated by TDUMP, the flags mean:
345 * 0x0001 function is exported
346 * 0x0002 Single data (seems to occur only in DLLs)
348 if (sel == 0xff) { /* moveable */
349 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
350 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
352 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
353 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
355 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
356 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
360 /* Verify the signature */
361 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
362 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
363 && fixup_ptr[2] == 0x90)
367 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
368 /* can this happen? */
369 fprintf( stderr, "FixupPrologs got confused\n" );
371 *fixup_ptr = 0xb8; /* MOV AX, */
372 *(WORD *)(fixup_ptr+1) = dgroup;
376 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
377 fixup_ptr[0] = 0x90; /* non-library: NOPs */
383 dprintf_fixup( stddeb, "Unknown signature\n" );
387 dprintf_module( stddeb,"\n");
388 p += (sel == 0xff) ? 6 : 3;
395 /***********************************************************************
398 * Call the DLL initialization code
400 static BOOL NE_InitDLL( HMODULE hModule )
402 int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
404 SEGTABLEENTRY *pSegTable;
406 /* Registers at initialization must be:
408 * di library instance
409 * ds data segment if any
410 * es:si command line (always 0)
413 pModule = (NE_MODULE *)GlobalLock( hModule );
414 pSegTable = NE_SEG_TABLE( pModule );
416 if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/
417 if (!pModule->cs) return TRUE; /* no initialization code */
419 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
421 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
424 fprintf(stderr, "Library is not marked SINGLEDATA\n");
427 else /* DATA NONE DLL */
433 else /* DATA SINGLE DLL */
435 ds_reg = pSegTable[pModule->dgroup-1].selector;
436 cx_reg = pModule->heap_size;
439 cs_reg = pSegTable[pModule->cs-1].selector;
440 ip_reg = pModule->ip;
441 di_reg = ds_reg ? ds_reg : hModule;
442 bp_reg = IF1632_Saved16_sp + ((WORD)&((STACK16FRAME*)1)->bp - 1);
444 pModule->cs = 0; /* Don't initialize it twice */
445 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
446 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
447 return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
448 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
449 cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
453 /***********************************************************************
456 * Initialize the loaded DLLs.
458 void NE_InitializeDLLs( HMODULE hModule )
463 pModule = (NE_MODULE *)GlobalLock( hModule );
464 if (pModule->dlls_to_init)
466 HANDLE to_init = pModule->dlls_to_init;
467 pModule->dlls_to_init = 0;
468 for (pDLL = (WORD *)GlobalLock( to_init ); *pDLL; pDLL++)
470 NE_InitializeDLLs( *pDLL );
473 GlobalFree( to_init );
475 NE_InitDLL( hModule );