X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fsave.c;h=b3addc9f655c8c933666a22e10e9249ba6dd0ccc;hb=9ae34bc57917880d3fe6c2a1b5e322698b81ce96;hp=20d72d7a4ce1e5980ec998f951cbabc717fd8dc1;hpb=f82850855bab2cdaaf51c4e92d506b365866e65f;p=sbcl.git diff --git a/src/runtime/save.c b/src/runtime/save.c index 20d72d7..b3addc9 100644 --- a/src/runtime/save.c +++ b/src/runtime/save.c @@ -56,13 +56,18 @@ write_runtime_options(FILE *file, struct runtime_options *options) optarray[3] = options->thread_control_stack_size; } - fwrite(optarray, sizeof(size_t), RUNTIME_OPTIONS_WORDS, file); + if (RUNTIME_OPTIONS_WORDS != + fwrite(optarray, sizeof(size_t), RUNTIME_OPTIONS_WORDS, file)) { + perror("Error writing runtime options to file"); + } } static void write_lispobj(lispobj obj, FILE *file) { - fwrite(&obj, sizeof(lispobj), 1, file); + if (1 != fwrite(&obj, sizeof(lispobj), 1, file)) { + perror("Error writing to file"); + } } static long @@ -307,15 +312,22 @@ save_to_filehandle(FILE *file, char *filename, lispobj init_function, &~(os_vm_page_size-1); unsigned long *data = calloc(size, 1); if (data) { + unsigned long word; long offset; int i; for (i = 0; i < last_free_page; i++) { - data[i] = page_table[i].region_start_offset; + /* Thanks to alignment requirements, the two low bits + * are always zero, so we can use them to store the + * allocation type -- region is always closed, so only + * the two low bits of allocation flags matter. */ + word = page_table[i].region_start_offset; + gc_assert((word & 0x03) == 0); + data[i] = word | (0x03 & page_table[i].allocated); } write_lispobj(PAGE_TABLE_CORE_ENTRY_TYPE_CODE, file); write_lispobj(4, file); write_lispobj(size, file); - offset = write_bytes(file, (char *) data, size, core_start_pos); + offset = write_bytes(file, (char *)data, size, core_start_pos); write_lispobj(offset, file); } } @@ -354,9 +366,13 @@ save_to_filehandle(FILE *file, char *filename, lispobj init_function, write_runtime_options(file, (save_runtime_options ? runtime_options : NULL)); - fwrite(&core_start_pos, sizeof(os_vm_offset_t), 1, file); - write_lispobj(CORE_MAGIC, file); - fclose(file); + if (1 != fwrite(&core_start_pos, sizeof(os_vm_offset_t), 1, file)) { + perror("Error writing core starting position to file"); + fclose(file); + } else { + write_lispobj(CORE_MAGIC, file); + fclose(file); + } #ifndef LISP_FEATURE_WIN32 if (make_executable) @@ -367,6 +383,25 @@ save_to_filehandle(FILE *file, char *filename, lispobj init_function, exit(0); } +/* Check if the build_id for the current runtime is present in a + * buffer. */ +int +check_runtime_build_id(void *buf, size_t size) +{ + size_t idlen; + char *pos; + + idlen = strlen(build_id) - 1; + while ((pos = memchr(buf, build_id[0], size)) != NULL) { + size -= (pos + 1) - (char *)buf; + buf = (pos + 1); + if (idlen <= size && memcmp(buf, build_id + 1, idlen) == 0) + return 1; + } + + return 0; +} + /* Slurp the executable portion of the runtime into a malloced buffer * and return it. Places the size in bytes of the runtime into * 'size_out'. Returns NULL if the runtime cannot be loaded from @@ -398,6 +433,12 @@ load_runtime(char *runtime_path, size_t *size_out) goto lose; } + if (!check_runtime_build_id(buf, size)) { + fprintf(stderr, "Failed to locate current build_id in runtime: %s\n", + runtime_path); + goto lose; + } + fclose(input); *size_out = size; return buf; @@ -416,13 +457,20 @@ save_runtime_to_filehandle(FILE *output, void *runtime, size_t runtime_size) size_t padding; void *padbytes; - fwrite(runtime, 1, runtime_size, output); + if (runtime_size != fwrite(runtime, 1, runtime_size, output)) { + perror("Error saving runtime"); + return 0; + } padding = (os_vm_page_size - (runtime_size % os_vm_page_size)) & ~os_vm_page_size; if (padding > 0) { padbytes = successful_malloc(padding); memset(padbytes, 0, padding); - fwrite(padbytes, 1, padding, output); + if (padding != fwrite(padbytes, 1, padding, output)) { + perror("Error saving runtime"); + free(padbytes); + return 0; + } free(padbytes); } @@ -437,15 +485,19 @@ prepare_to_save(char *filename, boolean prepend_runtime, void **runtime_bytes, char *runtime_path; if (prepend_runtime) { - runtime_path = os_get_runtime_executable_path(); + runtime_path = os_get_runtime_executable_path(0); - if (runtime_path == NULL) { + if (runtime_path == NULL && saved_runtime_path == NULL) { fprintf(stderr, "Unable to get default runtime path.\n"); return NULL; } - *runtime_bytes = load_runtime(runtime_path, runtime_size); - free(runtime_path); + if (runtime_path == NULL) + *runtime_bytes = load_runtime(saved_runtime_path, runtime_size); + else { + *runtime_bytes = load_runtime(runtime_path, runtime_size); + free(runtime_path); + } if (*runtime_bytes == NULL) return 0;