emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

scratch/no-purespace ec121292d5c 01/13: Unexec removal: Remove obsolete


From: Pip Cet
Subject: scratch/no-purespace ec121292d5c 01/13: Unexec removal: Remove obsolete files
Date: Tue, 20 Aug 2024 15:42:43 -0400 (EDT)

branch: scratch/no-purespace
commit ec121292d5c44922380d6978963c803b7dece9b4
Author: Pip Cet <pipcet@protonmail.com>
Commit: Pip Cet <pipcet@protonmail.com>

    Unexec removal: Remove obsolete files
    
    * sheap.c, sheap.h, unexec.h:
    unexaix.c, unexcoff.c, unexcw.c, unexelf.c, unexhp9k800.c,
    unexmacosx.c, unexsol.c, unexw32.c: Files removed.
---
 src/sheap.c       |   79 ---
 src/sheap.h       |   30 --
 src/unexaix.c     |  611 -----------------------
 src/unexcoff.c    |  540 --------------------
 src/unexcw.c      |  302 ------------
 src/unexec.h      |    4 -
 src/unexelf.c     |  659 -------------------------
 src/unexhp9k800.c |  324 ------------
 src/unexmacosx.c  | 1406 -----------------------------------------------------
 src/unexsol.c     |   28 --
 src/unexw32.c     |  684 --------------------------
 11 files changed, 4667 deletions(-)

