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