diff src/dumper.c @ 771:943eaba38521

[xemacs-hg @ 2002-03-13 08:51:24 by ben] The big ben-mule-21-5 check-in! Various files were added and deleted. See CHANGES-ben-mule. There are still some test suite failures. No crashes, though. Many of the failures have to do with problems in the test suite itself rather than in the actual code. I'll be addressing these in the next day or so -- none of the test suite failures are at all critical. Meanwhile I'll be trying to address the biggest issues -- i.e. build or run failures, which will almost certainly happen on various platforms. All comments should be sent to ben@xemacs.org -- use a Cc: if necessary when sending to mailing lists. There will be pre- and post- tags, something like pre-ben-mule-21-5-merge-in, and post-ben-mule-21-5-merge-in.
author ben
date Wed, 13 Mar 2002 08:54:06 +0000
parents fdefd0186b75
children e38acbeb1cae
line wrap: on
line diff
--- a/src/dumper.c	Fri Mar 08 13:33:14 2002 +0000
+++ b/src/dumper.c	Wed Mar 13 08:54:06 2002 +0000
@@ -1,6 +1,7 @@
 /* Portable data dumper for XEmacs.
    Copyright (C) 1999-2000 Olivier Galibert
    Copyright (C) 2001 Martin Buchholz
+   Copyright (C) 2001 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -25,23 +26,20 @@
 #include "lisp.h"
 
 #include "specifier.h"
+#include "file-coding.h"
 #include "elhash.h"
 #include "sysfile.h"
 #include "console-stream.h"
 #include "dumper.h"
 
 #ifdef WIN32_NATIVE
-#include "nt.h"
+#include "syswindows.h"
 #else
 #ifdef HAVE_MMAP
 #include <sys/mman.h>
 #endif
 #endif
 
-#ifndef SEPCHAR
-#define SEPCHAR ':'
-#endif
-
 typedef struct
 {
   const void *varaddress;
@@ -98,7 +96,8 @@
    non-heap address VARADDRESS for dumping.
    All the objects reachable from this pointer will also be dumped. */
 void
