root/src/unexw32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. open_output_file
  2. find_section
  3. offset_to_section
  4. relocate_offset
  5. get_section_info
  6. copy_executable_and_dump_data
  7. unexec

     1 /* unexec for GNU Emacs on Windows NT.
     2    Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
     3 
     4 This file is part of GNU Emacs.
     5 
     6 GNU Emacs is free software: you can redistribute it and/or modify
     7 it under the terms of the GNU General Public License as published by
     8 the Free Software Foundation, either version 3 of the License, or (at
     9 your option) any later version.
    10 
    11 GNU Emacs is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 GNU General Public License for more details.
    15 
    16 You should have received a copy of the GNU General Public License
    17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 /*
    20    Geoff Voelker (voelker@cs.washington.edu)                         8-12-94
    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 /* Include relevant definitions from IMAGEHLP.H, which can be found
    35    in \\win32sdk\mstools\samples\image\include\imagehlp.h. */
    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 /* Cached info about the .data section in the executable.  */
    53 PIMAGE_SECTION_HEADER data_section;
    54 PCHAR  data_start = 0;
    55 DWORD_PTR  data_size = 0;
    56 
    57 /* Cached info about the .bss section in the executable.  */
    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 /* bss data that is static might be discontiguous from non-static.  */
    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 /* File handling.  */
    69 
    70 /* Implementation note: this and the next functions work with ANSI
    71    codepage encoded file names!  */
    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   /* We delete any existing FILENAME because loadup.el will create a
    81      hard link to it under the name emacs-XX.YY.ZZ.nn.exe.  Evidently,
    82      overwriting a file on Unix breaks any hard links to it, but that
    83      doesn't happen on Windows.  If we don't delete the file before
    84      creating it, all the emacs-XX.YY.ZZ.nn.exe end up being hard
    85      links to the same file, which defeats the purpose of these hard
    86      links: being able to run previous builds.  */
    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 /* Routines to manipulate NT executable file sections.  */
   113 
   114 /* Return pointer to section header for named section. */
   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   /* unused */
   133 /* Return pointer to section header for section containing the given
   134    offset in its raw data area. */
   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 /* Return offset to an object in dst, given offset in src.  We assume
   155    there is at least one section in both src and dst images, and that
   156    the some sections may have been added to dst (after sections in src).  */
   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           /* Handle offsets after the last section.  */
   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 /* Convert address in executing image to RVA.  */
   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   /* unused */
   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 /* Flip through the executable and cache the info necessary for dumping.  */
   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   /* Check the NT header signature ...  */
   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   /* Locate the ".data" and ".bss" sections for Emacs.  (Note that the
   247      actual section names are probably different from these, and might
   248      actually be the same section.)
   249 
   250      We do this as follows: first we determine the virtual address
   251      ranges in this process for the data and bss variables that we wish
   252      to preserve.  Then we map these VAs to the section entries in the
   253      source image.  Finally, we determine the new size of the raw data
   254      area for the bss section, so we can make the new image the correct
   255      size.  */
   256 
   257   /* We arrange for the Emacs initialized data to be in a separate
   258      section if possible, because we cannot rely on my_begdata and
   259      my_edata marking out the full extent of the initialized data, at
   260      least on the Alpha where the linker freely reorders variables
   261      across libraries.  If we can arrange for this, all we need to do is
   262      find the start and size of the EMDATA section.  */
   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       /* Fallback on the old method if compiler doesn't support the
   273          data_set #pragma (or its equivalent).  */
   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   /* As noted in lastfile.c, the Alpha (but not the Intel) MSVC linker
   285      globally segregates all static and public bss data (ie. across all
   286      linked modules, not just per module), so we must take both static
   287      and public bss areas into account to determine the true extent of
   288      the bss area used by Emacs.
   289 
   290      To be strictly correct, we dump the static and public bss areas
   291      used by Emacs separately if non-overlapping (since otherwise we are
   292      dumping bss data belonging to system libraries, eg. the static bss
   293      system data on the Alpha).  */
   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   /* Compute how much the .bss section's raw data will grow.  */
   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   /* Compute how much the static .bss section's raw data will grow.  */
   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   /* Combine the bss sections into one if they overlap.  */
   324 #ifdef _ALPHA_
   325   overlap = 1;                  /* force all bss data to be dumped */
   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 /* Format to print a DWORD_PTR value.  */
   355 #if defined MINGW_W64 && defined _WIN64
   356 # define pDWP  "16llx"
   357 #else
   358 # define pDWP  "08lx"
   359 #endif
   360 
   361 /* The dump routines.  */
   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     /* Zero the alignment slop; it may actually initialize real data.  */       \
   417     memset (dst, 0, newdst - dst);                                              \
   418     dst = newdst;                                                               \
   419   } while (0)
   420 
   421   /* Copy the source image sequentially, ie. section by section after
   422      copying the headers and section table, to simplify the process of
   423      dumping the raw data for the bss and heap sections.
   424 
   425      Note that dst is updated implicitly by each COPY_CHUNK.  */
   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   /* Align the first section's raw data area, and set the header size
   445      field accordingly.  */
   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       /* Windows section names are fixed 8-char strings, only
   453          zero-terminated if the name is shorter than 8 characters.  */
   454       sprintf (msg, "Copying raw data for %.8s...", section->Name);
   455 
   456       dst_save = dst;
   457 
   458       /* Update the file-relative offset for this section's raw data (if
   459          it has any) in case things have been relocated; we will update
   460          the other offsets below once we know where everything is.  */
   461       if (dst_section->PointerToRawData)
   462         dst_section->PointerToRawData = DST_TO_OFFSET ();
   463 
   464       /* Can always copy the original raw data.  */
   465       COPY_CHUNK
   466         (msg, OFFSET_TO_PTR (section->PointerToRawData, p_infile),
   467          section->SizeOfRawData, be_verbose);
   468       /* Ensure alignment slop is zeroed.  */
   469       ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
   470 
   471       /* Note that various sections below may be aliases.  */
   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           /* Dump contents of bss variables, adjusting the section's raw
   483              data size as necessary.  */
   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           /* Determine new size of raw data area.  */
   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           /* Dump contents of static bss variables, adjusting the
   499              section's raw data size as necessary.  */
   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           /* Determine new size of raw data area.  */
   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       /* Align the section's raw data area.  */
   514       ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
   515 
   516       section++;
   517       dst_section++;
   518     }
   519 
   520   /* Copy remainder of source image.  */
   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   /* Final size for new image.  */
   532   p_outfile->size = DST_TO_OFFSET ();
   533 
   534   /* Now patch up remaining file-relative offsets.  */
   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       /* Recompute data sizes for completeness.  */
   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   /* Update offsets in debug directory entries. */
   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 /* Dump out .data and .bss sections into a new executable.  */
   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   /* Ignore old_name, and get our actual location from the OS.  */
   592   if (!GetModuleFileNameA (NULL, in_filename, MAX_PATH))
   593     abort ();
   594 
   595   /* Can't use dostounix_filename here, since that needs its file name
   596      argument encoded in UTF-8.  */
   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   /* Change the base of the output filename to match the requested name.  */
   605   if ((p = strrchr (out_filename, '/')) == NULL)
   606     abort ();
   607   /* The filenames have already been expanded, and will be in Unix
   608      format, so it is safe to expect an absolute name.  */
   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   /* Make sure that the output filename has the ".exe" extension...patch
   618      it up if not.  */
   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   /* Open the undumped executable file.  */
   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   /* Get the interesting section info, like start and size of .bss...  */
   635   get_section_info (&in_file);
   636 
   637   /* The size of the dumped executable is the size of the original
   638      executable plus the size of the heap and the size of the .bss section.  */
   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   /* Patch up header fields; profiler is picky about this. */
   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 //    nt_header->FileHeader.TimeDateStamp = time (NULL);
   664 //    dos_header->e_cp = size / 512;
   665 //    nt_header->OptionalHeader.SizeOfImage = size;
   666 
   667     pfnCheckSumMappedFile = (void *) GetProcAddress (hImagehelp, "CheckSumMappedFile");
   668     if (pfnCheckSumMappedFile)
   669       {
   670 //      nt_header->FileHeader.TimeDateStamp = time (NULL);
   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 /* eof */

/* [<][>][^][v][top][bottom][index][help] */