1 /* Portable data dumper for XEmacs.
2 Copyright (C) 1999-2000 Olivier Galibert
3 Copyright (C) 2001 Martin Buchholz
5 This file is part of XEmacs.
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Synched up with: Not in FSF. */
27 #include "specifier.h"
30 #include "console-stream.h"
53 Dynarr_declare (pdump_opaque);
54 } pdump_opaque_dynarr;
59 const struct struct_description *desc;
60 } pdump_root_struct_ptr;
64 Dynarr_declare (pdump_root_struct_ptr);
65 } pdump_root_struct_ptr_dynarr;
71 } pdump_static_Lisp_Object;
75 char **address; /* char * for ease of doing relocation */
77 } pdump_static_pointer;
79 static pdump_opaque_dynarr *pdump_opaques;
80 static pdump_root_struct_ptr_dynarr *pdump_root_struct_ptrs;
81 static Lisp_Object_ptr_dynarr *pdump_root_objects;
82 static Lisp_Object_ptr_dynarr *pdump_weak_object_chains;
84 /* Mark SIZE bytes at non-heap address VARADDRESS for dumping as is,
85 without any bit-twiddling. */
87 dump_add_opaque (void *varaddress, size_t size)
90 info.varaddress = varaddress;
92 if (pdump_opaques == NULL)
93 pdump_opaques = Dynarr_new (pdump_opaque);
94 Dynarr_add (pdump_opaques, info);
97 /* Mark the struct described by DESC and pointed to by the pointer at
98 non-heap address VARADDRESS for dumping.
99 All the objects reachable from this pointer will also be dumped. */
101 dump_add_root_struct_ptr (void *ptraddress, const struct struct_description *desc)
103 pdump_root_struct_ptr info;
104 info.ptraddress = (void **) ptraddress;
106 if (pdump_root_struct_ptrs == NULL)
107 pdump_root_struct_ptrs = Dynarr_new (pdump_root_struct_ptr);
108 Dynarr_add (pdump_root_struct_ptrs, info);
111 /* Mark the Lisp_Object at non-heap address VARADDRESS for dumping.
112 All the objects reachable from this var will also be dumped. */
114 dump_add_root_object (Lisp_Object *varaddress)
116 if (pdump_root_objects == NULL)
117 pdump_root_objects = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
118 Dynarr_add (pdump_root_objects, varaddress);
121 /* Mark the list pointed to by the Lisp_Object at VARADDRESS for dumping. */
123 dump_add_weak_object_chain (Lisp_Object *varaddress)
125 if (pdump_weak_object_chains == NULL)
126 pdump_weak_object_chains = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
127 Dynarr_add (pdump_weak_object_chains, varaddress);
132 pdump_align_stream (FILE *stream, size_t alignment)
134 long offset = ftell (stream);
135 long adjustment = ALIGN_SIZE (offset, alignment) - offset;
137 fseek (stream, adjustment, SEEK_CUR);
140 #define PDUMP_ALIGN_OUTPUT(type) pdump_align_stream (pdump_out, ALIGNOF (type))
142 #define PDUMP_WRITE(type, object) \
143 fwrite (&object, sizeof (object), 1, pdump_out);
145 #define PDUMP_WRITE_ALIGNED(type, object) do { \
146 PDUMP_ALIGN_OUTPUT (type); \
147 PDUMP_WRITE (type, object); \
150 #define PDUMP_READ(ptr, type) \
151 (((type *) (ptr = (char*) (((type *) ptr) + 1)))[-1])
153 #define PDUMP_READ_ALIGNED(ptr, type) \
154 ((ptr = (char *) ALIGN_PTR (ptr, ALIGNOF (type))), PDUMP_READ (ptr, type))
160 const struct lrecord_description *desc;
164 static char *pdump_rt_list = 0;
167 pdump_objects_unmark (void)
170 char *p = pdump_rt_list;
174 pdump_reloc_table *rt = (pdump_reloc_table *)p;
175 p += sizeof (pdump_reloc_table);
178 for (i=0; i<rt->count; i++)
180 struct lrecord_header *lh = * (struct lrecord_header **) p;
181 if (! C_READONLY_RECORD_HEADER_P (lh))
182 UNMARK_RECORD_HEADER (lh);
183 p += sizeof (EMACS_INT);
191 /* The structure of the file
194 stab_offset - nb_root_struct_ptrs*pair(void *, adr)
195 for pointers to structures
196 - nb_opaques*pair(void *, size) for raw bits to restore
198 - root lisp object address/value couples with the count
203 #define PDUMP_SIGNATURE "XEmacsDP"
204 #define PDUMP_SIGNATURE_LEN (sizeof (PDUMP_SIGNATURE) - 1)
208 char signature[PDUMP_SIGNATURE_LEN];
210 EMACS_UINT stab_offset;
211 EMACS_UINT reloc_address;
212 int nb_root_struct_ptrs;
218 static size_t pdump_length;
221 /* Handle for the dump file */
222 static HANDLE pdump_hFile = INVALID_HANDLE_VALUE;
223 /* Handle for the file mapping object for the dump file */
224 static HANDLE pdump_hMap = INVALID_HANDLE_VALUE;
227 static void (*pdump_free) (void);
229 static unsigned char pdump_align_table[] =
231 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
232 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
233 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
234 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1
237 static inline unsigned int
238 pdump_size_to_align (size_t size)
240 return pdump_align_table[size % countof (pdump_align_table)];
243 typedef struct pdump_entry_list_elt
245 struct pdump_entry_list_elt *next;
249 EMACS_INT save_offset;
250 } pdump_entry_list_elt;
254 pdump_entry_list_elt *first;
259 typedef struct pdump_struct_list_elt
261 pdump_entry_list list;
262 const struct struct_description *sdesc;
263 } pdump_struct_list_elt;
267 pdump_struct_list_elt *list;
272 static pdump_entry_list *pdump_object_table;
273 static pdump_entry_list pdump_opaque_data_list;
274 static pdump_struct_list pdump_struct_table;
276 static int *pdump_alert_undump_object;
278 static unsigned long cur_offset;
279 static size_t max_size;
281 static void *pdump_buf;
282 static FILE *pdump_out;
284 #define PDUMP_HASHSIZE 200001
286 static pdump_entry_list_elt **pdump_hash;
288 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
290 pdump_make_hash (const void *obj)
292 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
295 static pdump_entry_list_elt *
296 pdump_get_entry (const void *obj)
298 int pos = pdump_make_hash (obj);
299 pdump_entry_list_elt *e;
303 while ((e = pdump_hash[pos]) != 0)
309 if (pos == PDUMP_HASHSIZE)
316 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size,
319 pdump_entry_list_elt *e;
320 int pos = pdump_make_hash (obj);
322 while ((e = pdump_hash[pos]) != 0)
328 if (pos == PDUMP_HASHSIZE)
332 e = xnew (pdump_entry_list_elt);
334 e->next = list->first;
340 list->count += count;
344 int align = pdump_size_to_align (size);
346 if (align < list->align)
351 static pdump_entry_list *
352 pdump_get_entry_list (const struct struct_description *sdesc)
355 for (i=0; i<pdump_struct_table.count; i++)
356 if (pdump_struct_table.list[i].sdesc == sdesc)
357 return &pdump_struct_table.list[i].list;
359 if (pdump_struct_table.size <= pdump_struct_table.count)
361 if (pdump_struct_table.size == -1)
362 pdump_struct_table.size = 10;
364 pdump_struct_table.size = pdump_struct_table.size * 2;
365 pdump_struct_table.list = (pdump_struct_list_elt *)
366 xrealloc (pdump_struct_table.list,
367 pdump_struct_table.size * sizeof (pdump_struct_list_elt));
369 pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
370 pdump_struct_table.list[pdump_struct_table.count].list.align = ALIGNOF (max_align_t);
371 pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
372 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
374 return &pdump_struct_table.list[pdump_struct_table.count++].list;
379 struct lrecord_header *obj;
387 pdump_backtrace (void)
390 stderr_out ("pdump backtrace :\n");
391 for (i=0;i<depth;i++)
393 if (!backtrace[i].obj)
394 stderr_out (" - ind. (%d, %d)\n",
395 backtrace[i].position,
396 backtrace[i].offset);
399 stderr_out (" - %s (%d, %d)\n",
400 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
401 backtrace[i].position,
402 backtrace[i].offset);
407 static void pdump_register_object (Lisp_Object obj);
408 static void pdump_register_struct (const void *data,
409 const struct struct_description *sdesc,
413 pdump_get_indirect_count (EMACS_INT code,
414 const struct lrecord_description *idesc,
420 int line = XD_INDIRECT_VAL (code);
421 int delta = XD_INDIRECT_DELTA (code);
423 irdata = ((char *)idata) + idesc[line].offset;
424 switch (idesc[line].type)
427 count = *(size_t *)irdata;
430 count = *(int *)irdata;
433 count = *(long *)irdata;
436 count = *(Bytecount *)irdata;
439 stderr_out ("Unsupported count type : %d (line = %d, code=%ld)\n",
440 idesc[line].type, line, (long)code);
449 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me)
454 for (pos = 0; desc[pos].type != XD_END; pos++)
456 const void *rdata = (const char *)data + desc[pos].offset;
458 backtrace[me].position = pos;
459 backtrace[me].offset = desc[pos].offset;
461 switch (desc[pos].type)
463 case XD_SPECIFIER_END:
465 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
474 case XD_OPAQUE_DATA_PTR:
476 EMACS_INT count = desc[pos].data1;
477 if (XD_IS_INDIRECT (count))
478 count = pdump_get_indirect_count (count, desc, data);
480 pdump_add_entry (&pdump_opaque_data_list,
481 *(void **)rdata, count, 1);
486 const char *str = *(const char **)rdata;
488 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1);
493 const char *str = *(const char **)rdata;
494 if ((EMACS_INT)str > 0)
495 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1);
500 const Lisp_Object *pobj = (const Lisp_Object *)rdata;
502 assert (desc[pos].data1 == 0);
504 backtrace[me].offset = (const char *)pobj - (const char *)data;
505 pdump_register_object (*pobj);
508 case XD_LISP_OBJECT_ARRAY:
511 EMACS_INT count = desc[pos].data1;
512 if (XD_IS_INDIRECT (count))
513 count = pdump_get_indirect_count (count, desc, data);
515 for (i = 0; i < count; i++)
517 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i;
518 Lisp_Object dobj = *pobj;
520 backtrace[me].offset = (const char *)pobj - (const char *)data;
521 pdump_register_object (dobj);
527 EMACS_INT count = desc[pos].data1;
528 const struct struct_description *sdesc = desc[pos].data2;
529 const char *dobj = *(const char **)rdata;
532 if (XD_IS_INDIRECT (count))
533 count = pdump_get_indirect_count (count, desc, data);
535 pdump_register_struct (dobj, sdesc, count);
540 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
548 pdump_register_object (Lisp_Object obj)
550 struct lrecord_header *objh;
551 const struct lrecord_implementation *imp;
553 if (!POINTER_TYPE_P (XTYPE (obj)))
556 objh = XRECORD_LHEADER (obj);
560 if (pdump_get_entry (objh))
563 imp = LHEADER_IMPLEMENTATION (objh);
565 if (imp->description)
570 stderr_out ("Backtrace overflow, loop ?\n");
573 backtrace[me].obj = objh;
574 backtrace[me].position = 0;
575 backtrace[me].offset = 0;
577 pdump_add_entry (pdump_object_table + objh->type,
581 imp->size_in_bytes_method (objh),
583 pdump_register_sub (objh, imp->description, me);
588 pdump_alert_undump_object[objh->type]++;
589 stderr_out ("Undumpable object type : %s\n", imp->name);
595 pdump_register_struct (const void *data,
596 const struct struct_description *sdesc,
599 if (data && !pdump_get_entry (data))
605 stderr_out ("Backtrace overflow, loop ?\n");
608 backtrace[me].obj = 0;
609 backtrace[me].position = 0;
610 backtrace[me].offset = 0;
612 pdump_add_entry (pdump_get_entry_list (sdesc),
613 data, sdesc->size, count);
614 for (i=0; i<count; i++)
616 pdump_register_sub (((char *)data) + sdesc->size*i,
625 pdump_dump_data (pdump_entry_list_elt *elt,
626 const struct lrecord_description *desc)
628 size_t size = elt->size;
629 int count = elt->count;
633 memcpy (pdump_buf, elt->obj, size*count);
635 for (i=0; i<count; i++)
637 char *cur = ((char *)pdump_buf) + i*size;
639 for (pos = 0; desc[pos].type != XD_END; pos++)
641 void *rdata = cur + desc[pos].offset;
642 switch (desc[pos].type)
644 case XD_SPECIFIER_END:
645 desc = ((const Lisp_Specifier *)(elt->obj))->methods->extra_description;
654 EMACS_INT val = desc[pos].data1;
655 if (XD_IS_INDIRECT (val))
656 val = pdump_get_indirect_count (val, desc, elt->obj);
660 case XD_OPAQUE_DATA_PTR:
664 void *ptr = *(void **)rdata;
666 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
671 Lisp_Object obj = *(Lisp_Object *)rdata;
672 pdump_entry_list_elt *elt1;
675 elt1 = pdump_get_entry (XRECORD_LHEADER (obj));
678 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
680 *(EMACS_INT *)rdata = elt1->save_offset;
685 Lisp_Object *pobj = (Lisp_Object *) rdata;
687 assert (desc[pos].data1 == 0);
689 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
691 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
694 case XD_LISP_OBJECT_ARRAY:
696 EMACS_INT num = desc[pos].data1;
698 if (XD_IS_INDIRECT (num))
699 num = pdump_get_indirect_count (num, desc, elt->obj);
701 for (j=0; j<num; j++)
703 Lisp_Object *pobj = ((Lisp_Object *)rdata) + j;
704 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
706 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
712 EMACS_INT str = *(EMACS_INT *)rdata;
714 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
718 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
724 fwrite (desc ? pdump_buf : elt->obj, size, count, pdump_out);
728 pdump_reloc_one (void *data, EMACS_INT delta,
729 const struct lrecord_description *desc)
734 for (pos = 0; desc[pos].type != XD_END; pos++)
736 void *rdata = (char *)data + desc[pos].offset;
737 switch (desc[pos].type)
739 case XD_SPECIFIER_END:
741 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
749 case XD_OPAQUE_DATA_PTR:
754 EMACS_INT ptr = *(EMACS_INT *)rdata;
756 *(EMACS_INT *)rdata = ptr+delta;
761 Lisp_Object *pobj = (Lisp_Object *) rdata;
763 assert (desc[pos].data1 == 0);
765 if (POINTER_TYPE_P (XTYPE (*pobj))
766 && ! EQ (*pobj, Qnull_pointer))
767 XSETOBJ (*pobj, (char *) XPNTR (*pobj) + delta);
771 case XD_LISP_OBJECT_ARRAY:
773 EMACS_INT num = desc[pos].data1;
775 if (XD_IS_INDIRECT (num))
776 num = pdump_get_indirect_count (num, desc, data);
778 for (j=0; j<num; j++)
780 Lisp_Object *pobj = (Lisp_Object *) rdata + j;
782 if (POINTER_TYPE_P (XTYPE (*pobj))
783 && ! EQ (*pobj, Qnull_pointer))
784 XSETOBJ (*pobj, (char *) XPNTR (*pobj) + delta);
790 EMACS_INT str = *(EMACS_INT *)rdata;
792 *(EMACS_INT *)rdata = str + delta;
796 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
803 pdump_allocate_offset (pdump_entry_list_elt *elt,
804 const struct lrecord_description *desc)
806 size_t size = elt->count * elt->size;
807 elt->save_offset = cur_offset;
814 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elt *,
815 const struct lrecord_description *))
819 for (align = ALIGNOF (max_align_t); align; align>>=1)
822 pdump_entry_list_elt *elt;
824 for (i=0; i<lrecord_type_count; i++)
825 if (pdump_object_table[i].align == align)
826 for (elt = pdump_object_table[i].first; elt; elt = elt->next)
827 f (elt, lrecord_implementations_table[i]->description);
829 for (i=0; i<pdump_struct_table.count; i++)
831 pdump_struct_list_elt list = pdump_struct_table.list[i];
832 if (list.list.align == align)
833 for (elt = list.list.first; elt; elt = elt->next)
834 f (elt, list.sdesc->description);
837 for (elt = pdump_opaque_data_list.first; elt; elt = elt->next)
838 if (pdump_size_to_align (elt->size) == align)
844 pdump_dump_root_struct_ptrs (void)
847 size_t count = Dynarr_length (pdump_root_struct_ptrs);
848 pdump_static_pointer *data = alloca_array (pdump_static_pointer, count);
849 for (i = 0; i < count; i++)
851 data[i].address = (char **) Dynarr_atp (pdump_root_struct_ptrs, i)->ptraddress;
852 data[i].value = (char *) pdump_get_entry (* data[i].address)->save_offset;
854 PDUMP_ALIGN_OUTPUT (pdump_static_pointer);
855 fwrite (data, sizeof (pdump_static_pointer), count, pdump_out);
859 pdump_dump_opaques (void)
862 for (i = 0; i < Dynarr_length (pdump_opaques); i++)
864 pdump_opaque *info = Dynarr_atp (pdump_opaques, i);
865 PDUMP_WRITE_ALIGNED (pdump_opaque, *info);
866 fwrite (info->varaddress, info->size, 1, pdump_out);
871 pdump_dump_rtables (void)
874 pdump_entry_list_elt *elt;
875 pdump_reloc_table rt;
877 for (i=0; i<lrecord_type_count; i++)
879 elt = pdump_object_table[i].first;
882 rt.desc = lrecord_implementations_table[i]->description;
883 rt.count = pdump_object_table[i].count;
884 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
887 EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset;
888 PDUMP_WRITE_ALIGNED (EMACS_INT, rdata);
895 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
897 for (i=0; i<pdump_struct_table.count; i++)
899 elt = pdump_struct_table.list[i].list.first;
900 rt.desc = pdump_struct_table.list[i].sdesc->description;
901 rt.count = pdump_struct_table.list[i].list.count;
902 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
905 EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset;
907 for (j=0; j<elt->count; j++)
909 PDUMP_WRITE_ALIGNED (EMACS_INT, rdata);
917 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
921 pdump_dump_root_objects (void)
923 size_t count = (Dynarr_length (pdump_root_objects) +
924 Dynarr_length (pdump_weak_object_chains));
927 PDUMP_WRITE_ALIGNED (size_t, count);
928 PDUMP_ALIGN_OUTPUT (pdump_static_Lisp_Object);
930 for (i=0; i<Dynarr_length (pdump_root_objects); i++)
932 pdump_static_Lisp_Object obj;
933 obj.address = Dynarr_at (pdump_root_objects, i);
934 obj.value = * obj.address;
936 if (POINTER_TYPE_P (XTYPE (obj.value)))
937 obj.value = wrap_object ((void *) pdump_get_entry (XRECORD_LHEADER (obj.value))->save_offset);
939 PDUMP_WRITE (pdump_static_Lisp_Object, obj);
942 for (i=0; i<Dynarr_length (pdump_weak_object_chains); i++)
944 pdump_entry_list_elt *elt;
945 pdump_static_Lisp_Object obj;
947 obj.address = Dynarr_at (pdump_weak_object_chains, i);
948 obj.value = * obj.address;
952 const struct lrecord_description *desc;
954 elt = pdump_get_entry (XRECORD_LHEADER (obj.value));
957 desc = XRECORD_LHEADER_IMPLEMENTATION (obj.value)->description;
958 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
959 assert (desc[pos].type != XD_END);
961 obj.value = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj.value)));
963 obj.value = wrap_object ((void *) elt->save_offset);
965 PDUMP_WRITE (pdump_static_Lisp_Object, obj);
973 Lisp_Object t_console, t_device, t_frame;
977 pdump_object_table = xnew_array (pdump_entry_list, lrecord_type_count);
978 pdump_alert_undump_object = xnew_array (int, lrecord_type_count);
980 assert (ALIGNOF (max_align_t) <= pdump_align_table[0]);
982 for (i = 0; i < countof (pdump_align_table); i++)
983 if (pdump_align_table[i] > ALIGNOF (max_align_t))
984 pdump_align_table[i] = ALIGNOF (max_align_t);
986 flush_all_buffer_local_cache ();
988 /* These appear in a DEFVAR_LISP, which does a staticpro() */
989 t_console = Vterminal_console; Vterminal_console = Qnil;
990 t_frame = Vterminal_frame; Vterminal_frame = Qnil;
991 t_device = Vterminal_device; Vterminal_device = Qnil;
993 dump_add_opaque (&lrecord_implementations_table,
994 lrecord_type_count * sizeof (lrecord_implementations_table[0]));
995 dump_add_opaque (&lrecord_markers,
996 lrecord_type_count * sizeof (lrecord_markers[0]));
998 pdump_hash = xnew_array_and_zero (pdump_entry_list_elt *, PDUMP_HASHSIZE);
1000 for (i=0; i<lrecord_type_count; i++)
1002 pdump_object_table[i].first = 0;
1003 pdump_object_table[i].align = ALIGNOF (max_align_t);
1004 pdump_object_table[i].count = 0;
1005 pdump_alert_undump_object[i] = 0;
1007 pdump_struct_table.count = 0;
1008 pdump_struct_table.size = -1;
1010 pdump_opaque_data_list.first = 0;
1011 pdump_opaque_data_list.align = ALIGNOF (max_align_t);
1012 pdump_opaque_data_list.count = 0;
1015 for (i=0; i<Dynarr_length (pdump_root_objects); i++)
1016 pdump_register_object (* Dynarr_at (pdump_root_objects, i));
1019 for (i=0; i<lrecord_type_count; i++)
1020 if (pdump_alert_undump_object[i])
1023 printf ("Undumpable types list :\n");
1025 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]);
1030 for (i=0; i<Dynarr_length (pdump_root_struct_ptrs); i++)
1032 pdump_root_struct_ptr info = Dynarr_at (pdump_root_struct_ptrs, i);
1033 pdump_register_struct (*(info.ptraddress), info.desc, 1);
1036 memcpy (header.signature, PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN);
1037 header.id = dump_id;
1038 header.reloc_address = 0;
1039 header.nb_root_struct_ptrs = Dynarr_length (pdump_root_struct_ptrs);
1040 header.nb_opaques = Dynarr_length (pdump_opaques);
1042 cur_offset = ALIGN_SIZE (sizeof (header), ALIGNOF (max_align_t));
1045 pdump_scan_by_alignment (pdump_allocate_offset);
1046 cur_offset = ALIGN_SIZE (cur_offset, ALIGNOF (max_align_t));
1047 header.stab_offset = cur_offset;
1049 pdump_buf = xmalloc (max_size);
1050 /* Avoid use of the `open' macro. We want the real function. */
1052 pdump_fd = open (EMACS_PROGNAME ".dmp",
1053 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
1054 pdump_out = fdopen (pdump_fd, "w");
1056 fwrite (&header, sizeof (header), 1, pdump_out);
1057 PDUMP_ALIGN_OUTPUT (max_align_t);
1059 pdump_scan_by_alignment (pdump_dump_data);
1061 fseek (pdump_out, header.stab_offset, SEEK_SET);
1063 pdump_dump_root_struct_ptrs ();
1064 pdump_dump_opaques ();
1065 pdump_dump_rtables ();
1066 pdump_dump_root_objects ();
1075 Vterminal_console = t_console;
1076 Vterminal_frame = t_frame;
1077 Vterminal_device = t_device;
1081 pdump_load_check (void)
1083 return (!memcmp (((pdump_header *)pdump_start)->signature,
1084 PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN)
1085 && ((pdump_header *)pdump_start)->id == dump_id);
1088 /*----------------------------------------------------------------------*/
1089 /* Reading the dump file */
1090 /*----------------------------------------------------------------------*/
1092 pdump_load_finish (void)
1098 pdump_header *header = (pdump_header *)pdump_start;
1100 pdump_end = pdump_start + pdump_length;
1102 delta = ((EMACS_INT)pdump_start) - header->reloc_address;
1103 p = pdump_start + header->stab_offset;
1105 /* Put back the pdump_root_struct_ptrs */
1106 p = (char *) ALIGN_PTR (p, ALIGNOF (pdump_static_pointer));
1107 for (i=0; i<header->nb_root_struct_ptrs; i++)
1109 pdump_static_pointer ptr = PDUMP_READ (p, pdump_static_pointer);
1110 (* ptr.address) = ptr.value + delta;
1113 /* Put back the pdump_opaques */
1114 for (i=0; i<header->nb_opaques; i++)
1116 pdump_opaque info = PDUMP_READ_ALIGNED (p, pdump_opaque);
1117 memcpy (info.varaddress, p, info.size);
1121 /* Do the relocations */
1126 pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table);
1127 p = (char *) ALIGN_PTR (p, ALIGNOF (char *));
1130 char **reloc = (char **)p;
1131 for (i=0; i < rt.count; i++)
1134 pdump_reloc_one (reloc[i], delta, rt.desc);
1136 p += rt.count * sizeof (char *);
1142 /* Put the pdump_root_objects variables in place */
1143 i = PDUMP_READ_ALIGNED (p, size_t);
1144 p = (char *) ALIGN_PTR (p, ALIGNOF (pdump_static_Lisp_Object));
1147 pdump_static_Lisp_Object obj = PDUMP_READ (p, pdump_static_Lisp_Object);
1149 if (POINTER_TYPE_P (XTYPE (obj.value)))
1150 obj.value = wrap_object ((char *) XPNTR (obj.value) + delta);
1152 (* obj.address) = obj.value;
1155 /* Final cleanups */
1156 /* reorganize hash tables */
1160 pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table);
1161 p = (char *) ALIGN_PTR (p, ALIGNOF (Lisp_Object));
1164 if (rt.desc == hash_table_description)
1166 for (i=0; i < rt.count; i++)
1167 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object));
1170 p += sizeof (Lisp_Object) * rt.count;
1177 /* Free the mapped file if we decide we don't want it after all */
1179 pdump_file_unmap (void)
1181 UnmapViewOfFile (pdump_start);
1182 CloseHandle (pdump_hFile);
1183 CloseHandle (pdump_hMap);
1187 pdump_file_get (const char *path)
1190 pdump_hFile = CreateFile (path,
1191 GENERIC_READ + GENERIC_WRITE, /* Required for copy on write */
1193 NULL, /* Not inheritable */
1195 FILE_ATTRIBUTE_NORMAL,
1196 NULL); /* No template file */
1197 if (pdump_hFile == INVALID_HANDLE_VALUE)
1200 pdump_length = GetFileSize (pdump_hFile, NULL);
1201 pdump_hMap = CreateFileMapping (pdump_hFile,
1202 NULL, /* No security attributes */
1203 PAGE_WRITECOPY, /* Copy on write */
1204 0, /* Max size, high half */
1205 0, /* Max size, low half */
1206 NULL); /* Unnamed */
1207 if (pdump_hMap == INVALID_HANDLE_VALUE)
1210 pdump_start = MapViewOfFile (pdump_hMap,
1211 FILE_MAP_COPY, /* Copy on write */
1212 0, /* Start at zero */
1214 0); /* Map all of it */
1215 pdump_free = pdump_file_unmap;
1219 /* pdump_resource_free is called (via the pdump_free pointer) to release
1220 any resources allocated by pdump_resource_get. Since the Windows API
1221 specs specifically state that you don't need to (and shouldn't) free the
1222 resources allocated by FindResource, LoadResource, and LockResource this
1223 routine does nothing. */
1225 pdump_resource_free (void)
1230 pdump_resource_get (void)
1232 HRSRC hRes; /* Handle to dump resource */
1233 HRSRC hResLoad; /* Handle to loaded dump resource */
1235 /* See Q126630 which describes how Windows NT and 95 trap writes to
1236 resource sections and duplicate the page to allow the write to proceed.
1237 It also describes how to make the resource section read/write (and hence
1238 private to each process). Doing this avoids the exceptions and related
1239 overhead, but causes the resource section to be private to each process
1240 that is running XEmacs. Since the resource section contains little
1241 other than the dumped data, which should be private to each process, we
1242 make the whole resource section read/write so we don't have to copy it. */
1244 hRes = FindResource (NULL, MAKEINTRESOURCE(101), "DUMP");
1248 /* Found it, use the data in the resource */
1249 hResLoad = LoadResource (NULL, hRes);
1250 if (hResLoad == NULL)
1253 pdump_start = LockResource (hResLoad);
1254 if (pdump_start == NULL)
1257 pdump_free = pdump_resource_free;
1258 pdump_length = SizeofResource (NULL, hRes);
1259 if (pdump_length <= sizeof (pdump_header))
1268 #else /* !WIN32_NATIVE */
1271 pdump_file_free (void)
1273 xfree (pdump_start);
1278 pdump_file_unmap (void)
1280 munmap (pdump_start, pdump_length);
1285 pdump_file_get (const char *path)
1287 int fd = open (path, O_RDONLY | OPEN_BINARY);
1291 pdump_length = lseek (fd, 0, SEEK_END);
1292 if (pdump_length < sizeof (pdump_header))
1298 lseek (fd, 0, SEEK_SET);
1301 /* Unix 98 requires that sys/mman.h define MAP_FAILED,
1302 but many earlier implementations don't. */
1304 # define MAP_FAILED ((void *) -1L)
1306 pdump_start = (char *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
1307 if (pdump_start != (char *) MAP_FAILED)
1309 pdump_free = pdump_file_unmap;
1313 #endif /* HAVE_MMAP */
1315 pdump_start = xnew_array (char, pdump_length);
1316 pdump_free = pdump_file_free;
1317 read (fd, pdump_start, pdump_length);
1322 #endif /* !WIN32_NATIVE */
1326 pdump_file_try (char *exe_path)
1328 char *w = exe_path + strlen (exe_path);
1332 sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id);
1333 if (pdump_file_get (exe_path))
1335 if (pdump_load_check ())
1340 sprintf (w, "-%08x.dmp", dump_id);
1341 if (pdump_file_get (exe_path))
1343 if (pdump_load_check ())
1348 sprintf (w, ".dmp");
1349 if (pdump_file_get (exe_path))
1351 if (pdump_load_check ())
1358 while (w>exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && (*w != '.'));
1360 while (w>exe_path && !IS_DIRECTORY_SEP (*w));
1365 pdump_load (const char *argv0)
1367 char exe_path[PATH_MAX];
1369 GetModuleFileName (NULL, exe_path, PATH_MAX);
1370 #else /* !WIN32_NATIVE */
1372 const char *dir, *p;
1377 /* XEmacs as a login shell, oh goody! */
1378 dir = getenv ("SHELL");
1381 p = dir + strlen (dir);
1382 while (p != dir && !IS_ANY_SEP (p[-1])) p--;
1386 /* invocation-name includes a directory component -- presumably it
1387 is relative to cwd, not $PATH */
1388 strcpy (exe_path, dir);
1392 const char *path = getenv ("PATH");
1393 const char *name = p;
1397 while (*p && *p != SEPCHAR)
1406 memcpy (exe_path, path, p - path);
1407 w = exe_path + (p - path);
1409 if (!IS_DIRECTORY_SEP (w[-1]))
1415 /* ### #$%$#^$^@%$^#%@$ ! */
1420 if (!access (exe_path, X_OK))
1424 /* Oh well, let's have some kind of default */
1425 sprintf (exe_path, "./%s", name);
1431 #endif /* WIN32_NATIVE */
1433 if (pdump_file_try (exe_path))
1435 pdump_load_finish ();
1440 if (pdump_resource_get ())
1442 if (pdump_load_check ())
1444 pdump_load_finish ();