-dump_add_root_struct_ptr (void *ptraddress, const struct struct_description *desc)
+dump_add_root_struct_ptr (void *ptraddress,
+			  const struct struct_description *desc)
 {
   pdump_root_struct_ptr info;
   info.ptraddress = (void **) ptraddress;
@@ -140,7 +139,7 @@
 #define PDUMP_ALIGN_OUTPUT(type) pdump_align_stream (pdump_out, ALIGNOF (type))
 
 #define PDUMP_WRITE(type, object) \
-fwrite (&object, sizeof (object), 1, pdump_out);
+retry_fwrite (&object, sizeof (object), 1, pdump_out);
 
 #define PDUMP_WRITE_ALIGNED(type, object) do {	\
   PDUMP_ALIGN_OUTPUT (type);			\
@@ -388,7 +387,7 @@
 {
   int i;
   stderr_out ("pdump backtrace :\n");
-  for (i=0;i<depth;i++)
+  for (i = 0; i < depth; i++)
     {
       if (!backtrace[i].obj)
 	stderr_out ("  - ind. (%d, %d)\n",
@@ -405,6 +404,10 @@
 }
 
 static void pdump_register_object (Lisp_Object obj);
+static void pdump_register_struct_contents (const void *data,
+					    const struct struct_description *
+					    sdesc,
+					    int count);
 static void pdump_register_struct (const void *data,
 				   const struct struct_description *sdesc,
 				   int count);
@@ -468,6 +471,11 @@
 	  pos = 0;
 	  desc = ((const Lisp_Specifier *)data)->methods->extra_description;
 	  goto restart;
+	case XD_CODING_SYSTEM_END:
+	  pos = 0;
+	  desc =
+	    ((const Lisp_Coding_System *)data)->methods->extra_description;
+	  goto restart;
 	case XD_BYTECOUNT:
 	case XD_ELEMCOUNT:
 	case XD_HASHCODE:
@@ -541,6 +549,20 @@
 	      }
 	    break;
 	  }
+	case XD_STRUCT_ARRAY:
+	  {
+	    EMACS_INT count = desc[pos].data1;
+	    const struct struct_description *sdesc = desc[pos].data2;
+
+	    if (XD_IS_INDIRECT (count))
+	      count = pdump_get_indirect_count (count, desc, data);
+
+	    pdump_register_struct_contents (rdata, sdesc, count);
+	    break;
+	  }
+	case XD_UNION:
+	  abort (); /* #### IMPLEMENT ME!  NEEDED FOR UNICODE SUPPORT */
+
 	default:
 	  stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
 	  pdump_backtrace ();
@@ -570,7 +592,7 @@
   if (imp->description)
     {
       int me = depth++;
-      if (me>65536)
+      if (me > 65536)
 	{
 	  stderr_out ("Backtrace overflow, loop ?\n");
 	  abort ();
@@ -596,6 +618,193 @@
     }
 }
 
+/* Return the size of the memory block (NOT necessarily a structure!) 
+   described by SDESC and pointed to by OBJ.  If SDESC records an
+   explicit size (i.e. non-zero), it is simply returned; otherwise,
+   the size is calculated by the maximum offset and the size of the
+   object at that offset, rounded up to the maximum alignment.  In
+   this case, we may need the object, for example when retrieving an
+   "indirect count" of an inlined array (the count is not constant,
+   but is specified by one of the elements of the memory block). (It
+   is generally not a problem if we return an overly large size -- we
+   will simply end up reserving more space than necessary; but if the
+   size is too small we could be in serious trouble, in particular
+   with nested inlined structures, where there may be alignment
+   padding in the middle of a block. #### In fact there is an (at
+   least theoretical) problem with an overly large size -- we may
+   trigger a protection fault when reading from invalid memory.  We
+   need to handle this -- perhaps in a stupid but dependable way,
+   i.e. by trapping SIGSEGV and SIGBUS.) */
+
+static Bytecount
+pdump_structure_size (const void *obj, const struct struct_description *sdesc)
+{
+  int max_offset = -1;
+  int max_offset_pos = -1;
+  int size_at_max = 0;
+  int pos;
+  const struct lrecord_description *desc;
+  void *rdata;
+
+  if (sdesc->size)
+    return sdesc->size;
+
+  desc = sdesc->description;
+
+  for (pos = 0; desc[pos].type != XD_END; pos++)
+    {
+      if (desc[pos].offset == max_offset)
+	{
+	  stderr_out ("Two relocatable elements at same offset?\n");
+	  abort ();
+	}
+      else if (desc[pos].offset > max_offset)
+	{
+	  max_offset = desc[pos].offset;
+	  max_offset_pos = pos;
+	}
+    }
+
+  if (max_offset_pos < 0)
+    return 0;
+
+  pos = max_offset_pos;
+  rdata = (char *) obj + desc[pos].offset;
+
+  switch (desc[pos].type)
+    {
+    case XD_LISP_OBJECT_ARRAY:
+      {
+	EMACS_INT val = desc[pos].data1;
+	if (XD_IS_INDIRECT (val))
+	  val = pdump_get_indirect_count (val, desc, obj);
+	size_at_max = val * sizeof (Lisp_Object);
+	break;
+      }
+    case XD_LISP_OBJECT:
+    case XD_LO_LINK:
+      size_at_max = sizeof (Lisp_Object);
+      break;
+    case XD_OPAQUE_PTR:
+      size_at_max = sizeof (void *);
+      break;
+    case XD_STRUCT_PTR:
+      {
+	EMACS_INT val = desc[pos].data1;
+	if (XD_IS_INDIRECT (val))
+	  val = pdump_get_indirect_count (val, desc, obj);
+	size_at_max = val * sizeof (void *);
+	break;
+      }
+      break;
+    case XD_STRUCT_ARRAY:
+      {
+	EMACS_INT val = desc[pos].data1;
+
+	if (XD_IS_INDIRECT (val))
+	  val = pdump_get_indirect_count (val, desc, obj);
+	    
+	size_at_max = val * pdump_structure_size (rdata, desc[pos].data2);
+	break;
+      }
+      break;
+    case XD_OPAQUE_DATA_PTR:
+      size_at_max = sizeof (void *);
+      break;
+    case XD_UNION:
+      abort ();			/* #### IMPLEMENT ME!  NEEDED FOR UNICODE
+				   SUPPORT */
+      break;
+    case XD_C_STRING:
+      size_at_max = sizeof (void *);
+      break;
+    case XD_DOC_STRING:
+      size_at_max = sizeof (void *);
+      break;
+    case XD_INT_RESET:
+      size_at_max = sizeof (int);
+      break;
+    case XD_BYTECOUNT:
+      size_at_max = sizeof (Bytecount);
+      break;
+    case XD_ELEMCOUNT:
+      size_at_max = sizeof (Elemcount);
+      break;
+    case XD_HASHCODE:
+      size_at_max = sizeof (Hashcode);
+      break;
+    case XD_INT:
+      size_at_max = sizeof (int);
+      break;
+    case XD_LONG:
+      size_at_max = sizeof (long);
+      break;
+    case XD_SPECIFIER_END:
+    case XD_CODING_SYSTEM_END:
+      stderr_out
+	("Should not be seeing XD_SPECIFIER_END or\n"
+	 "XD_CODING_SYSTEM_END outside of struct Lisp_Specifier\n"
+	 "and struct Lisp_Coding_System.\n");
+      abort ();
+    default:
+      stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
+      abort ();
+    }
+
+  /* We have no way of knowing the required alignment for this structure,
+     so just max it maximally aligned. */
+  return ALIGN_SIZE (max_offset + size_at_max, ALIGNOF (max_align_t));
+}
+
+/* Register the referenced objects in the array of COUNT objects of
+   located at DATA; each object is described by SDESC.  "Object" here
+   simply means any block of memory; it need not actually be a C
+   "struct".  It could be a single integer or Lisp_Object, for
+   example, as long as the description is accurate.
+
+   This does not register the block of memory itself; it may, for
+   example, be an array of structures inlined in another memory block
+   and thus should not be registered.  See pdump_register_struct(),
+   which does register the memory block. */
+
+static void
+pdump_register_struct_contents (const void *data,
+				const struct struct_description *sdesc,
+				int count)
+
+{
+  int me = depth++;
+  int i;
+  Bytecount elsize;
+
+  if (me>65536)
+    {
+      stderr_out ("Backtrace overflow, loop ?\n");
+      abort ();
+    }
+  backtrace[me].obj = 0;
+  backtrace[me].position = 0;
+  backtrace[me].offset = 0;
+
+  elsize = pdump_structure_size (data, sdesc);
+
+  for (i = 0; i < count; i++)
+    {
+      pdump_register_sub (((char *) data) + elsize * i,
+			  sdesc->description,
+			  me);
+    }
+  --depth;
+}
+
+/* Register the array of COUNT objects of located at DATA; each object is
+   described by SDESC.  "Object" here simply means any block of memory;
+   it need not actually be a C "struct".  It could be a single integer
+   or Lisp_Object, for example, as long as the description is accurate.
+
+   This is like pdump_register_struct_contents() but also registers
+   the memory block itself. */
+
 static void
 pdump_register_struct (const void *data,
 		       const struct struct_description *sdesc,
@@ -603,29 +812,182 @@
 {
   if (data && !pdump_get_entry (data))
     {
-      int me = depth++;
-      int i;
-      if (me>65536)
-	{
-	  stderr_out ("Backtrace overflow, loop ?\n");
-	  abort ();
-	}
-      backtrace[me].obj = 0;
-      backtrace[me].position = 0;
-      backtrace[me].offset = 0;
+      pdump_add_entry (pdump_get_entry_list (sdesc), data,
+		       pdump_structure_size (data, sdesc), count);
 
-      pdump_add_entry (pdump_get_entry_list (sdesc),
-		       data, sdesc->size, count);
-      for (i=0; i<count; i++)
-	{
-	  pdump_register_sub (((char *)data) + sdesc->size*i,
-			      sdesc->description,
-			      me);
-	}
-      --depth;
+      pdump_register_struct_contents (data, sdesc, count);
     }
 }
 
+/* Store the already-calculated new pointer offsets for all pointers
+   in the COUNT contiguous blocks of memory, each described by DESC
+   and of size SIZE, whose original is located at ORIG_DATA and the
+   modifiable copy at DATA.
+
+   This is done just before writing the modified block of memory to
+   the dump file.  The new pointer offsets have been carefully
+   calculated so that the data being pointed gets written at that
+   offset in the dump file.  That way, the dump file is a correct
+   memory image except perhaps for a constant that needs to be added
+   to all pointers. (#### In fact, we SHOULD be starting up a dumped
+   XEmacs, seeing where the dumped file gets loaded into memory, and
+   then rewriting the dumped file after relocating all the pointers
+   relative to this memory location.  That way, if the file gets
+   loaded again at the same location, which will be common, we don't
+   have to do any relocating, which is both faster at startup and
+   allows the read-only part of the dumped data to be shared read-only
+   between different invocations of XEmacs.)
+
+   #### Do we distinguish between read-only and writable dumped data?
+   Should we?  It's tricky because the dumped data, once loaded again,
+   cannot really be free()d or garbage collected since it's all stored
+   in one contiguous block of data with no malloc() headers, and we
+   don't keep track of the pointers used internally in malloc() and
+   the Lisp allocator to track allocated blocks of memory. */
+
+static void
+pdump_store_new_pointer_offsets (int count, void *data, const void *orig_data,
+				 const struct lrecord_description *desc,
+				 int size)
+{
+  int pos, i;
+  /* Process each block one by one */
+  for (i = 0; i < count; i++)
+    {
+      /* CUR points to the beginning of each block in the new data. */
+      char *cur = ((char *)data) + i*size;
+    restart:
+      /* Scan each line of the description for relocatable pointers */
+      for (pos = 0; desc[pos].type != XD_END; pos++)
+	{
+	  /* RDATA points to the beginning of each element in the new data. */
+	  void *rdata = cur + desc[pos].offset;
+	  switch (desc[pos].type)
+	    {
+	    case XD_SPECIFIER_END:
+	      desc = ((const Lisp_Specifier *)(orig_data))->
+		methods->extra_description;
+	      goto restart;
+	    case XD_CODING_SYSTEM_END:
+	      desc = ((const Lisp_Coding_System *)(orig_data))->
+		methods->extra_description;
+	      goto restart;
+	    case XD_BYTECOUNT:
+	    case XD_ELEMCOUNT:
+	    case XD_HASHCODE:
+	    case XD_INT:
+	    case XD_LONG:
+	      break;
+	    case XD_INT_RESET:
+	      {
+		EMACS_INT val = desc[pos].data1;
+		if (XD_IS_INDIRECT (val))
+		  val = pdump_get_indirect_count (val, desc, orig_data);
+		* (int *) rdata = val;
+		break;
+	      }
+	    case XD_OPAQUE_DATA_PTR:
+	    case XD_C_STRING:
+	    case XD_STRUCT_PTR:
+	      {
+		void *ptr = * (void **) rdata;
+		if (ptr)
+		  * (EMACS_INT *) rdata = pdump_get_entry (ptr)->save_offset;
+		break;
+	      }
+	    case XD_LO_LINK:
+	      {
+		/* As described in lrecord.h, this is a weak link.
+                   Thus, we need to link this object not (necessarily)
+                   to the object directly pointed to, but to the next
+                   referenced object in the chain.  None of the
+                   intermediate objects will be written out, so we
+                   traverse down the chain of objects until we find a
+                   referenced one. (The Qnil or Qunbound that ends the
+                   chain will always be a referenced object.) */
+		Lisp_Object obj = * (Lisp_Object *) rdata;
+		pdump_entry_list_elt *elt1;
+		for (;;)
+		  {
+		    elt1 = pdump_get_entry (XRECORD_LHEADER (obj));
+		    if (elt1)
+		      break;
+		    obj = * (Lisp_Object *) (desc[pos].offset +
+					     (char *)(XRECORD_LHEADER (obj)));
+		  }
+		* (EMACS_INT *) rdata = elt1->save_offset;
+		break;
+	      }
+	    case XD_LISP_OBJECT:
+	      {
+		Lisp_Object *pobj = (Lisp_Object *) rdata;
+
+		assert (desc[pos].data1 == 0);
+
+		if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
+		  * (EMACS_INT *) pobj =
+		    pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
+		break;
+	      }
+	    case XD_LISP_OBJECT_ARRAY:
+	      {
+		EMACS_INT num = desc[pos].data1;
+		int j;
+		if (XD_IS_INDIRECT (num))
+		  num = pdump_get_indirect_count (num, desc, orig_data);
+
+		for (j = 0; j < num; j++)
+		  {
+		    Lisp_Object *pobj = ((Lisp_Object *) rdata) + j;
+		    if (POINTER_TYPE_P (XTYPE (*pobj)) &&
+			XRECORD_LHEADER (*pobj))
+		      * (EMACS_INT *) pobj =
+			pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
+		  }
+		break;
+	      }
+	    case XD_DOC_STRING:
+	      {
+		EMACS_INT str = *(EMACS_INT *)rdata;
+		if (str > 0)
+		  * (EMACS_INT *) rdata =
+		    pdump_get_entry ((void *)str)->save_offset;
+		break;
+	      }
+	    case XD_STRUCT_ARRAY:
+	      {
+		EMACS_INT num = desc[pos].data1;
+		if (XD_IS_INDIRECT (num))
+		  num = pdump_get_indirect_count (num, desc, orig_data);
+
+		pdump_store_new_pointer_offsets
+		  (num, rdata,
+		   ((char *) rdata - (char *) data) + (char *) orig_data,
+		   desc[pos].data2->description,
+		   pdump_structure_size
+		   (((char *) rdata - (char *) data) + (char *) orig_data,
+		    desc[pos].data2));
+		break;
+	      }
+	    case XD_UNION:
+	      abort ();		/* #### IMPLEMENT ME!  NEEDED FOR UNICODE
+				   SUPPORT */
+
+	    default:
+	      stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
+	      abort ();
+	    }
+	}
+    }
+}
+
+/* Write out to global file descriptor PDUMP_OUT the element (one or
+   more contiguous blocks of identical size/description) recorded in
+   ELT and described by DESC.  The element is first copied to a buffer
+   and then all pointers (this includes Lisp_Objects other than
+   integer/character) are relocated to the (pre-computed) offset in
+   the dump file. */
+
 static void
 pdump_dump_data (pdump_entry_list_elt *elt,
 		 const struct lrecord_description *desc)
@@ -634,101 +996,20 @@
   int count = elt->count;
   if (desc)
     {
-      int pos, i;
+      /* Copy to temporary buffer */
       memcpy (pdump_buf, elt->obj, size*count);
 
-      for (i=0; i<count; i++)
-	{
-	  char *cur = ((char *)pdump_buf) + i*size;
-	restart:
-	  for (pos = 0; desc[pos].type != XD_END; pos++)
-	    {
-	      void *rdata = cur + desc[pos].offset;
-	      switch (desc[pos].type)
-		{
-		case XD_SPECIFIER_END:
-		  desc = ((const Lisp_Specifier *)(elt->obj))->methods->extra_description;
-		  goto restart;
-		case XD_BYTECOUNT:
-		case XD_ELEMCOUNT:
-		case XD_HASHCODE:
-		case XD_INT:
-		case XD_LONG:
-		  break;
-		case XD_INT_RESET:
-		  {
-		    EMACS_INT val = desc[pos].data1;
-		    if (XD_IS_INDIRECT (val))
-		      val = pdump_get_indirect_count (val, desc, elt->obj);
-		    *(int *)rdata = val;
-		    break;
-		  }
-		case XD_OPAQUE_DATA_PTR:
-		case XD_C_STRING:
-		case XD_STRUCT_PTR:
-		  {
-		    void *ptr = *(void **)rdata;
-		    if (ptr)
-		      *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
-		    break;
-		  }
-		case XD_LO_LINK:
-		  {
-		    Lisp_Object obj = *(Lisp_Object *)rdata;
-		    pdump_entry_list_elt *elt1;
-		    for (;;)
-		      {
-			elt1 = pdump_get_entry (XRECORD_LHEADER (obj));
-			if (elt1)
-			  break;
-			obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
-		      }
-		    *(EMACS_INT *)rdata = elt1->save_offset;
-		    break;
-		  }
-		case XD_LISP_OBJECT:
-		  {
-		    Lisp_Object *pobj = (Lisp_Object *) rdata;
+      /* Store new offsets into all pointers in block */
+      pdump_store_new_pointer_offsets (count, pdump_buf, elt->obj, desc, size);
+    }
+  retry_fwrite (desc ? pdump_buf : elt->obj, size, count, pdump_out);
+}
 
-		    assert (desc[pos].data1 == 0);
-
-		    if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
-		      *(EMACS_INT *)pobj =
-			pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
-		    break;
-		  }
-		case XD_LISP_OBJECT_ARRAY:
-		  {
-		    EMACS_INT num = desc[pos].data1;
-		    int j;
-		    if (XD_IS_INDIRECT (num))
-		      num = pdump_get_indirect_count (num, desc, elt->obj);
-
-		    for (j=0; j<num; j++)
-		      {
-			Lisp_Object *pobj = ((Lisp_Object *)rdata) + j;
-			if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
-			  *(EMACS_INT *)pobj =
-			    pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
-		      }
-		    break;
-		  }
-		case XD_DOC_STRING:
-		  {
-		    EMACS_INT str = *(EMACS_INT *)rdata;
-		    if (str > 0)
-		      *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
-		    break;
-		  }
-		default:
-		  stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
-		  abort ();
-		}
-	    }
-	}
-    }
-  fwrite (desc ? pdump_buf : elt->obj, size, count, pdump_out);
-}
+/* Relocate a single memory block at DATA, described by DESC, from its
+   assumed load location to its actual one by adding DELTA to all
+   pointers in the block.  Does not recursively relocate any other
+   memory blocks pointed to. (We already have a list of all memory
+   blocks in the dump file.) */
 
 static void
 pdump_reloc_one (void *data, EMACS_INT delta,
@@ -746,6 +1027,11 @@
 	  pos = 0;
 	  desc = ((const Lisp_Specifier *)data)->methods->extra_description;
 	  goto restart;
+	case XD_CODING_SYSTEM_END:
+	  pos = 0;
+	  desc =
+	    ((const Lisp_Coding_System *)data)->methods->extra_description;
+	  goto restart;
 	case XD_BYTECOUNT:
 	case XD_ELEMCOUNT:
 	case XD_HASHCODE:
@@ -799,6 +1085,25 @@
 	      *(EMACS_INT *)rdata = str + delta;
 	    break;
 	  }
