This source file includes following definitions.
- open_output_file
- find_section
- offset_to_section
- relocate_offset
- get_section_info
- copy_executable_and_dump_data
- unexec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <config.h>
24 #include "unexec.h"
25 #include "lisp.h"
26 #include "w32common.h"
27 #include "w32.h"
28
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <time.h>
32 #include <windows.h>
33
34
35
36
37 PIMAGE_NT_HEADERS (__stdcall * pfnCheckSumMappedFile) (LPVOID BaseAddress,
38 DWORD FileLength,
39 LPDWORD HeaderSum,
40 LPDWORD CheckSum);
41
42 extern char my_begdata[];
43 extern char my_begbss[];
44 extern char *my_begbss_static;
45
46 #include "w32heap.h"
47
48 void get_section_info (file_data *p_file);
49 void copy_executable_and_dump_data (file_data *, file_data *);
50 void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile);
51
52
53 PIMAGE_SECTION_HEADER data_section;
54 PCHAR data_start = 0;
55 DWORD_PTR data_size = 0;
56
57
58 PIMAGE_SECTION_HEADER bss_section;
59 PCHAR bss_start = 0;
60 DWORD_PTR bss_size = 0;
61 DWORD_PTR extra_bss_size = 0;
62
63 PIMAGE_SECTION_HEADER bss_section_static;
64 PCHAR bss_start_static = 0;
65 DWORD_PTR bss_size_static = 0;
66 DWORD_PTR extra_bss_size_static = 0;
67
68
69
70
71
72
73 int
74 open_output_file (file_data *p_file, char *filename, unsigned long size)
75 {
76 HANDLE file;
77 HANDLE file_mapping;
78 void *file_base;
79
80
81
82
83
84
85
86
87 DeleteFileA (filename);
88 file = CreateFileA (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
89 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
90 if (file == INVALID_HANDLE_VALUE)
91 return FALSE;
92
93 file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
94 0, size, NULL);
95 if (!file_mapping)
96 return FALSE;
97
98 file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
99 if (file_base == 0)
100 return FALSE;
101
102 p_file->name = filename;
103 p_file->size = size;
104 p_file->file = file;
105 p_file->file_mapping = file_mapping;
106 p_file->file_base = file_base;
107
108 return TRUE;
109 }
110
111
112
113
114
115 IMAGE_SECTION_HEADER *
116 find_section (const char * name, IMAGE_NT_HEADERS * nt_header)
117 {
118 PIMAGE_SECTION_HEADER section;
119 int i;
120
121 section = IMAGE_FIRST_SECTION (nt_header);
122
123 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
124 {
125 if (strcmp ((char *)section->Name, name) == 0)
126 return section;
127 section++;
128 }
129 return NULL;
130 }
131
132 #if 0
133
134
135 static IMAGE_SECTION_HEADER *
136 offset_to_section (DWORD_PTR offset, IMAGE_NT_HEADERS * nt_header)
137 {
138 PIMAGE_SECTION_HEADER section;
139 int i;
140
141 section = IMAGE_FIRST_SECTION (nt_header);
142
143 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
144 {
145 if (offset >= section->PointerToRawData
146 && offset < section->PointerToRawData + section->SizeOfRawData)
147 return section;
148 section++;
149 }
150 return NULL;
151 }
152 #endif
153
154
155
156
157 static DWORD_PTR
158 relocate_offset (DWORD_PTR offset,
159 IMAGE_NT_HEADERS * src_nt_header,
160 IMAGE_NT_HEADERS * dst_nt_header)
161 {
162 PIMAGE_SECTION_HEADER src_section = IMAGE_FIRST_SECTION (src_nt_header);
163 PIMAGE_SECTION_HEADER dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
164 int i = 0;
165
166 while (offset >= src_section->PointerToRawData)
167 {
168 if (offset < src_section->PointerToRawData + src_section->SizeOfRawData)
169 break;
170 i++;
171 if (i == src_nt_header->FileHeader.NumberOfSections)
172 {
173
174 dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
175 dst_section += dst_nt_header->FileHeader.NumberOfSections - 1;
176 while (dst_section->PointerToRawData == 0)
177 dst_section--;
178 while (src_section->PointerToRawData == 0)
179 src_section--;
180 return offset
181 + (dst_section->PointerToRawData + dst_section->SizeOfRawData)
182 - (src_section->PointerToRawData + src_section->SizeOfRawData);
183 }
184 src_section++;
185 dst_section++;
186 }
187 return offset +
188 (dst_section->PointerToRawData - src_section->PointerToRawData);
189 }
190
191 #define RVA_TO_OFFSET(rva, section) \
192 ((section)->PointerToRawData + ((DWORD_PTR)(rva) - (section)->VirtualAddress))
193
194 #define RVA_TO_SECTION_OFFSET(rva, section) \
195 ((DWORD_PTR)(rva) - (section)->VirtualAddress)
196
197
198 #define PTR_TO_RVA(ptr) ((DWORD_PTR)(ptr) - (DWORD_PTR) GetModuleHandle (NULL))
199
200 #define PTR_TO_OFFSET(ptr, pfile_data) \
201 ((unsigned char *)(ptr) - (pfile_data)->file_base)
202
203 #define OFFSET_TO_PTR(offset, pfile_data) \
204 ((pfile_data)->file_base + (DWORD_PTR)(offset))
205
206 #if 0
207 #define OFFSET_TO_RVA(offset, section) \
208 ((section)->VirtualAddress + ((DWORD_PTR)(offset) - (section)->PointerToRawData))
209
210 #define RVA_TO_PTR(var,section,filedata) \
211 ((unsigned char *)(RVA_TO_OFFSET (var,section) + (filedata).file_base))
212 #endif
213
214
215
216 void
217 get_section_info (file_data *p_infile)
218 {
219 PIMAGE_DOS_HEADER dos_header;
220 PIMAGE_NT_HEADERS nt_header;
221 int overlap;
222
223 dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
224 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
225 {
226 printf ("Unknown EXE header in %s...bailing.\n", p_infile->name);
227 exit (1);
228 }
229 nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
230 dos_header->e_lfanew);
231 if (nt_header == NULL)
232 {
233 printf ("Failed to find IMAGE_NT_HEADER in %s...bailing.\n",
234 p_infile->name);
235 exit (1);
236 }
237
238
239 if (nt_header->Signature != IMAGE_NT_SIGNATURE)
240 {
241 printf ("Invalid IMAGE_NT_SIGNATURE 0x%lx in %s...bailing.\n",
242 nt_header->Signature, p_infile->name);
243 exit (1);
244 }
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263 data_section = find_section ("EMDATA", nt_header);
264 if (data_section)
265 {
266 data_start = (char *) nt_header->OptionalHeader.ImageBase +
267 data_section->VirtualAddress;
268 data_size = data_section->Misc.VirtualSize;
269 }
270 else
271 {
272
273
274 data_start = my_begdata;
275 data_size = my_edata - my_begdata;
276 data_section = rva_to_section (PTR_TO_RVA (my_begdata), nt_header);
277 if (data_section != rva_to_section (PTR_TO_RVA (my_edata), nt_header))
278 {
279 printf ("Initialized data is not in a single section...bailing\n");
280 exit (1);
281 }
282 }
283
284
285
286
287
288
289
290
291
292
293
294
295 bss_start = my_begbss;
296 bss_size = my_endbss - my_begbss;
297 bss_section = rva_to_section (PTR_TO_RVA (my_begbss), nt_header);
298 if (bss_section != rva_to_section (PTR_TO_RVA (my_endbss), nt_header))
299 {
300 printf ("Uninitialized data is not in a single section...bailing\n");
301 exit (1);
302 }
303
304 extra_bss_size =
305 ROUND_UP (RVA_TO_SECTION_OFFSET (PTR_TO_RVA (my_endbss), bss_section),
306 nt_header->OptionalHeader.FileAlignment)
307 - bss_section->SizeOfRawData;
308
309 bss_start_static = my_begbss_static;
310 bss_size_static = my_endbss_static - my_begbss_static;
311 bss_section_static = rva_to_section (PTR_TO_RVA (my_begbss_static), nt_header);
312 if (bss_section_static != rva_to_section (PTR_TO_RVA (my_endbss_static), nt_header))
313 {
314 printf ("Uninitialized static data is not in a single section...bailing\n");
315 exit (1);
316 }
317
318 extra_bss_size_static =
319 ROUND_UP (RVA_TO_SECTION_OFFSET (PTR_TO_RVA (my_endbss_static), bss_section_static),
320 nt_header->OptionalHeader.FileAlignment)
321 - bss_section_static->SizeOfRawData;
322
323
324 #ifdef _ALPHA_
325 overlap = 1;
326 #else
327 overlap = 0;
328 #endif
329 if (bss_start < bss_start_static)
330 {
331 if (bss_start_static < bss_start + bss_size)
332 overlap = 1;
333 }
334 else
335 {
336 if (bss_start < bss_start_static + bss_size_static)
337 overlap = 1;
338 }
339 if (overlap)
340 {
341 if (bss_section != bss_section_static)
342 {
343 printf ("BSS data not in a single section...bailing\n");
344 exit (1);
345 }
346 bss_start = min (bss_start, bss_start_static);
347 bss_size = max (my_endbss, my_endbss_static) - bss_start;
348 bss_section_static = 0;
349 extra_bss_size = max (extra_bss_size, extra_bss_size_static);
350 extra_bss_size_static = 0;
351 }
352 }
353
354
355 #if defined MINGW_W64 && defined _WIN64
356 # define pDWP "16llx"
357 #else
358 # define pDWP "08lx"
359 #endif
360
361
362
363 void
364 copy_executable_and_dump_data (file_data *p_infile,
365 file_data *p_outfile)
366 {
367 unsigned char *dst, *dst_save;
368 PIMAGE_DOS_HEADER dos_header;
369 PIMAGE_NT_HEADERS nt_header;
370 PIMAGE_NT_HEADERS dst_nt_header;
371 PIMAGE_SECTION_HEADER section;
372 PIMAGE_SECTION_HEADER dst_section;
373 DWORD_PTR offset;
374 int i;
375 int be_verbose = GetEnvironmentVariable ("DEBUG_DUMP", NULL, 0) > 0;
376
377 #define COPY_CHUNK(message, src, size, verbose) \
378 do { \
379 unsigned char *s = (void *)(src); \
380 DWORD_PTR count = (size); \
381 if (verbose) \
382 { \
383 printf ("%s\n", (message)); \
384 printf ("\t0x%"pDWP" Offset in input file.\n", (DWORD_PTR)(s - p_infile->file_base)); \
385 printf ("\t0x%"pDWP" Offset in output file.\n", (DWORD_PTR)(dst - p_outfile->file_base)); \
386 printf ("\t0x%"pDWP" Size in bytes.\n", count); \
387 } \
388 memcpy (dst, s, count); \
389 dst += count; \
390 } while (0)
391
392 #define COPY_PROC_CHUNK(message, src, size, verbose) \
393 do { \
394 unsigned char *s = (void *)(src); \
395 DWORD_PTR count = (size); \
396 if (verbose) \
397 { \
398 printf ("%s\n", (message)); \
399 printf ("\t0x%p Address in process.\n", s); \
400 printf ("\t0x%p Base output file.\n", p_outfile->file_base); \
401 printf ("\t0x%"pDWP" Offset in output file.\n", (DWORD_PTR)(dst - p_outfile->file_base)); \
402 printf ("\t0x%p Address in output file.\n", dst); \
403 printf ("\t0x%"pDWP" Size in bytes.\n", count); \
404 } \
405 memcpy (dst, s, count); \
406 dst += count; \
407 } while (0)
408
409 #define DST_TO_OFFSET() PTR_TO_OFFSET (dst, p_outfile)
410 #define ROUND_UP_DST(align) \
411 (dst = p_outfile->file_base + ROUND_UP (DST_TO_OFFSET (), (align)))
412 #define ROUND_UP_DST_AND_ZERO(align) \
413 do { \
414 unsigned char *newdst = p_outfile->file_base \
415 + ROUND_UP (DST_TO_OFFSET (), (align)); \
416 \
417 memset (dst, 0, newdst - dst); \
418 dst = newdst; \
419 } while (0)
420
421
422
423
424
425
426
427 dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
428 nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
429 dos_header->e_lfanew);
430 section = IMAGE_FIRST_SECTION (nt_header);
431
432 dst = (unsigned char *) p_outfile->file_base;
433
434 COPY_CHUNK ("Copying DOS header...", dos_header,
435 (DWORD_PTR) nt_header - (DWORD_PTR) dos_header, be_verbose);
436 dst_nt_header = (PIMAGE_NT_HEADERS) dst;
437 COPY_CHUNK ("Copying NT header...", nt_header,
438 (DWORD_PTR) section - (DWORD_PTR) nt_header, be_verbose);
439 dst_section = (PIMAGE_SECTION_HEADER) dst;
440 COPY_CHUNK ("Copying section table...", section,
441 nt_header->FileHeader.NumberOfSections * sizeof (*section),
442 be_verbose);
443
444
445
446 ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
447 dst_nt_header->OptionalHeader.SizeOfHeaders = DST_TO_OFFSET ();
448
449 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
450 {
451 char msg[100];
452
453
454 sprintf (msg, "Copying raw data for %.8s...", section->Name);
455
456 dst_save = dst;
457
458
459
460
461 if (dst_section->PointerToRawData)
462 dst_section->PointerToRawData = DST_TO_OFFSET ();
463
464
465 COPY_CHUNK
466 (msg, OFFSET_TO_PTR (section->PointerToRawData, p_infile),
467 section->SizeOfRawData, be_verbose);
468
469 ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
470
471
472 if (section == data_section)
473 {
474 dst = dst_save
475 + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (data_start), dst_section);
476 COPY_PROC_CHUNK ("Dumping initialized data...",
477 data_start, data_size, be_verbose);
478 dst = dst_save + dst_section->SizeOfRawData;
479 }
480 if (section == bss_section)
481 {
482
483
484 dst = dst_save
485 + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (bss_start), dst_section);
486 COPY_PROC_CHUNK ("Dumping bss data...", bss_start,
487 bss_size, be_verbose);
488 ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
489 dst_section->PointerToRawData = PTR_TO_OFFSET (dst_save, p_outfile);
490
491 dst = max (dst, dst_save + dst_section->SizeOfRawData);
492 dst_section->SizeOfRawData = dst - dst_save;
493 dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;
494 dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;
495 }
496 if (section == bss_section_static)
497 {
498
499
500 dst = dst_save
501 + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (bss_start_static), dst_section);
502 COPY_PROC_CHUNK ("Dumping static bss data...", bss_start_static,
503 bss_size_static, be_verbose);
504 ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
505 dst_section->PointerToRawData = PTR_TO_OFFSET (dst_save, p_outfile);
506
507 dst = max (dst, dst_save + dst_section->SizeOfRawData);
508 dst_section->SizeOfRawData = dst - dst_save;
509 dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;
510 dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;
511 }
512
513
514 ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
515
516 section++;
517 dst_section++;
518 }
519
520
521 do
522 section--;
523 while (section->PointerToRawData == 0);
524 offset = ROUND_UP (section->PointerToRawData + section->SizeOfRawData,
525 nt_header->OptionalHeader.FileAlignment);
526 COPY_CHUNK
527 ("Copying remainder of executable...",
528 OFFSET_TO_PTR (offset, p_infile),
529 p_infile->size - offset, be_verbose);
530
531
532 p_outfile->size = DST_TO_OFFSET ();
533
534
535 section = IMAGE_FIRST_SECTION (nt_header);
536 dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
537
538 #define ADJUST_OFFSET(var) \
539 do { \
540 if ((var) != 0) \
541 (var) = relocate_offset ((var), nt_header, dst_nt_header); \
542 } while (0)
543
544 dst_nt_header->OptionalHeader.SizeOfInitializedData = 0;
545 dst_nt_header->OptionalHeader.SizeOfUninitializedData = 0;
546 for (i = 0; i < dst_nt_header->FileHeader.NumberOfSections; i++)
547 {
548
549 if (dst_section[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
550 dst_nt_header->OptionalHeader.SizeOfInitializedData +=
551 ROUND_UP (dst_section[i].Misc.VirtualSize, dst_nt_header->OptionalHeader.FileAlignment);
552 else if (dst_section[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
553 dst_nt_header->OptionalHeader.SizeOfUninitializedData +=
554 ROUND_UP (dst_section[i].Misc.VirtualSize, dst_nt_header->OptionalHeader.FileAlignment);
555
556 ADJUST_OFFSET (dst_section[i].PointerToLinenumbers);
557 }
558
559 ADJUST_OFFSET (dst_nt_header->FileHeader.PointerToSymbolTable);
560
561
562 {
563 IMAGE_DATA_DIRECTORY debug_dir =
564 dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
565 PIMAGE_DEBUG_DIRECTORY debug_entry;
566
567 section = rva_to_section (debug_dir.VirtualAddress, dst_nt_header);
568 if (section)
569 {
570 debug_entry = (PIMAGE_DEBUG_DIRECTORY)
571 (RVA_TO_OFFSET (debug_dir.VirtualAddress, section) + p_outfile->file_base);
572 debug_dir.Size /= sizeof (IMAGE_DEBUG_DIRECTORY);
573
574 for (i = 0; i < debug_dir.Size; i++, debug_entry++)
575 ADJUST_OFFSET (debug_entry->PointerToRawData);
576 }
577 }
578 }
579
580
581
582 void
583 unexec (const char *new_name, const char *old_name)
584 {
585 file_data in_file, out_file;
586 char out_filename[MAX_PATH], in_filename[MAX_PATH], new_name_a[MAX_PATH];
587 unsigned long size;
588 char *p;
589 char *q;
590
591
592 if (!GetModuleFileNameA (NULL, in_filename, MAX_PATH))
593 abort ();
594
595
596
597 for (p = in_filename; *p; p = CharNextA (p))
598 if (*p == '\\')
599 *p = '/';
600
601 strcpy (out_filename, in_filename);
602 filename_to_ansi (new_name, new_name_a);
603
604
605 if ((p = strrchr (out_filename, '/')) == NULL)
606 abort ();
607
608
609 if ((q = strrchr (new_name_a, '/')) == NULL)
610 abort ();
611 strcpy (p, q);
612
613 #ifdef ENABLE_CHECKING
614 report_temacs_memory_usage ();
615 #endif
616
617
618
619 p = out_filename + strlen (out_filename) - 4;
620 if (strcmp (p, ".exe"))
621 strcat (out_filename, ".exe");
622
623 printf ("Dumping from %s\n", in_filename);
624 printf (" to %s\n", out_filename);
625
626
627 if (!open_input_file (&in_file, in_filename))
628 {
629 printf ("Failed to open %s (%lu)...bailing.\n",
630 in_filename, GetLastError ());
631 exit (1);
632 }
633
634
635 get_section_info (&in_file);
636
637
638
639 size = in_file.size +
640 extra_bss_size +
641 extra_bss_size_static;
642 if (!open_output_file (&out_file, out_filename, size))
643 {
644 printf ("Failed to open %s (%lu)...bailing.\n",
645 out_filename, GetLastError ());
646 exit (1);
647 }
648
649 copy_executable_and_dump_data (&in_file, &out_file);
650
651
652 {
653 PIMAGE_DOS_HEADER dos_header;
654 PIMAGE_NT_HEADERS nt_header;
655 HANDLE hImagehelp = LoadLibrary ("imagehlp.dll");
656 DWORD headersum;
657 DWORD checksum;
658
659 dos_header = (PIMAGE_DOS_HEADER) out_file.file_base;
660 nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
661
662 nt_header->OptionalHeader.CheckSum = 0;
663
664
665
666
667 pfnCheckSumMappedFile = (void *) GetProcAddress (hImagehelp, "CheckSumMappedFile");
668 if (pfnCheckSumMappedFile)
669 {
670
671 pfnCheckSumMappedFile (out_file.file_base,
672 out_file.size,
673 &headersum,
674 &checksum);
675 nt_header->OptionalHeader.CheckSum = checksum;
676 }
677 FreeLibrary (hImagehelp);
678 }
679
680 close_file_data (&in_file);
681 close_file_data (&out_file);
682 }
683
684