Mercurial > hg > xemacs-beta
comparison src/unexnt.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 8de8e3f6228a |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* unexec for GNU Emacs on Windows NT. | |
2 Copyright (C) 1994 Free Software Foundation, Inc. | |
3 | |
4 This file is part of XEmacs. | |
5 | |
6 XEmacs is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with XEmacs; see the file COPYING. If not, write to the Free | |
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
19 02111-1307, USA. | |
20 | |
21 Geoff Voelker (voelker@cs.washington.edu) 8-12-94 */ | |
22 | |
23 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ | |
24 | |
25 /* The linkers that come with MSVC >= 4.0 merge .bss into .data and reorder | |
26 * uninitialised data so that the .data section looks like: | |
27 * | |
28 * crt0 initialised data | |
29 * emacs initialised data | |
30 * <my_edata> | |
31 * library initialised data | |
32 * <start of bss part of .data> | |
33 * emacs static uninitialised data | |
34 * library static uninitialised data | |
35 * emacs global uninitialised data | |
36 * <my_ebss> | |
37 * library global uninitialised data | |
38 * | |
39 * This means that we can't use the normal my_ebss in lastfile.c trick to | |
40 * differentiate between unitialised data that belongs to emacs and | |
41 * uninitialised data that belongs to system libraries. This is bad because | |
42 * we do want to initialise the emacs data, but we don't want to initialise | |
43 * the system library data. | |
44 * | |
45 * To solve this problem using MSVC >= 5.0 we use a pragma directive to tell | |
46 * the compiler to put emacs's data (both initialised and uninitialised) in | |
47 * a separate section in the executable, and we only dump that section. This | |
48 * means that all files that define initialized data must include config.h | |
49 * to pick up the pragma. We don't try to make any part of that section | |
50 * read-only. | |
51 * | |
52 * This pragma directive isn't supported by the MSVC 4.x compiler. Instead, | |
53 * we dump crt0 initialised data and library static uninitialised data in | |
54 * addition to the emacs data. This is wrong, but we appear to be able to | |
55 * get away with it. A proper fix might involve the introduction of a static | |
56 * version of my_ebss in lastfile.c and a new firstfile.c file. jhar */ | |
57 | |
58 #include <config.h> | |
59 #include <stdlib.h> /* _fmode */ | |
60 #include <stdio.h> | |
61 #include <fcntl.h> | |
62 #include <windows.h> | |
63 | |
64 /* From IMAGEHLP.H which is not installed by default by MSVC < 5 */ | |
65 /* The IMAGEHLP.DLL library is not distributed by default with Windows95 */ | |
66 PIMAGE_NT_HEADERS | |
67 (__stdcall * pfnCheckSumMappedFile) (LPVOID BaseAddress, DWORD FileLength, | |
68 LPDWORD HeaderSum, LPDWORD CheckSum); | |
69 | |
70 #if 0 | |
71 extern BOOL ctrl_c_handler (unsigned long type); | |
72 #endif | |
73 | |
74 #include "ntheap.h" | |
75 | |
76 /* Sync with FSF Emacs 19.34.6 note: struct file_data is now defined in ntheap.h */ | |
77 | |
78 enum { | |
79 HEAP_UNINITIALIZED = 1, | |
80 HEAP_UNLOADED, | |
81 HEAP_LOADED | |
82 }; | |
83 | |
84 /* Basically, our "initialized" flag. */ | |
85 int heap_state = HEAP_UNINITIALIZED; | |
86 | |
87 /* So we can find our heap in the file to recreate it. */ | |
88 unsigned long heap_index_in_executable = UNINIT_LONG; | |
89 | |
90 void get_section_info (file_data *p_file); | |
91 void copy_executable_and_dump_data_section (file_data *, file_data *); | |
92 void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile); | |
93 | |
94 /* Cached info about the .data section in the executable. */ | |
95 PUCHAR data_start_va = UNINIT_PTR; | |
96 DWORD data_start_file = UNINIT_LONG; | |
97 DWORD data_size = UNINIT_LONG; | |
98 | |
99 /* Cached info about the .bss section in the executable. */ | |
100 PUCHAR bss_start = UNINIT_PTR; | |
101 DWORD bss_size = UNINIT_LONG; | |
102 | |
103 #ifdef HAVE_NTGUI | |
104 HINSTANCE hinst = NULL; | |
105 HINSTANCE hprevinst = NULL; | |
106 LPSTR lpCmdLine = ""; | |
107 int nCmdShow = 0; | |
108 #endif /* HAVE_NTGUI */ | |
109 | |
110 /* Startup code for running on NT. When we are running as the dumped | |
111 version, we need to bootstrap our heap and .bss section into our | |
112 address space before we can actually hand off control to the startup | |
113 code supplied by NT (primarily because that code relies upon malloc ()). */ | |
114 void | |
115 _start (void) | |
116 { | |
117 char * p; | |
118 extern void mainCRTStartup (void); | |
119 | |
120 /* Cache system info, e.g., the NT page size. */ | |
121 cache_system_info (); | |
122 | |
123 /* If we're a dumped version of emacs then we need to recreate | |
124 our heap and play tricks with our .bss section. Do this before | |
125 start up. (WARNING: Do not put any code before this section | |
126 that relies upon malloc () and runs in the dumped version. It | |
127 won't work.) */ | |
128 if (heap_state == HEAP_UNLOADED) | |
129 { | |
130 char executable_path[MAX_PATH]; | |
131 | |
132 if (GetModuleFileName (NULL, executable_path, MAX_PATH) == 0) | |
133 { | |
134 exit (1); | |
135 } | |
136 | |
137 /* To allow profiling, make sure executable_path names the .exe | |
138 file, not the file created by the profiler */ | |
139 p = strrchr (executable_path, '\\'); | |
140 strcpy (p+1, PATH_PROGNAME ".exe"); | |
141 | |
142 recreate_heap (executable_path); | |
143 heap_state = HEAP_LOADED; | |
144 } | |
145 | |
146 /* The default behavior is to treat files as binary and patch up | |
147 text files appropriately, in accordance with the MSDOS code. */ | |
148 _fmode = O_BINARY; | |
149 | |
150 #if 0 | |
151 /* This prevents ctrl-c's in shells running while we're suspended from | |
152 having us exit. */ | |
153 SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE); | |
154 #endif | |
155 | |
156 /* Invoke the NT CRT startup routine now that our housecleaning | |
157 is finished. */ | |
158 #ifdef HAVE_NTGUI | |
159 /* determine WinMain args like crt0.c does */ | |
160 hinst = GetModuleHandle(NULL); | |
161 lpCmdLine = GetCommandLine(); | |
162 nCmdShow = SW_SHOWDEFAULT; | |
163 #endif | |
164 mainCRTStartup (); | |
165 } | |
166 | |
167 /* Dump out .data and .bss sections into a new executable. */ | |
168 void | |
169 unexec (char *new_name, char *old_name, void *start_data, void *start_bss, | |
170 void *entry_address) | |
171 { | |
172 file_data in_file, out_file; | |
173 char out_filename[MAX_PATH], in_filename[MAX_PATH]; | |
174 unsigned long size; | |
175 char *ptr; | |
176 HANDLE hImagehelp; | |
177 | |
178 /* Make sure that the input and output filenames have the | |
179 ".exe" extension...patch them up if they don't. */ | |
180 strcpy (in_filename, old_name); | |
181 ptr = in_filename + strlen (in_filename) - 4; | |
182 if (strcmp (ptr, ".exe")) | |
183 strcat (in_filename, ".exe"); | |
184 | |
185 strcpy (out_filename, new_name); | |
186 ptr = out_filename + strlen (out_filename) - 4; | |
187 if (strcmp (ptr, ".exe")) | |
188 strcat (out_filename, ".exe"); | |
189 | |
190 printf ("Dumping from %s\n", in_filename); | |
191 printf (" to %s\n", out_filename); | |
192 | |
193 /* We need to round off our heap to NT's allocation unit (64KB). */ | |
194 round_heap (get_allocation_unit ()); | |
195 | |
196 /* Open the undumped executable file. */ | |
197 if (!open_input_file (&in_file, in_filename)) | |
198 { | |
199 printf ("Failed to open %s (%d)...bailing.\n", | |
200 in_filename, GetLastError ()); | |
201 exit (1); | |
202 } | |
203 | |
204 /* Get the interesting section info, like start and size of .bss... */ | |
205 get_section_info (&in_file); | |
206 | |
207 /* The size of the dumped executable is the size of the original | |
208 executable plus the size of the heap and the size of the .bss section. */ | |
209 heap_index_in_executable = (unsigned long) | |
210 round_to_next ((unsigned char *) in_file.size, get_allocation_unit ()); | |
211 size = heap_index_in_executable + get_committed_heap_size () + bss_size; | |
212 if (!open_output_file (&out_file, out_filename, size)) | |
213 { | |
214 printf ("Failed to open %s (%d)...bailing.\n", | |
215 out_filename, GetLastError ()); | |
216 exit (1); | |
217 } | |
218 | |
219 /* Set the flag (before dumping). */ | |
220 heap_state = HEAP_UNLOADED; | |
221 | |
222 copy_executable_and_dump_data_section (&in_file, &out_file); | |
223 dump_bss_and_heap (&in_file, &out_file); | |
224 | |
225 /* Patch up header fields; profiler is picky about this. */ | |
226 hImagehelp = LoadLibrary ("imagehlp.dll"); | |
227 if (hImagehelp) | |
228 { | |
229 PIMAGE_DOS_HEADER dos_header; | |
230 PIMAGE_NT_HEADERS nt_header; | |
231 DWORD headersum; | |
232 DWORD checksum; | |
233 | |
234 dos_header = (PIMAGE_DOS_HEADER) out_file.file_base; | |
235 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew); | |
236 | |
237 nt_header->OptionalHeader.CheckSum = 0; | |
238 // nt_header->FileHeader.TimeDateStamp = time (NULL); | |
239 // dos_header->e_cp = size / 512; | |
240 // nt_header->OptionalHeader.SizeOfImage = size; | |
241 | |
242 pfnCheckSumMappedFile = (void *) GetProcAddress (hImagehelp, "CheckSumMappedFile"); | |
243 if (pfnCheckSumMappedFile) | |
244 { | |
245 // nt_header->FileHeader.TimeDateStamp = time (NULL); | |
246 pfnCheckSumMappedFile (out_file.file_base, | |
247 out_file.size, | |
248 &headersum, | |
249 &checksum); | |
250 nt_header->OptionalHeader.CheckSum = checksum; | |
251 } | |
252 FreeLibrary (hImagehelp); | |
253 } | |
254 | |
255 close_file_data (&in_file); | |
256 close_file_data (&out_file); | |
257 } | |
258 | |
259 | |
260 /* File handling. */ | |
261 | |
262 | |
263 int | |
264 open_output_file (file_data *p_file, CONST char *filename, unsigned long size) | |
265 { | |
266 HANDLE file; | |
267 HANDLE file_mapping; | |
268 void *file_base; | |
269 | |
270 file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, | |
271 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); | |
272 if (file == INVALID_HANDLE_VALUE) | |
273 return FALSE; | |
274 | |
275 file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE, | |
276 0, size, NULL); | |
277 if (!file_mapping) | |
278 return FALSE; | |
279 | |
280 file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size); | |
281 if (file_base == 0) | |
282 return FALSE; | |
283 | |
284 p_file->name = filename; | |
285 p_file->size = size; | |
286 p_file->file = file; | |
287 p_file->file_mapping = file_mapping; | |
288 p_file->file_base = file_base; | |
289 | |
290 return TRUE; | |
291 } | |
292 | |
293 /* Routines to manipulate NT executable file sections. */ | |
294 | |
295 #ifndef DUMP_SEPARATE_SECTION | |
296 static void | |
297 get_bss_info_from_map_file (file_data *p_infile, PUCHAR *p_bss_start, | |
298 DWORD *p_bss_size) | |
299 { | |
300 int n, start, len; | |
301 char map_filename[MAX_PATH]; | |
302 char buffer[256]; | |
303 FILE *map; | |
304 | |
305 /* Overwrite the .exe extension on the executable file name with | |
306 the .map extension. */ | |
307 strcpy (map_filename, p_infile->name); | |
308 n = strlen (map_filename) - 3; | |
309 strcpy (&map_filename[n], "map"); | |
310 | |
311 map = fopen (map_filename, "r"); | |
312 if (!map) | |
313 { | |
314 printf ("Failed to open map file %s, error %d...bailing out.\n", | |
315 map_filename, GetLastError ()); | |
316 exit (-1); | |
317 } | |
318 | |
319 while (fgets (buffer, sizeof (buffer), map)) | |
320 { | |
321 if (!(strstr (buffer, ".bss") && strstr (buffer, "DATA"))) | |
322 continue; | |
323 n = sscanf (buffer, " %*d:%x %x", &start, &len); | |
324 if (n != 2) | |
325 { | |
326 printf ("Failed to scan the .bss section line:\n%s", buffer); | |
327 exit (-1); | |
328 } | |
329 break; | |
330 } | |
331 *p_bss_start = (PUCHAR) start; | |
332 *p_bss_size = (DWORD) len; | |
333 } | |
334 #endif | |
335 | |
336 /* Flip through the executable and cache the info necessary for dumping. */ | |
337 static void | |
338 get_section_info (file_data *p_infile) | |
339 { | |
340 PIMAGE_DOS_HEADER dos_header; | |
341 PIMAGE_NT_HEADERS nt_header; | |
342 PIMAGE_SECTION_HEADER section, data_section; | |
343 unsigned char *ptr; | |
344 int i; | |
345 | |
346 dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base; | |
347 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | |
348 { | |
349 printf ("Unknown EXE header in %s...bailing.\n", p_infile->name); | |
350 exit (1); | |
351 } | |
352 nt_header = (PIMAGE_NT_HEADERS) (((unsigned long) dos_header) + | |
353 dos_header->e_lfanew); | |
354 if (nt_header == NULL) | |
355 { | |
356 printf ("Failed to find IMAGE_NT_HEADER in %s...bailing.\n", | |
357 p_infile->name); | |
358 exit (1); | |
359 } | |
360 | |
361 /* Check the NT header signature ... */ | |
362 if (nt_header->Signature != IMAGE_NT_SIGNATURE) | |
363 { | |
364 printf ("Invalid IMAGE_NT_SIGNATURE 0x%x in %s...bailing.\n", | |
365 nt_header->Signature, p_infile->name); | |
366 } | |
367 | |
368 /* Flip through the sections for .data and .bss ... */ | |
369 section = (PIMAGE_SECTION_HEADER) IMAGE_FIRST_SECTION (nt_header); | |
370 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) | |
371 { | |
372 #ifndef DUMP_SEPARATE_SECTION | |
373 if (!strcmp (section->Name, ".bss")) | |
374 { | |
375 extern int my_ebss; /* From lastfile.c */ | |
376 | |
377 ptr = (char *) nt_header->OptionalHeader.ImageBase + | |
378 section->VirtualAddress; | |
379 bss_start = ptr; | |
380 bss_size = (char*)&my_ebss - (char*)bss_start; | |
381 } | |
382 | |
383 if (!strcmp (section->Name, ".data")) | |
384 #else | |
385 if (!strcmp (section->Name, "xdata")) | |
386 #endif | |
387 { | |
388 extern char my_edata[]; /* From lastfile.c */ | |
389 | |
390 /* The .data section. */ | |
391 data_section = section; | |
392 ptr = (char *) nt_header->OptionalHeader.ImageBase + | |
393 section->VirtualAddress; | |
394 data_start_va = ptr; | |
395 data_start_file = section->PointerToRawData; | |
396 | |
397 #ifndef DUMP_SEPARATE_SECTION | |
398 /* Write only the part of the section that contains emacs data. */ | |
399 data_size = my_edata - data_start_va; | |
400 #else | |
401 /* Write back the full section. */ | |
402 data_size = section->SizeOfRawData; | |
403 | |
404 /* This code doesn't know how to grow the raw size of a section. */ | |
405 if (section->SizeOfRawData < section->Misc.VirtualSize) | |
406 { | |
407 printf ("The emacs data section is smaller than expected" | |
408 "...bailing.\n"); | |
409 exit (1); | |
410 } | |
411 #endif | |
412 } | |
413 section++; | |
414 } | |
415 | |
416 #ifndef DUMP_SEPARATE_SECTION | |
417 if (bss_start == UNINIT_PTR) | |
418 { | |
419 /* Starting with MSVC 4.0, the .bss section has been eliminated | |
420 and appended virtually to the end of the .data section. Our | |
421 only hint about where the .bss section starts in the address | |
422 comes from the SizeOfRawData field in the .data section | |
423 header. Unfortunately, this field is only approximate, as it | |
424 is a rounded number and is typically rounded just beyond the | |
425 start of the .bss section. To find the start and size of the | |
426 .bss section exactly, we have to peek into the map file. */ | |
427 extern int my_ebss; | |
428 | |
429 get_bss_info_from_map_file (p_infile, &ptr, &bss_size); | |
430 bss_start = ptr + nt_header->OptionalHeader.ImageBase | |
431 + data_section->VirtualAddress; | |
432 bss_size = (char*)&my_ebss - (char*)bss_start; | |
433 } | |
434 #else | |
435 bss_size = 0; | |
436 #endif | |
437 } | |
438 | |
439 | |
440 /* The dump routines. */ | |
441 | |
442 #ifdef DEBUG_XEMACS | |
443 #define DUMP_MSG(x) printf x | |
444 #else | |
445 #define DUMP_MSG(x) | |
446 #endif | |
447 | |
448 static void | |
449 copy_executable_and_dump_data_section (file_data *p_infile, | |
450 file_data *p_outfile) | |
451 { | |
452 unsigned char *data_file, *data_va; | |
453 unsigned long size, index; | |
454 | |
455 /* Get a pointer to where the raw data should go in the executable file. */ | |
456 data_file = (char *) p_outfile->file_base + data_start_file; | |
457 | |
458 /* Get a pointer to the raw data in our address space. */ | |
459 data_va = data_start_va; | |
460 | |
461 size = (DWORD) data_file - (DWORD) p_outfile->file_base; | |
462 DUMP_MSG (("Copying executable up to data section...\n")); | |
463 DUMP_MSG (("\t0x%08x Offset in input file.\n", 0)); | |
464 DUMP_MSG (("\t0x%08x Offset in output file.\n", 0)); | |
465 DUMP_MSG (("\t0x%08x Size in bytes.\n", size)); | |
466 memcpy (p_outfile->file_base, p_infile->file_base, size); | |
467 | |
468 size = data_size; | |
469 DUMP_MSG (("Dumping data section...\n")); | |
470 DUMP_MSG (("\t0x%08x Address in process.\n", data_va)); | |
471 DUMP_MSG (("\t0x%08x Offset in output file.\n", | |
472 data_file - p_outfile->file_base)); | |
473 DUMP_MSG (("\t0x%08x Size in bytes.\n", size)); | |
474 memcpy (data_file, data_va, size); | |
475 | |
476 index = (DWORD) data_file + size - (DWORD) p_outfile->file_base; | |
477 size = p_infile->size - index; | |
478 DUMP_MSG (("Copying rest of executable...\n")); | |
479 DUMP_MSG (("\t0x%08x Offset in input file.\n", index)); | |
480 DUMP_MSG (("\t0x%08x Offset in output file.\n", index)); | |
481 DUMP_MSG (("\t0x%08x Size in bytes.\n", size)); | |
482 memcpy ((char *) p_outfile->file_base + index, | |
483 (char *) p_infile->file_base + index, size); | |
484 } | |
485 | |
486 static void | |
487 dump_bss_and_heap (file_data *p_infile, file_data *p_outfile) | |
488 { | |
489 unsigned char *heap_data; | |
490 unsigned long size, index; | |
491 | |
492 DUMP_MSG (("Dumping heap onto end of executable...\n")); | |
493 | |
494 index = heap_index_in_executable; | |
495 size = get_committed_heap_size (); | |
496 heap_data = get_heap_start (); | |
497 | |
498 DUMP_MSG (("\t0x%08x Heap start in process.\n", heap_data)); | |
499 DUMP_MSG (("\t0x%08x Heap offset in executable.\n", index)); | |
500 DUMP_MSG (("\t0x%08x Heap size in bytes.\n", size)); | |
501 | |
502 memcpy ((PUCHAR) p_outfile->file_base + index, heap_data, size); | |
503 | |
504 #ifndef DUMP_SEPARATE_SECTION | |
505 DUMP_MSG (("Dumping bss onto end of executable...\n")); | |
506 | |
507 index += size; | |
508 size = bss_size; | |
509 | |
510 DUMP_MSG (("\t0x%08x BSS start in process.\n", bss_start)); | |
511 DUMP_MSG (("\t0x%08x BSS offset in executable.\n", index)); | |
512 DUMP_MSG (("\t0x%08x BSS size in bytes.\n", size)); | |
513 memcpy ((char *) p_outfile->file_base + index, bss_start, size); | |
514 #endif | |
515 } | |
516 | |
517 #undef DUMP_MSG | |
518 | |
519 /* Reload and remap routines. */ | |
520 | |
521 | |
522 /* Load the dumped .bss section into the .bss area of our address space. */ | |
523 /* Already done if the .bss was part of a separate emacs data section */ | |
524 void | |
525 read_in_bss (char *filename) | |
526 { | |
527 #ifndef DUMP_SEPARATE_SECTION | |
528 HANDLE file; | |
529 unsigned long index, n_read; | |
530 | |
531 file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL, | |
532 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |
533 if (file == INVALID_HANDLE_VALUE) | |
534 abort (); | |
535 | |
536 /* Seek to where the .bss section is tucked away after the heap... */ | |
537 index = heap_index_in_executable + get_committed_heap_size (); | |
538 if (SetFilePointer (file, index, NULL, FILE_BEGIN) == 0xFFFFFFFF) | |
539 abort (); | |
540 | |
541 /* Ok, read in the saved .bss section and initialize all | |
542 uninitialized variables. */ | |
543 if (!ReadFile (file, bss_start, bss_size, &n_read, NULL)) | |
544 abort (); | |
545 | |
546 CloseHandle (file); | |
547 #endif | |
548 } | |
549 | |
550 /* Map the heap dumped into the executable file into our address space. */ | |
551 void | |
552 map_in_heap (char *filename) | |
553 { | |
554 HANDLE file; | |
555 HANDLE file_mapping; | |
556 void *file_base; | |
557 unsigned long size, upper_size, n_read; | |
558 | |
559 file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL, | |
560 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |
561 if (file == INVALID_HANDLE_VALUE) | |
562 abort (); | |
563 | |
564 size = GetFileSize (file, &upper_size); | |
565 file_mapping = CreateFileMapping (file, NULL, PAGE_WRITECOPY, | |
566 0, size, NULL); | |
567 if (!file_mapping) | |
568 abort (); | |
569 | |
570 size = get_committed_heap_size (); | |
571 file_base = MapViewOfFileEx (file_mapping, FILE_MAP_COPY, 0, | |
572 heap_index_in_executable, size, | |
573 get_heap_start ()); | |
574 if (file_base != 0) | |
575 { | |
576 return; | |
577 } | |
578 | |
579 /* If we don't succeed with the mapping, then copy from the | |
580 data into the heap. */ | |
581 | |
582 CloseHandle (file_mapping); | |
583 | |
584 if (VirtualAlloc (get_heap_start (), get_committed_heap_size (), | |
585 MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) == NULL) | |
586 abort (); | |
587 | |
588 /* Seek to the location of the heap data in the executable. */ | |
589 if (SetFilePointer (file, heap_index_in_executable, | |
590 NULL, FILE_BEGIN) == 0xFFFFFFFF) | |
591 abort (); | |
592 | |
593 /* Read in the data. */ | |
594 if (!ReadFile (file, get_heap_start (), | |
595 get_committed_heap_size (), &n_read, NULL)) | |
596 abort (); | |
597 | |
598 CloseHandle (file); | |
599 } |