diff options
author | Geoff Voelker <voelker@cs.washington.edu> | 1997-09-03 00:42:10 +0000 |
---|---|---|
committer | Geoff Voelker <voelker@cs.washington.edu> | 1997-09-03 00:42:10 +0000 |
commit | 43640c4dfeec138b7c789f998062e94e7d61303b (patch) | |
tree | 803e63fc66068fba8bf765eb53c833942748ae41 /src/unexw32.c | |
parent | 17fa2f54c036f2ca09ba2ebbc2809d0066acec86 (diff) |
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.
Diffstat (limited to 'src/unexw32.c')
-rw-r--r-- | src/unexw32.c | 235 |
1 files changed, 172 insertions, 63 deletions
diff --git a/src/unexw32.c b/src/unexw32.c index ef4ed56fb9..b1fa3e85ee 100644 --- a/src/unexw32.c +++ b/src/unexw32.c @@ -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 } |