+	case XD_STRUCT_ARRAY:
+	  {
+	    EMACS_INT num = desc[pos].data1;
+	    int j;
+	    const struct struct_description *sdesc = desc[pos].data2;
+	    Bytecount size = pdump_structure_size (rdata, sdesc);
+
+	    if (XD_IS_INDIRECT (num))
+	      num = pdump_get_indirect_count (num, desc, data);
+	    /* Note: We are recursing over data in the block itself */
+	    for (j = 0; j < num; j++)
+	      pdump_reloc_one ((char *) rdata + j * size, delta,
+			       sdesc->description);
+
+	    break;
+	  }
+
+	case XD_UNION:
+	  abort (); /* #### IMPLEMENT ME!  NEEDED FOR UNICODE SUPPORT */
 	default:
 	  stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
 	  abort ();
@@ -859,7 +1164,7 @@
       data[i].value   = (char *) pdump_get_entry (* data[i].address)->save_offset;
     }
   PDUMP_ALIGN_OUTPUT (pdump_static_pointer);
-  fwrite (data, sizeof (pdump_static_pointer), count, pdump_out);
+  retry_fwrite (data, sizeof (pdump_static_pointer), count, pdump_out);
 }
 
 static void
@@ -870,7 +1175,7 @@
     {
       pdump_opaque *info = Dynarr_atp (pdump_opaques, i);
       PDUMP_WRITE_ALIGNED (pdump_opaque, *info);
-      fwrite (info->varaddress, info->size, 1, pdump_out);
+      retry_fwrite (info->varaddress, info->size, 1, pdump_out);
     }
 }
 
