From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4956 invoked by alias); 22 Feb 2019 11:29:51 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 4941 invoked by uid 89); 22 Feb 2019 11:29:51 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-9.1 required=5.0 tests=BAYES_00,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,SPF_PASS,UNSUBSCRIBE_BODY autolearn=ham version=3.3.2 spammy=Make-lang.in, make-lang.in, Makelangin, *note X-HELO: mx1.suse.de Received: from mx2.suse.de (HELO mx1.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 22 Feb 2019 11:29:49 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 05ED7AF3A for ; Fri, 22 Feb 2019 11:29:47 +0000 (UTC) Date: Fri, 22 Feb 2019 11:29:00 -0000 From: Richard Biener To: gcc@gcc.gnu.org Subject: [RFC] Change PCH "checksum" Message-ID: User-Agent: Alpine 2.20 (LSU 67 2015-01-07) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-SW-Source: 2019-02/txt/msg00120.txt.bz2 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 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 * ... 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 + +#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; }