]> git.eshelyaron.com Git - emacs.git/commitdiff
Include config.h and time.h.
authorGeoff Voelker <voelker@cs.washington.edu>
Wed, 3 Sep 1997 00:42:10 +0000 (00:42 +0000)
committerGeoff Voelker <voelker@cs.washington.edu>
Wed, 3 Sep 1997 00:42:10 +0000 (00:42 +0000)
Declare extern data and functions.
(file_data): Move definition from w32heap.c.
(_start): Add debug hook for when profiling.
Spoof executable name when using profilers.
Invoke sbrk immediately when undumped.
(unexec): Print error messages when input and output dump files
cannot be opened.
Reset header checksum.
(open_input_file, open_output_file): Return status instead of aborting.
(get_section_size): Handle different linkers.
(find_section, rva_to_section): New functions.
(get_section_info) [SEPARATE_BSS_SECTION]: Make code for using
a separate .bss section conditional.
Use my_begbss and my_endbss to determine .bss size by default.
Look for Emacs data in EMDATA section.

src/unexw32.c

index ef4ed56fb9f3d6cb6ac245b23d79acbcbfad2d4a..b1fa3e85eed40207121a0d286a5233563d709aca 100644 (file)
@@ -21,27 +21,31 @@ Boston, MA 02111-1307, USA.
    Geoff Voelker (voelker@cs.washington.edu)                         8-12-94
 */
 
+#include <config.h>
+
 #include <stdlib.h>    /* _fmode */
 #include <stdio.h>
 #include <fcntl.h>
+#include <time.h>
 #include <windows.h>
 
-extern BOOL ctrl_c_handler (unsigned long type);
+/* Include relevant definitions from IMAGEHLP.H, which can be found
+   in \\win32sdk\mstools\samples\image\include\imagehlp.h. */
 
-#include "w32heap.h"
+PIMAGE_NT_HEADERS
+(__stdcall * pfnCheckSumMappedFile) (LPVOID BaseAddress,
+                                   DWORD FileLength,
+                                   LPDWORD HeaderSum,
+                                   LPDWORD CheckSum);
 
-/* A convenient type for keeping all the info about a mapped file together.  */
-typedef struct file_data {
-    char          *name;
-    unsigned long  size;
-    HANDLE         file;
-    HANDLE         file_mapping;
-    unsigned char *file_base;
-} file_data;
+extern BOOL ctrl_c_handler (unsigned long type);
+
+extern char my_begdata[];
+extern char my_edata[];
+extern char my_begbss[];
+extern char my_endbss[];
 
-/* Force zero initialized variables to be placed in the .data segment;
-   MSVC 5.0 otherwise places them in .bss, which breaks the dumping code.  */
-#pragma data_seg(".data")
+#include "w32heap.h"
 
 /* Basically, our "initialized" flag.  */
 BOOL need_to_recreate_heap = FALSE;
@@ -49,8 +53,8 @@ BOOL need_to_recreate_heap = FALSE;
 /* So we can find our heap in the file to recreate it.  */
 unsigned long heap_index_in_executable = 0;
 
-void open_input_file (file_data *p_file, char *name);
-void open_output_file (file_data *p_file, char *name, unsigned long size);
+int open_input_file (file_data *p_file, char *name);
+int open_output_file (file_data *p_file, char *name, unsigned long size);
 void close_file_data (file_data *p_file);
 
 void get_section_info (file_data *p_file);
@@ -82,6 +86,13 @@ _start (void)
 {
   extern void mainCRTStartup (void);
 
+#if 0
+  /* Give us a way to debug problems with crashes on startup when
+     running under the MSVC profiler. */
+  if (GetEnvironmentVariable ("EMACS_DEBUG", NULL, 0) > 0)
+    DebugBreak ();
+#endif
+
   /* Cache system info, e.g., the NT page size.  */
   cache_system_info ();
 
@@ -99,9 +110,35 @@ _start (void)
          printf ("Failed to find path for executable.\n");
          exit (1);
        }
+
+#if 1
+      /* To allow profiling, make sure executable_path names the .exe
+        file, not the ._xe file created by the profiler which contains
+        extra code that makes the stored exe offsets incorrect.  (This
+        will not be necessary when unexec properly extends the .bss (or
+        .data as appropriate) section to include the dumped bss data,
+        and dumps the heap into a proper section of its own.)  */
+      {
+       char * p = strrchr (executable_path, '.');
+       if (p && p[1] == '_')
+         p[1] = 'e';
+      }
+
+      /* Using HiProf profiler, exe name is different still. */
+      {
+       char * p = strrchr (executable_path, '\\');
+       strcpy (p, "\\emacs.exe");
+      }
+#endif
+
       recreate_heap (executable_path);
       need_to_recreate_heap = FALSE;
     }
