5 * Copyright 1993 Robert J. Amstadt
6 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
21 #include "selectors.h"
24 #include "stackframe.h"
30 /***********************************************************************
33 BOOL
NE_LoadSegment( HMODULE16 hModule
, WORD segnum
)
36 SEGTABLEENTRY
*pSegTable
, *pSeg
;
38 WORD count
, i
, offset
;
42 struct relocation_entry_s
*rep
, *reloc_entries
;
48 int ordinal
, additive
;
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
);
56 if (!pSeg
->filepos
) return TRUE
; /* No file image, just return */
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) {
66 /* Implement self loading segments */
67 SELFLOADHEADER
*selfloadheader
;
68 STACK16FRAME
*stack16Top
;
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 - sizeof(*stack16Top
);
77 stack16Top
= CURRENT_STACK16
;
78 stack16Top
->saved_ss
= 0;
79 stack16Top
->saved_sp
= 0;
80 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
81 stack16Top
->entry_point
= 0;
82 stack16Top
->entry_ip
= 0;
83 stack16Top
->entry_cs
= 0;
87 /* FIXME: we probably need to pass a DOS file handle here */
88 newselector
= CallTo16_word_www(selfloadheader
->LoadAppSeg
,
89 pModule
->self_loading_sel
, hModule
, fd
, segnum
);
90 if (newselector
!= oldselector
) {
91 /* Self loaders like creating their own selectors;
92 * they love asking for trouble to Wine developers
94 if (segnum
== pModule
->dgroup
) {
95 memcpy(PTR_SEG_OFF_TO_LIN(oldselector
,0),
96 PTR_SEG_OFF_TO_LIN(newselector
,0),
97 pSeg
->minsize
? pSeg
->minsize
: 0x10000);
98 FreeSelector(newselector
);
99 pSeg
->selector
= oldselector
;
100 fprintf(stderr
, "A new selector was allocated for the dgroup segment\n"
101 "Old selector is %d, new one is %d", oldselector
, newselector
);
103 FreeSelector(pSeg
->selector
);
104 pSeg
->selector
= newselector
;
108 IF1632_Saved16_ss
= oldss
;
109 IF1632_Saved16_sp
= oldsp
;
111 fprintf(stderr
,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
114 else if (!(pSeg
->flags
& NE_SEGFLAGS_ITERATED
))
118 The following bit of code for "iterated segments" was written without
119 any documentation on the format of these segments. It seems to work,
120 but may be missing something. If you have any doco please either send
121 it to me or fix the code yourself. gfm@werple.mira.net.au
123 char* buff
= xmalloc(size
);
125 read(fd
, buff
, size
);
126 while(curr
< buff
+ size
) {
127 unsigned int rept
= *((short*) curr
)++;
128 unsigned int len
= *((short*) curr
)++;
129 for(; rept
> 0; rept
--) {
132 for(byte
= 0; byte
< len
; byte
++)
140 pSeg
->flags
|= NE_SEGFLAGS_LOADED
;
141 if (!(pSeg
->flags
& NE_SEGFLAGS_RELOC_DATA
))
142 return TRUE
; /* No relocation data, we are done */
144 read( fd
, &count
, sizeof(count
) );
145 if (!count
) return TRUE
;
147 dprintf_fixup( stddeb
, "Fixups for %*.*s, segment %d, selector %04x\n",
148 *((BYTE
*)pModule
+ pModule
->name_table
),
149 *((BYTE
*)pModule
+ pModule
->name_table
),
150 (char *)pModule
+ pModule
->name_table
+ 1,
151 segnum
, pSeg
->selector
);
153 reloc_entries
= (struct relocation_entry_s
*)xmalloc(count
* sizeof(struct relocation_entry_s
));
154 if (read( fd
, reloc_entries
, count
* sizeof(struct relocation_entry_s
)) !=
155 count
* sizeof(struct relocation_entry_s
))
157 dprintf_fixup( stddeb
, "Unable to read relocation information\n" );
162 * Go through the relocation table on entry at a time.
165 for (i
= 0; i
< count
; i
++, rep
++)
168 * Get the target address corresponding to this entry.
171 /* If additive, there is no target chain list. Instead, add source
173 additive
= rep
->relocation_type
& NE_RELFLAG_ADDITIVE
;
174 rep
->relocation_type
&= 0x3;
176 switch (rep
->relocation_type
)
178 case NE_RELTYPE_ORDINAL
:
179 module
= pModuleTable
[rep
->target1
-1];
180 ordinal
= rep
->target2
;
181 address
= MODULE_GetEntryPoint( module
, ordinal
);
184 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
186 fprintf( stderr
, "Module not found: %04x, reference %d of module %*.*s\n",
187 module
, rep
->target1
,
188 *((BYTE
*)pModule
+ pModule
->name_table
),
189 *((BYTE
*)pModule
+ pModule
->name_table
),
190 (char *)pModule
+ pModule
->name_table
+ 1 );
192 fprintf( stderr
, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
193 *((BYTE
*)pTarget
+ pTarget
->name_table
),
194 *((BYTE
*)pTarget
+ pTarget
->name_table
),
195 (char *)pTarget
+ pTarget
->name_table
+ 1,
200 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
201 fprintf( stddeb
,"%d: %*.*s.%d=%04x:%04x\n", i
+ 1,
202 *((BYTE
*)pTarget
+ pTarget
->name_table
),
203 *((BYTE
*)pTarget
+ pTarget
->name_table
),
204 (char *)pTarget
+ pTarget
->name_table
+ 1,
205 ordinal
, HIWORD(address
), LOWORD(address
) );
209 case NE_RELTYPE_NAME
:
210 module
= pModuleTable
[rep
->target1
-1];
211 func_name
= (char *)pModule
+ pModule
->import_table
+ rep
->target2
;
212 memcpy( buffer
, func_name
+1, *func_name
);
213 buffer
[*func_name
] = '\0';
215 ordinal
= MODULE_GetOrdinal( module
, func_name
);
217 address
= MODULE_GetEntryPoint( module
, ordinal
);
221 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
222 fprintf( stderr
, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
223 *((BYTE
*)pTarget
+ pTarget
->name_table
),
224 *((BYTE
*)pTarget
+ pTarget
->name_table
),
225 (char *)pTarget
+ pTarget
->name_table
+ 1, func_name
);
229 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
230 fprintf( stddeb
,"%d: %*.*s.%s=%04x:%04x\n", i
+ 1,
231 *((BYTE
*)pTarget
+ pTarget
->name_table
),
232 *((BYTE
*)pTarget
+ pTarget
->name_table
),
233 (char *)pTarget
+ pTarget
->name_table
+ 1,
234 func_name
, HIWORD(address
), LOWORD(address
) );
238 case NE_RELTYPE_INTERNAL
:
239 if (rep
->target1
== 0x00ff)
241 address
= MODULE_GetEntryPoint( hModule
, rep
->target2
);
245 address
= (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( pSegTable
[rep
->target1
-1].selector
, rep
->target2
);
248 dprintf_fixup(stddeb
,"%d: %04x:%04x\n",
249 i
+ 1, HIWORD(address
), LOWORD(address
) );
252 case NE_RELTYPE_OSFIXUP
:
253 /* Relocation type 7:
255 * These appear to be used as fixups for the Windows
256 * floating point emulator. Let's just ignore them and
257 * try to use the hardware floating point. Linux should
258 * successfully emulate the coprocessor if it doesn't
261 dprintf_fixup(stddeb
,
262 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
263 i
+ 1, rep
->address_type
, rep
->relocation_type
,
265 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
266 rep
->target1
, rep
->target2
);
270 dprintf_fixup(stddeb
,
271 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
272 i
+ 1, rep
->address_type
, rep
->relocation_type
,
274 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
275 rep
->target1
, rep
->target2
);
280 offset
= rep
->offset
;
282 switch (rep
->address_type
)
284 case NE_RADDR_LOWBYTE
:
286 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
287 dprintf_fixup(stddeb
," %04x:%04x:%04x BYTE%s\n",
288 pSeg
->selector
, offset
, *sp
, additive
? " additive":"");
291 *(unsigned char*)sp
= (unsigned char)(((int)address
+offset
) & 0xFF);
293 *(unsigned char*)sp
= (unsigned char)((int)address
& 0xFF);
295 while (offset
!= 0xffff && !additive
);
298 case NE_RADDR_OFFSET16
:
300 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
301 dprintf_fixup(stddeb
," %04x:%04x:%04x OFFSET16%s\n",
302 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
304 *sp
= LOWORD(address
);
305 if (additive
) *sp
+= offset
;
307 while (offset
!= 0xffff && !additive
);
310 case NE_RADDR_POINTER32
:
312 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
313 dprintf_fixup(stddeb
," %04x:%04x:%04x POINTER32%s\n",
314 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
316 *sp
= LOWORD(address
);
317 if (additive
) *sp
+= offset
;
318 *(sp
+1) = HIWORD(address
);
320 while (offset
!= 0xffff && !additive
);
323 case NE_RADDR_SELECTOR
:
325 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
326 dprintf_fixup(stddeb
," %04x:%04x:%04x SELECTOR%s\n",
327 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
329 *sp
= HIWORD(address
);
330 /* Borland creates additive records with offset zero. Strange, but OK */
331 if(additive
&& offset
)
332 fprintf(stderr
,"Additive selector to %4.4x.Please report\n",offset
);
334 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
335 while (offset
&& offset
!= 0xffff && !additive
);
339 dprintf_fixup(stddeb
,
340 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
341 i
+ 1, rep
->address_type
, rep
->relocation_type
,
343 dprintf_fixup(stddeb
,
344 "TARGET %04x %04x\n", rep
->target1
, rep
->target2
);
355 /***********************************************************************
358 * Fixup the exported functions prologs.
360 void NE_FixupPrologs( NE_MODULE
*pModule
)
363 fprintf(stderr
,"NE_FixupPrologs should not be called for libwine\n");
365 SEGTABLEENTRY
*pSegTable
;
368 BYTE
*p
, *fixup_ptr
, count
;
370 pSegTable
= NE_SEG_TABLE(pModule
);
371 if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
372 dgroup
= pSegTable
[pModule
->dgroup
-1].selector
;
374 dprintf_module( stddeb
, "MODULE_FixupPrologs(%04x)\n", pModule
->self
);
375 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
378 if (p
[1] == 0) /* Unused entry */
380 p
+= 2; /* Skip it */
383 if (p
[1] == 0xfe) /* Constant entry */
385 p
+= 2 + *p
* 3; /* Skip it */
389 /* Now fixup the entries of this bundle */
395 dprintf_module( stddeb
,"Flags: %04x, sel %02x ", *p
, sel
);
396 /* According to the output generated by TDUMP, the flags mean:
397 * 0x0001 function is exported
398 * 0x0002 Single data (seems to occur only in DLLs)
400 if (sel
== 0xff) { /* moveable */
401 dprintf_module( stddeb
, "(%02x) o %04x ", p
[3], *(WORD
*)(p
+4) );
402 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[p
[3]-1].selector
) + *(WORD
*)(p
+ 4);
404 dprintf_module( stddeb
, "offset %04x ", *(WORD
*)(p
+1) );
405 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[sel
-1].selector
) + *(WORD
*)(p
+ 1);
407 dprintf_module( stddeb
, "Signature: %02x %02x %02x,ff %x\n",
408 fixup_ptr
[0], fixup_ptr
[1], fixup_ptr
[2],
412 /* Verify the signature */
413 if (((fixup_ptr
[0] == 0x1e && fixup_ptr
[1] == 0x58)
414 || (fixup_ptr
[0] == 0x8c && fixup_ptr
[1] == 0xd8))
415 && fixup_ptr
[2] == 0x90)
419 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
420 /* can this happen? */
421 fprintf( stderr
, "FixupPrologs got confused\n" );
423 *fixup_ptr
= 0xb8; /* MOV AX, */
424 *(WORD
*)(fixup_ptr
+1) = dgroup
;
428 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
429 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
435 dprintf_fixup( stddeb
, "Unknown signature\n" );
439 dprintf_module( stddeb
,"\n");
440 p
+= (sel
== 0xff) ? 6 : 3;
447 /***********************************************************************
450 * Call the DLL initialization code
452 static BOOL
NE_InitDLL( HMODULE16 hModule
)
455 int cs_reg
, ds_reg
, ip_reg
, cx_reg
, di_reg
, bp_reg
;
457 SEGTABLEENTRY
*pSegTable
;
459 /* Registers at initialization must be:
461 * di library instance
462 * ds data segment if any
463 * es:si command line (always 0)
466 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
467 pSegTable
= NE_SEG_TABLE( pModule
);
469 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) ||
470 (pModule
->flags
& NE_FFLAGS_WIN32
)) return TRUE
; /*not a library*/
471 if (!pModule
->cs
) return TRUE
; /* no initialization code */
473 if (!(pModule
->flags
& NE_FFLAGS_SINGLEDATA
))
475 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
|| pModule
->dgroup
)
478 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
481 else /* DATA NONE DLL */
487 else /* DATA SINGLE DLL */
489 ds_reg
= pSegTable
[pModule
->dgroup
-1].selector
;
490 cx_reg
= pModule
->heap_size
;
493 cs_reg
= pSegTable
[pModule
->cs
-1].selector
;
494 ip_reg
= pModule
->ip
;
495 di_reg
= ds_reg
? ds_reg
: hModule
;
496 bp_reg
= IF1632_Saved16_sp
+ ((WORD
)&((STACK16FRAME
*)1)->bp
- 1);
498 pModule
->cs
= 0; /* Don't initialize it twice */
499 dprintf_dll( stddeb
, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
500 cs_reg
, ip_reg
, ds_reg
, di_reg
, cx_reg
);
501 return CallTo16_regs_( (FARPROC16
)(cs_reg
<< 16 | ip_reg
), ds_reg
,
502 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
503 cx_reg
, 0 /*dx*/, 0 /*si*/, di_reg
);
505 fprintf( stderr
,"JBP: Ignoring call to LibMain\n" );
511 /***********************************************************************
514 * Initialize the loaded DLLs.
516 void NE_InitializeDLLs( HMODULE16 hModule
)
521 if (!(pModule
= MODULE_GetPtr( hModule
))) return;
522 if (pModule
->flags
& NE_FFLAGS_WIN32
)
524 PE_InitializeDLLs(hModule
);
527 if (pModule
->dlls_to_init
)
529 HANDLE to_init
= pModule
->dlls_to_init
;
530 pModule
->dlls_to_init
= 0;
531 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
533 NE_InitializeDLLs( *pDLL
);
536 GlobalFree16( to_init
);
538 NE_InitDLL( hModule
);
542 /***********************************************************************
545 * Needed for self-loading modules.
548 /* It does nothing */
549 void PatchCodeHandle(HANDLE hSel
)