Mercurial > mplayer.hg
annotate loader/pe_image.c @ 29888:5c39c41f38e8
Deobfuscate the special hack to disable cache for live555.
Cache can not be used for it, since it does not provide any
data stream, the data is provided to the demuxer "behind
MPlayer's back".
author | reimar |
---|---|
date | Tue, 17 Nov 2009 19:23:55 +0000 |
parents | 0f1b5b68af32 |
children | 914208d188b9 |
rev | line source |
---|---|
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
1 /* |
1 | 2 * Copyright 1994 Eric Youndale & Erik Bos |
23734 | 3 * Copyright 1995 Martin von Löwis |
1 | 4 * Copyright 1996-98 Marcus Meissner |
5 * | |
6 * based on Eric Youndale's pe-test and: | |
7 * | |
8 * ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP | |
9 * make that: | |
10 * ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP | |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
13375
diff
changeset
|
11 * |
18783 | 12 * Modified for use with MPlayer, detailed changelog at |
13 * http://svn.mplayerhq.hu/mplayer/trunk/ | |
15166
f5537cc95b02
Mark modified imported files as such to comply with GPL ¡ø2a.
diego
parents:
13375
diff
changeset
|
14 * |
1 | 15 */ |
16 /* Notes: | |
17 * Before you start changing something in this file be aware of the following: | |
18 * | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
19 * - There are several functions called recursively. In a very subtle and |
1 | 20 * obscure way. DLLs can reference each other recursively etc. |
21 * - If you want to enhance, speed up or clean up something in here, think | |
22 * twice WHY it is implemented in that strange way. There is usually a reason. | |
23 * Though sometimes it might just be lazyness ;) | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
24 * - In PE_MapImage, right before fixup_imports() all external and internal |
1 | 25 * state MUST be correct since this function can be called with the SAME image |
26 * AGAIN. (Thats recursion for you.) That means MODREF.module and | |
27 * NE_MODULE.module32. | |
28 * - Sometimes, we can't use Linux mmap() to mmap() the images directly. | |
29 * | |
30 * The problem is, that there is not direct 1:1 mapping from a diskimage and | |
31 * a memoryimage. The headers at the start are mapped linear, but the sections | |
32 * are not. Older x86 pe binaries are 512 byte aligned in file and 4096 byte | |
33 * aligned in memory. Linux likes them 4096 byte aligned in memory (due to | |
34 * x86 pagesize, this cannot be fixed without a rather large kernel rewrite) | |
35 * and 'blocksize' file-aligned (offsets). Since we have 512/1024/2048 (CDROM) | |
36 * and other byte blocksizes, we can't always do this. We *can* do this for | |
37 * newer pe binaries produced by MSVC 5 and later, since they are also aligned | |
38 * to 4096 byte boundaries on disk. | |
39 */ | |
2069 | 40 #include "config.h" |
21261
a2e02e6b6379
Rename config.h --> debug.h and include config.h explicitly.
diego
parents:
18783
diff
changeset
|
41 #include "debug.h" |
1 | 42 |
43 #include <errno.h> | |
44 #include <assert.h> | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
45 #include <stdio.h> |
1 | 46 #include <stdlib.h> |
47 #include <string.h> | |
48 #include <unistd.h> | |
49 #include <sys/types.h> | |
50 #include <sys/stat.h> | |
51 #include <fcntl.h> | |
52 #ifdef HAVE_SYS_MMAN_H | |
53 #include <sys/mman.h> | |
26111
eb82d1524b6d
#include osdep/mman.h if sys/mman.h is not available.
diego
parents:
25870
diff
changeset
|
54 #else |
eb82d1524b6d
#include osdep/mman.h if sys/mman.h is not available.
diego
parents:
25870
diff
changeset
|
55 #include "osdep/mmap.h" |
1 | 56 #endif |
7386 | 57 #include "wine/windef.h" |
58 #include "wine/winbase.h" | |
59 #include "wine/winerror.h" | |
60 #include "wine/heap.h" | |
61 #include "wine/pe_image.h" | |
62 #include "wine/module.h" | |
63 #include "wine/debugtools.h" | |
2069 | 64 #include "ext.h" |
1 | 65 #include "win32.h" |
66 | |
67 #define RVA(x) ((void *)((char *)load_addr+(unsigned int)(x))) | |
68 | |
69 #define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta)) | |
70 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
71 static void dump_exports( HMODULE hModule ) |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
72 { |
1 | 73 char *Module; |
7386 | 74 unsigned int i, j; |
28162 | 75 unsigned short *ordinal; |
76 unsigned long *function,*functions; | |
77 unsigned char **name; | |
1 | 78 unsigned int load_addr = hModule; |
79 | |
80 DWORD rva_start = PE_HEADER(hModule)->OptionalHeader | |
81 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | |
82 DWORD rva_end = rva_start + PE_HEADER(hModule)->OptionalHeader | |
83 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; | |
84 IMAGE_EXPORT_DIRECTORY *pe_exports = (IMAGE_EXPORT_DIRECTORY*)RVA(rva_start); | |
85 | |
86 Module = (char*)RVA(pe_exports->Name); | |
87 TRACE("*******EXPORT DATA*******\n"); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
88 TRACE("Module name is %s, %ld functions, %ld names\n", |
1 | 89 Module, pe_exports->NumberOfFunctions, pe_exports->NumberOfNames); |
90 | |
28162 | 91 ordinal=(unsigned short*) RVA(pe_exports->AddressOfNameOrdinals); |
92 functions=function=(unsigned long*) RVA(pe_exports->AddressOfFunctions); | |
93 name=(unsigned char**) RVA(pe_exports->AddressOfNames); | |
1 | 94 |
95 TRACE(" Ord RVA Addr Name\n" ); | |
96 for (i=0;i<pe_exports->NumberOfFunctions;i++, function++) | |
97 { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
98 if (!*function) continue; |
1 | 99 if (TRACE_ON(win32)) |
100 { | |
25870
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
101 dbg_printf( "%4ld %08lx %p", i + pe_exports->Base, *function, RVA(*function) ); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
102 |
1 | 103 for (j = 0; j < pe_exports->NumberOfNames; j++) |
104 if (ordinal[j] == i) | |
105 { | |
25870
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
106 dbg_printf( " %s", (char*)RVA(name[j]) ); |
1 | 107 break; |
108 } | |
109 if ((*function >= rva_start) && (*function <= rva_end)) | |
25870
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
110 dbg_printf(" (forwarded -> %s)", (char *)RVA(*function)); |
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
111 dbg_printf("\n"); |
1 | 112 } |
113 } | |
114 } | |
115 | |
116 /* Look up the specified function or ordinal in the exportlist: | |
117 * If it is a string: | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
118 * - look up the name in the Name list. |
1 | 119 * - look up the ordinal with that index. |
120 * - use the ordinal as offset into the functionlist | |
121 * If it is a ordinal: | |
122 * - use ordinal-pe_export->Base as offset into the functionlist | |
123 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
124 FARPROC PE_FindExportedFunction( |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
125 WINE_MODREF *wm, |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
126 LPCSTR funcName, |
1 | 127 WIN_BOOL snoop ) |
128 { | |
28162 | 129 unsigned short * ordinals; |
130 unsigned long * function; | |
131 unsigned char ** name; | |
7386 | 132 const char *ename = NULL; |
1 | 133 int i, ordinal; |
134 PE_MODREF *pem = &(wm->binfmt.pe); | |
135 IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export; | |
136 unsigned int load_addr = wm->module; | |
28162 | 137 unsigned long rva_start, rva_end, addr; |
1 | 138 char * forward; |
139 | |
140 if (HIWORD(funcName)) | |
141 TRACE("(%s)\n",funcName); | |
142 else | |
143 TRACE("(%d)\n",(int)funcName); | |
144 if (!exports) { | |
145 /* Not a fatal problem, some apps do | |
146 * GetProcAddress(0,"RegisterPenApp") which triggers this | |
147 * case. | |
148 */ | |
149 WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem); | |
150 return NULL; | |
151 } | |
28162 | 152 ordinals= (unsigned short*) RVA(exports->AddressOfNameOrdinals); |
153 function= (unsigned long*) RVA(exports->AddressOfFunctions); | |
154 name = (unsigned char **) RVA(exports->AddressOfNames); | |
1 | 155 forward = NULL; |
156 rva_start = PE_HEADER(wm->module)->OptionalHeader | |
157 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | |
158 rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader | |
159 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; | |
160 | |
161 if (HIWORD(funcName)) | |
162 { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
163 |
1 | 164 int min = 0, max = exports->NumberOfNames - 1; |
165 while (min <= max) | |
166 { | |
167 int res, pos = (min + max) / 2; | |
7386 | 168 ename = (const char*) RVA(name[pos]); |
169 if (!(res = strcmp( ename, funcName ))) | |
1 | 170 { |
171 ordinal = ordinals[pos]; | |
172 goto found; | |
173 } | |
174 if (res > 0) max = pos - 1; | |
175 else min = pos + 1; | |
176 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
177 |
7386 | 178 for (i = 0; i < exports->NumberOfNames; i++) |
1 | 179 { |
7386 | 180 ename = (const char*) RVA(name[i]); |
1 | 181 if (!strcmp( ename, funcName )) |
182 { | |
2069 | 183 ERR( "%s.%s required a linear search\n", wm->modname, funcName ); |
1 | 184 ordinal = ordinals[i]; |
185 goto found; | |
186 } | |
187 } | |
188 return NULL; | |
189 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
190 else |
1 | 191 { |
192 ordinal = LOWORD(funcName) - exports->Base; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
193 if (snoop && name) |
1 | 194 { |
195 for (i = 0; i < exports->NumberOfNames; i++) | |
196 if (ordinals[i] == ordinal) | |
197 { | |
198 ename = RVA(name[i]); | |
199 break; | |
200 } | |
201 } | |
202 } | |
203 | |
204 found: | |
205 if (ordinal >= exports->NumberOfFunctions) | |
206 { | |
207 TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base ); | |
208 return NULL; | |
209 } | |
210 addr = function[ordinal]; | |
211 if (!addr) return NULL; | |
212 if ((addr < rva_start) || (addr >= rva_end)) | |
213 { | |
214 FARPROC proc = RVA(addr); | |
215 if (snoop) | |
216 { | |
217 if (!ename) ename = "@"; | |
218 // proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc); | |
219 TRACE("SNOOP_GetProcAddress n/a\n"); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
220 |
1 | 221 } |
222 return proc; | |
223 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
224 else |
1 | 225 { |
226 WINE_MODREF *wm; | |
227 char *forward = RVA(addr); | |
228 char module[256]; | |
229 char *end = strchr(forward, '.'); | |
230 | |
231 if (!end) return NULL; | |
232 if (end - forward >= sizeof(module)) return NULL; | |
233 memcpy( module, forward, end - forward ); | |
234 module[end-forward] = 0; | |
235 if (!(wm = MODULE_FindModule( module ))) | |
236 { | |
237 ERR("module not found for forward '%s'\n", forward ); | |
238 return NULL; | |
239 } | |
240 return MODULE_GetProcAddress( wm->module, end + 1, snoop ); | |
241 } | |
242 } | |
243 | |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
244 static DWORD fixup_imports( WINE_MODREF *wm ) |
1 | 245 { |
246 IMAGE_IMPORT_DESCRIPTOR *pe_imp; | |
247 PE_MODREF *pem; | |
248 unsigned int load_addr = wm->module; | |
249 int i,characteristics_detection=1; | |
250 char *modname; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
251 |
1 | 252 assert(wm->type==MODULE32_PE); |
253 pem = &(wm->binfmt.pe); | |
254 if (pem->pe_export) | |
255 modname = (char*) RVA(pem->pe_export->Name); | |
256 else | |
257 modname = "<unknown>"; | |
258 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
259 |
1 | 260 TRACE("Dumping imports list\n"); |
261 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
262 |
1 | 263 pe_imp = pem->pe_import; |
264 if (!pe_imp) return 0; | |
265 | |
266 /* We assume that we have at least one import with !0 characteristics and | |
267 * detect broken imports with all characteristsics 0 (notably Borland) and | |
268 * switch the detection off for them. | |
269 */ | |
270 for (i = 0; pe_imp->Name ; pe_imp++) { | |
271 if (!i && !pe_imp->u.Characteristics) | |
272 characteristics_detection = 0; | |
273 if (characteristics_detection && !pe_imp->u.Characteristics) | |
274 break; | |
275 i++; | |
276 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
277 if (!i) return 0; |
1 | 278 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
279 |
1 | 280 wm->nDeps = i; |
281 wm->deps = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) ); | |
282 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
283 /* load the imported modules. They are automatically |
1 | 284 * added to the modref list of the process. |
285 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
286 |
1 | 287 for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) { |
288 IMAGE_IMPORT_BY_NAME *pe_name; | |
289 PIMAGE_THUNK_DATA import_list,thunk_list; | |
290 char *name = (char *) RVA(pe_imp->Name); | |
291 | |
292 if (characteristics_detection && !pe_imp->u.Characteristics) | |
293 break; | |
294 | |
295 //#warning FIXME: here we should fill imports | |
296 TRACE("Loading imports for %s.dll\n", name); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
297 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
298 if (pe_imp->u.OriginalFirstThunk != 0) { |
1 | 299 TRACE("Microsoft style imports used\n"); |
300 import_list =(PIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk); | |
301 thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk); | |
302 | |
303 while (import_list->u1.Ordinal) { | |
304 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) { | |
305 int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal); | |
306 | |
307 // TRACE("--- Ordinal %s,%d\n", name, ordinal); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
308 |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
309 thunk_list->u1.Function=LookupExternal(name, ordinal); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
310 } else { |
1 | 311 pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData); |
312 // TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint); | |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
313 thunk_list->u1.Function=LookupExternalByName(name, pe_name->Name); |
1 | 314 } |
315 import_list++; | |
316 thunk_list++; | |
317 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
318 } else { |
1 | 319 TRACE("Borland style imports used\n"); |
320 thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk); | |
321 while (thunk_list->u1.Ordinal) { | |
322 if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
323 |
1 | 324 int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal); |
325 | |
326 TRACE("--- Ordinal %s.%d\n",name,ordinal); | |
327 thunk_list->u1.Function=LookupExternal( | |
328 name, ordinal); | |
329 } else { | |
330 pe_name=(PIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData); | |
331 TRACE("--- %s %s.%d\n", | |
332 pe_name->Name,name,pe_name->Hint); | |
333 thunk_list->u1.Function=LookupExternalByName( | |
334 name, pe_name->Name); | |
335 } | |
336 thunk_list++; | |
337 } | |
338 } | |
339 } | |
340 return 0; | |
341 } | |
342 | |
343 static int calc_vma_size( HMODULE hModule ) | |
344 { | |
345 int i,vma_size = 0; | |
346 IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(hModule); | |
347 | |
348 TRACE("Dump of segment table\n"); | |
349 TRACE(" Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n"); | |
350 for (i = 0; i< PE_HEADER(hModule)->FileHeader.NumberOfSections; i++) | |
351 { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
352 TRACE("%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n", |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
353 pe_seg->Name, |
1 | 354 pe_seg->Misc.VirtualSize, |
355 pe_seg->VirtualAddress, | |
356 pe_seg->SizeOfRawData, | |
357 pe_seg->PointerToRawData, | |
358 pe_seg->PointerToRelocations, | |
359 pe_seg->PointerToLinenumbers, | |
360 pe_seg->NumberOfRelocations, | |
361 pe_seg->NumberOfLinenumbers, | |
362 pe_seg->Characteristics); | |
363 vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->SizeOfRawData); | |
364 vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->Misc.VirtualSize); | |
365 pe_seg++; | |
366 } | |
367 return vma_size; | |
368 } | |
369 | |
370 static void do_relocations( unsigned int load_addr, IMAGE_BASE_RELOCATION *r ) | |
371 { | |
372 int delta = load_addr - PE_HEADER(load_addr)->OptionalHeader.ImageBase; | |
373 int hdelta = (delta >> 16) & 0xFFFF; | |
374 int ldelta = delta & 0xFFFF; | |
375 | |
376 if(delta == 0) | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
377 |
1 | 378 return; |
379 while(r->VirtualAddress) | |
380 { | |
381 char *page = (char*) RVA(r->VirtualAddress); | |
382 int count = (r->SizeOfBlock - 8)/2; | |
383 int i; | |
384 TRACE_(fixup)("%x relocations for page %lx\n", | |
385 count, r->VirtualAddress); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
386 |
1 | 387 for(i=0;i<count;i++) |
388 { | |
389 int offset = r->TypeOffset[i] & 0xFFF; | |
390 int type = r->TypeOffset[i] >> 12; | |
391 // TRACE_(fixup)("patching %x type %x\n", offset, type); | |
392 switch(type) | |
393 { | |
394 case IMAGE_REL_BASED_ABSOLUTE: break; | |
395 case IMAGE_REL_BASED_HIGH: | |
396 *(short*)(page+offset) += hdelta; | |
397 break; | |
398 case IMAGE_REL_BASED_LOW: | |
399 *(short*)(page+offset) += ldelta; | |
400 break; | |
401 case IMAGE_REL_BASED_HIGHLOW: | |
402 *(int*)(page+offset) += delta; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
403 |
1 | 404 break; |
405 case IMAGE_REL_BASED_HIGHADJ: | |
406 FIXME("Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n"); | |
407 break; | |
408 case IMAGE_REL_BASED_MIPS_JMPADDR: | |
409 FIXME("Is this a MIPS machine ???\n"); | |
410 break; | |
411 default: | |
412 FIXME("Unknown fixup type\n"); | |
413 break; | |
414 } | |
415 } | |
416 r = (IMAGE_BASE_RELOCATION*)((char*)r + r->SizeOfBlock); | |
417 } | |
418 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
419 |
1 | 420 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
421 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
422 |
1 | 423 |
424 /********************************************************************** | |
425 * PE_LoadImage | |
426 * Load one PE format DLL/EXE into memory | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
427 * |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
428 * Unluckily we can't just mmap the sections where we want them, for |
1 | 429 * (at least) Linux does only support offsets which are page-aligned. |
430 * | |
431 * BUT we have to map the whole image anyway, for Win32 programs sometimes | |
432 * want to access them. (HMODULE32 point to the start of it) | |
433 */ | |
434 HMODULE PE_LoadImage( int handle, LPCSTR filename, WORD *version ) | |
435 { | |
436 HMODULE hModule; | |
437 HANDLE mapping; | |
438 | |
439 IMAGE_NT_HEADERS *nt; | |
440 IMAGE_SECTION_HEADER *pe_sec; | |
441 IMAGE_DATA_DIRECTORY *dir; | |
24381 | 442 // BY_HANDLE_FILE_INFORMATION bhfi; |
1 | 443 int i, rawsize, lowest_va, vma_size, file_size = 0; |
444 DWORD load_addr = 0, aoep, reloc = 0; | |
445 // struct get_read_fd_request *req = get_req_buffer(); | |
446 int unix_handle = handle; | |
447 int page_size = getpagesize(); | |
448 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
449 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
450 // if ( GetFileInformationByHandle( hFile, &bhfi ) ) |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
451 // file_size = bhfi.nFileSizeLow; |
1 | 452 file_size=lseek(handle, 0, SEEK_END); |
453 lseek(handle, 0, SEEK_SET); | |
454 | |
455 //#warning fix CreateFileMappingA | |
456 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY | SEC_COMMIT, | |
457 0, 0, NULL ); | |
458 if (!mapping) | |
459 { | |
460 WARN("CreateFileMapping error %ld\n", GetLastError() ); | |
461 return 0; | |
462 } | |
463 // hModule = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); | |
464 hModule=(HMODULE)mapping; | |
465 // CloseHandle( mapping ); | |
466 if (!hModule) | |
467 { | |
468 WARN("MapViewOfFile error %ld\n", GetLastError() ); | |
469 return 0; | |
470 } | |
471 if ( *(WORD*)hModule !=IMAGE_DOS_SIGNATURE) | |
472 { | |
473 WARN("%s image doesn't have DOS signature, but 0x%04x\n", filename,*(WORD*)hModule); | |
474 goto error; | |
475 } | |
476 | |
477 nt = PE_HEADER( hModule ); | |
478 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
479 |
1 | 480 if ( nt->Signature != IMAGE_NT_SIGNATURE ) |
481 { | |
482 WARN("%s image doesn't have PE signature, but 0x%08lx\n", filename, nt->Signature ); | |
483 goto error; | |
484 } | |
485 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
486 |
1 | 487 if ( nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 ) |
488 { | |
25870
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
489 dbg_printf("Trying to load PE image for unsupported architecture ("); |
1 | 490 switch (nt->FileHeader.Machine) |
491 { | |
25870
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
492 case IMAGE_FILE_MACHINE_UNKNOWN: dbg_printf("Unknown"); break; |
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
493 case IMAGE_FILE_MACHINE_I860: dbg_printf("I860"); break; |
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
494 case IMAGE_FILE_MACHINE_R3000: dbg_printf("R3000"); break; |
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
495 case IMAGE_FILE_MACHINE_R4000: dbg_printf("R4000"); break; |
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
496 case IMAGE_FILE_MACHINE_R10000: dbg_printf("R10000"); break; |
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
497 case IMAGE_FILE_MACHINE_ALPHA: dbg_printf("Alpha"); break; |
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
498 case IMAGE_FILE_MACHINE_POWERPC: dbg_printf("PowerPC"); break; |
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
499 default: dbg_printf("Unknown-%04x", nt->FileHeader.Machine); break; |
1 | 500 } |
25870
b6fb25907033
Get rid of redundant dbg_printf redefinition. Fixes some warnings:
diego
parents:
25849
diff
changeset
|
501 dbg_printf(")\n"); |
1 | 502 goto error; |
503 } | |
504 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
505 |
1 | 506 pe_sec = PE_SECTIONS( hModule ); |
507 rawsize = 0; lowest_va = 0x10000; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
508 for (i = 0; i < nt->FileHeader.NumberOfSections; i++) |
1 | 509 { |
510 if (lowest_va > pe_sec[i].VirtualAddress) | |
511 lowest_va = pe_sec[i].VirtualAddress; | |
512 if (pe_sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) | |
513 continue; | |
514 if (pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData > rawsize) | |
515 rawsize = pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData; | |
516 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
517 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
518 |
1 | 519 if ( file_size && file_size < rawsize ) |
520 { | |
521 ERR("PE module is too small (header: %d, filesize: %d), " | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
522 "probably truncated download?\n", |
1 | 523 rawsize, file_size ); |
524 goto error; | |
525 } | |
526 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
527 |
1 | 528 aoep = nt->OptionalHeader.AddressOfEntryPoint; |
529 if (aoep && (aoep < lowest_va)) | |
530 FIXME("VIRUS WARNING: '%s' has an invalid entrypoint (0x%08lx) " | |
531 "below the first virtual address (0x%08x) " | |
532 "(possibly infected by Tchernobyl/SpaceFiller virus)!\n", | |
533 filename, aoep, lowest_va ); | |
534 | |
535 | |
536 /* FIXME: Hack! While we don't really support shared sections yet, | |
537 * this checks for those special cases where the whole DLL | |
538 * consists only of shared sections and is mapped into the | |
539 * shared address space > 2GB. In this case, we assume that | |
540 * the module got mapped at its base address. Thus we simply | |
541 * check whether the module has actually been mapped there | |
542 * and use it, if so. This is needed to get Win95 USER32.DLL | |
543 * to work (until we support shared sections properly). | |
544 */ | |
545 | |
23961 | 546 if ( nt->OptionalHeader.ImageBase & 0x80000000 && |
547 !strstr(filename, "xanlib.dll")) | |
1 | 548 { |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
549 HMODULE sharedMod = (HMODULE)nt->OptionalHeader.ImageBase; |
1 | 550 IMAGE_NT_HEADERS *sharedNt = (PIMAGE_NT_HEADERS) |
551 ( (LPBYTE)sharedMod + ((LPBYTE)nt - (LPBYTE)hModule) ); | |
552 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
553 /* Well, this check is not really comprehensive, |
1 | 554 but should be good enough for now ... */ |
555 if ( !IsBadReadPtr( (LPBYTE)sharedMod, sizeof(IMAGE_DOS_HEADER) ) | |
556 && memcmp( (LPBYTE)sharedMod, (LPBYTE)hModule, sizeof(IMAGE_DOS_HEADER) ) == 0 | |
557 && !IsBadReadPtr( sharedNt, sizeof(IMAGE_NT_HEADERS) ) | |
558 && memcmp( sharedNt, nt, sizeof(IMAGE_NT_HEADERS) ) == 0 ) | |
559 { | |
560 UnmapViewOfFile( (LPVOID)hModule ); | |
561 return sharedMod; | |
562 } | |
563 } | |
564 | |
2069 | 565 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
566 |
1 | 567 load_addr = nt->OptionalHeader.ImageBase; |
568 vma_size = calc_vma_size( hModule ); | |
569 | |
570 load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size, | |
571 MEM_RESERVE | MEM_COMMIT, | |
572 PAGE_EXECUTE_READWRITE ); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
573 if (load_addr == 0) |
1 | 574 { |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
575 |
1 | 576 FIXME("We need to perform base relocations for %s\n", filename); |
577 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BASERELOC; | |
578 if (dir->Size) | |
579 reloc = dir->VirtualAddress; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
580 else |
1 | 581 { |
582 FIXME( "FATAL: Need to relocate %s, but no relocation records present (%s). Try to run that file directly !\n", | |
583 filename, | |
584 (nt->FileHeader.Characteristics&IMAGE_FILE_RELOCS_STRIPPED)? | |
585 "stripped during link" : "unknown reason" ); | |
586 goto error; | |
587 } | |
588 | |
589 /* FIXME: If we need to relocate a system DLL (base > 2GB) we should | |
590 * really make sure that the *new* base address is also > 2GB. | |
591 * Some DLLs really check the MSB of the module handle :-/ | |
592 */ | |
593 if ( nt->OptionalHeader.ImageBase & 0x80000000 ) | |
594 ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" ); | |
595 | |
596 load_addr = (DWORD)VirtualAlloc( NULL, vma_size, | |
597 MEM_RESERVE | MEM_COMMIT, | |
598 PAGE_EXECUTE_READWRITE ); | |
599 if (!load_addr) { | |
600 FIXME_(win32)( | |
601 "FATAL: Couldn't load module %s (out of memory, %d needed)!\n", filename, vma_size); | |
602 goto error; | |
603 } | |
604 } | |
605 | |
606 TRACE("Load addr is %lx (base %lx), range %x\n", | |
607 load_addr, nt->OptionalHeader.ImageBase, vma_size ); | |
608 TRACE_(segment)("Loading %s at %lx, range %x\n", | |
609 filename, load_addr, vma_size ); | |
610 | |
611 #if 0 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
612 |
1 | 613 *(PIMAGE_DOS_HEADER)load_addr = *(PIMAGE_DOS_HEADER)hModule; |
614 *PE_HEADER( load_addr ) = *nt; | |
615 memcpy( PE_SECTIONS(load_addr), PE_SECTIONS(hModule), | |
616 sizeof(IMAGE_SECTION_HEADER) * nt->FileHeader.NumberOfSections ); | |
617 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
618 |
1 | 619 memcpy( load_addr, hModule, lowest_fa ); |
620 #endif | |
621 | |
622 if ((void*)FILE_dommap( handle, (void *)load_addr, 0, nt->OptionalHeader.SizeOfHeaders, | |
623 0, 0, PROT_EXEC | PROT_WRITE | PROT_READ, | |
624 MAP_PRIVATE | MAP_FIXED ) != (void*)load_addr) | |
625 { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
626 ERR_(win32)( "Critical Error: failed to map PE header to necessary address.\n"); |
1 | 627 goto error; |
628 } | |
629 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
630 |
1 | 631 pe_sec = PE_SECTIONS( hModule ); |
632 for (i = 0; i < nt->FileHeader.NumberOfSections; i++, pe_sec++) | |
633 { | |
634 if (!pe_sec->SizeOfRawData || !pe_sec->PointerToRawData) continue; | |
635 TRACE("%s: mmaping section %s at %p off %lx size %lx/%lx\n", | |
636 filename, pe_sec->Name, (void*)RVA(pe_sec->VirtualAddress), | |
637 pe_sec->PointerToRawData, pe_sec->SizeOfRawData, pe_sec->Misc.VirtualSize ); | |
638 if ((void*)FILE_dommap( unix_handle, (void*)RVA(pe_sec->VirtualAddress), | |
639 0, pe_sec->SizeOfRawData, 0, pe_sec->PointerToRawData, | |
640 PROT_EXEC | PROT_WRITE | PROT_READ, | |
641 MAP_PRIVATE | MAP_FIXED ) != (void*)RVA(pe_sec->VirtualAddress)) | |
642 { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
643 |
1 | 644 ERR_(win32)( "Critical Error: failed to map PE section to necessary address.\n"); |
645 goto error; | |
646 } | |
647 if ((pe_sec->SizeOfRawData < pe_sec->Misc.VirtualSize) && | |
648 (pe_sec->SizeOfRawData & (page_size-1))) | |
649 { | |
650 DWORD end = (pe_sec->SizeOfRawData & ~(page_size-1)) + page_size; | |
651 if (end > pe_sec->Misc.VirtualSize) end = pe_sec->Misc.VirtualSize; | |
652 TRACE("clearing %p - %p\n", | |
653 RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, | |
654 RVA(pe_sec->VirtualAddress) + end ); | |
655 memset( (char*)RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, 0, | |
656 end - pe_sec->SizeOfRawData ); | |
657 } | |
658 } | |
659 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
660 |
1 | 661 if ( reloc ) |
662 do_relocations( load_addr, (IMAGE_BASE_RELOCATION *)RVA(reloc) ); | |
663 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
664 |
1 | 665 *version = ( (nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 ) |
666 | (nt->OptionalHeader.MinorSubsystemVersion & 0xff); | |
667 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
668 |
1 | 669 UnmapViewOfFile( (LPVOID)hModule ); |
670 return (HMODULE)load_addr; | |
671 | |
672 error: | |
673 if (unix_handle != -1) close( unix_handle ); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
674 if (load_addr) |
128 | 675 VirtualFree( (LPVOID)load_addr, 0, MEM_RELEASE ); |
1 | 676 UnmapViewOfFile( (LPVOID)hModule ); |
677 return 0; | |
678 } | |
679 | |
680 /********************************************************************** | |
681 * PE_CreateModule | |
682 * | |
683 * Create WINE_MODREF structure for loaded HMODULE32, link it into | |
684 * process modref_list, and fixup all imports. | |
685 * | |
686 * Note: hModule must point to a correctly allocated PE image, | |
687 * with base relocations applied; the 16-bit dummy module | |
688 * associated to hModule must already exist. | |
689 * | |
690 * Note: This routine must always be called in the context of the | |
691 * process that is to own the module to be created. | |
692 */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
693 WINE_MODREF *PE_CreateModule( HMODULE hModule, |
1 | 694 LPCSTR filename, DWORD flags, WIN_BOOL builtin ) |
695 { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
696 DWORD load_addr = (DWORD)hModule; |
1 | 697 IMAGE_NT_HEADERS *nt = PE_HEADER(hModule); |
698 IMAGE_DATA_DIRECTORY *dir; | |
699 IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL; | |
700 IMAGE_EXPORT_DIRECTORY *pe_export = NULL; | |
701 IMAGE_RESOURCE_DIRECTORY *pe_resource = NULL; | |
702 WINE_MODREF *wm; | |
703 | |
704 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
705 |
1 | 706 |
707 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT; | |
708 if (dir->Size) | |
709 pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress); | |
710 | |
711 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT; | |
712 if (dir->Size) | |
713 pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(dir->VirtualAddress); | |
714 | |
715 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE; | |
716 if (dir->Size) | |
717 pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(dir->VirtualAddress); | |
718 | |
719 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION; | |
720 if (dir->Size) FIXME("Exception directory ignored\n" ); | |
721 | |
722 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY; | |
723 if (dir->Size) FIXME("Security directory ignored\n" ); | |
724 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
725 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
726 |
1 | 727 |
728 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DEBUG; | |
729 if (dir->Size) TRACE("Debug directory ignored\n" ); | |
730 | |
731 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COPYRIGHT; | |
732 if (dir->Size) FIXME("Copyright string ignored\n" ); | |
733 | |
734 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR; | |
735 if (dir->Size) FIXME("Global Pointer (MIPS) ignored\n" ); | |
736 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
737 |
1 | 738 |
739 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG; | |
740 if (dir->Size) FIXME("Load Configuration directory ignored\n" ); | |
741 | |
742 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT; | |
743 if (dir->Size) TRACE("Bound Import directory ignored\n" ); | |
744 | |
745 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT; | |
746 if (dir->Size) TRACE("Import Address Table directory ignored\n" ); | |
747 | |
748 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT; | |
749 if (dir->Size) | |
750 { | |
751 TRACE("Delayed import, stub calls LoadLibrary\n" ); | |
752 /* | |
753 * Nothing to do here. | |
754 */ | |
755 | |
756 #ifdef ImgDelayDescr | |
757 /* | |
758 * This code is useful to observe what the heck is going on. | |
759 */ | |
760 { | |
761 ImgDelayDescr *pe_delay = NULL; | |
762 pe_delay = (PImgDelayDescr)RVA(dir->VirtualAddress); | |
763 TRACE_(delayhlp)("pe_delay->grAttrs = %08x\n", pe_delay->grAttrs); | |
764 TRACE_(delayhlp)("pe_delay->szName = %s\n", pe_delay->szName); | |
765 TRACE_(delayhlp)("pe_delay->phmod = %08x\n", pe_delay->phmod); | |
766 TRACE_(delayhlp)("pe_delay->pIAT = %08x\n", pe_delay->pIAT); | |
767 TRACE_(delayhlp)("pe_delay->pINT = %08x\n", pe_delay->pINT); | |
768 TRACE_(delayhlp)("pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT); | |
769 TRACE_(delayhlp)("pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT); | |
770 TRACE_(delayhlp)("pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp); | |
771 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
772 #endif |
1 | 773 } |
774 | |
775 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR; | |
776 if (dir->Size) FIXME("Unknown directory 14 ignored\n" ); | |
777 | |
778 dir = nt->OptionalHeader.DataDirectory+15; | |
779 if (dir->Size) FIXME("Unknown directory 15 ignored\n" ); | |
780 | |
781 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
782 |
1 | 783 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
784 wm = (WINE_MODREF *)HeapAlloc( GetProcessHeap(), |
1 | 785 HEAP_ZERO_MEMORY, sizeof(*wm) ); |
786 wm->module = hModule; | |
787 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
788 if ( builtin ) |
1 | 789 wm->flags |= WINE_MODREF_INTERNAL; |
790 if ( flags & DONT_RESOLVE_DLL_REFERENCES ) | |
791 wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS; | |
792 if ( flags & LOAD_LIBRARY_AS_DATAFILE ) | |
793 wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE; | |
794 | |
795 wm->type = MODULE32_PE; | |
796 wm->binfmt.pe.pe_export = pe_export; | |
797 wm->binfmt.pe.pe_import = pe_import; | |
798 wm->binfmt.pe.pe_resource = pe_resource; | |
799 wm->binfmt.pe.tlsindex = -1; | |
800 | |
801 wm->filename = malloc(strlen(filename)+1); | |
802 strcpy(wm->filename, filename ); | |
803 wm->modname = strrchr( wm->filename, '\\' ); | |
804 if (!wm->modname) wm->modname = wm->filename; | |
805 else wm->modname++; | |
806 | |
807 if ( pe_export ) | |
808 dump_exports( hModule ); | |
809 | |
810 /* Fixup Imports */ | |
811 | |
812 if ( pe_import | |
813 && !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
814 && !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
815 && fixup_imports( wm ) ) |
1 | 816 { |
817 /* remove entry from modref chain */ | |
818 return NULL; | |
819 } | |
820 | |
821 return wm; | |
822 } | |
823 | |
824 /****************************************************************************** | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
825 * The PE Library Loader frontend. |
1 | 826 * FIXME: handle the flags. |
827 */ | |
828 WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags) | |
829 { | |
830 HMODULE hModule32; | |
831 WINE_MODREF *wm; | |
832 char filename[256]; | |
833 int hFile; | |
834 WORD version = 0; | |
835 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
836 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
837 strncpy(filename, name, sizeof(filename)); |
1 | 838 hFile=open(filename, O_RDONLY); |
839 if(hFile==-1) | |
840 return NULL; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
841 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
842 |
1 | 843 hModule32 = PE_LoadImage( hFile, filename, &version ); |
844 if (!hModule32) | |
845 { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
846 SetLastError( ERROR_OUTOFMEMORY ); |
1 | 847 return NULL; |
848 } | |
849 | |
850 if ( !(wm = PE_CreateModule( hModule32, filename, flags, FALSE )) ) | |
851 { | |
852 ERR( "can't load %s\n", filename ); | |
853 SetLastError( ERROR_OUTOFMEMORY ); | |
854 return NULL; | |
855 } | |
856 close(hFile); | |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
857 //printf("^^^^^^^^^^^^^^^^Alloc VM1 %p\n", wm); |
1 | 858 return wm; |
859 } | |
860 | |
861 | |
862 /***************************************************************************** | |
863 * PE_UnloadLibrary | |
864 * | |
865 * Unload the library unmapping the image and freeing the modref structure. | |
866 */ | |
867 void PE_UnloadLibrary(WINE_MODREF *wm) | |
868 { | |
869 TRACE(" unloading %s\n", wm->filename); | |
870 | |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
871 if (wm->filename) |
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
872 free(wm->filename); |
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
873 if (wm->short_filename) |
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
874 free(wm->short_filename); |
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
875 HeapFree( GetProcessHeap(), 0, wm->deps ); |
128 | 876 VirtualFree( (LPVOID)wm->module, 0, MEM_RELEASE ); |
1 | 877 HeapFree( GetProcessHeap(), 0, wm ); |
2651
958d10763c34
partially synced with avifile... (TODO: migrate to new registry.c and driver.c)
arpi
parents:
2069
diff
changeset
|
878 //printf("^^^^^^^^^^^^^^^^Free VM1 %p\n", wm); |
1 | 879 } |
880 | |
881 /***************************************************************************** | |
882 * Load the PE main .EXE. All other loading is done by PE_LoadLibraryExA | |
883 * FIXME: this function should use PE_LoadLibraryExA, but currently can't | |
884 * due to the PROCESS_Create stuff. | |
885 */ | |
886 | |
2069 | 887 |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
888 /* |
1411
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
889 * This is a dirty hack. |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
890 * The win32 DLLs contain an alloca routine, that first probes the soon |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
891 * to be allocated new memory *below* the current stack pointer in 4KByte |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
892 * increments. After the mem probing below the current %esp, the stack |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
893 * pointer is finally decremented to make room for the "alloca"ed memory. |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
894 * Maybe the probing code is intended to extend the stack on a windows box. |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
895 * Anyway, the linux kernel does *not* extend the stack by simply accessing |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
896 * memory below %esp; it segfaults. |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
897 * The extend_stack_for_dll_alloca() routine just preallocates a big chunk |
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
898 * of memory on the stack, for use by the DLLs alloca routine. |
13375
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
899 * Added the noinline attribute as e.g. gcc 3.2.2 inlines this function |
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
900 * in a way that breaks it. |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
901 */ |
13375
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
902 static void __attribute__((noinline)) extend_stack_for_dll_alloca(void) |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
903 { |
15566 | 904 #if !defined(__FreeBSD__) && !defined(__DragonFly__) |
13375
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
905 volatile int* mem=alloca(0x20000); |
460281609f28
force compilers not to optimize/inline extend_stack_for_dll_alloca
reimar
parents:
7386
diff
changeset
|
906 *mem=0x1234; |
2069 | 907 #endif |
1307
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
908 } |
d8c1b0b38edc
Add prototypes to wine/loader stuff, so that we can catch __stdcall function
jkeil
parents:
128
diff
changeset
|
909 |
1 | 910 /* Called if the library is loaded or freed. |
911 * NOTE: if a thread attaches a DLL, the current thread will only do | |
912 * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH | |
913 * (SDK) | |
914 */ | |
915 WIN_BOOL PE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) | |
916 { | |
917 WIN_BOOL retv = TRUE; | |
918 assert( wm->type == MODULE32_PE ); | |
919 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
920 |
1 | 921 if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) && |
922 (PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint) | |
923 ) { | |
924 DLLENTRYPROC entry ; | |
925 entry = (void*)PE_FindExportedFunction(wm, "DllMain", 0); | |
926 if(entry==NULL) | |
927 entry = (void*)RVA_PTR( wm->module,OptionalHeader.AddressOfEntryPoint ); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
928 |
1 | 929 TRACE_(relay)("CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n", |
930 entry, wm->module, type, lpReserved ); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
931 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
932 |
128 | 933 TRACE("Entering DllMain("); |
1 | 934 switch(type) |
935 { | |
936 case DLL_PROCESS_DETACH: | |
128 | 937 TRACE("DLL_PROCESS_DETACH) "); |
1 | 938 break; |
939 case DLL_PROCESS_ATTACH: | |
128 | 940 TRACE("DLL_PROCESS_ATTACH) "); |
1 | 941 break; |
942 case DLL_THREAD_DETACH: | |
128 | 943 TRACE("DLL_THREAD_DETACH) "); |
1 | 944 break; |
945 case DLL_THREAD_ATTACH: | |
128 | 946 TRACE("DLL_THREAD_ATTACH) "); |
1 | 947 break; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28162
diff
changeset
|
948 } |
128 | 949 TRACE("for %s\n", wm->filename); |
1411
db849cee5777
Pre-allocate some stack space to work around a problem with DLL alloca() code
jkeil
parents:
1307
diff
changeset
|
950 extend_stack_for_dll_alloca(); |
1 | 951 retv = entry( wm->module, type, lpReserved ); |
952 } | |
953 | |
954 return retv; | |
955 } |