Commit 43640c4d authored by Geoff Voelker's avatar Geoff Voelker

Include config.h and time.h.

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.
parent 17fa2f54
......@@ -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
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment