Use defglobal less
[sbcl.git] / src / runtime / save.c
blobe7ebe93b1d9eb235b7023b5bcfe7ef2524ff864d
1 /*
2 * This software is part of the SBCL system. See the README file for
3 * more information.
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.
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 <sys/file.h>
21 #include "sbcl.h"
22 #if defined(LISP_FEATURE_WIN32) && defined(LISP_FEATURE_SB_THREAD)
23 #include "pthreads_win32.h"
24 #else
25 #include <signal.h>
26 #endif
27 #include "runtime.h"
28 #include "os.h"
29 #include "core.h"
30 #include "globals.h"
31 #include "save.h"
32 #include "dynbind.h"
33 #include "lispregs.h"
34 #include "validate.h"
35 #include "gc-internal.h"
36 #include "thread.h"
37 #include "arch.h"
38 #include "pseudo-atomic.h"
40 #include "genesis/static-symbols.h"
41 #include "genesis/symbol.h"
43 #ifdef LISP_FEATURE_SB_CORE_COMPRESSION
44 # include <zlib.h>
45 #endif
47 /* write_runtime_options uses a simple serialization scheme that
48 * consists of one word of magic, one word indicating whether options
49 * are actually saved, and one word per struct field. */
50 static void
51 write_runtime_options(FILE *file, struct runtime_options *options)
53 size_t optarray[RUNTIME_OPTIONS_WORDS];
55 memset(&optarray, 0, sizeof(optarray));
56 optarray[0] = RUNTIME_OPTIONS_MAGIC;
58 if (options != NULL) {
59 /* optarray[1] is a flag indicating that options are present */
60 optarray[1] = 1;
61 optarray[2] = options->dynamic_space_size;
62 optarray[3] = options->thread_control_stack_size;
65 if (RUNTIME_OPTIONS_WORDS !=
66 fwrite(optarray, sizeof(size_t), RUNTIME_OPTIONS_WORDS, file)) {
67 perror("Error writing runtime options to file");
71 static void
72 write_lispobj(lispobj obj, FILE *file)
74 if (1 != fwrite(&obj, sizeof(lispobj), 1, file)) {
75 perror("Error writing to file");
79 static void
80 write_bytes_to_file(FILE * file, char *addr, long bytes, int compression)
82 if (compression == COMPRESSION_LEVEL_NONE) {
83 while (bytes > 0) {
84 sword_t count = fwrite(addr, 1, bytes, file);
85 if (count > 0) {
86 bytes -= count;
87 addr += count;
89 else {
90 perror("error writing to core file");
91 lose("core file is incomplete or corrupt\n");
94 #ifdef LISP_FEATURE_SB_CORE_COMPRESSION
95 } else if ((compression >= -1) && (compression <= 9)) {
96 # define ZLIB_BUFFER_SIZE (1u<<16)
97 z_stream stream;
98 unsigned char* buf = successful_malloc(ZLIB_BUFFER_SIZE);
99 unsigned char * written, * end;
100 long total_written = 0;
101 int ret;
102 stream.zalloc = NULL;
103 stream.zfree = NULL;
104 stream.opaque = NULL;
105 stream.avail_in = bytes;
106 stream.next_in = (void*)addr;
107 ret = deflateInit(&stream, compression);
108 if (ret != Z_OK)
109 lose("deflateInit: %i\n", ret);
110 do {
111 stream.avail_out = ZLIB_BUFFER_SIZE;
112 stream.next_out = buf;
113 ret = deflate(&stream, Z_FINISH);
114 if (ret < 0) lose("zlib deflate error: %i... exiting\n", ret);
115 written = buf;
116 end = buf+ZLIB_BUFFER_SIZE-stream.avail_out;
117 total_written += end - written;
118 while (written < end) {
119 long count = fwrite(written, 1, end-written, file);
120 if (count > 0) {
121 written += count;
122 } else {
123 perror("error writing to core file");
124 lose("core file is incomplete or corrupt\n");
127 } while (stream.avail_out == 0);
128 deflateEnd(&stream);
129 free(buf);
130 printf("compressed %lu bytes into %lu at level %i\n",
131 bytes, total_written, compression);
132 # undef ZLIB_BUFFER_SIZE
133 #endif
134 } else {
135 #ifdef LISP_FEATURE_SB_CORE_COMPRESSION
136 lose("Unknown core compression level %i, exiting\n", compression);
137 #else
138 lose("zlib-compressed core support not built in this runtime\n");
139 #endif
142 if (fflush(file) != 0) {
143 perror("error writing to core file");
144 lose("core file is incomplete or corrupt\n");
149 static long
150 write_and_compress_bytes(FILE *file, char *addr, long bytes, os_vm_offset_t file_offset,
151 int compression)
153 long here, data;
155 bytes = (bytes+os_vm_page_size-1)&~(os_vm_page_size-1);
157 #ifdef LISP_FEATURE_WIN32
158 long count;
159 /* touch every single page in the space to force it to be mapped. */
160 for (count = 0; count < bytes; count += 0x1000) {
161 volatile int temp = addr[count];
163 #endif
165 fflush(file);
166 here = ftell(file);
167 fseek(file, 0, SEEK_END);
168 data = (ftell(file)+os_vm_page_size-1)&~(os_vm_page_size-1);
169 fseek(file, data, SEEK_SET);
170 write_bytes_to_file(file, addr, bytes, compression);
171 fseek(file, here, SEEK_SET);
172 return ((data - file_offset) / os_vm_page_size) - 1;
175 static long __attribute__((__unused__))
176 write_bytes(FILE *file, char *addr, long bytes, os_vm_offset_t file_offset)
178 return write_and_compress_bytes(file, addr, bytes, file_offset,
179 COMPRESSION_LEVEL_NONE);
182 extern struct lisp_startup_options lisp_startup_options;
184 static void
185 output_space(FILE *file, int id, lispobj *addr, lispobj *end,
186 os_vm_offset_t file_offset,
187 int core_compression_level)
189 size_t words, bytes, data, compressed_flag;
190 static char *names[] = {NULL, "dynamic", "static", "read-only",
191 "immobile", "immobile"};
193 compressed_flag
194 = ((core_compression_level != COMPRESSION_LEVEL_NONE)
195 ? DEFLATED_CORE_SPACE_ID_FLAG : 0);
197 write_lispobj(id | compressed_flag, file);
198 words = end - addr;
199 write_lispobj(words, file);
201 bytes = words * sizeof(lispobj);
203 if (!lisp_startup_options.noinform)
204 printf("writing %lu bytes from the %s space at %p\n",
205 (long unsigned)bytes, names[id], addr);
207 data = write_and_compress_bytes(file, (char *)addr, bytes, file_offset,
208 core_compression_level);
210 write_lispobj(data, file);
211 write_lispobj((uword_t)addr / os_vm_page_size, file);
212 write_lispobj((bytes + os_vm_page_size - 1) / os_vm_page_size, file);
215 FILE *
216 open_core_for_saving(char *filename)
218 /* Open the output file. We don't actually need the file yet, but
219 * the fopen() might fail for some reason, and we want to detect
220 * that and back out before we do anything irreversible. */
221 unlink(filename);
222 return fopen(filename, "wb");
225 #ifdef LISP_FEATURE_IMMOBILE_SPACE
226 extern void prepare_immobile_space_for_save();
227 # define N_SPACES_TO_SAVE 5
228 # ifdef LISP_FEATURE_IMMOBILE_CODE
229 lispobj code_component_order;
230 extern void defrag_immobile_space(lispobj,boolean);
231 # endif
232 #else
233 # define N_SPACES_TO_SAVE 3
234 #endif
235 boolean
236 save_to_filehandle(FILE *file, char *filename, lispobj init_function,
237 boolean make_executable,
238 boolean save_runtime_options,
239 int core_compression_level)
241 struct thread *th;
242 os_vm_offset_t core_start_pos;
243 boolean verbose = !lisp_startup_options.noinform;
245 #ifdef LISP_FEATURE_X86_64
246 untune_asm_routines_for_microarch();
247 #endif
249 /* Smash the enclosing state. (Once we do this, there's no good
250 * way to go back, which is a sufficient reason that this ends up
251 * being SAVE-LISP-AND-DIE instead of SAVE-LISP-AND-GO-ON). */
252 if (verbose) {
253 printf("[undoing binding stack and other enclosing state... ");
254 fflush(stdout);
256 for_each_thread(th) { /* XXX really? */
257 unbind_to_here((lispobj *)th->binding_stack_start,th);
258 SetSymbolValue(CURRENT_CATCH_BLOCK, 0,th);
259 SetSymbolValue(CURRENT_UNWIND_PROTECT_BLOCK, 0,th);
261 if (verbose) printf("done]\n");
262 #ifdef LISP_FEATURE_IMMOBILE_CODE
263 // It's better to wait to defrag until after the binding stack is undone,
264 // because we explicitly don't fixup code refs from stacks.
265 // i.e. if there *were* something on the binding stack that cared that code
266 // moved, it would be wrong. This way we can be sure we don't care.
267 if (code_component_order) {
268 // Assert that defrag will not move the init_function
269 gc_assert(!immobile_space_p(init_function));
270 if (verbose) {
271 printf("[defragmenting immobile space... ");
272 fflush(stdout);
274 defrag_immobile_space(code_component_order, verbose);
275 if (verbose) printf("done]\n");
277 #endif
279 /* (Now we can actually start copying ourselves into the output file.) */
281 if (verbose) {
282 printf("[saving current Lisp image into %s:\n", filename);
283 fflush(stdout);
286 core_start_pos = ftell(file);
287 write_lispobj(CORE_MAGIC, file);
289 write_lispobj(BUILD_ID_CORE_ENTRY_TYPE_CODE, file);
290 write_lispobj(/* (We're writing the word count of the entry here, and the 2
291 * term is one word for the leading BUILD_ID_CORE_ENTRY_TYPE_CODE
292 * word and one word where we store the count itself.) */
293 2 + strlen((const char *)build_id),
294 file);
296 unsigned char *p;
297 for (p = (unsigned char *)build_id; *p; ++p)
298 write_lispobj(*p, file);
301 write_lispobj(NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE, file);
302 write_lispobj(/* (word count = N spaces described by 5 words each, plus the
303 * entry type code, plus this count itself) */
304 (5*N_SPACES_TO_SAVE)+2, file);
305 output_space(file,
306 READ_ONLY_CORE_SPACE_ID,
307 (lispobj *)READ_ONLY_SPACE_START,
308 read_only_space_free_pointer,
309 core_start_pos,
310 core_compression_level);
311 output_space(file,
312 STATIC_CORE_SPACE_ID,
313 (lispobj *)STATIC_SPACE_START,
314 static_space_free_pointer,
315 core_start_pos,
316 core_compression_level);
317 #ifdef LISP_FEATURE_GENCGC
318 /* Flush the current_region, updating the tables. */
319 gc_alloc_update_all_page_tables(1);
320 update_dynamic_space_free_pointer();
321 #endif
322 #ifdef LISP_FEATURE_IMMOBILE_SPACE
323 prepare_immobile_space_for_save();
324 output_space(file,
325 IMMOBILE_FIXEDOBJ_CORE_SPACE_ID,
326 (lispobj *)IMMOBILE_SPACE_START,
327 immobile_fixedobj_free_pointer,
328 core_start_pos,
329 core_compression_level);
330 output_space(file,
331 IMMOBILE_VARYOBJ_CORE_SPACE_ID,
332 (lispobj *)IMMOBILE_VARYOBJ_SUBSPACE_START,
333 immobile_space_free_pointer,
334 core_start_pos,
335 core_compression_level);
336 #endif
337 output_space(file,
338 DYNAMIC_CORE_SPACE_ID,
339 current_dynamic_space,
340 (lispobj *)get_alloc_pointer(),
341 core_start_pos,
342 core_compression_level);
344 write_lispobj(INITIAL_FUN_CORE_ENTRY_TYPE_CODE, file);
345 write_lispobj(3, file);
346 write_lispobj(init_function, file);
348 #ifdef LISP_FEATURE_GENCGC
350 size_t true_size = sizeof last_free_page
351 + (last_free_page * sizeof(struct corefile_pte));
352 size_t rounded_size = CEILING(true_size, os_vm_page_size);
353 char* data = successful_malloc(rounded_size);
354 *(page_index_t*)data = last_free_page;
355 struct corefile_pte *ptes = (struct corefile_pte*)(data + sizeof(page_index_t));
356 page_index_t i;
357 for (i = 0; i < last_free_page; i++) {
358 /* Thanks to alignment requirements, the two low bits
359 * are always zero, so we can use them to store the
360 * allocation type -- region is always closed, so only
361 * the two low bits of allocation flags matter. */
362 uword_t word = page_scan_start_offset(i);
363 gc_assert((word & 0x03) == 0);
364 ptes[i].sso = word | (0x03 & page_table[i].allocated);
365 ptes[i].bytes_used = page_bytes_used(i);
367 write_lispobj(PAGE_TABLE_CORE_ENTRY_TYPE_CODE, file);
368 write_lispobj(4, file);
369 write_lispobj(rounded_size, file);
370 sword_t offset = write_bytes(file, data, rounded_size, core_start_pos);
371 write_lispobj(offset, file);
373 #endif
375 write_lispobj(END_CORE_ENTRY_TYPE_CODE, file);
377 /* Write a trailing header, ignored when parsing the core normally.
378 * This is used to locate the start of the core when the runtime is
379 * prepended to it. */
380 fseek(file, 0, SEEK_END);
382 /* If NULL runtime options are passed to write_runtime_options,
383 * command-line processing is performed as normal in the SBCL
384 * executable. Otherwise, the saved runtime options are used and
385 * all command-line arguments are available to Lisp in
386 * SB-EXT:*POSIX-ARGV*. */
387 write_runtime_options(file,
388 (save_runtime_options ? runtime_options : NULL));
390 if (1 != fwrite(&core_start_pos, sizeof(os_vm_offset_t), 1, file)) {
391 perror("Error writing core starting position to file");
392 fclose(file);
393 } else {
394 write_lispobj(CORE_MAGIC, file);
395 fclose(file);
398 #ifndef LISP_FEATURE_WIN32
399 if (make_executable)
400 chmod (filename, 0755);
401 #endif
403 if (verbose) printf("done]\n");
404 exit(0);
406 #undef N_SPACES_TO_SAVE
408 /* Check if the build_id for the current runtime is present in a
409 * buffer. */
411 check_runtime_build_id(void *buf, size_t size)
413 size_t idlen;
414 char *pos;
416 idlen = strlen((const char*)build_id) - 1;
417 while ((pos = memchr(buf, build_id[0], size)) != NULL) {
418 size -= (pos + 1) - (char *)buf;
419 buf = (pos + 1);
420 if (idlen <= size && memcmp(buf, build_id + 1, idlen) == 0)
421 return 1;
424 return 0;
427 /* Slurp the executable portion of the runtime into a malloced buffer
428 * and return it. Places the size in bytes of the runtime into
429 * 'size_out'. Returns NULL if the runtime cannot be loaded from
430 * 'runtime_path'. */
431 void *
432 load_runtime(char *runtime_path, size_t *size_out)
434 void *buf = NULL;
435 FILE *input = NULL;
436 size_t size, count;
437 os_vm_offset_t core_offset;
439 core_offset = search_for_embedded_core (runtime_path);
440 if ((input = fopen(runtime_path, "rb")) == NULL) {
441 fprintf(stderr, "Unable to open runtime: %s\n", runtime_path);
442 goto lose;
445 fseek(input, 0, SEEK_END);
446 size = (size_t) ftell(input);
447 fseek(input, 0, SEEK_SET);
449 if (core_offset != -1 && size > (size_t) core_offset)
450 size = core_offset;
452 buf = successful_malloc(size);
453 if ((count = fread(buf, 1, size, input)) != size) {
454 fprintf(stderr, "Premature EOF while reading runtime.\n");
455 goto lose;
458 if (!check_runtime_build_id(buf, size)) {
459 fprintf(stderr, "Failed to locate current build_id in runtime: %s\n",
460 runtime_path);
461 goto lose;
464 fclose(input);
465 *size_out = size;
466 return buf;
468 lose:
469 if (input != NULL)
470 fclose(input);
471 if (buf != NULL)
472 free(buf);
473 return NULL;
476 boolean
477 save_runtime_to_filehandle(FILE *output, void *runtime, size_t runtime_size,
478 int application_type)
480 size_t padding;
481 void *padbytes;
483 #ifdef LISP_FEATURE_WIN32
485 PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)runtime;
486 PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)((char *)dos_header +
487 dos_header->e_lfanew);
489 int sub_system;
490 switch (application_type) {
491 case 0:
492 sub_system = IMAGE_SUBSYSTEM_WINDOWS_CUI;
493 break;
494 case 1:
495 sub_system = IMAGE_SUBSYSTEM_WINDOWS_GUI;
496 break;
497 default:
498 fprintf(stderr, "Invalid application type %d\n", application_type);
499 return 0;
502 nt_header->OptionalHeader.Subsystem = sub_system;
504 #endif
506 if (runtime_size != fwrite(runtime, 1, runtime_size, output)) {
507 perror("Error saving runtime");
508 return 0;
511 padding = (os_vm_page_size - (runtime_size % os_vm_page_size)) & ~os_vm_page_size;
512 if (padding > 0) {
513 padbytes = successful_malloc(padding);
514 memset(padbytes, 0, padding);
515 if (padding != fwrite(padbytes, 1, padding, output)) {
516 perror("Error saving runtime");
517 free(padbytes);
518 return 0;
520 free(padbytes);
523 return 1;
526 FILE *
527 prepare_to_save(char *filename, boolean prepend_runtime, void **runtime_bytes,
528 size_t *runtime_size)
530 FILE *file;
531 char *runtime_path;
533 if (prepend_runtime) {
534 runtime_path = os_get_runtime_executable_path(0);
536 if (runtime_path == NULL && saved_runtime_path == NULL) {
537 fprintf(stderr, "Unable to get default runtime path.\n");
538 return NULL;
541 if (runtime_path == NULL)
542 *runtime_bytes = load_runtime(saved_runtime_path, runtime_size);
543 else {
544 *runtime_bytes = load_runtime(runtime_path, runtime_size);
545 free(runtime_path);
548 if (*runtime_bytes == NULL)
549 return 0;
552 file = open_core_for_saving(filename);
553 if (file == NULL) {
554 free(*runtime_bytes);
555 perror(filename);
556 return NULL;
559 return file;
562 #ifdef LISP_FEATURE_CHENEYGC
563 boolean
564 save(char *filename, lispobj init_function, boolean prepend_runtime,
565 boolean save_runtime_options, boolean compressed, int compression_level,
566 int application_type)
568 FILE *file;
569 void *runtime_bytes = NULL;
570 size_t runtime_size;
572 file = prepare_to_save(filename, prepend_runtime, &runtime_bytes, &runtime_size);
573 if (file == NULL)
574 return 1;
576 if (prepend_runtime)
577 save_runtime_to_filehandle(file, runtime_bytes, runtime_size, application_type);
579 return save_to_filehandle(file, filename, init_function, prepend_runtime,
580 save_runtime_options,
581 compressed ? compressed : COMPRESSION_LEVEL_NONE);
583 #endif