On Fri, Apr 23, 2021 at 9:59 AM Martin Liška <[email protected]> wrote:
>
> On 4/23/21 9:28 AM, Richard Biener wrote:
> > On Tue, Apr 20, 2021 at 8:49 PM Martin Liška <[email protected]> wrote:
> >>
> >> On 4/20/21 2:46 PM, Richard Biener wrote:
> >>> OK. Can you somehow arrange for trunk to pick up LTO_major from GCC
> >>> major automagically then?
> >>
> >> I have a pretty nice solution for it where I extended (and simplified)
> >> the existing gcov-iov.c generator. Doing that we can remove
> >> gcc/version.[ch].
> >>
> >> Using the patch, the following version.h is generated:
> >>
> >> #ifndef VERSION_H
> >> #define VERSION_H
> >>
> >> /* Generated automatically by genversion. */
> >>
> >> #define GCC_major_version 12
> >>
> >> /* The complete version string, assembled from several pieces.
> >> BASEVER, DATESTAMP, DEVPHASE, and REVISION are defined by the
> >> Makefile. */
> >>
> >> #define version_string "12.0.0 20210420 (experimental)"
> >> #define pkgversion_string "(GCC) "
> >>
> >> /* This is the location of the online document giving instructions for
> >> reporting bugs. If you distribute a modified version of GCC,
> >> please configure with --with-bugurl pointing to a document giving
> >> instructions for reporting bugs to you, not us. (You are of course
> >> welcome to forward us bugs reported to you, if you determine that
> >> they are not bugs in your modifications.) */
> >>
> >> #define bug_report_url "<https://gcc.gnu.org/bugs/>"
> >>
> >> #define GCOV_VERSION ((gcov_unsigned_t)0x42323020) /* B20 */
> >>
> >> #endif /* VERSION_H */
> >>
> >> Ready for master?
> >
> > Nice. This is OK if others do not have further comments.
>
> Thanks, I'm going to install it once GCC 11.1 is released.
>
> >
> > I think we'd want to explore whether we can integrate
> > genchecksum.c as well and make the PCH checksum
> > based on a set of source files (including the generated
> > auto-host.h) - that might allow removing the two-stage
>
> Definitely. I see multiple options:
>
> 1) using git, it can make provide a hash for content of a folder:
>
> $ git ls-tree HEAD -- gcc
>
> 040000 tree db613554ec17462c63bace2015c877d6bed70bbe gcc
>
> One can do that per-file as well:
> git ls-tree HEAD -- gcc/c/*.c
>
> 100644 blob bae5757ad137c0af58dbe66229d4201a45094aca gcc/c/c-aux-info.c
>
> 100644 blob d0035a31723447657a04c2ef79c9fd7c0ddc7568 gcc/c/c-convert.c
>
> 100644 blob 3ea4708c5075d9274601a0676f86a6900a9345b0 gcc/c/c-decl.c
>
> 100644 blob de98958ceabac9d631f937f9f28547d8aed26af2 gcc/c/c-errors.c
>
> 100644 blob 68c74cc1eb2ef908545b36e2dbff65606f756e15 gcc/c/c-fold.c
>
> ...
I think using git is out of the question unless we want to check in the
generated file. We ship tarballs (w/o generated files for snapshots) and those
have to build as well.
> That needs to be combined with the generated auto-host.h header file.
> From which locations do you want to build the hash? Any other $objdir
> files except auto-host.h?
In fact for PCH just summing the gengtype generated files would be
good enough I guess ...
> Note 'git archive' can append arbitrary non-git files.
>
> 2) Doing checksum of *.[cC] in a given folder + auto-host.h.
>
> 3) Using git hash (+ auto-host.h), but it's likely too gross, right?
>
> > link and my "hack" to re-use the version from prev-gcc
> > as well as our openSUSE "hack" for reproducible builds
> > which elides genchecksum.c for the use of the build-id
> > in the actual executables.
>
> What a hack. The binary is reading it's buildid right from the memory,
> right?
Well, yes (I think I've posted the patch as RFC once, attached for reference).
Richard.
> Thoughts?
>
> Martin
>
> >
> > Richard.
> >
> >> Thanks,
> >> Martin
>
Use the binaries build-id as checksum for PCH purposes.
diff --git a/gcc/c-family/c-pch.c b/gcc/c-family/c-pch.c
index a2292f46a7d..94d633d139a 100644
--- a/gcc/c-family/c-pch.c
+++ b/gcc/c-family/c-pch.c
@@ -65,6 +65,66 @@ 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))
+
+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;
+ ElfW(Nhdr) *nhdr
+ = (ElfW(Nhdr) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
+ ptrdiff_t size = info->dlpi_phdr[i].p_filesz;
+ ptrdiff_t align = info->dlpi_phdr[i].p_align;
+ if (align != 8)
+ align = 4;
+ while (size >= (ptrdiff_t)sizeof (ElfW(Nhdr)))
+ {
+ if (nhdr->n_type == NT_GNU_BUILD_ID
+ && nhdr->n_namesz == 4
+ && strncmp ((char *)nhdr
+ + sizeof (ElfW(Nhdr)),
+ "GNU", 4) == 0
+ && nhdr->n_descsz >= 16)
+ {
+ memcpy (data,
+ (char *)nhdr
+ + ALIGN (sizeof (ElfW(Nhdr))
+ + nhdr->n_namesz, align), 16);
+ return 1;
+ }
+ size_t offset = (ALIGN (sizeof (ElfW(Nhdr))
+ + nhdr->n_namesz, align)
+ + ALIGN(nhdr->n_descsz, align));
+ nhdr = (ElfW(Nhdr) *)((char *)nhdr + 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
@@ -120,8 +180,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, "cannot write to %s: %m", pch_file);
@@ -237,7 +300,10 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
}
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,
diff --git a/gcc/genchecksum.c b/gcc/genchecksum.c
index 09fbb63fa93..ec8b3281d53 100644
--- a/gcc/genchecksum.c
+++ b/gcc/genchecksum.c
@@ -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;
}