Add original .xcf logo images
[sxemacs] / src / dumper.c
1 /* Portable data dumper for SXEmacs.
2    Copyright (C) 1999-2000 Olivier Galibert
3    Copyright (C) 2001 Martin Buchholz
4
5 This file is part of SXEmacs
6
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
19
20
21 /* Synched up with: Not in FSF. */
22
23 #include <config.h>
24 #include "lisp.h"
25
26 #include "specifier.h"
27 #include "elhash.h"
28 #include "sysfile.h"
29 #include "ui/console-stream.h"
30 #include "dumper.h"
31 #include "sysdep.h"
32
33 #ifdef HAVE_MMAP
34 #include <sys/mman.h>
35 #endif
36
37 /* For PATH_EXEC */
38 #include <sxe-paths.h>
39
40 #ifndef SEPCHAR
41 #define SEPCHAR ':'
42 #endif
43
44 typedef struct {
45         void *varaddress;
46         size_t size;
47 } pdump_opaque;
48
49 typedef struct {
50         Dynarr_declare(pdump_opaque);
51 } pdump_opaque_dynarr;
52
53 typedef struct {
54         void **ptraddress;
55         const struct struct_description *desc;
56 } pdump_root_struct_ptr;
57
58 typedef struct {
59         Dynarr_declare(pdump_root_struct_ptr);
60 } pdump_root_struct_ptr_dynarr;
61
62 typedef struct {
63         Lisp_Object *address;
64         Lisp_Object value;
65 } pdump_static_Lisp_Object;
66
67 typedef struct {
68         char **address;         /* char * for ease of doing relocation */
69         char *value;
70 } pdump_static_pointer;
71
72 static pdump_opaque_dynarr *pdump_opaques;
73 static pdump_root_struct_ptr_dynarr *pdump_root_struct_ptrs;
74 static Lisp_Object_ptr_dynarr *pdump_root_objects;
75 static Lisp_Object_ptr_dynarr *pdump_weak_object_chains;
76
77 /* Mark SIZE bytes at non-heap address VARADDRESS for dumping as is,
78    without any bit-twiddling. */
79 void dump_add_opaque(void *varaddress, size_t size)
80 {
81         pdump_opaque info;
82         info.varaddress = varaddress;
83         info.size = size;
84         if (pdump_opaques == NULL)
85                 pdump_opaques = Dynarr_new(pdump_opaque);
86         Dynarr_add(pdump_opaques, info);
87 }
88
89 /* Mark the struct described by DESC and pointed to by the pointer at
90    non-heap address VARADDRESS for dumping.
91    All the objects reachable from this pointer will also be dumped. */
92 void
93 dump_add_root_struct_ptr(void *ptraddress,
94                          const struct struct_description *desc)
95 {
96         pdump_root_struct_ptr info;
97         info.ptraddress = (void **)ptraddress;
98         info.desc = desc;
99         if (pdump_root_struct_ptrs == NULL)
100                 pdump_root_struct_ptrs = Dynarr_new(pdump_root_struct_ptr);
101         Dynarr_add(pdump_root_struct_ptrs, info);
102 }
103
104 /* Mark the Lisp_Object at non-heap address VARADDRESS for dumping.
105    All the objects reachable from this var will also be dumped. */
106 void dump_add_root_object(Lisp_Object * varaddress)
107 {
108         if (pdump_root_objects == NULL)
109                 pdump_root_objects =
110                     Dynarr_new2(Lisp_Object_ptr_dynarr, Lisp_Object *);
111         Dynarr_add(pdump_root_objects, varaddress);
112 }
113
114 /* Mark the list pointed to by the Lisp_Object at VARADDRESS for dumping. */
115 void dump_add_weak_object_chain(Lisp_Object * varaddress)
116 {
117         if (pdump_weak_object_chains == NULL)
118                 pdump_weak_object_chains =
119                     Dynarr_new2(Lisp_Object_ptr_dynarr, Lisp_Object *);
120         Dynarr_add(pdump_weak_object_chains, varaddress);
121 }
122 \f
123 inline static void pdump_align_stream(FILE * stream, size_t alignment)
124 {
125         long offset = ftell(stream);
126         long adjustment = ALIGN_SIZE(offset, alignment) - offset;
127         if (adjustment)
128                 fseek(stream, adjustment, SEEK_CUR);
129 }
130
131 #define PDUMP_ALIGN_OUTPUT(type) pdump_align_stream (pdump_out, ALIGNOF (type))
132
133 #define PDUMP_WRITE(type, object) \
134 fwrite (&object, sizeof (object), 1, pdump_out);
135
136 #define PDUMP_WRITE_ALIGNED(type, object) do {  \
137   PDUMP_ALIGN_OUTPUT (type);                    \
138   PDUMP_WRITE (type, object);                   \
139 } while (0)
140
141 #define PDUMP_READ(ptr, type) \
142 (((type *) (ptr = (char*) (((type *) ptr) + 1)))[-1])
143
144 #define PDUMP_READ_ALIGNED(ptr, type) \
145 ((ptr = (char *) ALIGN_PTR (ptr, ALIGNOF (type))), PDUMP_READ (ptr, type))
146 \f
147 typedef struct {
148         const struct lrecord_description *desc;
149         int count;
150 } pdump_reloc_table;
151
152 static char *pdump_rt_list = 0;
153
154 void pdump_objects_unmark(void)
155 {
156         int i;
157         char *p = pdump_rt_list;
158         if (p)
159                 for (;;) {
160                         pdump_reloc_table *rt = (pdump_reloc_table *) p;
161                         p += sizeof(pdump_reloc_table);
162                         if (rt->desc) {
163                                 for (i = 0; i < rt->count; i++) {
164                                         struct lrecord_header *lh =
165                                             *(struct lrecord_header **)p;
166                                         if (!C_READONLY_RECORD_HEADER_P(lh))
167                                                 UNMARK_RECORD_HEADER(lh);
168                                         p += sizeof(EMACS_INT);
169                                 }
170                         } else
171                                 break;
172                 }
173 }
174
175 /* The structure of the file
176  0              - header
177                 - dumped objects
178  stab_offset    - nb_root_struct_ptrs*pair(void *, adr)
179                   for pointers to structures
180                 - nb_opaques*pair(void *, size) for raw bits to restore
181                 - relocation table
182                 - root lisp object address/value couples with the count
183                   preceding the list
184  */
185
186 #define PDUMP_SIGNATURE "SXEmacsDP"
187 #define PDUMP_SIGNATURE_LEN (sizeof (PDUMP_SIGNATURE) - 1)
188
189 typedef struct {
190         char signature[PDUMP_SIGNATURE_LEN];
191         unsigned int id;
192         EMACS_UINT stab_offset;
193         EMACS_UINT reloc_address;
194         int nb_root_struct_ptrs;
195         int nb_opaques;
196 } pdump_header;
197
198 char *pdump_start;
199 char *pdump_end;
200 static off_t pdump_length;
201
202
203 static void (*pdump_free) (void);
204
205 static unsigned char pdump_align_table[] = {
206         64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
207         16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
208         32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
209         16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1
210 };
211
212 static inline unsigned int pdump_size_to_align(size_t size)
213 {
214         return pdump_align_table[size % countof(pdump_align_table)];
215 }
216
217 typedef struct pdump_entry_list_elt {
218         struct pdump_entry_list_elt *next;
219         const void *obj;
220         size_t size;
221         int count;
222         EMACS_INT save_offset;
223 } pdump_entry_list_elt;
224
225 typedef struct {
226         pdump_entry_list_elt *first;
227         int align;
228         int count;
229 } pdump_entry_list;
230
231 typedef struct pdump_struct_list_elt {
232         pdump_entry_list list;
233         const struct struct_description *sdesc;
234 } pdump_struct_list_elt;
235
236 typedef struct {
237         pdump_struct_list_elt *list;
238         int count;
239         int size;
240 } pdump_struct_list;
241
242 static pdump_entry_list *pdump_object_table;
243 static pdump_entry_list pdump_opaque_data_list;
244 static pdump_struct_list pdump_struct_table;
245
246 static int *pdump_alert_undump_object;
247