This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] Change PCH "checksum"


GCC builds are currently not reproducible because for one the checksum
we compute for PCH purposes (by genchecksum) nowaways includes checksums
of archives (since we switched from checksumming a dummy executable
to checksumming object files).  That includes dates (unless built with
-D which we don't do).

Then later we switched to do thin archives so for example libbackend.a
we checksum doesn't contain the actual code anymore...

A pragmatic approach to "fix" things would be to just checksum
gtype-desc.o which should have enough state to cover PCH dependences
if I understand the workings correctly (patch below - a single
checksum would suffice so more simplifications are possible).

Another solution working on ELF systems with build-id support is
simply forgo checksumming anything and rely on the executable
build-id instead (pat^whack below as well).

Does anybody think that just checksumming gtype-desc.o is a
degradation over the current state (which checksums thin archives)?

Thanks,
Richard.

2019-02-22  Richard Biener  <rguenther@suse.de>

	c/
	* Make-lang.in (cc1-checksum.c): Checksum only gtype-desc.o.

	cp/
	* Make-lang.in (cc1plus-checksum.c): Checksum only gtype-desc.o.

	objc/
	* Make-lang.in (cc1obj-checksum.c): Checksum only gtype-desc.o.

	objcp/
	* Make-lang.in (cc1objplus-checksum.c): Checksum only gtype-desc.o.

Index: gcc/c/Make-lang.in
===================================================================
--- gcc/c/Make-lang.in	(revision 269111)
+++ gcc/c/Make-lang.in	(working copy)
@@ -70,14 +70,13 @@ endif
 # compute checksum over all object files and the options
 # re-use the checksum from the prev-final stage so it passes
 # the bootstrap comparison and allows comparing of the cc1 binary
-cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \
-	$(C_OBJS) $(BACKEND) $(LIBDEPS) 
+cc1-checksum.c : build/genchecksum$(build_exeext) gtype-desc.o 
 	if [ -f ../stage_final ] \
 	   && cmp -s ../stage_current ../stage_final; then \
 	  cp ../prev-gcc/cc1-checksum.c cc1-checksum.c; \
 	else \
-	  build/genchecksum$(build_exeext) $(C_OBJS) $(BACKEND) $(LIBDEPS) \
-                     checksum-options > cc1-checksum.c.tmp && 		 \
+	  build/genchecksum$(build_exeext) gtype-desc.o \
+                     > cc1-checksum.c.tmp && 		 \
 	  $(srcdir)/../move-if-change cc1-checksum.c.tmp cc1-checksum.c; \
 	fi
 
Index: gcc/cp/Make-lang.in
===================================================================
--- gcc/cp/Make-lang.in	(revision 269111)
+++ gcc/cp/Make-lang.in	(working copy)
@@ -105,14 +105,13 @@ cp-warn = $(STRICT_WARN)
 # compute checksum over all object files and the options
 # re-use the checksum from the prev-final stage so it passes
 # the bootstrap comparison and allows comparing of the cc1 binary
-cc1plus-checksum.c : build/genchecksum$(build_exeext) checksum-options \
-	$(CXX_OBJS) $(BACKEND) $(LIBDEPS) 
+cc1plus-checksum.c : build/genchecksum$(build_exeext) gtype-desc.o 
 	if [ -f ../stage_final ] \
 	   && cmp -s ../stage_current ../stage_final; then \
 	   cp ../prev-gcc/cc1plus-checksum.c cc1plus-checksum.c; \
 	else \
-	  build/genchecksum$(build_exeext) $(CXX_OBJS) $(BACKEND) $(LIBDEPS) \
-                     checksum-options > cc1plus-checksum.c.tmp &&	   \
+	  build/genchecksum$(build_exeext) gtype-desc.o \
+                     > cc1plus-checksum.c.tmp &&	   \
 	  $(srcdir)/../move-if-change cc1plus-checksum.c.tmp cc1plus-checksum.c; \
 	fi
 
Index: gcc/objc/Make-lang.in
===================================================================
--- gcc/objc/Make-lang.in	(revision 269111)
+++ gcc/objc/Make-lang.in	(working copy)
@@ -56,10 +56,9 @@ OBJC_OBJS = objc/objc-lang.o objc/objc-a
 
 objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
 
-cc1obj-checksum.c : build/genchecksum$(build_exeext) checksum-options \
-        $(OBJC_OBJS) $(C_AND_OBJC_OBJS) $(BACKEND) $(LIBDEPS)
-	build/genchecksum$(build_exeext) $(OBJC_OBJS) $(C_AND_OBJC_OBJS) \
-        $(BACKEND) $(LIBDEPS) checksum-options > cc1obj-checksum.c.tmp && \
+cc1obj-checksum.c : build/genchecksum$(build_exeext) gtype-desc.o
+	build/genchecksum$(build_exeext) gtype-desc.o
+		> cc1obj-checksum.c.tmp && \
 	$(srcdir)/../move-if-change cc1obj-checksum.c.tmp cc1obj-checksum.c
 
 cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(LIBDEPS)
Index: gcc/objcp/Make-lang.in
===================================================================
--- gcc/objcp/Make-lang.in	(revision 269111)
+++ gcc/objcp/Make-lang.in	(working copy)
@@ -59,10 +59,9 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/ob
 
 obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o
 
-cc1objplus-checksum.c : build/genchecksum$(build_exeext) checksum-options \
-	$(OBJCXX_OBJS) $(BACKEND) $(LIBDEPS)
-	build/genchecksum$(build_exeext) $(OBJCXX_OBJS) $(BACKEND) \
-		$(LIBDEPS) checksum-options > cc1objplus-checksum.c.tmp && \
+cc1objplus-checksum.c : build/genchecksum$(build_exeext) gtype-desc.o 
+	build/genchecksum$(build_exeext) gtype-desc.o
+		> cc1objplus-checksum.c.tmp && \
 	$(srcdir)/../move-if-change cc1objplus-checksum.c.tmp \
 	cc1objplus-checksum.c
 


2019-02-22  Richard Biener  <rguenther@suse.de>

	* ...

Index: gcc/c-family/c-pch.c
===================================================================
--- gcc/c-family/c-pch.c	(revision 269111)
+++ gcc/c-family/c-pch.c	(working copy)
@@ -45,10 +45,6 @@ enum {
   MATCH_SIZE = ARRAY_SIZE (pch_matching)
 };
 
-/* The value of the checksum in the dummy compiler that is actually
-   checksummed.  That compiler should never be run.  */
-static const char no_checksum[16] = { 0 };
-
 /* Information about flags and suchlike that affect PCH validity.
 
    Before this structure is read, both an initial 8-character identification
@@ -69,6 +65,67 @@ static FILE *pch_outfile;
 
 static const char *get_ident (void);
 
+#if _GNU_SOURCE
+#include <link.h>
+
+#define ALIGN(val, align)      (((val) + (align) - 1) & ~((align) - 1))
+
+struct build_id_note {
+    /* The NHdr.  */
+    uint32_t namesz;
+    uint32_t descsz;
+    uint32_t type;
+
+    char name[4]; /* Note name for build-id is "GNU\0" */
+    unsigned char build_id[16];
+};
+
+static int
+get_build_id_1 (struct dl_phdr_info *info, size_t, void *data)
+{
+  for (unsigned i = 0; i < info->dlpi_phnum; ++i)
+    {
+      if (info->dlpi_phdr[i].p_type != PT_NOTE)
+	continue;
+      build_id_note *note
+	= (build_id_note *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
+      ptrdiff_t size = info->dlpi_phdr[i].p_filesz;
+      while (size >= (ptrdiff_t)sizeof (build_id_note))
+	{
+	  if (note->type == NT_GNU_BUILD_ID
+	      && note->namesz == 4
+	      && note->descsz >= 16)
+	    {
+	      memcpy (data, note->build_id, 16);
+	      return 1;
+	    }
+	  size_t offset = (sizeof (uint32_t) * 3
+			   + ALIGN(note->namesz, 4)
+			   + ALIGN(note->descsz, 4));
+	  note = (build_id_note *)((char *)note + offset);
+	  size -= offset;
+	}
+    }
+
+  return 0;
+}
+
+static const unsigned char *
+get_build_id ()
+{
+  static unsigned char build_id[16];
+  if (!dl_iterate_phdr (get_build_id_1, build_id))
+    return NULL;
+  return build_id;
+}
+#else
+static const unsigned char *
+get_build_id ()
+{
+  return NULL;
+}
+#endif
+
 /* Compute an appropriate 8-byte magic number for the PCH file, so that
    utilities like file(1) can identify it, and so that GCC can quickly
    ignore non-PCH files and PCH files that are of a completely different
@@ -111,8 +168,6 @@ pch_init (void)
 		 pch_file);
   pch_outfile = f;
 
-  gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0);
-
   memset (&v, '\0', sizeof (v));
   v.debug_info_type = write_symbols;
   {
@@ -126,8 +181,11 @@ pch_init (void)
   v.pch_init = &pch_init;
   target_validity = targetm.get_pch_validity (&v.target_data_length);
 
+  const unsigned char *chksum = get_build_id ();
+  if (!chksum)
+    chksum = executable_checksum;
   if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
-      || fwrite (executable_checksum, 16, 1, f) != 1
+      || fwrite (chksum, 16, 1, f) != 1
       || fwrite (&v, sizeof (v), 1, f) != 1
       || fwrite (target_validity, v.target_data_length, 1, f) != 1)
     fatal_error (input_location, "can%'t write to %s: %m", pch_file);
@@ -212,8 +270,6 @@ c_common_valid_pch (cpp_reader *pfile, c
   /* Perform a quick test of whether this is a valid
      precompiled header for the current language.  */
 
-  gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0);
-
   sizeread = read (fd, ident, IDENT_LENGTH + 16);
   if (sizeread == -1)
     fatal_error (input_location, "can%'t read %s: %m", name);
