2 * Copyright 1994 Eric Youndale & Erik Bos
4 * based on Eric Youndale's pe-test and:
6 * ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
14 #include <sys/types.h>
27 #include "registers.h"
28 #include "selectors.h"
33 #define MAP_ANONYMOUS 0x20
35 struct w_files
*wine_files
= NULL
;
37 unsigned int load_addr
;
39 void my_wcstombs(char * result
, u_short
* source
, int len
)
42 if(isascii(*source
)) *result
++ = *source
++;
44 printf("Unable to handle unicode right now\n");
50 char * xmmap(char * vaddr
, unsigned int v_size
, unsigned int r_size
,
51 int prot
, int flags
, int fd
, unsigned int file_offset
)
54 /* .bss has no associated storage in the PE file */
59 fprintf(stderr
,"xmmap: %s line %d doesn't support MAP_ANON\n",__FILE__
, __LINE__
);
63 result
= mmap(vaddr
, v_size
, prot
, flags
, fd
, file_offset
);
64 if((unsigned int) result
!= 0xffffffff) return result
;
66 /* Sigh. Alignment must be wrong for mmap. Do this the hard way. */
67 if(!(flags
& MAP_FIXED
)) {
68 vaddr
= (char *)0x40000000;
72 mmap(vaddr
, v_size
, prot
, MAP_ANONYMOUS
| flags
, 0, 0);
73 lseek(fd
, file_offset
, SEEK_SET
);
74 read(fd
, vaddr
, v_size
);
78 void dump_exports(struct PE_Export_Directory
* pe_exports
)
84 u_char
** name
, *ename
;
86 Module
= ((char *) load_addr
) + pe_exports
->Name
;
87 printf("\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n",
89 pe_exports
->Number_Of_Functions
,
90 pe_exports
->Number_Of_Names
);
92 ordinal
= (u_short
*) (((char *) load_addr
) + (int) pe_exports
->Address_Of_Name_Ordinals
);
93 function
= (u_long
*) (((char *) load_addr
) + (int) pe_exports
->AddressOfFunctions
);
94 name
= (u_char
**) (((char *) load_addr
) + (int) pe_exports
->AddressOfNames
);
96 printf("%-32s Ordinal Virt Addr\n", "Function Name");
97 for(i
=0; i
< pe_exports
->Number_Of_Functions
; i
++)
99 ename
= (char *) (((char *) load_addr
) + (int) *name
++);
100 printf("%-32s %4d %8.8lx\n", ename
, *ordinal
++, *function
++);
104 void fixup_imports(struct PE_Import_Directory
*pe_imports
)
106 struct PE_Import_Directory
* pe_imp
;
109 /* OK, now dump the import list */
110 printf("\nDumping imports list\n");
112 while (pe_imp
->ModuleName
)
115 struct pe_import_name
* pe_name
;
116 unsigned int * import_list
, *thunk_list
;
119 Module
= ((char *) load_addr
) + pe_imp
->ModuleName
;
120 printf("%s\n", Module
);
121 c
= strchr(Module
, '.');
124 import_list
= (unsigned int *)
125 (((unsigned int) load_addr
) + pe_imp
->Import_List
);
126 thunk_list
= (unsigned int *)
127 (((unsigned int) load_addr
) + pe_imp
->Thunk_List
);
132 pe_name
= (struct pe_import_name
*) ((int) load_addr
+ *import_list
);
133 if((unsigned)pe_name
& 0x80000000)
135 fprintf(stderr
,"Import by ordinal not supported\n");
138 printf("--- %s %s.%d\n", pe_name
->Name
, Module
, pe_name
->Hint
);
139 #ifndef WINELIB /* FIXME: JBP: Should this happen in libwine.a? */
140 *thunk_list
=(unsigned int)RELAY32_GetEntryPoint(Module
,pe_name
->Name
,pe_name
->Hint
);
142 fprintf(stderr
,"JBP: Call to RELAY32_GetEntryPoint being ignored.\n");
146 fprintf(stderr
,"No implementation for %s.%d\n",Module
, pe_name
->Hint
);
155 if(fixup_failed
)exit(1);
158 static void dump_table(struct w_files
*wpnt
)
162 printf("Dump of segment table\n");
163 printf(" Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
164 for(i
=0; i
< wpnt
->pe
->pe_header
->coff
.NumberOfSections
; i
++)
166 printf("%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
167 wpnt
->pe
->pe_seg
[i
].Name
,
168 wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
169 wpnt
->pe
->pe_seg
[i
].Virtual_Address
,
170 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
,
171 wpnt
->pe
->pe_seg
[i
].PointerToRawData
,
172 wpnt
->pe
->pe_seg
[i
].PointerToRelocations
,
173 wpnt
->pe
->pe_seg
[i
].PointerToLinenumbers
,
174 wpnt
->pe
->pe_seg
[i
].NumberOfRelocations
,
175 wpnt
->pe
->pe_seg
[i
].NumberOfLinenumbers
,
176 wpnt
->pe
->pe_seg
[i
].Characteristics
);
180 /**********************************************************************
182 * Load one PE format executable into memory
184 HINSTANCE
PE_LoadImage(struct w_files
*wpnt
)
188 wpnt
->pe
= xmalloc(sizeof(struct pe_data
));
189 memset(wpnt
->pe
,0,sizeof(struct pe_data
));
190 wpnt
->pe
->pe_header
= xmalloc(sizeof(struct pe_header_s
));
193 lseek(wpnt
->fd
, wpnt
->mz_header
->ne_offset
, SEEK_SET
);
194 read(wpnt
->fd
, wpnt
->pe
->pe_header
, sizeof(struct pe_header_s
));
197 wpnt
->pe
->pe_seg
= xmalloc(sizeof(struct pe_segment_table
) *
198 wpnt
->pe
->pe_header
->coff
.NumberOfSections
);
199 read(wpnt
->fd
, wpnt
->pe
->pe_seg
, sizeof(struct pe_segment_table
) *
200 wpnt
->pe
->pe_header
->coff
.NumberOfSections
);
202 load_addr
= wpnt
->pe
->pe_header
->opt_coff
.BaseOfImage
;
203 printf("Load addr is %x\n",load_addr
);
206 for(i
=0; i
< wpnt
->pe
->pe_header
->coff
.NumberOfSections
; i
++)
209 result
= (int)xmmap((char *)0, wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
210 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7,
211 MAP_PRIVATE
, wpnt
->fd
, wpnt
->pe
->pe_seg
[i
].PointerToRawData
);
212 load_addr
= (unsigned int) result
- wpnt
->pe
->pe_seg
[i
].Virtual_Address
;
214 result
= (int)xmmap((char *) load_addr
+ wpnt
->pe
->pe_seg
[i
].Virtual_Address
,
215 wpnt
->pe
->pe_seg
[i
].Virtual_Size
,
216 wpnt
->pe
->pe_seg
[i
].Size_Of_Raw_Data
, 7, MAP_PRIVATE
| MAP_FIXED
,
217 wpnt
->fd
, wpnt
->pe
->pe_seg
[i
].PointerToRawData
);
220 fprintf(stderr
,"Could not load section %x to desired address %lx\n",
221 i
, load_addr
+wpnt
->pe
->pe_seg
[i
].Virtual_Address
);
222 fprintf(stderr
,"Need to implement relocations now\n");
226 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".idata") == 0)
227 wpnt
->pe
->pe_import
= (struct PE_Import_Directory
*) result
;
229 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".edata") == 0)
230 wpnt
->pe
->pe_export
= (struct PE_Export_Directory
*) result
;
232 if(strcmp(wpnt
->pe
->pe_seg
[i
].Name
, ".rsrc") == 0) {
233 wpnt
->pe
->pe_resource
= (struct PE_Resource_Directory
*) result
;
235 /* save offset for PE_FindResource */
236 wpnt
->pe
->resource_offset
= wpnt
->pe
->pe_seg
[i
].Virtual_Address
-
237 wpnt
->pe
->pe_seg
[i
].PointerToRawData
;
241 if(wpnt
->pe
->pe_import
) fixup_imports(wpnt
->pe
->pe_import
);
242 if(wpnt
->pe
->pe_export
) dump_exports(wpnt
->pe
->pe_export
);
244 wpnt
->hinstance
= (HINSTANCE
)0x8000;
245 return (wpnt
->hinstance
);
248 HINSTANCE
MODULE_CreateInstance(HMODULE hModule
,LOADPARAMS
*params
);
249 void InitTask(struct sigcontext_struct context
);
251 HINSTANCE
PE_LoadModule(int fd
, OFSTRUCT
*ofs
, LOADPARAMS
* params
)
253 struct w_files
*wpnt
;
256 LOADEDFILEINFO
*pFileInfo
;
257 SEGTABLEENTRY
*pSegment
;
265 wpnt
=xmalloc(sizeof(struct w_files
));
266 wpnt
->next
=wine_files
;
274 lseek(fd
,0,SEEK_SET
);
275 wpnt
->mz_header
=xmalloc(sizeof(struct mz_header_s
));
276 read(fd
,wpnt
->mz_header
,sizeof(struct mz_header_s
));
278 size
=sizeof(NE_MODULE
) +
279 /* loaded file info */
280 sizeof(LOADEDFILEINFO
) + strlen(ofs
->szPathName
) +
281 /* segment table: DS,CS */
282 2 * sizeof(SEGTABLEENTRY
) +
285 /* several empty tables */
288 hModule
= GlobalAlloc( GMEM_MOVEABLE
| GMEM_ZEROINIT
, size
);
289 wpnt
->hModule
=hModule
;
290 if (!hModule
) return (HINSTANCE
)11; /* invalid exe */
292 FarSetOwner( hModule
, hModule
);
294 pModule
= (NE_MODULE
*)GlobalLock(hModule
);
296 /* Set all used entries */
297 pModule
->magic
=NE_SIGNATURE
;
304 /* Who wants to LocalAlloc for a PE Module? */
305 pModule
->heap_size
=0x1000;
306 pModule
->stack_size
=0xF000;
307 pModule
->seg_count
=1;
308 pModule
->modref_count
=0;
309 pModule
->nrname_size
=0;
310 pModule
->seg_table
=sizeof(NE_MODULE
)+
311 sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
);
312 pModule
->fileinfo
=sizeof(NE_MODULE
);
313 pModule
->os_flags
=NE_OSFLAGS_WINDOWS
;
314 pModule
->expected_version
=0x30A;
316 pFileInfo
=(LOADEDFILEINFO
*)(pModule
+ 1);
317 pFileInfo
->length
= sizeof(LOADEDFILEINFO
)+strlen(ofs
->szPathName
)-1;
318 strcpy(pFileInfo
->filename
,ofs
->szPathName
);
320 pSegment
=(SEGTABLEENTRY
*)((char*)pFileInfo
+pFileInfo
->length
+1);
321 pModule
->dgroup_entry
=(int)pSegment
-(int)pModule
;
323 pSegment
->flags
=NE_SEGFLAGS_DATA
;
324 pSegment
->minsize
=0x1000;
327 cts
=(DWORD
)GetWndProcEntry16("Win32CallToStart");
329 pSegment
->selector
=(void*)cts
;
332 pSegment
->selector
=cts
>>16;
333 pModule
->ip
=cts
& 0xFFFF;
337 pStr
=(char*)pSegment
;
338 pModule
->name_table
=(int)pStr
-(int)pModule
;
339 strcpy(pStr
,"\x08W32SXXXX");
342 /* All tables zero terminated */
343 pModule
->res_table
=pModule
->import_table
=pModule
->entry_table
=
344 (int)pStr
-(int)pModule
;
348 pModule
->heap_size
=0x1000;
349 pModule
->stack_size
=0xE000;
351 /* CreateInstance allocates now 64KB */
352 hInstance
=MODULE_CreateInstance(hModule
,NULL
/* FIX: NULL? really? */);
353 wpnt
->hinstance
=hInstance
;
355 TASK_CreateTask(hModule
,hInstance
,0,
356 params
->hEnvironment
,(LPSTR
)PTR_SEG_TO_LIN(params
->cmdLine
),
357 *((WORD
*)PTR_SEG_TO_LIN(params
->showCmd
)+1));
362 int USER_InitApp(HINSTANCE hInstance
);
364 void PE_Win32CallToStart(struct sigcontext_struct context
)
367 struct w_files
*wpnt
=wine_files
;
368 fs
=(int)GlobalAlloc(GHND
,0x10000);
369 fprintf(stddeb
,"Going to start Win32 program\n");
371 USER_InitApp(wpnt
->hModule
);
372 __asm__
__volatile__("movw %w0,%%fs"::"r" (fs
));
373 ((void(*)())(load_addr
+wpnt
->pe
->pe_header
->opt_coff
.AddressOfEntryPoint
))();
376 int PE_UnloadImage(struct w_files
*wpnt
)
378 printf("PEunloadImage() called!\n");
379 /* free resources, image, unmap */
383 void PE_InitDLL(struct w_files
*wpnt
)
385 /* Is this a library? */
386 if (wpnt
->pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DLL
) {
387 printf("InitPEDLL() called!\n");