1.0.21.24: saving runtime options in executables
[sbcl.git] / src / runtime / save.c
1 /*
2  * This software is part of the SBCL system. See the README file for
3  * more information.
4  *
5  * This software is derived from the CMU CL system, which was
6  * written at Carnegie Mellon University and released into the
7  * public domain. The software is in the public domain and is
8  * provided with absolutely no warranty. See the COPYING and CREDITS
9  * files for more information.
10  */
11
12 #ifndef LISP_FEATURE_WIN32
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #endif
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <signal.h>
20 #include <sys/file.h>
21
22 #include "sbcl.h"
23 #include "runtime.h"
24 #include "os.h"
25 #include "core.h"
26 #include "globals.h"
27 #include "save.h"
28 #include "dynbind.h"
29 #include "lispregs.h"
30 #include "validate.h"
31 #include "gc-internal.h"
32 #include "thread.h"
33
34 #include "genesis/static-symbols.h"
35 #include "genesis/symbol.h"
36
37 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
38 #include "genesis/lutex.h"
39 #endif
40
41 /* write_runtime_options uses a simple serialization scheme that
42  * consists of one word of magic, one word indicating whether options
43  * are actually saved, and one word per struct field. */
44 static void
45 write_runtime_options(FILE *file, struct runtime_options *options)
46 {
47     size_t optarray[RUNTIME_OPTIONS_WORDS];
48
49     memset(&optarray, 0, sizeof(optarray));
50     optarray[0] = RUNTIME_OPTIONS_MAGIC;
51
52     if (options != NULL) {
53         /* optarray[1] is a flag indicating that options are present */
54         optarray[1] = 1;
55         optarray[2] = options->dynamic_space_size;
56         optarray[3] = options->thread_control_stack_size;
57     }
58
59     fwrite(optarray, sizeof(size_t), RUNTIME_OPTIONS_WORDS, file);
60 }
61
62 static void
63 write_lispobj(lispobj obj, FILE *file)
64 {
65     fwrite(&obj, sizeof(lispobj), 1, file);
66 }
67
68 static long
69 write_bytes(FILE *file, char *addr, long bytes, os_vm_offset_t file_offset)
70 {
71     long count, here, data;
72
73     bytes = (bytes+os_vm_page_size-1)&~(os_vm_page_size-1);
74
75 #ifdef LISP_FEATURE_WIN32
76     /* touch every single page in the space to force it to be mapped. */
77     for (count = 0; count < bytes; count += 0x1000) {
78         volatile int temp = addr[count];
79     }
80 #endif
81
82     fflush(file);
83     here = ftell(file);
84     fseek(file, 0, SEEK_END);
85     data = (ftell(file)+os_vm_page_size-1)&~(os_vm_page_size-1);
86     fseek(file, data, SEEK_SET);
87
88     while (bytes > 0) {
89         count = fwrite(addr, 1, bytes, file);
90         if (count > 0) {
91             bytes -= count;
92             addr += count;
93         }
94         else {
95             perror("error writing to save file");
96             bytes = 0;
97         }
98     }
99     fflush(file);
100     fseek(file, here, SEEK_SET);
101     return ((data - file_offset) / os_vm_page_size) - 1;
102 }
103
104 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
105 /* saving lutexes in the core */
106 static void **lutex_addresses;
107 static long n_lutexes = 0;
108 static long max_lutexes = 0;
109
110 static long
111 default_scan_action(lispobj *obj)
112 {
113     return (sizetab[widetag_of(*obj)])(obj);
114 }
115
116 static long
117 lutex_scan_action(lispobj *obj)
118 {
119     /* note the address of the lutex */
120     if(n_lutexes >= max_lutexes) {
121         max_lutexes *= 2;
122         lutex_addresses = realloc(lutex_addresses, max_lutexes * sizeof(void *));
123         gc_assert(lutex_addresses);
124     }
125
126     lutex_addresses[n_lutexes++] = obj;
127
128     return (*sizetab[widetag_of(*obj)])(obj);
129 }
130
131 typedef long (*scan_table[256])(lispobj *obj);
132
133 static void
134 scan_objects(lispobj *start, long n_words, scan_table table)
135 {
136     lispobj *end = start + n_words;
137     lispobj *object_ptr;
138     long n_words_scanned;
139     for (object_ptr = start;
140          object_ptr < end;
141          object_ptr += n_words_scanned) {
142         lispobj obj = *object_ptr;
143
144         n_words_scanned = (table[widetag_of(obj)])(object_ptr);
145     }
146 }
147
148 static void
149 scan_for_lutexes(lispobj *addr, long n_words)
150 {
151     static int initialized = 0;
152     static scan_table lutex_scan_table;
153
154     if (!initialized) {
155         int i;
156
157         /* allocate a little space to get started */
158         lutex_addresses = malloc(16*sizeof(void *));
159         gc_assert(lutex_addresses);
160         max_lutexes = 16;
161
162         /* initialize the mapping table */
163         for(i = 0; i < ((sizeof lutex_scan_table)/(sizeof lutex_scan_table[0])); ++i) {
164             lutex_scan_table[i] = default_scan_action;
165         }
166
167         lutex_scan_table[LUTEX_WIDETAG] = lutex_scan_action;
168
169         initialized = 1;
170     }
171
172     /* do the scan */
173     scan_objects(addr, n_words, lutex_scan_table);
174 }
175 #endif
176
177 static void
178 output_space(FILE *file, int id, lispobj *addr, lispobj *end, os_vm_offset_t file_offset)
179 {
180     size_t words, bytes, data;
181     static char *names[] = {NULL, "dynamic", "static", "read-only"};
182
183     write_lispobj(id, file);
184     words = end - addr;
185     write_lispobj(words, file);
186
187     bytes = words * sizeof(lispobj);
188
189 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
190     printf("scanning space for lutexes...\n");
191     scan_for_lutexes((char *)addr, words);
192 #endif
193
194     printf("writing %lu bytes from the %s space at 0x%08lx\n",
195            (unsigned long)bytes, names[id], (unsigned long)addr);
196
197     data = write_bytes(file, (char *)addr, bytes, file_offset);
198
199     write_lispobj(data, file);
200     write_lispobj((long)addr / os_vm_page_size, file);
201     write_lispobj((bytes + os_vm_page_size - 1) / os_vm_page_size, file);
202 }
203
204 FILE *
205 open_core_for_saving(char *filename)
206 {
207     /* Open the output file. We don't actually need the file yet, but
208      * the fopen() might fail for some reason, and we want to detect
209      * that and back out before we do anything irreversible. */
210     unlink(filename);
211     return fopen(filename, "wb");
212 }
213
214 boolean
215 save_to_filehandle(FILE *file, char *filename, lispobj init_function,
216                    boolean make_executable,
217                    boolean save_runtime_options)
218 {
219     struct thread *th;
220     os_vm_offset_t core_start_pos;
221
222     /* Smash the enclosing state. (Once we do this, there's no good
223      * way to go back, which is a sufficient reason that this ends up
224      * being SAVE-LISP-AND-DIE instead of SAVE-LISP-AND-GO-ON). */
225     printf("[undoing binding stack and other enclosing state... ");
226     fflush(stdout);
227     for_each_thread(th) {       /* XXX really? */
228         unbind_to_here((lispobj *)th->binding_stack_start,th);
229         SetSymbolValue(CURRENT_CATCH_BLOCK, 0,th);
230         SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0,th);
231     }
232     printf("done]\n");
233     fflush(stdout);
234
235     /* (Now we can actually start copying ourselves into the output file.) */
236
237     printf("[saving current Lisp image into %s:\n", filename);
238     fflush(stdout);
239
240     core_start_pos = ftell(file);
241     write_lispobj(CORE_MAGIC, file);
242
243     write_lispobj(VERSION_CORE_ENTRY_TYPE_CODE, file);
244     write_lispobj(3, file);
245     write_lispobj(SBCL_CORE_VERSION_INTEGER, file);
246
247     write_lispobj(BUILD_ID_CORE_ENTRY_TYPE_CODE, file);
248     write_lispobj(/* (We're writing the word count of the entry here, and the 2
249           * term is one word for the leading BUILD_ID_CORE_ENTRY_TYPE_CODE
250           * word and one word where we store the count itself.) */
251          2 + strlen((const char *)build_id),
252          file);
253     {
254         unsigned char *p;
255         for (p = (unsigned char *)build_id; *p; ++p)
256             write_lispobj(*p, file);
257     }
258
259     write_lispobj(NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE, file);
260     write_lispobj(/* (word count = 3 spaces described by 5 words each, plus the
261           * entry type code, plus this count itself) */
262          (5*3)+2, file);
263     output_space(file,
264                  READ_ONLY_CORE_SPACE_ID,
265                  (lispobj *)READ_ONLY_SPACE_START,
266                  (lispobj *)SymbolValue(READ_ONLY_SPACE_FREE_POINTER,0),
267                  core_start_pos);
268     output_space(file,
269                  STATIC_CORE_SPACE_ID,
270                  (lispobj *)STATIC_SPACE_START,
271                  (lispobj *)SymbolValue(STATIC_SPACE_FREE_POINTER,0),
272                  core_start_pos);
273 #ifdef LISP_FEATURE_GENCGC
274     /* Flush the current_region, updating the tables. */
275     gc_alloc_update_all_page_tables();
276     update_dynamic_space_free_pointer();
277 #endif
278 #ifdef reg_ALLOC
279 #ifdef LISP_FEATURE_GENCGC
280     output_space(file,
281                  DYNAMIC_CORE_SPACE_ID,
282                  (lispobj *)DYNAMIC_SPACE_START,
283                  dynamic_space_free_pointer,
284                  core_start_pos);
285 #else
286     output_space(file,
287                  DYNAMIC_CORE_SPACE_ID,
288                  (lispobj *)current_dynamic_space,
289                  dynamic_space_free_pointer,
290                  core_start_pos);
291 #endif
292 #else
293     output_space(file,
294                  DYNAMIC_CORE_SPACE_ID,
295                  (lispobj *)DYNAMIC_SPACE_START,
296                  (lispobj *)SymbolValue(ALLOCATION_POINTER,0),
297                  core_start_pos);
298 #endif
299
300     write_lispobj(INITIAL_FUN_CORE_ENTRY_TYPE_CODE, file);
301     write_lispobj(3, file);
302     write_lispobj(init_function, file);
303
304 #ifdef LISP_FEATURE_GENCGC
305     {
306         size_t size = (last_free_page*sizeof(long)+os_vm_page_size-1)
307             &~(os_vm_page_size-1);
308         unsigned long *data = calloc(size, 1);
309         if (data) {
310             long offset;
311             int i;
312             for (i = 0; i < last_free_page; i++) {
313                 data[i] = page_table[i].region_start_offset;
314             }
315             write_lispobj(PAGE_TABLE_CORE_ENTRY_TYPE_CODE, file);
316             write_lispobj(4, file);
317             write_lispobj(size, file);
318             offset = write_bytes(file, (char *) data, size, core_start_pos);
319             write_lispobj(offset, file);
320         }
321     }
322 #endif
323
324 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_LUTEX)
325     if(n_lutexes > 0) {
326         long offset;
327         printf("writing %ld lutexes to the core...\n", n_lutexes);
328         write_lispobj(LUTEX_TABLE_CORE_ENTRY_TYPE_CODE, file);
329         /* word count of the entry */
330         write_lispobj(4, file);
331         /* indicate how many lutexes we saved */
332         write_lispobj(n_lutexes, file);
333         /* save the lutexes */
334         offset = write_bytes(file, (char *) lutex_addresses,
335                              n_lutexes * sizeof(*lutex_addresses),
336                              core_start_pos);
337
338         write_lispobj(offset, file);
339     }
340 #endif
341
342     write_lispobj(END_CORE_ENTRY_TYPE_CODE, file);
343
344     /* Write a trailing header, ignored when parsing the core normally.
345      * This is used to locate the start of the core when the runtime is
346      * prepended to it. */
347     fseek(file, 0, SEEK_END);
348
349     /* If NULL runtime options are passed to write_runtime_options,
350      * command-line processing is performed as normal in the SBCL
351      * executable. Otherwise, the saved runtime options are used and
352      * all command-line arguments are available to Lisp in
353      * SB-EXT:*POSIX-ARGV*. */
354     write_runtime_options(file,
355                           (save_runtime_options ? runtime_options : NULL));
356
357     fwrite(&core_start_pos, sizeof(os_vm_offset_t), 1, file);
358     write_lispobj(CORE_MAGIC, file);
359     fclose(file);
360
361 #ifndef LISP_FEATURE_WIN32
362     if (make_executable)
363         chmod (filename, 0755);
364 #endif
365
366     printf("done]\n");
367     exit(0);
368 }
369
370 /* Slurp the executable portion of the runtime into a malloced buffer
371  * and return it.  Places the size in bytes of the runtime into
372  * 'size_out'.  Returns NULL if the runtime cannot be loaded from
373  * 'runtime_path'. */
374 void *
375 load_runtime(char *runtime_path, size_t *size_out)
376 {
377     void *buf = NULL;
378     FILE *input = NULL;
379     size_t size, count;
380     os_vm_offset_t core_offset;
381
382     core_offset = search_for_embedded_core (runtime_path);
383     if ((input = fopen(runtime_path, "rb")) == NULL) {
384         fprintf(stderr, "Unable to open runtime: %s\n", runtime_path);
385         goto lose;
386     }
387
388     fseek(input, 0, SEEK_END);
389     size = (size_t) ftell(input);
390     fseek(input, 0, SEEK_SET);
391
392     if (core_offset != -1 && size > core_offset)
393         size = core_offset;
394
395     buf = successful_malloc(size);
396     if ((count = fread(buf, 1, size, input)) != size) {
397         fprintf(stderr, "Premature EOF while reading runtime.\n");
398         goto lose;
399     }
400
401     fclose(input);
402     *size_out = size;
403     return buf;
404
405 lose:
406     if (input != NULL)
407         fclose(input);
408     if (buf != NULL)
409         free(buf);
410     return NULL;
411 }
412
413 boolean
414 save_runtime_to_filehandle(FILE *output, void *runtime, size_t runtime_size)
415 {
416     size_t padding;
417     void *padbytes;
418
419     fwrite(runtime, 1, runtime_size, output);
420
421     padding = (os_vm_page_size - (runtime_size % os_vm_page_size)) & ~os_vm_page_size;
422     if (padding > 0) {
423         padbytes = successful_malloc(padding);
424         memset(padbytes, 0, padding);
425         fwrite(padbytes, 1, padding, output);
426         free(padbytes);
427     }
428
429     return 1;
430 }
431
432 FILE *
433 prepare_to_save(char *filename, boolean prepend_runtime, void **runtime_bytes,
434                 size_t *runtime_size)
435 {
436     FILE *file;
437     char *runtime_path;
438
439     if (prepend_runtime) {
440         runtime_path = os_get_runtime_executable_path();
441
442         if (runtime_path == NULL) {
443             fprintf(stderr, "Unable to get default runtime path.\n");
444             return NULL;
445         }
446
447         *runtime_bytes = load_runtime(runtime_path, runtime_size);
448         free(runtime_path);
449
450         if (*runtime_bytes == NULL)
451             return 0;
452     }
453
454     file = open_core_for_saving(filename);
455     if (file == NULL) {
456         free(*runtime_bytes);
457         perror(filename);
458         return NULL;
459     }
460
461     return file;
462 }
463
464 boolean
465 save(char *filename, lispobj init_function, boolean prepend_runtime,
466      boolean save_runtime_options)
467 {
468     FILE *file;
469     void *runtime_bytes = NULL;
470     size_t runtime_size;
471
472     file = prepare_to_save(filename, prepend_runtime, &runtime_bytes, &runtime_size);
473     if (file == NULL)
474         return 1;
475
476     if (prepend_runtime)
477         save_runtime_to_filehandle(file, runtime_bytes, runtime_size);
478
479     return save_to_filehandle(file, filename, init_function, prepend_runtime,
480                               save_runtime_options);
481 }