@@ -245,7 +301,10 @@ c_common_valid_pch (cpp_reader *pfile, c
 	}
       return 2;
     }
-  if (memcmp (ident + IDENT_LENGTH, executable_checksum, 16) != 0)
+  const unsigned char *chksum = get_build_id ();
+  if (!chksum)
+    chksum = executable_checksum;
+  if (memcmp (ident + IDENT_LENGTH, chksum, 16) != 0)
     {
       if (cpp_get_options (pfile)->warn_invalid_pch)
 	cpp_error (pfile, CPP_DL_WARNING,
Index: gcc/genchecksum.c
===================================================================
--- gcc/genchecksum.c	(revision 269111)
+++ gcc/genchecksum.c	(working copy)
@@ -113,8 +113,13 @@ main (int argc, char ** argv)
   puts ("#include \"config.h\"");
   puts ("#include \"system.h\"");
   fputs ("EXPORTED_CONST unsigned char executable_checksum[16] = { ", stdout);
+#if _GNU_SOURCE
+  for (i = 0; i < 16; i++)
+    printf ("0x%02x%s", 0, i == 15 ? " };\n" : ", ");
+#else
   for (i = 0; i < 16; i++)
     printf ("0x%02x%s", result[i], i == 15 ? " };\n" : ", ");
+#endif
 
   return 0;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]