Release 961222
[wine/gsoc-2012-control.git] / loader / ne_image.c
blob3bf7849cbe23ff94386ea16f7e2ffaf78d5df2c3
1 #ifndef WINELIB
2 /*
3 * NE modules
5 * Copyright 1993 Robert J. Amstadt
6 * Copyright 1995 Alexandre Julliard
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <ctype.h>
16 #include <string.h>
17 #include <errno.h>
18 #include "neexe.h"
19 #include "windows.h"
20 #include "arch.h"
21 #include "selectors.h"
22 #include "callback.h"
23 #include "file.h"
24 #include "module.h"
25 #include "stackframe.h"
26 #include "stddebug.h"
27 #include "debug.h"
28 #include "xmalloc.h"
31 /***********************************************************************
32 * NE_LoadSegment
34 BOOL NE_LoadSegment( HMODULE16 hModule, WORD segnum )
36 NE_MODULE *pModule;
37 SEGTABLEENTRY *pSegTable, *pSeg;
38 WORD *pModuleTable;
39 WORD count, i, offset;
40 HMODULE16 module;
41 FARPROC16 address;
42 int fd;
43 struct relocation_entry_s *rep, *reloc_entries;
44 BYTE *func_name;
45 int size;
46 char* mem;
48 char buffer[100];
49 int ordinal, additive;
50 unsigned short *sp;
52 if (!(pModule = MODULE_GetPtr( 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=%04x\n",
61 segnum, pSeg->selector );
62 lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
63 size = pSeg->size ? pSeg->size : 0x10000;
64 mem = GlobalLock16(pSeg->selector);
65 if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1) {
66 #ifndef WINELIB
67 /* Implement self loading segments */
68 SELFLOADHEADER *selfloadheader;
69 STACK16FRAME *stack16Top;
70 WORD oldss, oldsp, oldselector, newselector;
71 HFILE hf = FILE_DupUnixHandle( fd );
73 selfloadheader = (SELFLOADHEADER *)
74 PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
75 oldss = IF1632_Saved16_ss;
76 oldsp = IF1632_Saved16_sp;
77 oldselector = pSeg->selector;
78 IF1632_Saved16_ss = pModule->self_loading_sel;
79 IF1632_Saved16_sp = 0xFF00 - sizeof(*stack16Top);
80 stack16Top = CURRENT_STACK16;
81 stack16Top->saved_ss = 0;
82 stack16Top->saved_sp = 0;
83 stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
84 stack16Top->entry_point = 0;
85 stack16Top->entry_ip = 0;
86 stack16Top->entry_cs = 0;
87 stack16Top->bp = 0;
88 stack16Top->ip = 0;
89 stack16Top->cs = 0;
90 newselector = CallTo16_word_www( selfloadheader->LoadAppSeg,
91 hModule, hf, segnum );
92 _lclose( hf );
93 if (newselector != oldselector) {
94 /* Self loaders like creating their own selectors;
95 * they love asking for trouble to Wine developers
97 if (segnum == pModule->dgroup) {
98 memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
99 PTR_SEG_OFF_TO_LIN(newselector,0),
100 pSeg->minsize ? pSeg->minsize : 0x10000);
101 FreeSelector(newselector);
102 pSeg->selector = oldselector;
103 fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
104 "Old selector is %d, new one is %d", oldselector, newselector);
105 } else {
106 FreeSelector(pSeg->selector);
107 pSeg->selector = newselector;
111 IF1632_Saved16_ss = oldss;
112 IF1632_Saved16_sp = oldsp;
113 #else
114 fprintf(stderr,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
115 #endif
117 else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
118 read(fd, mem, size);
119 else {
121 The following bit of code for "iterated segments" was written without
122 any documentation on the format of these segments. It seems to work,
123 but may be missing something. If you have any doco please either send
124 it to me or fix the code yourself. gfm@werple.mira.net.au
126 char* buff = xmalloc(size);
127 char* curr = buff;
128 read(fd, buff, size);
129 while(curr < buff + size) {
130 unsigned int rept = *((short*) curr)++;
131 unsigned int len = *((short*) curr)++;
132 for(; rept > 0; rept--) {
133 char* bytes = curr;
134 unsigned int byte;
135 for(byte = 0; byte < len; byte++)
136 *mem++ = *bytes++;
138 curr += len;
140 free(buff);
143 pSeg->flags |= NE_SEGFLAGS_LOADED;
144 if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
145 return TRUE; /* No relocation data, we are done */
147 read( fd, &count, sizeof(count) );
148 if (!count) return TRUE;
150 dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector %04x\n",
151 *((BYTE *)pModule + pModule->name_table),
152 *((BYTE *)pModule + pModule->name_table),
153 (char *)pModule + pModule->name_table + 1,
154 segnum, pSeg->selector );
156 reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
157 if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
158 count * sizeof(struct relocation_entry_s))
160 dprintf_fixup( stddeb, "Unable to read relocation information\n" );
161 return FALSE;
165 * Go through the relocation table on entry at a time.
167 rep = reloc_entries;
168 for (i = 0; i < count; i++, rep++)
171 * Get the target address corresponding to this entry.
174 /* If additive, there is no target chain list. Instead, add source
175 and target */
176 additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
177 rep->relocation_type &= 0x3;
179 switch (rep->relocation_type)
181 case NE_RELTYPE_ORDINAL:
182 module = pModuleTable[rep->target1-1];
183 ordinal = rep->target2;
184 address = MODULE_GetEntryPoint( module, ordinal );
185 if (!address)
187 NE_MODULE *pTarget = MODULE_GetPtr( module );
188 if (!pTarget)
189 fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
190 module, rep->target1,
191 *((BYTE *)pModule + pModule->name_table),
192 *((BYTE *)pModule + pModule->name_table),
193 (char *)pModule + pModule->name_table + 1 );
194 else
195 fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
196 *((BYTE *)pTarget + pTarget->name_table),
197 *((BYTE *)pTarget + pTarget->name_table),
198 (char *)pTarget + pTarget->name_table + 1,
199 ordinal );
201 if (debugging_fixup)
203 NE_MODULE *pTarget = MODULE_GetPtr( module );
204 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
205 *((BYTE *)pTarget + pTarget->name_table),
206 *((BYTE *)pTarget + pTarget->name_table),
207 (char *)pTarget + pTarget->name_table + 1,
208 ordinal, HIWORD(address), LOWORD(address) );
210 break;
212 case NE_RELTYPE_NAME:
213 module = pModuleTable[rep->target1-1];
214 func_name = (char *)pModule + pModule->import_table + rep->target2;
215 memcpy( buffer, func_name+1, *func_name );
216 buffer[*func_name] = '\0';
217 func_name = buffer;
218 ordinal = MODULE_GetOrdinal( module, func_name );
220 address = MODULE_GetEntryPoint( module, ordinal );
222 if (!address)
224 NE_MODULE *pTarget = MODULE_GetPtr( module );
225 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
226 *((BYTE *)pTarget + pTarget->name_table),
227 *((BYTE *)pTarget + pTarget->name_table),
228 (char *)pTarget + pTarget->name_table + 1, func_name );
230 if (debugging_fixup)
232 NE_MODULE *pTarget = MODULE_GetPtr( module );
233 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1,
234 *((BYTE *)pTarget + pTarget->name_table),
235 *((BYTE *)pTarget + pTarget->name_table),
236 (char *)pTarget + pTarget->name_table + 1,
237 func_name, HIWORD(address), LOWORD(address) );
239 break;
241 case NE_RELTYPE_INTERNAL:
242 if (rep->target1 == 0x00ff)
244 address = MODULE_GetEntryPoint( hModule, rep->target2 );
246 else
248 address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( pSegTable[rep->target1-1].selector, rep->target2 );
251 dprintf_fixup(stddeb,"%d: %04x:%04x\n",
252 i + 1, HIWORD(address), LOWORD(address) );
253 break;
255 case NE_RELTYPE_OSFIXUP:
256 /* Relocation type 7:
258 * These appear to be used as fixups for the Windows
259 * floating point emulator. Let's just ignore them and
260 * try to use the hardware floating point. Linux should
261 * successfully emulate the coprocessor if it doesn't
262 * exist.
264 dprintf_fixup(stddeb,
265 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
266 i + 1, rep->address_type, rep->relocation_type,
267 rep->offset);
268 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
269 rep->target1, rep->target2);
270 continue;
272 default:
273 dprintf_fixup(stddeb,
274 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
275 i + 1, rep->address_type, rep->relocation_type,
276 rep->offset);
277 dprintf_fixup(stddeb,"TARGET %04x %04x\n",
278 rep->target1, rep->target2);
279 free(reloc_entries);
280 return FALSE;
283 offset = rep->offset;
285 switch (rep->address_type)
287 case NE_RADDR_LOWBYTE:
288 do {
289 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
290 dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
291 pSeg->selector, offset, *sp, additive ? " additive":"");
292 offset = *sp;
293 if(additive)
294 *(unsigned char*)sp = (unsigned char)(((int)address+offset) & 0xFF);
295 else
296 *(unsigned char*)sp = (unsigned char)((int)address & 0xFF);
298 while (offset != 0xffff && !additive);
299 break;
301 case NE_RADDR_OFFSET16:
302 do {
303 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
304 dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
305 pSeg->selector, offset, *sp, additive ? " additive" : "" );
306 offset = *sp;
307 *sp = LOWORD(address);
308 if (additive) *sp += offset;
310 while (offset != 0xffff && !additive);
311 break;
313 case NE_RADDR_POINTER32:
314 do {
315 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
316 dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
317 pSeg->selector, offset, *sp, additive ? " additive" : "" );
318 offset = *sp;
319 *sp = LOWORD(address);
320 if (additive) *sp += offset;
321 *(sp+1) = HIWORD(address);
323 while (offset != 0xffff && !additive);
324 break;
326 case NE_RADDR_SELECTOR:
327 do {
328 sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
329 dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
330 pSeg->selector, offset, *sp, additive ? " additive" : "" );
331 offset = *sp;
332 *sp = HIWORD(address);
333 /* Borland creates additive records with offset zero. Strange, but OK */
334 if(additive && offset)
335 fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
337 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
338 while (offset && offset != 0xffff && !additive);
339 break;
341 default:
342 dprintf_fixup(stddeb,
343 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
344 i + 1, rep->address_type, rep->relocation_type,
345 rep->offset);
346 dprintf_fixup(stddeb,
347 "TARGET %04x %04x\n", rep->target1, rep->target2);
348 free(reloc_entries);
349 return FALSE;
353 free(reloc_entries);
354 return TRUE;
358 /***********************************************************************
359 * NE_FixupPrologs
361 * Fixup the exported functions prologs.
363 void NE_FixupPrologs( NE_MODULE *pModule )
365 #ifdef WINELIB
366 fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
367 #else
368 SEGTABLEENTRY *pSegTable;
369 WORD dgroup = 0;
370 WORD sel;
371 BYTE *p, *fixup_ptr, count;
373 pSegTable = NE_SEG_TABLE(pModule);
374 if (pModule->flags & NE_FFLAGS_SINGLEDATA)
375 dgroup = pSegTable[pModule->dgroup-1].selector;
377 dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self );
378 p = (BYTE *)pModule + pModule->entry_table;
379 while (*p)
381 if (p[1] == 0) /* Unused entry */
383 p += 2; /* Skip it */
384 continue;
386 if (p[1] == 0xfe) /* Constant entry */
388 p += 2 + *p * 3; /* Skip it */
389 continue;
392 /* Now fixup the entries of this bundle */
393 count = *p;
394 sel = p[1];
395 p += 2;
396 while (count-- > 0)
398 dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
399 /* According to the output generated by TDUMP, the flags mean:
400 * 0x0001 function is exported
401 * 0x0002 Single data (seems to occur only in DLLs)
403 if (sel == 0xff) { /* moveable */
404 dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
405 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
406 } else { /* fixed */
407 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
408 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
410 dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
411 fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
412 pModule->flags );
413 if (*p & 0x0001)
415 /* Verify the signature */
416 if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
417 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
418 && fixup_ptr[2] == 0x90)
420 if (*p & 0x0002)
422 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
423 /* can this happen? */
424 fprintf( stderr, "FixupPrologs got confused\n" );
426 *fixup_ptr = 0xb8; /* MOV AX, */
427 *(WORD *)(fixup_ptr+1) = dgroup;
429 else
431 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
432 fixup_ptr[0] = 0x90; /* non-library: NOPs */
433 fixup_ptr[1] = 0x90;
434 fixup_ptr[2] = 0x90;
437 } else {
438 dprintf_fixup( stddeb, "Unknown signature\n" );
441 else
442 dprintf_module( stddeb,"\n");
443 p += (sel == 0xff) ? 6 : 3;
446 #endif
450 /***********************************************************************
451 * NE_InitDLL
453 * Call the DLL initialization code
455 static BOOL NE_InitDLL( HMODULE16 hModule )
457 #ifndef WINELIB
458 int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
459 NE_MODULE *pModule;
460 SEGTABLEENTRY *pSegTable;
462 /* Registers at initialization must be:
463 * cx heap size
464 * di library instance
465 * ds data segment if any
466 * es:si command line (always 0)
469 if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
470 pSegTable = NE_SEG_TABLE( pModule );
472 if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
473 (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
474 if (!pModule->cs) return TRUE; /* no initialization code */
476 if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
478 if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
480 /* Not SINGLEDATA */
481 fprintf(stderr, "Library is not marked SINGLEDATA\n");
482 exit(1);
484 else /* DATA NONE DLL */
486 ds_reg = 0;
487 cx_reg = 0;
490 else /* DATA SINGLE DLL */
492 ds_reg = pSegTable[pModule->dgroup-1].selector;
493 cx_reg = pModule->heap_size;
496 cs_reg = pSegTable[pModule->cs-1].selector;
497 ip_reg = pModule->ip;
498 di_reg = ds_reg ? ds_reg : hModule;
499 bp_reg = IF1632_Saved16_sp + ((WORD)&((STACK16FRAME*)1)->bp - 1);
501 pModule->cs = 0; /* Don't initialize it twice */
502 dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
503 cs_reg, ip_reg, ds_reg, di_reg, cx_reg );
504 return CallTo16_regs_( (FARPROC16)(cs_reg << 16 | ip_reg), ds_reg,
505 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
506 cx_reg, 0 /*dx*/, 0 /*si*/, di_reg );
507 #else
508 fprintf( stderr,"JBP: Ignoring call to LibMain\n" );
509 return FALSE;
510 #endif
514 /***********************************************************************
515 * NE_InitializeDLLs
517 * Initialize the loaded DLLs.
519 void NE_InitializeDLLs( HMODULE16 hModule )
521 NE_MODULE *pModule;
522 HMODULE16 *pDLL;
524 if (!(pModule = MODULE_GetPtr( hModule ))) return;
525 if (pModule->flags & NE_FFLAGS_WIN32)
527 /* PE_InitializeDLLs(hModule); */
528 return;
530 if (pModule->dlls_to_init)
532 HGLOBAL16 to_init = pModule->dlls_to_init;
533 pModule->dlls_to_init = 0;
534 for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
536 NE_InitializeDLLs( *pDLL );
537 NE_InitDLL( *pDLL );
539 GlobalFree16( to_init );
541 NE_InitDLL( hModule );
545 /***********************************************************************
546 * NE_PatchCodeHandle
548 * Needed for self-loading modules.
551 /* It does nothing */
552 void PatchCodeHandle(HANDLE16 hSel)
555 #endif /* WINELIB */