X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/5b79dba5b941740286727d2d24091bdec94e2f6f..3c53a3cf83c218772d9bcfde4cd60c1face33e93:/src/unexw32.c diff --git a/src/unexw32.c b/src/unexw32.c index 4cdffac287..7b907beda6 100644 --- a/src/unexw32.c +++ b/src/unexw32.c @@ -67,17 +67,17 @@ void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile); /* Cached info about the .data section in the executable. */ PIMAGE_SECTION_HEADER data_section; -PUCHAR data_start = 0; +PCHAR data_start = 0; DWORD data_size = 0; /* Cached info about the .bss section in the executable. */ PIMAGE_SECTION_HEADER bss_section; -PUCHAR bss_start = 0; +PCHAR bss_start = 0; DWORD bss_size = 0; DWORD extra_bss_size = 0; /* bss data that is static might be discontiguous from non-static. */ PIMAGE_SECTION_HEADER bss_section_static; -PUCHAR bss_start_static = 0; +PCHAR bss_start_static = 0; DWORD bss_size_static = 0; DWORD extra_bss_size_static = 0; @@ -99,7 +99,7 @@ _start (void) { extern void mainCRTStartup (void); -#if 0 +#if 1 /* Give us a way to debug problems with crashes on startup when running under the MSVC profiler. */ if (GetEnvironmentVariable ("EMACS_DEBUG", NULL, 0) > 0) @@ -284,7 +284,7 @@ offset_to_section (DWORD offset, IMAGE_NT_HEADERS * nt_header) /* Return offset to an object in dst, given offset in src. We assume there is at least one section in both src and dst images, and that the some sections may have been added to dst (after sections in src). */ -static DWORD +DWORD relocate_offset (DWORD offset, IMAGE_NT_HEADERS * src_nt_header, IMAGE_NT_HEADERS * dst_nt_header) @@ -331,14 +331,14 @@ relocate_offset (DWORD offset, #define PTR_TO_RVA(ptr) ((DWORD)(ptr) - (DWORD) GetModuleHandle (NULL)) #define PTR_TO_OFFSET(ptr, pfile_data) \ - ((char *)(ptr) - (pfile_data)->file_base) + ((unsigned char *)(ptr) - (pfile_data)->file_base) #define OFFSET_TO_PTR(offset, pfile_data) \ ((pfile_data)->file_base + (DWORD)(offset)) /* Flip through the executable and cache the info necessary for dumping. */ -static void +void get_section_info (file_data *p_infile) { PIMAGE_DOS_HEADER dos_header; @@ -380,13 +380,31 @@ get_section_info (file_data *p_infile) area for the bss section, so we can make the new image the correct size. */ - data_start = my_begdata; - data_size = my_edata - my_begdata; - data_section = rva_to_section (PTR_TO_RVA (my_begdata), nt_header); - if (data_section != rva_to_section (PTR_TO_RVA (my_edata), nt_header)) + /* We arrange for the Emacs initialized data to be in a separate + section if possible, because we cannot rely on my_begdata and + my_edata marking out the full extent of the initialized data, at + least on the Alpha where the linker freely reorders variables + across libraries. If we can arrange for this, all we need to do is + find the start and size of the EMDATA section. */ + data_section = find_section ("EMDATA", nt_header); + if (data_section) { - printf ("Initialized data is not in a single section...bailing\n"); - exit (1); + data_start = (char *) nt_header->OptionalHeader.ImageBase + + data_section->VirtualAddress; + data_size = data_section->Misc.VirtualSize; + } + else + { + /* Fallback on the old method if compiler doesn't support the + data_set #pragma (or its equivalent). */ + data_start = my_begdata; + data_size = my_edata - my_begdata; + data_section = rva_to_section (PTR_TO_RVA (my_begdata), nt_header); + if (data_section != rva_to_section (PTR_TO_RVA (my_edata), nt_header)) + { + printf ("Initialized data is not in a single section...bailing\n"); + exit (1); + } } /* As noted in lastfile.c, the Alpha (but not the Intel) MSVC linker @@ -429,7 +447,11 @@ get_section_info (file_data *p_infile) - bss_section_static->SizeOfRawData; /* Combine the bss sections into one if they overlap. */ +#ifdef _ALPHA_ + overlap = 1; /* force all bss data to be dumped */ +#else overlap = 0; +#endif if (bss_start < bss_start_static) { if (bss_start_static < bss_start + bss_size) @@ -459,7 +481,7 @@ get_section_info (file_data *p_infile) /* The dump routines. */ -static void +void copy_executable_and_dump_data (file_data *p_infile, file_data *p_outfile) { @@ -499,6 +521,14 @@ copy_executable_and_dump_data (file_data *p_infile, #define DST_TO_OFFSET() PTR_TO_OFFSET (dst, p_outfile) #define ROUND_UP_DST(align) \ (dst = p_outfile->file_base + ROUND_UP (DST_TO_OFFSET (), (align))) +#define ROUND_UP_DST_AND_ZERO(align) \ + do { \ + unsigned char *newdst = p_outfile->file_base \ + + ROUND_UP (DST_TO_OFFSET (), (align)); \ + /* Zero the alignment slop; it may actually initialize real data. */ \ + memset (dst, 0, newdst - dst); \ + dst = newdst; \ + } while (0) /* Copy the source image sequentially, ie. section by section after copying the headers and section table, to simplify the process of @@ -522,13 +552,16 @@ copy_executable_and_dump_data (file_data *p_infile, COPY_CHUNK ("Copying section table...", section, nt_header->FileHeader.NumberOfSections * sizeof (*section)); + /* Align the first section's raw data area, and set the header size + field accordingly. */ + ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment); + dst_nt_header->OptionalHeader.SizeOfHeaders = DST_TO_OFFSET (); + for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) { char msg[100]; sprintf (msg, "Copying raw data for %s...", section->Name); - /* Align the section's raw data area. */ - ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment); dst_save = dst; /* Update the file-relative offset for this section's raw data (if @@ -541,6 +574,8 @@ copy_executable_and_dump_data (file_data *p_infile, COPY_CHUNK (msg, OFFSET_TO_PTR (section->PointerToRawData, p_infile), section->SizeOfRawData); + /* Ensure alignment slop is zeroed. */ + ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment); /* Note that various sections below may be aliases. */ if (section == data_section) @@ -582,7 +617,7 @@ copy_executable_and_dump_data (file_data *p_infile, } if (section == heap_section) { - DWORD heap_start = get_heap_start (); + DWORD heap_start = (DWORD) get_heap_start (); DWORD heap_size = get_committed_heap_size (); /* Dump the used portion of the predump heap, adjusting the @@ -608,13 +643,13 @@ copy_executable_and_dump_data (file_data *p_infile, dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; } + /* Align the section's raw data area. */ + ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment); + section++; dst_section++; } - /* Pad out the final section raw data area. */ - ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment); - /* Copy remainder of source image. */ do section--; @@ -684,18 +719,28 @@ unexec (char *new_name, char *old_name, void *start_data, void *start_bss, file_data in_file, out_file; char out_filename[MAX_PATH], in_filename[MAX_PATH]; unsigned long size; - char *ptr; + char *p; + char *q; + + /* Ignore old_name, and get our actual location from the OS. */ + if (!GetModuleFileName (NULL, in_filename, MAX_PATH)) + abort (); + dostounix_filename (in_filename); + strcpy (out_filename, in_filename); + + /* Change the base of the output filename to match the requested name. */ + if ((p = strrchr (out_filename, '/')) == NULL) + abort (); + /* The filenames have already been expanded, and will be in Unix + format, so it is safe to expect an absolute name. */ + if ((q = strrchr (new_name, '/')) == NULL) + abort (); + strcpy (p, q); - /* Make sure that the input and output filenames have the - ".exe" extension...patch them up if they don't. */ - strcpy (in_filename, old_name); - ptr = in_filename + strlen (in_filename) - 4; - if (strcmp (ptr, ".exe")) - strcat (in_filename, ".exe"); - - strcpy (out_filename, new_name); - ptr = out_filename + strlen (out_filename) - 4; - if (strcmp (ptr, ".exe")) + /* Make sure that the output filename has the ".exe" extension...patch + it up if not. */ + p = out_filename + strlen (out_filename) - 4; + if (strcmp (p, ".exe")) strcat (out_filename, ".exe"); printf ("Dumping from %s\n", in_filename);