1 static char RCSId
[] = "$Id: wine.c,v 1.1 1993/06/29 15:55:18 root Exp $";
2 static char Copyright
[] = "Copyright Robert J. Amstadt, 1993";
10 #include <linux/unistd.h>
11 #include <linux/head.h>
12 #include <linux/ldt.h>
13 #include <linux/segment.h>
17 #include "prototypes.h"
20 extern int CallToInit16(unsigned long csip
, unsigned long sssp
,
22 extern void CallTo32();
24 unsigned short WIN_StackSize
;
25 unsigned short WIN_HeapSize
;
29 struct mz_header_s
*CurrentMZHeader
;
30 struct ne_header_s
*CurrentNEHeader
;
33 /**********************************************************************
37 DebugPrintString(char *str
)
43 /**********************************************************************
47 myerror(const char *s
)
51 sprintf(buffer
, "%s", Argv
[0]);
55 fprintf(stderr
, "%s: %s\n", buffer
, s
);
60 /**********************************************************************
63 main(int argc
, char **argv
)
66 struct mz_header_s
*mz_header
;
67 struct ne_header_s
*ne_header
;
68 struct ne_segment_table_entry_s
*seg_table
;
70 unsigned int read_size
;
71 struct segment_descriptor_s
*selector_table
;
74 int cs_reg
, ds_reg
, ss_reg
, ip_reg
, sp_reg
;
82 fprintf(stderr
, "usage: %s FILENAME\n", argv
[0]);
87 * Open file for reading.
89 fd
= open(argv
[1], O_RDONLY
);
96 * Allocate memory to hold entire executable.
98 if (fstat(fd
, &finfo
) < 0)
102 * Establish header pointers.
104 mz_header
= (struct mz_header_s
*) malloc(sizeof(struct mz_header_s
));;
105 status
= lseek(fd
, 0, SEEK_SET
);
106 if (read(fd
, mz_header
, sizeof(struct mz_header_s
)) !=
107 sizeof(struct mz_header_s
))
109 myerror("Unable to read MZ header from file");
111 if (mz_header
->must_be_0x40
!= 0x40)
112 myerror("This is not a Windows program");
114 ne_header
= (struct ne_header_s
*) malloc(sizeof(struct ne_header_s
));
115 status
= lseek(fd
, mz_header
->ne_offset
, SEEK_SET
);
116 if (read(fd
, ne_header
, sizeof(struct ne_header_s
))
117 != sizeof(struct ne_header_s
))
119 myerror("Unable to read NE header from file");
121 if (ne_header
->header_type
[0] != 'N' || ne_header
->header_type
[1] != 'E')
122 myerror("This is not a Windows program");
124 CurrentMZHeader
= mz_header
;
125 CurrentNEHeader
= ne_header
;
128 WIN_StackSize
= ne_header
->stack_length
;
129 WIN_HeapSize
= ne_header
->local_heap_length
;
132 * Create segment selectors.
134 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->segment_tab_offset
,
136 read_size
= ne_header
->n_segment_tab
*
137 sizeof(struct ne_segment_table_entry_s
);
138 seg_table
= (struct ne_segment_table_entry_s
*) malloc(read_size
);
139 if (read(fd
, seg_table
, read_size
) != read_size
)
140 myerror("Unable to read segment table header from file");
141 selector_table
= CreateSelectors(fd
, seg_table
, ne_header
);
146 for (segment
= 0; segment
< ne_header
->n_segment_tab
; segment
++)
148 if (FixupSegment(fd
, mz_header
, ne_header
, seg_table
,
149 selector_table
, segment
) < 0)
151 myerror("fixup failed.");
156 * Fixup stack and jump to start.
158 ds_reg
= selector_table
[ne_header
->auto_data_seg
-1].selector
;
159 cs_reg
= selector_table
[ne_header
->cs
-1].selector
;
160 ip_reg
= ne_header
->ip
;
161 ss_reg
= selector_table
[ne_header
->ss
-1].selector
;
162 sp_reg
= ne_header
->sp
;
164 rv
= CallToInit16(cs_reg
<< 16 | ip_reg
, ss_reg
<< 16 | sp_reg
, ds_reg
);
165 printf ("rv = %x\n", rv
);
169 /**********************************************************************
173 GetImportedName(int fd
, struct mz_header_s
*mz_header
,
174 struct ne_header_s
*ne_header
, int name_offset
, char *buffer
)
181 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
182 name_offset
, SEEK_SET
);
184 read(fd
, &length
, 1); /* Get the length byte */
185 read(fd
, buffer
, length
);
190 /**********************************************************************
194 GetModuleName(int fd
, struct mz_header_s
*mz_header
,
195 struct ne_header_s
*ne_header
, int index
, char *buffer
)
199 int name_offset
, status
;
202 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->moduleref_tab_offset
+
203 2*(index
- 1), SEEK_SET
);
205 read(fd
, &name_offset
, 2);
206 status
= lseek(fd
, mz_header
->ne_offset
+ ne_header
->iname_tab_offset
+
207 name_offset
, SEEK_SET
);
209 read(fd
, &length
, 1); /* Get the length byte */
210 read(fd
, buffer
, length
);
216 /**********************************************************************
220 FixupSegment(int fd
, struct mz_header_s
* mz_header
,
221 struct ne_header_s
*ne_header
,
222 struct ne_segment_table_entry_s
*seg_table
,
223 struct segment_descriptor_s
*selector_table
,
226 struct relocation_entry_s
*rep
, *rep1
;
227 struct ne_segment_table_entry_s
*seg
;
228 struct segment_descriptor_s
*sel
;
229 struct dll_table_entry_s
*dll_table
;
231 unsigned int selector
, address
;
232 unsigned int next_addr
;
239 seg
= &seg_table
[segment_num
];
240 sel
= &selector_table
[segment_num
];
242 if (seg
->seg_data_offset
== 0)
246 * Go through the relocation table on entry at a time.
248 i
= seg
->seg_data_length
;
252 status
= lseek(fd
, seg
->seg_data_offset
*
253 (1 << ne_header
->align_shift_count
) + i
, SEEK_SET
);
255 read(fd
, &n_entries
, sizeof(short int));
256 rep
= (struct relocation_entry_s
*)
257 malloc(n_entries
* sizeof(struct relocation_entry_s
));
259 if (read(fd
,rep
, n_entries
* sizeof(struct relocation_entry_s
)) !=
260 n_entries
* sizeof(struct relocation_entry_s
))
262 myerror("Unable to read relocation information");
267 for (i
= 0; i
< n_entries
; i
++, rep
++)
270 * Get the target address corresponding to this entry.
272 switch (rep
->relocation_type
)
274 case NE_RELTYPE_ORDINAL
:
275 if (GetModuleName(fd
, mz_header
, ne_header
, rep
->target1
,
281 dll_table
= FindDLLTable(dll_name
);
282 if (dll_table
== NULL
)
286 sprintf(s
, "Bad DLL name '%s'", dll_name
);
291 ordinal
= rep
->target2
;
292 selector
= dll_table
[ordinal
].selector
;
293 address
= (unsigned int) dll_table
[ordinal
].address
;
295 printf("%d: %s.%d: %04.4x:%04.4x\n", i
+ 1, dll_name
, ordinal
,
300 case NE_RELTYPE_NAME
:
301 if (GetModuleName(fd
, mz_header
, ne_header
, rep
->target1
, dll_name
)
306 dll_table
= FindDLLTable(dll_name
);
307 if (dll_table
== NULL
)
311 sprintf(s
, "Bad DLL name '%s'", dll_name
);
316 if (GetImportedName(fd
, mz_header
, ne_header
,
317 rep
->target2
, func_name
) == NULL
)
321 ordinal
= FindOrdinalFromName(dll_table
, func_name
);
322 selector
= dll_table
[ordinal
].selector
;
323 address
= (unsigned int) dll_table
[ordinal
].address
;
325 printf("%d: %s %s.%d: %04.4x:%04.4x\n", i
+ 1, func_name
,
326 dll_name
, ordinal
, selector
, address
);
330 case NE_RELTYPE_INTERNAL
:
331 if (rep
->target1
== 0x00ff)
333 address
= GetEntryPointFromOrdinal(fd
, mz_header
, ne_header
,
335 selector
= (address
>> 16) & 0xffff;
340 selector
= selector_table
[rep
->target1
-1].selector
;
341 address
= rep
->target2
;
345 printf("%d: %04.4x:%04.4x\n", i
+ 1, selector
, address
);
350 /* Relocation type 7:
352 * These appear to be used as fixups for the Windows
353 * floating point emulator. Let's just ignore them and
354 * try to use the hardware floating point. Linux should
355 * successfully emulate the coprocessor if it doesn't
359 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
360 i
+ 1, rep
->address_type
, rep
->relocation_type
,
362 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
368 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
369 i
+ 1, rep
->address_type
, rep
->relocation_type
,
371 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);
378 * Stuff the right size result in.
380 sp
= (unsigned short *) ((char *) sel
->base_addr
+ rep
->offset
);
381 switch (rep
->address_type
)
383 case NE_RADDR_OFFSET16
:
386 *sp
= (unsigned short) address
;
387 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
389 while (next_addr
!= 0xffff);
393 case NE_RADDR_POINTER32
:
396 *sp
= (unsigned short) address
;
397 *(sp
+1) = (unsigned short) selector
;
398 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
400 while (next_addr
!= 0xffff);
404 case NE_RADDR_SELECTOR
:
407 *sp
= (unsigned short) selector
;
408 sp
= (unsigned short *) ((char *) sel
->base_addr
+ next_addr
);
410 while (next_addr
!= 0xffff);
416 printf("%d: ADDR TYPE %d, TYPE %d, OFFSET %04.4x, ",
417 i
+ 1, rep
->address_type
, rep
->relocation_type
,
419 printf("TARGET %04.4x %04.4x\n", rep
->target1
, rep
->target2
);