diff --git a/src/sheap.c b/src/sheap.c
deleted file mode 100644
index bab70c4e343..00000000000
--- a/src/sheap.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* simulate `sbrk' with an array in .bss, for `unexec' support for Cygwin;
-   complete rewrite of xemacs Cygwin `unexec' code
-
-   Copyright (C) 2004-2024 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-#include <config.h>
-
-#include "sheap.h"
-
-#include <stdio.h>
-#include "lisp.h"
-#include <unistd.h>
-#include <stdlib.h>            /* for exit */
-
-static int debug_sheap;
-
-char bss_sbrk_buffer[STATIC_HEAP_SIZE];
-char *max_bss_sbrk_ptr;
-
-void *
-bss_sbrk (ptrdiff_t request_size)
-{
-  static char *bss_sbrk_ptr;
-
-  if (!bss_sbrk_ptr)
-    {
-      max_bss_sbrk_ptr = bss_sbrk_ptr = bss_sbrk_buffer;
-#ifdef CYGWIN
-      /* Force space for fork to work.  */
-      sbrk (4096);
-#endif
-    }
-
-  int used = bss_sbrk_ptr - bss_sbrk_buffer;
-
-  if (request_size < -used)
-    {
-      printf (("attempt to free too much: "
-              "avail %d used %d failed request %"pD"d\n"),
-             STATIC_HEAP_SIZE, used, request_size);
-      exit (-1);
-      return 0;
-    }
-  else if (STATIC_HEAP_SIZE - used < request_size)
-    {
-      printf ("static heap exhausted: avail %d used %d failed request 
%"pD"d\n",
-             STATIC_HEAP_SIZE, used, request_size);
-      exit (-1);
-      return 0;
-    }
-
-  void *ret = bss_sbrk_ptr;
-  bss_sbrk_ptr += request_size;
-  if (max_bss_sbrk_ptr < bss_sbrk_ptr)
-    max_bss_sbrk_ptr = bss_sbrk_ptr;
-  if (debug_sheap)
-    {
-      if (request_size < 0)
-       printf ("freed size %"pD"d\n", request_size);
-      else
-       printf ("allocated %p size %"pD"d\n", ret, request_size);
-    }
-  return ret;
-}
diff --git a/src/sheap.h b/src/sheap.h
deleted file mode 100644
index 92f7ba5e857..00000000000
--- a/src/sheap.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Static heap allocation for GNU Emacs.
-
-Copyright 2016-2024 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-#include <stddef.h>
-#include "lisp.h"
-
-/* Size of the static heap.  Guess a value that is probably too large,
-   by up to a factor of four or so.  Typically the unused part is not
-   paged in and so does not cost much.  */
-enum { STATIC_HEAP_SIZE = sizeof (Lisp_Object) << 24 };
-
-extern char bss_sbrk_buffer[STATIC_HEAP_SIZE];
-extern char *max_bss_sbrk_ptr;
-extern void *bss_sbrk (ptrdiff_t);
diff --git a/src/unexaix.c b/src/unexaix.c
deleted file mode 100644
index f9bc39cf927..00000000000
--- a/src/unexaix.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/* Dump an executable file.
-   Copyright (C) 1985-1988, 1999, 2001-2024 Free Software Foundation,
-   Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/*
-In other words, you are welcome to use, share and improve this program.
-You are forbidden to forbid anyone else to use, share and improve
-what you give them.   Help stamp out software-hoarding!  */
-
-
-/* Originally based on the COFF unexec.c by Spencer W. Thomas.
- *
- * Subsequently hacked on by
- * Bill Mann <Bill_Man@praxisint.com>
- * Andrew Vignaux <Andrew.Vignaux@comp.vuw.ac.nz>
- * Mike Sperber <sperber@informatik.uni-tuebingen.de>
- *
- * Synopsis:
- *     unexec (const char *new_name, const *old_name);
- *
- * Takes a snapshot of the program and makes an a.out format file in the
- * file named by the string argument new_name.
- * If a_name is non-NULL, the symbol table will be taken from the given file.
- * On some machines, an existing a_name file is required.
- *
- */
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-
-#define PERROR(file) report_error (file, new)
-#include <a.out.h>
-/* Define getpagesize () if the system does not.
-   Note that this may depend on symbols defined in a.out.h
- */
-#include "getpagesize.h"
-
-#include <sys/types.h>
-#include <inttypes.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-extern char _data[];
-extern char _text[];
-
-#include <filehdr.h>
-#include <aouthdr.h>
-#include <scnhdr.h>
-#include <syms.h>
-
-static struct filehdr f_hdr;           /* File header */
-static struct aouthdr f_ohdr;          /* Optional file header (a.out) */
-static off_t bias;                     /* Bias to add for growth */
-static off_t lnnoptr;                  /* Pointer to line-number info within 
file */
-
-static off_t text_scnptr;
-static off_t data_scnptr;
-#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1))
-static off_t load_scnptr;
-static off_t orig_load_scnptr;
-static off_t orig_data_scnptr;
-static int unrelocate_symbols (int, int, const char *, const char *);
-
-#ifndef MAX_SECTIONS
-#define MAX_SECTIONS   10
-#endif
-
-static int adjust_lnnoptrs (int, int, const char *);
-
-static int pagemask;
-
-#include "lisp.h"
-
-static _Noreturn void
-report_error (const char *file, int fd)
-{
-  int err = errno;
-  if (fd)
-    emacs_close (fd);
-  report_file_errno ("Cannot unexec", build_string (file), err);
-}
-
-#define ERROR0(msg) report_error_1 (new, msg)
-#define ERROR1(msg,x) report_error_1 (new, msg, x)
-#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y)
-
-static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (2, 3)
-report_error_1 (int fd, const char *msg, ...)
-{
-  va_list ap;
-  emacs_close (fd);
-  va_start (ap, msg);
-  verror (msg, ap);
-  va_end (ap);
-}
-
-static int make_hdr (int, int, const char *, const char *);
-static void mark_x (const char *);
-static int copy_text_and_data (int);
-static int copy_sym (int, int, const char *, const char *);
-static void write_segment (int, char *, char *);
-
-/* ****************************************************************
- * unexec
- *
- * driving logic.
- */
-void
-unexec (const char *new_name, const char *a_name)
-{
-  int new = -1, a_out = -1;
-
-  if (a_name && (a_out = emacs_open (a_name, O_RDONLY, 0)) < 0)
-    {
-      PERROR (a_name);
-    }
-  if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0777)) < 0)
-    {
-      PERROR (new_name);
-    }
-  if (make_hdr (new, a_out,
-               a_name, new_name) < 0
-      || copy_text_and_data (new) < 0
-      || copy_sym (new, a_out, a_name, new_name) < 0
-      || adjust_lnnoptrs (new, a_out, new_name) < 0
-      || unrelocate_symbols (new, a_out, a_name, new_name) < 0)
-    {
-      emacs_close (new);
-      return;
-    }
-
-  emacs_close (new);
-  if (a_out >= 0)
-    emacs_close (a_out);
-}
-
-/* ****************************************************************
- * make_hdr
- *
- * Make the header in the new a.out from the header in core.
- * Modify the text and data sizes.
- */
-static int
-make_hdr (int new, int a_out,
-         const char *a_name, const char *new_name)
-{
-  int scns;
-  uintptr_t bss_start;
-  uintptr_t data_start;
-
-  struct scnhdr section[MAX_SECTIONS];
-  struct scnhdr * f_thdr;              /* Text section header */
-  struct scnhdr * f_dhdr;              /* Data section header */
-  struct scnhdr * f_bhdr;              /* Bss section header */
-  struct scnhdr * f_lhdr;              /* Loader section header */
-  struct scnhdr * f_tchdr;             /* Typechk section header */
-  struct scnhdr * f_dbhdr;             /* Debug section header */
-  struct scnhdr * f_xhdr;              /* Except section header */
-
-  load_scnptr = orig_load_scnptr = lnnoptr = 0;
-  pagemask = getpagesize () - 1;
-
-  /* Adjust text/data boundary. */
-  data_start = (uintptr_t) _data;
-
-  data_start = data_start & ~pagemask; /* (Down) to page boundary. */
-
-  bss_start = (uintptr_t) sbrk (0) + pagemask;
-  bss_start &= ~ pagemask;
-
-  if (data_start > bss_start)  /* Can't have negative data size. */
-    {
-      ERROR2 (("unexec: data_start (0x%"PRIxPTR
-              ") can't be greater than bss_start (0x%"PRIxPTR")"),
-             data_start, bss_start);
-    }
-
-  /* Salvage as much info from the existing file as possible */
-  f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
-  f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
-  if (a_out >= 0)
-    {
-      if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
-       {
-         PERROR (a_name);
-       }
-      if (f_hdr.f_opthdr > 0)
-       {
-         if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
-           {
-             PERROR (a_name);
-           }
-       }
-      if (f_hdr.f_nscns > MAX_SECTIONS)
-       {
-         ERROR0 ("unexec: too many section headers -- increase MAX_SECTIONS");
-       }
-      /* Loop through section headers */
-      for (scns = 0; scns < f_hdr.f_nscns; scns++) {
-       struct scnhdr *s = &section[scns];
-       if (read (a_out, s, sizeof (*s)) != sizeof (*s))
-         {
-           PERROR (a_name);
-         }
-
-#define CHECK_SCNHDR(ptr, name, flags) \
-  if (strcmp (s->s_name, name) == 0) { \
-    if (s->s_flags != flags) { \
-      fprintf (stderr, "unexec: %lx flags where %x expected in %s section.\n", 
\
-               (unsigned long)s->s_flags, flags, name);                 \
-    } \
-    if (ptr) { \
-      fprintf (stderr, "unexec: duplicate section header for section %s.\n", \
-               name);                                                   \
-    } \
-    ptr = s; \
-  }
-       CHECK_SCNHDR (f_thdr, _TEXT, STYP_TEXT);
-       CHECK_SCNHDR (f_dhdr, _DATA, STYP_DATA);
-       CHECK_SCNHDR (f_bhdr, _BSS, STYP_BSS);
-       CHECK_SCNHDR (f_lhdr, _LOADER, STYP_LOADER);
-       CHECK_SCNHDR (f_dbhdr, _DEBUG,  STYP_DEBUG);
-       CHECK_SCNHDR (f_tchdr, _TYPCHK,  STYP_TYPCHK);
-       CHECK_SCNHDR (f_xhdr, _EXCEPT,  STYP_EXCEPT);
-      }
-
-      if (f_thdr == 0)
-       {
-         ERROR1 ("unexec: couldn't find \"%s\" section", _TEXT);
-       }
-      if (f_dhdr == 0)
-       {
-         ERROR1 ("unexec: couldn't find \"%s\" section", _DATA);
-       }
-      if (f_bhdr == 0)
-       {
-         ERROR1 ("unexec: couldn't find \"%s\" section", _BSS);
-       }
-    }
-  else
-    {
-      ERROR0 ("can't build a COFF file from scratch yet");
-    }
-  orig_data_scnptr = f_dhdr->s_scnptr;
-  orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
-
-  /* Now we alter the contents of all the f_*hdr variables
-     to correspond to what we want to dump.  */
-
-  /* Indicate that the reloc information is no longer valid for ld (bind);
-     we only update it enough to fake out the exec-time loader.  */
-  f_hdr.f_flags |= (F_RELFLG | F_EXEC);
-
-  f_ohdr.dsize = bss_start - f_ohdr.data_start;
-  f_ohdr.bsize = 0;
-
-  f_dhdr->s_size = f_ohdr.dsize;
-  f_bhdr->s_size = f_ohdr.bsize;
-  f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize;
-  f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
-
-  /* fix scnptr's */
-  {
-    off_t ptr = section[0].s_scnptr;
-
-    bias = -1;
-    for (scns = 0; scns < f_hdr.f_nscns; scns++)
-      {
-       struct scnhdr *s = &section[scns];
-
-       if (s->s_flags & STYP_PAD)        /* .pad sections omitted in AIX 4.1 */
-         {
-           /*
-            * the text_start should probably be o_algntext but that doesn't
-            * seem to change
-            */
-           if (f_ohdr.text_start != 0) /* && scns != 0 */
-             {
-               s->s_size = 512 - (ptr % 512);
-               if (s->s_size == 512)
-                 s->s_size = 0;
-             }
-           s->s_scnptr = ptr;
-         }
-       else if (s->s_flags & STYP_DATA)
-         s->s_scnptr = ptr;
-       else if (!(s->s_flags & (STYP_TEXT | STYP_BSS)))
-         {
-           if (bias == -1)                /* if first section after bss */
-             bias = ptr - s->s_scnptr;
-
-           s->s_scnptr += bias;
-           ptr = s->s_scnptr;
-         }
-
-       ptr = ptr + s->s_size;
-      }
-  }
-
-  /* fix other pointers */
-  for (scns = 0; scns < f_hdr.f_nscns; scns++)
-    {
-      struct scnhdr *s = &section[scns];
-
-      if (s->s_relptr != 0)
-       {
-         s->s_relptr += bias;
-       }
-      if (s->s_lnnoptr != 0)
-       {
-         if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
-         s->s_lnnoptr += bias;
-       }
-    }
-
-  if (f_hdr.f_symptr > 0L)
-    {
-      f_hdr.f_symptr += bias;
-    }
-
-  text_scnptr = f_thdr->s_scnptr;
-  data_scnptr = f_dhdr->s_scnptr;
-  load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
-
-  if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
-    {
-      PERROR (new_name);
-    }
-
-  if (f_hdr.f_opthdr > 0)
-    {
-      if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
-       {
-         PERROR (new_name);
-       }
-    }
-
-  for (scns = 0; scns < f_hdr.f_nscns; scns++) {
-    struct scnhdr *s = &section[scns];
-    if (write (new, s, sizeof (*s)) != sizeof (*s))
-      {
-       PERROR (new_name);
-      }
-  }
-
-  return (0);
-}
-
-/* ****************************************************************
-
- *
- * Copy the text and data segments from memory to the new a.out
- */
-static int
-copy_text_and_data (int new)
-{
-  char *end;
-  char *ptr;
-
-  lseek (new, text_scnptr, SEEK_SET);
-  ptr = _text;
-  end = ptr + f_ohdr.tsize;
-  write_segment (new, ptr, end);
-
-  lseek (new, data_scnptr, SEEK_SET);
-  ptr = (char *) (ptrdiff_t) f_ohdr.data_start;
-  end = ptr + f_ohdr.dsize;
-  write_segment (new, ptr, end);
-
-  return 0;
-}
-
-#define UnexBlockSz (1<<12)                    /* read/write block size */
-static void
-write_segment (int new, char *ptr, char *end)
-{
-  int i, nwrite, ret;
-  char zeros[UnexBlockSz];
-
-  for (i = 0; ptr < end;)
-    {
-      /* distance to next block.  */
-      nwrite = (((ptrdiff_t) ptr + UnexBlockSz) & -UnexBlockSz) - (ptrdiff_t) 
ptr;
-      /* But not beyond specified end.  */
-      if (nwrite > end - ptr) nwrite = end - ptr;
-      ret = write (new, ptr, nwrite);
-      /* If write gets a page fault, it means we reached
-        a gap between the old text segment and the old data segment.
-        This gap has probably been remapped into part of the text segment.
-        So write zeros for it.  */
-      if (ret == -1 && errno == EFAULT)
-       {
-         memset (zeros, 0, nwrite);
-         write (new, zeros, nwrite);
-       }
-      else if (nwrite != ret)
-       {
-         int write_errno = errno;
-         char buf[1000];
-         void *addr = ptr;
-         sprintf (buf,
-                  "unexec write failure: addr %p, fileno %d, size 0x%x, wrote 
0x%x, errno %d",
-                  addr, new, nwrite, ret, errno);
-         errno = write_errno;
-         PERROR (buf);
-       }
-      i += nwrite;
-      ptr += nwrite;
-    }
-}
-
-/* ****************************************************************
- * copy_sym
- *
- * Copy the relocation information and symbol table from the a.out to the new
- */
-static int
-copy_sym (int new, int a_out, const char *a_name, const char *new_name)
-{
-  char page[UnexBlockSz];
-  int n;
-
-  if (a_out < 0)
-    return 0;
-
-  if (orig_load_scnptr == 0L)
-    return 0;
-
-  if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info  
*/
-    lseek (a_out, lnnoptr, SEEK_SET);  /* start copying from there */
-  else
-    lseek (a_out, orig_load_scnptr, SEEK_SET); /* Position a.out to symtab. */
-
-  while ((n = read (a_out, page, sizeof page)) > 0)
-    {
-      if (write (new, page, n) != n)
-       {
-         PERROR (new_name);
-       }
-    }
-  if (n < 0)
-    {
-      PERROR (a_name);
-    }
-  return 0;
-}
-
-static int
-adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
-{
-  int nsyms;
-  int naux;
-  int new;
-  struct syment symentry;
-  union auxent auxentry;
-
-  if (!lnnoptr || !f_hdr.f_symptr)
-    return 0;
-
-  if ((new = emacs_open (new_name, O_RDWR, 0)) < 0)
-    {
-      PERROR (new_name);
-      return -1;
-    }
-
-  lseek (new, f_hdr.f_symptr, SEEK_SET);
-  for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
-    {
-      read (new, &symentry, SYMESZ);
-      if (symentry.n_sclass == C_BINCL || symentry.n_sclass == C_EINCL)
-       {
-         symentry.n_value += bias;
-         lseek (new, -SYMESZ, SEEK_CUR);
-         write (new, &symentry, SYMESZ);
-       }
-
-      for (naux = symentry.n_numaux; naux-- != 0; )
-       {
-         read (new, &auxentry, AUXESZ);
-         nsyms++;
-         if (naux != 0              /* skip csect auxentry (last entry) */
-              && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT))
-            {
-              auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
-              lseek (new, -AUXESZ, SEEK_CUR);
-              write (new, &auxentry, AUXESZ);
-            }
-       }
-    }
-  emacs_close (new);
-
-  return 0;
-}
-
-static int
-unrelocate_symbols (int new, int a_out,
-                   const char *a_name, const char *new_name)
-{
-  int i;
-  LDHDR ldhdr;
-  LDREL ldrel;
-  off_t t_reloc = (intptr_t) _text - f_ohdr.text_start;
-#ifndef ALIGN_DATA_RELOC
-  off_t d_reloc = (intptr_t) _data - f_ohdr.data_start;
-#else
-  /* This worked (and was needed) before AIX 4.2.
-     I have no idea why. -- Mike */
-  off_t d_reloc = (intptr_t) _data - ALIGN (f_ohdr.data_start, 2);
-#endif
-  int * p;
-
-  if (load_scnptr == 0)
-    return 0;
-
-  lseek (a_out, orig_load_scnptr, SEEK_SET);
-  if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr))
-    {
-      PERROR (new_name);
-    }
-
-#define SYMNDX_TEXT    0
-#define SYMNDX_DATA    1
-#define SYMNDX_BSS     2
-
-  for (i = 0; i < ldhdr.l_nreloc; i++)
-    {
-      lseek (a_out,
-            orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
-            SEEK_SET);
-
-      if (read (a_out, &ldrel, LDRELSZ) != LDRELSZ)
-       {
-         PERROR (a_name);
-       }
-
-      /* move the BSS loader symbols to the DATA segment */
-      if (ldrel.l_symndx == SYMNDX_BSS)
-       {
-         ldrel.l_symndx = SYMNDX_DATA;
-
-         lseek (new,
-                load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
-                SEEK_SET);
-
-         if (write (new, &ldrel, LDRELSZ) != LDRELSZ)
-           {
-             PERROR (new_name);
-           }
-       }
-
-      if (ldrel.l_rsecnm == f_ohdr.o_sndata)
-       {
-         int orig_int;
-
-         lseek (a_out,
-                 orig_data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start),
-                SEEK_SET);
-
-         if (read (a_out, (void *) &orig_int, sizeof (orig_int))
-             != sizeof (orig_int))
-           {
-             PERROR (a_name);
-           }
-
-          p = (int *) (intptr_t) (ldrel.l_vaddr + d_reloc);
-
-         switch (ldrel.l_symndx) {
-         case SYMNDX_TEXT:
-           orig_int = * p - t_reloc;
-           break;
-
-         case SYMNDX_DATA:
-         case SYMNDX_BSS:
-           orig_int = * p - d_reloc;
-           break;
-         }
-
-          if (orig_int != * p)
-            {
-              lseek (new,
-                     data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start),
-                    SEEK_SET);
-              if (write (new, (void *) &orig_int, sizeof (orig_int))
-                  != sizeof (orig_int))
-                {
-                  PERROR (new_name);
-                }
-            }
-       }
-    }
-  return 0;
-}
diff --git a/src/unexcoff.c b/src/unexcoff.c
deleted file mode 100644
index 4a981da4a04..00000000000
--- a/src/unexcoff.c
+++ /dev/null
@@ -1,540 +0,0 @@
-/* Copyright (C) 1985-1988, 1992-1994, 2001-2024 Free Software
- * Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-
-/*
- * unexcoff.c - Convert a running program into an a.out or COFF file.
- *
- * ==================================================================
- * Note: This file is currently used only by the MSDOS (a.k.a. DJGPP)
- * build of Emacs.  If you are not interested in the MSDOS build, you
- * are looking at the wrong version of unexec!
- * ==================================================================
- *
- * Author:     Spencer W. Thomas
- *             Computer Science Dept.
- *             University of Utah
- * Date:       Tue Mar  2 1982
- * Originally under the name unexec.c.
- * Modified heavily since then.
- *
- * Synopsis:
- *     unexec (const char *new_name, const char *old_name);
- *
- * Takes a snapshot of the program and makes an a.out format file in the
- * file named by the string argument new_name.
- * If a_name is non-NULL, the symbol table will be taken from the given file.
- * On some machines, an existing a_name file is required.
- *
- * If you make improvements I'd like to get them too.
- * harpo!utah-cs!thomas, thomas@Utah-20
- *
- */
-
-/* Modified to support SysVr3 shared libraries by James Van Artsdalen
- * of Dell Computer Corporation.  james@bigtex.cactus.org.
- */
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-
-#define PERROR(file) report_error (file, new)
-
-#ifdef HAVE_UNEXEC  /* all rest of file!  */
-
-#ifdef HAVE_COFF_H
-#include <coff.h>
-#ifdef MSDOS
-#include <fcntl.h>  /* for O_RDONLY, O_RDWR */
-#include <crt0.h>   /* for _crt0_startup_flags and its bits */
-#include <sys/exceptn.h>
-static int save_djgpp_startup_flags;
-#include <libc/atexit.h>
-static struct __atexit *save_atexit_ptr;
-#define filehdr external_filehdr
-#define scnhdr external_scnhdr
-#define syment external_syment
-#define auxent external_auxent
-#define n_numaux e_numaux
-#define n_type e_type
-struct aouthdr
-{
-  unsigned short       magic;  /* type of file                         */
-  unsigned short       vstamp; /* version stamp                        */
-  unsigned long                tsize;  /* text size in bytes, padded to FW 
bdry*/
-  unsigned long                dsize;  /* initialized data "  "                
*/
-  unsigned long                bsize;  /* uninitialized data "   "             
*/
-  unsigned long                entry;  /* entry pt.                            
*/
-  unsigned long                text_start;/* base of text used for this file */
-  unsigned long                data_start;/* base of data used for this file */
-};
-#endif /* MSDOS */
-#else  /* not HAVE_COFF_H */
-#include <a.out.h>
-#endif /* not HAVE_COFF_H */
-
-/* Define getpagesize if the system does not.
-   Note that this may depend on symbols defined in a.out.h.  */
-#include "getpagesize.h"
-
-#ifndef makedev                        /* Try to detect types.h already loaded 
*/
-#include <sys/types.h>
-#endif /* makedev */
-#include <errno.h>
-
-#include <sys/file.h>
-
-extern int etext;
-
-static long block_copy_start;          /* Old executable start point */
-static struct filehdr f_hdr;           /* File header */
-static struct aouthdr f_ohdr;          /* Optional file header (a.out) */
-long bias;                     /* Bias to add for growth */
-long lnnoptr;                  /* Pointer to line-number info within file */
-#define SYMS_START block_copy_start
-
-static long text_scnptr;
-static long data_scnptr;
-
-static long coff_offset;
-
-static int pagemask;
-
-/* Correct an int which is the bit pattern of a pointer to a byte
-   into an int which is the number of a byte.
-   This is a no-op on ordinary machines, but not on all.  */
-
-#define ADDR_CORRECT(x) ((char *) (x) - (char *) 0)
-
-#include "lisp.h"
-
-static void
-report_error (const char *file, int fd)
-{
-  int err = errno;
-  if (fd)
-    emacs_close (fd);
-  report_file_errno ("Cannot unexec", build_string (file), err);
-}
-
-#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
-#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
-#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
-
-static void
-report_error_1 (int fd, const char *msg, int a1, int a2)
-{
-  emacs_close (fd);
-  error (msg, a1, a2);
-}
-
-static int make_hdr (int, int, const char *, const char *);
-static int copy_text_and_data (int, int);
-static int copy_sym (int, int, const char *, const char *);
-static void mark_x (const char *);
-
-/* ****************************************************************
- * make_hdr
- *
- * Make the header in the new a.out from the header in core.
- * Modify the text and data sizes.
- */
-static int
-make_hdr (int new, int a_out,
-         const char *a_name, const char *new_name)
-{
-  auto struct scnhdr f_thdr;           /* Text section header */
-  auto struct scnhdr f_dhdr;           /* Data section header */
-  auto struct scnhdr f_bhdr;           /* Bss section header */
-  auto struct scnhdr scntemp;          /* Temporary section header */
-  register int scns;
-  unsigned int bss_start;
-  unsigned int data_start;
-
-  pagemask = getpagesize () - 1;
-
-  /* Adjust text/data boundary. */
-  data_start = (int) DATA_START;
-  data_start = ADDR_CORRECT (data_start);
-  data_start = data_start & ~pagemask; /* (Down) to page boundary. */
-
-  bss_start = ADDR_CORRECT (sbrk (0)) + pagemask;
-  bss_start &= ~ pagemask;
-
-  if (data_start > bss_start)  /* Can't have negative data size. */
-    {
-      ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
-             data_start, bss_start);
-    }
-
-  coff_offset = 0L;            /* stays zero, except in DJGPP */
-
-  /* Salvage as much info from the existing file as possible */
-  if (a_out >= 0)
-    {
-#ifdef MSDOS
-      /* Support the coff-go32-exe format with a prepended stub, since
-        this is what GCC 2.8.0 and later generates by default in DJGPP.  */
-      unsigned short mz_header[3];
-
-      if (read (a_out, &mz_header, sizeof (mz_header)) != sizeof (mz_header))
-       {
-         PERROR (a_name);
-       }
-      if (mz_header[0] == 0x5a4d || mz_header[0] == 0x4d5a) /* "MZ" or "ZM" */
-       {
-         coff_offset = (long)mz_header[2] * 512L;
-         if (mz_header[1])
-           coff_offset += (long)mz_header[1] - 512L;
-         lseek (a_out, coff_offset, 0);
-       }
-      else
-       lseek (a_out, 0L, 0);
-#endif /* MSDOS */
-      if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
-       {
-         PERROR (a_name);
-       }
-      block_copy_start += sizeof (f_hdr);
-      if (f_hdr.f_opthdr > 0)
-       {
-         if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
-           {
-             PERROR (a_name);
-           }
-         block_copy_start += sizeof (f_ohdr);
-       }
-      /* Loop through section headers, copying them in */
-      lseek (a_out, coff_offset + sizeof (f_hdr) + f_hdr.f_opthdr, 0);
-      for (scns = f_hdr.f_nscns; scns > 0; scns--) {
-       if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
-         {
-           PERROR (a_name);
-         }
-       if (scntemp.s_scnptr > 0L)
-         {
-            if (block_copy_start < scntemp.s_scnptr + scntemp.s_size)
-             block_copy_start = scntemp.s_scnptr + scntemp.s_size;
-         }
-       if (strcmp (scntemp.s_name, ".text") == 0)
-         {
-           f_thdr = scntemp;
-         }
-       else if (strcmp (scntemp.s_name, ".data") == 0)
-         {
-           f_dhdr = scntemp;
-         }
-       else if (strcmp (scntemp.s_name, ".bss") == 0)
-         {
-           f_bhdr = scntemp;
-         }
-      }
-    }
-  else
-    {
-      ERROR0 ("can't build a COFF file from scratch yet");
-    }
-
-  /* Now we alter the contents of all the f_*hdr variables
-     to correspond to what we want to dump.  */
-
-  f_hdr.f_flags |= (F_RELFLG | F_EXEC);
-  f_ohdr.dsize = bss_start - f_ohdr.data_start;
-  f_ohdr.bsize = 0;
-  f_thdr.s_size = f_ohdr.tsize;
-  f_thdr.s_scnptr = sizeof (f_hdr) + sizeof (f_ohdr);
-  f_thdr.s_scnptr += (f_hdr.f_nscns) * (sizeof (f_thdr));
-  lnnoptr = f_thdr.s_lnnoptr;
-  text_scnptr = f_thdr.s_scnptr;
-  f_dhdr.s_paddr = f_ohdr.data_start;
-  f_dhdr.s_vaddr = f_ohdr.data_start;
-  f_dhdr.s_size = f_ohdr.dsize;
-  f_dhdr.s_scnptr = f_thdr.s_scnptr + f_thdr.s_size;
-  data_scnptr = f_dhdr.s_scnptr;
-  f_bhdr.s_paddr = f_ohdr.data_start + f_ohdr.dsize;
-  f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
-  f_bhdr.s_size = f_ohdr.bsize;
-  f_bhdr.s_scnptr = 0L;
-  bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start;
-
-  if (f_hdr.f_symptr > 0L)
-    {
-      f_hdr.f_symptr += bias;
-    }
-
-  if (f_thdr.s_lnnoptr > 0L)
-    {
-      f_thdr.s_lnnoptr += bias;
-    }
-
-  if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
-    {
-      PERROR (new_name);
-    }
-
-  if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
-    {
-      PERROR (new_name);
-    }
-
-  if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
-    {
-      PERROR (new_name);
-    }
-
-  if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
-    {
-      PERROR (new_name);
-    }
-
-  if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
-    {
-      PERROR (new_name);
-    }
-
-  return (0);
-
-}
-
-void
-write_segment (int new, const char *ptr, const char *end)
-{
-  register int i, nwrite, ret;
-  /* This is the normal amount to write at once.
-     It is the size of block that NFS uses.  */
-  int writesize = 1 << 13;
-  int pagesize = getpagesize ();
-  char zeros[1 << 13];
-
-  memset (zeros, 0, sizeof (zeros));
-
-  for (i = 0; ptr < end;)
-    {
-      /* Distance to next multiple of writesize.  */
-      nwrite = (((int) ptr + writesize) & -writesize) - (int) ptr;
-      /* But not beyond specified end.  */
-      if (nwrite > end - ptr) nwrite = end - ptr;
-      ret = write (new, ptr, nwrite);
-      /* If write gets a page fault, it means we reached
-        a gap between the old text segment and the old data segment.
-        This gap has probably been remapped into part of the text segment.
-        So write zeros for it.  */
-      if (ret == -1 && errno == EFAULT)
-       {
-         /* Write only a page of zeros at once,
-            so that we don't overshoot the start
-            of the valid memory in the old data segment.  */
-         if (nwrite > pagesize)
-           nwrite = pagesize;
-         write (new, zeros, nwrite);
-       }
-      i += nwrite;
-      ptr += nwrite;
-    }
-}
-/* ****************************************************************
- * copy_text_and_data
- *
- * Copy the text and data segments from memory to the new a.out
- */
-static int
-copy_text_and_data (int new, int a_out)
-{
-  register char *end;
-  register char *ptr;
-
-#ifdef MSDOS
-  /* Dump the original table of exception handlers, not the one
-     where our exception hooks are registered.  */
-  __djgpp_exception_toggle ();
-
-  /* Switch off startup flags that might have been set at runtime
-     and which might change the way that dumped Emacs works.  */
-  save_djgpp_startup_flags = _crt0_startup_flags;
-  _crt0_startup_flags &= ~(_CRT0_FLAG_NO_LFN | _CRT0_FLAG_NEARPTR);
-
-  /* Zero out the 'atexit' chain in the dumped executable, to avoid
-     calling the atexit functions twice.  (emacs.c:main installs an
-     atexit function.)  */
-  save_atexit_ptr = __atexit_ptr;
-  __atexit_ptr = NULL;
-#endif
-
-  lseek (new, (long) text_scnptr, 0);
-  ptr = (char *) f_ohdr.text_start;
-  end = ptr + f_ohdr.tsize;
-  write_segment (new, ptr, end);
-
-  lseek (new, (long) data_scnptr, 0);
-  ptr = (char *) f_ohdr.data_start;
-  end = ptr + f_ohdr.dsize;
-  write_segment (new, ptr, end);
-
-#ifdef MSDOS
-  /* Restore our exception hooks.  */
-  __djgpp_exception_toggle ();
-
-  /* Restore the startup flags.  */
-  _crt0_startup_flags = save_djgpp_startup_flags;
-
-  /* Restore the atexit chain.  */
-  __atexit_ptr = save_atexit_ptr;
-#endif
-
-
-  return 0;
-}
-
-/* ****************************************************************
- * copy_sym
- *
- * Copy the relocation information and symbol table from the a.out to the new
- */
-static int
-copy_sym (int new, int a_out, const char *a_name, const char *new_name)
-{
-  char page[1024];
-  int n;
-
-  if (a_out < 0)
-    return 0;
-
-  if (SYMS_START == 0L)
-    return 0;
-
-  if (lnnoptr)                 /* if there is line number info */
-    lseek (a_out, coff_offset + lnnoptr, 0);   /* start copying from there */
-  else
-    lseek (a_out, coff_offset + SYMS_START, 0);        /* Position a.out to 
symtab. */
-
-  while ((n = read (a_out, page, sizeof page)) > 0)
-    {
-      if (write (new, page, n) != n)
-       {
-         PERROR (new_name);
-       }
-    }
-  if (n < 0)
-    {
-      PERROR (a_name);
-    }
-  return 0;
-}
-
-
-/*
- *     If the COFF file contains a symbol table and a line number section,
- *     then any auxiliary entries that have values for x_lnnoptr must
- *     be adjusted by the amount that the line number section has moved
- *     in the file (bias computed in make_hdr).  The #@$%&* designers of
- *     the auxiliary entry structures used the absolute file offsets for
- *     the line number entry rather than an offset from the start of the
- *     line number section!
- *
- *     When I figure out how to scan through the symbol table and pick out
- *     the auxiliary entries that need adjustment, this routine will
- *     be fixed.  As it is now, all such entries are wrong and sdb
- *     will complain.   Fred Fish, UniSoft Systems Inc.
- */
-
-/* This function is probably very slow.  Instead of reopening the new
-   file for input and output it should copy from the old to the new
-   using the two descriptors already open (WRITEDESC and READDESC).
-   Instead of reading one small structure at a time it should use
-   a reasonable size buffer.  But I don't have time to work on such
-   things, so I am installing it as submitted to me.  -- RMS.  */
-
-int
-adjust_lnnoptrs (int writedesc, int readdesc, const char *new_name)
-{
-  register int nsyms;
-  register int new;
-  struct syment symentry;
-  union auxent auxentry;
-
-  if (!lnnoptr || !f_hdr.f_symptr)
-    return 0;
-
-#ifdef MSDOS
-  if ((new = writedesc) < 0)
-#else
-  if ((new = emacs_open (new_name, O_RDWR, 0)) < 0)
-#endif
-    {
-      PERROR (new_name);
-      return -1;
-    }
-
-  lseek (new, f_hdr.f_symptr, 0);
-  for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
-    {
-      read (new, &symentry, SYMESZ);
-      if (symentry.n_numaux)
-       {
-         read (new, &auxentry, AUXESZ);
-         nsyms++;
-         if (ISFCN (symentry.n_type) || symentry.n_type == 0x2400)
-           {
-             auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
-             lseek (new, -AUXESZ, 1);
-             write (new, &auxentry, AUXESZ);
-           }
-       }
-    }
-#ifndef MSDOS
-  emacs_close (new);
-#endif
-  return 0;
-}
-
-/* ****************************************************************
- * unexec
- *
- * driving logic.
- */
-void
-unexec (const char *new_name, const char *a_name)
-{
-  int new = -1, a_out = -1;
-
-  if (a_name && (a_out = emacs_open (a_name, O_RDONLY, 0)) < 0)
-    {
-      PERROR (a_name);
-    }
-  if ((new = emacs_open (new_name, O_WRONLY | O_CREAT | O_TRUNC, 0777)) < 0)
-    {
-      PERROR (new_name);
-    }
-
-  if (make_hdr (new, a_out, a_name, new_name) < 0
-      || copy_text_and_data (new, a_out) < 0
-      || copy_sym (new, a_out, a_name, new_name) < 0
-      || adjust_lnnoptrs (new, a_out, new_name) < 0
-      )
-    {
-      emacs_close (new);
-      return;
-    }
-
-  emacs_close (new);
-  if (a_out >= 0)
-    emacs_close (a_out);
-}
-
-#endif /* HAVE_UNEXEC */
diff --git a/src/unexcw.c b/src/unexcw.c
deleted file mode 100644
index 5c91498cc6c..00000000000
--- a/src/unexcw.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* unexec() support for Cygwin;
-   complete rewrite of xemacs Cygwin unexec() code
-
-   Copyright (C) 2004-2024 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-#include <stdio.h>
-#include <fcntl.h>
-#include <a.out.h>
-#include <unistd.h>
-#include <assert.h>
-
-#define DOTEXE ".exe"
-
-/*
-** header for Windows executable files
-*/
-typedef struct
-{
-  FILHDR file_header;
-  PEAOUTHDR file_optional_header;
-  SCNHDR section_header[32];
-} exe_header_t;
-
-int debug_unexcw = 0;
-
-/*
-** Read the header from the executable into memory so we can more easily 
access it.
-*/
-static exe_header_t *
-read_exe_header (int fd, exe_header_t * exe_header_buffer)
-{
-  int i;
-  MAYBE_UNUSED int ret;
-
-  assert (fd >= 0);
-  assert (exe_header_buffer != 0);
-
-  ret = lseek (fd, 0L, SEEK_SET);
-  assert (ret != -1);
-
-  ret =
-    read (fd, &exe_header_buffer->file_header,
-         sizeof (exe_header_buffer->file_header));
-  assert (ret == sizeof (exe_header_buffer->file_header));
-
-  assert (exe_header_buffer->file_header.e_magic == 0x5a4d);
-  assert (exe_header_buffer->file_header.nt_signature == 0x4550);
-#ifdef __x86_64__
-  assert (exe_header_buffer->file_header.f_magic == 0x8664);
-#else
-  assert (exe_header_buffer->file_header.f_magic == 0x014c);
-#endif
-  assert (exe_header_buffer->file_header.f_nscns > 0);
-  assert (exe_header_buffer->file_header.f_nscns <=
-          ARRAYELTS (exe_header_buffer->section_header));
-  assert (exe_header_buffer->file_header.f_opthdr > 0);
-
-  ret =
-    read (fd, &exe_header_buffer->file_optional_header,
-         sizeof (exe_header_buffer->file_optional_header));
-  assert (ret == sizeof (exe_header_buffer->file_optional_header));
-
-#ifdef __x86_64__
-  assert (exe_header_buffer->file_optional_header.magic == 0x020b);
-#else
-  assert (exe_header_buffer->file_optional_header.magic == 0x010b);
-#endif
-
-  for (i = 0; i < exe_header_buffer->file_header.f_nscns; ++i)
-    {
-      ret =
-       read (fd, &exe_header_buffer->section_header[i],
-             sizeof (exe_header_buffer->section_header[i]));
-      assert (ret == sizeof (exe_header_buffer->section_header[i]));
-    }
-
-  return (exe_header_buffer);
-}
-
-/*
-** Fix the dumped emacs executable:
-**
-** - copy .data section data of interest from running executable into
-**   output .exe file
-**
-** - convert .bss section into an initialized data section (like
-**   .data) and copy .bss section data of interest from running
-**   executable into output .exe file
-*/
-static void
-fixup_executable (int fd)
-{
-  exe_header_t exe_header_buffer;
-  exe_header_t *exe_header;
-  int i;
-  MAYBE_UNUSED int ret;
-  int found_data = 0;
-  int found_bss = 0;
-
-  exe_header = read_exe_header (fd, &exe_header_buffer);
-  assert (exe_header != 0);
-
-  assert (exe_header->file_header.f_nscns > 0);
-  for (i = 0; i < exe_header->file_header.f_nscns; ++i)
-    {
-      unsigned long start_address =
-       exe_header->section_header[i].s_vaddr +
-       exe_header->file_optional_header.ImageBase;
-      unsigned long end_address =
-       exe_header->section_header[i].s_vaddr +
-       exe_header->file_optional_header.ImageBase +
-       exe_header->section_header[i].s_paddr;
-      if (debug_unexcw)
-       printf ("%8s start %#lx end %#lx\n",
-               exe_header->section_header[i].s_name,
-               start_address, end_address);
-      if (my_edata >= (char *) start_address
-         && my_edata < (char *) end_address)
-       {
-         /* data section */
-         ret =
-           lseek (fd, (long) (exe_header->section_header[i].s_scnptr),
-                  SEEK_SET);
-         assert (ret != -1);
-         ret =
-           write (fd, (char *) start_address,
-                  my_edata - (char *) start_address);
-         assert (ret == my_edata - (char *) start_address);
-         ++found_data;
-         if (debug_unexcw)
-           printf ("         .data, mem start %#lx mem length %td\n",
-                   start_address, my_edata - (char *) start_address);
-         if (debug_unexcw)
-           printf ("         .data, file start %d file length %d\n",
-                   (int) exe_header->section_header[i].s_scnptr,
-                   (int) exe_header->section_header[i].s_paddr);
-       }
-      else if (my_endbss >= (char *) start_address
-              && my_endbss < (char *) end_address)
-       {
-         /* bss section */
-         ++found_bss;
-         if (exe_header->section_header[i].s_flags & 0x00000080)
-           {
-             /* convert uninitialized data section to initialized data section 
*/
-             struct stat statbuf;
-             ret = fstat (fd, &statbuf);
-             assert (ret != -1);
-
-             exe_header->section_header[i].s_flags &= ~0x00000080;
-             exe_header->section_header[i].s_flags |= 0x00000040;
-
-             exe_header->section_header[i].s_scnptr =
-               (statbuf.st_size +
-                exe_header->file_optional_header.FileAlignment) /
-               exe_header->file_optional_header.FileAlignment *
-               exe_header->file_optional_header.FileAlignment;
-
-             exe_header->section_header[i].s_size =
-               (exe_header->section_header[i].s_paddr +
-                exe_header->file_optional_header.FileAlignment) /
-               exe_header->file_optional_header.FileAlignment *
-               exe_header->file_optional_header.FileAlignment;
-
-              /* Make sure the generated bootstrap binary isn't
-               * sparse.  NT doesn't use a file cache for sparse
-               * executables, so if we bootstrap Emacs using a sparse
-               * bootstrap-emacs.exe, bootstrap takes about twenty
-               * times longer than it would otherwise.  */
-
-              ret = posix_fallocate (fd,
-                                     ( exe_header->section_header[i].s_scnptr +
-                                       exe_header->section_header[i].s_size ),
-                                     1);
-
-              assert (ret != -1);
-
-             ret =
-               lseek (fd,
-                      (long) (exe_header->section_header[i].s_scnptr +
-                              exe_header->section_header[i].s_size - 1),
-                      SEEK_SET);
-             assert (ret != -1);
-             ret = write (fd, "", 1);
-             assert (ret == 1);
-
-             ret =
-               lseek (fd,
-                      (long) ((char *) &exe_header->section_header[i] -
-                              (char *) exe_header), SEEK_SET);
-             assert (ret != -1);
-             ret =
-               write (fd, &exe_header->section_header[i],
-                      sizeof (exe_header->section_header[i]));
-             assert (ret == sizeof (exe_header->section_header[i]));
-             if (debug_unexcw)
-               printf ("         seek to %ld, write %zu\n",
-                       (long) ((char *) &exe_header->section_header[i] -
-                               (char *) exe_header),
-                       sizeof (exe_header->section_header[i]));
-           }
-         /* write initialized data section */
-         ret =
-           lseek (fd, (long) (exe_header->section_header[i].s_scnptr),
-                  SEEK_SET);
-         assert (ret != -1);
-         ret =
-           write (fd, (char *) start_address,
-                  my_endbss - (char *) start_address);
-         assert (ret == (my_endbss - (char *) start_address));
-         if (debug_unexcw)
-           printf ("         .bss, mem start %#lx mem length %td\n",
-                   start_address, my_endbss - (char *) start_address);
-         if (debug_unexcw)
-           printf ("         .bss, file start %d file length %d\n",
-                   (int) exe_header->section_header[i].s_scnptr,
-                   (int) exe_header->section_header[i].s_paddr);
-       }
-    }
-  assert (found_bss == 1);
-  assert (found_data == 1);
-}
-
-/*
-** Windows likes .exe suffixes on executables.
-*/
-static char *
-add_exe_suffix_if_necessary (const char *name, char *modified)
-{
-  int i = strlen (name);
-  if (i <= (sizeof (DOTEXE) - 1))
-    {
-      sprintf (modified, "%s%s", name, DOTEXE);
-    }
-  else if (!strcasecmp (name + i - (sizeof (DOTEXE) - 1), DOTEXE))
-    {
-      strcpy (modified, name);
-    }
-  else
-    {
-      sprintf (modified, "%s%s", name, DOTEXE);
-    }
-  return (modified);
-}
-
-void
-unexec (const char *outfile, const char *infile)
-{
-  char infile_buffer[FILENAME_MAX];
-  char outfile_buffer[FILENAME_MAX];
-  int fd_in;
-  int fd_out;
-  int ret;
-  MAYBE_UNUSED int ret2;
-
-  infile = add_exe_suffix_if_necessary (infile, infile_buffer);
-  outfile = add_exe_suffix_if_necessary (outfile, outfile_buffer);
-
-  fd_in = emacs_open (infile, O_RDONLY, 0);
-  assert (fd_in >= 0);
-  fd_out = emacs_open (outfile, O_RDWR | O_TRUNC | O_CREAT, 0755);
-  assert (fd_out >= 0);
-  for (;;)
-    {
-      char buffer[4096];
-      ret = read (fd_in, buffer, sizeof (buffer));
-      if (ret == 0)
-       {
-         /* eof */
-         break;
-       }
-      assert (ret > 0);
-      /* data */
-      ret2 = write (fd_out, buffer, ret);
-      assert (ret2 == ret);
-    }
-  ret = emacs_close (fd_in);
-  assert (ret == 0);
-
-  fixup_executable (fd_out);
-
-  ret = emacs_close (fd_out);
-  assert (ret == 0);
-}
diff --git a/src/unexec.h b/src/unexec.h
deleted file mode 100644
index cdb2e8016ea..00000000000
--- a/src/unexec.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef EMACS_UNEXEC_H
-#define EMACS_UNEXEC_H
-void unexec (const char *, const char *);
-#endif /* EMACS_UNEXEC_H */
diff --git a/src/unexelf.c b/src/unexelf.c
deleted file mode 100644
index a9a8f2d6ce9..00000000000
--- a/src/unexelf.c
+++ /dev/null
@@ -1,659 +0,0 @@
-/* Copyright (C) 1985-1988, 1990, 1992, 1999-2024 Free Software
-   Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/*
-In other words, you are welcome to use, share and improve this program.
-You are forbidden to forbid anyone else to use, share and improve
-what you give them.   Help stamp out software-hoarding!  */
-
-
-/*
- * unexec.c - Convert a running program into an a.out file.
- *
- * Author:     Spencer W. Thomas
- *             Computer Science Dept.
- *             University of Utah
- * Date:       Tue Mar  2 1982
- * Modified heavily since then.
- *
- * Synopsis:
- *     unexec (const char *new_name, const char *old_name);
- *
- * Takes a snapshot of the program and makes an a.out format file in the
- * file named by the string argument new_name.
- * If old_name is non-NULL, the symbol table will be taken from the given file.
- * On some machines, an existing old_name file is required.
- *
- */
-
-/* We do not use mmap because that fails with NFS.
-   Instead we read the whole file, modify it, and write it out.  */
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <memory.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#ifdef __QNX__
-# include <sys/elf.h>
-#elif !defined __NetBSD__ && !defined __OpenBSD__
-# include <elf.h>
-#endif
-#include <sys/mman.h>
-#if defined (_SYSTYPE_SYSV)
-#include <sys/elf_mips.h>
-#include <sym.h>
-#endif /* _SYSTYPE_SYSV */
-
-#ifndef MAP_ANON
-#ifdef MAP_ANONYMOUS
-#define MAP_ANON MAP_ANONYMOUS
-#else
-#define MAP_ANON 0
-#endif
-#endif
-
-#ifndef MAP_FAILED
-#define MAP_FAILED ((void *) -1)
-#endif
-
-#if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
-/* Declare COFF debugging symbol table.  This used to be in
-   /usr/include/sym.h, but this file is no longer included in Red Hat
-   5.0 and presumably in any other glibc 2.x based distribution.  */
-typedef struct {
-       short magic;
-       short vstamp;
-       int ilineMax;
-       int idnMax;
-       int ipdMax;
-       int isymMax;
-       int ioptMax;
-       int iauxMax;
-       int issMax;
-       int issExtMax;
-       int ifdMax;
-       int crfd;
-       int iextMax;
-       long cbLine;
-       long cbLineOffset;
-       long cbDnOffset;
-       long cbPdOffset;
-       long cbSymOffset;
-       long cbOptOffset;
-       long cbAuxOffset;
-       long cbSsOffset;
-       long cbSsExtOffset;
-       long cbFdOffset;
-       long cbRfdOffset;
-       long cbExtOffset;
-} HDRR, *pHDRR;
-#define cbHDRR sizeof (HDRR)
-#define hdrNil ((pHDRR)0)
-#endif
-
-#ifdef __NetBSD__
-/*
- * NetBSD does not have normal-looking user-land ELF support.
- */
-# if defined __alpha__ || defined __sparc_v9__ || defined _LP64
-#  define ELFSIZE      64
-# else
-#  define ELFSIZE      32
-# endif
-# include <sys/exec_elf.h>
-
-# ifndef PT_LOAD
-#  define PT_LOAD      Elf_pt_load
-#  if 0                                                /* was in pkgsrc 
patches for 20.7 */
-#   define SHT_PROGBITS Elf_sht_progbits
-#  endif
-#  define SHT_SYMTAB   Elf_sht_symtab
-#  define SHT_DYNSYM   Elf_sht_dynsym
-#  define SHT_NULL     Elf_sht_null
-#  define SHT_NOBITS   Elf_sht_nobits
-#  define SHT_REL      Elf_sht_rel
-#  define SHT_RELA     Elf_sht_rela
-
-#  define SHN_UNDEF    Elf_eshn_undefined
-#  define SHN_ABS      Elf_eshn_absolute
-#  define SHN_COMMON   Elf_eshn_common
-# endif /* !PT_LOAD */
-
-# ifdef __alpha__
-#  include <sys/exec_ecoff.h>
-#  define HDRR         struct ecoff_symhdr
-#  define pHDRR                HDRR *
-# endif /* __alpha__ */
-
-#ifdef __mips__                        /* was in pkgsrc patches for 20.7 */
-# define SHT_MIPS_DEBUG        DT_MIPS_FLAGS
-# define HDRR          struct Elf_Shdr
-#endif /* __mips__ */
-#endif /* __NetBSD__ */
-
-#ifdef __OpenBSD__
-# include <sys/exec_elf.h>
-#endif
-
-#if __GNU_LIBRARY__ - 0 >= 6
-# include <link.h>     /* get ElfW etc */
-#endif
-
-#ifndef ElfW
-# define ElfBitsW(bits, type) Elf##bits##_##type
-# ifndef ELFSIZE
-#  ifdef _LP64
-#   define ELFSIZE 64
-#  else
-#   define ELFSIZE 32
-#  endif
-# endif
-  /* This macro expands `bits' before invoking ElfBitsW.  */
-# define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
-# define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
-#endif
-
-/* The code often converts ElfW (Half) values like e_shentsize to ptrdiff_t;
-   check that this doesn't lose information.  */
-#include <intprops.h>
-#include <verify.h>
-verify ((! TYPE_SIGNED (ElfW (Half))
-        || PTRDIFF_MIN <= TYPE_MINIMUM (ElfW (Half)))
-       && TYPE_MAXIMUM (ElfW (Half)) <= PTRDIFF_MAX);
-
-#ifdef UNEXELF_DEBUG
-# define DEBUG_LOG(expr) fprintf (stderr, #expr " 0x%"PRIxMAX"\n", \
-                                 (uintmax_t) (expr))
-#endif
-
-/* Get the address of a particular section or program header entry,
- * accounting for the size of the entries.
- */
-
-static void *
-entry_address (void *section_h, ptrdiff_t idx, ptrdiff_t entsize)
-{
-  char *h = section_h;
-  return h + idx * entsize;
-}
-
-#define OLD_SECTION_H(n) \
-  (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
-#define NEW_SECTION_H(n) \
-  (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
-#define OLD_PROGRAM_H(n) \
-  (*(ElfW (Phdr) *) entry_address (old_program_h, n, old_file_h->e_phentsize))
-
-typedef unsigned char byte;
-
-/* ****************************************************************
- * unexec
- *
- * driving logic.
- *
- * In ELF, this works by replacing the old bss SHT_NOBITS section with
- * a new, larger, SHT_PROGBITS section.
- *
- */
-void
-unexec (const char *new_name, const char *old_name)
-{
-  int new_file, old_file;
-  off_t new_file_size;
-
-  /* Pointers to the base of the image of the two files.  */
-  caddr_t old_base, new_base;
-
-#if MAP_ANON == 0
-  int mmap_fd;
-#else
-# define mmap_fd -1
-#endif
-
-  /* Pointers to the file, program and section headers for the old and
-     new files.  */
-  ElfW (Ehdr) *old_file_h, *new_file_h;
-  ElfW (Phdr) *old_program_h, *new_program_h;
-  ElfW (Shdr) *old_section_h, *new_section_h;
-
-  /* Point to the section name table.  */
-  char *old_section_names, *new_section_names;
-
-  ElfW (Phdr) *old_bss_seg, *new_bss_seg;
-  ElfW (Addr) old_bss_addr, new_bss_addr;
-  ElfW (Word) old_bss_size, bss_size_growth, new_data2_size;
-  ElfW (Off) old_bss_offset, new_data2_offset;
-
-  ptrdiff_t n;
-  ptrdiff_t old_bss_index;
-  struct stat stat_buf;
-  off_t old_file_size;
-
-  /* Open the old file, allocate a buffer of the right size, and read
-     in the file contents.  */
-
-  old_file = emacs_open (old_name, O_RDONLY, 0);
-
-  if (old_file < 0)
-    fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
-
-  if (fstat (old_file, &stat_buf) != 0)
-    fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
-
-#if MAP_ANON == 0
-  mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
-  if (mmap_fd < 0)
-    fatal ("Can't open /dev/zero for reading: %s", strerror (errno));
-#endif
-
-  /* We cannot use malloc here because that may use sbrk.  If it does,
-     we'd dump our temporary buffers with Emacs, and we'd have to be
-     extra careful to use the correct value of sbrk(0) after
-     allocating all buffers in the code below, which we aren't.  */
-  old_file_size = stat_buf.st_size;
-  if (! (0 <= old_file_size && old_file_size <= SIZE_MAX))
-    fatal ("File size out of range");
-  old_base = mmap (NULL, old_file_size, PROT_READ | PROT_WRITE,
-                  MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
-  if (old_base == MAP_FAILED)
-    fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
-
-  if (read (old_file, old_base, old_file_size) != old_file_size)
-    fatal ("Didn't read all of %s: %s", old_name, strerror (errno));
-
-  /* Get pointers to headers & section names */
-
-  old_file_h = (ElfW (Ehdr) *) old_base;
-  old_program_h = (ElfW (Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
-  old_section_h = (ElfW (Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
-  old_section_names = (char *) old_base
-    + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
-
-  /* Find the PT_LOAD header covering the highest address.  This
-     segment will be where bss sections are located, past p_filesz.  */
-  old_bss_seg = 0;
-  for (n = old_file_h->e_phnum; --n >= 0; )
-    {
-      ElfW (Phdr) *seg = &OLD_PROGRAM_H (n);
-      if (seg->p_type == PT_LOAD
-         && (old_bss_seg == 0
-             || seg->p_vaddr > old_bss_seg->p_vaddr))
-       old_bss_seg = seg;
-    }
-  eassume (old_bss_seg);
-  if (!old_bss_seg)
-    emacs_abort ();
-
-  /* Note that old_bss_addr may be lower than the first bss section
-     address, since the section may need aligning.  */
-  old_bss_addr = old_bss_seg->p_vaddr + old_bss_seg->p_filesz;
-  old_bss_offset = old_bss_seg->p_offset + old_bss_seg->p_filesz;
-  old_bss_size = old_bss_seg->p_memsz - old_bss_seg->p_filesz;
-
-  /* Find the last bss style section in the bss segment range.  */
-  old_bss_index = -1;
-  for (n = old_file_h->e_shnum; --n > 0; )
-    {
-      ElfW (Shdr) *shdr = &OLD_SECTION_H (n);
-      if (shdr->sh_type == SHT_NOBITS
-         && shdr->sh_addr >= old_bss_addr
-         && shdr->sh_addr + shdr->sh_size <= old_bss_addr + old_bss_size
-         && (old_bss_index == -1
-             || OLD_SECTION_H (old_bss_index).sh_addr < shdr->sh_addr))
-       old_bss_index = n;
-    }
-
-  if (old_bss_index == -1)
-    fatal ("no bss section found");
-
-  void *no_break = (void *) (intptr_t) -1;
-  void *new_break = no_break;
-#ifdef HAVE_SBRK
-  new_break = sbrk (0);
-#endif
-  if (new_break == no_break)
-    new_break = (byte *) old_bss_addr + old_bss_size;
-  new_bss_addr = (ElfW (Addr)) new_break;
-  bss_size_growth = new_bss_addr - old_bss_addr;
-  new_data2_size = bss_size_growth;
-  new_data2_size += alignof (ElfW (Shdr)) - 1;
-  new_data2_size -= new_data2_size % alignof (ElfW (Shdr));
-
-  new_data2_offset = old_bss_offset;
-
-#ifdef UNEXELF_DEBUG
-  fprintf (stderr, "old_bss_index %td\n", old_bss_index);
-  DEBUG_LOG (old_bss_addr);
-  DEBUG_LOG (old_bss_size);
-  DEBUG_LOG (old_bss_offset);
-  DEBUG_LOG (new_bss_addr);
-  DEBUG_LOG (new_data2_size);
-  DEBUG_LOG (new_data2_offset);
-#endif
-
-  if (new_bss_addr < old_bss_addr + old_bss_size)
-    fatal (".bss shrank when undumping");
-
-  /* Set the output file to the right size.  Allocate a buffer to hold
-     the image of the new file.  Set pointers to various interesting
-     objects.  */
-
-  new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0777);
-  if (new_file < 0)
-    fatal ("Can't creat (%s): %s", new_name, strerror (errno));
-
-  new_file_size = old_file_size + new_data2_size;
-
-  if (ftruncate (new_file, new_file_size))
-    fatal ("Can't ftruncate (%s): %s", new_name, strerror (errno));
-
-  new_base = mmap (NULL, new_file_size, PROT_READ | PROT_WRITE,
-                  MAP_ANON | MAP_PRIVATE, mmap_fd, 0);
-  if (new_base == MAP_FAILED)
-    fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
-
-  /* Make our new file, program and section headers as copies of the
-     originals.  */
-
-  new_file_h = (ElfW (Ehdr) *) new_base;
-  memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
-
-  /* Fix up file header.  Section header is further away now.  */
-
-  if (new_file_h->e_shoff >= old_bss_offset)
-    new_file_h->e_shoff += new_data2_size;
-
-  new_program_h = (ElfW (Phdr) *) ((byte *) new_base + new_file_h->e_phoff);
-  new_section_h = (ElfW (Shdr) *) ((byte *) new_base + new_file_h->e_shoff);
-
-  memcpy (new_program_h, old_program_h,
-         old_file_h->e_phnum * old_file_h->e_phentsize);
-  memcpy (new_section_h, old_section_h,
-         old_file_h->e_shnum * old_file_h->e_shentsize);
-
-#ifdef UNEXELF_DEBUG
-  DEBUG_LOG (old_file_h->e_shoff);
-  fprintf (stderr, "Old section count %td\n", (ptrdiff_t) old_file_h->e_shnum);
-  DEBUG_LOG (new_file_h->e_shoff);
-  fprintf (stderr, "New section count %td\n", (ptrdiff_t) new_file_h->e_shnum);
-#endif
-
-  /* Fix up program header.  Extend the writable data segment so
-     that the bss area is covered too.  */
-
-  new_bss_seg = new_program_h + (old_bss_seg - old_program_h);
-  new_bss_seg->p_filesz = new_bss_addr - new_bss_seg->p_vaddr;
-  new_bss_seg->p_memsz = new_bss_seg->p_filesz;
-
-  /* Copy over what we have in memory now for the bss area. */
-  memcpy (new_base + new_data2_offset, (caddr_t) old_bss_addr,
-         bss_size_growth);
-
-  /* Walk through all section headers, copying data and updating.  */
-  for (n = 1; n < old_file_h->e_shnum; n++)
-    {
-      caddr_t src;
-      ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
-      ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
-
-      if (new_shdr->sh_type == SHT_NOBITS
-         && new_shdr->sh_addr >= old_bss_addr
-         && (new_shdr->sh_addr + new_shdr->sh_size
-             <= old_bss_addr + old_bss_size))
-       {
-         /* This section now has file backing.  */
-         new_shdr->sh_type = SHT_PROGBITS;
-
-         /* SHT_NOBITS sections do not need a valid sh_offset, so it
-            might be incorrect.  Write the correct value.  */
-         new_shdr->sh_offset = (new_shdr->sh_addr - new_bss_seg->p_vaddr
-                                + new_bss_seg->p_offset);
-
-         /* If this is was a SHT_NOBITS .plt section, then it is
-            probably a PowerPC PLT.  If it is PowerPC64 ELFv1 then
-            glibc ld.so doesn't initialize the toc pointer word.  A
-            non-zero toc pointer word can defeat Power7 thread safety
-            during lazy update of a PLT entry.  This only matters if
-            emacs becomes multi-threaded.  */
-         if (strcmp (old_section_names + new_shdr->sh_name, ".plt") == 0)
-           memset (new_shdr->sh_offset + new_base, 0, new_shdr->sh_size);
-
-         /* Extend the size of the last bss section to cover dumped
-            data.  */
-         if (n == old_bss_index)
-           new_shdr->sh_size = new_bss_addr - new_shdr->sh_addr;
-
-         /* We have already copied this section from the current
-            process.  */
-         continue;
-       }
-
-      /* Any section that was originally placed after the .bss
-        section should now be offset by NEW_DATA2_SIZE.  */
-      if (new_shdr->sh_offset >= old_bss_offset)
-       new_shdr->sh_offset += new_data2_size;
-
-      /* Now, start to copy the content of sections.  */
-      if (new_shdr->sh_type == SHT_NULL
-         || new_shdr->sh_type == SHT_NOBITS)
-       continue;
-
-      /* Some sections are copied from the current process instead of
-        the old file.  */
-      if (!strcmp (old_section_names + new_shdr->sh_name, ".data")
-         || !strcmp (old_section_names + new_shdr->sh_name, ".sdata")
-         || !strcmp (old_section_names + new_shdr->sh_name, ".lit4")
-         || !strcmp (old_section_names + new_shdr->sh_name, ".lit8")
-         || !strcmp (old_section_names + new_shdr->sh_name, ".sdata1")
-         || !strcmp (old_section_names + new_shdr->sh_name, ".data1"))
-       src = (caddr_t) old_shdr->sh_addr;
-      else
-       src = old_base + old_shdr->sh_offset;
-
-      memcpy (new_shdr->sh_offset + new_base, src, new_shdr->sh_size);
-
-#if (defined __alpha__ && !defined __OpenBSD__) || defined _SYSTYPE_SYSV
-      /* Update Alpha and MIPS COFF debug symbol table.  */
-      if (strcmp (old_section_names + new_shdr->sh_name, ".mdebug") == 0
-         && new_shdr->sh_offset - old_shdr->sh_offset != 0
-#if defined _SYSTYPE_SYSV
-         && new_shdr->sh_type == SHT_MIPS_DEBUG
-#endif
-         )
-       {
-         ptrdiff_t diff = new_shdr->sh_offset - old_shdr->sh_offset;
-         HDRR *phdr = (HDRR *) (new_shdr->sh_offset + new_base);
-
-         phdr->cbLineOffset += diff;
-         phdr->cbDnOffset += diff;
-         phdr->cbPdOffset += diff;
-         phdr->cbSymOffset += diff;
-         phdr->cbOptOffset += diff;
-         phdr->cbAuxOffset += diff;
-         phdr->cbSsOffset += diff;
-         phdr->cbSsExtOffset += diff;
-         phdr->cbFdOffset += diff;
-         phdr->cbRfdOffset += diff;
-         phdr->cbExtOffset += diff;
-       }
-#endif /* __alpha__ || _SYSTYPE_SYSV */
-    }
-
-  /* Update the symbol values of _edata and _end.  */
-  for (n = new_file_h->e_shnum; 0 < --n; )
-    {
-      byte *symnames;
-      ElfW (Sym) *symp, *symendp;
-      ElfW (Shdr) *sym_shdr = &NEW_SECTION_H (n);
-
-      if (sym_shdr->sh_type != SHT_DYNSYM
-         && sym_shdr->sh_type != SHT_SYMTAB)
-       continue;
-
-      symnames = ((byte *) new_base
-                 + NEW_SECTION_H (sym_shdr->sh_link).sh_offset);
-      symp = (ElfW (Sym) *) (sym_shdr->sh_offset + new_base);
-      symendp = (ElfW (Sym) *) ((byte *) symp + sym_shdr->sh_size);
-
-      for (; symp < symendp; symp ++)
-       {
-         if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
-             || strcmp ((char *) (symnames + symp->st_name), "end") == 0
-             || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
-             || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
-           memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
-
-         /* Strictly speaking, #ifdef below is not necessary.  But we
-            keep it to indicate that this kind of change may also be
-            necessary for other unexecs to support GNUstep.  */
-#ifdef NS_IMPL_GNUSTEP
-         /* ObjC runtime modifies the values of some data structures
-            such as classes and selectors in the .data section after
-            loading.  As the dump process copies the .data section
-            from the current process, that causes problems when the
-            modified classes are reinitialized in the dumped
-            executable.  We copy such data from the old file, not
-            from the current process.  */
-         if (strncmp ((char *) (symnames + symp->st_name),
-                      "_OBJC_", sizeof ("_OBJC_") - 1) == 0)
-           {
-             ElfW (Shdr) *new_shdr = &NEW_SECTION_H (symp->st_shndx);
-             if (new_shdr->sh_type != SHT_NOBITS)
-               {
-                 ElfW (Shdr) *old_shdr = &OLD_SECTION_H (symp->st_shndx);
-                 ptrdiff_t reladdr = symp->st_value - new_shdr->sh_addr;
-                 ptrdiff_t newoff = reladdr + new_shdr->sh_offset;
-
-                 if (old_shdr->sh_type == SHT_NOBITS)
-                   memset (new_base + newoff, 0, symp->st_size);
-                 else
-                   {
-                     ptrdiff_t oldoff = reladdr + old_shdr->sh_offset;
-                     memcpy (new_base + newoff, old_base + oldoff,
-                             symp->st_size);
-                   }
-               }
-           }
-#endif
-       }
-    }
-
-  /* Modify the names of sections we changed from SHT_NOBITS to
-     SHT_PROGBITS.  This is really just cosmetic, but some tools that
-     (wrongly) operate on section names rather than types might be
-     confused by a SHT_PROGBITS .bss section.  */
-  new_section_names = ((char *) new_base
-                      + NEW_SECTION_H (new_file_h->e_shstrndx).sh_offset);
-  for (n = new_file_h->e_shnum; 0 < --n; )
-    {
-      ElfW (Shdr) *old_shdr = &OLD_SECTION_H (n);
-      ElfW (Shdr) *new_shdr = &NEW_SECTION_H (n);
-
-      /* Replace the leading '.' with ','.  When .shstrtab is string
-        merged this will rename both .bss and .rela.bss to ,bss and
-        .rela,bss.  */
-      if (old_shdr->sh_type == SHT_NOBITS
-         && new_shdr->sh_type == SHT_PROGBITS)
-       *(new_section_names + new_shdr->sh_name) = ',';
-    }
-
-  /* This loop seeks out relocation sections for the data section, so
-     that it can undo relocations performed by the runtime loader.
-
-     The following approach does not work on x86 platforms that use
-     the GNU Gold linker, which can generate .rel.dyn relocation
-     sections containing R_386_32 entries that the following code does
-     not grok.  Emacs works around this problem by avoiding C
-     constructs that generate such entries, which is horrible hack.
-
-     FIXME: Presumably more problems like this will crop up as linkers
-     get fancier.  We really need to stop assuming that Emacs can grok
-     arbitrary linker output.  See Bug#27248.  */
-  for (n = new_file_h->e_shnum; 0 < --n; )
-    {
-      ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
-      ElfW (Shdr) *shdr;
-
-      switch (rel_shdr->sh_type)
-       {
-       default:
-         break;
-       case SHT_REL:
-       case SHT_RELA:
-         /* This code handles two different size structs, but there should
-            be no harm in that provided that r_offset is always the first
-            member.  */
-         shdr = &NEW_SECTION_H (rel_shdr->sh_info);
-         if (!strcmp (old_section_names + shdr->sh_name, ".data")
-             || !strcmp (old_section_names + shdr->sh_name, ".sdata")
-             || !strcmp (old_section_names + shdr->sh_name, ".lit4")
-             || !strcmp (old_section_names + shdr->sh_name, ".lit8")
-             || !strcmp (old_section_names + shdr->sh_name, ".sdata1")
-             || !strcmp (old_section_names + shdr->sh_name, ".data1"))
-           {
-             ElfW (Addr) offset = shdr->sh_addr - shdr->sh_offset;
-             caddr_t reloc = old_base + rel_shdr->sh_offset, end;
-             for (end = reloc + rel_shdr->sh_size;
-                  reloc < end;
-                  reloc += rel_shdr->sh_entsize)
-               {
-                 ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
-                 /* Ignore R_*_NONE relocs.  */
-                 if (((ElfW (Rel) *) reloc)->r_offset == 0)
-                   continue;
-                 /* Assume reloc applies to a word.
-                    ??? This is not always true, eg. TLS module/index
-                    pair in .got which occupies two words.  */
-                 memcpy (new_base + addr, old_base + addr,
-                         sizeof (ElfW (Addr)));
-               }
-           }
-         break;
-       }
-    }
-
-  /* Write out new_file, and free the buffers.  */
-
-  if (write (new_file, new_base, new_file_size) != new_file_size)
-    fatal ("Didn't write %lu bytes to %s: %s",
-          (unsigned long) new_file_size, new_name, strerror (errno));
-  munmap (old_base, old_file_size);
-  munmap (new_base, new_file_size);
-
-  /* Close the files and make the new file executable.  */
-
-#if MAP_ANON == 0
-  emacs_close (mmap_fd);
-#endif
-
-  if (emacs_close (old_file) != 0)
-    fatal ("Can't close (%s): %s", old_name, strerror (errno));
-
-  if (emacs_close (new_file) != 0)
-    fatal ("Can't close (%s): %s", new_name, strerror (errno));
-}
diff --git a/src/unexhp9k800.c b/src/unexhp9k800.c
deleted file mode 100644
index d2943eb18c9..00000000000
--- a/src/unexhp9k800.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/* Unexec for HP 9000 Series 800 machines.
-
-  This file is in the public domain.
-
-  Author: John V. Morris
-
-  This file was written by John V. Morris at Hewlett Packard.
-  Both the author and Hewlett Packard Co. have disclaimed the
-  copyright on this file, and it is therefore in the public domain.
-  (Search for "hp9k800" in copyright.list.)
-*/
-
-/*
-   Bob Desinger <hpsemc!bd@hplabs.hp.com>
-
-   Note that the GNU project considers support for HP operation a
-   peripheral activity which should not be allowed to divert effort
-   from development of the GNU system.  Changes in this code will be
-   installed when users send them in, but aside from that we don't
-   plan to think about it, or about whether other Emacs maintenance
-   might break it.
-
-
-  Unexec creates a copy of the old a.out file, and replaces the old data
-  area with the current data area.  When the new file is executed, the
-  process will see the same data structures and data values that the
-  original process had when unexec was called.
-
-  Unlike other versions of unexec, this one copies symbol table and
-  debug information to the new a.out file.  Thus, the new a.out file
-  may be debugged with symbolic debuggers.
-
-  If you fix any bugs in this, I'd like to incorporate your fixes.
-  Send them to uunet!hpda!hpsemc!jmorris or jmorris%hpsemc@hplabs.HP.COM.
-
-  CAVEATS:
-  This routine saves the current value of all static and external
-  variables.  This means that any data structure that needs to be
-  initialized must be explicitly reset.  Variables will not have their
-  expected default values.
-
-  Unfortunately, the HP-UX signal handler has internal initialization
-  flags which are not explicitly reset.  Thus, for signals to work in
-  conjunction with this routine, the following code must executed when
-  the new process starts up.
-
-  void _sigreturn ();
-  ...
-  sigsetreturn (_sigreturn);
-*/
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-#include "sysstdio.h"
-
-#include <fcntl.h>
-#include <errno.h>
-#include <a.out.h>
-#include <dl.h>
-
-/* brk value to restore, stored as a global.
-   This is really used only if we used shared libraries.  */
-static long brk_on_dump = 0;
-
-/* Called from main, if we use shared libraries.  */
-int
-run_time_remap (char *ignored)
-{
-  brk ((char *) brk_on_dump);
-}
-
-#undef roundup
-#define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1))  /* n is power of 2 */
-
-/* Report a fatal error and exit.  */
-static _Noreturn void
-unexec_error (char const *msg)
-{
-  perror (msg);
-  exit (1);
-}
-
-/* Do an lseek and check the result.  */
-static void
-check_lseek (int fd, off_t offset, int whence)
-{
-  if (lseek (fd, offset, whence) < 0)
-    unexec_error ("Cannot lseek");
-}
-
-/* Save current data space in the file, update header.  */
-
-static void
-save_data_space (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr,
-                int size)
-{
-  /* Write the entire data space out to the file */
-  if (write (file, auxhdr->exec_dmem, size) != size)
-    unexec_error ("Can't save new data space");
-
-  /* Update the header to reflect the new data size */
-  auxhdr->exec_dsize = size;
-  auxhdr->exec_bsize = 0;
-}
-
-/* Update the values of file pointers when something is inserted.  */
-
-static void
-update_file_ptrs (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr,
-                 unsigned int location, int offset)
-{
-  struct subspace_dictionary_record subspace;
-  int i;
-
-  /* Increase the overall size of the module */
-  hdr->som_length += offset;
-
-  /* Update the various file pointers in the header */
-#define update(ptr) if (ptr > location) ptr = ptr + offset
-  update (hdr->aux_header_location);
-  update (hdr->space_strings_location);
-  update (hdr->init_array_location);
-  update (hdr->compiler_location);
-  update (hdr->symbol_location);
-  update (hdr->fixup_request_location);
-  update (hdr->symbol_strings_location);
-  update (hdr->unloadable_sp_location);
-  update (auxhdr->exec_tfile);
-  update (auxhdr->exec_dfile);
-
-  /* Do for each subspace dictionary entry */
-  check_lseek (file, hdr->subspace_location, 0);
-  for (i = 0; i < hdr->subspace_total; i++)
-    {
-      ptrdiff_t subspace_size = sizeof subspace;
-      if (read (file, &subspace, subspace_size) != subspace_size)
-       unexec_error ("Can't read subspace record");
-
-      /* If subspace has a file location, update it */
-      if (subspace.initialization_length > 0
-         && subspace.file_loc_init_value > location)
-       {
-         subspace.file_loc_init_value += offset;
-         check_lseek (file, -subspace_size, 1);
-         if (write (file, &subspace, subspace_size) != subspace_size)
-           unexec_error ("Can't update subspace record");
-       }
-    }
-
-  /* Do for each initialization pointer record */
-  /* (I don't think it applies to executable files, only relocatables) */
-#undef update
-}
-
-/* Read in the header records from an a.out file.  */
-
-static void
-read_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr)
-{
-
-  /* Read the header in */
-  check_lseek (file, 0, 0);
-  if (read (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
-    unexec_error ("Couldn't read header from a.out file");
-
-  if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
-      &&  hdr->a_magic != DEMAND_MAGIC)
-    {
-      fputs ("a.out file doesn't have valid magic number\n", stderr);
-      exit (1);
-    }
-
-  check_lseek (file, hdr->aux_header_location, 0);
-  if (read (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
-    unexec_error ("Couldn't read auxiliary header from a.out file");
-}
-
-/* Write out the header records into an a.out file.  */
-
-static void
-write_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr)
-{
-  /* Update the checksum */
-  hdr->checksum = calculate_checksum (hdr);
-
-  /* Write the header back into the a.out file */
-  check_lseek (file, 0, 0);
-  if (write (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
-    unexec_error ("Couldn't write header to a.out file");
-  check_lseek (file, hdr->aux_header_location, 0);
-  if (write (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
-    unexec_error ("Couldn't write auxiliary header to a.out file");
-}
-
-/* Calculate the checksum of a SOM header record. */
-
-static int
-calculate_checksum (struct header *hdr)
-{
-  int checksum, i, *ptr;
-
-  checksum = 0;  ptr = (int *) hdr;
-
-  for (i = 0; i < sizeof (*hdr) / sizeof (int) - 1; i++)
-    checksum ^= ptr[i];
-
-  return (checksum);
-}
-
-/* Copy size bytes from the old file to the new one.  */
-
-static void
-copy_file (int old, int new, int size)
-{
-  int len;
-  int buffer[8192];  /* word aligned will be faster */
-
-  for (; size > 0; size -= len)
-    {
-      len = min (size, sizeof (buffer));
-      if (read (old, buffer, len) != len)
-       unexec_error ("Read failure on a.out file");
-      if (write (new, buffer, len) != len)
-       unexec_error ("Write failure in a.out file");
-    }
-}
-
-/* Copy the rest of the file, up to EOF.  */
-
-static void
-copy_rest (int old, int new)
-{
-  int buffer[4096];
-  int len;
-
-  /* Copy bytes until end of file or error */
-  while ((len = read (old, buffer, sizeof (buffer))) > 0)
-    if (write (new, buffer, len) != len) break;
-
-  if (len != 0)
-    unexec_error ("Unable to copy the rest of the file");
-}
-
-#ifdef DEBUG
-static void
-display_header (struct header *hdr, struct som_exec_auxhdr *auxhdr)
-{
-  /* Display the header information (debug) */
-  printf ("\n\nFILE HEADER\n");
-  printf ("magic number %d \n", hdr->a_magic);
-  printf ("text loc %.8x   size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
-  printf ("data loc %.8x   size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
-  printf ("entry     %x \n",   auxhdr->exec_entry);
-  printf ("Bss  segment size %u\n", auxhdr->exec_bsize);
-  printf ("\n");
-  printf ("data file loc %d    size %d\n",
-         auxhdr->exec_dfile, auxhdr->exec_dsize);
-  printf ("som_length %d\n", hdr->som_length);
-  printf ("unloadable sploc %d    size %d\n",
-         hdr->unloadable_sp_location, hdr->unloadable_sp_size);
-}
-#endif /* DEBUG */
-
-
-/* Create a new a.out file, same as old but with current data space */
-void
-unexec (const char *new_name,      /* name of the new a.out file to be created 
*/
-       const char *old_name)       /* name of the old a.out file */
-{
-  int old, new;
-  int old_size, new_size;
-  struct header hdr;
-  struct som_exec_auxhdr auxhdr;
-  long i;
-
-  /* For the greatest flexibility, should create a temporary file in
-     the same directory as the new file.  When everything is complete,
-     rename the temp file to the new name.
-     This way, a program could update its own a.out file even while
-     it is still executing.  If problems occur, everything is still
-     intact.  NOT implemented.  */
-
-  /* Open the input and output a.out files.  */
-  old = emacs_open (old_name, O_RDONLY, 0);
-  if (old < 0)
-    unexec_error (old_name);
-  new = emacs_open (new_name, O_CREAT | O_RDWR | O_TRUNC, 0777);
-  if (new < 0)
-    unexec_error (new_name);
-
-  /* Read the old headers.  */
-  read_header (old, &hdr, &auxhdr);
-
-  brk_on_dump = (long) sbrk (0);
-
-  /* Decide how large the new and old data areas are.  */
-  old_size = auxhdr.exec_dsize;
-  /* I suspect these two statements are separate
-     to avoid a compiler bug in hpux version 8.  */
-  i = (long) sbrk (0);
-  new_size = i - auxhdr.exec_dmem;
-
-  /* Copy the old file to the new, up to the data space.  */
-  check_lseek (old, 0, 0);
-  copy_file (old, new, auxhdr.exec_dfile);
-
-  /* Skip the old data segment and write a new one.  */
-  check_lseek (old, old_size, 1);
-  save_data_space (new, &hdr, &auxhdr, new_size);
-
-  /* Copy the rest of the file.  */
-  copy_rest (old, new);
-
-  /* Update file pointers since we probably changed size of data area.  */
-  update_file_ptrs (new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
-
-  /* Save the modified header.  */
-  write_header (new, &hdr, &auxhdr);
-
-  /* Close the binary file.  */
-  emacs_close (old);
-  emacs_close (new);
-}
diff --git a/src/unexmacosx.c b/src/unexmacosx.c
deleted file mode 100644
index 7b2326441b4..00000000000
--- a/src/unexmacosx.c
+++ /dev/null
@@ -1,1406 +0,0 @@
-/* Dump Emacs in Mach-O format for use on macOS.
-   Copyright (C) 2001-2024 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/* Contributed by Andrew Choi (akochoi@mac.com).  */
-
-/* Documentation note.
-
-   Consult the following documents/files for a description of the
-   Mach-O format: the file loader.h, man pages for Mach-O and ld, old
-   NEXTSTEP documents of the Mach-O format.  The tool otool dumps the
-   mach header (-h option) and the load commands (-l option) in a
-   Mach-O file.  The tool nm on macOS displays the symbol table in
-   a Mach-O file.  For examples of unexec for the Mach-O format, see
-   the file unexnext.c in the GNU Emacs distribution, the file
-   unexdyld.c in the Darwin port of GNU Emacs 20.7, and unexdyld.c in
-   the Darwin port of XEmacs 21.1.  Also the Darwin Libc source
-   contains the source code for malloc_freezedry and malloc_jumpstart.
-   Read that to see what they do.  This file was written completely
-   from scratch, making use of information from the above sources.  */
-
-/* The macOS implementation of unexec makes use of Darwin's `zone'
-   memory allocator.  All calls to malloc, realloc, and free in Emacs
-   are redirected to unexec_malloc, unexec_realloc, and unexec_free in
-   this file.  When temacs is run, all memory requests are handled in
-   the zone EmacsZone.  The Darwin memory allocator library calls
-   maintain the data structures to manage this zone.  Dumping writes
-   its contents to data segments of the executable file.  When emacs
-   is run, the loader recreates the contents of the zone in memory.
-   However since the initialization routine of the zone memory
-   allocator is run again, this `zone' can no longer be used as a
-   heap.  That is why emacs uses the ordinary malloc system call to
-   allocate memory.  Also, when a block of memory needs to be
-   reallocated and the new size is larger than the old one, a new
-   block must be obtained by malloc and the old contents copied to
-   it.  */
-
-/* Peculiarity of the Mach-O files generated by ld in macOS
-   (possible causes of future bugs if changed).
-
-   The file offset of the start of the __TEXT segment is zero.  Since
-   the Mach header and load commands are located at the beginning of a
-   Mach-O file, copying the contents of the __TEXT segment from the
-   input file overwrites them in the output file.  Despite this,
-   unexec works fine as written below because the segment load command
-   for __TEXT appears, and is therefore processed, before all other
-   load commands except the segment load command for __PAGEZERO, which
-   remains unchanged.
-
-   Although the file offset of the start of the __TEXT segment is
-   zero, none of the sections it contains actually start there.  In
-   fact, the earliest one starts a few hundred bytes beyond the end of
-   the last load command.  The linker option -headerpad controls the
-   minimum size of this padding.  Its setting can be changed in
-   s/darwin.h.  A value of 0x690, e.g., leaves room for 30 additional
-   load commands for the newly created __DATA segments (at 56 bytes
-   each).  Unexec fails if there is not enough room for these new
-   segments.
-
-   The __TEXT segment contains the sections __text, __cstring,
-   __picsymbol_stub, and __const and the __DATA segment contains the
-   sections __data, __la_symbol_ptr, __nl_symbol_ptr, __dyld, __bss,
-   and __common.  The other segments do not contain any sections.
-   These sections are copied from the input file to the output file,
-   except for __data, __bss, and __common, which are dumped from
-   memory.  The types of the sections __bss and __common are changed
-   from S_ZEROFILL to S_REGULAR.  Note that the number of sections and
-   their relative order in the input and output files remain
-   unchanged.  Otherwise all n_sect fields in the nlist records in the
-   symbol table (specified by the LC_SYMTAB load command) will have to
-   be changed accordingly.
-*/
-
-#include <config.h>
-
-/* Although <config.h> redefines malloc to unexec_malloc, etc., this
-   file wants stdlib.h to declare the originals.  */
-#undef malloc
-#undef realloc
-#undef free
-
-#include <stdlib.h>
-
-#include "unexec.h"
-#include "lisp.h"
-#include "sysstdio.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <mach/mach.h>
-#include <mach/vm_map.h>
-#include <mach-o/loader.h>
-#include <mach-o/reloc.h>
-#ifdef HAVE_MALLOC_MALLOC_H
-#include <malloc/malloc.h>
-#else
-#include <objc/malloc.h>
-#endif
-
-#include <assert.h>
-
-/* LC_DATA_IN_CODE is not defined in mach-o/loader.h on Mac OS X 10.7.
-   But it is used if we build with "Command Line Tools for Xcode 4.5
-   (Mac OS X Lion) - September 2012".  */
-#ifndef LC_DATA_IN_CODE
-#define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */
-#endif
-
-#ifdef _LP64
-#define mach_header                    mach_header_64
-#define segment_command                        segment_command_64
-#undef  VM_REGION_BASIC_INFO_COUNT
-#define VM_REGION_BASIC_INFO_COUNT     VM_REGION_BASIC_INFO_COUNT_64
-#undef  VM_REGION_BASIC_INFO
-#define VM_REGION_BASIC_INFO           VM_REGION_BASIC_INFO_64
-#undef  LC_SEGMENT
-#define LC_SEGMENT                     LC_SEGMENT_64
-#define vm_region                      vm_region_64
-#define section                                section_64
-#undef MH_MAGIC
-#define MH_MAGIC                       MH_MAGIC_64
-#endif
-
-#define VERBOSE 1
-
-/* Size of buffer used to copy data from the input file to the output
-   file in function unexec_copy.  */
-#define UNEXEC_COPY_BUFSZ 1024
-
-/* Regions with memory addresses above this value are assumed to be
-   mapped to dynamically loaded libraries and will not be dumped.  */
-#define VM_DATA_TOP (20 * 1024 * 1024)
-
-/* Type of an element on the list of regions to be dumped.  */
-struct region_t {
-  vm_address_t address;
-  vm_size_t size;
-  vm_prot_t protection;
-  vm_prot_t max_protection;
-
-  struct region_t *next;
-};
-
-/* Head and tail of the list of regions to be dumped.  */
-static struct region_t *region_list_head = 0;
-static struct region_t *region_list_tail = 0;
-
-/* Pointer to array of load commands.  */
-static struct load_command **lca;
-
-/* Number of load commands.  */
-static int nlc;
-
-/* The highest VM address of segments loaded by the input file.
-   Regions with addresses beyond this are assumed to be allocated
-   dynamically and thus require dumping.  */
-static vm_address_t infile_lc_highest_addr = 0;
-
-/* The lowest file offset used by the all sections in the __TEXT
-   segments.  This leaves room at the beginning of the file to store
-   the Mach-O header.  Check this value against header size to ensure
-   the added load commands for the new __DATA segments did not
-   overwrite any of the sections in the __TEXT segment.  */
-static unsigned long text_seg_lowest_offset = 0x10000000;
-
-/* Mach header.  */
-static struct mach_header mh;
-
-/* Offset at which the next load command should be written.  */
-static unsigned long curr_header_offset = sizeof (struct mach_header);
-
-/* Offset at which the next segment should be written.  */
-static unsigned long curr_file_offset = 0;
-
-static unsigned long pagesize;
-#define ROUNDUP_TO_PAGE_BOUNDARY(x)    (((x) + pagesize - 1) & ~(pagesize - 1))
-
-static int infd, outfd;
-
-static int in_dumped_exec = 0;
-
-static malloc_zone_t *emacs_zone;
-
-/* file offset of input file's data segment */
-static off_t data_segment_old_fileoff = 0;
-
-static struct segment_command *data_segment_scp;
-
-/* Read N bytes from infd into memory starting at address DEST.
-   Return true if successful, false otherwise.  */
-static int
-unexec_read (void *dest, size_t n)
-{
-  return n == read (infd, dest, n);
-}
-
-/* Write COUNT bytes from memory starting at address SRC to outfd
-   starting at offset DEST.  Return true if successful, false
-   otherwise.  */
-static int
-unexec_write (off_t dest, const void *src, size_t count)
-{
-  task_t task = mach_task_self();
-  if (task == MACH_PORT_NULL || task == MACH_PORT_DEAD)
-    return false;
-
-  if (lseek (outfd, dest, SEEK_SET) != dest)
-    return 0;
-
-  /* We use the Mach virtual memory API to read our process memory
-     because using src directly would be undefined behavior and fails
-     under Address Sanitizer.  */
-  bool success = false;
-  vm_offset_t data;
-  mach_msg_type_number_t data_count;
-  if (vm_read (task, (uintptr_t) src, count, &data, &data_count)
-      == KERN_SUCCESS)
-    {
-      success =
-        write (outfd, (const void *) (uintptr_t) data, data_count) == count;
-      vm_deallocate (task, data, data_count);
-    }
-  return success;
-}
-
-/* Write COUNT bytes of zeros to outfd starting at offset DEST.
-   Return true if successful, false otherwise.  */
-static int
-unexec_write_zero (off_t dest, size_t count)
-{
-  char buf[UNEXEC_COPY_BUFSZ];
-  ssize_t bytes;
-
-  memset (buf, 0, UNEXEC_COPY_BUFSZ);
-  if (lseek (outfd, dest, SEEK_SET) != dest)
-    return 0;
-
-  while (count > 0)
-    {
-      bytes = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
-      if (write (outfd, buf, bytes) != bytes)
-       return 0;
-      count -= bytes;
-    }
-
-  return 1;
-}
-
-/* Copy COUNT bytes from starting offset SRC in infd to starting
-   offset DEST in outfd.  Return true if successful, false
-   otherwise.  */
-static int
-unexec_copy (off_t dest, off_t src, ssize_t count)
-{
-  ssize_t bytes_read;
-  ssize_t bytes_to_read;
-
-  char buf[UNEXEC_COPY_BUFSZ];
-
-  if (lseek (infd, src, SEEK_SET) != src)
-    return 0;
-
-  if (lseek (outfd, dest, SEEK_SET) != dest)
-    return 0;
-
-  while (count > 0)
-    {
-      bytes_to_read = count > UNEXEC_COPY_BUFSZ ? UNEXEC_COPY_BUFSZ : count;
-      bytes_read = read (infd, buf, bytes_to_read);
-      if (bytes_read <= 0)
-       return 0;
-      if (write (outfd, buf, bytes_read) != bytes_read)
-       return 0;
-      count -= bytes_read;
-    }
-
-  return 1;
-}
-
-/* Debugging and informational messages routines.  */
-
-static _Noreturn void
-unexec_error (const char *format, ...)
-{
-  va_list ap;
-
-  va_start (ap, format);
-  fputs ("unexec: ", stderr);
-  vfprintf (stderr, format, ap);
-  putc ('\n', stderr);
-  va_end (ap);
-  exit (1);
-}
-
-static void
-print_prot (vm_prot_t prot)
-{
-  if (prot == VM_PROT_NONE)
-    printf ("none");
-  else
-    {
-      putchar (prot & VM_PROT_READ ? 'r' : ' ');
-      putchar (prot & VM_PROT_WRITE ? 'w' : ' ');
-      putchar (prot & VM_PROT_EXECUTE ? 'x' : ' ');
-      putchar (' ');
-    }
-}
-
-static void
-print_region (vm_address_t address, vm_size_t size, vm_prot_t prot,
-             vm_prot_t max_prot)
-{
-  printf ("%#10lx %#8lx ", (long) address, (long) size);
-  print_prot (prot);
-  putchar (' ');
-  print_prot (max_prot);
-  putchar ('\n');
-}
-
-static void
-print_region_list (void)
-{
-  struct region_t *r;
-
-  printf ("   address     size prot maxp\n");
-
-  for (r = region_list_head; r; r = r->next)
-    print_region (r->address, r->size, r->protection, r->max_protection);
-}
-
-/* Build the list of regions that need to be dumped.  Regions with
-   addresses above VM_DATA_TOP are omitted.  Adjacent regions with
-   identical protection are merged.  Note that non-writable regions
-   cannot be omitted because they some regions created at run time are
-   read-only.  */
-static void
-build_region_list (void)
-{
-  task_t target_task = mach_task_self ();
-  vm_address_t address = (vm_address_t) 0;
-  vm_size_t size;
-  struct vm_region_basic_info info;
-  mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
-  mach_port_t object_name;
-  struct region_t *r;
-
-#if VERBOSE
-  printf ("--- List of All Regions ---\n");
-  printf ("   address     size prot maxp\n");
-#endif
-
-  while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
-                   (vm_region_info_t) &info, &info_count, &object_name)
-        == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
-    {
-      /* Done when we reach addresses of shared libraries, which are
-        loaded in high memory.  */
-      if (address >= VM_DATA_TOP)
-       break;
-
-#if VERBOSE
-      print_region (address, size, info.protection, info.max_protection);
-#endif
-
-      /* If a region immediately follows the previous one (the one
-        most recently added to the list) and has identical
-        protection, merge it with the latter.  Otherwise create a
-        new list element for it.  */
-      if (region_list_tail
-         && info.protection == region_list_tail->protection
-         && info.max_protection == region_list_tail->max_protection
-         && region_list_tail->address + region_list_tail->size == address)
-       {
-         region_list_tail->size += size;
-       }
-      else
-       {
-         r = malloc (sizeof *r);
-
-         if (!r)
-           unexec_error ("cannot allocate region structure");
-
-         r->address = address;
-         r->size = size;
-         r->protection = info.protection;
-         r->max_protection = info.max_protection;
-
-         r->next = 0;
-         if (region_list_head == 0)
-           {
-             region_list_head = r;
-             region_list_tail = r;
-           }
-         else
-           {
-             region_list_tail->next = r;
-             region_list_tail = r;
-           }
-
-         /* Deallocate (unused) object name returned by
-            vm_region.  */
-         if (object_name != MACH_PORT_NULL)
-           mach_port_deallocate (target_task, object_name);
-       }
-
-      address += size;
-    }
-
-  printf ("--- List of Regions to be Dumped ---\n");
-  print_region_list ();
-}
-
-
-#define MAX_UNEXEC_REGIONS 400
-
-static int num_unexec_regions;
-typedef struct {
-  vm_range_t range;
-  vm_size_t filesize;
-} unexec_region_info;
-static unexec_region_info unexec_regions[MAX_UNEXEC_REGIONS];
-
-static void
-unexec_regions_recorder (task_t task, void *rr, unsigned type,
-                        vm_range_t *ranges, unsigned num)
-{
-  vm_address_t p;
-  vm_size_t filesize;
-
-  while (num && num_unexec_regions < MAX_UNEXEC_REGIONS)
-    {
-      /* Subtract the size of trailing null bytes from filesize.  It
-        can be smaller than vmsize in segment commands.  In such a
-        case, trailing bytes are initialized with zeros.  */
-      for (p = ranges->address + ranges->size; p > ranges->address; p--)
-       if (*(((char *) p)-1))
-         break;
-      filesize = p - ranges->address;
-
-      unexec_regions[num_unexec_regions].filesize = filesize;
-      unexec_regions[num_unexec_regions++].range = *ranges;
-      printf ("%#10lx (sz: %#8lx/%#8lx)\n", (long) (ranges->address),
-             (long) filesize, (long) (ranges->size));
-      ranges++; num--;
-    }
-}
-
-static kern_return_t
-unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr)
-{
-  *ptr = (void *) address;
-  return KERN_SUCCESS;
-}
-
-static void
-find_emacs_zone_regions (void)
-{
-  num_unexec_regions = 0;
-
-  emacs_zone->introspect->enumerator (mach_task_self (), 0,
-                                     MALLOC_PTR_REGION_RANGE_TYPE
-                                     | MALLOC_ADMIN_REGION_RANGE_TYPE,
-                                     (vm_address_t) emacs_zone,
-                                     unexec_reader,
-                                     unexec_regions_recorder);
-
-  if (num_unexec_regions == MAX_UNEXEC_REGIONS)
-    unexec_error ("find_emacs_zone_regions: too many regions");
-}
-
-static int
-unexec_regions_sort_compare (const void *a, const void *b)
-{
-  vm_address_t aa = ((unexec_region_info *) a)->range.address;
-  vm_address_t bb = ((unexec_region_info *) b)->range.address;
-
-  if (aa < bb)
-    return -1;
-  else if (aa > bb)
-    return 1;
-  else
-    return 0;
-}
-
-static void
-unexec_regions_merge (void)
-{
-  qsort (unexec_regions, num_unexec_regions, sizeof (unexec_regions[0]),
-        &unexec_regions_sort_compare);
-
-  /* Align each region start address to a page boundary.  */
-  for (unexec_region_info *cur = unexec_regions;
-       cur < unexec_regions + num_unexec_regions; cur++)
-    {
-      vm_size_t padsize = cur->range.address & (pagesize - 1);
-      if (padsize)
-       {
-         cur->range.address -= padsize;
-         cur->range.size += padsize;
-         cur->filesize += padsize;
-
-         unexec_region_info *prev = cur == unexec_regions ? NULL : cur - 1;
-         if (prev
-             && prev->range.address + prev->range.size > cur->range.address)
-           {
-             prev->range.size = cur->range.address - prev->range.address;
-             if (prev->filesize > prev->range.size)
-               prev->filesize = prev->range.size;
-           }
-       }
-    }
-
-  int n = 0;
-  unexec_region_info r = unexec_regions[0];
-  for (int i = 1; i < num_unexec_regions; i++)
-    {
-      if (r.range.address + r.range.size == unexec_regions[i].range.address
-         && r.range.size - r.filesize < 2 * pagesize)
-       {
-         r.filesize = r.range.size + unexec_regions[i].filesize;
-         r.range.size += unexec_regions[i].range.size;
-       }
-      else
-       {
-         unexec_regions[n++] = r;
-         r = unexec_regions[i];
-       }
-    }
-  unexec_regions[n++] = r;
-  num_unexec_regions = n;
-}
-
-
-/* More informational messages routines.  */
-
-static void
-print_load_command_name (int lc)
-{
-  switch (lc)
-    {
-    case LC_SEGMENT:
-#ifndef _LP64
-      printf ("LC_SEGMENT       ");
-#else
-      printf ("LC_SEGMENT_64    ");
-#endif
-      break;
-    case LC_LOAD_DYLINKER:
-      printf ("LC_LOAD_DYLINKER ");
-      break;
-    case LC_LOAD_DYLIB:
-      printf ("LC_LOAD_DYLIB    ");
-      break;
-    case LC_SYMTAB:
-      printf ("LC_SYMTAB        ");
-      break;
-    case LC_DYSYMTAB:
-      printf ("LC_DYSYMTAB      ");
-      break;
-    case LC_UNIXTHREAD:
-      printf ("LC_UNIXTHREAD    ");
-      break;
-    case LC_PREBOUND_DYLIB:
-      printf ("LC_PREBOUND_DYLIB");
-      break;
-    case LC_TWOLEVEL_HINTS:
-      printf ("LC_TWOLEVEL_HINTS");
-      break;
-#ifdef LC_UUID
-    case LC_UUID:
-      printf ("LC_UUID          ");
-      break;
-#endif
-#ifdef LC_DYLD_INFO
-    case LC_DYLD_INFO:
-      printf ("LC_DYLD_INFO     ");
-      break;
-    case LC_DYLD_INFO_ONLY:
-      printf ("LC_DYLD_INFO_ONLY");
-      break;
-#endif
-#ifdef LC_VERSION_MIN_MACOSX
-    case LC_VERSION_MIN_MACOSX:
-      printf ("LC_VERSION_MIN_MACOSX");
-      break;
-#endif
-#ifdef LC_FUNCTION_STARTS
-    case LC_FUNCTION_STARTS:
-      printf ("LC_FUNCTION_STARTS");
-      break;
-#endif
-#ifdef LC_MAIN
-    case LC_MAIN:
-      printf ("LC_MAIN          ");
-      break;
-#endif
-#ifdef LC_DATA_IN_CODE
-    case LC_DATA_IN_CODE:
-      printf ("LC_DATA_IN_CODE  ");
-      break;
-#endif
-#ifdef LC_SOURCE_VERSION
-    case LC_SOURCE_VERSION:
-      printf ("LC_SOURCE_VERSION");
-      break;
-#endif
-#ifdef LC_DYLIB_CODE_SIGN_DRS
-    case LC_DYLIB_CODE_SIGN_DRS:
-      printf ("LC_DYLIB_CODE_SIGN_DRS");
-      break;
-#endif
-    default:
-      printf ("unknown          ");
-    }
-}
-
-static void
-print_load_command (struct load_command *lc)
-{
-  print_load_command_name (lc->cmd);
-  printf ("%8d", lc->cmdsize);
-
-  if (lc->cmd == LC_SEGMENT)
-    {
-      struct segment_command *scp;
-      struct section *sectp;
-      int j;
-
-      scp = (struct segment_command *) lc;
-      printf (" %-16.16s %#10lx %#8lx\n",
-             scp->segname, (long) (scp->vmaddr), (long) (scp->vmsize));
-
-      sectp = (struct section *) (scp + 1);
-      for (j = 0; j < scp->nsects; j++)
-       {
-         printf ("                           %-16.16s %#10lx %#8lx\n",
-                 sectp->sectname, (long) (sectp->addr), (long) (sectp->size));
-         sectp++;
-       }
-    }
-  else
-    printf ("\n");
-}
-
-/* Read header and load commands from input file.  Store the latter in
-   the global array lca.  Store the total number of load commands in
-   global variable nlc.  */
-static void
-read_load_commands (void)
-{
-  int i;
-
-  if (!unexec_read (&mh, sizeof (struct mach_header)))
-    unexec_error ("cannot read mach-o header");
-
-  if (mh.magic != MH_MAGIC)
-    unexec_error ("input file not in Mach-O format");
-
-  if (mh.filetype != MH_EXECUTE)
-    unexec_error ("input Mach-O file is not an executable object file");
-
-#if VERBOSE
-  printf ("--- Header Information ---\n");
-  printf ("Magic = 0x%08x\n", mh.magic);
-  printf ("CPUType = %d\n", mh.cputype);
-  printf ("CPUSubType = %d\n", mh.cpusubtype);
-  printf ("FileType = 0x%x\n", mh.filetype);
-  printf ("NCmds = %d\n", mh.ncmds);
-  printf ("SizeOfCmds = %d\n", mh.sizeofcmds);
-  printf ("Flags = 0x%08x\n", mh.flags);
-#endif
-
-  nlc = mh.ncmds;
-  lca = malloc (nlc * sizeof *lca);
-
-  for (i = 0; i < nlc; i++)
-    {
-      struct load_command lc;
-      /* Load commands are variable-size: so read the command type and
-        size first and then read the rest.  */
-      if (!unexec_read (&lc, sizeof (struct load_command)))
-        unexec_error ("cannot read load command");
-      lca[i] = malloc (lc.cmdsize);
-      memcpy (lca[i], &lc, sizeof (struct load_command));
-      if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command)))
-        unexec_error ("cannot read content of load command");
-      if (lc.cmd == LC_SEGMENT)
-       {
-         struct segment_command *scp = (struct segment_command *) lca[i];
-
-         if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr)
-           infile_lc_highest_addr = scp->vmaddr + scp->vmsize;
-
-         if (strncmp (scp->segname, SEG_TEXT, 16) == 0)
-           {
-             struct section *sectp = (struct section *) (scp + 1);
-             int j;
-
-             for (j = 0; j < scp->nsects; j++)
-               if (sectp->offset < text_seg_lowest_offset)
-                 text_seg_lowest_offset = sectp->offset;
-           }
-       }
-    }
-
-  printf ("Highest address of load commands in input file: %#8lx\n",
-         (unsigned long)infile_lc_highest_addr);
-
-  printf ("Lowest offset of all sections in __TEXT segment: %#8lx\n",
-         text_seg_lowest_offset);
-
-  printf ("--- List of Load Commands in Input File ---\n");
-  printf ("# cmd              cmdsize name                address     size\n");
-
-  for (i = 0; i < nlc; i++)
-    {
-      printf ("%1d ", i);
-      print_load_command (lca[i]);
-    }
-}
-
-/* Copy a LC_SEGMENT load command other than the __DATA segment from
-   the input file to the output file, adjusting the file offset of the
-   segment and the file offsets of sections contained in it.  */
-static void
-copy_segment (struct load_command *lc)
-{
-  struct segment_command *scp = (struct segment_command *) lc;
-  unsigned long old_fileoff = scp->fileoff;
-  struct section *sectp;
-  int j;
-
-  scp->fileoff = curr_file_offset;
-
-  sectp = (struct section *) (scp + 1);
-  for (j = 0; j < scp->nsects; j++)
-    {
-      sectp->offset += curr_file_offset - old_fileoff;
-      sectp++;
-    }
-
-  printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
-         scp->segname, (long) (scp->fileoff), (long) (scp->filesize),
-         (long) (scp->vmsize), (long) (scp->vmaddr));
-
-  if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize))
-    unexec_error ("cannot copy segment from input to output file");
-  curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize);
-
-  if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
-    unexec_error ("cannot write load command to header");
-
-  curr_header_offset += lc->cmdsize;
-}
-
-/* Copy a LC_SEGMENT load command for the __DATA segment in the input
-   file to the output file.  We assume that only one such segment load
-   command exists in the input file and it contains the sections
-   __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and
-   __dyld.  The first three of these should be dumped from memory and
-   the rest should be copied from the input file.  Note that the
-   sections __bss and __common contain no data in the input file
-   because their flag fields have the value S_ZEROFILL.  Dumping these
-   from memory makes it necessary to adjust file offset fields in
-   subsequently dumped load commands.  Then, create new __DATA segment
-   load commands for regions on the region list other than the one
-   corresponding to the __DATA segment in the input file.  */
-static void
-copy_data_segment (struct load_command *lc)
-{
-  struct segment_command *scp = (struct segment_command *) lc;
-  struct section *sectp;
-  int j;
-  unsigned long header_offset, old_file_offset;
-
-  /* The new filesize of the segment is set to its vmsize because data
-     blocks for segments must start at region boundaries.  Note that
-     this may leave unused locations at the end of the segment data
-     block because the total of the sizes of all sections in the
-     segment is generally smaller than vmsize.  */
-  scp->filesize = scp->vmsize;
-
-  printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
-         scp->segname, curr_file_offset, (long)(scp->filesize),
-         (long)(scp->vmsize), (long) (scp->vmaddr));
-
-  /* Offsets in the output file for writing the next section structure
-     and segment data block, respectively.  */
-  header_offset = curr_header_offset + sizeof (struct segment_command);
-
-  sectp = (struct section *) (scp + 1);
-  for (j = 0; j < scp->nsects; j++)
-    {
-      old_file_offset = sectp->offset;
-      sectp->offset = sectp->addr - scp->vmaddr + curr_file_offset;
-      /* The __data section is dumped from memory.  The __bss and
-        __common sections are also dumped from memory but their flag
-        fields require changing (from S_ZEROFILL to S_REGULAR).  The
-        other three kinds of sections are just copied from the input
-        file.  */
-      if (strncmp (sectp->sectname, SECT_DATA, 16) == 0)
-       {
-         unsigned long my_size;
-
-         /* The __data section is basically dumped from memory.  But
-            initialized data in statically linked libraries are
-            copied from the input file.  In particular,
-            add_image_hook.names and add_image_hook.pointers stored
-            by libarclite_macosx.a, are restored so that they will be
-            reinitialized when the dumped binary is executed.  */
-         my_size = (unsigned long)my_edata - sectp->addr;
-         if (!(sectp->addr <= (unsigned long)my_edata
-               && my_size <= sectp->size))
-           unexec_error ("my_edata is not in section %s", SECT_DATA);
-         if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
-           unexec_error ("cannot write section %s", SECT_DATA);
-         if (!unexec_copy (sectp->offset + my_size, old_file_offset + my_size,
-                           sectp->size - my_size))
-           unexec_error ("cannot copy section %s", SECT_DATA);
-         if (!unexec_write (header_offset, sectp, sizeof (struct section)))
-           unexec_error ("cannot write section %s's header", SECT_DATA);
-       }
-      else if (strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
-       {
-         sectp->flags = S_REGULAR;
-         if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
-           unexec_error ("cannot write section %.16s", sectp->sectname);
-         if (!unexec_write (header_offset, sectp, sizeof (struct section)))
-           unexec_error ("cannot write section %.16s's header", 
sectp->sectname);
-       }
-      else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0)
-       {
-         unsigned long my_size;
-
-         sectp->flags = S_REGULAR;
-
-         /* Clear uninitialized local variables in statically linked
-            libraries.  In particular, function pointers stored by
-            libSystemStub.a, which is introduced in Mac OS X 10.4 for
-            binary compatibility with respect to long double, are
-            cleared so that they will be reinitialized when the
-            dumped binary is executed on other versions of OS.  */
-         my_size = (unsigned long)my_endbss_static - sectp->addr;
-         if (!(sectp->addr <= (unsigned long)my_endbss_static
-               && my_size <= sectp->size))
-           unexec_error ("my_endbss_static is not in section %.16s",
-                         sectp->sectname);
-         if (!unexec_write (sectp->offset, (void *) sectp->addr, my_size))
-           unexec_error ("cannot write section %.16s", sectp->sectname);
-         if (!unexec_write_zero (sectp->offset + my_size,
-                                 sectp->size - my_size))
-           unexec_error ("cannot write section %.16s", sectp->sectname);
-         if (!unexec_write (header_offset, sectp, sizeof (struct section)))
-           unexec_error ("cannot write section %.16s's header", 
sectp->sectname);
-       }
-      else if (strncmp (sectp->sectname, "__bss", 5) == 0
-              || strncmp (sectp->sectname, "__pu_bss", 8) == 0)
-       {
-         sectp->flags = S_REGULAR;
-
-         /* These sections are produced by GCC 4.6+.
-
-            FIXME: We possibly ought to clear uninitialized local
-            variables in statically linked libraries like for
-            SECT_BSS (__bss) above, but setting up the markers we
-            need in lastfile.c would be rather messy. See
-            darwin_output_aligned_bss () in gcc/config/darwin.c for
-            the root of the problem, keeping in mind that the
-            sections are numbered by their alignment in GCC 4.6, but
-            by log2(alignment) in GCC 4.7. */
-
-         if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
-           unexec_error ("cannot copy section %.16s", sectp->sectname);
-         if (!unexec_write (header_offset, sectp, sizeof (struct section)))
-           unexec_error ("cannot write section %.16s's header", 
sectp->sectname);
-       }
-      else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0
-              || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0
-              || strncmp (sectp->sectname, "__got", 16) == 0
-              || strncmp (sectp->sectname, "__la_sym_ptr2", 16) == 0
-              || strncmp (sectp->sectname, "__dyld", 16) == 0
-              || strncmp (sectp->sectname, "__const", 16) == 0
-              || strncmp (sectp->sectname, "__cfstring", 16) == 0
-              || strncmp (sectp->sectname, "__gcc_except_tab", 16) == 0
-              || strncmp (sectp->sectname, "__program_vars", 16) == 0
-              || strncmp (sectp->sectname, "__mod_init_func", 16) == 0
-              || strncmp (sectp->sectname, "__mod_term_func", 16) == 0
-              || strncmp (sectp->sectname, "__static_data", 16) == 0
-              || strncmp (sectp->sectname, "__objc_", 7) == 0)
-       {
-         if (!unexec_copy (sectp->offset, old_file_offset, sectp->size))
-           unexec_error ("cannot copy section %.16s", sectp->sectname);
-         if (!unexec_write (header_offset, sectp, sizeof (struct section)))
-           unexec_error ("cannot write section %.16s's header", 
sectp->sectname);
-       }
-      else
-       unexec_error ("unrecognized section %.16s in __DATA segment",
-                     sectp->sectname);
-
-      printf ("        section %-16.16s at %#8lx - %#8lx (sz: %#8lx)\n",
-             sectp->sectname, (long) (sectp->offset),
-             (long) (sectp->offset + sectp->size), (long) (sectp->size));
-
-      header_offset += sizeof (struct section);
-      sectp++;
-    }
-
-  curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (scp->filesize);
-
-  if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command)))
-    unexec_error ("cannot write header of __DATA segment");
-  curr_header_offset += lc->cmdsize;
-
-  /* Create new __DATA segment load commands for regions on the region
-     list that do not corresponding to any segment load commands in
-     the input file.
-  */
-  for (j = 0; j < num_unexec_regions; j++)
-    {
-      struct segment_command sc;
-
-      sc.cmd = LC_SEGMENT;
-      sc.cmdsize = sizeof (struct segment_command);
-      strncpy (sc.segname, SEG_DATA, 16);
-      sc.vmaddr = unexec_regions[j].range.address;
-      sc.vmsize = unexec_regions[j].range.size;
-      sc.fileoff = curr_file_offset;
-      sc.filesize = unexec_regions[j].filesize;
-      sc.maxprot = VM_PROT_READ | VM_PROT_WRITE;
-      sc.initprot = VM_PROT_READ | VM_PROT_WRITE;
-      sc.nsects = 0;
-      sc.flags = 0;
-
-      printf ("Writing segment %-16.16s @ %#8lx (%#8lx/%#8lx @ %#10lx)\n",
-             sc.segname, (long) (sc.fileoff), (long) (sc.filesize),
-             (long) (sc.vmsize), (long) (sc.vmaddr));
-
-      if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.filesize))
-       unexec_error ("cannot write new __DATA segment");
-      curr_file_offset += ROUNDUP_TO_PAGE_BOUNDARY (sc.filesize);
-
-      if (!unexec_write (curr_header_offset, &sc, sc.cmdsize))
-       unexec_error ("cannot write new __DATA segment's header");
-      curr_header_offset += sc.cmdsize;
-      mh.ncmds++;
-    }
-}
-
-/* Copy a LC_SYMTAB load command from the input file to the output
-   file, adjusting the file offset fields.  */
-static void
-copy_symtab (struct load_command *lc, long delta)
-{
-  struct symtab_command *stp = (struct symtab_command *) lc;
-
-  stp->symoff += delta;
-  stp->stroff += delta;
-
-  printf ("Writing LC_SYMTAB command\n");
-
-  if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
-    unexec_error ("cannot write symtab command to header");
-
-  curr_header_offset += lc->cmdsize;
-}
-
-/* Fix up relocation entries. */
-static void
-unrelocate (const char *name, off_t reloff, int nrel, vm_address_t base)
-{
-  int i, unreloc_count;
-  struct relocation_info reloc_info;
-  struct scattered_relocation_info *sc_reloc_info
-    = (struct scattered_relocation_info *) &reloc_info;
-  vm_address_t location;
-
-  for (unreloc_count = 0, i = 0; i < nrel; i++)
-    {
-      if (lseek (infd, reloff, L_SET) != reloff)
-       unexec_error ("unrelocate: %s:%d cannot seek to reloc_info", name, i);
-      if (!unexec_read (&reloc_info, sizeof (reloc_info)))
-       unexec_error ("unrelocate: %s:%d cannot read reloc_info", name, i);
-      reloff += sizeof (reloc_info);
-
-      if (sc_reloc_info->r_scattered == 0)
-       switch (reloc_info.r_type)
-         {
-         case GENERIC_RELOC_VANILLA:
-           location = base + reloc_info.r_address;
-           if (location >= data_segment_scp->vmaddr
-               && location < (data_segment_scp->vmaddr
-                              + data_segment_scp->vmsize))
-             {
-               off_t src_off = data_segment_old_fileoff
-                 + (location - data_segment_scp->vmaddr);
-               off_t dst_off = data_segment_scp->fileoff
-                 + (location - data_segment_scp->vmaddr);
-
-               if (!unexec_copy (dst_off, src_off, 1 << reloc_info.r_length))
-                 unexec_error ("unrelocate: %s:%d cannot copy original value",
-                               name, i);
-               unreloc_count++;
-             }
-           break;
-         default:
-           unexec_error ("unrelocate: %s:%d cannot handle type = %d",
-                         name, i, reloc_info.r_type);
-         }
-      else
-        unexec_error ("unrelocate: %s:%d cannot handle scattered type = %d",
-                      name, i, sc_reloc_info->r_type);
-    }
-
-  if (nrel > 0)
-    printf ("Fixed up %d/%d %s relocation entries in data segment.\n",
-           unreloc_count, nrel, name);
-}
-
-/* Copy a LC_DYSYMTAB load command from the input file to the output
-   file, adjusting the file offset fields.  */
-static void
-copy_dysymtab (struct load_command *lc, long delta)
-{
-  struct dysymtab_command *dstp = (struct dysymtab_command *) lc;
-  vm_address_t base;
-
-#ifdef _LP64
-  /* First writable segment address.  */
-  base = data_segment_scp->vmaddr;
-#else
-  /* First segment address in the file (unless MH_SPLIT_SEGS set). */
-  base = 0;
-#endif
-
-  unrelocate ("local", dstp->locreloff, dstp->nlocrel, base);
-  unrelocate ("external", dstp->extreloff, dstp->nextrel, base);
-
-  if (dstp->nextrel > 0) {
-    dstp->extreloff += delta;
-  }
-
-  if (dstp->nlocrel > 0) {
-    dstp->locreloff += delta;
-  }
-
-  if (dstp->nindirectsyms > 0)
-    dstp->indirectsymoff += delta;
-
-  printf ("Writing LC_DYSYMTAB command\n");
-
-  if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
-    unexec_error ("cannot write symtab command to header");
-
-  curr_header_offset += lc->cmdsize;
-}
-
-/* Copy a LC_TWOLEVEL_HINTS load command from the input file to the output
-   file, adjusting the file offset fields.  */
-static void
-copy_twolevelhints (struct load_command *lc, long delta)
-{
-  struct twolevel_hints_command *tlhp = (struct twolevel_hints_command *) lc;
-
-  if (tlhp->nhints > 0) {
-    tlhp->offset += delta;
-  }
-
-  printf ("Writing LC_TWOLEVEL_HINTS command\n");
-
-  if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
-    unexec_error ("cannot write two level hint command to header");
-
-  curr_header_offset += lc->cmdsize;
-}
-
-#ifdef LC_DYLD_INFO
-/* Copy a LC_DYLD_INFO(_ONLY) load command from the input file to the output
-   file, adjusting the file offset fields.  */
-static void
-copy_dyld_info (struct load_command *lc, long delta)
-{
-  struct dyld_info_command *dip = (struct dyld_info_command *) lc;
-
-  if (dip->rebase_off > 0)
-    dip->rebase_off += delta;
-  if (dip->bind_off > 0)
-    dip->bind_off += delta;
-  if (dip->weak_bind_off > 0)
-    dip->weak_bind_off += delta;
-  if (dip->lazy_bind_off > 0)
-    dip->lazy_bind_off += delta;
-  if (dip->export_off > 0)
-    dip->export_off += delta;
-
-  printf ("Writing ");
-  print_load_command_name (lc->cmd);
-  printf (" command\n");
-
-  if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
-    unexec_error ("cannot write dyld info command to header");
-
-  curr_header_offset += lc->cmdsize;
-}
-#endif
-
-#ifdef LC_FUNCTION_STARTS
-/* Copy a LC_FUNCTION_STARTS/LC_DATA_IN_CODE/LC_DYLIB_CODE_SIGN_DRS
-   load command from the input file to the output file, adjusting the
-   data offset field.  */
-static void
-copy_linkedit_data (struct load_command *lc, long delta)
-{
-  struct linkedit_data_command *ldp = (struct linkedit_data_command *) lc;
-
-  if (ldp->dataoff > 0)
-    ldp->dataoff += delta;
-
-  printf ("Writing ");
-  print_load_command_name (lc->cmd);
-  printf (" command\n");
-
-  if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
-    unexec_error ("cannot write linkedit data command to header");
-
-  curr_header_offset += lc->cmdsize;
-}
-#endif
-
-/* Copy other kinds of load commands from the input file to the output
-   file, ones that do not require adjustments of file offsets.  */
-static void
-copy_other (struct load_command *lc)
-{
-  printf ("Writing ");
-  print_load_command_name (lc->cmd);
-  printf (" command\n");
-
-  if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
-    unexec_error ("cannot write symtab command to header");
-
-  curr_header_offset += lc->cmdsize;
-}
-
-/* Loop through all load commands and dump them.  Then write the Mach
-   header.  */
-static void
-dump_it (void)
-{
-  int i;
-  long linkedit_delta = 0;
-
-  printf ("--- Load Commands written to Output File ---\n");
-
-  for (i = 0; i < nlc; i++)
-    switch (lca[i]->cmd)
-      {
-      case LC_SEGMENT:
-       {
-         struct segment_command *scp = (struct segment_command *) lca[i];
-         if (strncmp (scp->segname, SEG_DATA, 16) == 0)
-           {
-             /* save data segment file offset and segment_command for
-                unrelocate */
-             if (data_segment_old_fileoff)
-               unexec_error ("cannot handle multiple DATA segments"
-                             " in input file");
-             data_segment_old_fileoff = scp->fileoff;
-             data_segment_scp = scp;
-
-             copy_data_segment (lca[i]);
-           }
-         else
-           {
-             if (strncmp (scp->segname, SEG_LINKEDIT, 16) == 0)
-               {
-                 if (linkedit_delta)
-                   unexec_error ("cannot handle multiple LINKEDIT segments"
-                                 " in input file");
-                 linkedit_delta = curr_file_offset - scp->fileoff;
-               }
-
-             copy_segment (lca[i]);
-           }
-       }
-       break;
-      case LC_SYMTAB:
-       copy_symtab (lca[i], linkedit_delta);
-       break;
-      case LC_DYSYMTAB:
-       copy_dysymtab (lca[i], linkedit_delta);
-       break;
-      case LC_TWOLEVEL_HINTS:
-       copy_twolevelhints (lca[i], linkedit_delta);
-       break;
-#ifdef LC_DYLD_INFO
-      case LC_DYLD_INFO:
-      case LC_DYLD_INFO_ONLY:
-       copy_dyld_info (lca[i], linkedit_delta);
-       break;
-#endif
-#ifdef LC_FUNCTION_STARTS
-      case LC_FUNCTION_STARTS:
-#ifdef LC_DATA_IN_CODE
-      case LC_DATA_IN_CODE:
-#endif
-#ifdef LC_DYLIB_CODE_SIGN_DRS
-      case LC_DYLIB_CODE_SIGN_DRS:
-#endif
-       copy_linkedit_data (lca[i], linkedit_delta);
-       break;
-#endif
-      default:
-       copy_other (lca[i]);
-       break;
-      }
-
-  if (curr_header_offset > text_seg_lowest_offset)
-    unexec_error ("not enough room for load commands for new __DATA segments"
-                 " (increase headerpad_extra in configure.in to at least %lX)",
-                 num_unexec_regions * sizeof (struct segment_command));
-
-  printf ("%ld unused bytes follow Mach-O header\n",
-         text_seg_lowest_offset - curr_header_offset);
-
-  mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header);
-  if (!unexec_write (0, &mh, sizeof (struct mach_header)))
-    unexec_error ("cannot write final header contents");
-}
-
-/* Take a snapshot of Emacs and make a Mach-O format executable file
-   from it.  The file names of the output and input files are outfile
-   and infile, respectively.  The three other parameters are
-   ignored.  */
-void
-unexec (const char *outfile, const char *infile)
-{
-  if (in_dumped_exec)
-    unexec_error ("Unexec from a dumped executable is not supported.");
-
-  pagesize = getpagesize ();
-  infd = emacs_open (infile, O_RDONLY, 0);
-  if (infd < 0)
-    {
-      unexec_error ("%s: %s", infile, strerror (errno));
-    }
-
-  outfd = emacs_open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0777);
-  if (outfd < 0)
-    {
-      emacs_close (infd);
-      unexec_error ("%s: %s", outfile, strerror (errno));
-    }
-
-  build_region_list ();
-  read_load_commands ();
-
-  find_emacs_zone_regions ();
-  unexec_regions_merge ();
-
-  in_dumped_exec = 1;
-
-  dump_it ();
-
-  emacs_close (outfd);
-}
-
-
-void
-unexec_init_emacs_zone (void)
-{
-  emacs_zone = malloc_create_zone (0, 0);
-  malloc_set_zone_name (emacs_zone, "EmacsZone");
-}
-
-#ifndef MACOSX_MALLOC_MULT16
-#define MACOSX_MALLOC_MULT16 1
-#endif
-
-typedef struct unexec_malloc_header {
-  union {
-    char c[8];
-    size_t size;
-  } u;
-} unexec_malloc_header_t;
-
-#if MACOSX_MALLOC_MULT16
-
-#define ptr_in_unexec_regions(p) ((((vm_address_t) (p)) & 8) != 0)
-
-#else
-
-int
-ptr_in_unexec_regions (void *ptr)
-{
-  int i;
-
-  for (i = 0; i < num_unexec_regions; i++)
-    if ((vm_address_t) ptr - unexec_regions[i].range.address
-       < unexec_regions[i].range.size)
-      return 1;
-
-  return 0;
-}
-
-#endif
-
-void *
-unexec_malloc (size_t size)
-{
-  if (in_dumped_exec)
-    {
-      void *p;
-
-      p = malloc (size);
-#if MACOSX_MALLOC_MULT16
-      assert (((vm_address_t) p % 16) == 0);
-#endif
-      return p;
-    }
-  else
-    {
-      unexec_malloc_header_t *ptr;
-
-      ptr = (unexec_malloc_header_t *)
-       malloc_zone_malloc (emacs_zone, size + sizeof (unexec_malloc_header_t));
-      ptr->u.size = size;
-      ptr++;
-#if MACOSX_MALLOC_MULT16
-      assert (((vm_address_t) ptr % 16) == 8);
-#endif
-      return (void *) ptr;
-    }
-}
-
-void *
-unexec_realloc (void *old_ptr, size_t new_size)
-{
-  if (in_dumped_exec)
-    {
-      void *p;
-
-      if (ptr_in_unexec_regions (old_ptr))
-       {
-         size_t old_size = ((unexec_malloc_header_t *) old_ptr)[-1].u.size;
-         size_t size = new_size > old_size ? old_size : new_size;
-
-         p = malloc (new_size);
-         if (size)
-           memcpy (p, old_ptr, size);
-       }
-      else
-       {
-         p = realloc (old_ptr, new_size);
-       }
-#if MACOSX_MALLOC_MULT16
-      assert (((vm_address_t) p % 16) == 0);
-#endif
-      return p;
-    }
-  else
-    {
-      unexec_malloc_header_t *ptr;
-
-      ptr = (unexec_malloc_header_t *)
-       malloc_zone_realloc (emacs_zone, (unexec_malloc_header_t *) old_ptr - 1,
-                            new_size + sizeof (unexec_malloc_header_t));
-      ptr->u.size = new_size;
-      ptr++;
-#if MACOSX_MALLOC_MULT16
-      assert (((vm_address_t) ptr % 16) == 8);
-#endif
-      return (void *) ptr;
-    }
-}
-
-void
-unexec_free (void *ptr)
-{
-  if (ptr == NULL)
-    return;
-  if (in_dumped_exec)
-    {
-      if (!ptr_in_unexec_regions (ptr))
-       free (ptr);
-    }
-  else
-    malloc_zone_free (emacs_zone, (unexec_malloc_header_t *) ptr - 1);
-}
diff --git a/src/unexsol.c b/src/unexsol.c
deleted file mode 100644
index 0f84099d39e..00000000000
--- a/src/unexsol.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Trivial unexec for Solaris.  */
-
-#include <config.h>
-#include "unexec.h"
-
-#include <dlfcn.h>
-
-#include "lisp.h"
-#include "buffer.h"
-#include "coding.h"
-
-void
-unexec (const char *new_name, const char *old_name)
-{
-  Lisp_Object data;
-  Lisp_Object errstring;
-
-  if (! dldump (0, new_name, RTLD_MEMORY))
-    return;
-
-  data = list1 (build_string (new_name));
-  synchronize_system_messages_locale ();
-  errstring = code_convert_string_norecord (build_string (dlerror ()),
-                                           Vlocale_coding_system, 0);
-
-  xsignal (Qfile_error,
-          Fcons (build_string ("Cannot unexec"), Fcons (errstring, data)));
-}
diff --git a/src/unexw32.c b/src/unexw32.c
deleted file mode 100644
index f0a910781cc..00000000000
--- a/src/unexw32.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/* unexec for GNU Emacs on Windows NT.
-   Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/*
-   Geoff Voelker (voelker@cs.washington.edu)                         8-12-94
-*/
-
-#include <config.h>
-#include "unexec.h"
-#include "lisp.h"
-#include "w32common.h"
-#include "w32.h"
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <time.h>
-#include <windows.h>
-
-/* Include relevant definitions from IMAGEHLP.H, which can be found
-   in \\win32sdk\mstools\samples\image\include\imagehlp.h. */
-
-PIMAGE_NT_HEADERS (__stdcall * pfnCheckSumMappedFile) (LPVOID BaseAddress,
-                                                      DWORD FileLength,
-                                                      LPDWORD HeaderSum,
-                                                      LPDWORD CheckSum);
-
-extern char my_begdata[];
-extern char my_begbss[];
-extern char *my_begbss_static;
-
-#include "w32heap.h"
-
-void get_section_info (file_data *p_file);
-void copy_executable_and_dump_data (file_data *, file_data *);
-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;
-PCHAR  data_start = 0;
-DWORD_PTR  data_size = 0;
-
-/* Cached info about the .bss section in the executable.  */
-PIMAGE_SECTION_HEADER bss_section;
-PCHAR  bss_start = 0;
-DWORD_PTR  bss_size = 0;
-DWORD_PTR  extra_bss_size = 0;
-/* bss data that is static might be discontiguous from non-static.  */
-PIMAGE_SECTION_HEADER bss_section_static;
-PCHAR  bss_start_static = 0;
-DWORD_PTR  bss_size_static = 0;
-DWORD_PTR  extra_bss_size_static = 0;
-
-/* File handling.  */
-
-/* Implementation note: this and the next functions work with ANSI
-   codepage encoded file names!  */
-
-int
-open_output_file (file_data *p_file, char *filename, unsigned long size)
-{
-  HANDLE file;
-  HANDLE file_mapping;
-  void  *file_base;
-
-  /* We delete any existing FILENAME because loadup.el will create a
-     hard link to it under the name emacs-XX.YY.ZZ.nn.exe.  Evidently,
-     overwriting a file on Unix breaks any hard links to it, but that
-     doesn't happen on Windows.  If we don't delete the file before
-     creating it, all the emacs-XX.YY.ZZ.nn.exe end up being hard
-     links to the same file, which defeats the purpose of these hard
-     links: being able to run previous builds.  */
-  DeleteFileA (filename);
-  file = CreateFileA (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
-                     CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
-  if (file == INVALID_HANDLE_VALUE)
-    return FALSE;
-
-  file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
-                                   0, size, NULL);
-  if (!file_mapping)
-    return FALSE;
-
-  file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
-  if (file_base == 0)
-    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;
-}
-
-
-/* Routines to manipulate NT executable file sections.  */
-
-/* Return pointer to section header for named section. */
-IMAGE_SECTION_HEADER *
-find_section (const 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++)
-    {
-      if (strcmp ((char *)section->Name, name) == 0)
-       return section;
-      section++;
-    }
-  return NULL;
-}
-
-#if 0  /* unused */
-/* Return pointer to section header for section containing the given
-   offset in its raw data area. */
-static IMAGE_SECTION_HEADER *
-offset_to_section (DWORD_PTR offset, 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 (offset >= section->PointerToRawData
-         && offset < section->PointerToRawData + section->SizeOfRawData)
-       return section;
-      section++;
-    }
-  return NULL;
-}
-#endif
-
-/* 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_PTR
-relocate_offset (DWORD_PTR offset,
-                IMAGE_NT_HEADERS * src_nt_header,
-                IMAGE_NT_HEADERS * dst_nt_header)
-{
-  PIMAGE_SECTION_HEADER src_section = IMAGE_FIRST_SECTION (src_nt_header);
-  PIMAGE_SECTION_HEADER dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
-  int i = 0;
-
-  while (offset >= src_section->PointerToRawData)
-    {
-      if (offset < src_section->PointerToRawData + src_section->SizeOfRawData)
-       break;
-      i++;
-      if (i == src_nt_header->FileHeader.NumberOfSections)
-       {
-         /* Handle offsets after the last section.  */
-         dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
-         dst_section += dst_nt_header->FileHeader.NumberOfSections - 1;
-         while (dst_section->PointerToRawData == 0)
-           dst_section--;
-         while (src_section->PointerToRawData == 0)
-           src_section--;
-         return offset
-           + (dst_section->PointerToRawData + dst_section->SizeOfRawData)
-           - (src_section->PointerToRawData + src_section->SizeOfRawData);
-       }
-      src_section++;
-      dst_section++;
-    }
-  return offset +
-    (dst_section->PointerToRawData - src_section->PointerToRawData);
-}
-
-#define RVA_TO_OFFSET(rva, section) \
-  ((section)->PointerToRawData + ((DWORD_PTR)(rva) - 
(section)->VirtualAddress))
-
-#define RVA_TO_SECTION_OFFSET(rva, section) \
-  ((DWORD_PTR)(rva) - (section)->VirtualAddress)
-
-/* Convert address in executing image to RVA.  */
-#define PTR_TO_RVA(ptr) ((DWORD_PTR)(ptr) - (DWORD_PTR) GetModuleHandle (NULL))
-
-#define PTR_TO_OFFSET(ptr, pfile_data) \
-          ((unsigned char *)(ptr) - (pfile_data)->file_base)
-
-#define OFFSET_TO_PTR(offset, pfile_data) \
-          ((pfile_data)->file_base + (DWORD_PTR)(offset))
-
-#if 0  /* unused */
-#define OFFSET_TO_RVA(offset, section) \
-  ((section)->VirtualAddress + ((DWORD_PTR)(offset) - 
(section)->PointerToRawData))
-
-#define RVA_TO_PTR(var,section,filedata) \
-         ((unsigned char *)(RVA_TO_OFFSET (var,section) + 
(filedata).file_base))
-#endif
-
-
-/* Flip through the executable and cache the info necessary for dumping.  */
-void
-get_section_info (file_data *p_infile)
-{
-  PIMAGE_DOS_HEADER dos_header;
-  PIMAGE_NT_HEADERS nt_header;
-  int overlap;
-
-  dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
-  if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
-    {
-      printf ("Unknown EXE header in %s...bailing.\n", p_infile->name);
-      exit (1);
-    }
-  nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
-                                  dos_header->e_lfanew);
-  if (nt_header == NULL)
-    {
-      printf ("Failed to find IMAGE_NT_HEADER in %s...bailing.\n",
-            p_infile->name);
-      exit (1);
-    }
-
-  /* Check the NT header signature ...  */
-  if (nt_header->Signature != IMAGE_NT_SIGNATURE)
-    {
-      printf ("Invalid IMAGE_NT_SIGNATURE 0x%lx in %s...bailing.\n",
-             nt_header->Signature, p_infile->name);
-      exit (1);
-    }
-
-  /* Locate the ".data" and ".bss" sections for Emacs.  (Note that the
-     actual section names are probably different from these, and might
-     actually be the same section.)
-
-     We do this as follows: first we determine the virtual address
-     ranges in this process for the data and bss variables that we wish
-     to preserve.  Then we map these VAs to the section entries in the
-     source image.  Finally, we determine the new size of the raw data
-     area for the bss section, so we can make the new image the correct
-     size.  */
-
-  /* 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)
-    {
-      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
-     globally segregates all static and public bss data (ie. across all
-     linked modules, not just per module), so we must take both static
-     and public bss areas into account to determine the true extent of
-     the bss area used by Emacs.
-
-     To be strictly correct, we dump the static and public bss areas
-     used by Emacs separately if non-overlapping (since otherwise we are
-     dumping bss data belonging to system libraries, eg. the static bss
-     system data on the Alpha).  */
-
-  bss_start = my_begbss;
-  bss_size = my_endbss - my_begbss;
-  bss_section = rva_to_section (PTR_TO_RVA (my_begbss), nt_header);
-  if (bss_section != rva_to_section (PTR_TO_RVA (my_endbss), nt_header))
-    {
-      printf ("Uninitialized data is not in a single section...bailing\n");
-      exit (1);
-    }
-  /* Compute how much the .bss section's raw data will grow.  */
-  extra_bss_size =
-    ROUND_UP (RVA_TO_SECTION_OFFSET (PTR_TO_RVA (my_endbss), bss_section),
-             nt_header->OptionalHeader.FileAlignment)
-    - bss_section->SizeOfRawData;
-
-  bss_start_static = my_begbss_static;
-  bss_size_static = my_endbss_static - my_begbss_static;
-  bss_section_static = rva_to_section (PTR_TO_RVA (my_begbss_static), 
nt_header);
-  if (bss_section_static != rva_to_section (PTR_TO_RVA (my_endbss_static), 
nt_header))
-    {
-      printf ("Uninitialized static data is not in a single 
section...bailing\n");
-      exit (1);
-    }
-  /* Compute how much the static .bss section's raw data will grow.  */
-  extra_bss_size_static =
-    ROUND_UP (RVA_TO_SECTION_OFFSET (PTR_TO_RVA (my_endbss_static), 
bss_section_static),
-             nt_header->OptionalHeader.FileAlignment)
-    - 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)
-       overlap = 1;
-    }
-  else
-    {
-      if (bss_start < bss_start_static + bss_size_static)
-       overlap = 1;
-    }
-  if (overlap)
-    {
-      if (bss_section != bss_section_static)
-       {
-         printf ("BSS data not in a single section...bailing\n");
-         exit (1);
-       }
-      bss_start = min (bss_start, bss_start_static);
-      bss_size = max (my_endbss, my_endbss_static) - bss_start;
-      bss_section_static = 0;
-      extra_bss_size = max (extra_bss_size, extra_bss_size_static);
-      extra_bss_size_static = 0;
-    }
-}
-
-/* Format to print a DWORD_PTR value.  */
-#if defined MINGW_W64 && defined _WIN64
-# define pDWP  "16llx"
-#else
-# define pDWP  "08lx"
-#endif
-
-/* The dump routines.  */
-
-void
-copy_executable_and_dump_data (file_data *p_infile,
-                              file_data *p_outfile)
-{
-  unsigned char *dst, *dst_save;
-  PIMAGE_DOS_HEADER dos_header;
-  PIMAGE_NT_HEADERS nt_header;
-  PIMAGE_NT_HEADERS dst_nt_header;
-  PIMAGE_SECTION_HEADER section;
-  PIMAGE_SECTION_HEADER dst_section;
-  DWORD_PTR offset;
-  int i;
-  int be_verbose = GetEnvironmentVariable ("DEBUG_DUMP", NULL, 0) > 0;
-
-#define COPY_CHUNK(message, src, size, verbose)                                
        \
-  do {                                                                         
\
-    unsigned char *s = (void *)(src);                                          
\
-    DWORD_PTR count = (size);                                          \
-    if (verbose)                                                               
\
-      {                                                                        
        \
-       printf ("%s\n", (message));                                             
\
-       printf ("\t0x%"pDWP" Offset in input file.\n", (DWORD_PTR)(s - 
p_infile->file_base)); \
-       printf ("\t0x%"pDWP" Offset in output file.\n", (DWORD_PTR)(dst - 
p_outfile->file_base)); \
-       printf ("\t0x%"pDWP" Size in bytes.\n", count);                         
\
-      }                                                                        
        \
-    memcpy (dst, s, count);                                                    
\
-    dst += count;                                                              
\
-  } while (0)
-
-#define COPY_PROC_CHUNK(message, src, size, verbose)                           
\
-  do {                                                                         
\
-    unsigned char *s = (void *)(src);                                          
\
-    DWORD_PTR count = (size);                                          \
-    if (verbose)                                                               
\
-      {                                                                        
        \
-       printf ("%s\n", (message));                                             
\
-       printf ("\t0x%p Address in process.\n", s);                             
\
-       printf ("\t0x%p Base       output file.\n", p_outfile->file_base); \
-       printf ("\t0x%"pDWP" Offset  in output file.\n", (DWORD_PTR)(dst - 
p_outfile->file_base)); \
-       printf ("\t0x%p Address in output file.\n", dst); \
-       printf ("\t0x%"pDWP" Size in bytes.\n", count);                         
\
-      }                                                                        
        \
-    memcpy (dst, s, count);                                                    
\
-    dst += count;                                                              
\
-  } while (0)
-
-#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
-     dumping the raw data for the bss and heap sections.
-
-     Note that dst is updated implicitly by each COPY_CHUNK.  */
-
-  dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
-  nt_header = (PIMAGE_NT_HEADERS) (((DWORD_PTR) dos_header) +
-                                  dos_header->e_lfanew);
-  section = IMAGE_FIRST_SECTION (nt_header);
-
-  dst = (unsigned char *) p_outfile->file_base;
-
-  COPY_CHUNK ("Copying DOS header...", dos_header,
-             (DWORD_PTR) nt_header - (DWORD_PTR) dos_header, be_verbose);
-  dst_nt_header = (PIMAGE_NT_HEADERS) dst;
-  COPY_CHUNK ("Copying NT header...", nt_header,
-             (DWORD_PTR) section - (DWORD_PTR) nt_header, be_verbose);
-  dst_section = (PIMAGE_SECTION_HEADER) dst;
-  COPY_CHUNK ("Copying section table...", section,
-             nt_header->FileHeader.NumberOfSections * sizeof (*section),
-             be_verbose);
-
-  /* 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];
-      /* Windows section names are fixed 8-char strings, only
-        zero-terminated if the name is shorter than 8 characters.  */
-      sprintf (msg, "Copying raw data for %.8s...", section->Name);
-
-      dst_save = dst;
-
-      /* Update the file-relative offset for this section's raw data (if
-         it has any) in case things have been relocated; we will update
-         the other offsets below once we know where everything is.  */
-      if (dst_section->PointerToRawData)
-       dst_section->PointerToRawData = DST_TO_OFFSET ();
-
-      /* Can always copy the original raw data.  */
-      COPY_CHUNK
-       (msg, OFFSET_TO_PTR (section->PointerToRawData, p_infile),
-        section->SizeOfRawData, be_verbose);
-      /* 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)
-       {
-         dst = dst_save
-           + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (data_start), dst_section);
-         COPY_PROC_CHUNK ("Dumping initialized data...",
-                          data_start, data_size, be_verbose);
-         dst = dst_save + dst_section->SizeOfRawData;
-       }
-      if (section == bss_section)
-       {
-         /* Dump contents of bss variables, adjusting the section's raw
-             data size as necessary.  */
-         dst = dst_save
-           + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (bss_start), dst_section);
-         COPY_PROC_CHUNK ("Dumping bss data...", bss_start,
-                          bss_size, be_verbose);
-         ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
-         dst_section->PointerToRawData = PTR_TO_OFFSET (dst_save, p_outfile);
-         /* Determine new size of raw data area.  */
-         dst = max (dst, dst_save + dst_section->SizeOfRawData);
-         dst_section->SizeOfRawData = dst - dst_save;
-         dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;
-         dst_section->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;
-       }
-      if (section == bss_section_static)
-       {
-         /* Dump contents of static bss variables, adjusting the
-             section's raw data size as necessary.  */
-         dst = dst_save
-           + RVA_TO_SECTION_OFFSET (PTR_TO_RVA (bss_start_static), 
dst_section);
-         COPY_PROC_CHUNK ("Dumping static bss data...", bss_start_static,
-                          bss_size_static, be_verbose);
-         ROUND_UP_DST (dst_nt_header->OptionalHeader.FileAlignment);
-         dst_section->PointerToRawData = PTR_TO_OFFSET (dst_save, p_outfile);
-         /* Determine new size of raw data area.  */
-         dst = max (dst, dst_save + dst_section->SizeOfRawData);
-         dst_section->SizeOfRawData = dst - dst_save;
-         dst_section->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;
-         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++;
-    }
-
-  /* Copy remainder of source image.  */
-  do
-    section--;
-  while (section->PointerToRawData == 0);
-  offset = ROUND_UP (section->PointerToRawData + section->SizeOfRawData,
-                    nt_header->OptionalHeader.FileAlignment);
-  COPY_CHUNK
-    ("Copying remainder of executable...",
-     OFFSET_TO_PTR (offset, p_infile),
-     p_infile->size - offset, be_verbose);
-
-  /* Final size for new image.  */
-  p_outfile->size = DST_TO_OFFSET ();
-
-  /* Now patch up remaining file-relative offsets.  */
-  section = IMAGE_FIRST_SECTION (nt_header);
-  dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
-
-#define ADJUST_OFFSET(var)                                             \
-  do {                                                                 \
-    if ((var) != 0)                                                    \
-      (var) = relocate_offset ((var), nt_header, dst_nt_header);       \
-  } while (0)
-
-  dst_nt_header->OptionalHeader.SizeOfInitializedData = 0;
-  dst_nt_header->OptionalHeader.SizeOfUninitializedData = 0;
-  for (i = 0; i < dst_nt_header->FileHeader.NumberOfSections; i++)
-    {
-      /* Recompute data sizes for completeness.  */
-      if (dst_section[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
-       dst_nt_header->OptionalHeader.SizeOfInitializedData +=
-         ROUND_UP (dst_section[i].Misc.VirtualSize, 
dst_nt_header->OptionalHeader.FileAlignment);
-      else if (dst_section[i].Characteristics & 
IMAGE_SCN_CNT_UNINITIALIZED_DATA)
-       dst_nt_header->OptionalHeader.SizeOfUninitializedData +=
-         ROUND_UP (dst_section[i].Misc.VirtualSize, 
dst_nt_header->OptionalHeader.FileAlignment);
-
-      ADJUST_OFFSET (dst_section[i].PointerToLinenumbers);
-    }
-
-  ADJUST_OFFSET (dst_nt_header->FileHeader.PointerToSymbolTable);
-
-  /* Update offsets in debug directory entries. */
-  {
-    IMAGE_DATA_DIRECTORY debug_dir =
-      dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
-    PIMAGE_DEBUG_DIRECTORY debug_entry;
-
-    section = rva_to_section (debug_dir.VirtualAddress, dst_nt_header);
-    if (section)
-      {
-       debug_entry = (PIMAGE_DEBUG_DIRECTORY)
-         (RVA_TO_OFFSET (debug_dir.VirtualAddress, section) + 
p_outfile->file_base);
-       debug_dir.Size /= sizeof (IMAGE_DEBUG_DIRECTORY);
-
-       for (i = 0; i < debug_dir.Size; i++, debug_entry++)
-         ADJUST_OFFSET (debug_entry->PointerToRawData);
-      }
-  }
-}
-
-
-/* Dump out .data and .bss sections into a new executable.  */
-void
-unexec (const char *new_name, const char *old_name)
-{
-  file_data in_file, out_file;
-  char out_filename[MAX_PATH], in_filename[MAX_PATH], new_name_a[MAX_PATH];
-  unsigned long size;
-  char *p;
-  char *q;
-
-  /* Ignore old_name, and get our actual location from the OS.  */
-  if (!GetModuleFileNameA (NULL, in_filename, MAX_PATH))
-    abort ();
-
-  /* Can't use dostounix_filename here, since that needs its file name
-     argument encoded in UTF-8.  */
-  for (p = in_filename; *p; p = CharNextA (p))
-    if (*p == '\\')
-      *p = '/';
-
-  strcpy (out_filename, in_filename);
-  filename_to_ansi (new_name, new_name_a);
-
-  /* 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_a, '/')) == NULL)
-    abort ();
-  strcpy (p, q);
-
-#ifdef ENABLE_CHECKING
-  report_temacs_memory_usage ();
-#endif
-
-  /* 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);
-  printf ("          to %s\n", out_filename);
-
-  /* Open the undumped executable file.  */
-  if (!open_input_file (&in_file, in_filename))
-    {
-      printf ("Failed to open %s (%lu)...bailing.\n",
-             in_filename, GetLastError ());
-      exit (1);
-    }
-
-  /* Get the interesting section info, like start and size of .bss...  */
-  get_section_info (&in_file);
-
-  /* The size of the dumped executable is the size of the original
-     executable plus the size of the heap and the size of the .bss section.  */
-  size = in_file.size +
-    extra_bss_size +
-    extra_bss_size_static;
-  if (!open_output_file (&out_file, out_filename, size))
-    {
-      printf ("Failed to open %s (%lu)...bailing.\n",
-             out_filename, GetLastError ());
-      exit (1);
-    }
-
-  copy_executable_and_dump_data (&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);
-}
-
-/* eof */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]