Release 950918
[wine/testsucceed.git] / loader / ne_image.c
blobb05e65eb88973a72c51092a87cc6f513b2f37856
1 /*
2 * NE modules
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <ctype.h>
15 #include <string.h>
16 #include <errno.h>
17 #include "neexe.h"
18 #include "dlls.h"
19 #include "windows.h"
20 #include "arch.h"
21 #include "selectors.h"
22 #include "callback.h"
23 #include "module.h"
24 #include "stackframe.h"
25 #include "stddebug.h"
26 #include "debug.h"
29 /***********************************************************************
30 * NE_LoadSegment
32 BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
34 NE_MODULE *pModule;
35 SEGTABLEENTRY *pSegTable, *pSeg;
36 WORD *pModuleTable;
37 WORD count, i, module, offset;
38 DWORD address;
39 int fd;
40 struct relocation_entry_s *rep, *reloc_entries;
41 BYTE *func_name;
42 int size;
43 char* mem;
45 char buffer[100];
46 int ordinal, additive;
47 unsigned short *sp;
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 (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1) {
63 /* Implement self loading segments */
64 SELFLOADHEADER *selfloadheader;
65 WORD oldss, oldsp, oldselector, newselector;
66 selfloadheader = (SELFLOADHEADER *)
67 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
68 oldss = IF1632_Saved16_ss;
69 oldsp = IF1632_Saved16_sp;
70 oldselector = pSeg->selector;
71 IF1632_Saved16_ss = pModule->self_loading_sel;
72 IF1632_Saved16_sp = 0xFF00;
73 newselector = CallTo16_word_www(selfloadheader->LoadAppSeg,
74 pModule->self_loading_sel, hModule, fd, segnum);
75 if (newselector != oldselector) {
76 /* Self loaders like creating their own selectors;
77 * they love asking for trouble to Wine developers
79 if (segnum == pModule->dgroup) {
80 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
81 PTR_SEG_OFF_TO_LIN(newselector,0),
82 pSeg->minsize ? pSeg->minsize : 0x10000);
83 FreeSelector(newselector);
84 pSeg->selector = oldselector;
85 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
86 "Old selector is %d, new one is %d", oldselector, newselector);
87 } else {
88 FreeSelector(pSeg->selector);
89 pSeg->selector = newselector;
93 IF1632_Saved16_ss = oldss;
94 IF1632_Saved16_sp = oldsp;
96 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
97 read(fd, mem, size);
98 else {
100 The following bit of code for "iterated segments" was written without
101 any documentation on the format of these segments. It seems to work,
102 but may be missing something. If you have any doco please either send
103 it to me or fix the code yourself. gfm@werple.mira.net.au
105 char* buff = malloc(size);
106 char* curr = buff;
107 read(fd, buff, size);
108 while(curr < buff + size) {
109 unsigned int rept = *((short*) curr)++;
110 unsigned int len = *((short*) curr)++;
111 for(; rept > 0; rept--) {
112 char* bytes = curr;
113 unsigned int byte;
114 for(byte = 0; byte < len; byte++)
115 *mem++ = *bytes++;
117 curr += len;
119 free(buff);
122 pSeg->flags |= NE_SEGFLAGS_LOADED;
123 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
124 return TRUE; /* No relocation data, we are done */
126 read( fd, &count, sizeof(count) );
127 if (!count) return TRUE;
129 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector %04x\n",
130 *((BYTE *)pModule + pModule->name_table),
131 *((BYTE *)pModule + pModule->name_table),
132 (char *)pModule + pModule->name_table + 1,
133 segnum, pSeg->selector );
135 reloc_entries = (struct relocation_entry_s *)malloc(count * sizeof(struct relocation_entry_s));
136 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
137 count * sizeof(struct relocation_entry_s))
139 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
140 return FALSE;
144 * Go through the relocation table on entry at a time.
146 rep = reloc_entries;
147 for (i = 0; i < count; i++, rep++)
150 * Get the target address corresponding to this entry.
153 /* If additive, there is no target chain list. Instead, add source
154 and target */
155 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
156 rep->relocation_type &= 0x3;
158 switch (rep->relocation_type)
160 case NE_RELTYPE_ORDINAL:
161 module = pModuleTable[rep->target1-1];
162 ordinal = rep->target2;
163 address = MODULE_GetEntryPoint( module, ordinal );
164 if (!address)
166 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
167 if (!pTarget)
168 fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
169 module, rep->target1,
170 *((BYTE *)pModule + pModule->name_table),
171 *((BYTE *)pModule + pModule->name_table),
172 (char *)pModule + pModule->name_table + 1 );
173 else
174 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
175 *((BYTE *)pTarget + pTarget->name_table),
176 *((BYTE *)pTarget + pTarget->name_table),
177 (char *)pTarget + pTarget->name_table + 1,
178 ordinal );
180 if (debugging_fixup)
182 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
183 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
184 *((BYTE *)pTarget + pTarget->name_table),
185 *((BYTE *)pTarget + pTarget->name_table),
186 (char *)pTarget + pTarget->name_table + 1,
187 ordinal, HIWORD(address), LOWORD(address) );
189 break;
191 case NE_RELTYPE_NAME:
192 module = pModuleTable[rep->target1-1];
193 func_name = (char *)pModule + pModule->import_table + rep->target2;
194 memcpy( buffer, func_name+1, *func_name );
195 buffer[*func_name] = '\0';
196 func_name = buffer;
197 ordinal = MODULE_GetOrdinal( module, func_name );
199 address = MODULE_GetEntryPoint( module, ordinal );
201 if (!address)
203 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
204 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
205 *((BYTE *)pTarget + pTarget->name_table),
206 *((BYTE *)pTarget + pTarget->name_table),
207 (char *)pTarget + pTarget->name_table + 1, func_name );
209 if (debugging_fixup)
211 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
212 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1,
213 *((BYTE *)pTarget + pTarget->name_table),
214 *((BYTE *)pTarget + pTarget->name_table),
215 (char *)pTarget + pTarget->name_table + 1,
216 func_name, HIWORD(address), LOWORD(address) );
218 break;
220 case NE_RELTYPE_INTERNAL:
221 if (rep->target1 == 0x00ff)
223 address = MODULE_GetEntryPoint( hModule, rep->target2 );
225 else
227 address = MAKELONG( rep->target2, pSegTable[rep->target1-1].selector );
230 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
231 i + 1, HIWORD(address), LOWORD(address) );
232 break;
234 case NE_RELTYPE_OSFIXUP:
235 /* Relocation type 7:
237 * These appear to be used as fixups for the Windows
238 * floating point emulator. Let's just ignore them and
239 * try to use the hardware floating point. Linux should
240 * successfully emulate the coprocessor if it doesn't
241 * exist.
243 dprintf_fixup(stddeb,
244 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
245 i + 1, rep->address_type, rep->relocation_type,
246 rep->offset);
247 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
248 rep->target1, rep->target2);
249 continue;
251 default:
252 dprintf_fixup(stddeb,
253 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
254 i + 1, rep->address_type, rep->relocation_type,
255 rep->offset);
256 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
257 rep->target1, rep->target2);
258 free(reloc_entries);
259 return FALSE;
262 offset = rep->offset;
264 switch (rep->address_type)
266 case NE_RADDR_LOWBYTE:
267 do {
268 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
269 dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
270 pSeg->selector, offset, *sp, additive ? " additive":"");
271 offset = *sp;
272 if(additive)
273 *(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
274 else
275 *(unsigned char*)sp = (unsigned char)(address & 0xFF);
277 while (offset != 0xffff && !additive);
278 break;
280 case NE_RADDR_OFFSET16:
281 do {
282 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
283 dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
284 pSeg->selector, offset, *sp, additive ? " additive" : "" );
285 offset = *sp;
286 *sp = LOWORD(address);
287 if (additive) *sp += offset;
289 while (offset != 0xffff && !additive);
290 break;
292 case NE_RADDR_POINTER32:
293 do {
294 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
295 dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
296 pSeg->selector, offset, *sp, additive ? " additive" : "" );
297 offset = *sp;
298 *sp = LOWORD(address);
299 if (additive) *sp += offset;
300 *(sp+1) = HIWORD(address);
302 while (offset != 0xffff && !additive);
303 break;
305 case NE_RADDR_SELECTOR:
306 do {
307 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
308 dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
309 pSeg->selector, offset, *sp, additive ? " additive" : "" );
310 offset = *sp;
311 *sp = HIWORD(address);
312 /* Borland creates additive records with offset zero. Strange, but OK */
313 if(additive && offset)
314 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
316 while (offset != 0xffff && !additive);
317 break;
319 default:
320 dprintf_fixup(stddeb,
321 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
322 i + 1, rep->address_type, rep->relocation_type,
323 rep->offset);
324 dprintf_fixup(stddeb,
325 "TARGET %04x %04x\n", rep->target1, rep->target2);
326 free(reloc_entries);
327 return FALSE;
331 free(reloc_entries);
332 return TRUE;
336 /***********************************************************************
337 * NE_FixupPrologs
339 * Fixup the exported functions prologs.
341 void NE_FixupPrologs( HMODULE hModule )
343 #ifdef WINELIB
344 fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
345 #else
346 NE_MODULE *pModule;
347 SEGTABLEENTRY *pSegTable;
348 WORD dgroup = 0;
349 WORD sel;
350 BYTE *p, *fixup_ptr, count;
352 pModule = (NE_MODULE *)GlobalLock( hModule );
353 pSegTable = NE_SEG_TABLE(pModule);
354 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
355 dgroup = pSegTable[pModule->dgroup-1].selector;
357 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule );
358 p = (BYTE *)pModule + pModule->entry_table;
359 while (*p)
361 if (p[1] == 0) /* Unused entry */
363 p += 2; /* Skip it */
364 continue;
366 if (p[1] == 0xfe) /* Constant entry */
368 p += 2 + *p * 3; /* Skip it */
369 continue;
372 /* Now fixup the entries of this bundle */
373 count = *p;
374 sel = p[1];
375 p += 2;
376 while (count-- > 0)
378 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
379 /* According to the output generated by TDUMP, the flags mean:
380 * 0x0001 function is exported
381 * 0x0002 Single data (seems to occur only in DLLs)
383 if (sel == 0xff) { /* moveable */
384 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
385 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
386 } else { /* fixed */
387 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
388 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
390 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
391 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
392 pModule->flags );
393 if (*p & 0x0001)
395 /* Verify the signature */
396 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
397 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
398 && fixup_ptr[2] == 0x90)
400 if (*p & 0x0002)
402 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
403 /* can this happen? */
404 fprintf( stderr, "FixupPrologs got confused\n" );
406 *fixup_ptr = 0xb8; /* MOV AX, */
407 *(WORD *)(fixup_ptr+1) = dgroup;
409 else
411 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
412 fixup_ptr[0] = 0x90; /* non-library: NOPs */
413 fixup_ptr[1] = 0x90;
414 fixup_ptr[2] = 0x90;
417 } else {
418 dprintf_fixup( stddeb, "Unknown signature\n" );
421 else
422 dprintf_module( stddeb,"\n");
423 p += (sel == 0xff) ? 6 : 3;
426 #endif
430 /***********************************************************************
431 * NE_InitDLL
433 * Call the DLL initialization code
435 static BOOL NE_InitDLL( HMODULE hModule )
437 int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
438 NE_MODULE *pModule;
439 SEGTABLEENTRY *pSegTable;
441 /* Registers at initialization must be:
442 * cx heap size
443 * di library instance
444 * ds data segment if any
445 * es:si command line (always 0)
448 pModule = (NE_MODULE *)GlobalLock( hModule );
449 pSegTable = NE_SEG_TABLE( pModule );
451 if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/
452 if (!pModule->cs) return TRUE; /* no initialization code */
454 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
456 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
458 /* Not SINGLEDATA */
459 fprintf(stderr, "Library is not marked SINGLEDATA\n");
460 exit(1);
462 else /* DATA NONE DLL */
464 ds_reg = 0;
465 cx_reg = 0;
468 else /* DATA SINGLE DLL */
470 ds_reg = pSegTable[pModule->dgroup-1].selector;
471 cx_reg = pModule->heap_size;
474 cs_reg = pSegTable[pModule->cs-1].selector;
475 ip_reg = pModule->ip;
476 di_reg = ds_reg ? ds_reg : hModule;
477 bp_reg = IF1632_Saved16_sp + ((WORD)&((STACK16FRAME*)1)->bp - 1);
479 pModule->cs = 0; /* Don't initialize it twice */
480 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
481 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
482 return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
483 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
484 cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
488 /***********************************************************************
489 * NE_InitializeDLLs
491 * Initialize the loaded DLLs.
493 void NE_InitializeDLLs( HMODULE hModule )
495 NE_MODULE *pModule;
496 WORD *pDLL;
498 pModule = (NE_MODULE *)GlobalLock( hModule );
499 if (pModule->dlls_to_init)
501 HANDLE to_init = pModule->dlls_to_init;
502 pModule->dlls_to_init = 0;
503 for (pDLL = (WORD *)GlobalLock( to_init ); *pDLL; pDLL++)
505 NE_InitializeDLLs( *pDLL );
506 NE_InitDLL( *pDLL );
508 GlobalFree( to_init );
510 NE_InitDLL( hModule );
514 /***********************************************************************
515 * NE_PatchCodeHandle
517 * Needed for self-loading modules.
520 /* It does nothing */
521 void PatchCodeHandle(HANDLE hSel)