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
;
73 WORD oldselector
, newselector
;
74 HFILE32 hf
= FILE_DupUnixHandle( fd
);
76 selfloadheader
= (SELFLOADHEADER
*)
77 PTR_SEG_OFF_TO_LIN(pSegTable
->selector
,0);
78 oldstack
= IF1632_Saved16_ss_sp
;
79 oldselector
= pSeg
->selector
;
80 IF1632_Saved16_ss_sp
= PTR_SEG_OFF_TO_SEGPTR(pModule
->self_loading_sel
,
81 0xff00 - sizeof(*stack16Top
));
82 stack16Top
= CURRENT_STACK16
;
83 stack16Top
->saved_ss_sp
= 0;
84 stack16Top
->ds
= stack16Top
->es
= pModule
->self_loading_sel
;
85 stack16Top
->entry_point
= 0;
86 stack16Top
->entry_ip
= 0;
87 stack16Top
->entry_cs
= 0;
91 newselector
= CallTo16_word_www( selfloadheader
->LoadAppSeg
,
92 hModule
, hf
, segnum
);
94 if (newselector
!= oldselector
) {
95 /* Self loaders like creating their own selectors;
96 * they love asking for trouble to Wine developers
98 if (segnum
== pModule
->dgroup
) {
99 memcpy(PTR_SEG_OFF_TO_LIN(oldselector
,0),
100 PTR_SEG_OFF_TO_LIN(newselector
,0),
101 pSeg
->minsize
? pSeg
->minsize
: 0x10000);
102 FreeSelector(newselector
);
103 pSeg
->selector
= oldselector
;
104 fprintf(stderr
, "A new selector was allocated for the dgroup segment\n"
105 "Old selector is %d, new one is %d", oldselector
, newselector
);
107 FreeSelector(pSeg
->selector
);
108 pSeg
->selector
= newselector
;
112 IF1632_Saved16_ss_sp
= oldstack
;
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
& 0xff) == 0xff)
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 "WARNING: %d: ADDR TYPE %d, unknown 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 /* Apparently, high bit of address_type is sometimes set; */
283 /* we ignore it for now */
284 if (rep
->address_type
> NE_RADDR_OFFSET32
)
285 fprintf( stderr
, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
286 MODULE_GetModuleName(hModule
), rep
->address_type
);
288 switch (rep
->address_type
& 0x7f)
290 case NE_RADDR_LOWBYTE
:
292 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
293 dprintf_fixup(stddeb
," %04x:%04x:%04x BYTE%s\n",
294 pSeg
->selector
, offset
, *sp
, additive
? " additive":"");
297 *(unsigned char*)sp
= (unsigned char)(((int)address
+offset
) & 0xFF);
299 *(unsigned char*)sp
= (unsigned char)((int)address
& 0xFF);
301 while (offset
!= 0xffff && !additive
);
304 case NE_RADDR_OFFSET16
:
306 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
307 dprintf_fixup(stddeb
," %04x:%04x:%04x OFFSET16%s\n",
308 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
310 *sp
= LOWORD(address
);
311 if (additive
) *sp
+= offset
;
313 while (offset
!= 0xffff && !additive
);
316 case NE_RADDR_POINTER32
:
318 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
319 dprintf_fixup(stddeb
," %04x:%04x:%04x POINTER32%s\n",
320 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
322 *sp
= LOWORD(address
);
323 if (additive
) *sp
+= offset
;
324 *(sp
+1) = HIWORD(address
);
326 while (offset
!= 0xffff && !additive
);
329 case NE_RADDR_SELECTOR
:
331 sp
= PTR_SEG_OFF_TO_LIN( pSeg
->selector
, offset
);
332 dprintf_fixup(stddeb
," %04x:%04x:%04x SELECTOR%s\n",
333 pSeg
->selector
, offset
, *sp
, additive
? " additive" : "" );
335 *sp
= HIWORD(address
);
336 /* Borland creates additive records with offset zero. Strange, but OK */
337 if(additive
&& offset
)
338 fprintf(stderr
,"Additive selector to %4.4x.Please report\n",offset
);
340 /* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
341 while (offset
&& offset
!= 0xffff && !additive
);
345 dprintf_fixup(stddeb
,
346 "WARNING: %d: unknown ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
347 i
+ 1, rep
->address_type
, rep
->relocation_type
,
349 dprintf_fixup(stddeb
,
350 "TARGET %04x %04x\n", rep
->target1
, rep
->target2
);
361 /***********************************************************************
364 * Fixup the exported functions prologs.
366 void NE_FixupPrologs( NE_MODULE
*pModule
)
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
)
424 /* can this happen? */
425 fprintf( stderr
, "FixupPrologs got confused\n" );
427 else if (pModule
->flags
& NE_FFLAGS_SINGLEDATA
)
429 *fixup_ptr
= 0xb8; /* MOV AX, */
430 *(WORD
*)(fixup_ptr
+1) = dgroup
;
435 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
) {
436 fixup_ptr
[0] = 0x90; /* non-library: NOPs */
442 dprintf_fixup( stddeb
, "Unknown signature\n" );
446 dprintf_module( stddeb
,"\n");
447 p
+= (sel
== 0xff) ? 6 : 3;
453 /***********************************************************************
456 * Call the DLL initialization code
458 static BOOL32
NE_InitDLL( HMODULE16 hModule
)
461 SEGTABLEENTRY
*pSegTable
;
464 /* Registers at initialization must be:
466 * di library instance
467 * ds data segment if any
468 * es:si command line (always 0)
471 if (!(pModule
= MODULE_GetPtr( hModule
))) return FALSE
;
472 pSegTable
= NE_SEG_TABLE( pModule
);
474 if (!(pModule
->flags
& NE_FFLAGS_LIBMODULE
) ||
475 (pModule
->flags
& NE_FFLAGS_WIN32
)) return TRUE
; /*not a library*/
476 if (!pModule
->cs
) return TRUE
; /* no initialization code */
478 memset( &context
, 0, sizeof(context
) );
480 if (!(pModule
->flags
& NE_FFLAGS_SINGLEDATA
))
482 if (pModule
->flags
& NE_FFLAGS_MULTIPLEDATA
|| pModule
->dgroup
)
485 fprintf(stderr
, "Library is not marked SINGLEDATA\n");
488 else /* DATA NONE DLL */
490 DS_reg(&context
) = 0;
491 ECX_reg(&context
) = 0;
494 else /* DATA SINGLE DLL */
496 DS_reg(&context
) = pSegTable
[pModule
->dgroup
-1].selector
;
497 ECX_reg(&context
) = pModule
->heap_size
;
500 CS_reg(&context
) = pSegTable
[pModule
->cs
-1].selector
;
501 EIP_reg(&context
) = pModule
->ip
;
502 EBP_reg(&context
) = OFFSETOF(IF1632_Saved16_ss_sp
)
503 + (WORD
)&((STACK16FRAME
*)0)->bp
;
504 EDI_reg(&context
) = DS_reg(&context
) ? DS_reg(&context
) : hModule
;
507 pModule
->cs
= 0; /* Don't initialize it twice */
508 dprintf_dll( stddeb
, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
509 CS_reg(&context
), IP_reg(&context
), DS_reg(&context
),
510 DI_reg(&context
), CX_reg(&context
) );
511 CallTo16_regs_( &context
);
516 /***********************************************************************
519 * Initialize the loaded DLLs.
521 void NE_InitializeDLLs( HMODULE16 hModule
)
526 if (!(pModule
= MODULE_GetPtr( hModule
))) return;
527 if (pModule
->flags
& NE_FFLAGS_WIN32
)
529 /* PE_InitializeDLLs(hModule); */
532 if (pModule
->dlls_to_init
)
534 HGLOBAL16 to_init
= pModule
->dlls_to_init
;
535 pModule
->dlls_to_init
= 0;
536 for (pDLL
= (HMODULE16
*)GlobalLock16( to_init
); *pDLL
; pDLL
++)
538 NE_InitializeDLLs( *pDLL
);
540 GlobalFree16( to_init
);
542 NE_InitDLL( hModule
);
546 /***********************************************************************
549 * Needed for self-loading modules.
552 /* It does nothing */
553 void PatchCodeHandle(HANDLE16 hSel
)