@@ -1056,13 +1361,17 @@
   header.stab_offset = cur_offset;
 
   pdump_buf = xmalloc (max_size);
-  /* Avoid use of the `open' macro.  We want the real function. */
-#undef open
   pdump_fd = open (EMACS_PROGNAME ".dmp",
 		   O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
+  if (pdump_fd < 0)
+    report_file_error ("Unable to open dump file",
+		       build_string (EMACS_PROGNAME ".dmp"));
   pdump_out = fdopen (pdump_fd, "w");
+  if (pdump_out < 0)
+    report_file_error ("Unable to open dump file for writing",
+		       build_string (EMACS_PROGNAME ".dmp"));
 
-  fwrite (&header, sizeof (header), 1, pdump_out);
+  retry_fwrite (&header, sizeof (header), 1, pdump_out);
   PDUMP_ALIGN_OUTPUT (max_align_t);
 
   pdump_scan_by_alignment (pdump_dump_data);
@@ -1074,8 +1383,8 @@
   pdump_dump_rtables ();
   pdump_dump_root_objects ();
 
-  fclose (pdump_out);
-  close (pdump_fd);
+  retry_fclose (pdump_out);
+  retry_close (pdump_fd);
 
   free (pdump_buf);
 
@@ -1300,7 +1609,7 @@
   pdump_length = lseek (fd, 0, SEEK_END);
   if (pdump_length < (Bytecount) sizeof (pdump_header))
     {
-      close (fd);
+      retry_close (fd);
       return 0;
     }
 
@@ -1316,16 +1625,16 @@
   if (pdump_start != (char *) MAP_FAILED)
     {
       pdump_free = pdump_file_unmap;
-      close (fd);
+      retry_close (fd);
       return 1;
     }
 #endif /* HAVE_MMAP */
 
   pdump_start = xnew_array (char, pdump_length);
   pdump_free = pdump_file_free;
-  read (fd, pdump_start, pdump_length);
+  retry_read (fd, pdump_start, pdump_length);
 
-  close (fd);
+  retry_close (fd);
   return 1;
 }
 #endif /* !WIN32_NATIVE */
