Release 960131
[wine] / loader / ne_image.c
1 #ifndef WINELIB
2 /*
3  * NE modules
4  *
5  * Copyright 1993 Robert J. Amstadt
6  * Copyright 1995 Alexandre Julliard
7  */
8
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 "dlls.h"
20 #include "windows.h"
21 #include "arch.h"
22 #include "selectors.h"
23 #include "callback.h"
24 #include "module.h"
25 #include "stackframe.h"
26 #include "stddebug.h"
27 #include "debug.h"
28 #include "xmalloc.h"
29
30
31 /***********************************************************************
32  *           NE_LoadSegment
33  */
34 BOOL NE_LoadSegment( HMODULE hModule, WORD segnum )
35 {
36     NE_MODULE *pModule;
37     SEGTABLEENTRY *pSegTable, *pSeg;
38     WORD *pModuleTable;
39     WORD count, i, offset;
40     HMODULE module;
41     DWORD address;
42     int fd;
43     struct relocation_entry_s *rep, *reloc_entries;
44     BYTE *func_name;
45     int size;
46     char* mem;
47
48     char buffer[100];
49     int ordinal, additive;
50     unsigned short *sp;
51
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 );
56
57     if (!pSeg->filepos) return TRUE;  /* No file image, just return */
58         
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) {    
66 #ifndef WINELIB
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
82            */
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);
91           } else {
92             FreeSelector(pSeg->selector);
93             pSeg->selector = newselector;
94           }
95         } 
96         
97         IF1632_Saved16_ss = oldss;
98         IF1632_Saved16_sp = oldsp;
99 #else
100         fprintf(stderr,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
101 #endif
102      }
103     else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
104       read(fd, mem, size);
105     else {
106       /*
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
111       */
112       char* buff = xmalloc(size);
113       char* curr = buff;
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--) {
119           char* bytes = curr;
120           unsigned int byte;
121           for(byte = 0; byte < len; byte++)
122             *mem++ = *bytes++;
123         }
124         curr += len;
125       }
126       free(buff);
127     }
128
129     pSeg->flags |= NE_SEGFLAGS_LOADED;
130     if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
131         return TRUE;  /* No relocation data, we are done */
132
133     read( fd, &count, sizeof(count) );
134     if (!count) return TRUE;
135
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 );
141
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))
145     {
146         dprintf_fixup( stddeb, "Unable to read relocation information\n" );
147         return FALSE;
148     }
149
150     /*
151      * Go through the relocation table on entry at a time.
152      */
153     rep = reloc_entries;
154     for (i = 0; i < count; i++, rep++)
155     {
156         /*
157          * Get the target address corresponding to this entry.
158          */
159
160         /* If additive, there is no target chain list. Instead, add source
161            and target */
162         additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
163         rep->relocation_type &= 0x3;
164         
165         switch (rep->relocation_type)
166         {
167           case NE_RELTYPE_ORDINAL:
168             module = pModuleTable[rep->target1-1];
169             ordinal = rep->target2;
170             address = MODULE_GetEntryPoint( module, ordinal );
171             if (!address)
172             {
173                 NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
174                 if (!pTarget)
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 );
180                 else
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,
185                             ordinal );
186             }
187             if (debugging_fixup)
188             {
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) );
195             }
196             break;
197             
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';
203             func_name = buffer;
204             ordinal = MODULE_GetOrdinal( module, func_name );
205
206             address = MODULE_GetEntryPoint( module, ordinal );
207
208             if (!address)
209             {
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 );
215             }
216             if (debugging_fixup)
217             {
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) );
224             }
225             break;
226             
227           case NE_RELTYPE_INTERNAL:
228             if (rep->target1 == 0x00ff)
229             {
230                 address  = MODULE_GetEntryPoint( hModule, rep->target2 );
231             }
232             else
233             {
234                 address = MAKELONG( rep->target2, pSegTable[rep->target1-1].selector );
235             }
236             
237             dprintf_fixup(stddeb,"%d: %04x:%04x\n", 
238                           i + 1, HIWORD(address), LOWORD(address) );
239             break;
240
241           case NE_RELTYPE_OSFIXUP:
242             /* Relocation type 7:
243              *
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
248              * exist.
249              */
250             dprintf_fixup(stddeb,
251                    "%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04x,  ",
252                    i + 1, rep->address_type, rep->relocation_type, 
253                    rep->offset);
254             dprintf_fixup(stddeb,"TARGET %04x %04x\n", 
255                    rep->target1, rep->target2);
256             continue;
257             
258           default:
259             dprintf_fixup(stddeb,
260                    "%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04x,  ",
261                    i + 1, rep->address_type, rep->relocation_type, 
262                    rep->offset);
263             dprintf_fixup(stddeb,"TARGET %04x %04x\n", 
264                     rep->target1, rep->target2);
265             free(reloc_entries);
266             return FALSE;
267         }
268
269         offset  = rep->offset;
270
271         switch (rep->address_type)
272         {
273           case NE_RADDR_LOWBYTE:
274             do {
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":"");
278                 offset = *sp;
279                 if(additive)
280                     *(unsigned char*)sp = (unsigned char)((address+offset) & 0xFF);
281                 else
282                     *(unsigned char*)sp = (unsigned char)(address & 0xFF);
283             }
284             while (offset != 0xffff && !additive);
285             break;
286
287           case NE_RADDR_OFFSET16:
288             do {
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" : "" );
292                 offset = *sp;
293                 *sp = LOWORD(address);
294                 if (additive) *sp += offset;
295             } 
296             while (offset != 0xffff && !additive);
297             break;
298             
299           case NE_RADDR_POINTER32:
300             do {
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" : "" );
304                 offset = *sp;
305                 *sp    = LOWORD(address);
306                 if (additive) *sp += offset;
307                 *(sp+1) = HIWORD(address);
308             } 
309             while (offset != 0xffff && !additive);
310             break;
311             
312           case NE_RADDR_SELECTOR:
313             do {
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" : "" );
317                 offset = *sp;
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);
322             } 
323             /* FIXME: Quicken 5 has a zero offset fixup.  This seems to work */
324             while (offset && offset != 0xffff && !additive);
325             break;
326             
327           default:
328             dprintf_fixup(stddeb,
329                    "%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04x,  ",
330                    i + 1, rep->address_type, rep->relocation_type, 
331                    rep->offset);
332             dprintf_fixup(stddeb,
333                    "TARGET %04x %04x\n", rep->target1, rep->target2);
334             free(reloc_entries);
335             return FALSE;
336         }
337     }
338
339     free(reloc_entries);
340     return TRUE;
341 }
342
343
344 /***********************************************************************
345  *           NE_FixupPrologs
346  *
347  * Fixup the exported functions prologs.
348  */
349 void NE_FixupPrologs( HMODULE hModule )
350 {
351 #ifdef WINELIB
352         fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
353 #else
354     NE_MODULE *pModule;
355     SEGTABLEENTRY *pSegTable;
356     WORD dgroup = 0;
357     WORD sel;
358     BYTE *p, *fixup_ptr, count;
359
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;
364
365     dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule );
366     p = (BYTE *)pModule + pModule->entry_table;
367     while (*p)
368     {
369         if (p[1] == 0)  /* Unused entry */
370         {
371             p += 2;  /* Skip it */
372             continue;
373         }
374         if (p[1] == 0xfe)  /* Constant entry */
375         {
376             p += 2 + *p * 3;  /* Skip it */
377             continue;
378         }
379
380         /* Now fixup the entries of this bundle */
381         count = *p;
382         sel = p[1];
383         p += 2;
384         while (count-- > 0)
385         {
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)
390              */
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);
394             } else { /* fixed */
395                 dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
396                 fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
397             }
398             dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
399                            fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
400                            pModule->flags );
401             if (*p & 0x0001)
402             {
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)
407                 {
408                     if (*p & 0x0002)
409                     {
410                         if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
411                             /* can this happen? */
412                             fprintf( stderr, "FixupPrologs got confused\n" );
413                         }
414                         *fixup_ptr = 0xb8;      /* MOV AX, */
415                         *(WORD *)(fixup_ptr+1) = dgroup;
416                     }
417                     else
418                     {
419                         if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
420                             fixup_ptr[0] = 0x90; /* non-library: NOPs */
421                             fixup_ptr[1] = 0x90;
422                             fixup_ptr[2] = 0x90;
423                         }
424                     }
425                 } else {
426                     dprintf_fixup( stddeb, "Unknown signature\n" );
427                 }
428             }
429             else
430               dprintf_module( stddeb,"\n");
431             p += (sel == 0xff) ? 6 : 3;  
432         }
433     }
434 #endif
435 }
436
437
438 /***********************************************************************
439  *           NE_InitDLL
440  *
441  * Call the DLL initialization code
442  */
443 static BOOL NE_InitDLL( HMODULE hModule )
444 {
445 #ifndef WINELIB
446     int cs_reg, ds_reg, ip_reg, cx_reg, di_reg, bp_reg;
447     NE_MODULE *pModule;
448     SEGTABLEENTRY *pSegTable;
449
450     /* Registers at initialization must be:
451      * cx     heap size
452      * di     library instance
453      * ds     data segment if any
454      * es:si  command line (always 0)
455      */
456
457     pModule = (NE_MODULE *)GlobalLock( hModule );
458     pSegTable = NE_SEG_TABLE( pModule );
459
460     if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/
461     if (!pModule->cs) return TRUE;  /* no initialization code */
462
463     if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
464     {
465         if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
466         {
467             /* Not SINGLEDATA */
468             fprintf(stderr, "Library is not marked SINGLEDATA\n");
469             exit(1);
470         }
471         else  /* DATA NONE DLL */
472         {
473             ds_reg = 0;
474             cx_reg = 0;
475         }
476     }
477     else  /* DATA SINGLE DLL */
478     {
479         ds_reg = pSegTable[pModule->dgroup-1].selector;
480         cx_reg = pModule->heap_size;
481     }
482
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);
487
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 );
494 #else
495     fprintf( stderr,"JBP: Ignoring call to LibMain\n" );
496     return FALSE;
497 #endif
498 }
499
500
501 /***********************************************************************
502  *           NE_InitializeDLLs
503  *
504  * Initialize the loaded DLLs.
505  */
506 void NE_InitializeDLLs( HMODULE hModule )
507 {
508     NE_MODULE *pModule;
509     HMODULE *pDLL;
510
511     pModule = (NE_MODULE *)GlobalLock( hModule );
512         if (pModule->magic == PE_SIGNATURE)
513         {
514                 PE_InitializeDLLs(hModule);
515                 return;
516         }
517     if (pModule->dlls_to_init)
518     {
519         HANDLE to_init = pModule->dlls_to_init;
520         pModule->dlls_to_init = 0;
521         for (pDLL = (HMODULE *)GlobalLock( to_init ); *pDLL; pDLL++)
522         {
523             NE_InitializeDLLs( *pDLL );
524             NE_InitDLL( *pDLL );
525         }
526         GlobalFree( to_init );
527     }
528     NE_InitDLL( hModule );
529 }
530
531
532 /***********************************************************************
533  *           NE_PatchCodeHandle
534  *
535  * Needed for self-loading modules.
536  */
537
538 /* It does nothing */
539 void PatchCodeHandle(HANDLE hSel)
540 {
541 }
542 #endif /* WINELIB */