1 /* Portable data dumper for XEmacs.
2 Copyright (C) 1999-2000 Olivier Galibert
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Synched up with: Not in FSF. */
27 #include "specifier.h"
31 #include "console-stream.h"
48 const struct lrecord_description *desc;
52 static char *pdump_rt_list = 0;
55 pdump_objects_unmark (void)
58 char *p = pdump_rt_list;
62 pdump_reloc_table *rt = (pdump_reloc_table *)p;
63 p += sizeof (pdump_reloc_table);
66 for (i=0; i<rt->count; i++)
68 struct lrecord_header *lh = * (struct lrecord_header **) p;
69 if (! C_READONLY_RECORD_HEADER_P (lh))
70 UNMARK_RECORD_HEADER (lh);
71 p += sizeof (EMACS_INT);
79 /* The structure of the file
82 * 256 - dumped objects
83 * stab_offset - nb_staticpro*(Lisp_Object *) from staticvec
84 * - nb_staticpro*(relocated Lisp_Object) pointed to by staticpro
85 * - nb_structdmp*pair(void *, adr) for pointers to structures
86 * - lrecord_implementations_table[]
88 * - wired variable address/value couples with the count preceding the list
92 #define DUMP_SIGNATURE "XEmacsDP"
93 #define DUMP_SIGNATURE_LEN (sizeof (DUMP_SIGNATURE) - 1)
97 char signature[DUMP_SIGNATURE_LEN];
99 EMACS_UINT stab_offset;
100 EMACS_UINT reloc_address;
106 char *pdump_start, *pdump_end;
107 static size_t pdump_length;
110 // Handle for the dump file
111 HANDLE pdump_hFile = INVALID_HANDLE_VALUE;
112 // Handle for the file mapping object for the dump file
113 HANDLE pdump_hMap = INVALID_HANDLE_VALUE;
116 void (*pdump_free) (void);
118 static const unsigned char align_table[256] =
120 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
121 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
122 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
123 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
124 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
125 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
126 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
127 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
128 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
129 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
130 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
131 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
132 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
133 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
134 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
135 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
138 typedef struct pdump_entry_list_elmt
140 struct pdump_entry_list_elmt *next;
145 EMACS_INT save_offset;
146 } pdump_entry_list_elmt;
150 pdump_entry_list_elmt *first;
155 typedef struct pdump_struct_list_elmt
157 pdump_entry_list list;
158 const struct struct_description *sdesc;
159 } pdump_struct_list_elmt;
163 pdump_struct_list_elmt *list;
168 static pdump_entry_list pdump_object_table[256];
169 static pdump_entry_list pdump_opaque_data_list;
170 static pdump_struct_list pdump_struct_table;
172 static int pdump_alert_undump_object[256];
174 static unsigned long cur_offset;
175 static size_t max_size;
177 static void *pdump_buf;
179 #define PDUMP_HASHSIZE 200001
181 static pdump_entry_list_elmt **pdump_hash;
183 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
185 pdump_make_hash (const void *obj)
187 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
190 static pdump_entry_list_elmt *
191 pdump_get_entry (const void *obj)
193 int pos = pdump_make_hash (obj);
194 pdump_entry_list_elmt *e;
198 while ((e = pdump_hash[pos]) != 0)
204 if (pos == PDUMP_HASHSIZE)
211 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size, int count, int is_lrecord)
213 pdump_entry_list_elmt *e;
215 int pos = pdump_make_hash (obj);
217 while ((e = pdump_hash[pos]) != 0)
223 if (pos == PDUMP_HASHSIZE)
227 e = xnew (pdump_entry_list_elmt);
229 e->next = list->first;
233 e->is_lrecord = is_lrecord;
236 list->count += count;
239 align = align_table[size & 255];
240 if (align < 2 && is_lrecord)
243 if (align < list->align)
247 static pdump_entry_list *
248 pdump_get_entry_list (const struct struct_description *sdesc)
251 for (i=0; i<pdump_struct_table.count; i++)
252 if (pdump_struct_table.list[i].sdesc == sdesc)
253 return &pdump_struct_table.list[i].list;
255 if (pdump_struct_table.size <= pdump_struct_table.count)
257 if (pdump_struct_table.size == -1)
258 pdump_struct_table.size = 10;
260 pdump_struct_table.size = pdump_struct_table.size * 2;
261 pdump_struct_table.list = (pdump_struct_list_elmt *)
262 xrealloc (pdump_struct_table.list,
263 pdump_struct_table.size * sizeof (pdump_struct_list_elmt));
265 pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
266 pdump_struct_table.list[pdump_struct_table.count].list.align = 8;
267 pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
268 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
270 return &pdump_struct_table.list[pdump_struct_table.count++].list;
275 struct lrecord_header *obj;
282 static void pdump_backtrace (void)
285 stderr_out ("pdump backtrace :\n");
286 for (i=0;i<depth;i++)
288 if (!backtrace[i].obj)
289 stderr_out (" - ind. (%d, %d)\n", backtrace[i].position, backtrace[i].offset);
292 stderr_out (" - %s (%d, %d)\n",
293 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
294 backtrace[i].position,
295 backtrace[i].offset);
300 static void pdump_register_object (Lisp_Object obj);
301 static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count);
304 pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata)
309 int line = XD_INDIRECT_VAL (code);
310 int delta = XD_INDIRECT_DELTA (code);
312 irdata = ((char *)idata) + idesc[line].offset;
313 switch (idesc[line].type)
316 count = *(size_t *)irdata;
319 count = *(int *)irdata;
322 count = *(long *)irdata;
325 count = *(Bytecount *)irdata;
328 stderr_out ("Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code);
337 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me)
342 for (pos = 0; desc[pos].type != XD_END; pos++)
344 const void *rdata = (const char *)data + desc[pos].offset;
346 backtrace[me].position = pos;
347 backtrace[me].offset = desc[pos].offset;
349 switch (desc[pos].type)
351 case XD_SPECIFIER_END:
353 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
362 case XD_OPAQUE_DATA_PTR:
364 EMACS_INT count = desc[pos].data1;
365 if (XD_IS_INDIRECT (count))
366 count = pdump_get_indirect_count (count, desc, data);
368 pdump_add_entry (&pdump_opaque_data_list,
377 const char *str = *(const char **)rdata;
379 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
384 const char *str = *(const char **)rdata;
385 if ((EMACS_INT)str > 0)
386 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
391 const Lisp_Object *pobj = (const Lisp_Object *)rdata;
393 assert (desc[pos].data1 == 0);
395 backtrace[me].offset = (const char *)pobj - (const char *)data;
396 pdump_register_object (*pobj);
399 case XD_LISP_OBJECT_ARRAY:
402 EMACS_INT count = desc[pos].data1;
403 if (XD_IS_INDIRECT (count))
404 count = pdump_get_indirect_count (count, desc, data);
406 for (i = 0; i < count; i++)
408 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i;
409 Lisp_Object dobj = *pobj;
411 backtrace[me].offset = (const char *)pobj - (const char *)data;
412 pdump_register_object (dobj);
418 EMACS_INT count = desc[pos].data1;
419 const struct struct_description *sdesc = desc[pos].data2;
420 const char *dobj = *(const char **)rdata;
423 if (XD_IS_INDIRECT (count))
424 count = pdump_get_indirect_count (count, desc, data);
426 pdump_register_struct (dobj, sdesc, count);
431 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
439 pdump_register_object (Lisp_Object obj)
441 struct lrecord_header *objh;
443 if (!POINTER_TYPE_P (XTYPE (obj)))
446 objh = XRECORD_LHEADER (obj);
450 if (pdump_get_entry (objh))
453 if (LHEADER_IMPLEMENTATION (objh)->description)
458 stderr_out ("Backtrace overflow, loop ?\n");
461 backtrace[me].obj = objh;
462 backtrace[me].position = 0;
463 backtrace[me].offset = 0;
465 pdump_add_entry (pdump_object_table + objh->type,
467 LHEADER_IMPLEMENTATION (objh)->static_size ?
468 LHEADER_IMPLEMENTATION (objh)->static_size :
469 LHEADER_IMPLEMENTATION (objh)->size_in_bytes_method (objh),
472 pdump_register_sub (objh,
473 LHEADER_IMPLEMENTATION (objh)->description,
479 pdump_alert_undump_object[objh->type]++;
480 stderr_out ("Undumpable object type : %s\n", LHEADER_IMPLEMENTATION (objh)->name);
486 pdump_register_struct (const void *data, const struct struct_description *sdesc, int count)
488 if (data && !pdump_get_entry (data))
494 stderr_out ("Backtrace overflow, loop ?\n");
497 backtrace[me].obj = 0;
498 backtrace[me].position = 0;
499 backtrace[me].offset = 0;
501 pdump_add_entry (pdump_get_entry_list (sdesc),
506 for (i=0; i<count; i++)
508 pdump_register_sub (((char *)data) + sdesc->size*i,
517 pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
519 size_t size = elmt->size;
520 int count = elmt->count;
524 memcpy (pdump_buf, elmt->obj, size*count);
526 for (i=0; i<count; i++)
528 char *cur = ((char *)pdump_buf) + i*size;
530 for (pos = 0; desc[pos].type != XD_END; pos++)
532 void *rdata = cur + desc[pos].offset;
533 switch (desc[pos].type)
535 case XD_SPECIFIER_END:
536 desc = ((const Lisp_Specifier *)(elmt->obj))->methods->extra_description;
545 EMACS_INT val = desc[pos].data1;
546 if (XD_IS_INDIRECT (val))
547 val = pdump_get_indirect_count (val, desc, elmt->obj);
551 case XD_OPAQUE_DATA_PTR:
555 void *ptr = *(void **)rdata;
557 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
562 Lisp_Object obj = *(Lisp_Object *)rdata;
563 pdump_entry_list_elmt *elmt1;
566 elmt1 = pdump_get_entry (XRECORD_LHEADER (obj));
569 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
571 *(EMACS_INT *)rdata = elmt1->save_offset;
576 Lisp_Object *pobj = (Lisp_Object *) rdata;
578 assert (desc[pos].data1 == 0);
580 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
582 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
585 case XD_LISP_OBJECT_ARRAY:
587 EMACS_INT num = desc[pos].data1;
589 if (XD_IS_INDIRECT (num))
590 num = pdump_get_indirect_count (num, desc, elmt->obj);
592 for (j=0; j<num; j++)
594 Lisp_Object *pobj = ((Lisp_Object *)rdata) + j;
595 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
597 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
603 EMACS_INT str = *(EMACS_INT *)rdata;
605 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
609 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
615 write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count);
616 if (elmt->is_lrecord && ((size*count) & 3))
617 write (pdump_fd, "\0\0\0", 4-((size*count) & 3));
621 pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc)
626 for (pos = 0; desc[pos].type != XD_END; pos++)
628 void *rdata = (char *)data + desc[pos].offset;
629 switch (desc[pos].type)
631 case XD_SPECIFIER_END:
633 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
641 case XD_OPAQUE_DATA_PTR:
646 EMACS_INT ptr = *(EMACS_INT *)rdata;
648 *(EMACS_INT *)rdata = ptr+delta;
653 Lisp_Object *pobj = (Lisp_Object *) rdata;
655 assert (desc[pos].data1 == 0);
657 if (POINTER_TYPE_P (XTYPE (*pobj))
658 && ! EQ (*pobj, Qnull_pointer))
659 XSETOBJ (*pobj, (char *) XPNTR (*pobj) + delta);
663 case XD_LISP_OBJECT_ARRAY:
665 EMACS_INT num = desc[pos].data1;
667 if (XD_IS_INDIRECT (num))
668 num = pdump_get_indirect_count (num, desc, data);
670 for (j=0; j<num; j++)
672 Lisp_Object *pobj = (Lisp_Object *) rdata + j;
674 if (POINTER_TYPE_P (XTYPE (*pobj))
675 && ! EQ (*pobj, Qnull_pointer))
676 XSETOBJ (*pobj, (char *) XPNTR (*pobj) + delta);
682 EMACS_INT str = *(EMACS_INT *)rdata;
684 *(EMACS_INT *)rdata = str + delta;
688 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
695 pdump_allocate_offset (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
697 size_t size = (elmt->is_lrecord ? (elmt->size + 3) & ~3 : elmt->size)*elmt->count;
698 elmt->save_offset = cur_offset;
705 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elmt *, const struct lrecord_description *))
708 const struct lrecord_description *idesc;
709 pdump_entry_list_elmt *elmt;
710 for (align=8; align>=0; align--)
712 for (i=0; i<lrecord_type_count; i++)
713 if (pdump_object_table[i].align == align)
715 elmt = pdump_object_table[i].first;
718 idesc = lrecord_implementations_table[i]->description;
726 for (i=0; i<pdump_struct_table.count; i++)
727 if (pdump_struct_table.list[i].list.align == align)
729 elmt = pdump_struct_table.list[i].list.first;
730 idesc = pdump_struct_table.list[i].sdesc->description;
738 elmt = pdump_opaque_data_list.first;
741 if (align_table[elmt->size & 255] == align)
749 pdump_dump_staticvec (void)
751 EMACS_INT *reloc = xnew_array (EMACS_INT, staticidx);
753 write (pdump_fd, staticvec, staticidx*sizeof (Lisp_Object *));
755 for (i=0; i<staticidx; i++)
757 Lisp_Object obj = *staticvec[i];
758 if (POINTER_TYPE_P (XTYPE (obj)))
759 reloc[i] = pdump_get_entry (XRECORD_LHEADER (obj))->save_offset;
761 reloc[i] = *(EMACS_INT *)(staticvec[i]);
763 write (pdump_fd, reloc, staticidx*sizeof (Lisp_Object));
768 pdump_dump_structvec (void)
771 for (i=0; i<dumpstructidx; i++)
774 write (pdump_fd, &(dumpstructvec[i].data), sizeof (void *));
775 adr = pdump_get_entry (*(void **)(dumpstructvec[i].data))->save_offset;
776 write (pdump_fd, &adr, sizeof (adr));
781 pdump_dump_opaquevec (void)
784 for (i=0; i<dumpopaqueidx; i++)
786 write (pdump_fd, &(dumpopaquevec[i]), sizeof (dumpopaquevec[i]));
787 write (pdump_fd, dumpopaquevec[i].data, dumpopaquevec[i].size);
792 pdump_dump_itable (void)
794 write (pdump_fd, lrecord_implementations_table, lrecord_type_count*sizeof (lrecord_implementations_table[0]));
798 pdump_dump_rtables (void)
801 pdump_entry_list_elmt *elmt;
802 pdump_reloc_table rt;
804 for (i=0; i<lrecord_type_count; i++)
806 elmt = pdump_object_table[i].first;
809 rt.desc = lrecord_implementations_table[i]->description;
810 rt.count = pdump_object_table[i].count;
811 write (pdump_fd, &rt, sizeof (rt));
814 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
815 write (pdump_fd, &rdata, sizeof (rdata));
822 write (pdump_fd, &rt, sizeof (rt));
824 for (i=0; i<pdump_struct_table.count; i++)
826 elmt = pdump_struct_table.list[i].list.first;
827 rt.desc = pdump_struct_table.list[i].sdesc->description;
828 rt.count = pdump_struct_table.list[i].list.count;
829 write (pdump_fd, &rt, sizeof (rt));
832 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
833 for (j=0; j<elmt->count; j++)
835 write (pdump_fd, &rdata, sizeof (rdata));
843 write (pdump_fd, &rt, sizeof (rt));
847 pdump_dump_wired (void)
849 EMACS_INT count = pdump_wireidx + pdump_wireidx_list;
852 write (pdump_fd, &count, sizeof (count));
854 for (i=0; i<pdump_wireidx; i++)
856 EMACS_INT obj = pdump_get_entry (XRECORD_LHEADER (*(pdump_wirevec[i])))->save_offset;
857 write (pdump_fd, &pdump_wirevec[i], sizeof (pdump_wirevec[i]));
858 write (pdump_fd, &obj, sizeof (obj));
861 for (i=0; i<pdump_wireidx_list; i++)
863 Lisp_Object obj = *(pdump_wirevec_list[i]);
864 pdump_entry_list_elmt *elmt;
869 const struct lrecord_description *desc;
871 elmt = pdump_get_entry (XRECORD_LHEADER (obj));
874 desc = XRECORD_LHEADER_IMPLEMENTATION (obj)->description;
875 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
876 assert (desc[pos].type != XD_END);
878 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
880 res = elmt->save_offset;
882 write (pdump_fd, &pdump_wirevec_list[i], sizeof (pdump_wirevec_list[i]));
883 write (pdump_fd, &res, sizeof (res));
891 Lisp_Object t_console, t_device, t_frame;
895 flush_all_buffer_local_cache ();
897 /* These appear in a DEFVAR_LISP, which does a staticpro() */
898 t_console = Vterminal_console;
899 t_frame = Vterminal_frame;
900 t_device = Vterminal_device;
902 Vterminal_console = Qnil;
903 Vterminal_frame = Qnil;
904 Vterminal_device = Qnil;
906 pdump_hash = xnew_array_and_zero (pdump_entry_list_elmt *, PDUMP_HASHSIZE);
908 for (i=0; i<lrecord_type_count; i++)
910 pdump_object_table[i].first = 0;
911 pdump_object_table[i].align = 8;
912 pdump_object_table[i].count = 0;
913 pdump_alert_undump_object[i] = 0;
915 pdump_struct_table.count = 0;
916 pdump_struct_table.size = -1;
918 pdump_opaque_data_list.first = 0;
919 pdump_opaque_data_list.align = 8;
920 pdump_opaque_data_list.count = 0;
923 for (i=0; i<staticidx; i++)
924 pdump_register_object (*staticvec[i]);
925 for (i=0; i<pdump_wireidx; i++)
926 pdump_register_object (*pdump_wirevec[i]);
929 for (i=0; i<lrecord_type_count; i++)
930 if (pdump_alert_undump_object[i])
933 printf ("Undumpable types list :\n");
935 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]);
940 for (i=0; i<dumpstructidx; i++)
941 pdump_register_struct (*(void **)(dumpstructvec[i].data), dumpstructvec[i].desc, 1);
943 memcpy (hd.signature, DUMP_SIGNATURE, DUMP_SIGNATURE_LEN);
945 hd.reloc_address = 0;
946 hd.nb_staticpro = staticidx;
947 hd.nb_structdmp = dumpstructidx;
948 hd.nb_opaquedmp = dumpopaqueidx;
953 pdump_scan_by_alignment (pdump_allocate_offset);
955 pdump_buf = xmalloc (max_size);
956 /* Avoid use of the `open' macro. We want the real function. */
958 pdump_fd = open (EMACS_PROGNAME ".dmp",
959 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
960 hd.stab_offset = (cur_offset + 3) & ~3;
962 write (pdump_fd, &hd, sizeof (hd));
963 lseek (pdump_fd, 256, SEEK_SET);
965 pdump_scan_by_alignment (pdump_dump_data);
967 lseek (pdump_fd, hd.stab_offset, SEEK_SET);
969 pdump_dump_staticvec ();
970 pdump_dump_structvec ();
971 pdump_dump_opaquevec ();
972 pdump_dump_itable ();
973 pdump_dump_rtables ();
981 Vterminal_console = t_console;
982 Vterminal_frame = t_frame;
983 Vterminal_device = t_device;
986 static int pdump_load_check (void)
988 return (!memcmp (((dump_header *)pdump_start)->signature, DUMP_SIGNATURE, DUMP_SIGNATURE_LEN)
989 && ((dump_header *)pdump_start)->id == dump_id);
992 static int pdump_load_finish (void)
999 pdump_end = pdump_start + pdump_length;
1001 #define PDUMP_READ(p, type) (p = (char*) (((type *) p) + 1), *((type *) p - 1))
1003 staticidx = ((dump_header *)(pdump_start))->nb_staticpro;
1004 delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address;
1005 p = pdump_start + ((dump_header *)pdump_start)->stab_offset;
1007 /* Put back the staticvec in place */
1008 memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *));
1009 p += staticidx*sizeof (Lisp_Object *);
1010 for (i=0; i<staticidx; i++)
1012 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
1013 if (POINTER_TYPE_P (XTYPE (obj)))
1014 XSETOBJ (obj, (char *) XPNTR (obj) + delta);
1015 *staticvec[i] = obj;
1018 /* Put back the dumpstructs */
1019 for (i=0; i<((dump_header *)pdump_start)->nb_structdmp; i++)
1021 void **adr = PDUMP_READ (p, void **);
1022 *adr = (void *) (PDUMP_READ (p, char *) + delta);
1025 /* Put back the opaques */
1026 for (i=0; i<((dump_header *)pdump_start)->nb_opaquedmp; i++)
1028 struct pdump_dumpopaqueinfo di = PDUMP_READ (p, struct pdump_dumpopaqueinfo);
1029 memcpy (di.data, p, di.size);
1033 /* Put back the lrecord_implementations_table */
1034 /* The (void *) cast is there to make Ben happy. */
1035 memcpy ((void *) lrecord_implementations_table, p, lrecord_type_count*sizeof (lrecord_implementations_table[0]));
1036 p += lrecord_type_count*sizeof (lrecord_implementations_table[0]);
1038 /* Reinitialize lrecord_markers from lrecord_implementations_table */
1039 for (i=0; i < lrecord_type_count; i++)
1040 if (lrecord_implementations_table[i])
1041 lrecord_markers[i] = lrecord_implementations_table[i]->marker;
1043 /* Do the relocations */
1048 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
1051 for (i=0; i < rt.count; i++)
1053 char *adr = delta + *(char **)p;
1055 pdump_reloc_one (adr, delta, rt.desc);
1056 p += sizeof (char *);
1063 /* Put the pdump_wire variables in place */
1064 count = PDUMP_READ (p, EMACS_INT);
1066 for (i=0; i<count; i++)
1068 Lisp_Object *var = PDUMP_READ (p, Lisp_Object *);
1069 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
1071 if (POINTER_TYPE_P (XTYPE (obj)))
1072 XSETOBJ (obj, (char *) XPNTR (obj) + delta);
1077 /* Final cleanups */
1078 /* reorganize hash tables */
1082 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
1085 if (rt.desc == hash_table_description)
1087 for (i=0; i < rt.count; i++)
1088 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object));
1091 p += sizeof (Lisp_Object) * rt.count;
1098 /* Free the mapped file if we decide we don't want it after all */
1099 static void pdump_file_unmap(void)
1101 UnmapViewOfFile (pdump_start);
1102 CloseHandle (pdump_hFile);
1103 CloseHandle (pdump_hMap);
1106 static int pdump_file_get(const char *path)
1109 pdump_hFile = CreateFile (path,
1110 GENERIC_READ + GENERIC_WRITE, /* Required for copy on write */
1112 NULL, /* Not inheritable */
1114 FILE_ATTRIBUTE_NORMAL,
1115 NULL); /* No template file */
1116 if (pdump_hFile == INVALID_HANDLE_VALUE)
1119 pdump_length = GetFileSize (pdump_hFile, NULL);
1120 pdump_hMap = CreateFileMapping (pdump_hFile,
1121 NULL, /* No security attributes */
1122 PAGE_WRITECOPY, /* Copy on write */
1123 0, /* Max size, high half */
1124 0, /* Max size, low half */
1125 NULL); /* Unnamed */
1126 if (pdump_hMap == INVALID_HANDLE_VALUE)
1129 pdump_start = MapViewOfFile (pdump_hMap,
1130 FILE_MAP_COPY, /* Copy on write */
1131 0, /* Start at zero */
1133 0); /* Map all of it */
1134 pdump_free = pdump_file_unmap;
1138 /* pdump_resource_free is called (via the pdump_free pointer) to release
1139 any resources allocated by pdump_resource_get. Since the Windows API
1140 specs specifically state that you don't need to (and shouldn't) free the
1141 resources allocated by FindResource, LoadResource, and LockResource this
1142 routine does nothing. */
1143 static void pdump_resource_free (void)
1147 static int pdump_resource_get (void)
1149 HRSRC hRes; /* Handle to dump resource */
1150 HRSRC hResLoad; /* Handle to loaded dump resource */
1152 /* See Q126630 which describes how Windows NT and 95 trap writes to
1153 resource sections and duplicate the page to allow the write to proceed.
1154 It also describes how to make the resource section read/write (and hence
1155 private to each process). Doing this avoids the exceptions and related
1156 overhead, but causes the resource section to be private to each process
1157 that is running XEmacs. Since the resource section contains little
1158 other than the dumped data, which should be private to each process, we
1159 make the whole resource section read/write so we don't have to copy it. */
1161 hRes = FindResource (NULL, MAKEINTRESOURCE(101), "DUMP");
1165 /* Found it, use the data in the resource */
1166 hResLoad = LoadResource (NULL, hRes);
1167 if (hResLoad == NULL)
1170 pdump_start = LockResource (hResLoad);
1171 if (pdump_start == NULL)
1174 pdump_free = pdump_resource_free;
1175 pdump_length = SizeofResource (NULL, hRes);
1176 if (pdump_length <= sizeof(dump_header))
1185 #else /* !WIN32_NATIVE */
1187 static void *pdump_mallocadr;
1189 static void pdump_file_free(void)
1191 xfree (pdump_mallocadr);
1195 static void pdump_file_unmap(void)
1197 munmap (pdump_start, pdump_length);
1201 static int pdump_file_get(const char *path)
1203 int fd = open (path, O_RDONLY | OPEN_BINARY);
1207 pdump_length = lseek (fd, 0, SEEK_END);
1208 if (pdump_length < sizeof (dump_header))
1214 lseek (fd, 0, SEEK_SET);
1217 pdump_start = (char *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
1218 if (pdump_start != MAP_FAILED)
1220 pdump_free = pdump_file_unmap;
1226 pdump_mallocadr = xmalloc(pdump_length+255);
1227 pdump_free = pdump_file_free;
1228 pdump_start = (char *)((255 + (unsigned long)pdump_mallocadr) & ~255);
1229 read (fd, pdump_start, pdump_length);
1234 #endif /* !WIN32_NATIVE */
1237 static int pdump_file_try(char *exe_path)
1241 w = exe_path + strlen(exe_path);
1244 sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id);
1245 if (pdump_file_get (exe_path))
1247 if (pdump_load_check ())
1252 sprintf (w, "-%08x.dmp", dump_id);
1253 if (pdump_file_get (exe_path))
1255 if (pdump_load_check ())
1260 sprintf (w, ".dmp");
1261 if (pdump_file_get (exe_path))
1263 if (pdump_load_check ())
1270 while (w>exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && (*w != '.'));
1272 while (w>exe_path && !IS_DIRECTORY_SEP (*w));
1276 int pdump_load(const char *argv0)
1278 char exe_path[PATH_MAX];
1280 GetModuleFileName (NULL, exe_path, PATH_MAX);
1281 #else /* !WIN32_NATIVE */
1283 const char *dir, *p;
1288 /* XEmacs as a login shell, oh goody! */
1289 dir = getenv("SHELL");
1292 p = dir + strlen(dir);
1293 while (p != dir && !IS_ANY_SEP (p[-1])) p--;
1297 /* invocation-name includes a directory component -- presumably it
1298 is relative to cwd, not $PATH */
1299 strcpy (exe_path, dir);
1303 const char *path = getenv ("PATH");
1304 const char *name = p;
1308 while (*p && *p != SEPCHAR)
1317 memcpy (exe_path, path, p - path);
1318 w = exe_path + (p - path);
1320 if (!IS_DIRECTORY_SEP (w[-1]))
1326 /* ### #$%$#^$^@%$^#%@$ ! */
1331 if (!access (exe_path, X_OK))
1335 /* Oh well, let's have some kind of default */
1336 sprintf (exe_path, "./%s", name);
1342 #endif /* WIN32_NATIVE */
1344 if (pdump_file_try (exe_path))
1346 pdump_load_finish ();
1351 if (pdump_resource_get ())
1353 if (pdump_load_check ())
1355 pdump_load_finish ();