+  else
+    {
+      /* Grab our malloc arena space now, before CRT starts up. */
+      sbrk (0);
+    }
 
   /* The default behavior is to treat files as binary and patch up
      text files appropriately, in accordance with the MSDOS code.  */
@@ -151,7 +188,12 @@ unexec (char *new_name, char *old_name, void *start_data, void *start_bss,
   round_heap (get_allocation_unit ());
 
   /* Open the undumped executable file.  */
-  open_input_file (&in_file, in_filename);
+  if (!open_input_file (&in_file, in_filename))
+    {
+      printf ("Failed to open %s (%d)...bailing.\n", 
+             in_filename, GetLastError ());
+      exit (1);
+    }
 
   /* Get the interesting section info, like start and size of .bss...  */
   get_section_info (&in_file);
@@ -161,7 +203,12 @@ unexec (char *new_name, char *old_name, void *start_data, void *start_bss,
   heap_index_in_executable = (unsigned long)
     round_to_next ((unsigned char *) in_file.size, get_allocation_unit ());
   size = heap_index_in_executable + get_committed_heap_size () + bss_size;
-  open_output_file (&out_file, out_filename, size);
+  if (!open_output_file (&out_file, out_filename, size))
+    {
+      printf ("Failed to open %s (%d)...bailing.\n", 
+             out_filename, GetLastError ());
+      exit (1);
+    }
 
   /* Set the flag (before dumping).  */
   need_to_recreate_heap = TRUE;
@@ -169,6 +216,35 @@ unexec (char *new_name, char *old_name, void *start_data, void *start_bss,
   copy_executable_and_dump_data_section (&in_file, &out_file);
   dump_bss_and_heap (&in_file, &out_file);
 
+  /* Patch up header fields; profiler is picky about this. */
+  {
+    PIMAGE_DOS_HEADER dos_header;
+    PIMAGE_NT_HEADERS nt_header;
+    HANDLE hImagehelp = LoadLibrary ("imagehlp.dll");
+    DWORD  headersum;
+    DWORD  checksum;
+
+    dos_header = (PIMAGE_DOS_HEADER) out_file.file_base;
+    nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
+
+    nt_header->OptionalHeader.CheckSum = 0;
+//    nt_header->FileHeader.TimeDateStamp = time (NULL);
+//    dos_header->e_cp = size / 512;
+//    nt_header->OptionalHeader.SizeOfImage = size;
+
+    pfnCheckSumMappedFile = (void *) GetProcAddress (hImagehelp, "CheckSumMappedFile");
+    if (pfnCheckSumMappedFile)
+      {
+//     nt_header->FileHeader.TimeDateStamp = time (NULL);
+       pfnCheckSumMappedFile (out_file.file_base,
+                              out_file.size,
+                              &headersum,
+                              &checksum);
+       nt_header->OptionalHeader.CheckSum = checksum;
+      }
+    FreeLibrary (hImagehelp);
+  }
+
   close_file_data (&in_file);
   close_file_data (&out_file);
 }
@@ -177,7 +253,7 @@ unexec (char *new_name, char *old_name, void *start_data, void *start_bss,
 /* File handling.  */
 
 
-void 
+int
 open_input_file (file_data *p_file, char *filename)
 {
   HANDLE file;
@@ -188,83 +264,59 @@ open_input_file (file_data *p_file, char *filename)
   file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
                     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
   if (file == INVALID_HANDLE_VALUE) 
-      {
-       printf ("Failed to open %s (%d)...bailing.\n", 
-              filename, GetLastError ());
-       exit (1);
-      }
+    return FALSE;
 
   size = GetFileSize (file, &upper_size);
   file_mapping = CreateFileMapping (file, NULL, PAGE_READONLY, 
                                    0, size, NULL);
   if (!file_mapping) 
-    {
-      printf ("Failed to create file mapping of %s (%d)...bailing.\n",
-            filename, GetLastError ());
-      exit (1);
-    }
+    return FALSE;
 
   file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size);
   if (file_base == 0) 
-    {
-      printf ("Failed to map view of file of %s (%d)...bailing.\n",
-            filename, GetLastError ());
-      exit (1);
-    }
+    return FALSE;
 
   p_file->name = filename;
   p_file->size = size;
   p_file->file = file;
   p_file->file_mapping = file_mapping;
   p_file->file_base = file_base;
+
+  return TRUE;
 }
 
-void 
+int
 open_output_file (file_data *p_file, char *filename, unsigned long size)
 {
   HANDLE file;
   HANDLE file_mapping;
   void  *file_base;
-  int    i;
 
   file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                     CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
   if (file == INVALID_HANDLE_VALUE) 
-    {
-      i = GetLastError ();
-      printf ("open_output_file: Failed to open %s (%d).\n", 
-            filename, i);
-      exit (1);
-    }
-  
+    return FALSE;
+
   file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE, 
                                    0, size, NULL);
   if (!file_mapping) 
-    {
-      i = GetLastError ();
-      printf ("open_output_file: Failed to create file mapping of %s (%d).\n",
-            filename, i);
-      exit (1);
-    }
+    return FALSE;
   
   file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
   if (file_base == 0) 
-    {
-      i = GetLastError ();
-      printf ("open_output_file: Failed to map view of file of %s (%d).\n",
-            filename, i);
-      exit (1);
-    }
+    return FALSE;
   
   p_file->name = filename;
   p_file->size = size;
   p_file->file = file;
   p_file->file_mapping = file_mapping;
   p_file->file_base = file_base;
+
+  return TRUE;
 }
 
 /* Close the system structures associated with the given file.  */
-static void
+void
 close_file_data (file_data *p_file)
 {
     UnmapViewOfFile (p_file->file_base);
@@ -314,19 +366,54 @@ get_bss_info_from_map_file (file_data *p_infile, PUCHAR *p_bss_start,
   *p_bss_size = (DWORD) len;
 }
 
-static unsigned long
+unsigned long
 get_section_size (PIMAGE_SECTION_HEADER p_section)
 {
-  /* The section size is in different locations in the different versions.  */
-  switch (get_w32_minor_version ()) 
+  /* The true section size, before rounding.  Some linkers swap the
+     meaning of these two values.  */
+  return min (p_section->SizeOfRawData,
+             p_section->Misc.VirtualSize);
+}
+
+/* Return pointer to section header for named section. */
+IMAGE_SECTION_HEADER *
+find_section (char * name, IMAGE_NT_HEADERS * nt_header)
+{
+  PIMAGE_SECTION_HEADER section;
+  int i;
+
+  section = IMAGE_FIRST_SECTION (nt_header);
+
+  for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
     {
-    case 10:
-      return p_section->SizeOfRawData;
-    default:
-      return p_section->Misc.VirtualSize;
+      if (strcmp (section->Name, name) == 0)
+       return section;
+      section++;
     }
+  return NULL;
 }
 
+/* Return pointer to section header for section containing the given
+   relative virtual address. */
+IMAGE_SECTION_HEADER *
+rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header)
+{
+  PIMAGE_SECTION_HEADER section;
+  int i;
+
+  section = IMAGE_FIRST_SECTION (nt_header);
+
+  for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
+    {
+      if (rva >= section->VirtualAddress
+         && rva < section->VirtualAddress + section->SizeOfRawData)
+       return section;
+      section++;
+    }
+  return NULL;
+}
+
+
 /* Flip through the executable and cache the info necessary for dumping.  */
 static void
 get_section_info (file_data *p_infile)
@@ -363,6 +450,7 @@ get_section_info (file_data *p_infile)
   section = (PIMAGE_SECTION_HEADER) IMAGE_FIRST_SECTION (nt_header);
   for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) 
     {
+#ifdef SEPARATE_BSS_SECTION
       if (!strcmp (section->Name, ".bss")) 
        {
          /* The .bss section.  */
@@ -371,6 +459,8 @@ get_section_info (file_data *p_infile)
          bss_start = ptr;
          bss_size = get_section_size (section);
        }
+#endif
+#if 0
       if (!strcmp (section->Name, ".data")) 
        {
          /* From lastfile.c  */
@@ -389,10 +479,25 @@ get_section_info (file_data *p_infile)
             than the one Emacs was dumped on).  */
          data_size = my_edata - data_start_va;
        }
+#else
+      if (!strcmp (section->Name, "EMDATA")) 
+       {
+         /* The Emacs initialized data section.  */
+         data_section = section;
+         ptr = (char *) nt_header->OptionalHeader.ImageBase +
+           section->VirtualAddress;
+         data_start_va = ptr;
+         data_start_file = section->PointerToRawData;
+
+         /* Write back the full section.  */
+         data_size = get_section_size (section);
+       }
+#endif
       section++;
     }
 
-  if (!bss_start && !bss_size)
+#ifdef SEPARATE_BSS_SECTION
+  if (bss_start == UNINIT_PTR && bss_size == UNINIT_LONG)
     {
       /* Starting with MSVC 4.0, the .bss section has been eliminated
         and appended virtually to the end of the .data section.  Our
@@ -406,6 +511,10 @@ get_section_info (file_data *p_infile)
       bss_start = ptr + nt_header->OptionalHeader.ImageBase
        + data_section->VirtualAddress;
     }
+#else
+  bss_start = my_begbss;
+  bss_size = my_endbss - bss_start;
+#endif
 }