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"
43 const struct lrecord_description *desc;
47 static char *pdump_rt_list = 0;
50 pdump_objects_unmark (void)
53 char *p = pdump_rt_list;
57 pdump_reloc_table *rt = (pdump_reloc_table *)p;
58 p += sizeof (pdump_reloc_table);
61 for (i=0; i<rt->count; i++)
63 struct lrecord_header *lh = * (struct lrecord_header **) p;
64 if (! C_READONLY_RECORD_HEADER_P (lh))
65 UNMARK_RECORD_HEADER (lh);
66 p += sizeof (EMACS_INT);
74 /* The structure of the file
77 * 256 - dumped objects
78 * stab_offset - nb_staticpro*(Lisp_Object *) from staticvec
79 * - nb_staticpro*(relocated Lisp_Object) pointed to by staticpro
80 * - nb_structdmp*pair(void *, adr) for pointers to structures
81 * - lrecord_implementations_table[]
83 * - wired variable address/value couples with the count preceding the list
87 #define DUMP_SIGNATURE "XEmacsDP"
88 #define DUMP_SIGNATURE_LEN (sizeof (DUMP_SIGNATURE) - 1)
92 char signature[DUMP_SIGNATURE_LEN];
94 EMACS_UINT stab_offset;
95 EMACS_UINT reloc_address;
101 char *pdump_start, *pdump_end;
102 static size_t pdump_length;
103 void (*pdump_free) (void);
105 static const unsigned char align_table[256] =
107 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
108 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
109 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
110 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
111 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
112 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
113 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
114 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
115 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
116 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
117 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
118 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
119 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
120 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
121 5, 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
125 typedef struct pdump_entry_list_elmt
127 struct pdump_entry_list_elmt *next;
132 EMACS_INT save_offset;
133 } pdump_entry_list_elmt;
137 pdump_entry_list_elmt *first;
142 typedef struct pdump_struct_list_elmt
144 pdump_entry_list list;
145 const struct struct_description *sdesc;
146 } pdump_struct_list_elmt;
150 pdump_struct_list_elmt *list;
155 static pdump_entry_list pdump_object_table[256];
156 static pdump_entry_list pdump_opaque_data_list;
157 static pdump_struct_list pdump_struct_table;
158 static pdump_entry_list_elmt *pdump_qnil;
160 static int pdump_alert_undump_object[256];
162 static unsigned long cur_offset;
163 static size_t max_size;
165 static void *pdump_buf;
167 #define PDUMP_HASHSIZE 200001
169 static pdump_entry_list_elmt **pdump_hash;
171 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
173 pdump_make_hash (const void *obj)
175 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
178 static pdump_entry_list_elmt *
179 pdump_get_entry (const void *obj)
181 int pos = pdump_make_hash (obj);
182 pdump_entry_list_elmt *e;
186 while ((e = pdump_hash[pos]) != 0)
192 if (pos == PDUMP_HASHSIZE)
199 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size, int count, int is_lrecord)
201 pdump_entry_list_elmt *e;
203 int pos = pdump_make_hash (obj);
205 while ((e = pdump_hash[pos]) != 0)
211 if (pos == PDUMP_HASHSIZE)
215 e = xnew (pdump_entry_list_elmt);
217 e->next = list->first;
221 e->is_lrecord = is_lrecord;
224 list->count += count;
227 align = align_table[size & 255];
228 if (align < 2 && is_lrecord)
231 if (align < list->align)
235 static pdump_entry_list *
236 pdump_get_entry_list (const struct struct_description *sdesc)
239 for (i=0; i<pdump_struct_table.count; i++)
240 if (pdump_struct_table.list[i].sdesc == sdesc)
241 return &pdump_struct_table.list[i].list;
243 if (pdump_struct_table.size <= pdump_struct_table.count)
245 if (pdump_struct_table.size == -1)
246 pdump_struct_table.size = 10;
248 pdump_struct_table.size = pdump_struct_table.size * 2;
249 pdump_struct_table.list = (pdump_struct_list_elmt *)
250 xrealloc (pdump_struct_table.list,
251 pdump_struct_table.size * sizeof (pdump_struct_list_elmt));
253 pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
254 pdump_struct_table.list[pdump_struct_table.count].list.align = 8;
255 pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
256 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
258 return &pdump_struct_table.list[pdump_struct_table.count++].list;
263 struct lrecord_header *obj;
270 static void pdump_backtrace (void)
273 stderr_out ("pdump backtrace :\n");
274 for (i=0;i<depth;i++)
276 if (!backtrace[i].obj)
277 stderr_out (" - ind. (%d, %d)\n", backtrace[i].position, backtrace[i].offset);
280 stderr_out (" - %s (%d, %d)\n",
281 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
282 backtrace[i].position,
283 backtrace[i].offset);
288 static void pdump_register_object (Lisp_Object obj);
289 static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count);
292 pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata)
297 int line = XD_INDIRECT_VAL (code);
298 int delta = XD_INDIRECT_DELTA (code);
300 irdata = ((char *)idata) + idesc[line].offset;
301 switch (idesc[line].type)
304 count = *(size_t *)irdata;
307 count = *(int *)irdata;
310 count = *(long *)irdata;
313 count = *(Bytecount *)irdata;
316 stderr_out ("Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code);
325 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me)
330 for (pos = 0; desc[pos].type != XD_END; pos++)
332 const void *rdata = (const char *)data + desc[pos].offset;
334 backtrace[me].position = pos;
335 backtrace[me].offset = desc[pos].offset;
337 switch (desc[pos].type)
339 case XD_SPECIFIER_END:
341 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
347 case XD_LO_RESET_NIL:
351 case XD_OPAQUE_DATA_PTR:
353 EMACS_INT count = desc[pos].data1;
354 if (XD_IS_INDIRECT (count))
355 count = pdump_get_indirect_count (count, desc, data);
357 pdump_add_entry (&pdump_opaque_data_list,
366 const char *str = *(const char **)rdata;
368 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
373 const char *str = *(const char **)rdata;
374 if ((EMACS_INT)str > 0)
375 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
380 const Lisp_Object *pobj = (const Lisp_Object *)rdata;
382 assert (desc[pos].data1 == 0);
384 backtrace[me].offset = (const char *)pobj - (const char *)data;
385 pdump_register_object (*pobj);
388 case XD_LISP_OBJECT_ARRAY:
391 EMACS_INT count = desc[pos].data1;
392 if (XD_IS_INDIRECT (count))
393 count = pdump_get_indirect_count (count, desc, data);
395 for (i = 0; i < count; i++)
397 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i;
398 Lisp_Object dobj = *pobj;
400 backtrace[me].offset = (const char *)pobj - (const char *)data;
401 pdump_register_object (dobj);
407 EMACS_INT count = desc[pos].data1;
408 const struct struct_description *sdesc = desc[pos].data2;
409 const char *dobj = *(const char **)rdata;
412 if (XD_IS_INDIRECT (count))
413 count = pdump_get_indirect_count (count, desc, data);
415 pdump_register_struct (dobj, sdesc, count);
420 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
428 pdump_register_object (Lisp_Object obj)
430 struct lrecord_header *objh;
432 if (!POINTER_TYPE_P (XTYPE (obj)))
435 objh = XRECORD_LHEADER (obj);
439 if (pdump_get_entry (objh))
442 if (LHEADER_IMPLEMENTATION (objh)->description)
447 stderr_out ("Backtrace overflow, loop ?\n");
450 backtrace[me].obj = objh;
451 backtrace[me].position = 0;
452 backtrace[me].offset = 0;
454 pdump_add_entry (pdump_object_table + objh->type,
456 LHEADER_IMPLEMENTATION (objh)->static_size ?
457 LHEADER_IMPLEMENTATION (objh)->static_size :
458 LHEADER_IMPLEMENTATION (objh)->size_in_bytes_method (objh),
461 pdump_register_sub (objh,
462 LHEADER_IMPLEMENTATION (objh)->description,
468 pdump_alert_undump_object[objh->type]++;
469 stderr_out ("Undumpable object type : %s\n", LHEADER_IMPLEMENTATION (objh)->name);
475 pdump_register_struct (const void *data, const struct struct_description *sdesc, int count)
477 if (data && !pdump_get_entry (data))
483 stderr_out ("Backtrace overflow, loop ?\n");
486 backtrace[me].obj = 0;
487 backtrace[me].position = 0;
488 backtrace[me].offset = 0;
490 pdump_add_entry (pdump_get_entry_list (sdesc),
495 for (i=0; i<count; i++)
497 pdump_register_sub (((char *)data) + sdesc->size*i,
506 pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
508 size_t size = elmt->size;
509 int count = elmt->count;
513 memcpy (pdump_buf, elmt->obj, size*count);
515 for (i=0; i<count; i++)
517 char *cur = ((char *)pdump_buf) + i*size;
519 for (pos = 0; desc[pos].type != XD_END; pos++)
521 void *rdata = cur + desc[pos].offset;
522 switch (desc[pos].type)
524 case XD_SPECIFIER_END:
525 desc = ((const Lisp_Specifier *)(elmt->obj))->methods->extra_description;
532 case XD_LO_RESET_NIL:
534 EMACS_INT num = desc[pos].data1;
536 if (XD_IS_INDIRECT (num))
537 num = pdump_get_indirect_count (num, desc, elmt->obj);
538 for (j=0; j<num; j++)
539 ((EMACS_INT *)rdata)[j] = pdump_qnil->save_offset;
544 EMACS_INT val = desc[pos].data1;
545 if (XD_IS_INDIRECT (val))
546 val = pdump_get_indirect_count (val, desc, elmt->obj);
550 case XD_OPAQUE_DATA_PTR:
554 void *ptr = *(void **)rdata;
556 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
561 Lisp_Object obj = *(Lisp_Object *)rdata;
562 pdump_entry_list_elmt *elmt1;
565 elmt1 = pdump_get_entry (XRECORD_LHEADER (obj));
568 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
570 *(EMACS_INT *)rdata = elmt1->save_offset;
575 Lisp_Object *pobj = (Lisp_Object *) rdata;
577 assert (desc[pos].data1 == 0);
579 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
581 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
584 case XD_LISP_OBJECT_ARRAY:
586 EMACS_INT num = desc[pos].data1;
588 if (XD_IS_INDIRECT (num))
589 num = pdump_get_indirect_count (num, desc, elmt->obj);
591 for (j=0; j<num; j++)
593 Lisp_Object *pobj = ((Lisp_Object *)rdata) + j;
594 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
596 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
602 EMACS_INT str = *(EMACS_INT *)rdata;
604 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
608 stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
614 write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count);
615 if (elmt->is_lrecord && ((size*count) & 3))
616 write (pdump_fd, "\0\0\0", 4-((size*count) & 3));
620 pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc)
625 for (pos = 0; desc[pos].type != XD_END; pos++)
627 void *rdata = (char *)data + desc[pos].offset;
628 switch (desc[pos].type)
630 case XD_SPECIFIER_END:
632 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
640 case XD_OPAQUE_DATA_PTR:
645 EMACS_INT ptr = *(EMACS_INT *)rdata;
647 *(EMACS_INT *)rdata = ptr+delta;
652 Lisp_Object *pobj = (Lisp_Object *) rdata;
654 assert (desc[pos].data1 == 0);
656 if (POINTER_TYPE_P (XTYPE (*pobj))
657 && ! EQ (*pobj, Qnull_pointer))
658 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta);
662 case XD_LISP_OBJECT_ARRAY:
663 case XD_LO_RESET_NIL:
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, XTYPE (*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 /* These appear in a DEFVAR_LISP, which does a staticpro() */
896 t_console = Vterminal_console;
897 t_frame = Vterminal_frame;
898 t_device = Vterminal_device;
900 Vterminal_console = Qnil;
901 Vterminal_frame = Qnil;
902 Vterminal_device = Qnil;
904 pdump_hash = xnew_array_and_zero (pdump_entry_list_elmt *, PDUMP_HASHSIZE);
906 for (i=0; i<lrecord_type_count; i++)
908 pdump_object_table[i].first = 0;
909 pdump_object_table[i].align = 8;
910 pdump_object_table[i].count = 0;
911 pdump_alert_undump_object[i] = 0;
913 pdump_struct_table.count = 0;
914 pdump_struct_table.size = -1;
916 pdump_opaque_data_list.first = 0;
917 pdump_opaque_data_list.align = 8;
918 pdump_opaque_data_list.count = 0;
921 for (i=0; i<staticidx; i++)
922 pdump_register_object (*staticvec[i]);
923 for (i=0; i<pdump_wireidx; i++)
924 pdump_register_object (*pdump_wirevec[i]);
927 for (i=0; i<lrecord_type_count; i++)
928 if (pdump_alert_undump_object[i])
931 printf ("Undumpable types list :\n");
933 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]);
938 for (i=0; i<dumpstructidx; i++)
939 pdump_register_struct (*(void **)(dumpstructvec[i].data), dumpstructvec[i].desc, 1);
941 memcpy (hd.signature, DUMP_SIGNATURE, DUMP_SIGNATURE_LEN);
943 hd.reloc_address = 0;
944 hd.nb_staticpro = staticidx;
945 hd.nb_structdmp = dumpstructidx;
946 hd.nb_opaquedmp = dumpopaqueidx;
951 pdump_scan_by_alignment (pdump_allocate_offset);
952 pdump_qnil = pdump_get_entry (XRECORD_LHEADER (Qnil));
954 pdump_buf = xmalloc (max_size);
955 /* Avoid use of the `open' macro. We want the real function. */
957 pdump_fd = open (EMACS_PROGNAME ".dmp",
958 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
959 hd.stab_offset = (cur_offset + 3) & ~3;
961 write (pdump_fd, &hd, sizeof (hd));
962 lseek (pdump_fd, 256, SEEK_SET);
964 pdump_scan_by_alignment (pdump_dump_data);
966 lseek (pdump_fd, hd.stab_offset, SEEK_SET);
968 pdump_dump_staticvec ();
969 pdump_dump_structvec ();
970 pdump_dump_opaquevec ();
971 pdump_dump_itable ();
972 pdump_dump_rtables ();
980 Vterminal_console = t_console;
981 Vterminal_frame = t_frame;
982 Vterminal_device = t_device;
985 static int pdump_load_check (void)
987 return (!memcmp (((dump_header *)pdump_start)->signature, DUMP_SIGNATURE, DUMP_SIGNATURE_LEN)
988 && ((dump_header *)pdump_start)->id == dump_id);
991 static int pdump_load_finish (void)
998 pdump_end = pdump_start + pdump_length;
1000 #define PDUMP_READ(p, type) (p = (char*) (((type *) p) + 1), *((type *) p - 1))
1002 staticidx = ((dump_header *)(pdump_start))->nb_staticpro;
1003 delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address;
1004 p = pdump_start + ((dump_header *)pdump_start)->stab_offset;
1006 /* Put back the staticvec in place */
1007 memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *));
1008 p += staticidx*sizeof (Lisp_Object *);
1009 for (i=0; i<staticidx; i++)
1011 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
1012 if (POINTER_TYPE_P (XTYPE (obj)))
1013 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta);
1014 *staticvec[i] = obj;
1017 /* Put back the dumpstructs */
1018 for (i=0; i<((dump_header *)pdump_start)->nb_structdmp; i++)
1020 void **adr = PDUMP_READ (p, void **);
1021 *adr = (void *) (PDUMP_READ (p, char *) + delta);
1024 /* Put back the opaques */
1025 for (i=0; i<((dump_header *)pdump_start)->nb_opaquedmp; i++)
1027 struct pdump_dumpopaqueinfo di = PDUMP_READ (p, struct pdump_dumpopaqueinfo);
1028 memcpy (di.data, p, di.size);
1032 /* Put back the lrecord_implementations_table */
1033 /* The (void *) cast is there to make Ben happy. */
1034 memcpy ((void *) lrecord_implementations_table, p, lrecord_type_count*sizeof (lrecord_implementations_table[0]));
1035 p += lrecord_type_count*sizeof (lrecord_implementations_table[0]);
1037 /* Reinitialize lrecord_markers from lrecord_implementations_table */
1038 for (i=0; i < lrecord_type_count; i++)
1039 if (lrecord_implementations_table[i])
1040 lrecord_markers[i] = lrecord_implementations_table[i]->marker;
1042 /* Do the relocations */
1047 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
1050 for (i=0; i < rt.count; i++)
1052 char *adr = delta + *(char **)p;
1054 pdump_reloc_one (adr, delta, rt.desc);
1055 p += sizeof (char *);
1062 /* Put the pdump_wire variables in place */
1063 count = PDUMP_READ (p, EMACS_INT);
1065 for (i=0; i<count; i++)
1067 Lisp_Object *var = PDUMP_READ (p, Lisp_Object *);
1068 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
1070 if (POINTER_TYPE_P (XTYPE (obj)))
1071 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta);
1076 /* Final cleanups */
1077 /* reorganize hash tables */
1081 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
1084 if (rt.desc == hash_table_description)
1086 for (i=0; i < rt.count; i++)
1087 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object));
1090 p += sizeof (Lisp_Object) * rt.count;
1093 /* Put back noninteractive1 to its real value */
1094 noninteractive1 = noninteractive;
1100 static void pdump_file_unmap(void)
1104 static int pdump_file_get(const char *path)
1109 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 (hFile == INVALID_HANDLE_VALUE)
1119 pdump_length = GetFileSize (hFile, NULL);
1120 hMap = CreateFileMapping (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 (hMap == INVALID_HANDLE_VALUE)
1129 pdump_start = MapViewOfFile (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 static void pdump_resource_free (void)
1139 static int pdump_resource_get (void)
1141 HRSRC hRes; /* Handle to dump resource */
1142 HRSRC hResLoad; /* Handle to loaded dump resource */
1144 /* See Q126630 which describes how Windows NT and 95 trap writes to
1145 resource sections and duplicate the page to allow the write to proceed.
1146 It also describes how to make the resource section read/write (and hence
1147 private to each process). Doing this avoids the exceptions and related
1148 overhead, but causes the resource section to be private to each process
1149 that is running XEmacs. Since the resource section contains little
1150 other than the dumped data, which should be private to each process, we
1151 make the whole resource section read/write so we don't have to copy it. */
1153 hRes = FindResource (NULL, MAKEINTRESOURCE(101), "DUMP");
1157 /* Found it, use the data in the resource */
1158 hResLoad = LoadResource (NULL, hRes);
1159 if (hResLoad == NULL)
1162 pdump_start = LockResource (hResLoad);
1163 if (pdump_start == NULL)
1166 pdump_free = pdump_resource_free;
1167 pdump_length = SizeofResource (NULL, hRes);
1168 if (pdump_length <= sizeof(dump_header))
1177 #else /* !WINDOWSNT */
1179 static void *pdump_mallocadr;
1181 static void pdump_file_free(void)
1183 xfree (pdump_mallocadr);
1187 static void pdump_file_unmap(void)
1189 munmap (pdump_start, pdump_length);
1193 static int pdump_file_get(const char *path)
1195 int fd = open (path, O_RDONLY | OPEN_BINARY);
1199 pdump_length = lseek (fd, 0, SEEK_END);
1200 if (pdump_length < sizeof (dump_header))
1206 lseek (fd, 0, SEEK_SET);
1209 pdump_start = (char *) mmap (0, pdump_length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
1210 if (pdump_start != MAP_FAILED)
1212 pdump_free = pdump_file_unmap;
1218 pdump_mallocadr = xmalloc(pdump_length+255);
1219 pdump_free = pdump_file_free;
1220 pdump_start = (char *)((255 + (unsigned long)pdump_mallocadr) & ~255);
1221 read (pdump_fd, pdump_start, pdump_length);
1226 #endif /* !WINDOWSNT */
1229 static int pdump_file_try(char *exe_path)
1233 w = exe_path + strlen(exe_path);
1236 sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id);
1237 if (pdump_file_get (exe_path))
1239 if (pdump_load_check ())
1244 sprintf (w, "-%08x.dmp", dump_id);
1245 if (pdump_file_get (exe_path))
1247 if (pdump_load_check ())
1252 sprintf (w, ".dmp");
1253 if (pdump_file_get (exe_path))
1255 if (pdump_load_check ())
1262 while (w>exe_path && !IS_DIRECTORY_SEP (*w) && (*w != '-') && (*w != '.'));
1264 while (w>exe_path && !IS_DIRECTORY_SEP (*w));
1268 int pdump_load(const char *argv0)
1270 char exe_path[PATH_MAX];
1273 GetModuleFileName (NULL, exe_name, PATH_MAX);
1274 #else /* !WINDOWSNT */
1275 const char *dir, *p;
1280 /* XEmacs as a login shell, oh goody! */
1281 dir = getenv("SHELL");
1284 p = dir + strlen(dir);
1285 while (p != dir && !IS_ANY_SEP (p[-1])) p--;
1289 /* invocation-name includes a directory component -- presumably it
1290 is relative to cwd, not $PATH */
1291 strcpy (exe_path, dir);
1295 const char *path = getenv ("PATH");
1296 const char *name = p;
1300 while (*p && *p != SEPCHAR)
1309 memcpy (exe_path, path, p - path);
1310 w = exe_path + (p - path);
1312 if (!IS_DIRECTORY_SEP (w[-1]))
1318 /* ### #$%$#^$^@%$^#%@$ ! */
1323 if (!access (exe_path, X_OK))
1327 /* Oh well, let's have some kind of default */
1328 sprintf (exe_path, "./%s", name);
1334 #endif /* WINDOWSNT */
1336 if (pdump_file_try (exe_path))
1338 pdump_load_finish ();
1343 if (pdump_resource_get ())
1345 if (pdump_load_check ())
1347 pdump_load_finish ();