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 BOOL32
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 if (pSeg
->size
) size
= pSeg
->size
;
64 else if (pSeg
->minsize
) size
= pSeg
->minsize
;
66 mem
= GlobalLock16(pSeg
->selector
);
67 if (pModule
->flags
& NE_FFLAGS_SELFLOAD
&& segnum
> 1)
69 /* Implement self loading segments */
70 SELFLOADHEADER
*selfloadheader
;
71 STACK16FRAME
*stack16Top
;
72 WORD oldss
, oldsp
, oldselector
, newselector
;
73 HFILE32 hf
= FILE_DupUnixHandle( fd
);
75 selfloadheader
= (SELFLOADHEADER
*)
76 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
,0);
77 oldss
= IF1632_Saved16_ss
;
78 oldsp
= IF1632_Saved16_sp
;
79 oldselector
= pSeg
->selector
;
80 IF1632_Saved16_ss
= pModule
->self_loading_sel
;
81 IF1632_Saved16_sp
= 0xFF00 - sizeof(*stack16Top
);
82 stack16Top
= CURRENT_STACK16
;
83 stack16Top
->saved_ss
= 0;
84 stack16Top
->saved_sp
= 0;
85 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
86 stack16Top
->entry_point
= 0;
87 stack16Top
->entry_ip
= 0;
88 stack16Top
->entry_cs
= 0;
92 newselector
= CallTo16_word_www( selfloadheader
->LoadAppSeg
,
93 hModule
, hf
, segnum
);
95 if (newselector
!= oldselector
) {
96 /* Self loaders like creating their own selectors;
97 * they love asking for trouble to Wine developers
99 if (segnum
== pModule
->dgroup
) {
100 memcpy(PTR_SEG_OFF_TO_LIN(oldselector
,0),
101 PTR_SEG_OFF_TO_LIN(newselector
,0),
102 pSeg
->minsize
? pSeg
->minsize
: 0x10000);
103 FreeSelector(newselector
);
104 pSeg
->selector
= oldselector
;
105 fprintf(stderr
, "A new selector was allocated for the dgroup segment\n"
106 "Old selector is %d, new one is %d", oldselector
, newselector
);
108 FreeSelector(pSeg
->selector
);
109 pSeg
->selector
= newselector
;
113 IF1632_Saved16_ss
= oldss
;
114 IF1632_Saved16_sp
= oldsp
;
116 else if (!(pSeg
->flags
& NE_SEGFLAGS_ITERATED
))
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
125 char* buff
= xmalloc(size
);
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
--) {
134 for(byte
= 0; byte
< len
; byte
++)
142 pSeg
->flags
|= NE_SEGFLAGS_LOADED
;
143 if (!(pSeg
->flags
& NE_SEGFLAGS_RELOC_DATA
))
144 return TRUE
; /* No relocation data, we are done */
146 read( fd
, &count
, sizeof(count
) );
147 if (!count
) return TRUE
;
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
);
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
))
159 dprintf_fixup( stddeb
, "Unable to read relocation information\n" );
164 * Go through the relocation table on entry at a time.
167 for (i
= 0; i
< count
; i
++, rep
++)
170 * Get the target address corresponding to this entry.
173 /* If additive, there is no target chain list. Instead, add source
175 additive
= rep
->relocation_type
& NE_RELFLAG_ADDITIVE
;
176 rep
->relocation_type
&= 0x3;
178 switch (rep
->relocation_type
)
180 case NE_RELTYPE_ORDINAL
:
181 module
= pModuleTable
[rep
->target1
-1];
182 ordinal
= rep
->target2
;
183 address
= MODULE_GetEntryPoint( module
, ordinal
);
186 NE_MODULE
*pTarget
= MODULE_GetPtr( module
);
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 );
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,
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
) );
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';
217 ordinal
= MODULE_GetOrdinal( module
, func_name
);
219 address
= MODULE_GetEntryPoint( module
, ordinal
);
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
);
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
) );
240 case NE_RELTYPE_INTERNAL
:
241 if ((rep
->target1
& 0xff) == 0xff)
243 address
= MODULE_GetEntryPoint( hModule
, rep
->target2
);
247 address
= (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( pSegTable
[rep
->target1
-1].selector
, rep
->target2
);
250 dprintf_fixup(stddeb
,"%d: %04x:%04x\n",
251 i
+ 1, HIWORD(address
), LOWORD(address
) );
254 case NE_RELTYPE_OSFIXUP
:
255 /* Relocation type 7:
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
263 dprintf_fixup(stddeb
,
264 "%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
265 i
+ 1, rep
->address_type
, rep
->relocation_type
,
267 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
268 rep
->target1
, rep
->target2
);
272 dprintf_fixup(stddeb
,
273 "WARNING: %d: ADDR TYPE %d, unknown TYPE %d, OFFSET %04x, ",
274 i
+ 1, rep
->address_type
, rep
->relocation_type
,
276 dprintf_fixup(stddeb
,"TARGET %04x %04x\n",
277 rep
->target1
, rep
->target2
);
282 offset
= rep
->offset
;
284 /* Apparently, high bit of address_type is sometimes set; */
285 /* we ignore it for now */
286 if (rep
->address_type
> NE_RADDR_OFFSET32
)
287 fprintf( stderr
, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
288 MODULE_GetModuleName(hModule
), rep
->address_type
);
290 switch (rep
->address_type
& 0x7f)
292 case NE_RADDR_LOWBYTE
:
294 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
295 dprintf_fixup(stddeb
," %04x:%04x:%04x BYTE%s\n",
296 pSeg
->selector
, offset
, *sp
, additive
? " additive":"");
299 *(unsigned char*)sp
= (unsigned char)(((int)address
+offset
) & 0xFF);
301 *(unsigned char*)sp
= (unsigned char)((int)address
& 0xFF);
303 while (offset
!= 0xffff && !additive
);
306 case NE_RADDR_OFFSET16
:
308 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
309 dprintf_fixup(stddeb
," %04x:%04x:%04x OFFSET16%s\n",
310 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
312 *sp
= LOWORD(address
);
313 if (additive
) *sp
+= offset
;
315 while (offset
!= 0xffff && !additive
);
318 case NE_RADDR_POINTER32
:
320 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
321 dprintf_fixup(stddeb
," %04x:%04x:%04x POINTER32%s\n",
322 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
324 *sp
= LOWORD(address
);
325 if (additive
) *sp
+= offset
;
326 *(sp
+1) = HIWORD(address
);
328 while (offset
!= 0xffff && !additive
);
331 case NE_RADDR_SELECTOR
:
333 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
334 dprintf_fixup(stddeb
," %04x:%04x:%04x SELECTOR%s\n",
335 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
337 *sp
= HIWORD(address
);
338 /* Borland creates additive records with offset zero. Strange, but OK */
339 if(additive
&& offset
)
340 fprintf(stderr
,"Additive selector to %4.4x.Please report\n",offset
);
342 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
343 while (offset
&& offset
!= 0xffff && !additive
);
347 dprintf_fixup(stddeb
,
348 "WARNING: %d: unknown ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
349 i
+ 1, rep
->address_type
, rep
->relocation_type
,
351 dprintf_fixup(stddeb
,
352 "TARGET %04x %04x\n", rep
->target1
, rep
->target2
);
363 /***********************************************************************
366 * Fixup the exported functions prologs.
368 void NE_FixupPrologs( NE_MODULE
*pModule
)
370 SEGTABLEENTRY
*pSegTable
;
373 BYTE
*p
, *fixup_ptr
, count
;
375 pSegTable
= NE_SEG_TABLE(pModule
);
376 if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
377 dgroup
= pSegTable
[pModule
->dgroup
-1].selector
;
379 dprintf_module( stddeb
, "MODULE_FixupPrologs(%04x)\n", pModule
->self
);
380 p
= (BYTE
*)pModule
+ pModule
->entry_table
;
383 if (p
[1] == 0) /* Unused entry */
385 p
+= 2; /* Skip it */
388 if (p
[1] == 0xfe) /* Constant entry */
390 p
+= 2 + *p
* 3; /* Skip it */
394 /* Now fixup the entries of this bundle */
400 dprintf_module( stddeb
,"Flags: %04x, sel %02x ", *p
, sel
);
401 /* According to the output generated by TDUMP, the flags mean:
402 * 0x0001 function is exported
403 * 0x0002 Single data (seems to occur only in DLLs)
405 if (sel
== 0xff) { /* moveable */
406 dprintf_module( stddeb
, "(%02x) o %04x ", p
[3], *(WORD
*)(p
+4) );
407 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[p
[3]-1].selector
) + *(WORD
*)(p
+ 4);
409 dprintf_module( stddeb
, "offset %04x ", *(WORD
*)(p
+1) );
410 fixup_ptr
= (char *)GET_SEL_BASE(pSegTable
[sel
-1].selector
) + *(WORD
*)(p
+ 1);
412 dprintf_module( stddeb
, "Signature: %02x %02x %02x,ff %x\n",
413 fixup_ptr
[0], fixup_ptr
[1], fixup_ptr
[2],
417 /* Verify the signature */
418 if (((fixup_ptr
[0] == 0x1e && fixup_ptr
[1] == 0x58)
419 || (fixup_ptr
[0] == 0x8c && fixup_ptr
[1] == 0xd8))
420 && fixup_ptr
[2] == 0x90)
424 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
)
426 /* can this happen? */
427 fprintf( stderr
, "FixupPrologs got confused\n" );
429 else if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
431 *fixup_ptr
= 0xb8; /* MOV AX, */
432 *(WORD
*)(fixup_ptr
+1) = dgroup
;
437 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
438 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
444 dprintf_fixup( stddeb
, "Unknown signature\n" );
448 dprintf_module( stddeb
,"\n");
449 p
+= (sel
== 0xff) ? 6 : 3;
455 /***********************************************************************
458 * Call the DLL initialization code
460 static BOOL32
NE_InitDLL( HMODULE16 hModule
)
463 SEGTABLEENTRY
*pSegTable
;
466 /* Registers at initialization must be:
468 * di library instance
469 * ds data segment if any
470 * es:si command line (always 0)
473 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
474 pSegTable
= NE_SEG_TABLE( pModule
);
476 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) ||
477 (pModule
->flags
& NE_FFLAGS_WIN32
)) return TRUE
; /*not a library*/
478 if (!pModule
->cs
) return TRUE
; /* no initialization code */
480 memset( &context
, 0, sizeof(context
) );
482 if (!(pModule
->flags
& NE_FFLAGS_SINGLEDATA
))
484 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
|| pModule
->dgroup
)
487 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
490 else /* DATA NONE DLL */
492 DS_reg(&context
) = 0;
493 ECX_reg(&context
) = 0;
496 else /* DATA SINGLE DLL */
498 DS_reg(&context
) = pSegTable
[pModule
->dgroup
-1].selector
;
499 ECX_reg(&context
) = pModule
->heap_size
;
502 CS_reg(&context
) = pSegTable
[pModule
->cs
-1].selector
;
503 EIP_reg(&context
) = pModule
->ip
;
504 EBP_reg(&context
) = IF1632_Saved16_sp
+ (WORD
)&((STACK16FRAME
*)0)->bp
;
505 EDI_reg(&context
) = DS_reg(&context
) ? DS_reg(&context
) : hModule
;
508 pModule
->cs
= 0; /* Don't initialize it twice */
509 dprintf_dll( stddeb
, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
510 CS_reg(&context
), IP_reg(&context
), DS_reg(&context
),
511 DI_reg(&context
), CX_reg(&context
) );
512 CallTo16_regs_( &context
);
517 /***********************************************************************
520 * Initialize the loaded DLLs.
522 void NE_InitializeDLLs( HMODULE16 hModule
)
527 if (!(pModule
= MODULE_GetPtr( hModule
))) return;
528 if (pModule
->flags
& NE_FFLAGS_WIN32
)
530 /* PE_InitializeDLLs(hModule); */
533 if (pModule
->dlls_to_init
)
535 HGLOBAL16 to_init
= pModule
->dlls_to_init
;
536 pModule
->dlls_to_init
= 0;
537 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
539 NE_InitializeDLLs( *pDLL
);
541 GlobalFree16( to_init
);
543 NE_InitDLL( hModule
);
547 /***********************************************************************
550 * Needed for self-loading modules.
553 /* It does nothing */
554 void PatchCodeHandle(HANDLE16 hSel
)