From cd2c70c8b5d4dcc62b968f5a9bedd3c9c8698e82 Mon Sep 17 00:00:00 2001 From: William Harold Newman Date: Wed, 2 Oct 2002 23:22:47 +0000 Subject: [PATCH] 0.7.8.12: added build id to .core files to try to discourage .core/sbcl mismatch adventures --- NEWS | 15 ++++++++++++--- make.sh | 4 ++++ package-data-list.lisp-expr | 1 + src/code/save.lisp | 17 +++++++++++++---- src/compiler/generic/genesis.lisp | 38 +++++++++++++++++++++++++++++++++++-- src/runtime/core.h | 7 +++++++ src/runtime/coreparse.c | 34 +++++++++++++++++++++++++++++++++ src/runtime/save.c | 20 +++++++++++++++---- version.lisp-expr | 2 +- 9 files changed, 124 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index e470949..5eab745 100644 --- a/NEWS +++ b/NEWS @@ -1298,14 +1298,23 @@ changes in sbcl-0.7.8 relative to sbcl-0.7.7: thing to do.) changes in sbcl-0.7.9 relative to sbcl-0.7.8: - * fixed bug: VALUES-LIST is no longer optimized away + * minor incompatible change: The runtime (the Unix executable named + "sbcl") is now much pickier about the .core files it will load. + Essentially it now requires .core files to descend from the same + build (not just the same sources or LISP-IMPLEMENTATION-VERSION) + as the runtime does. (The intent is to prevent the crashes which + can occur, and which can even be reported as mysterious failures, + when people patch the sources or change the build parameters + without changing LISP-IMPLEMENTATION-VERSION, then mix and match + sbcl and .core files.) + * fixed bug: VALUES-LIST is no longer optimized away. * fixed bug 142: The FFI conversion of C string values to Lisp string values no longer conses excessively. (thanks to Nathan Froyd porting Raymond Toy's fix to CMU CL) * improved MOP conformance in PCL (thanks to Nathan Froyd porting Gerd Moellman's work in CMU CL) - * fixed bug 202: the compiler failed on a function, which derived - type contradicted declared. + * fixed bug 202: The compiler no longer fails on functions whose + derived types contradict their declared type. planned incompatible changes in 0.7.x: * When the profiling interface settles down, maybe in 0.7.x, maybe diff --git a/make.sh b/make.sh index 6aa8f99..500f56f 100755 --- a/make.sh +++ b/make.sh @@ -65,6 +65,10 @@ echo //SBCL_XC_HOST=\"$SBCL_XC_HOST\" # and target machines. sh make-config.sh || exit 1 +# Make a unique ID for this build (to discourage people from +# mismatching sbcl and *.core files). +echo '"'`hostname -s`-`whoami`-`date +%F-%H-%M-%S`'"' > output/build-id.tmp + # The make-host-*.sh scripts are run on the cross-compilation host, # and the make-target-*.sh scripts are run on the target machine. In # ordinary compilation, we just do these phases consecutively on the diff --git a/package-data-list.lisp-expr b/package-data-list.lisp-expr index 5639584..20b0950 100644 --- a/package-data-list.lisp-expr +++ b/package-data-list.lisp-expr @@ -462,6 +462,7 @@ like *STACK-TOP-HINT* and unsupported stuff like *TRACED-FUN-LIST*." "SB!EXT" "SB!INT" "SB!KERNEL" "SB!SYS") :export ("*ASSEMBLER-ROUTINES*" "+BACKEND-FASL-FILE-IMPLEMENTATION+" + "BUILD-ID-CORE-ENTRY-TYPE-CODE" "*FASL-FILE-TYPE*" "CLOSE-FASL-OUTPUT" "DUMP-ASSEMBLER-ROUTINES" diff --git a/src/code/save.lisp b/src/code/save.lisp index cf3eeff..2356255 100644 --- a/src/code/save.lisp +++ b/src/code/save.lisp @@ -32,11 +32,20 @@ (root-structures ()) (environment-name "auxiliary")) #!+sb-doc - "Saves a CMU Common Lisp core image in the file of the specified name, - killing the current Lisp invocation in the process (unless it bails - out early because of some argument error or something). + "Save a \"core image\", i.e. enough information to restart a Lisp + process later in the same state, in the file of the specified name. - The following &KEY args are defined: + This implementation is not as polished and painless as you might like: + * It corrupts the current Lisp image enough that the current process + needs to be killed afterwards. + * There is absolutely no binary compatibility of core images between + different runtime support programs. Even runtimes built from the same + sources at different times are treated as incompatible for this purpose. + This isn't because we like it this way, but just because there don't + seem to be good quick fixes for either limitation and no one has been + sufficiently motivated to do lengthy fixes. + + The following &KEY arguments are defined: :TOPLEVEL The function to run when the created core file is resumed. The default function handles command line toplevel option diff --git a/src/compiler/generic/genesis.lisp b/src/compiler/generic/genesis.lisp index 4bff913..54c0730 100644 --- a/src/compiler/generic/genesis.lisp +++ b/src/compiler/generic/genesis.lisp @@ -47,13 +47,20 @@ ;;; way to do this in high level data like this (as opposed to e.g. in ;;; IP packets), and in fact the CMU CL version number never ended up ;;; being incremented past 0. A better approach might be to use a -;;; string which is set from CVS data. +;;; string which is set from CVS data. (Though now as of sbcl-0.7.8 or +;;; so, we have another problem that the core incompatibility +;;; detection mechanisms are on such a hair trigger -- with even +;;; different builds from the same sources being considered +;;; incompatible -- that any coarser-grained versioning mechanisms +;;; like this are largely irrelevant as long as the hair-triggering +;;; persists.) ;;; ;;; 0: inherited from CMU CL ;;; 1: rearranged static symbols for sbcl-0.6.8 ;;; 2: eliminated non-ANSI %DEFCONSTANT/%%DEFCONSTANT support, ;;; deleted a slot from DEBUG-SOURCE structure -(defconstant sbcl-core-version-integer 2) +;;; 3: added build ID to cores to discourage sbcl/.core mismatch +(defconstant sbcl-core-version-integer 3) (defun round-up (number size) #!+sb-doc @@ -2922,7 +2929,18 @@ initially undefined function references:~2%") (defvar *core-file*) (defvar *data-page*) +;;; magic numbers to identify entries in a core file +;;; +;;; (In case you were wondering: No, AFAIK there's no special magic about +;;; these which requires them to be in the 38xx range. They're just +;;; arbitrary words, tested not for being in a particular range but just +;;; for equality. However, if you ever need to look at a .core file and +;;; figure out what's going on, it's slightly convenient that they're +;;; all in an easily recognizable range, and displacing the range away from +;;; zero seems likely to reduce the chance that random garbage will be +;;; misinterpreted as a .core file.) (defconstant version-core-entry-type-code 3860) +(defconstant build-id-core-entry-type-code 3899) (defconstant new-directory-core-entry-type-code 3861) (defconstant initial-fun-core-entry-type-code 3863) (defconstant end-core-entry-type-code 3840) @@ -3017,6 +3035,22 @@ initially undefined function references:~2%") (write-word 3) (write-word sbcl-core-version-integer) + ;; Write the build ID. + (write-word build-id-core-entry-type-code) + (let ((build-id (with-open-file (s "output/build-id.tmp" + :direction :input) + (read s)))) + (declare (type simple-string build-id)) + (/show build-id (length build-id)) + ;; Write length of build ID record: BUILD-ID-CORE-ENTRY-TYPE-CODE + ;; word, this length word, and one word for each char of BUILD-ID. + (write-word (+ 2 (length build-id))) + (dovector (char build-id) + ;; (We write each character as a word in order to avoid + ;; having to think about word alignment issues in the + ;; sbcl-0.7.8 version of coreparse.c.) + (write-word (char-code char)))) + ;; Write the New Directory entry header. (write-word new-directory-core-entry-type-code) (write-word 17) ; length = (5 words/space) * 3 spaces + 2 for header. diff --git a/src/runtime/core.h b/src/runtime/core.h index 385d8a6..aa57ba9 100644 --- a/src/runtime/core.h +++ b/src/runtime/core.h @@ -32,4 +32,11 @@ struct ndir_entry { extern lispobj load_core_file(char *file); +/* arbitrary string identifying this build, embedded in .core files to + * prevent people mismatching a runtime built e.g. with :SB-SHOW + * against a .core built without :SB-SHOW (or against various grosser + * mismatches, e.g. a .core built with an old version of the code + * against a runtime with patches which add new C code) */ +extern unsigned char build_id[]; + #endif diff --git a/src/runtime/coreparse.c b/src/runtime/coreparse.c index b9bcddb..a00438c 100644 --- a/src/runtime/coreparse.c +++ b/src/runtime/coreparse.c @@ -34,6 +34,10 @@ #include "interr.h" #include "sbcl.h" +unsigned char build_id[] = +#include "../../output/build-id.tmp" +; + static void process_directory(int fd, u32 *ptr, int count) { @@ -172,6 +176,36 @@ load_core_file(char *file) } break; + case BUILD_ID_CORE_ENTRY_TYPE_CODE: + SHOW("BUILD_ID_CORE_ENTRY_TYPE_CODE case"); + { + int i; + + FSHOW((stderr, "build_id[]=\"%s\"\n", build_id)); + FSHOW((stderr, "remaining_len = %d\n", remaining_len)); + if (remaining_len != strlen(build_id)) + goto losing_build_id; + for (i = 0; i < remaining_len; ++i) { + FSHOW((stderr, "ptr[%d] = char = %d, expected=%d\n", + ptr[i], i, build_id[i])); + if (ptr[i] != build_id[i]) + goto losing_build_id; + } + break; + losing_build_id: + /* .core files are not binary-compatible between + * builds because we can't easily detect whether the + * sources were patched between the time the + * dumping-the-.core runtime was built and the time + * that the loading-the-.core runtime was built. + * + * (We could easily detect whether version.lisp-expr + * was changed, but people experimenting with patches + * don't necessarily update version.lisp-expr.) */ + + lose("can't load .core for different runtime, sorry"); + } + case NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE: SHOW("NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE case"); process_directory(fd, diff --git a/src/runtime/save.c b/src/runtime/save.c index 4fd98e7..da73349 100644 --- a/src/runtime/save.c +++ b/src/runtime/save.c @@ -102,8 +102,7 @@ save(char *filename, lispobj init_function) printf("done]\n"); fflush(stdout); - /* (Now we can actually start copying ourselves into the - * output file.) */ + /* (Now we can actually start copying ourselves into the output file.) */ printf("[saving current Lisp image into %s:\n", filename); fflush(stdout); @@ -114,9 +113,22 @@ save(char *filename, lispobj init_function) putw(3, file); putw(SBCL_CORE_VERSION_INTEGER, file); - putw(NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE, file); - putw((5*3)+2, file); + putw(BUILD_ID_CORE_ENTRY_TYPE_CODE, file); + putw(/* (We're writing the word count of the entry here, and the 2 + * term is one word for the leading BUILD_ID_CORE_ENTRY_TYPE_CODE + * word and one word where we store the count itself.) */ + 2 + strlen(build_id), + file); + { + char *p; + for (p = build_id; *p; ++p) + putw(*p, file); + } + putw(NEW_DIRECTORY_CORE_ENTRY_TYPE_CODE, file); + putw(/* (word count = 3 spaces described by 5 words each, plus the + * entry type code, plus this count itself) */ + (5*3)+2, file); output_space(file, READ_ONLY_CORE_SPACE_ID, (lispobj *)READ_ONLY_SPACE_START, diff --git a/version.lisp-expr b/version.lisp-expr index c2f7b61..d7e5823 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -18,4 +18,4 @@ ;;; internal versions off the main CVS branch, it gets hairier, e.g. ;;; "0.pre7.14.flaky4.13".) -"0.7.8.11" +"0.7.8.12" -- 1.7.10.4