emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] pdumper 11976b6 1/6: Verify hashes of lisp structures duri


From: Daniel Colascione
Subject: [Emacs-diffs] pdumper 11976b6 1/6: Verify hashes of lisp structures during compilation
Date: Mon, 19 Feb 2018 12:02:46 -0500 (EST)

branch: pdumper
commit 11976b69233578aa719ffef69612c037cfe9bee0
Author: Daniel Colascione <address@hidden>
Commit: Daniel Colascione <address@hidden>

    Verify hashes of lisp structures during compilation
---
 .gitignore                 |   1 +
 lib-src/make-fingerprint.c |  40 ++++++++++++++----
 src/Makefile.in            |   8 +++-
 src/dmpstruct.awk          |  28 +++++++++++++
 src/pdumper.c              | 101 +++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 166 insertions(+), 12 deletions(-)

diff --git a/.gitignore b/.gitignore
index ce97ad5..fa7e3ff 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 dd2f093..2ea839d 100644
--- a/lib-src/make-fingerprint.c
+++ b/lib-src/make-fingerprint.c
@@ -32,6 +32,7 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.  */
 #include <string.h>
 #include <sysstdio.h>
 #include <sha256.h>
+#include <getopt.h>
 
 #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 
<http://www.gnu.org/licenses/>.  */
 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 32f9cdf..4a0f5d5 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 0000000..608c26f
--- /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 a05b2c4..dfcf33e 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));



reply via email to

[Prev in Thread] Current Thread [Next in Thread]