4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
10 #include <sys/types.h>
21 #include "selectors.h"
24 #include "stackframe.h"
29 /***********************************************************************
32 BOOL
NE_LoadSegment( HMODULE hModule
, WORD segnum
)
35 SEGTABLEENTRY
*pSegTable
, *pSeg
;
37 WORD count
, i
, module
, offset
;
40 struct relocation_entry_s
*rep
, *reloc_entries
;
46 int ordinal
, additive
;
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
);
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
))
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
);
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
--) {
114 for(byte
= 0; byte
< len
; byte
++)
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" );
144 * Go through the relocation table on entry at a time.
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
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
);
166 NE_MODULE
*pTarget
= (NE_MODULE
*)GlobalLock( module
);
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 );
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,
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
) );
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';
197 ordinal
= MODULE_GetOrdinal( module
, func_name
);
199 address
= MODULE_GetEntryPoint( module
, ordinal
);
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
);
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
) );
220 case NE_RELTYPE_INTERNAL
:
221 if (rep
->target1
== 0x00ff)
223 address
= MODULE_GetEntryPoint( hModule
, rep
->target2
);
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
) );
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
243 dprintf_fixup(stddeb
,
244 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
245 i
+ 1, rep
->address_type
, rep
->relocation_type
,
247 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
248 rep
->target1
, rep
->target2
);
252 dprintf_fixup(stddeb
,
253 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
254 i
+ 1, rep
->address_type
, rep
->relocation_type
,
256 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
257 rep
->target1
, rep
->target2
);
262 offset
= rep
->offset
;
264 switch (rep
->address_type
)
266 case NE_RADDR_LOWBYTE
:
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":"");
273 *(unsigned char*)sp
= (unsigned char)((address
+offset
) & 0xFF);
275 *(unsigned char*)sp
= (unsigned char)(address
& 0xFF);
277 while (offset
!= 0xffff && !additive
);
280 case NE_RADDR_OFFSET16
:
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" : "" );
286 *sp
= LOWORD(address
);
287 if (additive
) *sp
+= offset
;
289 while (offset
!= 0xffff && !additive
);
292 case NE_RADDR_POINTER32
:
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" : "" );
298 *sp
= LOWORD(address
);
299 if (additive
) *sp
+= offset
;
300 *(sp
+1) = HIWORD(address
);
302 while (offset
!= 0xffff && !additive
);
305 case NE_RADDR_SELECTOR
:
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" : "" );
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
);
320 dprintf_fixup(stddeb
,
321 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
322 i
+ 1, rep
->address_type
, rep
->relocation_type
,
324 dprintf_fixup(stddeb
,
325 "TARGET %04x %04x\n", rep
->target1
, rep
->target2
);
336 /***********************************************************************
339 * Fixup the exported functions prologs.
341 void NE_FixupPrologs( HMODULE hModule
)
344 fprintf(stderr
,"NE_FixupPrologs should not be called for libwine\n");
347 SEGTABLEENTRY
*pSegTable
;
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
;
361 if (p
[1] == 0) /* Unused entry */
363 p
+= 2; /* Skip it */
366 if (p
[1] == 0xfe) /* Constant entry */
368 p
+= 2 + *p
* 3; /* Skip it */
372 /* Now fixup the entries of this bundle */
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);
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],
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)
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
;
411 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
412 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
418 dprintf_fixup( stddeb
, "Unknown signature\n" );
422 dprintf_module( stddeb
,"\n");
423 p
+= (sel
== 0xff) ? 6 : 3;
430 /***********************************************************************
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
;
439 SEGTABLEENTRY
*pSegTable
;
441 /* Registers at initialization must be:
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
)
459 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
462 else /* DATA NONE DLL */
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 /***********************************************************************
491 * Initialize the loaded DLLs.
493 void NE_InitializeDLLs( HMODULE hModule
)
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
);
508 GlobalFree( to_init
);
510 NE_InitDLL( hModule
);
514 /***********************************************************************
517 * Needed for self-loading modules.
520 /* It does nothing */
521 void PatchCodeHandle(HANDLE hSel
)