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;
171 static pdump_entry_list_elmt *pdump_qnil;
173 static int pdump_alert_undump_object[256];
175 static unsigned long cur_offset;
176 static size_t max_size;
178 static void *pdump_buf;
180 #define PDUMP_HASHSIZE 200001
182 static pdump_entry_list_elmt **pdump_hash;
184 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
186 pdump_make_hash (const void *obj)
188 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
191 static pdump_entry_list_elmt *
192 pdump_get_entry (const void *obj)
194 int pos = pdump_make_hash (obj);
195 pdump_entry_list_elmt *e;
199 while ((e = pdump_hash[pos]) != 0)
205 if (pos == PDUMP_HASHSIZE)
212 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size, int count, int is_lrecord)
214 pdump_entry_list_elmt *e;
216 int pos = pdump_make_hash (obj);
218 while ((e = pdump_hash[pos]) != 0)
224 if (pos == PDUMP_HASHSIZE)
228 e = xnew (pdump_entry_list_elmt);
230 e->next = list->first;
234 e->is_lrecord = is_lrecord;
237 list->count += count;
240 align = align_table[size & 255];
241 if (align < 2 && is_lrecord)
244 if (align < list->align)
248 static pdump_entry_list *
249 pdump_get_entry_list (const struct struct_description *sdesc)
252 for (i=0; i<pdump_struct_table.count; i++)
253 if (pdump_struct_table.list[i].sdesc == sdesc)
254 return &pdump_struct_table.list[i].list;
256 if (pdump_struct_table.size <= pdump_struct_table.count)
258 if (pdump_struct_table.size == -1)
259 pdump_struct_table.size = 10;
261 pdump_struct_table.size = pdump_struct_table.size * 2;
262 pdump_struct_table.list = (pdump_struct_list_elmt *)
263 xrealloc (pdump_struct_table.list,
264 pdump_struct_table.size * sizeof (pdump_struct_list_elmt));
266 pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
267 pdump_struct_table.list[pdump_struct_table.count].list.align = 8;
268 pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
269 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
271 return &pdump_struct_table.list[pdump_struct_table.count++].list;
276 struct lrecord_header *obj;
283 static void pdump_backtrace (void)
286 stderr_out ("pdump backtrace :\n");
287 for (i=0;i<depth;i++)
289 if (!backtrace[i].obj)
290 stderr_out (" - ind. (%d, %d)\n", backtrace[i].position, backtrace[i].offset);
293 stderr_out (" - %s (%d, %d)\n",
294 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
295 backtrace[i].position,
296 backtrace[i].offset);
301 static void pdump_register_object (Lisp_Object obj);
302 static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count);
305 pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata)
310 int line = XD_INDIRECT_VAL (code);
311 int delta = XD_INDIRECT_DELTA (code);
313 irdata = ((char *)idata) + idesc[line].offset;
314 switch (idesc[line].type)
317 count = *(size_t *)irdata;
320 count = *(int *)irdata;
323 count = *(long *)irdata;
326 count = *(Bytecount *)irdata;
329 stderr_out ("Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code);
338 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me)
343 for (pos = 0; desc[pos].type != XD_END; pos++)
345 const void *rdata = (const char *)data + desc[pos].offset;
347 backtrace[me].position = pos;
348 backtrace[me].offset = desc[pos].offset;
350 switch (desc[pos].type)
352 case XD_SPECIFIER_END:
354 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
360 case XD_LO_RESET_NIL:
364 case XD_OPAQUE_DATA_PTR:
366 EMACS_INT count = desc[pos].data1;
367 if (XD_IS_INDIRECT (count))
368 count = pdump_get_indirect_count (count, desc, data);
370 pdump_add_entry (&pdump_opaque_data_list,
379 const char *str = *(const char **)rdata;
381 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
386 const char *str = *(const char **)rdata;
387 if ((EMACS_INT)str > 0)
388 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
393 const Lisp_Object *pobj = (const Lisp_Object *)rdata;
395 assert (desc[pos].data1 == 0);
397 backtrace[me].offset = (const char *)pobj - (const char *)data;
398 pdump_register_object (*pobj);
401 case XD_LISP_OBJECT_ARRAY:
404 EMACS_INT count = desc[pos].data1;
405 if (XD_IS_INDIRECT (count))
406 count = pdump_get_indirect_count (count, desc, data);
408 for (i = 0; i < count; i++)
410 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i;
411 Lisp_Object dobj = *pobj;
413 backtrace[me].offset = (const char *)pobj - (const char *)data;
414 pdump_register_object (dobj);
420 EMACS_INT count = desc[pos].data1;
421 const struct struct_description *sdesc = desc[pos].data2;
422 const char *dobj = *(const char **)rdata;
425 if (XD_IS_INDIRECT (count))
426 count = pdump_get_indirect_count (count, desc, data);
428 pdump_register_struct (dobj, sdesc, count);
433 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
441 pdump_register_object (Lisp_Object obj)
443 struct lrecord_header *objh;
445 if (!POINTER_TYPE_P (XTYPE (obj)))
448 objh = XRECORD_LHEADER (obj);
452 if (pdump_get_entry (objh))
455 if (LHEADER_IMPLEMENTATION (objh)->description)
460 stderr_out ("Backtrace overflow, loop ?\n");
463 backtrace[me].obj = objh;
464 backtrace[me].position = 0;
465 backtrace[me].offset = 0;
467 pdump_add_entry (pdump_object_table + objh->type,
469 LHEADER_IMPLEMENTATION (objh)->static_size ?
470 LHEADER_IMPLEMENTATION (objh)->static_size :
471 LHEADER_IMPLEMENTATION (objh)->size_in_bytes_method (objh),
474 pdump_register_sub (objh,
475 LHEADER_IMPLEMENTATION (objh)->description,
481 pdump_alert_undump_object[objh->type]++;
482 stderr_out ("Undumpable object type : %s\n", LHEADER_IMPLEMENTATION (objh)->name);
488 pdump_register_struct (const void *data, const struct struct_description *sdesc, int count)
490 if (data && !pdump_get_entry (data))
496 stderr_out ("Backtrace overflow, loop ?\n");
499 backtrace[me].obj = 0;
500 backtrace[me].position = 0;
501 backtrace[me].offset = 0;
503 pdump_add_entry (pdump_get_entry_list (sdesc),
508 for (i=0; i<count; i++)
510 pdump_register_sub (((char *)data) + sdesc->size*i,
519 pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
521 size_t size = elmt->size;
522 int count = elmt->count;
526 memcpy (pdump_buf, elmt->obj, size*count);
528 for (i=0; i<count; i++)
530 char *cur = ((char *)pdump_buf) + i*size;
532 for (pos = 0; desc[pos].type != XD_END; pos++)
534 void *rdata = cur + desc[pos].offset;
535 switch (desc[pos].type)
537 case XD_SPECIFIER_END:
538 desc = ((const Lisp_Specifier *)(elmt->obj))->methods->extra_description;
545 case XD_LO_RESET_NIL:
547 EMACS_INT num = desc[pos].data1;
549 if (XD_IS_INDIRECT (num))
550 num = pdump_get_indirect_count (num, desc, elmt->obj);
551 for (j=0; j<num; j++)
552 ((EMACS_INT *)rdata)[j] = pdump_qnil->save_offset;
557 EMACS_INT val = desc[pos].data1;
558 if (XD_IS_INDIRECT (val))
559 val = pdump_get_indirect_count (val, desc, elmt->obj);
563 case XD_OPAQUE_DATA_PTR:
567 void *ptr = *(void **)rdata;
569 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
574 Lisp_Object obj = *(Lisp_Object *)rdata;
575 pdump_entry_list_elmt *elmt1;
578 elmt1 = pdump_get_entry (XRECORD_LHEADER (obj));
581 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
583 *(EMACS_INT *)rdata = elmt1->save_offset;
588 Lisp_Object *pobj = (Lisp_Object *) rdata;
590 assert (desc[pos].data1 == 0);
592 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
594 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
597 case XD_LISP_OBJECT_ARRAY:
599 EMACS_INT num = desc[pos].data1;
601 if (XD_IS_INDIRECT (num))
602 num = pdump_get_indirect_count (num, desc, elmt->obj);
604 for (j=0; j<num; j++)
606 Lisp_Object *pobj = ((Lisp_Object *)rdata) + j;
607 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
609 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
615 EMACS_INT str = *(EMACS_INT *)rdata;
617 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
621 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
627 write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count);
628 if (elmt->is_lrecord && ((size*count) & 3))
629 write (pdump_fd, "\0\0\0", 4-((size*count) & 3));
633 pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc)
638 for (pos = 0; desc[pos].type != XD_END; pos++)
640 void *rdata = (char *)data + desc[pos].offset;
641 switch (desc[pos].type)
643 case XD_SPECIFIER_END:
645 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
653 case XD_OPAQUE_DATA_PTR:
658 EMACS_INT ptr = *(EMACS_INT *)rdata;
660 *(EMACS_INT *)rdata = ptr+delta;
665 Lisp_Object *pobj = (Lisp_Object *) rdata;
667 assert (desc[pos].data1 == 0);
669 if (POINTER_TYPE_P (XTYPE (*pobj))
670 && ! EQ (*pobj, Qnull_pointer))
671 XSETOBJ (*pobj, (char *) XPNTR (*pobj) + delta);
675 case XD_LISP_OBJECT_ARRAY:
676 case XD_LO_RESET_NIL:
678 EMACS_INT num = desc[pos].data1;
680 if (XD_IS_INDIRECT (num))
681 num = pdump_get_indirect_count (num, desc, data);
683 for (j=0; j<num; j++)
685 Lisp_Object *pobj = (Lisp_Object *) rdata + j;
687 if (POINTER_TYPE_P (XTYPE (*pobj))
688 && ! EQ (*pobj, Qnull_pointer))
689 XSETOBJ (*pobj, (char *) XPNTR (*pobj) + delta);
695 EMACS_INT str = *(EMACS_INT *)rdata;
697 *(EMACS_INT *)rdata = str + delta;
701 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
708 pdump_allocate_offset (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
710 size_t size = (elmt->is_lrecord ? (elmt->size + 3) & ~3 : elmt->size)*elmt->count;
711 elmt->save_offset = cur_offset;
718 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elmt *, const struct lrecord_description *))
721 const struct lrecord_description *idesc;
722 pdump_entry_list_elmt *elmt;
723 for (align=8; align>=0; align--)
725 for (i=0; i<lrecord_type_count; i++)
726 if (pdump_object_table[i].align == align)
728 elmt = pdump_object_table[i].first;
731 idesc = lrecord_implementations_table[i]->description;
739 for (i=0; i<pdump_struct_table.count; i++)
740 if (pdump_struct_table.list[i].list.align == align)
742 elmt = pdump_struct_table.list[i].list.first;
743 idesc = pdump_struct_table.list[i].sdesc->description;
751 elmt = pdump_opaque_data_list.first;
754 if (align_table[elmt->size & 255] == align)
762 pdump_dump_staticvec (void)
764 EMACS_INT *reloc = xnew_array (EMACS_INT, staticidx);
766 write (pdump_fd, staticvec, staticidx*sizeof (Lisp_Object *));
768 for (i=0; i<staticidx; i++)
770 Lisp_Object obj = *staticvec[i];
771 if (POINTER_TYPE_P (XTYPE (obj)))
772 reloc[i] = pdump_get_entry (XRECORD_LHEADER (obj))->save_offset;
774 reloc[i] = *(EMACS_INT *)(staticvec[i]);
776 write (pdump_fd, reloc, staticidx*sizeof (Lisp_Object));
781 pdump_dump_structvec (void)
784 for (i=0; i<dumpstructidx; i++)
787 write (pdump_fd, &(dumpstructvec[i].data), sizeof (void *));
788 adr = pdump_get_entry (*(void **)(dumpstructvec[i].data))->save_offset;
789 write (pdump_fd, &adr, sizeof (adr));
794 pdump_dump_opaquevec (void)
797 for (i=0; i<dumpopaqueidx; i++)
799 write (pdump_fd, &(dumpopaquevec[i]), sizeof (dumpopaquevec[i]));
800 write (pdump_fd, dumpopaquevec[i].data, dumpopaquevec[i].size);
805 pdump_dump_itable (void)
807 write (pdump_fd, lrecord_implementations_table, lrecord_type_count*sizeof (lrecord_implementations_table[0]));
811 pdump_dump_rtables (void)
814 pdump_entry_list_elmt *elmt;
815 pdump_reloc_table rt;
817 for (i=0; i<lrecord_type_count; i++)
819 elmt = pdump_object_table[i].first;
822 rt.desc = lrecord_implementations_table[i]->description;
823 rt.count = pdump_object_table[i].count;
824 write (pdump_fd, &rt, sizeof (rt));
827 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
828 write (pdump_fd, &rdata, sizeof (rdata));
835 write (pdump_fd, &rt, sizeof (rt));
837 for (i=0; i<pdump_struct_table.count; i++)
839 elmt = pdump_struct_table.list[i].list.first;
840 rt.desc = pdump_struct_table.list[i].sdesc->description;
841 rt.count = pdump_struct_table.list[i].list.count;
842 write (pdump_fd, &rt, sizeof (rt));
845 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
846 for (j=0; j<elmt->count; j++)
848 write (pdump_fd, &rdata, sizeof (rdata));
856 write (pdump_fd, &rt, sizeof (rt));
860 pdump_dump_wired (void)
862 EMACS_INT count = pdump_wireidx + pdump_wireidx_list;
865 write (pdump_fd, &count, sizeof (count));
867 for (i=0; i<pdump_wireidx; i++)
869 EMACS_INT obj = pdump_get_entry (XRECORD_LHEADER (*(pdump_wirevec[i])))->save_offset;
870 write (pdump_fd, &pdump_wirevec[i], sizeof (pdump_wirevec[i]));
871 write (pdump_fd, &obj, sizeof (obj));
874 for (i=0; i<pdump_wireidx_list; i++)
876 Lisp_Object obj = *(pdump_wirevec_list[i]);
877 pdump_entry_list_elmt *elmt;
882 const struct lrecord_description *desc;
884 elmt = pdump_get_entry (XRECORD_LHEADER (obj));
887 desc = XRECORD_LHEADER_IMPLEMENTATION (obj)->description;
888 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
889 assert (desc[pos].type != XD_END);
891 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
893 res = elmt->save_offset;
895 write (pdump_fd, &pdump_wirevec_list[i], sizeof (pdump_wirevec_list[i]));
896 write (pdump_fd, &res, sizeof (res));
904 Lisp_Object t_console, t_device, t_frame;
908 /* These appear in a DEFVAR_LISP, which does a staticpro() */
909 t_console = Vterminal_console;
910 t_frame = Vterminal_frame;
911 t_device = Vterminal_device;
913 Vterminal_console = Qnil;
914 Vterminal_frame = Qnil;
915 Vterminal_device = Qnil;
917 pdump_hash = xnew_array_and_zero (pdump_entry_list_elmt *, PDUMP_HASHSIZE);
919 for (i=0; i<lrecord_type_count; i++)
921 pdump_object_table[i].first = 0;
922 pdump_object_table[i].align = 8;
923 pdump_object_table[i].count = 0;
924 pdump_alert_undump_object[i] = 0;
926 pdump_struct_table.count = 0;
927 pdump_struct_table.size = -1;
929 pdump_opaque_data_list.first = 0;
930 pdump_opaque_data_list.align = 8;
931 pdump_opaque_data_list.count = 0;
934 for (i=0; i<staticidx; i++)
935 pdump_register_object (*staticvec[i]);
936 for (i=0; i<pdump_wireidx; i++)
937 pdump_register_object (*pdump_wirevec[i]);
940 for (i=0; i<lrecord_type_count; i++)
941 if (pdump_alert_undump_object[i])
944 printf ("Undumpable types list :\n");
946 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]);
951 for (i=0; i<dumpstructidx; i++)
952 pdump_register_struct (*(void **)(dumpstructvec[i].data), dumpstructvec[i].desc, 1);
954 memcpy (hd.signature, DUMP_SIGNATURE, DUMP_SIGNATURE_LEN);
956 hd.reloc_address = 0;
957 hd.nb_staticpro = staticidx;
958 hd.nb_structdmp = dumpstructidx;
959 hd.nb_opaquedmp = dumpopaqueidx;
964 pdump_scan_by_alignment (pdump_allocate_offset);
965 pdump_qnil = pdump_get_entry (XRECORD_LHEADER (Qnil));
967 pdump_buf = xmalloc (max_size);
968 /* Avoid use of the `open' macro. We want the real function. */
970 pdump_fd = open (EMACS_PROGNAME ".dmp",
971 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
972 hd.stab_offset = (cur_offset + 3) & ~3;
974 write (pdump_fd, &hd, sizeof (hd));
975 lseek (pdump_fd, 256, SEEK_SET);
977 pdump_scan_by_alignment (pdump_dump_data);
979 lseek (pdump_fd, hd.stab_offset, SEEK_SET);
981 pdump_dump_staticvec ();
982 pdump_dump_structvec ();
983 pdump_dump_opaquevec ();
984 pdump_dump_itable ();
985 pdump_dump_rtables ();
993 Vterminal_console = t_console;
994 Vterminal_frame = t_frame;
995 Vterminal_device = t_device;
998 static int pdump_load_check (void)
1000 return (!memcmp (((dump_header *)pdump_start)->signature, DUMP_SIGNATURE, DUMP_SIGNATURE_LEN)
1001 && ((dump_header *)pdump_start)->id == dump_id);
1004 static int pdump_load_finish (void)
1011 pdump_end = pdump_start + pdump_length;
1013 #define PDUMP_READ(p, type) (p = (char*) (((type *) p) + 1), *((type *) p - 1))
1015 staticidx = ((dump_header *)(pdump_start))->nb_staticpro;
1016 delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address;
1017 p = pdump_start + ((dump_header *)pdump_start)->stab_offset;
1019 /* Put back the staticvec in place */
1020 memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *));
1021 p += staticidx*sizeof (Lisp_Object *);
1022 for (i=0; i<staticidx; i++)
1024 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
1025 if (POINTER_TYPE_P (XTYPE (obj)))
1026 XSETOBJ (obj, (char *) XPNTR (obj) + delta);
1027 *staticvec[i] = obj;
1030 /* Put back the dumpstructs */
1031 for (i=0; i<((dump_header *)pdump_start)->nb_structdmp; i++)
1033 void **adr = PDUMP_READ (p, void **);
1034 *adr = (void *) (PDUMP_READ (p, char *) + delta);
1037 /* Put back the opaques */
1038 for (i=0; i<((dump_header *)pdump_start)->nb_opaquedmp; i++)
1040 struct pdump_dumpopaqueinfo di = PDUMP_READ (p, struct pdump_dumpopaqueinfo);
1041 memcpy (di.data, p, di.size);
1045 /* Put back the lrecord_implementations_table */
1046 /* The (void *) cast is there to make Ben happy. */
1047 memcpy ((void *) lrecord_implementations_table, p, lrecord_type_count*sizeof (lrecord_implementations_table[0]));
1048 p += lrecord_type_count*sizeof (lrecord_implementations_table[0]);
1050 /* Reinitialize lrecord_markers from lrecord_implementations_table */
1051 for (i=0; i < lrecord_type_count; i++)
1052 if (lrecord_implementations_table[i])
1053 lrecord_markers[i] = lrecord_implementations_table[i]->marker;
1055 /* Do the relocations */
1060 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
1063 for (i=0; i < rt.count; i++)
1065 char *adr = delta + *(char **)p;
1067 pdump_reloc_one (adr, delta, rt.desc);
1068 p += sizeof (char *);
1075 /* Put the pdump_wire variables in place */
1076 count = PDUMP_READ (p, EMACS_INT);
1078 for (i=0; i<count; i++)
1080 Lisp_Object *var = PDUMP_READ (p, Lisp_Object *);
1081 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
1083 if (POINTER_TYPE_P (XTYPE (obj)))
1084 XSETOBJ (obj, (char *) XPNTR (obj) + delta);
1089 /* Final cleanups */
1090 /* reorganize hash tables */
1094 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
1097 if (rt.desc == hash_table_description)
1099 for (i=0; i < rt.count; i++)
1100 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object));
1103 p += sizeof (Lisp_Object) * rt.count;
1110 /* Free the mapped file if we decide we don't want it after all */
1111 static void pdump_file_unmap(void)
1113 UnmapViewOfFile (pdump_start);
1114 CloseHandle (pdump_hFile);
1115 CloseHandle (pdump_hMap);
1118 static int pdump_file_get(const char *path)
1121 pdump_hFile = CreateFile (path,
1122 GENERIC_READ + GENERIC_WRITE, /* Required for copy on write */
1124 NULL, /* Not inheritable */
1126 FILE_ATTRIBUTE_NORMAL,
1127 NULL); /* No template file */
1128 if (pdump_hFile == INVALID_HANDLE_VALUE)
1131 pdump_length = GetFileSize (pdump_hFile, NULL);
1132 pdump_hMap = CreateFileMapping (pdump_hFile,
1133 NULL, /* No security attributes */
1134 PAGE_WRITECOPY, /* Copy on write */
1135 0, /* Max size, high half */
1136 0, /* Max size, low half */
1137 NULL); /* Unnamed */
1138 if (pdump_hMap == INVALID_HANDLE_VALUE)
1141 pdump_start = MapViewOfFile (pdump_hMap,
1142 FILE_MAP_COPY, /* Copy on write */
1143 0, /* Start at zero */
1145 0); /* Map all of it */
1146 pdump_free = pdump_file_unmap;
1150 /* pdump_resource_free is called (via the pdump_free pointer) to release
1151 any resources allocated by pdump_resource_get. Since the Windows API
1152 specs specifically state that you don't need to (and shouldn't) free the
1153 resources allocated by FindResource, LoadResource, and LockResource this
1154 routine does nothing. */
1155 static void pdump_resource_free (void)
1159 static int pdump_resource_get (void)
1161 HRSRC hRes; /* Handle to dump resource */
1162 HRSRC hResLoad; /* Handle to loaded dump resource */
1164 /* See Q126630 which describes how Windows NT and 95 trap writes to
1165 resource sections and duplicate the page to allow the write to proceed.
1166 It also describes how to make the resource section read/write (and hence
1167 private to each process). Doing this avoids the exceptions and related
1168 overhead, but causes the resource section to be private to each process
1169 that is running XEmacs. Since the resource section contains little
1170 other than the dumped data, which should be private to each process, we
1171 make the whole resource section read/write so we don't have to copy it. */
1173 hRes = FindResource (NULL, MAKEINTRESOURCE(101), "DUMP");
1177 /* Found it, use the data in the resource */
1178 hResLoad = LoadResource (NULL, hRes);
1179 if (hResLoad == NULL)
1182 pdump_start = LockResource (hResLoad);
1183 if (pdump_start == NULL)
1186 pdump_free = pdump_resource_free;
1187 pdump_length = SizeofResource (NULL, hRes);
1188 if (pdump_length <= sizeof(dump_header))
1197 #else /* !WIN32_NATIVE */
1199 static void *pdump_mallocadr;
1201 static void pdump_file_free(void)
1203 xfree (pdump_mallocadr);
1207 static void pdump_file_unmap(void)
1209 munmap (pdump_start, pdump_length);
1213 static int pdump_file_get(const char *path)
1215 int fd = open (path, O_RDONLY | OPEN_BINARY);
1219 pdump_length = lseek (fd, 0, SEEK_END);
1220 if (pdump_length < sizeof (dump_header))
1226 lseek (fd, 0, SEEK_SET);
1229 pdump_start = (char *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
1230 if (pdump_start != MAP_FAILED)
1232 pdump_free = pdump_file_unmap;
1238 pdump_mallocadr = xmalloc(pdump_length+255);
1239 pdump_free = pdump_file_free;
1240 pdump_start = (char *)((255 + (unsigned long)pdump_mallocadr) & ~255);
1241 read (pdump_fd, pdump_start, pdump_length);
1246 #endif /* !WIN32_NATIVE */
1249 static int pdump_file_try(char *exe_path)
1253 w = exe_path + strlen(exe_path);
1256 sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id);
1257 if (pdump_file_get (exe_path))
1259 if (pdump_load_check ())
1264 sprintf (w, "-%08x.dmp", dump_id);
1265 if (pdump_file_get (exe_path))
1267 if (pdump_load_check ())
1272 sprintf (w, ".dmp");
1273 if (pdump_file_get (exe_path))
1275 if (pdump_load_check ())
1282 while (w>exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && (*w != '.'));
1284 while (w>exe_path && !IS_DIRECTORY_SEP (*w));
1288 int pdump_load(const char *argv0)
1290 char exe_path[PATH_MAX];
1292 GetModuleFileName (NULL, exe_path, PATH_MAX);
1293 #else /* !WIN32_NATIVE */
1295 const char *dir, *p;
1300 /* XEmacs as a login shell, oh goody! */
1301 dir = getenv("SHELL");
1304 p = dir + strlen(dir);
1305 while (p != dir && !IS_ANY_SEP (p[-1])) p--;
1309 /* invocation-name includes a directory component -- presumably it
1310 is relative to cwd, not $PATH */
1311 strcpy (exe_path, dir);
1315 const char *path = getenv ("PATH");
1316 const char *name = p;
1320 while (*p && *p != SEPCHAR)
1329 memcpy (exe_path, path, p - path);
1330 w = exe_path + (p - path);
1332 if (!IS_DIRECTORY_SEP (w[-1]))
1338 /* ### #$%$#^$^@%$^#%@$ ! */
1343 if (!access (exe_path, X_OK))
1347 /* Oh well, let's have some kind of default */
1348 sprintf (exe_path, "./%s", name);
1354 #endif /* WIN32_NATIVE */
1356 if (pdump_file_try (exe_path))
1358 pdump_load_finish ();
1363 if (pdump_resource_get ())
1365 if (pdump_load_check ())
1367 pdump_load_finish ();