guile-elisp bootstrap (lisp)
[bpt/emacs.git] / src / unexelf.c
index 951e7c0..0983f8f 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 1985-1988, 1990, 1992, 1999-2011
-                 Free Software Foundation, Inc.
+/* Copyright (C) 1985-1988, 1990, 1992, 1999-2014 Free Software
+   Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -386,18 +386,19 @@ temacs:
    Instead we read the whole file, modify it, and write it out.  */
 
 #include <config.h>
-#include <unexec.h>
+#include "unexec.h"
+#include "lisp.h"
 
-extern void fatal (const char *msgid, ...);
-
-#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <memory.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <sys/stat.h>
-#include <memory.h>
-#include <errno.h>
+#include <sys/types.h>
 #include <unistd.h>
-#include <fcntl.h>
+
 #if !defined (__NetBSD__) && !defined (__OpenBSD__)
 #include <elf.h>
 #endif /* not __NetBSD__ and not __OpenBSD__ */
@@ -453,7 +454,7 @@ typedef struct {
        long cbRfdOffset;
        long cbExtOffset;
 } HDRR, *pHDRR;
-#define cbHDRR sizeof(HDRR)
+#define cbHDRR sizeof (HDRR)
 #define hdrNil ((pHDRR)0)
 #endif
 
@@ -461,7 +462,7 @@ typedef struct {
 /*
  * NetBSD does not have normal-looking user-land ELF support.
  */
-# if defined __alpha__ || defined __sparc_v9__
+# if defined __alpha__ || defined __sparc_v9__ || defined _LP64
 #  define ELFSIZE      64
 # else
 #  define ELFSIZE      32
@@ -506,21 +507,31 @@ typedef struct {
 #endif
 
 #ifndef ElfW
-# ifdef __STDC__
-#  define ElfBitsW(bits, type) Elf##bits##_##type
-# else
-#  define ElfBitsW(bits, type) Elf/**/bits/**/_/**/type
-# endif
-# ifdef _LP64
-#  define ELFSIZE 64
-# else
-#  define ELFSIZE 32
+# 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%jx\n", (uintmax_t) (expr))
+#endif
+
 /* Get the address of a particular section or program header entry,
  * accounting for the size of the entries.
  */
@@ -548,25 +559,29 @@ typedef struct {
    Apr 23, 1996
    */
 
+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) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
+  (*(ElfW (Shdr) *) entry_address (old_section_h, n, old_file_h->e_shentsize))
 #define NEW_SECTION_H(n) \
-     (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
+  (*(ElfW (Shdr) *) entry_address (new_section_h, n, new_file_h->e_shentsize))
 #define NEW_PROGRAM_H(n) \
-     (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
+  (*(ElfW (Phdr) *) entry_address (new_program_h, n, new_file_h->e_phentsize))
 
-#define PATCH_INDEX(n) \
-  do { \
-        if ((int) (n) >= old_bss_index) \
-          (n)++; } while (0)
+#define PATCH_INDEX(n) ((n) += old_bss_index <= (n))
 typedef unsigned char byte;
 
 /* Round X up to a multiple of Y.  */
 
-static ElfW(Addr)
-round_up (ElfW(Addr) x, ElfW(Addr) y)
+static ElfW (Addr)
+round_up (ElfW (Addr) x, ElfW (Addr) y)
 {
-  int rem = x % y;
+  ElfW (Addr) rem = x % y;
   if (rem == 0)
     return x;
   return x - rem + y;
@@ -577,33 +592,28 @@ round_up (ElfW(Addr) x, ElfW(Addr) y)
    about the file we are looking in.
 
    If we don't find the section NAME, that is a fatal error
-   if NOERROR is 0; we return -1 if NOERROR is nonzero.  */
+   if NOERROR is false; return -1 if NOERROR is true.  */
 
-static int
+static ptrdiff_t
 find_section (const char *name, const char *section_names, const char *file_name,
-             ElfW(Ehdr) *old_file_h, ElfW(Shdr) *old_section_h, int noerror)
+             ElfW (Ehdr) *old_file_h, ElfW (Shdr) *old_section_h,
+             bool noerror)
 {
-  int idx;
+  ptrdiff_t idx;
 
   for (idx = 1; idx < old_file_h->e_shnum; idx++)
     {
-#ifdef DEBUG
-      fprintf (stderr, "Looking for %s - found %s\n", name,
-              section_names + OLD_SECTION_H (idx).sh_name);
+      char const *found_name = section_names + OLD_SECTION_H (idx).sh_name;
+#ifdef UNEXELF_DEBUG
+      fprintf (stderr, "Looking for %s - found %s\n", name, found_name);
 #endif
-      if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name,
-                  name))
-       break;
-    }
-  if (idx == old_file_h->e_shnum)
-    {
-      if (noerror)
-       return -1;
-      else
-       fatal ("Can't find %s in %s.\n", name, file_name);
+      if (strcmp (name, found_name) == 0)
+       return idx;
     }
 
-  return idx;
+  if (! noerror)
+    fatal ("Can't find %s in %s", name, file_name);
+  return -1;
 }
 
 /* ****************************************************************
@@ -618,11 +628,9 @@ find_section (const char *name, const char *section_names, const char *file_name
 void
 unexec (const char *new_name, const char *old_name)
 {
-  int new_file, old_file, new_file_size;
-
-#if defined (emacs) || !defined (DEBUG)
+  int new_file, old_file;
+  off_t new_file_size;
   void *new_break;
-#endif
 
   /* Pointers to the base of the image of the two files.  */
   caddr_t old_base, new_base;
@@ -635,44 +643,45 @@ unexec (const char *new_name, const char *old_name)
 
   /* 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;
+  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 in the old file.  */
   char *old_section_names;
 
-  ElfW(Addr) old_bss_addr, new_bss_addr;
-  ElfW(Word) old_bss_size, new_data2_size;
-  ElfW(Off)  new_data2_offset;
-  ElfW(Addr) new_data2_addr;
-  ElfW(Off)  old_bss_offset;
-  ElfW(Word) new_data2_incr;
+  ElfW (Addr) old_bss_addr, new_bss_addr;
+  ElfW (Word) old_bss_size, new_data2_size;
+  ElfW (Off)  new_data2_offset;
+  ElfW (Addr) new_data2_addr;
+  ElfW (Off)  old_bss_offset;
+  ElfW (Word) new_data2_incr;
 
-  int n, nn;
-  int old_bss_index, old_sbss_index, old_plt_index;
-  int old_data_index, new_data2_index;
+  ptrdiff_t n, nn;
+  ptrdiff_t old_bss_index, old_sbss_index, old_plt_index;
+  ptrdiff_t old_data_index, new_data2_index;
 #if defined _SYSTYPE_SYSV || defined __sgi
-  int old_mdebug_index;
+  ptrdiff_t old_mdebug_index;
 #endif
   struct stat stat_buf;
-  int old_file_size;
+  off_t old_file_size;
+  int mask;
 
   /* Open the old file, allocate a buffer of the right size, and read
      in the file contents.  */
 
-  old_file = open (old_name, O_RDONLY);
+  old_file = emacs_open (old_name, O_RDONLY, 0);
 
   if (old_file < 0)
-    fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
+    fatal ("Can't open %s for reading: %s", old_name, strerror (errno));
 
-  if (fstat (old_file, &stat_buf) == -1)
-    fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
+  if (fstat (old_file, &stat_buf) != 0)
+    fatal ("Can't fstat (%s): %s", old_name, strerror (errno));
 
 #if MAP_ANON == 0
-  mmap_fd = open ("/dev/zero", O_RDONLY);
+  mmap_fd = emacs_open ("/dev/zero", O_RDONLY, 0);
   if (mmap_fd < 0)
-    fatal ("Can't open /dev/zero for reading: errno %d\n", errno, 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,
@@ -680,19 +689,21 @@ unexec (const char *new_name, const char *old_name)
      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\n", old_name, 0);
+    fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
 
-  if (read (old_file, old_base, stat_buf.st_size) != stat_buf.st_size)
-    fatal ("Didn't read all of %s: errno %d\n", old_name, 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_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;
 
@@ -757,12 +768,8 @@ unexec (const char *new_name, const char *old_name)
   old_data_index = find_section (".data", old_section_names,
                                 old_name, old_file_h, old_section_h, 0);
 
-#if defined (emacs) || !defined (DEBUG)
   new_break = sbrk (0);
-  new_bss_addr = (ElfW(Addr)) new_break;
-#else
-  new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
-#endif
+  new_bss_addr = (ElfW (Addr)) new_break;
   new_data2_addr = old_bss_addr;
   new_data2_size = new_bss_addr - old_bss_addr;
   new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset
@@ -773,42 +780,42 @@ unexec (const char *new_name, const char *old_name)
      section) was unaligned.  */
   new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
 
-#ifdef DEBUG
-  fprintf (stderr, "old_bss_index %d\n", old_bss_index);
-  fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
-  fprintf (stderr, "old_bss_size %x\n", old_bss_size);
-  fprintf (stderr, "old_bss_offset %x\n", old_bss_offset);
-  fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
-  fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
-  fprintf (stderr, "new_data2_size %x\n", new_data2_size);
-  fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
-  fprintf (stderr, "new_data2_incr %x\n", new_data2_incr);
+#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_addr);
+  DEBUG_LOG (new_data2_size);
+  DEBUG_LOG (new_data2_offset);
+  DEBUG_LOG (new_data2_incr);
 #endif
 
-  if ((uintptr_t) new_bss_addr < (uintptr_t) old_bss_addr + old_bss_size)
-    fatal (".bss shrank when undumping???\n", 0, 0);
+  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.  stat_buf still has old_file data.  */
+     objects.  */
 
-  new_file = open (new_name, O_RDWR | O_CREAT, 0666);
+  new_file = emacs_open (new_name, O_RDWR | O_CREAT, 0666);
   if (new_file < 0)
-    fatal ("Can't creat (%s): errno %d\n", new_name, errno);
+    fatal ("Can't creat (%s): %s", new_name, strerror (errno));
 
-  new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_incr;
+  new_file_size = old_file_size + old_file_h->e_shentsize + new_data2_incr;
 
   if (ftruncate (new_file, new_file_size))
-    fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
+    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\n", old_name, 0);
+    fatal ("Can't allocate buffer for %s: %s", old_name, strerror (errno));
 
-  new_file_h = (ElfW(Ehdr) *) new_base;
-  new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
-  new_section_h = (ElfW(Shdr) *)
+  new_file_h = (ElfW (Ehdr) *) new_base;
+  new_program_h = (ElfW (Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
+  new_section_h = (ElfW (Shdr) *)
     ((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
 
   /* Make our new file, program and section headers as copies of the
@@ -827,11 +834,11 @@ unexec (const char *new_name, const char *old_name)
   new_file_h->e_shoff += new_data2_incr;
   new_file_h->e_shnum += 1;
 
-#ifdef DEBUG
-  fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
-  fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
-  fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
-  fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
+#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 a new program header.  Extend the writable data segment so
@@ -841,10 +848,10 @@ unexec (const char *new_name, const char *old_name)
      to adjust the offset and address of any segment that is above
      data2, just in case we decide to allow this later.  */
 
-  for (n = new_file_h->e_phnum - 1; n >= 0; n--)
+  for (n = new_file_h->e_phnum; --n >= 0; )
     {
       /* Compute maximum of all requirements for alignment of section.  */
-      ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align;
+      ElfW (Word) alignment = (NEW_PROGRAM_H (n)).p_align;
       if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
        alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
 
@@ -859,7 +866,7 @@ unexec (const char *new_name, const char *old_name)
          > (old_sbss_index == -1
             ? old_bss_addr
             : round_up (old_bss_addr, alignment)))
-         fatal ("Program segment above .bss in %s\n", old_name, 0);
+         fatal ("Program segment above .bss in %s", old_name);
 
       if (NEW_PROGRAM_H (n).p_type == PT_LOAD
          && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
@@ -869,7 +876,7 @@ unexec (const char *new_name, const char *old_name)
        break;
     }
   if (n < 0)
-    fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
+    fatal ("Couldn't find segment next to .bss in %s", old_name);
 
   /* Make sure that the size includes any padding before the old .bss
      section.  */
@@ -877,7 +884,7 @@ unexec (const char *new_name, const char *old_name)
   NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
 
 #if 0 /* Maybe allow section after data2 - does this ever happen? */
-  for (n = new_file_h->e_phnum - 1; n >= 0; n--)
+  for (n = new_file_h->e_phnum; --n >= 0; )
     {
       if (NEW_PROGRAM_H (n).p_vaddr
          && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
@@ -896,7 +903,7 @@ unexec (const char *new_name, const char *old_name)
 
   /* Walk through all section headers, insert the new data2 section right
      before the new bss section. */
-  for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
+  for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
     {
       caddr_t src;
       /* If it is (s)bss section, insert the new data2 section before it.  */
@@ -1019,7 +1026,7 @@ temacs:
          /* The conditional bit below was in Oliva's original code
             (1999-08-25) and seems to have been dropped by mistake
             subsequently.  It prevents a crash at startup under X in
-            `IRIX64 6.5 6.5.17m', whether compiled on that relase or
+            `IRIX64 6.5 6.5.17m', whether compiled on that release or
             an earlier one.  It causes no trouble on the other ELF
             platforms I could test (Irix 6.5.15m, Solaris 8, Debian
             Potato x86, Debian Woody SPARC); however, it's reported
@@ -1053,7 +1060,7 @@ temacs:
       memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
              NEW_SECTION_H (nn).sh_size);
 
-#ifdef __alpha__
+#if defined __alpha__ && !defined __OpenBSD__
       /* Update Alpha COFF symbol table: */
       if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
          == 0)
@@ -1072,14 +1079,15 @@ temacs:
          symhdr->cbRfdOffset += new_data2_size;
          symhdr->cbExtOffset += new_data2_size;
        }
-#endif /* __alpha__ */
+#endif /* __alpha__ && !__OpenBSD__ */
 
 #if defined (_SYSTYPE_SYSV)
       if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
          && old_mdebug_index != -1)
        {
-         int diff = NEW_SECTION_H(nn).sh_offset
-               - OLD_SECTION_H(old_mdebug_index).sh_offset;
+         ptrdiff_t new_offset = NEW_SECTION_H (nn).sh_offset;
+         ptrdiff_t old_offset = OLD_SECTION_H (old_mdebug_index).sh_offset;
+         ptrdiff_t diff = new_offset - old_offset;
          HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
 
          if (diff)
@@ -1158,9 +1166,9 @@ temacs:
       if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
          || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
        {
-         ElfW(Shdr) *spt = &NEW_SECTION_H (nn);
-         unsigned int num = spt->sh_size / spt->sh_entsize;
-         ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset +
+         ElfW (Shdr) *spt = &NEW_SECTION_H (nn);
+         ptrdiff_t num = spt->sh_size / spt->sh_entsize;
+         ElfW (Sym) * sym = (ElfW (Sym) *) (NEW_SECTION_H (nn).sh_offset +
                                           new_base);
          for (; num--; sym++)
            {
@@ -1175,10 +1183,10 @@ temacs:
     }
 
   /* Update the symbol values of _edata and _end.  */
-  for (n = new_file_h->e_shnum - 1; n; n--)
+  for (n = new_file_h->e_shnum; 0 < --n; )
     {
       byte *symnames;
-      ElfW(Sym) *symp, *symendp;
+      ElfW (Sym) *symp, *symendp;
 
       if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
          && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
@@ -1186,8 +1194,8 @@ temacs:
 
       symnames = ((byte *) new_base
                  + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
-      symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
-      symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
+      symp = (ElfW (Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
+      symendp = (ElfW (Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
 
       for (; symp < symendp; symp ++)
        {
@@ -1219,9 +1227,15 @@ temacs:
              nn = symp->st_shndx;
              if (nn > old_bss_index)
                nn--;
-             old = ((symp->st_value - NEW_SECTION_H (symp->st_shndx).sh_addr)
-                    + OLD_SECTION_H (nn).sh_offset + old_base);
-             memcpy (new, old, symp->st_size);
+             if (nn == old_bss_index)
+               memset (new, 0, symp->st_size);
+             else
+               {
+                 old = ((symp->st_value
+                         - NEW_SECTION_H (symp->st_shndx).sh_addr)
+                        + OLD_SECTION_H (nn).sh_offset + old_base);
+                 memcpy (new, old, symp->st_size);
+               }
            }
 #endif
        }
@@ -1229,9 +1243,9 @@ temacs:
 
   /* This loop seeks out relocation sections for the data section, so
      that it can undo relocations performed by the runtime linker.  */
-  for (n = new_file_h->e_shnum - 1; n; n--)
+  for (n = new_file_h->e_shnum; 0 < --n; )
     {
-      ElfW(Shdr) section = NEW_SECTION_H (n);
+      ElfW (Shdr) section = NEW_SECTION_H (n);
 
       /* Cause a compilation error if anyone uses n instead of nn below.  */
       #define n ((void) 0);
@@ -1263,21 +1277,21 @@ temacs:
              || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
                          ".data1"))
            {
-             ElfW(Addr) offset = (NEW_SECTION_H (nn).sh_addr
+             ElfW (Addr) offset = (NEW_SECTION_H (nn).sh_addr
                                   - NEW_SECTION_H (nn).sh_offset);
              caddr_t reloc = old_base + section.sh_offset, end;
              for (end = reloc + section.sh_size; reloc < end;
                   reloc += section.sh_entsize)
                {
-                 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
+                 ElfW (Addr) addr = ((ElfW (Rel) *) reloc)->r_offset - offset;
 #ifdef __alpha__
                  /* The Alpha ELF binutils currently have a bug that
                     sometimes results in relocs that contain all
                     zeroes.  Work around this for now...  */
-                 if (((ElfW(Rel) *) reloc)->r_offset == 0)
+                 if (((ElfW (Rel) *) reloc)->r_offset == 0)
                    continue;
 #endif
-                 memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr)));
+                 memcpy (new_base + addr, old_base + addr, sizeof (ElfW (Addr)));
                }
            }
          break;
@@ -1289,29 +1303,29 @@ temacs:
   /* Write out new_file, and free the buffers.  */
 
   if (write (new_file, new_base, new_file_size) != new_file_size)
-    fatal ("Didn't write %d bytes to %s: errno %d\n",
-          new_file_size, new_name, errno);
+    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
-  close (mmap_fd);
+  emacs_close (mmap_fd);
 #endif
 
-  if (close (old_file))
-    fatal ("Can't close (%s): errno %d\n", old_name, errno);
+  if (emacs_close (old_file) != 0)
+    fatal ("Can't close (%s): %s", old_name, strerror (errno));
 
-  if (close (new_file))
-    fatal ("Can't close (%s): errno %d\n", new_name, errno);
+  if (emacs_close (new_file) != 0)
+    fatal ("Can't close (%s): %s", new_name, strerror (errno));
 
-  if (stat (new_name, &stat_buf) == -1)
-    fatal ("Can't stat (%s): errno %d\n", new_name, errno);
+  if (stat (new_name, &stat_buf) != 0)
+    fatal ("Can't stat (%s): %s", new_name, strerror (errno));
 
-  n = umask (777);
-  umask (n);
-  stat_buf.st_mode |= 0111 & ~n;
-  if (chmod (new_name, stat_buf.st_mode) == -1)
-    fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
+  mask = umask (777);
+  umask (mask);
+  stat_buf.st_mode |= 0111 & ~mask;
+  if (chmod (new_name, stat_buf.st_mode) != 0)
+    fatal ("Can't chmod (%s): %s", new_name, strerror (errno));
 }