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"
54 Dynarr_declare (pdump_opaque);
55 } pdump_opaque_dynarr;
60 const struct struct_description *desc;
61 } pdump_root_struct_ptr;
65 Dynarr_declare (pdump_root_struct_ptr);
66 } pdump_root_struct_ptr_dynarr;
72 } pdump_static_Lisp_Object;
76 char **address; /* char * for ease of doing relocation */
78 } pdump_static_pointer;
80 static pdump_opaque_dynarr *pdump_opaques;
81 static pdump_root_struct_ptr_dynarr *pdump_root_struct_ptrs;
82 static Lisp_Object_ptr_dynarr *pdump_root_objects;
83 static Lisp_Object_ptr_dynarr *pdump_weak_object_chains;
85 /* Mark SIZE bytes at non-heap address VARADDRESS for dumping as is,
86 without any bit-twiddling. */
88 dump_add_opaque (void *varaddress, size_t size)
91 info.varaddress = varaddress;
93 if (pdump_opaques == NULL)
94 pdump_opaques = Dynarr_new (pdump_opaque);
95 Dynarr_add (pdump_opaques, info);
98 /* Mark the struct described by DESC and pointed to by the pointer at
99 non-heap address VARADDRESS for dumping.
100 All the objects reachable from this pointer will also be dumped. */
102 dump_add_root_struct_ptr (void *ptraddress, const struct struct_description *desc)
104 pdump_root_struct_ptr info;
105 info.ptraddress = (void **) ptraddress;
107 if (pdump_root_struct_ptrs == NULL)
108 pdump_root_struct_ptrs = Dynarr_new (pdump_root_struct_ptr);
109 Dynarr_add (pdump_root_struct_ptrs, info);
112 /* Mark the Lisp_Object at non-heap address VARADDRESS for dumping.
113 All the objects reachable from this var will also be dumped. */
115 dump_add_root_object (Lisp_Object *varaddress)
117 if (pdump_root_objects == NULL)
118 pdump_root_objects = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
119 Dynarr_add (pdump_root_objects, varaddress);
122 /* Mark the list pointed to by the Lisp_Object at VARADDRESS for dumping. */
124 dump_add_weak_object_chain (Lisp_Object *varaddress)
126 if (pdump_weak_object_chains == NULL)
127 pdump_weak_object_chains = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
128 Dynarr_add (pdump_weak_object_chains, varaddress);
133 pdump_align_stream (FILE *stream, size_t alignment)
135 long offset = ftell (stream);
136 long adjustment = ALIGN_SIZE (offset, alignment) - offset;
138 fseek (stream, adjustment, SEEK_CUR);
141 #define PDUMP_ALIGN_OUTPUT(type) pdump_align_stream (pdump_out, ALIGNOF (type))
143 #define PDUMP_WRITE(type, object) \
144 fwrite (&object, sizeof (object), 1, pdump_out);
146 #define PDUMP_WRITE_ALIGNED(type, object) do { \
147 PDUMP_ALIGN_OUTPUT (type); \
148 PDUMP_WRITE (type, object); \
151 #define PDUMP_READ(ptr, type) \
152 (((type *) (ptr = (char*) (((type *) ptr) + 1)))[-1])
154 #define PDUMP_READ_ALIGNED(ptr, type) \
155 ((ptr = (char *) ALIGN_PTR (ptr, ALIGNOF (type))), PDUMP_READ (ptr, type))
161 const struct lrecord_description *desc;
165 static char *pdump_rt_list = 0;
168 pdump_objects_unmark (void)
171 char *p = pdump_rt_list;
175 pdump_reloc_table *rt = (pdump_reloc_table *)p;
176 p += sizeof (pdump_reloc_table);
179 for (i=0; i<rt->count; i++)
181 struct lrecord_header *lh = * (struct lrecord_header **) p;
182 if (! C_READONLY_RECORD_HEADER_P (lh))
183 UNMARK_RECORD_HEADER (lh);
184 p += sizeof (EMACS_INT);
192 /* The structure of the file
195 stab_offset - nb_root_struct_ptrs*pair(void *, adr)
196 for pointers to structures
197 - nb_opaques*pair(void *, size) for raw bits to restore
199 - root lisp object address/value couples with the count
204 #define PDUMP_SIGNATURE "XEmacsDP"
205 #define PDUMP_SIGNATURE_LEN (sizeof (PDUMP_SIGNATURE) - 1)
209 char signature[PDUMP_SIGNATURE_LEN];
211 EMACS_UINT stab_offset;
212 EMACS_UINT reloc_address;
213 int nb_root_struct_ptrs;
219 static size_t pdump_length;
222 /* Handle for the dump file */
223 static HANDLE pdump_hFile = INVALID_HANDLE_VALUE;
224 /* Handle for the file mapping object for the dump file */
225 static HANDLE pdump_hMap = INVALID_HANDLE_VALUE;
228 static void (*pdump_free) (void);
230 static unsigned char pdump_align_table[] =
232 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
233 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
234 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
235 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1
238 static inline unsigned int
239 pdump_size_to_align (size_t size)
241 return pdump_align_table[size % countof (pdump_align_table)];
244 typedef struct pdump_entry_list_elt
246 struct pdump_entry_list_elt *next;
250 EMACS_INT save_offset;
251 } pdump_entry_list_elt;
255 pdump_entry_list_elt *first;
260 typedef struct pdump_struct_list_elt
262 pdump_entry_list list;
263 const struct struct_description *sdesc;
264 } pdump_struct_list_elt;
268 pdump_struct_list_elt *list;
273 static pdump_entry_list *pdump_object_table;
274 static pdump_entry_list pdump_opaque_data_list;
275 static pdump_struct_list pdump_struct_table;
277 static int *pdump_alert_undump_object;
279 static unsigned long cur_offset;
280 static size_t max_size;
282 static void *pdump_buf;
283 static FILE *pdump_out;
285 #define PDUMP_HASHSIZE 200001
287 static pdump_entry_list_elt **pdump_hash;
289 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
291 pdump_make_hash (const void *obj)
293 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
296 static pdump_entry_list_elt *
297 pdump_get_entry (const void *obj)
299 int pos = pdump_make_hash (obj);
300 pdump_entry_list_elt *e;
304 while ((e = pdump_hash[pos]) != 0)
310 if (pos == PDUMP_HASHSIZE)
317 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size,
320 pdump_entry_list_elt *e;
321 int pos = pdump_make_hash (obj);
323 while ((e = pdump_hash[pos]) != 0)
329 if (pos == PDUMP_HASHSIZE)
333 e = xnew (pdump_entry_list_elt);
335 e->next = list->first;
341 list->count += count;
345 int align = pdump_size_to_align (size);
347 if (align < list->align)
352 static pdump_entry_list *
353 pdump_get_entry_list (const struct struct_description *sdesc)
356 for (i=0; i<pdump_struct_table.count; i++)
357 if (pdump_struct_table.list[i].sdesc == sdesc)
358 return &pdump_struct_table.list[i].list;
360 if (pdump_struct_table.size <= pdump_struct_table.count)
362 if (pdump_struct_table.size == -1)
363 pdump_struct_table.size = 10;
365 pdump_struct_table.size = pdump_struct_table.size * 2;
366 pdump_struct_table.list = (pdump_struct_list_elt *)
367 xrealloc (pdump_struct_table.list,
368 pdump_struct_table.size * sizeof (pdump_struct_list_elt));
370 pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
371 pdump_struct_table.list[pdump_struct_table.count].list.align = ALIGNOF (max_align_t);
372 pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
373 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
375 return &pdump_struct_table.list[pdump_struct_table.count++].list;
380 struct lrecord_header *obj;
388 pdump_backtrace (void)
391 stderr_out ("pdump backtrace :\n");
392 for (i=0;i<depth;i++)
394 if (!backtrace[i].obj)
395 stderr_out (" - ind. (%d, %d)\n",
396 backtrace[i].position,
397 backtrace[i].offset);
400 stderr_out (" - %s (%d, %d)\n",
401 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
402 backtrace[i].position,
403 backtrace[i].offset);
408 static void pdump_register_object (Lisp_Object obj);
409 static void pdump_register_struct (const void *data,
410 const struct struct_description *sdesc,
414 pdump_get_indirect_count (EMACS_INT code,
415 const struct lrecord_description *idesc,
418 EMACS_INT count = 0; /* initialize to shut up GCC */
421 int line = XD_INDIRECT_VAL (code);
422 int delta = XD_INDIRECT_DELTA (code);
424 irdata = ((char *)idata) + idesc[line].offset;
425 switch (idesc[line].type)
428 count = *(size_t *)irdata;
431 count = *(int *)irdata;
434 count = *(long *)irdata;
437 count = *(Bytecount *)irdata;
440 stderr_out ("Unsupported count type : %d (line = %d, code=%ld)\n",
441 idesc[line].type, line, (long)code);
450 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me)
455 for (pos = 0; desc[pos].type != XD_END; pos++)
457 const void *rdata = (const char *)data + desc[pos].offset;
459 backtrace[me].position = pos;
460 backtrace[me].offset = desc[pos].offset;
462 switch (desc[pos].type)
464 case XD_SPECIFIER_END:
466 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
475 case XD_OPAQUE_DATA_PTR:
477 EMACS_INT count = desc[pos].data1;
478 if (XD_IS_INDIRECT (count))
479 count = pdump_get_indirect_count (count, desc, data);
481 pdump_add_entry (&pdump_opaque_data_list,
482 *(void **)rdata, count, 1);
487 const char *str = *(const char **)rdata;
489 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1);
494 const char *str = *(const char **)rdata;
495 if ((EMACS_INT)str > 0)
496 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1);
501 const Lisp_Object *pobj = (const Lisp_Object *)rdata;
503 assert (desc[pos].data1 == 0);
505 backtrace[me].offset = (const char *)pobj - (const char *)data;
506 pdump_register_object (*pobj);
509 case XD_LISP_OBJECT_ARRAY:
512 EMACS_INT count = desc[pos].data1;
513 if (XD_IS_INDIRECT (count))
514 count = pdump_get_indirect_count (count, desc, data);
516 for (i = 0; i < count; i++)
518 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i;
519 Lisp_Object dobj = *pobj;
521 backtrace[me].offset = (const char *)pobj - (const char *)data;
522 pdump_register_object (dobj);
528 EMACS_INT count = desc[pos].data1;
529 const struct struct_description *sdesc = desc[pos].data2;
530 const char *dobj = *(const char **)rdata;
533 if (XD_IS_INDIRECT (count))
534 count = pdump_get_indirect_count (count, desc, data);
536 pdump_register_struct (dobj, sdesc, count);
541 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
549 pdump_register_object (Lisp_Object obj)
551 struct lrecord_header *objh;
552 const struct lrecord_implementation *imp;
554 if (!POINTER_TYPE_P (XTYPE (obj)))
557 objh = XRECORD_LHEADER (obj);
561 if (pdump_get_entry (objh))
564 imp = LHEADER_IMPLEMENTATION (objh);
566 if (imp->description)
571 stderr_out ("Backtrace overflow, loop ?\n");
574 backtrace[me].obj = objh;
575 backtrace[me].position = 0;
576 backtrace[me].offset = 0;
578 pdump_add_entry (pdump_object_table + objh->type,
582 imp->size_in_bytes_method (objh),
584 pdump_register_sub (objh, imp->description, me);
589 pdump_alert_undump_object[objh->type]++;
590 stderr_out ("Undumpable object type : %s\n", imp->name);
596 pdump_register_struct (const void *data,
597 const struct struct_description *sdesc,
600 if (data && !pdump_get_entry (data))
606 stderr_out ("Backtrace overflow, loop ?\n");
609 backtrace[me].obj = 0;
610 backtrace[me].position = 0;
611 backtrace[me].offset = 0;
613 pdump_add_entry (pdump_get_entry_list (sdesc),
614 data, sdesc->size, count);
615 for (i=0; i<count; i++)
617 pdump_register_sub (((char *)data) + sdesc->size*i,
626 pdump_dump_data (pdump_entry_list_elt *elt,
627 const struct lrecord_description *desc)
629 size_t size = elt->size;
630 int count = elt->count;
634 memcpy (pdump_buf, elt->obj, size*count);
636 for (i=0; i<count; i++)
638 char *cur = ((char *)pdump_buf) + i*size;
640 for (pos = 0; desc[pos].type != XD_END; pos++)
642 void *rdata = cur + desc[pos].offset;
643 switch (desc[pos].type)
645 case XD_SPECIFIER_END:
646 desc = ((const Lisp_Specifier *)(elt->obj))->methods->extra_description;
655 EMACS_INT val = desc[pos].data1;
656 if (XD_IS_INDIRECT (val))
657 val = pdump_get_indirect_count (val, desc, elt->obj);
661 case XD_OPAQUE_DATA_PTR:
665 void *ptr = *(void **)rdata;
667 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
672 Lisp_Object obj = *(Lisp_Object *)rdata;
673 pdump_entry_list_elt *elt1;
676 elt1 = pdump_get_entry (XRECORD_LHEADER (obj));
679 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
681 *(EMACS_INT *)rdata = elt1->save_offset;
686 Lisp_Object *pobj = (Lisp_Object *) rdata;
688 assert (desc[pos].data1 == 0);
690 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
692 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
695 case XD_LISP_OBJECT_ARRAY:
697 EMACS_INT num = desc[pos].data1;
699 if (XD_IS_INDIRECT (num))
700 num = pdump_get_indirect_count (num, desc, elt->obj);
702 for (j=0; j<num; j++)
704 Lisp_Object *pobj = ((Lisp_Object *)rdata) + j;
705 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
707 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
713 EMACS_INT str = *(EMACS_INT *)rdata;
715 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
719 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
725 fwrite (desc ? pdump_buf : elt->obj, size, count, pdump_out);
729 pdump_reloc_one (void *data, EMACS_INT delta,
730 const struct lrecord_description *desc)
735 for (pos = 0; desc[pos].type != XD_END; pos++)
737 void *rdata = (char *)data + desc[pos].offset;
738 switch (desc[pos].type)
740 case XD_SPECIFIER_END:
742 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
750 case XD_OPAQUE_DATA_PTR:
755 EMACS_INT ptr = *(EMACS_INT *)rdata;
757 *(EMACS_INT *)rdata = ptr+delta;
762 Lisp_Object *pobj = (Lisp_Object *) rdata;
764 assert (desc[pos].data1 == 0);
766 if (POINTER_TYPE_P (XTYPE (*pobj))
767 && ! EQ (*pobj, Qnull_pointer))
768 XSETOBJ (*pobj, (char *) XPNTR (*pobj) + delta);
772 case XD_LISP_OBJECT_ARRAY:
774 EMACS_INT num = desc[pos].data1;
776 if (XD_IS_INDIRECT (num))
777 num = pdump_get_indirect_count (num, desc, data);
779 for (j=0; j<num; j++)
781 Lisp_Object *pobj = (Lisp_Object *) rdata + j;
783 if (POINTER_TYPE_P (XTYPE (*pobj))
784 && ! EQ (*pobj, Qnull_pointer))
785 XSETOBJ (*pobj, (char *) XPNTR (*pobj) + delta);
791 EMACS_INT str = *(EMACS_INT *)rdata;
793 *(EMACS_INT *)rdata = str + delta;
797 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
804 pdump_allocate_offset (pdump_entry_list_elt *elt,
805 const struct lrecord_description *desc)
807 size_t size = elt->count * elt->size;
808 elt->save_offset = cur_offset;
815 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elt *,
816 const struct lrecord_description *))
820 for (align = ALIGNOF (max_align_t); align; align>>=1)
823 pdump_entry_list_elt *elt;
825 for (i=0; i<lrecord_type_count; i++)
826 if (pdump_object_table[i].align == align)
827 for (elt = pdump_object_table[i].first; elt; elt = elt->next)
828 f (elt, lrecord_implementations_table[i]->description);
830 for (i=0; i<pdump_struct_table.count; i++)
832 pdump_struct_list_elt list = pdump_struct_table.list[i];
833 if (list.list.align == align)
834 for (elt = list.list.first; elt; elt = elt->next)
835 f (elt, list.sdesc->description);
838 for (elt = pdump_opaque_data_list.first; elt; elt = elt->next)
839 if (pdump_size_to_align (elt->size) == align)
845 pdump_dump_root_struct_ptrs (void)
848 size_t count = Dynarr_length (pdump_root_struct_ptrs);
849 pdump_static_pointer *data = alloca_array (pdump_static_pointer, count);
850 for (i = 0; i < count; i++)
852 data[i].address = (char **) Dynarr_atp (pdump_root_struct_ptrs, i)->ptraddress;
853 data[i].value = (char *) pdump_get_entry (* data[i].address)->save_offset;
855 PDUMP_ALIGN_OUTPUT (pdump_static_pointer);
856 fwrite (data, sizeof (pdump_static_pointer), count, pdump_out);
860 pdump_dump_opaques (void)
863 for (i = 0; i < Dynarr_length (pdump_opaques); i++)
865 pdump_opaque *info = Dynarr_atp (pdump_opaques, i);
866 PDUMP_WRITE_ALIGNED (pdump_opaque, *info);
867 fwrite (info->varaddress, info->size, 1, pdump_out);
872 pdump_dump_rtables (void)
875 pdump_entry_list_elt *elt;
876 pdump_reloc_table rt;
878 for (i=0; i<lrecord_type_count; i++)
880 elt = pdump_object_table[i].first;
883 rt.desc = lrecord_implementations_table[i]->description;
884 rt.count = pdump_object_table[i].count;
885 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
888 EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset;
889 PDUMP_WRITE_ALIGNED (EMACS_INT, rdata);
896 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
898 for (i=0; i<pdump_struct_table.count; i++)
900 elt = pdump_struct_table.list[i].list.first;
901 rt.desc = pdump_struct_table.list[i].sdesc->description;
902 rt.count = pdump_struct_table.list[i].list.count;
903 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
906 EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset;
908 for (j=0; j<elt->count; j++)
910 PDUMP_WRITE_ALIGNED (EMACS_INT, rdata);
918 PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
922 pdump_dump_root_objects (void)
924 size_t count = (Dynarr_length (pdump_root_objects) +
925 Dynarr_length (pdump_weak_object_chains));
928 PDUMP_WRITE_ALIGNED (size_t, count);
929 PDUMP_ALIGN_OUTPUT (pdump_static_Lisp_Object);
931 for (i=0; i<Dynarr_length (pdump_root_objects); i++)
933 pdump_static_Lisp_Object obj;
934 obj.address = Dynarr_at (pdump_root_objects, i);
935 obj.value = * obj.address;
937 if (POINTER_TYPE_P (XTYPE (obj.value)))
938 obj.value = wrap_object ((void *) pdump_get_entry (XRECORD_LHEADER (obj.value))->save_offset);
940 PDUMP_WRITE (pdump_static_Lisp_Object, obj);
943 for (i=0; i<Dynarr_length (pdump_weak_object_chains); i++)
945 pdump_entry_list_elt *elt;
946 pdump_static_Lisp_Object obj;
948 obj.address = Dynarr_at (pdump_weak_object_chains, i);
949 obj.value = * obj.address;
953 const struct lrecord_description *desc;
955 elt = pdump_get_entry (XRECORD_LHEADER (obj.value));
958 desc = XRECORD_LHEADER_IMPLEMENTATION (obj.value)->description;
959 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
960 assert (desc[pos].type != XD_END);
962 obj.value = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj.value)));
964 obj.value = wrap_object ((void *) elt->save_offset);
966 PDUMP_WRITE (pdump_static_Lisp_Object, obj);
974 Lisp_Object t_console, t_device, t_frame;
978 pdump_object_table = xnew_array (pdump_entry_list, lrecord_type_count);
979 pdump_alert_undump_object = xnew_array (int, lrecord_type_count);
981 assert (ALIGNOF (max_align_t) <= pdump_align_table[0]);
983 for (i = 0; i < countof (pdump_align_table); i++)
984 if (pdump_align_table[i] > ALIGNOF (max_align_t))
985 pdump_align_table[i] = ALIGNOF (max_align_t);
987 flush_all_buffer_local_cache ();
989 /* These appear in a DEFVAR_LISP, which does a staticpro() */
990 t_console = Vterminal_console; Vterminal_console = Qnil;
991 t_frame = Vterminal_frame; Vterminal_frame = Qnil;
992 t_device = Vterminal_device; Vterminal_device = Qnil;
994 dump_add_opaque ((void *) &lrecord_implementations_table,
995 lrecord_type_count * sizeof (lrecord_implementations_table[0]));
996 dump_add_opaque (&lrecord_markers,
997 lrecord_type_count * sizeof (lrecord_markers[0]));
999 pdump_hash = xnew_array_and_zero (pdump_entry_list_elt *, PDUMP_HASHSIZE);
1001 for (i=0; i<lrecord_type_count; i++)
1003 pdump_object_table[i].first = 0;
1004 pdump_object_table[i].align = ALIGNOF (max_align_t);
1005 pdump_object_table[i].count = 0;
1006 pdump_alert_undump_object[i] = 0;
1008 pdump_struct_table.count = 0;
1009 pdump_struct_table.size = -1;
1011 pdump_opaque_data_list.first = 0;
1012 pdump_opaque_data_list.align = ALIGNOF (max_align_t);
1013 pdump_opaque_data_list.count = 0;
1016 for (i=0; i<Dynarr_length (pdump_root_objects); i++)
1017 pdump_register_object (* Dynarr_at (pdump_root_objects, i));
1020 for (i=0; i<lrecord_type_count; i++)
1021 if (pdump_alert_undump_object[i])
1024 printf ("Undumpable types list :\n");
1026 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]);
1031 for (i=0; i<(size_t)Dynarr_length (pdump_root_struct_ptrs); i++)
1033 pdump_root_struct_ptr info = Dynarr_at (pdump_root_struct_ptrs, i);
1034 pdump_register_struct (*(info.ptraddress), info.desc, 1);
1037 memcpy (header.signature, PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN);
1038 header.id = dump_id;
1039 header.reloc_address = 0;
1040 header.nb_root_struct_ptrs = Dynarr_length (pdump_root_struct_ptrs);
1041 header.nb_opaques = Dynarr_length (pdump_opaques);
1043 cur_offset = ALIGN_SIZE (sizeof (header), ALIGNOF (max_align_t));
1046 pdump_scan_by_alignment (pdump_allocate_offset);
1047 cur_offset = ALIGN_SIZE (cur_offset, ALIGNOF (max_align_t));
1048 header.stab_offset = cur_offset;
1050 pdump_buf = xmalloc (max_size);
1051 /* Avoid use of the `open' macro. We want the real function. */
1053 pdump_fd = open (EMACS_PROGNAME ".dmp",
1054 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
1055 pdump_out = fdopen (pdump_fd, "w");
1057 fwrite (&header, sizeof (header), 1, pdump_out);
1058 PDUMP_ALIGN_OUTPUT (max_align_t);
1060 pdump_scan_by_alignment (pdump_dump_data);
1062 fseek (pdump_out, header.stab_offset, SEEK_SET);
1064 pdump_dump_root_struct_ptrs ();
1065 pdump_dump_opaques ();
1066 pdump_dump_rtables ();
1067 pdump_dump_root_objects ();
1076 Vterminal_console = t_console;
1077 Vterminal_frame = t_frame;
1078 Vterminal_device = t_device;
1082 pdump_load_check (void)
1084 return (!memcmp (((pdump_header *)pdump_start)->signature,
1085 PDUMP_SIGNATURE, PDUMP_SIGNATURE_LEN)
1086 && ((pdump_header *)pdump_start)->id == dump_id);
1089 /*----------------------------------------------------------------------*/
1090 /* Reading the dump file */
1091 /*----------------------------------------------------------------------*/
1093 pdump_load_finish (void)
1099 pdump_header *header = (pdump_header *)pdump_start;
1101 pdump_end = pdump_start + pdump_length;
1103 delta = ((EMACS_INT)pdump_start) - header->reloc_address;
1104 p = pdump_start + header->stab_offset;
1106 /* Put back the pdump_root_struct_ptrs */
1107 p = (char *) ALIGN_PTR (p, ALIGNOF (pdump_static_pointer));
1108 for (i=0; i<header->nb_root_struct_ptrs; i++)
1110 pdump_static_pointer ptr = PDUMP_READ (p, pdump_static_pointer);
1111 (* ptr.address) = ptr.value + delta;
1114 /* Put back the pdump_opaques */
1115 for (i=0; i<header->nb_opaques; i++)
1117 pdump_opaque info = PDUMP_READ_ALIGNED (p, pdump_opaque);
1118 memcpy (info.varaddress, p, info.size);
1122 /* Do the relocations */
1127 pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table);
1128 p = (char *) ALIGN_PTR (p, ALIGNOF (char *));
1131 char **reloc = (char **)p;
1132 for (i=0; i < rt.count; i++)
1135 pdump_reloc_one (reloc[i], delta, rt.desc);
1137 p += rt.count * sizeof (char *);
1143 /* Put the pdump_root_objects variables in place */
1144 i = PDUMP_READ_ALIGNED (p, size_t);
1145 p = (char *) ALIGN_PTR (p, ALIGNOF (pdump_static_Lisp_Object));
1148 pdump_static_Lisp_Object obj = PDUMP_READ (p, pdump_static_Lisp_Object);
1150 if (POINTER_TYPE_P (XTYPE (obj.value)))
1151 obj.value = wrap_object ((char *) XPNTR (obj.value) + delta);
1153 (* obj.address) = obj.value;
1156 /* Final cleanups */
1157 /* reorganize hash tables */
1161 pdump_reloc_table rt = PDUMP_READ_ALIGNED (p, pdump_reloc_table);
1162 p = (char *) ALIGN_PTR (p, ALIGNOF (Lisp_Object));
1165 if (rt.desc == hash_table_description)
1167 for (i=0; i < rt.count; i++)
1168 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object));
1171 p += sizeof (Lisp_Object) * rt.count;
1178 /* Free the mapped file if we decide we don't want it after all */
1180 pdump_file_unmap (void)
1182 UnmapViewOfFile (pdump_start);
1183 CloseHandle (pdump_hFile);
1184 CloseHandle (pdump_hMap);
1188 pdump_file_get (const char *path)
1191 pdump_hFile = CreateFile (path,
1192 GENERIC_READ + GENERIC_WRITE, /* Required for copy on write */
1194 NULL, /* Not inheritable */
1196 FILE_ATTRIBUTE_NORMAL,
1197 NULL); /* No template file */
1198 if (pdump_hFile == INVALID_HANDLE_VALUE)
1201 pdump_length = GetFileSize (pdump_hFile, NULL);
1202 pdump_hMap = CreateFileMapping (pdump_hFile,
1203 NULL, /* No security attributes */
1204 PAGE_WRITECOPY, /* Copy on write */
1205 0, /* Max size, high half */
1206 0, /* Max size, low half */
1207 NULL); /* Unnamed */
1208 if (pdump_hMap == INVALID_HANDLE_VALUE)
1211 pdump_start = MapViewOfFile (pdump_hMap,
1212 FILE_MAP_COPY, /* Copy on write */
1213 0, /* Start at zero */
1215 0); /* Map all of it */
1216 pdump_free = pdump_file_unmap;
1220 /* pdump_resource_free is called (via the pdump_free pointer) to release
1221 any resources allocated by pdump_resource_get. Since the Windows API
1222 specs specifically state that you don't need to (and shouldn't) free the
1223 resources allocated by FindResource, LoadResource, and LockResource this
1224 routine does nothing. */
1226 pdump_resource_free (void)
1231 pdump_resource_get (void)
1233 HRSRC hRes; /* Handle to dump resource */
1234 HRSRC hResLoad; /* Handle to loaded dump resource */
1236 /* See Q126630 which describes how Windows NT and 95 trap writes to
1237 resource sections and duplicate the page to allow the write to proceed.
1238 It also describes how to make the resource section read/write (and hence
1239 private to each process). Doing this avoids the exceptions and related
1240 overhead, but causes the resource section to be private to each process
1241 that is running XEmacs. Since the resource section contains little
1242 other than the dumped data, which should be private to each process, we
1243 make the whole resource section read/write so we don't have to copy it. */
1245 hRes = FindResource (NULL, MAKEINTRESOURCE(101), "DUMP");
1249 /* Found it, use the data in the resource */
1250 hResLoad = LoadResource (NULL, hRes);
1251 if (hResLoad == NULL)
1254 pdump_start = LockResource (hResLoad);
1255 if (pdump_start == NULL)
1258 pdump_free = pdump_resource_free;
1259 pdump_length = SizeofResource (NULL, hRes);
1260 if (pdump_length <= sizeof (pdump_header))
1269 #else /* !WIN32_NATIVE */
1272 pdump_file_free (void)
1274 xfree (pdump_start);
1279 pdump_file_unmap (void)
1281 munmap (pdump_start, pdump_length);
1286 pdump_file_get (const char *path)
1288 int fd = open (path, O_RDONLY | OPEN_BINARY);
1292 pdump_length = lseek (fd, 0, SEEK_END);
1293 if (pdump_length < sizeof (pdump_header))
1299 lseek (fd, 0, SEEK_SET);
1302 /* Unix 98 requires that sys/mman.h define MAP_FAILED,
1303 but many earlier implementations don't. */
1305 # define MAP_FAILED ((void *) -1L)
1307 pdump_start = (char *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
1308 if (pdump_start != (char *) MAP_FAILED)
1310 pdump_free = pdump_file_unmap;
1314 #endif /* HAVE_MMAP */
1316 pdump_start = xnew_array (char, pdump_length);
1317 pdump_free = pdump_file_free;
1318 read (fd, pdump_start, pdump_length);
1323 #endif /* !WIN32_NATIVE */
1327 pdump_file_try (char *exe_path)
1329 char *w = exe_path + strlen (exe_path);
1333 sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id);
1334 if (pdump_file_get (exe_path))
1336 if (pdump_load_check ())
1341 sprintf (w, "-%08x.dmp", dump_id);
1342 if (pdump_file_get (exe_path))
1344 if (pdump_load_check ())
1349 sprintf (w, ".dmp");
1350 if (pdump_file_get (exe_path))
1352 if (pdump_load_check ())
1359 while (w>exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && (*w != '.'));
1361 while (w>exe_path && !IS_DIRECTORY_SEP (*w));
1366 pdump_load (const char *argv0)
1368 char exe_path[PATH_MAX], real_exe_path[PATH_MAX];
1370 GetModuleFileName (NULL, exe_path, PATH_MAX);
1371 /* #### urk, needed for xrealpath() below */
1372 Vdirectory_sep_char = make_char ('\\');
1373 #else /* !WIN32_NATIVE */
1375 const char *dir, *p;
1380 /* XEmacs as a login shell, oh goody! */
1381 dir = getenv ("SHELL");
1384 p = dir + strlen (dir);
1385 while (p != dir && !IS_ANY_SEP (p[-1])) p--;
1389 /* invocation-name includes a directory component -- presumably it
1390 is relative to cwd, not $PATH */
1391 strcpy (exe_path, dir);
1395 const char *path = getenv ("PATH");
1396 const char *name = p;
1400 while (*p && *p != SEPCHAR)
1409 memcpy (exe_path, path, p - path);
1410 w = exe_path + (p - path);
1412 if (!IS_DIRECTORY_SEP (w[-1]))
1418 /* Check that exe_path is executable and not a directory */
1419 #undef access /* avoid !@#$%^& encapsulated access */
1420 #undef stat /* avoid !@#$%^& encapsulated stat */
1422 struct stat statbuf;
1423 if (access (exe_path, X_OK) == 0
1424 && stat (exe_path, &statbuf) == 0
1425 && ! S_ISDIR (statbuf.st_mode))
1431 /* Oh well, let's have some kind of default */
1432 sprintf (exe_path, "./%s", name);
1438 #endif /* WIN32_NATIVE */
1440 /* Save exe_path because pdump_file_try() modifies it */
1441 strcpy(real_exe_path, exe_path);
1442 if (pdump_file_try (exe_path)
1443 || (xrealpath(real_exe_path, real_exe_path)
1444 && pdump_file_try (real_exe_path)))
1446 pdump_load_finish ();
1451 if (pdump_resource_get ())
1453 if (pdump_load_check ())
1455 pdump_load_finish ();