From: Daniel Colascione Date: Mon, 19 Feb 2018 16:27:39 +0000 (-0800) Subject: Verify hashes of lisp structures during compilation X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=11976b69233578aa719ffef69612c037cfe9bee0;p=emacs.git Verify hashes of lisp structures during compilation --- diff --git a/.gitignore b/.gitignore index ce97ad51a78..fa7e3ff5dee 100644 --- a/.gitignore +++ b/.gitignore @@ -186,6 +186,7 @@ src/emacs-[0-9]* src/temacs src/temacs.in src/fingerprint.c +src/dmpstruct.h src/*.pdmp # Character-set info. diff --git a/lib-src/make-fingerprint.c b/lib-src/make-fingerprint.c index dd2f0935d43..2ea839d78e4 100644 --- a/lib-src/make-fingerprint.c +++ b/lib-src/make-fingerprint.c @@ -32,6 +32,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #ifdef WINDOWSNT /* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this @@ -43,10 +44,26 @@ along with GNU Emacs. If not, see . */ int main (int argc, char **argv) { + int c; + bool raw = false; + while (0 <= (c = getopt (argc, argv, "rh"))) + { + switch (c) + { + case 'r': + raw = true; + break; + case 'h': + printf ("make-fingerprint [-r] FILES...: compute a hash\n"); + default: + return 1; + } + } + struct sha256_ctx ctx; sha256_init_ctx (&ctx); - for (int i = 1; i < argc; ++i) + for (int i = optind; i < argc; ++i) { FILE *f = fopen (argv[i], "r" FOPEN_BINARY); if (!f) @@ -73,12 +90,21 @@ main (int argc, char **argv) uint8_t digest[32]; sha256_finish_ctx (&ctx, digest); - printf ("#include \"fingerprint.h\"\n"); - printf ("\n"); - printf ("const uint8_t fingerprint[32] = { "); - for (int i = 0; i < 32; ++i) - printf ("%s0x%02X", i ? ", " : "", digest[i]); - printf (" };\n"); + + if (raw) + { + for (int i = 0; i < 32; ++i) + printf ("%02X", digest[i]); + } + else + { + printf ("#include \"fingerprint.h\"\n"); + printf ("\n"); + printf ("const uint8_t fingerprint[32] = { "); + for (int i = 0; i < 32; ++i) + printf ("%s0x%02X", i ? ", " : "", digest[i]); + printf (" };\n"); + } return EXIT_SUCCESS; } diff --git a/src/Makefile.in b/src/Makefile.in index 32f9cdf1f8f..4a0f5d5c968 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -410,6 +410,12 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ) obj = $(base_obj) $(NS_OBJC_OBJ) +dmpstruct_headers=lisp.h buffer.h intervals.h charset.h +pdumper.o: dmpstruct.h +dmpstruct.h: dmpstruct.awk +dmpstruct.h: $(libsrc)/make-fingerprint$(EXEEXT) $(dmpstruct_headers) + POSIXLY_CORRECT=1 awk -f dmpstruct.awk $(dmpstruct_headers) > $@ + ## Object files used on some machine or other. ## These go in the DOC file on all machines in case they are needed. ## Some of them have no DOC entries, but it does no harm to have them @@ -663,7 +669,7 @@ ns-app: emacs$(EXEEXT) mostlyclean: rm -f temacs$(EXEEXT) core *.core \#* *.o - rm -f temacs.in$(EXEEXT) fingerprint.c + rm -f temacs.in$(EXEEXT) fingerprint.c dmpstruct.h rm -f emacs.pdmp rm -f ../etc/DOC rm -f bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp) diff --git a/src/dmpstruct.awk b/src/dmpstruct.awk new file mode 100755 index 00000000000..608c26fcc5c --- /dev/null +++ b/src/dmpstruct.awk @@ -0,0 +1,28 @@ +BEGIN { + print "/* Generated by dmpstruct.awk */" + print "#ifndef EMACS_DMPSTRUCT_H" + print "#define EMACS_DMPSTRUCT_H" + struct_name = "" + tmpfile = "dmpstruct.tmp" +} +# Match a type followed by optional syntactic whitespace +/^(enum|struct|union) [a-zA-Z0-9_]+([\t ]|\/\*.*\*\/)*$/ { + struct_name = $2 + close (tmpfile) +} +/^(enum|struct|union) [a-zA-Z0-9_]+([\t ]|\/\*.*\*\/)*$/, /^(| )};$/ { + print $0 > tmpfile +} +/^(| )};$/ { + if (struct_name != "") { + fflush (tmpfile) + cmd = "../lib-src/make-fingerprint -r " tmpfile + cmd | getline hash + close (cmd) + printf "#define HASH_%s_%.10s\n", struct_name, hash + struct_name = "" + } +} +END { + print "#endif /* EMACS_DMPSTRUCT_H */" +} diff --git a/src/pdumper.c b/src/pdumper.c index a05b2c47ce1..dfcf33e3914 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -26,6 +26,7 @@ #include "pdumper.h" #include "window.h" +#include "dmpstruct.h" /* TODO: @@ -47,13 +48,19 @@ - Compressed dump support. - - Automate detection of struct layout changes. - */ - #ifdef HAVE_PDUMPER +/* CHECK_STRUCTS being true makes the build break if we notice + changes to the source defining certain Lisp structures we dump. If + you change one of these structures, check that the pdumper code is + still valid and update the hash from the dmpstruct.h generated by + your new code. */ +#ifndef CHECK_STRUCTS +# define CHECK_STRUCTS 1 +#endif + #ifdef __GNUC__ # pragma GCC diagnostic error "-Wconversion" # pragma GCC diagnostic error "-Wshadow" @@ -1901,6 +1908,9 @@ dump_field_emacs_ptr (struct dump_context *ctx, static dump_off dump_cons (struct dump_context *ctx, const struct Lisp_Cons *cons) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Cons_F25EE3E42E) +# error "Lisp_Cons changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Cons out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); dump_field_lv (ctx, &out, cons, &cons->u.s.car, WEIGHT_STRONG); @@ -1913,6 +1923,9 @@ dump_interval_tree (struct dump_context *ctx, INTERVAL tree, dump_off parent_offset) { +#if CHECK_STRUCTS && !defined (HASH_interval_9110163DA0) +# error "interval changed. See CHECK_STRUCTS comment." +#endif // TODO: output tree breadth-first? struct interval out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); @@ -1956,6 +1969,9 @@ dump_interval_tree (struct dump_context *ctx, static dump_off dump_string (struct dump_context *ctx, const struct Lisp_String *string) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Symbol_EB06C0D9EA) +# error "Lisp_String changed. See CHECK_STRUCTS comment." +#endif /* If we have text properties, write them _after_ the string so that at runtime, the prefetcher and cache will DTRT. (We access the string before its properties.). @@ -1999,6 +2015,9 @@ dump_string (struct dump_context *ctx, const struct Lisp_String *string) static dump_off dump_marker (struct dump_context *ctx, const struct Lisp_Marker *marker) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Marker_3C824B47DB) +# error "Lisp_Marker changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Marker out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); DUMP_FIELD_COPY (&out, marker, type); @@ -2027,6 +2046,9 @@ dump_marker (struct dump_context *ctx, const struct Lisp_Marker *marker) static dump_off dump_overlay (struct dump_context *ctx, const struct Lisp_Overlay *overlay) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Overlay_CD6BBB22F3) +# error "Lisp_Overlay changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Overlay out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); DUMP_FIELD_COPY (&out, overlay, type); @@ -2044,6 +2066,12 @@ static dump_off dump_save_value (struct dump_context *ctx, const struct Lisp_Save_Value *ptr) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Save_Value_9DB4B1A97C) +# error "Lisp_Save_Value changed. See CHECK_STRUCTS comment." +#endif +#if CHECK_STRUCTS && !defined (HASH_Lisp_Save_Type_5202541810) +# error "Lisp_Save_Type changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Save_Value out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); DUMP_FIELD_COPY (&out, ptr, type); @@ -2092,6 +2120,9 @@ static dump_off dump_finalizer (struct dump_context *ctx, const struct Lisp_Finalizer *finalizer) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Finalizer_514A6407BC) +# error "Lisp_Finalizer changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Finalizer out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); DUMP_FIELD_COPY (&out, finalizer, base.type); @@ -2107,6 +2138,12 @@ dump_finalizer (struct dump_context *ctx, static dump_off dump_misc_any (struct dump_context *ctx, struct Lisp_Misc_Any *misc_any) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Misc_Any_8909174119) +# error "Lisp_Misc_Any changed. See CHECK_STRUCTS comment." +#endif +#if CHECK_STRUCTS && !defined (HASH_Lisp_Misc_Type_FC6C8DD619) +# error "Lisp_Misc_Type changed. See CHECK_STRUCTS comment." +#endif dump_off result; switch (misc_any->type) @@ -2146,6 +2183,9 @@ dump_misc_any (struct dump_context *ctx, struct Lisp_Misc_Any *misc_any) static dump_off dump_float (struct dump_context *ctx, const struct Lisp_Float *lfloat) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Float_938B4A25C3) +# error "Lisp_Float changed. See CHECK_STRUCTS comment." +#endif eassert (ctx->header.cold_start); struct Lisp_Float out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); @@ -2156,6 +2196,9 @@ dump_float (struct dump_context *ctx, const struct Lisp_Float *lfloat) static dump_off dump_fwd_int (struct dump_context *ctx, const struct Lisp_Intfwd *intfwd) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Intfwd_1225FA32CC) +# error "Lisp_Intfwd changed. See CHECK_STRUCTS comment." +#endif dump_emacs_reloc_immediate_emacs_int (ctx, intfwd->intvar, *intfwd->intvar); struct Lisp_Intfwd out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); @@ -2167,6 +2210,9 @@ dump_fwd_int (struct dump_context *ctx, const struct Lisp_Intfwd *intfwd) static dump_off dump_fwd_bool (struct dump_context *ctx, const struct Lisp_Boolfwd *boolfwd) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Boolfwd_0EA1C7ADCC) +# error "Lisp_Boolfwd changed. See CHECK_STRUCTS comment." +#endif dump_emacs_reloc_immediate_bool (ctx, boolfwd->boolvar, *boolfwd->boolvar); struct Lisp_Boolfwd out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); @@ -2178,6 +2224,9 @@ dump_fwd_bool (struct dump_context *ctx, const struct Lisp_Boolfwd *boolfwd) static dump_off dump_fwd_obj (struct dump_context *ctx, const struct Lisp_Objfwd *objfwd) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Objfwd_45D3E513DC) +# error "Lisp_Objfwd changed. See CHECK_STRUCTS comment." +#endif dump_emacs_reloc_to_dump_lv (ctx, objfwd->objvar, *objfwd->objvar); struct Lisp_Objfwd out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); @@ -2190,6 +2239,9 @@ static dump_off dump_fwd_buffer_obj (struct dump_context *ctx, const struct Lisp_Buffer_Objfwd *buffer_objfwd) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Buffer_Objfwd_611EBD13FF) +# error "Lisp_Buffer_Objfwd changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Buffer_Objfwd out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); DUMP_FIELD_COPY (&out, buffer_objfwd, type); @@ -2203,6 +2255,9 @@ static dump_off dump_fwd_kboard_obj (struct dump_context *ctx, const struct Lisp_Kboard_Objfwd *kboard_objfwd) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Kboard_Objfwd_CAA7E71069) +# error "Lisp_Intfwd changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Kboard_Objfwd out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); DUMP_FIELD_COPY (&out, kboard_objfwd, type); @@ -2213,6 +2268,12 @@ dump_fwd_kboard_obj (struct dump_context *ctx, static dump_off dump_fwd (struct dump_context *ctx, union Lisp_Fwd *fwd) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Fwd_5227B18E87) +# error "Lisp_Fwd changed. See CHECK_STRUCTS comment." +#endif +#if CHECK_STRUCTS && !defined (HASH_Lisp_Fwd_Type_9CBA6EE55E) +# error "Lisp_Fwd_Type changed. See CHECK_STRUCTS comment." +#endif dump_off offset; switch (XFWDTYPE (fwd)) @@ -2243,6 +2304,9 @@ static dump_off dump_blv (struct dump_context *ctx, const struct Lisp_Buffer_Local_Value *blv) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Buffer_Local_Value_2B3BD67753) +# error "Lisp_Buffer_Local_Value changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Buffer_Local_Value out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); DUMP_FIELD_COPY (&out, blv, local_if_set); @@ -2310,6 +2374,12 @@ dump_pre_dump_symbol ( static dump_off dump_symbol (struct dump_context *ctx, struct Lisp_Symbol *symbol) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Symbol_EB06C0D9EA) +# error "Lisp_Symbol changed. See CHECK_STRUCTS comment." +#endif +#if CHECK_STRUCTS && !defined (HASH_symbol_redirect_ADB4F5B113) +# error "symbol_redirect changed. See CHECK_STRUCTS comment." +#endif if (ctx->flags.defer_symbols) { /* Scan everything to which this symbol refers. */ @@ -2389,6 +2459,9 @@ dump_vectorlike_generic ( struct dump_context *ctx, const union vectorlike_header *header) { +#if CHECK_STRUCTS && !defined (HASH_vectorlike_header_8409709BAF) +# error "vectorlike_header changed. See CHECK_STRUCTS comment." +#endif const struct Lisp_Vector *v = (const struct Lisp_Vector *) header; ptrdiff_t size = header->size; enum pvec_type pvectype = PSEUDOVECTOR_TYPE (v); @@ -2556,6 +2629,9 @@ static dump_off dump_hash_table (struct dump_context *ctx, const struct Lisp_Hash_Table *hash_in) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Hash_Table_400EA529E0) +# error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment." +#endif bool is_stable = dump_hash_table_stable_p (hash_in); /* If the hash table is likely to be modified in memory (either because we need to rehash, and thus toggle hash->count, or @@ -2613,6 +2689,9 @@ dump_hash_table (struct dump_context *ctx, static dump_off dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) { +#if CHECK_STRUCTS && !defined (HASH_buffer_E8695CAE09) +# error "buffer changed. See CHECK_STRUCTS comment." +#endif struct buffer munged_buffer = *in_buffer; struct buffer *buffer = &munged_buffer; @@ -2748,6 +2827,9 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer) static dump_off dump_bool_vector (struct dump_context *ctx, const struct Lisp_Vector *v) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Vector_2FA5E2F339) +# error "Lisp_Vector changed. See CHECK_STRUCTS comment." +#endif /* No relocation needed, so we don't need dump_object_start. */ dump_align_output (ctx, GCALIGNMENT); eassert (ctx->offset >= ctx->header.cold_start); @@ -2762,6 +2844,9 @@ dump_bool_vector (struct dump_context *ctx, const struct Lisp_Vector *v) static dump_off dump_subr (struct dump_context *ctx, const struct Lisp_Subr *subr) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Subr_B0DEEE4344) +# error "Lisp_Subr changed. See CHECK_STRUCTS comment." +#endif struct Lisp_Subr out; dump_object_start (ctx, GCALIGNMENT, &out, sizeof (out)); DUMP_FIELD_COPY (&out, subr, header.size); @@ -2805,6 +2890,9 @@ dump_nilled_pseudovec (struct dump_context *ctx, static dump_off dump_vectorlike (struct dump_context *ctx, const struct Lisp_Vector *v) { +#if CHECK_STRUCTS && !defined (HASH_pvec_type_69A8BF53D8) +# error "pvec_type changed. See CHECK_STRUCTS comment." +#endif dump_off offset; Lisp_Object lv = make_lisp_ptr ((void *) v, Lisp_Vectorlike); switch (PSEUDOVECTOR_TYPE (v)) @@ -2877,11 +2965,13 @@ dump_vectorlike (struct dump_context *ctx, const struct Lisp_Vector *v) static dump_off dump_object_1 (struct dump_context *ctx, Lisp_Object object) { +#if CHECK_STRUCTS && !defined (HASH_Lisp_Type_C9E246F617) +# error "Lisp_Type changed. See CHECK_STRUCTS comment." +#endif #ifdef ENABLE_CHECKING /* Vdead is extern only when ENABLE_CHECKING. */ eassert (!EQ (object, Vdead)); #endif - dump_off offset = dump_recall_object (ctx, object); if (offset > 0) { @@ -3008,6 +3098,9 @@ dump_object_for_offset (struct dump_context *ctx, Lisp_Object object) static dump_off dump_charset (struct dump_context *ctx, int cs_i) { +#if CHECK_STRUCTS && !defined (HASH_charset_317C49E291) +# error "charset changed. See CHECK_STRUCTS comment." +#endif const struct charset *cs = charset_table + cs_i; struct charset out; dump_object_start (ctx, sizeof (int), &out, sizeof (out));