5 * Copyright 1993 Robert J. Amstadt
6 * Copyright 1995 Alexandre Julliard
11 #include <sys/types.h>
21 #include "selectors.h"
25 #include "stackframe.h"
31 /***********************************************************************
34 BOOL
NE_LoadSegment( HMODULE16 hModule
, WORD segnum
)
37 SEGTABLEENTRY
*pSegTable
, *pSeg
;
39 WORD count
, i
, offset
;
43 struct relocation_entry_s
*rep
, *reloc_entries
;
49 int ordinal
, additive
;
52 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
53 pSegTable
= NE_SEG_TABLE( pModule
);
54 pSeg
= pSegTable
+ segnum
- 1;
55 pModuleTable
= NE_MODULE_TABLE( pModule
);
57 if (!pSeg
->filepos
) return TRUE
; /* No file image, just return */
59 fd
= MODULE_OpenFile( hModule
);
60 dprintf_module( stddeb
, "Loading segment %d, selector=%04x\n",
61 segnum
, pSeg
->selector
);
62 lseek( fd
, pSeg
->filepos
<< pModule
->alignment
, SEEK_SET
);
63 size
= pSeg
->size
? pSeg
->size
: 0x10000;
64 mem
= GlobalLock16(pSeg
->selector
);
65 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
&& segnum
> 1) {
67 /* Implement self loading segments */
68 SELFLOADHEADER
*selfloadheader
;
69 STACK16FRAME
*stack16Top
;
70 WORD oldss
, oldsp
, oldselector
, newselector
;
71 HFILE hf
= FILE_DupUnixHandle( fd
);
73 selfloadheader
= (SELFLOADHEADER
*)
74 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
,0);
75 oldss
= IF1632_Saved16_ss
;
76 oldsp
= IF1632_Saved16_sp
;
77 oldselector
= pSeg
->selector
;
78 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
79 IF1632_Saved16_sp
= 0xFF00 - sizeof(*stack16Top
);
80 stack16Top
= CURRENT_STACK16
;
81 stack16Top
->saved_ss
= 0;
82 stack16Top
->saved_sp
= 0;
83 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
84 stack16Top
->entry_point
= 0;
85 stack16Top
->entry_ip
= 0;
86 stack16Top
->entry_cs
= 0;
90 newselector
= CallTo16_word_www( selfloadheader
->LoadAppSeg
,
91 hModule
, hf
, segnum
);
93 if (newselector
!= oldselector
) {
94 /* Self loaders like creating their own selectors;
95 * they love asking for trouble to Wine developers
97 if (segnum
== pModule
->dgroup
) {
98 memcpy(PTR_SEG_OFF_TO_LIN(oldselector
,0),
99 PTR_SEG_OFF_TO_LIN(newselector
,0),
100 pSeg
->minsize
? pSeg
->minsize
: 0x10000);
101 FreeSelector(newselector
);
102 pSeg
->selector
= oldselector
;
103 fprintf(stderr
, "A new selector was allocated for the dgroup segment\n"
104 "Old selector is %d, new one is %d", oldselector
, newselector
);
106 FreeSelector(pSeg
->selector
);
107 pSeg
->selector
= newselector
;
111 IF1632_Saved16_ss
= oldss
;
112 IF1632_Saved16_sp
= oldsp
;
114 fprintf(stderr
,"JBP: Ignoring self loading segments in NE_LoadSegment.\n");
117 else if (!(pSeg
->flags
& NE_SEGFLAGS_ITERATED
))
121 The following bit of code for "iterated segments" was written without
122 any documentation on the format of these segments. It seems to work,
123 but may be missing something. If you have any doco please either send
124 it to me or fix the code yourself. gfm@werple.mira.net.au
126 char* buff
= xmalloc(size
);
128 read(fd
, buff
, size
);
129 while(curr
< buff
+ size
) {
130 unsigned int rept
= *((short*) curr
)++;
131 unsigned int len
= *((short*) curr
)++;
132 for(; rept
> 0; rept
--) {
135 for(byte
= 0; byte
< len
; byte
++)
143 pSeg
->flags
|= NE_SEGFLAGS_LOADED
;
144 if (!(pSeg
->flags
& NE_SEGFLAGS_RELOC_DATA
))
145 return TRUE
; /* No relocation data, we are done */
147 read( fd
, &count
, sizeof(count
) );
148 if (!count
) return TRUE
;
150 dprintf_fixup( stddeb
, "Fixups for %*.*s, segment %d, selector %04x\n",
151 *((BYTE
*)pModule
+ pModule
->name_table
),
152 *((BYTE
*)pModule
+ pModule
->name_table
),
153 (char *)pModule
+ pModule
->name_table
+ 1,
154 segnum
, pSeg
->selector
);
156 reloc_entries
= (struct relocation_entry_s
*)xmalloc(count
* sizeof(struct relocation_entry_s
));
157 if (read( fd
, reloc_entries
, count
* sizeof(struct relocation_entry_s
)) !=
158 count
* sizeof(struct relocation_entry_s
))
160 dprintf_fixup( stddeb
, "Unable to read relocation information\n" );
165 * Go through the relocation table on entry at a time.
168 for (i
= 0; i
< count
; i
++, rep
++)
171 * Get the target address corresponding to this entry.
174 /* If additive, there is no target chain list. Instead, add source
176 additive
= rep
->relocation_type
& NE_RELFLAG_ADDITIVE
;
177 rep
->relocation_type
&= 0x3;
179 switch (rep
->relocation_type
)
181 case NE_RELTYPE_ORDINAL
:
182 module
= pModuleTable
[rep
->target1
-1];
183 ordinal
= rep
->target2
;
184 address
= MODULE_GetEntryPoint( module
, ordinal
);
187 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
189 fprintf( stderr
, "Module not found: %04x, reference %d of module %*.*s\n",
190 module
, rep
->target1
,
191 *((BYTE
*)pModule
+ pModule
->name_table
),
192 *((BYTE
*)pModule
+ pModule
->name_table
),
193 (char *)pModule
+ pModule
->name_table
+ 1 );
195 fprintf( stderr
, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
196 *((BYTE
*)pTarget
+ pTarget
->name_table
),
197 *((BYTE
*)pTarget
+ pTarget
->name_table
),
198 (char *)pTarget
+ pTarget
->name_table
+ 1,
203 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
204 fprintf( stddeb
,"%d: %*.*s.%d=%04x:%04x\n", i
+ 1,
205 *((BYTE
*)pTarget
+ pTarget
->name_table
),
206 *((BYTE
*)pTarget
+ pTarget
->name_table
),
207 (char *)pTarget
+ pTarget
->name_table
+ 1,
208 ordinal
, HIWORD(address
), LOWORD(address
) );
212 case NE_RELTYPE_NAME
:
213 module
= pModuleTable
[rep
->target1
-1];
214 func_name
= (char *)pModule
+ pModule
->import_table
+ rep
->target2
;
215 memcpy( buffer
, func_name
+1, *func_name
);
216 buffer
[*func_name
] = '\0';
218 ordinal
= MODULE_GetOrdinal( module
, func_name
);
220 address
= MODULE_GetEntryPoint( module
, ordinal
);
224 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
225 fprintf( stderr
, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
226 *((BYTE
*)pTarget
+ pTarget
->name_table
),
227 *((BYTE
*)pTarget
+ pTarget
->name_table
),
228 (char *)pTarget
+ pTarget
->name_table
+ 1, func_name
);
232 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
233 fprintf( stddeb
,"%d: %*.*s.%s=%04x:%04x\n", i
+ 1,
234 *((BYTE
*)pTarget
+ pTarget
->name_table
),
235 *((BYTE
*)pTarget
+ pTarget
->name_table
),
236 (char *)pTarget
+ pTarget
->name_table
+ 1,
237 func_name
, HIWORD(address
), LOWORD(address
) );
241 case NE_RELTYPE_INTERNAL
:
242 if (rep
->target1
== 0x00ff)
244 address
= MODULE_GetEntryPoint( hModule
, rep
->target2
);
248 address
= (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( pSegTable
[rep
->target1
-1].selector
, rep
->target2
);
251 dprintf_fixup(stddeb
,"%d: %04x:%04x\n",
252 i
+ 1, HIWORD(address
), LOWORD(address
) );
255 case NE_RELTYPE_OSFIXUP
:
256 /* Relocation type 7:
258 * These appear to be used as fixups for the Windows
259 * floating point emulator. Let's just ignore them and
260 * try to use the hardware floating point. Linux should
261 * successfully emulate the coprocessor if it doesn't
264 dprintf_fixup(stddeb
,
265 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
266 i
+ 1, rep
->address_type
, rep
->relocation_type
,
268 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
269 rep
->target1
, rep
->target2
);
273 dprintf_fixup(stddeb
,
274 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
275 i
+ 1, rep
->address_type
, rep
->relocation_type
,
277 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
278 rep
->target1
, rep
->target2
);
283 offset
= rep
->offset
;
285 switch (rep
->address_type
)
287 case NE_RADDR_LOWBYTE
:
289 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
290 dprintf_fixup(stddeb
," %04x:%04x:%04x BYTE%s\n",
291 pSeg
->selector
, offset
, *sp
, additive
? " additive":"");
294 *(unsigned char*)sp
= (unsigned char)(((int)address
+offset
) & 0xFF);
296 *(unsigned char*)sp
= (unsigned char)((int)address
& 0xFF);
298 while (offset
!= 0xffff && !additive
);
301 case NE_RADDR_OFFSET16
:
303 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
304 dprintf_fixup(stddeb
," %04x:%04x:%04x OFFSET16%s\n",
305 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
307 *sp
= LOWORD(address
);
308 if (additive
) *sp
+= offset
;
310 while (offset
!= 0xffff && !additive
);
313 case NE_RADDR_POINTER32
:
315 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
316 dprintf_fixup(stddeb
," %04x:%04x:%04x POINTER32%s\n",
317 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
319 *sp
= LOWORD(address
);
320 if (additive
) *sp
+= offset
;
321 *(sp
+1) = HIWORD(address
);
323 while (offset
!= 0xffff && !additive
);
326 case NE_RADDR_SELECTOR
:
328 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
329 dprintf_fixup(stddeb
," %04x:%04x:%04x SELECTOR%s\n",
330 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
332 *sp
= HIWORD(address
);
333 /* Borland creates additive records with offset zero. Strange, but OK */
334 if(additive
&& offset
)
335 fprintf(stderr
,"Additive selector to %4.4x.Please report\n",offset
);
337 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
338 while (offset
&& offset
!= 0xffff && !additive
);
342 dprintf_fixup(stddeb
,
343 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
344 i
+ 1, rep
->address_type
, rep
->relocation_type
,
346 dprintf_fixup(stddeb
,
347 "TARGET %04x %04x\n", rep
->target1
, rep
->target2
);
358 /***********************************************************************
361 * Fixup the exported functions prologs.
363 void NE_FixupPrologs( NE_MODULE
*pModule
)
366 fprintf(stderr
,"NE_FixupPrologs should not be called for libwine\n");
368 SEGTABLEENTRY
*pSegTable
;
371 BYTE
*p
, *fixup_ptr
, count
;
373 pSegTable
= NE_SEG_TABLE(pModule
);
374 if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
375 dgroup
= pSegTable
[pModule
->dgroup
-1].selector
;
377 dprintf_module( stddeb
, "MODULE_FixupPrologs(%04x)\n", pModule
->self
);
378 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
381 if (p
[1] == 0) /* Unused entry */
383 p
+= 2; /* Skip it */
386 if (p
[1] == 0xfe) /* Constant entry */
388 p
+= 2 + *p
* 3; /* Skip it */
392 /* Now fixup the entries of this bundle */
398 dprintf_module( stddeb
,"Flags: %04x, sel %02x ", *p
, sel
);
399 /* According to the output generated by TDUMP, the flags mean:
400 * 0x0001 function is exported
401 * 0x0002 Single data (seems to occur only in DLLs)
403 if (sel
== 0xff) { /* moveable */
404 dprintf_module( stddeb
, "(%02x) o %04x ", p
[3], *(WORD
*)(p
+4) );
405 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[p
[3]-1].selector
) + *(WORD
*)(p
+ 4);
407 dprintf_module( stddeb
, "offset %04x ", *(WORD
*)(p
+1) );
408 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[sel
-1].selector
) + *(WORD
*)(p
+ 1);
410 dprintf_module( stddeb
, "Signature: %02x %02x %02x,ff %x\n",
411 fixup_ptr
[0], fixup_ptr
[1], fixup_ptr
[2],
415 /* Verify the signature */
416 if (((fixup_ptr
[0] == 0x1e && fixup_ptr
[1] == 0x58)
417 || (fixup_ptr
[0] == 0x8c && fixup_ptr
[1] == 0xd8))
418 && fixup_ptr
[2] == 0x90)
422 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
423 /* can this happen? */
424 fprintf( stderr
, "FixupPrologs got confused\n" );
426 *fixup_ptr
= 0xb8; /* MOV AX, */
427 *(WORD
*)(fixup_ptr
+1) = dgroup
;
431 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
432 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
438 dprintf_fixup( stddeb
, "Unknown signature\n" );
442 dprintf_module( stddeb
,"\n");
443 p
+= (sel
== 0xff) ? 6 : 3;
450 /***********************************************************************
453 * Call the DLL initialization code
455 static BOOL
NE_InitDLL( HMODULE16 hModule
)
458 int cs_reg
, ds_reg
, ip_reg
, cx_reg
, di_reg
, bp_reg
;
460 SEGTABLEENTRY
*pSegTable
;
462 /* Registers at initialization must be:
464 * di library instance
465 * ds data segment if any
466 * es:si command line (always 0)
469 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
470 pSegTable
= NE_SEG_TABLE( pModule
);
472 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) ||
473 (pModule
->flags
& NE_FFLAGS_WIN32
)) return TRUE
; /*not a library*/
474 if (!pModule
->cs
) return TRUE
; /* no initialization code */
476 if (!(pModule
->flags
& NE_FFLAGS_SINGLEDATA
))
478 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
|| pModule
->dgroup
)
481 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
484 else /* DATA NONE DLL */
490 else /* DATA SINGLE DLL */
492 ds_reg
= pSegTable
[pModule
->dgroup
-1].selector
;
493 cx_reg
= pModule
->heap_size
;
496 cs_reg
= pSegTable
[pModule
->cs
-1].selector
;
497 ip_reg
= pModule
->ip
;
498 di_reg
= ds_reg
? ds_reg
: hModule
;
499 bp_reg
= IF1632_Saved16_sp
+ ((WORD
)&((STACK16FRAME
*)1)->bp
- 1);
501 pModule
->cs
= 0; /* Don't initialize it twice */
502 dprintf_dll( stddeb
, "Calling LibMain, cs:ip=%04x:%04x ds=%04x di=%04x cx=%04x\n",
503 cs_reg
, ip_reg
, ds_reg
, di_reg
, cx_reg
);
504 return CallTo16_regs_( (FARPROC16
)(cs_reg
<< 16 | ip_reg
), ds_reg
,
505 0 /*es*/, 0 /*bp*/, 0 /*ax*/, 0 /*bx*/,
506 cx_reg
, 0 /*dx*/, 0 /*si*/, di_reg
);
508 fprintf( stderr
,"JBP: Ignoring call to LibMain\n" );
514 /***********************************************************************
517 * Initialize the loaded DLLs.
519 void NE_InitializeDLLs( HMODULE16 hModule
)
524 if (!(pModule
= MODULE_GetPtr( hModule
))) return;
525 if (pModule
->flags
& NE_FFLAGS_WIN32
)
527 /* PE_InitializeDLLs(hModule); */
530 if (pModule
->dlls_to_init
)
532 HGLOBAL16 to_init
= pModule
->dlls_to_init
;
533 pModule
->dlls_to_init
= 0;
534 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
536 NE_InitializeDLLs( *pDLL
);
539 GlobalFree16( to_init
);
541 NE_InitDLL( hModule
);
545 /***********************************************************************
548 * Needed for self-loading modules.
551 /* It does nothing */
552 void PatchCodeHandle(HANDLE16 hSel
)