> > 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 ...

I think one can, for example, change datastructure layout/meaning of a
bit in tree.h that invalidates PCH but makes the accessors same.

Honza
> 
> > 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;
>  }

Reply via email to