genchecksum.c 2.85 KB
Newer Older
1
/* Generate checksums of executables for PCH validation
2
   Copyright (C) 2005-2018 Free Software Foundation, Inc.
3 4 5 6 7

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
8
Software Foundation; either version 3, or (at your option) any later
9 10 11 12 13 14 15 16
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
17 18
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
19 20 21 22 23 24 25 26

#include "bconfig.h"
#include "system.h"
#include "md5.h"

static void
usage (void)
{
27
  fputs ("Usage: genchecksums <filename> ...\n", stderr);
28 29
}

30 31 32
/* Important: BLOCKSIZE must be a multiple of 64.  */
#define BLOCKSIZE 4096

33
static void
34
dosum (struct md5_ctx *ctx, const char *file)
35 36
{
  FILE *f;
37 38
  char buffer[BLOCKSIZE + 72];
  size_t sum;
H.J. Lu committed
39

40 41 42 43 44 45
  f = fopen (file, "rb");
  if (!f)
    {
      fprintf (stderr, "opening %s: %s\n", file, xstrerror (errno));
      exit (1);
    }
H.J. Lu committed
46

47 48 49 50 51 52
  /* Some executable formats have timestamps in the first 16 bytes, yuck.  */
  if (fseek (f, 16, SEEK_SET) != 0)
     {
      fprintf (stderr, "seeking in %s: %s\n", file, xstrerror (errno));
      exit (1);
    }
H.J. Lu committed
53

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
  /* Iterate over full file contents.  */
  while (1)
    {
      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
	 computation function processes the whole buffer so that with the
	 next round of the loop another block can be read.  */
      size_t n;
      sum = 0;

      /* Read block.  Take care for partial reads.  */
      do
	{
	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, f);

	  sum += n;
	}
      while (sum < BLOCKSIZE && n != 0);
      if (n == 0 && ferror (f))
        exit (1);

      /* If end of file is reached, end the loop.  */
      if (n == 0)
	break;

      /* Process buffer with BLOCKSIZE bytes.  Note that
			BLOCKSIZE % 64 == 0
       */
      md5_process_block (buffer, BLOCKSIZE, ctx);
    }

  /* Add the last bytes if necessary.  */
  if (sum > 0)
    md5_process_bytes (buffer, sum, ctx);

  if (fclose (f) != 0)
89 90 91 92 93 94 95 96 97
     {
      fprintf (stderr, "reading %s: %s\n", file, xstrerror (errno));
      exit (1);
    }
}

int
main (int argc, char ** argv)
{
98 99 100 101 102
  struct md5_ctx ctx;
  unsigned char result[16];
  int i;

  if (argc < 2)
103 104 105 106 107
    {
      usage ();
      return 1;
    }

108 109 110 111 112 113 114 115 116 117
  md5_init_ctx (&ctx);
  for (i = 1; i < argc; i++) 
    dosum (&ctx, argv[i]);
  md5_finish_ctx (&ctx, result);

  puts ("#include \"config.h\"");
  puts ("#include \"system.h\"");
  fputs ("EXPORTED_CONST unsigned char executable_checksum[16] = { ", stdout);
  for (i = 0; i < 16; i++)
    printf ("0x%02x%s", result[i], i == 15 ? " };\n" : ", ");
118 119 120

  return 0;
}