@@ -1371,20 +1680,20 @@
 }
 
 int
-pdump_load (const char *argv0)
+pdump_load (const Extbyte *argv0)
 {
-  char exe_path[PATH_MAX];
+  Extbyte exe_path[PATH_MAX];
 #ifdef WIN32_NATIVE
   GetModuleFileName (NULL, exe_path, PATH_MAX);
 #else /* !WIN32_NATIVE */
-  char *w;
-  const char *dir, *p;
+  Extbyte *w;
+  const Extbyte *dir, *p;
 
   dir = argv0;
   if (dir[0] == '-')
     {
       /* XEmacs as a login shell, oh goody! */
-      dir = getenv ("SHELL");
+      dir = getenv ("SHELL"); /* not egetenv -- not yet initialized */
     }
 
   p = dir + strlen (dir);
@@ -1398,8 +1707,8 @@
     }
   else
     {
-      const char *path = getenv ("PATH");
-      const char *name = p;
+      const Extbyte *path = getenv ("PATH"); /* not egetenv -- not yet init. */
+      const Extbyte *name = p;
       for (;;)
 	{
 	  p = path;
@@ -1421,11 +1730,6 @@
 	    }
 	  strcpy (w, name);
 
-	  /* ### #$%$#^$^@%$^#%@$ ! */
-#ifdef access
-#undef access
-#endif
-
 	  if (!access (exe_path, X_OK))
 	    break;
 	  if (!*p)