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