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
, offset
;
41 struct relocation_entry_s
*rep
, *reloc_entries
;
47 int ordinal
, additive
;
50 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return FALSE
;
51 pSegTable
= NE_SEG_TABLE( pModule
);
52 pSeg
= pSegTable
+ segnum
- 1;
53 pModuleTable
= NE_MODULE_TABLE( pModule
);
55 if (!pSeg
->filepos
) return TRUE
; /* No file image, just return */
57 fd
= MODULE_OpenFile( hModule
);
58 dprintf_module( stddeb
, "Loading segment %d, selector="NPFMT
"\n",
59 segnum
, pSeg
->selector
);
60 lseek( fd
, pSeg
->filepos
<< pModule
->alignment
, SEEK_SET
);
61 size
= pSeg
->size
? pSeg
->size
: 0x10000;
62 mem
= GlobalLock(pSeg
->selector
);
63 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
&& segnum
> 1) {
65 /* Implement self loading segments */
66 SELFLOADHEADER
*selfloadheader
;
67 WORD oldss
, oldsp
, oldselector
, newselector
;
68 selfloadheader
= (SELFLOADHEADER
*)
69 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
,0);
70 oldss
= IF1632_Saved16_ss
;
71 oldsp
= IF1632_Saved16_sp
;
72 oldselector
= pSeg
->selector
;
73 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
74 IF1632_Saved16_sp
= 0xFF00;
75 newselector
= CallTo16_word_www(selfloadheader
->LoadAppSeg
,
76 pModule
->self_loading_sel
, hModule
, fd
, segnum
);
77 if (newselector
!= oldselector
) {
78 /* Self loaders like creating their own selectors;
79 * they love asking for trouble to Wine developers
81 if (segnum
== pModule
->dgroup
) {
82 memcpy(PTR_SEG_OFF_TO_LIN(oldselector
,0),
83 PTR_SEG_OFF_TO_LIN(newselector
,0),
84 pSeg
->minsize
? pSeg
->minsize
: 0x10000);
85 FreeSelector(newselector
);
86 pSeg
->selector
= oldselector
;
87 fprintf(stderr
, "A new selector was allocated for the dgroup segment\n"
88 "Old selector is %d, new one is %d", oldselector
, newselector
);
90 FreeSelector(pSeg
->selector
);
91 pSeg
->selector
= newselector
;
95 IF1632_Saved16_ss
= oldss
;
96 IF1632_Saved16_sp
= oldsp
;
98 fprintf(stderr
,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
101 else if (!(pSeg
->flags
& NE_SEGFLAGS_ITERATED
))
105 The following bit of code for "iterated segments" was written without
106 any documentation on the format of these segments. It seems to work,
107 but may be missing something. If you have any doco please either send
108 it to me or fix the code yourself. gfm@werple.mira.net.au
110 char* buff
= malloc(size
);
112 read(fd
, buff
, size
);
113 while(curr
< buff
+ size
) {
114 unsigned int rept
= *((short*) curr
)++;
115 unsigned int len
= *((short*) curr
)++;
116 for(; rept
> 0; rept
--) {
119 for(byte
= 0; byte
< len
; byte
++)
127 pSeg
->flags
|= NE_SEGFLAGS_LOADED
;
128 if (!(pSeg
->flags
& NE_SEGFLAGS_RELOC_DATA
))
129 return TRUE
; /* No relocation data, we are done */
131 read( fd
, &count
, sizeof(count
) );
132 if (!count
) return TRUE
;
134 dprintf_fixup( stddeb
, "Fixups for %*.*s, segment %d, selector "NPFMT
"\n",
135 *((BYTE
*)pModule
+ pModule
->name_table
),
136 *((BYTE
*)pModule
+ pModule
->name_table
),
137 (char *)pModule
+ pModule
->name_table
+ 1,
138 segnum
, pSeg
->selector
);
140 reloc_entries
= (struct relocation_entry_s
*)malloc(count
* sizeof(struct relocation_entry_s
));
141 if (read( fd
, reloc_entries
, count
* sizeof(struct relocation_entry_s
)) !=
142 count
* sizeof(struct relocation_entry_s
))
144 dprintf_fixup( stddeb
, "Unable to read relocation information\n" );
149 * Go through the relocation table on entry at a time.
152 for (i
= 0; i
< count
; i
++, rep
++)
155 * Get the target address corresponding to this entry.
158 /* If additive, there is no target chain list. Instead, add source
160 additive
= rep
->relocation_type
& NE_RELFLAG_ADDITIVE
;
161 rep
->relocation_type
&= 0x3;
163 switch (rep
->relocation_type
)
165 case NE_RELTYPE_ORDINAL
:
166 module
= pModuleTable
[rep
->target1
-1];
167 ordinal
= rep
->target2
;
168 address
= MODULE_GetEntryPoint( module
, ordinal
);
171 NE_MODULE
*pTarget
= (NE_MODULE
*)GlobalLock( module
);
173 fprintf( stderr
, "Module not found: "NPFMT
", reference %d of module %*.*s\n",
174 module
, rep
->target1
,
175 *((BYTE
*)pModule
+ pModule
->name_table
),
176 *((BYTE
*)pModule
+ pModule
->name_table
),
177 (char *)pModule
+ pModule
->name_table
+ 1 );
179 fprintf( stderr
, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
180 *((BYTE
*)pTarget
+ pTarget
->name_table
),
181 *((BYTE
*)pTarget
+ pTarget
->name_table
),
182 (char *)pTarget
+ pTarget
->name_table
+ 1,
187 NE_MODULE
*pTarget
= (NE_MODULE
*)GlobalLock( module
);
188 fprintf( stddeb
,"%d: %*.*s.%d=%04x:%04x\n", i
+ 1,
189 *((BYTE
*)pTarget
+ pTarget
->name_table
),
190 *((BYTE
*)pTarget
+ pTarget
->name_table
),
191 (char *)pTarget
+ pTarget
->name_table
+ 1,
192 ordinal
, HIWORD(address
), LOWORD(address
) );
196 case NE_RELTYPE_NAME
:
197 module
= pModuleTable
[rep
->target1
-1];
198 func_name
= (char *)pModule
+ pModule
->import_table
+ rep
->target2
;
199 memcpy( buffer
, func_name
+1, *func_name
);
200 buffer
[*func_name
] = '\0';
202 ordinal
= MODULE_GetOrdinal( module
, func_name
);
204 address
= MODULE_GetEntryPoint( module
, ordinal
);
208 NE_MODULE
*pTarget
= (NE_MODULE
*)GlobalLock( module
);
209 fprintf( stderr
, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
210 *((BYTE
*)pTarget
+ pTarget
->name_table
),
211 *((BYTE
*)pTarget
+ pTarget
->name_table
),
212 (char *)pTarget
+ pTarget
->name_table
+ 1, func_name
);
216 NE_MODULE
*pTarget
= (NE_MODULE
*)GlobalLock( module
);
217 fprintf( stddeb
,"%d: %*.*s.%s=%04x:%04x\n", i
+ 1,
218 *((BYTE
*)pTarget
+ pTarget
->name_table
),
219 *((BYTE
*)pTarget
+ pTarget
->name_table
),
220 (char *)pTarget
+ pTarget
->name_table
+ 1,
221 func_name
, HIWORD(address
), LOWORD(address
) );
225 case NE_RELTYPE_INTERNAL
:
226 if (rep
->target1
== 0x00ff)
228 address
= MODULE_GetEntryPoint( hModule
, rep
->target2
);
232 address
= MAKELONG( rep
->target2
, pSegTable
[rep
->target1
-1].selector
);
235 dprintf_fixup(stddeb
,"%d: %04x:%04x\n",
236 i
+ 1, HIWORD(address
), LOWORD(address
) );
239 case NE_RELTYPE_OSFIXUP
:
240 /* Relocation type 7:
242 * These appear to be used as fixups for the Windows
243 * floating point emulator. Let's just ignore them and
244 * try to use the hardware floating point. Linux should
245 * successfully emulate the coprocessor if it doesn't
248 dprintf_fixup(stddeb
,
249 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
250 i
+ 1, rep
->address_type
, rep
->relocation_type
,
252 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
253 rep
->target1
, rep
->target2
);
257 dprintf_fixup(stddeb
,
258 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
259 i
+ 1, rep
->address_type
, rep
->relocation_type
,
261 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
262 rep
->target1
, rep
->target2
);
267 offset
= rep
->offset
;
269 switch (rep
->address_type
)
271 case NE_RADDR_LOWBYTE
:
273 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
274 dprintf_fixup(stddeb
," "NPFMT
":%04x:%04x BYTE%s\n",
275 pSeg
->selector
, offset
, *sp
, additive
? " additive":"");
278 *(unsigned char*)sp
= (unsigned char)((address
+offset
) & 0xFF);
280 *(unsigned char*)sp
= (unsigned char)(address
& 0xFF);
282 while (offset
!= 0xffff && !additive
);
285 case NE_RADDR_OFFSET16
:
287 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
288 dprintf_fixup(stddeb
," "NPFMT
":%04x:%04x OFFSET16%s\n",
289 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
291 *sp
= LOWORD(address
);
292 if (additive
) *sp
+= offset
;
294 while (offset
!= 0xffff && !additive
);
297 case NE_RADDR_POINTER32
:
299 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
300 dprintf_fixup(stddeb
," "NPFMT
":%04x:%04x POINTER32%s\n",
301 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
303 *sp
= LOWORD(address
);
304 if (additive
) *sp
+= offset
;
305 *(sp
+1) = HIWORD(address
);
307 while (offset
!= 0xffff && !additive
);
310 case NE_RADDR_SELECTOR
:
312 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
313 dprintf_fixup(stddeb
," "NPFMT
":%04x:%04x SELECTOR%s\n",
314 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
316 *sp
= HIWORD(address
);
317 /* Borland creates additive records with offset zero. Strange, but OK */
318 if(additive
&& offset
)
319 fprintf(stderr
,"Additive selector to %4.4x.Please report\n",offset
);
321 while (offset
!= 0xffff && !additive
);
325 dprintf_fixup(stddeb
,
326 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
327 i
+ 1, rep
->address_type
, rep
->relocation_type
,
329 dprintf_fixup(stddeb
,
330 "TARGET %04x %04x\n", rep
->target1
, rep
->target2
);
341 /***********************************************************************
344 * Fixup the exported functions prologs.
346 void NE_FixupPrologs( HMODULE hModule
)
349 fprintf(stderr
,"NE_FixupPrologs should not be called for libwine\n");
352 SEGTABLEENTRY
*pSegTable
;
355 BYTE
*p
, *fixup_ptr
, count
;
357 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
358 pSegTable
= NE_SEG_TABLE(pModule
);
359 if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
360 dgroup
= pSegTable
[pModule
->dgroup
-1].selector
;
362 dprintf_module( stddeb
, "MODULE_FixupPrologs(%04x)\n", hModule
);
363 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
366 if (p
[1] == 0) /* Unused entry */
368 p
+= 2; /* Skip it */
371 if (p
[1] == 0xfe) /* Constant entry */
373 p
+= 2 + *p
* 3; /* Skip it */
377 /* Now fixup the entries of this bundle */
383 dprintf_module( stddeb
,"Flags: %04x, sel %02x ", *p
, sel
);
384 /* According to the output generated by TDUMP, the flags mean:
385 * 0x0001 function is exported
386 * 0x0002 Single data (seems to occur only in DLLs)
388 if (sel
== 0xff) { /* moveable */
389 dprintf_module( stddeb
, "(%02x) o %04x ", p
[3], *(WORD
*)(p
+4) );
390 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[p
[3]-1].selector
) + *(WORD
*)(p
+ 4);
392 dprintf_module( stddeb
, "offset %04x ", *(WORD
*)(p
+1) );
393 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[sel
-1].selector
) + *(WORD
*)(p
+ 1);
395 dprintf_module( stddeb
, "Signature: %02x %02x %02x,ff %x\n",
396 fixup_ptr
[0], fixup_ptr
[1], fixup_ptr
[2],
400 /* Verify the signature */
401 if (((fixup_ptr
[0] == 0x1e && fixup_ptr
[1] == 0x58)
402 || (fixup_ptr
[0] == 0x8c && fixup_ptr
[1] == 0xd8))
403 && fixup_ptr
[2] == 0x90)
407 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
408 /* can this happen? */
409 fprintf( stderr
, "FixupPrologs got confused\n" );
411 *fixup_ptr
= 0xb8; /* MOV AX, */
412 *(WORD
*)(fixup_ptr
+1) = dgroup
;
416 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
417 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
423 dprintf_fixup( stddeb
, "Unknown signature\n" );
427 dprintf_module( stddeb
,"\n");
428 p
+= (sel
== 0xff) ? 6 : 3;
435 /***********************************************************************
438 * Call the DLL initialization code
440 static BOOL
NE_InitDLL( HMODULE hModule
)
443 int cs_reg
, ds_reg
, ip_reg
, cx_reg
, di_reg
, bp_reg
;
445 SEGTABLEENTRY
*pSegTable
;
447 /* Registers at initialization must be:
449 * di library instance
450 * ds data segment if any
451 * es:si command line (always 0)
454 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
455 pSegTable
= NE_SEG_TABLE( pModule
);
457 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
)) return TRUE
; /*not a library*/
458 if (!pModule
->cs
) return TRUE
; /* no initialization code */
460 if (!(pModule
->flags
& NE_FFLAGS_SINGLEDATA
))
462 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
|| pModule
->dgroup
)
465 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
468 else /* DATA NONE DLL */
474 else /* DATA SINGLE DLL */
476 ds_reg
= pSegTable
[pModule
->dgroup
-1].selector
;
477 cx_reg
= pModule
->heap_size
;
480 cs_reg
= pSegTable
[pModule
->cs
-1].selector
;
481 ip_reg
= pModule
->ip
;
482 di_reg
= ds_reg
? ds_reg
: hModule
;
483 bp_reg
= IF1632_Saved16_sp
+ ((WORD
)&((STACK16FRAME
*)1)->bp
- 1);
485 pModule
->cs
= 0; /* Don't initialize it twice */
486 dprintf_dll( stddeb
, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
487 cs_reg
, ip_reg
, ds_reg
, di_reg
, cx_reg
);
488 return CallTo16_regs_( (FARPROC
)(cs_reg
<< 16 | ip_reg
), ds_reg
,
489 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
490 cx_reg
, 0 /*dx*/, 0 /*si*/, di_reg
);
492 fprintf( stderr
,"JBP: Ignoring call to LibMain\n" );
498 /***********************************************************************
501 * Initialize the loaded DLLs.
503 void NE_InitializeDLLs( HMODULE hModule
)
508 pModule
= (NE_MODULE
*)GlobalLock( hModule
);
509 if (pModule
->dlls_to_init
)
511 HANDLE to_init
= pModule
->dlls_to_init
;
512 pModule
->dlls_to_init
= 0;
513 for (pDLL
= (HMODULE
*)GlobalLock( to_init
); *pDLL
; pDLL
++)
515 NE_InitializeDLLs( *pDLL
);
518 GlobalFree( to_init
);
520 NE_InitDLL( hModule
);
524 /***********************************************************************
527 * Needed for self-loading modules.
530 /* It does nothing */
531 void PatchCodeHandle(HANDLE hSel
)