Release 950727
[wine] / loader / pe_image.c
1 /* 
2  *  Copyright   1994    Eric Youndale & Erik Bos
3  *
4  *      based on Eric Youndale's pe-test and:
5  *
6  *      ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
7  */
8
9 #include <ctype.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/mman.h>
16 #include "windows.h"
17 #include "dlls.h"
18 #include "neexe.h"
19 #include "peexe.h"
20 #include "pe_image.h"
21
22 #define MAP_ANONYMOUS   0x20
23
24 struct w_files *wine_files = NULL;
25
26 unsigned int load_addr;
27
28 void my_wcstombs(char * result, u_short * source, int len)
29 {
30   while(len--) {
31     if(isascii(*source)) *result++ = *source++;
32     else {
33       printf("Unable to handle unicode right now\n");
34       exit(0);
35     }
36   };
37 }
38
39 char * xmmap(char * vaddr, unsigned int v_size, unsigned int r_size,
40         int prot, int flags, int fd, unsigned int file_offset)
41 {
42   char * result;
43   /* .bss has no associated storage in the PE file */
44   if(r_size)
45     v_size=r_size;
46   else
47     flags |= MAP_ANON;
48   result = mmap(vaddr, v_size, prot, flags, fd, file_offset);
49   if((unsigned int) result != 0xffffffff) return result;
50
51   /* Sigh.  Alignment must be wrong for mmap.  Do this the hard way. */
52   if(!(flags & MAP_FIXED)) {
53     vaddr = (char *)0x40000000;
54     flags |= MAP_FIXED;
55   };
56
57   mmap(vaddr, v_size, prot, MAP_ANONYMOUS | flags, 0, 0);
58   lseek(fd, file_offset, SEEK_SET);
59   read(fd, vaddr, v_size);
60   return vaddr;
61 };
62
63 void dump_exports(struct PE_Export_Directory * pe_exports)
64
65   char * Module;
66   int i;
67   u_short * ordinal;
68   u_long * function;
69   u_char ** name, *ename;
70
71   Module = ((char *) load_addr) + pe_exports->Name;
72   printf("\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n", 
73          Module,
74          pe_exports->Number_Of_Functions,
75          pe_exports->Number_Of_Names);
76
77   ordinal = (u_short *) (((char *) load_addr) + (int) pe_exports->Address_Of_Name_Ordinals);
78   function = (u_long *)  (((char *) load_addr) + (int) pe_exports->AddressOfFunctions);
79   name = (u_char **)  (((char *) load_addr) + (int) pe_exports->AddressOfNames);
80
81   printf("%-32s Ordinal Virt Addr\n", "Function Name");
82   for(i=0; i< pe_exports->Number_Of_Functions; i++)
83     {
84       ename =  (char *) (((char *) load_addr) + (int) *name++);
85       printf("%-32s %4d    %8.8lx\n", ename, *ordinal++, *function++);
86     }
87 }
88
89 void fixup_imports(struct PE_Import_Directory *pe_imports)
90
91   struct PE_Import_Directory * pe_imp;
92   int fixup_failed=0;
93
94  /* OK, now dump the import list */
95   printf("\nDumping imports list\n");
96   pe_imp = pe_imports;
97   while (pe_imp->ModuleName)
98     {
99       char * Module;
100       struct pe_import_name * pe_name;
101       unsigned int * import_list, *thunk_list;
102       char * c;
103
104       Module = ((char *) load_addr) + pe_imp->ModuleName;
105       printf("%s\n", Module);
106       c = strchr(Module, '.');
107       if (c) *c = 0;
108
109       import_list = (unsigned int *) 
110         (((unsigned int) load_addr) + pe_imp->Import_List);
111           thunk_list = (unsigned int *)
112           (((unsigned int) load_addr) + pe_imp->Thunk_List);
113
114
115       while(*import_list)
116         {
117           pe_name = (struct pe_import_name *) ((int) load_addr + *import_list);
118           if((unsigned)pe_name & 0x80000000)
119           {
120                 fprintf(stderr,"Import by ordinal not supported\n");
121                 exit(0);
122           }
123           printf("--- %s %s.%d\n", pe_name->Name, Module, pe_name->Hint);
124           *thunk_list=RELAY32_GetEntryPoint(Module,pe_name->Name,pe_name->Hint);
125           if(!*thunk_list)
126           {
127                 fprintf(stderr,"No implementation for %s.%d\n",Module, pe_name->Hint);
128                 fixup_failed=1;
129           }
130
131           import_list++;
132           thunk_list++;
133         }
134       pe_imp++;
135     };
136         if(fixup_failed)exit(1);
137 }
138
139 static void dump_table(struct w_files *wpnt)
140 {
141   int i;
142
143   printf("Dump of segment table\n");
144   printf("   Name    VSz  Vaddr     SzRaw   Fileadr  *Reloc *Lineum #Reloc #Linum Char\n");
145   for(i=0; i< wpnt->pe->pe_header->coff.NumberOfSections; i++)
146     {
147       printf("%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n", 
148              wpnt->pe->pe_seg[i].Name, 
149              wpnt->pe->pe_seg[i].Virtual_Size,
150              wpnt->pe->pe_seg[i].Virtual_Address,
151              wpnt->pe->pe_seg[i].Size_Of_Raw_Data,
152              wpnt->pe->pe_seg[i].PointerToRawData,
153              wpnt->pe->pe_seg[i].PointerToRelocations,
154              wpnt->pe->pe_seg[i].PointerToLinenumbers,
155              wpnt->pe->pe_seg[i].NumberOfRelocations,
156              wpnt->pe->pe_seg[i].NumberOfLinenumbers,
157              wpnt->pe->pe_seg[i].Characteristics);
158     }
159 }
160
161 /**********************************************************************
162  *                      PE_LoadImage
163  * Load one PE format executable into memory
164  */
165 HINSTANCE PE_LoadImage(struct w_files *wpnt)
166 {
167         int i, result;
168
169         wpnt->pe = malloc(sizeof(struct pe_data));
170         wpnt->pe->pe_header = malloc(sizeof(struct pe_header_s));
171
172         /* read PE header */
173         lseek(wpnt->fd, wpnt->mz_header->ne_offset, SEEK_SET);
174         read(wpnt->fd, wpnt->pe->pe_header, sizeof(struct pe_header_s));
175
176         /* read sections */
177         wpnt->pe->pe_seg = malloc(sizeof(struct pe_segment_table) * 
178                                 wpnt->pe->pe_header->coff.NumberOfSections);
179         read(wpnt->fd, wpnt->pe->pe_seg, sizeof(struct pe_segment_table) * 
180                         wpnt->pe->pe_header->coff.NumberOfSections);
181
182         load_addr = wpnt->pe->pe_header->opt_coff.BaseOfImage;
183         printf("Load addr is %x\n",load_addr);
184         dump_table(wpnt);
185
186         for(i=0; i < wpnt->pe->pe_header->coff.NumberOfSections; i++)
187         {
188         if(!load_addr) {
189                 result = xmmap((char *)0, wpnt->pe->pe_seg[i].Virtual_Size,
190                         wpnt->pe->pe_seg[i].Size_Of_Raw_Data, 7,
191                         MAP_PRIVATE, wpnt->fd, wpnt->pe->pe_seg[i].PointerToRawData);
192                 load_addr = (unsigned int) result -  wpnt->pe->pe_seg[i].Virtual_Address;
193         } else {
194                 result = xmmap((char *) load_addr + wpnt->pe->pe_seg[i].Virtual_Address, 
195                           wpnt->pe->pe_seg[i].Virtual_Size,
196                       wpnt->pe->pe_seg[i].Size_Of_Raw_Data, 7, MAP_PRIVATE | MAP_FIXED, 
197                       wpnt->fd, wpnt->pe->pe_seg[i].PointerToRawData);
198         }
199         if(result==-1){
200                 fprintf(stderr,"Could not load section %x to desired address %lx\n",
201                         i, load_addr+wpnt->pe->pe_seg[i].Virtual_Address);
202                 fprintf(stderr,"Need to implement relocations now\n");
203                 exit(0);
204         }
205
206         if(strcmp(wpnt->pe->pe_seg[i].Name, ".idata") == 0)
207                 wpnt->pe->pe_import = (struct PE_Import_Directory *) result;
208
209         if(strcmp(wpnt->pe->pe_seg[i].Name, ".edata") == 0)
210                 wpnt->pe->pe_export = (struct PE_Export_Directory *) result;
211
212         if(strcmp(wpnt->pe->pe_seg[i].Name, ".rsrc") == 0) {
213             wpnt->pe->pe_resource = (struct PE_Resource_Directory *) result;
214
215             /* save offset for PE_FindResource */
216             wpnt->pe->resource_offset = wpnt->pe->pe_seg[i].Virtual_Address - 
217                                         wpnt->pe->pe_seg[i].PointerToRawData;
218             }
219         }
220
221         if(wpnt->pe->pe_import) fixup_imports(wpnt->pe->pe_import);
222         if(wpnt->pe->pe_export) dump_exports(wpnt->pe->pe_export);
223   
224         wpnt->hinstance = 0x8000;
225         return (wpnt->hinstance);
226 }
227
228 int PE_UnloadImage(struct w_files *wpnt)
229 {
230         printf("PEunloadImage() called!\n");
231         /* free resources, image, unmap */
232         return 1;
233 }
234
235 void PE_InitDLL(struct w_files *wpnt)
236 {
237         /* Is this a library? */
238         if (wpnt->pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL) {
239                 printf("InitPEDLL() called!\n");
240         }
241 }