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. */
26 #include "specifier.h"
30 #include "console-stream.h"
34 #define WINDOWS_LEAN_AND_MEAN
36 #define PATH_MAX MAXPATHLEN
49 const struct lrecord_description *desc;
53 static char *pdump_rt_list = 0;
56 pdump_objects_unmark (void)
59 char *p = pdump_rt_list;
63 pdump_reloc_table *rt = (pdump_reloc_table *)p;
64 p += sizeof (pdump_reloc_table);
67 for (i=0; i<rt->count; i++)
69 struct lrecord_header *lh = * (struct lrecord_header **) p;
70 if (! C_READONLY_RECORD_HEADER_P (lh))
71 UNMARK_RECORD_HEADER (lh);
72 p += sizeof (EMACS_INT);
80 /* The structure of the file
83 * 256 - dumped objects
84 * stab_offset - nb_staticpro*(Lisp_Object *) from staticvec
85 * - nb_staticpro*(relocated Lisp_Object) pointed to by staticpro
86 * - nb_structdmp*pair(void *, adr) for pointers to structures
87 * - lrecord_implementations_table[]
89 * - wired variable address/value couples with the count preceding the list
93 #define DUMP_SIGNATURE "XEmacsDP"
94 #define DUMP_SIGNATURE_LEN (sizeof (DUMP_SIGNATURE) - 1)
98 char signature[DUMP_SIGNATURE_LEN];
100 EMACS_UINT stab_offset;
101 EMACS_UINT reloc_address;
107 char *pdump_start, *pdump_end;
108 static size_t pdump_length;
111 // Handle for the dump file
112 HANDLE pdump_hFile = INVALID_HANDLE_VALUE;
113 // Handle for the file mapping object for the dump file
114 HANDLE pdump_hMap = INVALID_HANDLE_VALUE;
117 void (*pdump_free) (void);
119 static const unsigned char align_table[256] =
121 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
122 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
123 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
124 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
125 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
126 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
127 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
128 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
129 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
130 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
131 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
132 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
133 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
134 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
135 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
136 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
139 typedef struct pdump_entry_list_elmt
141 struct pdump_entry_list_elmt *next;
146 EMACS_INT save_offset;
147 } pdump_entry_list_elmt;
151 pdump_entry_list_elmt *first;
156 typedef struct pdump_struct_list_elmt
158 pdump_entry_list list;
159 const struct struct_description *sdesc;
160 } pdump_struct_list_elmt;
164 pdump_struct_list_elmt *list;
169 static pdump_entry_list pdump_object_table[256];
170 static pdump_entry_list pdump_opaque_data_list;
171 static pdump_struct_list pdump_struct_table;
172 static pdump_entry_list_elmt *pdump_qnil;
174 static int pdump_alert_undump_object[256];
176 static unsigned long cur_offset;
177 static size_t max_size;
179 static void *pdump_buf;
181 #define PDUMP_HASHSIZE 200001
183 static pdump_entry_list_elmt **pdump_hash;
185 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
187 pdump_make_hash (const void *obj)
189 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
192 static pdump_entry_list_elmt *
193 pdump_get_entry (const void *obj)
195 int pos = pdump_make_hash (obj);
196 pdump_entry_list_elmt *e;
200 while ((e = pdump_hash[pos]) != 0)
206 if (pos == PDUMP_HASHSIZE)
213 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size, int count, int is_lrecord)
215 pdump_entry_list_elmt *e;
217 int pos = pdump_make_hash (obj);
219 while ((e = pdump_hash[pos]) != 0)
225 if (pos == PDUMP_HASHSIZE)
229 e = xnew (pdump_entry_list_elmt);
231 e->next = list->first;
235 e->is_lrecord = is_lrecord;
238 list->count += count;
241 align = align_table[size & 255];
242 if (align < 2 && is_lrecord)
245 if (align < list->align)
249 static pdump_entry_list *
250 pdump_get_entry_list (const struct struct_description *sdesc)
253 for (i=0; i<pdump_struct_table.count; i++)
254 if (pdump_struct_table.list[i].sdesc == sdesc)
255 return &pdump_struct_table.list[i].list;
257 if (pdump_struct_table.size <= pdump_struct_table.count)
259 if (pdump_struct_table.size == -1)
260 pdump_struct_table.size = 10;
262 pdump_struct_table.size = pdump_struct_table.size * 2;
263 pdump_struct_table.list = (pdump_struct_list_elmt *)
264 xrealloc (pdump_struct_table.list,
265 pdump_struct_table.size * sizeof (pdump_struct_list_elmt));
267 pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
268 pdump_struct_table.list[pdump_struct_table.count].list.align = 8;
269 pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
270 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
272 return &pdump_struct_table.list[pdump_struct_table.count++].list;
277 struct lrecord_header *obj;
284 static void pdump_backtrace (void)
287 stderr_out ("pdump backtrace :\n");
288 for (i=0;i<depth;i++)
290 if (!backtrace[i].obj)
291 stderr_out (" - ind. (%d, %d)\n", backtrace[i].position, backtrace[i].offset);
294 stderr_out (" - %s (%d, %d)\n",
295 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
296 backtrace[i].position,
297 backtrace[i].offset);
302 static void pdump_register_object (Lisp_Object obj);
303 static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count);
306 pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata)
311 int line = XD_INDIRECT_VAL (code);
312 int delta = XD_INDIRECT_DELTA (code);
314 irdata = ((char *)idata) + idesc[line].offset;
315 switch (idesc[line].type)
318 count = *(size_t *)irdata;
321 count = *(int *)irdata;
324 count = *(long *)irdata;
327 count = *(Bytecount *)irdata;
330 stderr_out ("Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code);
339 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me)
344 for (pos = 0; desc[pos].type != XD_END; pos++)
346 const void *rdata = (const char *)data + desc[pos].offset;
348 backtrace[me].position = pos;
349 backtrace[me].offset = desc[pos].offset;
351 switch (desc[pos].type)
353 case XD_SPECIFIER_END:
355 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
361 case XD_LO_RESET_NIL:
365 case XD_OPAQUE_DATA_PTR:
367 EMACS_INT count = desc[pos].data1;
368 if (XD_IS_INDIRECT (count))
369 count = pdump_get_indirect_count (count, desc, data);
371 pdump_add_entry (&pdump_opaque_data_list,
380 const char *str = *(const char **)rdata;
382 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
387 const char *str = *(const char **)rdata;
388 if ((EMACS_INT)str > 0)
389 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
394 const Lisp_Object *pobj = (const Lisp_Object *)rdata;
396 assert (desc[pos].data1 == 0);
398 backtrace[me].offset = (const char *)pobj - (const char *)data;
399 pdump_register_object (*pobj);
402 case XD_LISP_OBJECT_ARRAY:
405 EMACS_INT count = desc[pos].data1;
406 if (XD_IS_INDIRECT (count))
407 count = pdump_get_indirect_count (count, desc, data);
409 for (i = 0; i < count; i++)
411 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i;
412 Lisp_Object dobj = *pobj;
414 backtrace[me].offset = (const char *)pobj - (const char *)data;
415 pdump_register_object (dobj);
421 EMACS_INT count = desc[pos].data1;
422 const struct struct_description *sdesc = desc[pos].data2;
423 const char *dobj = *(const char **)rdata;
426 if (XD_IS_INDIRECT (count))
427 count = pdump_get_indirect_count (count, desc, data);
429 pdump_register_struct (dobj, sdesc, count);
434 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
442 pdump_register_object (Lisp_Object obj)
444 struct lrecord_header *objh;
446 if (!POINTER_TYPE_P (XTYPE (obj)))
449 objh = XRECORD_LHEADER (obj);
453 if (pdump_get_entry (objh))
456 if (LHEADER_IMPLEMENTATION (objh)->description)
461 stderr_out ("Backtrace overflow, loop ?\n");
464 backtrace[me].obj = objh;
465 backtrace[me].position = 0;
466 backtrace[me].offset = 0;
468 pdump_add_entry (pdump_object_table + objh->type,
470 LHEADER_IMPLEMENTATION (objh)->static_size ?
471 LHEADER_IMPLEMENTATION (objh)->static_size :
472 LHEADER_IMPLEMENTATION (objh)->size_in_bytes_method (objh),
475 pdump_register_sub (objh,
476 LHEADER_IMPLEMENTATION (objh)->description,
482 pdump_alert_undump_object[objh->type]++;
483 stderr_out ("Undumpable object type : %s\n", LHEADER_IMPLEMENTATION (objh)->name);
489 pdump_register_struct (const void *data, const struct struct_description *sdesc, int count)
491 if (data && !pdump_get_entry (data))
497 stderr_out ("Backtrace overflow, loop ?\n");
500 backtrace[me].obj = 0;
501 backtrace[me].position = 0;
502 backtrace[me].offset = 0;
504 pdump_add_entry (pdump_get_entry_list (sdesc),
509 for (i=0; i<count; i++)
511 pdump_register_sub (((char *)data) + sdesc->size*i,
520 pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
522 size_t size = elmt->size;
523 int count = elmt->count;
527 memcpy (pdump_buf, elmt->obj, size*count);
529 for (i=0; i<count; i++)
531 char *cur = ((char *)pdump_buf) + i*size;
533 for (pos = 0; desc[pos].type != XD_END; pos++)
535 void *rdata = cur + desc[pos].offset;
536 switch (desc[pos].type)
538 case XD_SPECIFIER_END:
539 desc = ((const Lisp_Specifier *)(elmt->obj))->methods->extra_description;
546 case XD_LO_RESET_NIL:
548 EMACS_INT num = desc[pos].data1;
550 if (XD_IS_INDIRECT (num))
551 num = pdump_get_indirect_count (num, desc, elmt->obj);
552 for (j=0; j<num; j++)
553 ((EMACS_INT *)rdata)[j] = pdump_qnil->save_offset;
558 EMACS_INT val = desc[pos].data1;
559 if (XD_IS_INDIRECT (val))
560 val = pdump_get_indirect_count (val, desc, elmt->obj);
564 case XD_OPAQUE_DATA_PTR:
568 void *ptr = *(void **)rdata;
570 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
575 Lisp_Object obj = *(Lisp_Object *)rdata;
576 pdump_entry_list_elmt *elmt1;
579 elmt1 = pdump_get_entry (XRECORD_LHEADER (obj));
582 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
584 *(EMACS_INT *)rdata = elmt1->save_offset;
589 Lisp_Object *pobj = (Lisp_Object *) rdata;
591 assert (desc[pos].data1 == 0);
593 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
595 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
598 case XD_LISP_OBJECT_ARRAY:
600 EMACS_INT num = desc[pos].data1;
602 if (XD_IS_INDIRECT (num))
603 num = pdump_get_indirect_count (num, desc, elmt->obj);
605 for (j=0; j<num; j++)
607 Lisp_Object *pobj = ((Lisp_Object *)rdata) + j;
608 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
610 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
616 EMACS_INT str = *(EMACS_INT *)rdata;
618 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
622 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
628 write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count);
629 if (elmt->is_lrecord && ((size*count) & 3))
630 write (pdump_fd, "\0\0\0", 4-((size*count) & 3));
634 pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc)
639 for (pos = 0; desc[pos].type != XD_END; pos++)
641 void *rdata = (char *)data + desc[pos].offset;
642 switch (desc[pos].type)
644 case XD_SPECIFIER_END:
646 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
654 case XD_OPAQUE_DATA_PTR:
659 EMACS_INT ptr = *(EMACS_INT *)rdata;
661 *(EMACS_INT *)rdata = ptr+delta;
666 Lisp_Object *pobj = (Lisp_Object *) rdata;
668 assert (desc[pos].data1 == 0);
670 if (POINTER_TYPE_P (XTYPE (*pobj))
671 && ! EQ (*pobj, Qnull_pointer))
672 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta);
676 case XD_LISP_OBJECT_ARRAY:
677 case XD_LO_RESET_NIL:
679 EMACS_INT num = desc[pos].data1;
681 if (XD_IS_INDIRECT (num))
682 num = pdump_get_indirect_count (num, desc, data);
684 for (j=0; j<num; j++)
686 Lisp_Object *pobj = (Lisp_Object *) rdata + j;
688 if (POINTER_TYPE_P (XTYPE (*pobj))
689 && ! EQ (*pobj, Qnull_pointer))
690 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta);
696 EMACS_INT str = *(EMACS_INT *)rdata;
698 *(EMACS_INT *)rdata = str + delta;
702 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
709 pdump_allocate_offset (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
711 size_t size = (elmt->is_lrecord ? (elmt->size + 3) & ~3 : elmt->size)*elmt->count;
712 elmt->save_offset = cur_offset;
719 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elmt *, const struct lrecord_description *))
722 const struct lrecord_description *idesc;
723 pdump_entry_list_elmt *elmt;
724 for (align=8; align>=0; align--)
726 for (i=0; i<lrecord_type_count; i++)
727 if (pdump_object_table[i].align == align)
729 elmt = pdump_object_table[i].first;
732 idesc = lrecord_implementations_table[i]->description;
740 for (i=0; i<pdump_struct_table.count; i++)
741 if (pdump_struct_table.list[i].list.align == align)
743 elmt = pdump_struct_table.list[i].list.first;
744 idesc = pdump_struct_table.list[i].sdesc->description;
752 elmt = pdump_opaque_data_list.first;
755 if (align_table[elmt->size & 255] == align)
763 pdump_dump_staticvec (void)
765 EMACS_INT *reloc = xnew_array (EMACS_INT, staticidx);
767 write (pdump_fd, staticvec, staticidx*sizeof (Lisp_Object *));
769 for (i=0; i<staticidx; i++)
771 Lisp_Object obj = *staticvec[i];
772 if (POINTER_TYPE_P (XTYPE (obj)))
773 reloc[i] = pdump_get_entry (XRECORD_LHEADER (obj))->save_offset;
775 reloc[i] = *(EMACS_INT *)(staticvec[i]);
777 write (pdump_fd, reloc, staticidx*sizeof (Lisp_Object));
782 pdump_dump_structvec (void)
785 for (i=0; i<dumpstructidx; i++)
788 write (pdump_fd, &(dumpstructvec[i].data), sizeof (void *));
789 adr = pdump_get_entry (*(void **)(dumpstructvec[i].data))->save_offset;
790 write (pdump_fd, &adr, sizeof (adr));
795 pdump_dump_opaquevec (void)
798 for (i=0; i<dumpopaqueidx; i++)
800 write (pdump_fd, &(dumpopaquevec[i]), sizeof (dumpopaquevec[i]));
801 write (pdump_fd, dumpopaquevec[i].data, dumpopaquevec[i].size);
806 pdump_dump_itable (void)
808 write (pdump_fd, lrecord_implementations_table, lrecord_type_count*sizeof (lrecord_implementations_table[0]));
812 pdump_dump_rtables (void)
815 pdump_entry_list_elmt *elmt;
816 pdump_reloc_table rt;
818 for (i=0; i<lrecord_type_count; i++)
820 elmt = pdump_object_table[i].first;
823 rt.desc = lrecord_implementations_table[i]->description;
824 rt.count = pdump_object_table[i].count;
825 write (pdump_fd, &rt, sizeof (rt));
828 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
829 write (pdump_fd, &rdata, sizeof (rdata));
836 write (pdump_fd, &rt, sizeof (rt));
838 for (i=0; i<pdump_struct_table.count; i++)
840 elmt = pdump_struct_table.list[i].list.first;
841 rt.desc = pdump_struct_table.list[i].sdesc->description;
842 rt.count = pdump_struct_table.list[i].list.count;
843 write (pdump_fd, &rt, sizeof (rt));
846 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
847 for (j=0; j<elmt->count; j++)
849 write (pdump_fd, &rdata, sizeof (rdata));
857 write (pdump_fd, &rt, sizeof (rt));
861 pdump_dump_wired (void)
863 EMACS_INT count = pdump_wireidx + pdump_wireidx_list;
866 write (pdump_fd, &count, sizeof (count));
868 for (i=0; i<pdump_wireidx; i++)
870 EMACS_INT obj = pdump_get_entry (XRECORD_LHEADER (*(pdump_wirevec[i])))->save_offset;
871 write (pdump_fd, &pdump_wirevec[i], sizeof (pdump_wirevec[i]));
872 write (pdump_fd, &obj, sizeof (obj));
875 for (i=0; i<pdump_wireidx_list; i++)
877 Lisp_Object obj = *(pdump_wirevec_list[i]);
878 pdump_entry_list_elmt *elmt;
883 const struct lrecord_description *desc;
885 elmt = pdump_get_entry (XRECORD_LHEADER (obj));
888 desc = XRECORD_LHEADER_IMPLEMENTATION (obj)->description;
889 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
890 assert (desc[pos].type != XD_END);
892 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
894 res = elmt->save_offset;
896 write (pdump_fd, &pdump_wirevec_list[i], sizeof (pdump_wirevec_list[i]));
897 write (pdump_fd, &res, sizeof (res));
905 Lisp_Object t_console, t_device, t_frame;
909 /* These appear in a DEFVAR_LISP, which does a staticpro() */
910 t_console = Vterminal_console;
911 t_frame = Vterminal_frame;
912 t_device = Vterminal_device;
914 Vterminal_console = Qnil;
915 Vterminal_frame = Qnil;
916 Vterminal_device = Qnil;
918 pdump_hash = xnew_array_and_zero (pdump_entry_list_elmt *, PDUMP_HASHSIZE);
920 for (i=0; i<lrecord_type_count; i++)
922 pdump_object_table[i].first = 0;
923 pdump_object_table[i].align = 8;
924 pdump_object_table[i].count = 0;
925 pdump_alert_undump_object[i] = 0;
927 pdump_struct_table.count = 0;
928 pdump_struct_table.size = -1;
930 pdump_opaque_data_list.first = 0;
931 pdump_opaque_data_list.align = 8;
932 pdump_opaque_data_list.count = 0;
935 for (i=0; i<staticidx; i++)
936 pdump_register_object (*staticvec[i]);
937 for (i=0; i<pdump_wireidx; i++)
938 pdump_register_object (*pdump_wirevec[i]);
941 for (i=0; i<lrecord_type_count; i++)
942 if (pdump_alert_undump_object[i])
945 printf ("Undumpable types list :\n");
947 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]);
952 for (i=0; i<dumpstructidx; i++)
953 pdump_register_struct (*(void **)(dumpstructvec[i].data), dumpstructvec[i].desc, 1);
955 memcpy (hd.signature, DUMP_SIGNATURE, DUMP_SIGNATURE_LEN);
957 hd.reloc_address = 0;
958 hd.nb_staticpro = staticidx;
959 hd.nb_structdmp = dumpstructidx;
960 hd.nb_opaquedmp = dumpopaqueidx;
965 pdump_scan_by_alignment (pdump_allocate_offset);
966 pdump_qnil = pdump_get_entry (XRECORD_LHEADER (Qnil));
968 pdump_buf = xmalloc (max_size);
969 /* Avoid use of the `open' macro. We want the real function. */
971 pdump_fd = open (EMACS_PROGNAME ".dmp",
972 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
973 hd.stab_offset = (cur_offset + 3) & ~3;
975 write (pdump_fd, &hd, sizeof (hd));
976 lseek (pdump_fd, 256, SEEK_SET);
978 pdump_scan_by_alignment (pdump_dump_data);
980 lseek (pdump_fd, hd.stab_offset, SEEK_SET);
982 pdump_dump_staticvec ();
983 pdump_dump_structvec ();
984 pdump_dump_opaquevec ();
985 pdump_dump_itable ();
986 pdump_dump_rtables ();
994 Vterminal_console = t_console;
995 Vterminal_frame = t_frame;
996 Vterminal_device = t_device;
999 static int pdump_load_check (void)
1001 return (!memcmp (((dump_header *)pdump_start)->signature, DUMP_SIGNATURE, DUMP_SIGNATURE_LEN)
1002 && ((dump_header *)pdump_start)->id == dump_id);
1005 static int pdump_load_finish (void)
1012 pdump_end = pdump_start + pdump_length;
1014 #define PDUMP_READ(p, type) (p = (char*) (((type *) p) + 1), *((type *) p - 1))
1016 staticidx = ((dump_header *)(pdump_start))->nb_staticpro;
1017 delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address;
1018 p = pdump_start + ((dump_header *)pdump_start)->stab_offset;
1020 /* Put back the staticvec in place */
1021 memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *));
1022 p += staticidx*sizeof (Lisp_Object *);
1023 for (i=0; i<staticidx; i++)
1025 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
1026 if (POINTER_TYPE_P (XTYPE (obj)))
1027 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta);
1028 *staticvec[i] = obj;
1031 /* Put back the dumpstructs */
1032 for (i=0; i<((dump_header *)pdump_start)->nb_structdmp; i++)
1034 void **adr = PDUMP_READ (p, void **);
1035 *adr = (void *) (PDUMP_READ (p, char *) + delta);
1038 /* Put back the opaques */
1039 for (i=0; i<((dump_header *)pdump_start)->nb_opaquedmp; i++)
1041 struct pdump_dumpopaqueinfo di = PDUMP_READ (p, struct pdump_dumpopaqueinfo);
1042 memcpy (di.data, p, di.size);
1046 /* Put back the lrecord_implementations_table */
1047 /* The (void *) cast is there to make Ben happy. */
1048 memcpy ((void *) lrecord_implementations_table, p, lrecord_type_count*sizeof (lrecord_implementations_table[0]));
1049 p += lrecord_type_count*sizeof (lrecord_implementations_table[0]);
1051 /* Reinitialize lrecord_markers from lrecord_implementations_table */
1052 for (i=0; i < lrecord_type_count; i++)
1053 if (lrecord_implementations_table[i])
1054 lrecord_markers[i] = lrecord_implementations_table[i]->marker;
1056 /* Do the relocations */
1061 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
1064 for (i=0; i < rt.count; i++)
1066 char *adr = delta + *(char **)p;
1068 pdump_reloc_one (adr, delta, rt.desc);
1069 p += sizeof (char *);
1076 /* Put the pdump_wire variables in place */
1077 count = PDUMP_READ (p, EMACS_INT);
1079 for (i=0; i<count; i++)
1081 Lisp_Object *var = PDUMP_READ (p, Lisp_Object *);
1082 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
1084 if (POINTER_TYPE_P (XTYPE (obj)))
1085 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta);
1090 /* Final cleanups */
1091 /* reorganize hash tables */
1095 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
1098 if (rt.desc == hash_table_description)
1100 for (i=0; i < rt.count; i++)
1101 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object));
1104 p += sizeof (Lisp_Object) * rt.count;
1107 /* Put back noninteractive1 to its real value */
1108 noninteractive1 = noninteractive;
1114 /* Free the mapped file if we decide we don't want it after all */
1115 static void pdump_file_unmap(void)
1117 UnmapViewOfFile (pdump_start);
1118 CloseHandle (pdump_hFile);
1119 CloseHandle (pdump_hMap);
1122 static int pdump_file_get(const char *path)
1125 pdump_hFile = CreateFile (path,
1126 GENERIC_READ + GENERIC_WRITE, /* Required for copy on write */
1128 NULL, /* Not inheritable */
1130 FILE_ATTRIBUTE_NORMAL,
1131 NULL); /* No template file */
1132 if (pdump_hFile == INVALID_HANDLE_VALUE)
1135 pdump_length = GetFileSize (pdump_hFile, NULL);
1136 pdump_hMap = CreateFileMapping (pdump_hFile,
1137 NULL, /* No security attributes */
1138 PAGE_WRITECOPY, /* Copy on write */
1139 0, /* Max size, high half */
1140 0, /* Max size, low half */
1141 NULL); /* Unnamed */
1142 if (pdump_hMap == INVALID_HANDLE_VALUE)
1145 pdump_start = MapViewOfFile (pdump_hMap,
1146 FILE_MAP_COPY, /* Copy on write */
1147 0, /* Start at zero */
1149 0); /* Map all of it */
1150 pdump_free = pdump_file_unmap;
1154 /* pdump_resource_free is called (via the pdump_free pointer) to release
1155 any resources allocated by pdump_resource_get. Since the Windows API
1156 specs specifically state that you don't need to (and shouldn't) free the
1157 resources allocated by FindResource, LoadResource, and LockResource this
1158 routine does nothing. */
1159 static void pdump_resource_free (void)
1163 static int pdump_resource_get (void)
1165 HRSRC hRes; /* Handle to dump resource */
1166 HRSRC hResLoad; /* Handle to loaded dump resource */
1168 /* See Q126630 which describes how Windows NT and 95 trap writes to
1169 resource sections and duplicate the page to allow the write to proceed.
1170 It also describes how to make the resource section read/write (and hence
1171 private to each process). Doing this avoids the exceptions and related
1172 overhead, but causes the resource section to be private to each process
1173 that is running XEmacs. Since the resource section contains little
1174 other than the dumped data, which should be private to each process, we
1175 make the whole resource section read/write so we don't have to copy it. */
1177 hRes = FindResource (NULL, MAKEINTRESOURCE(101), "DUMP");
1181 /* Found it, use the data in the resource */
1182 hResLoad = LoadResource (NULL, hRes);
1183 if (hResLoad == NULL)
1186 pdump_start = LockResource (hResLoad);
1187 if (pdump_start == NULL)
1190 pdump_free = pdump_resource_free;
1191 pdump_length = SizeofResource (NULL, hRes);
1192 if (pdump_length <= sizeof(dump_header))
1201 #else /* !WINDOWSNT */
1203 static void *pdump_mallocadr;
1205 static void pdump_file_free(void)
1207 xfree (pdump_mallocadr);
1211 static void pdump_file_unmap(void)
1213 munmap (pdump_start, pdump_length);
1217 static int pdump_file_get(const char *path)
1219 int fd = open (path, O_RDONLY | OPEN_BINARY);
1223 pdump_length = lseek (fd, 0, SEEK_END);
1224 if (pdump_length < sizeof (dump_header))
1230 lseek (fd, 0, SEEK_SET);
1233 pdump_start = (char *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
1234 if (pdump_start != MAP_FAILED)
1236 pdump_free = pdump_file_unmap;
1242 pdump_mallocadr = xmalloc(pdump_length+255);
1243 pdump_free = pdump_file_free;
1244 pdump_start = (char *)((255 + (unsigned long)pdump_mallocadr) & ~255);
1245 read (pdump_fd, pdump_start, pdump_length);
1250 #endif /* !WINDOWSNT */
1253 static int pdump_file_try(char *exe_path)
1257 w = exe_path + strlen(exe_path);
1260 sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id);
1261 if (pdump_file_get (exe_path))
1263 if (pdump_load_check ())
1268 sprintf (w, "-%08x.dmp", dump_id);
1269 if (pdump_file_get (exe_path))
1271 if (pdump_load_check ())
1276 sprintf (w, ".dmp");
1277 if (pdump_file_get (exe_path))
1279 if (pdump_load_check ())
1286 while (w>exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && (*w != '.'));
1288 while (w>exe_path && !IS_DIRECTORY_SEP (*w));
1292 int pdump_load(const char *argv0)
1294 char exe_path[PATH_MAX];
1296 GetModuleFileName (NULL, exe_path, PATH_MAX);
1297 #else /* !WINDOWSNT */
1299 const char *dir, *p;
1304 /* XEmacs as a login shell, oh goody! */
1305 dir = getenv("SHELL");
1308 p = dir + strlen(dir);
1309 while (p != dir && !IS_ANY_SEP (p[-1])) p--;
1313 /* invocation-name includes a directory component -- presumably it
1314 is relative to cwd, not $PATH */
1315 strcpy (exe_path, dir);
1319 const char *path = getenv ("PATH");
1320 const char *name = p;
1324 while (*p && *p != SEPCHAR)
1333 memcpy (exe_path, path, p - path);
1334 w = exe_path + (p - path);
1336 if (!IS_DIRECTORY_SEP (w[-1]))
1342 /* ### #$%$#^$^@%$^#%@$ ! */
1347 if (!access (exe_path, X_OK))
1351 /* Oh well, let's have some kind of default */
1352 sprintf (exe_path, "./%s", name);
1358 #endif /* WINDOWSNT */
1360 if (pdump_file_try (exe_path))
1362 pdump_load_finish ();
1367 if (pdump_resource_get ())
1369 if (pdump_load_check ())
1371 pdump_load_finish ();