+ void *varaddress;
+ size_t size;
+} pdump_opaque;
+
+typedef struct
+{
+ Dynarr_declare (pdump_opaque);
+} pdump_opaque_dynarr;
+
+typedef struct
+{
+ void **ptraddress;
+ const struct struct_description *desc;
+} pdump_root_struct_ptr;
+
+typedef struct
+{
+ Dynarr_declare (pdump_root_struct_ptr);
+} pdump_root_struct_ptr_dynarr;
+
+typedef struct
+{
+ Lisp_Object *address;
+ Lisp_Object value;
+} pdump_static_Lisp_Object;
+
+typedef struct
+{
+ char **address; /* char * for ease of doing relocation */
+ char * value;
+} pdump_static_pointer;
+
+static pdump_opaque_dynarr *pdump_opaques;
+static pdump_root_struct_ptr_dynarr *pdump_root_struct_ptrs;
+static Lisp_Object_ptr_dynarr *pdump_root_objects;
+static Lisp_Object_ptr_dynarr *pdump_weak_object_chains;
+
+/* Mark SIZE bytes at non-heap address VARADDRESS for dumping as is,
+ without any bit-twiddling. */
+void
+dump_add_opaque (void *varaddress, size_t size)
+{
+ pdump_opaque info;
+ info.varaddress = varaddress;
+ info.size = size;
+ if (pdump_opaques == NULL)
+ pdump_opaques = Dynarr_new (pdump_opaque);
+ Dynarr_add (pdump_opaques, info);
+}
+
+/* Mark the struct described by DESC and pointed to by the pointer at
+ 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)
+{
+ pdump_root_struct_ptr info;
+ info.ptraddress = (void **) ptraddress;
+ info.desc = desc;
+ if (pdump_root_struct_ptrs == NULL)
+ pdump_root_struct_ptrs = Dynarr_new (pdump_root_struct_ptr);
+ Dynarr_add (pdump_root_struct_ptrs, info);
+}
+
+/* Mark the Lisp_Object at non-heap address VARADDRESS for dumping.
+ All the objects reachable from this var will also be dumped. */
+void
+dump_add_root_object (Lisp_Object *varaddress)
+{
+ if (pdump_root_objects == NULL)
+ pdump_root_objects = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
+ Dynarr_add (pdump_root_objects, varaddress);
+}
+
+/* Mark the list pointed to by the Lisp_Object at VARADDRESS for dumping. */
+void
+dump_add_weak_object_chain (Lisp_Object *varaddress)
+{
+ if (pdump_weak_object_chains == NULL)
+ pdump_weak_object_chains = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
+ Dynarr_add (pdump_weak_object_chains, varaddress);
+}
+\f
+
+inline static void
+pdump_align_stream (FILE *stream, size_t alignment)
+{
+ long offset = ftell (stream);
+ long adjustment = ALIGN_SIZE (offset, alignment) - offset;
+ if (adjustment)
+ fseek (stream, adjustment, SEEK_CUR);
+}
+
+#define PDUMP_ALIGN_OUTPUT(type) pdump_align_stream (pdump_out, ALIGNOF (type))
+
+#define PDUMP_WRITE(type, object) \
+fwrite (&object, sizeof (object), 1, pdump_out);
+
+#define PDUMP_WRITE_ALIGNED(type, object) do { \
+ PDUMP_ALIGN_OUTPUT (type); \
+ PDUMP_WRITE (type, object); \
+} while (0)
+
+#define PDUMP_READ(ptr, type) \
+(((type *) (ptr = (char*) (((type *) ptr) + 1)))[-1])
+
+#define PDUMP_READ_ALIGNED(ptr, type) \
+((ptr = (char *) ALIGN_PTR (ptr, ALIGNOF (type))), PDUMP_READ (ptr, type))
+
+\f
+
+typedef struct
+{