]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Implement SHA1 build-id handling in ld.
authorUlrich Drepper <drepper@redhat.com>
Fri, 1 Feb 2008 18:05:21 +0000 (18:05 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 1 Feb 2008 18:05:21 +0000 (18:05 +0000)
lib/ChangeLog
lib/Makefile.am
lib/sha1.c [new file with mode: 0644]
lib/sha1.h [new file with mode: 0644]
src/ChangeLog
src/ld.c
src/ldgeneric.c
tests/ChangeLog
tests/Makefile.am

index 1697d00ec21ac6f8aa8edc2b5bd5b46746a25093..c3cd0acf3f562aa7f6181572b56e62131601802b 100644 (file)
@@ -1,7 +1,16 @@
+2008-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+       * Makefile.am (libeu_a_SOURCES): Add sha1.c.
+       (noinst_HEADERS): Add sha1.h.
+       * sha1.c: New file.
+       * sha1.h: New file.
+
 2008-01-31  Ulrich Drepper  <drepper@redhat.com>
 
        * Makefile.am (libeu_a_SOURCES): Add md5.c.
        (noinst_HEADERS): Add md5.h.
+       * md5.c: New file.
+       * md5.h: New file.
 
 2006-04-04  Ulrich Drepper  <drepper@redhat.com>
 
index 7ee03463acd4d79192d539a7df59e0c2b9f70c77..7662c380288a5b2f08bbbf511a2c50b1bf1e26ef 100644 (file)
@@ -36,9 +36,10 @@ INCLUDES = -I$(srcdir)/../libelf -I..
 noinst_LIBRARIES = libeu.a
 
 libeu_a_SOURCES = xstrndup.c xmalloc.c next_prime.c \
-                 crc32.c crc32_file.c md5.c
+                 crc32.c crc32_file.c md5.c sha1.c
 
-noinst_HEADERS = fixedsizehash.h system.h dynamicsizehash.h list.h md5.h
+noinst_HEADERS = fixedsizehash.h system.h dynamicsizehash.h list.h md5.h \
+                sha1.h
 EXTRA_DIST = dynamicsizehash.c
 
 if !GPROF
diff --git a/lib/sha1.c b/lib/sha1.c
new file mode 100644 (file)
index 0000000..0459cd6
--- /dev/null
@@ -0,0 +1,386 @@
+/* Functions to compute SHA1 message digest of files or memory blocks.
+   according to the definition of SHA1 in FIPS 180-1 from April 1997.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2008.
+
+   Red Hat elfutils 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 Software Foundation; version 2 of the License.
+
+   Red Hat elfutils 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 along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <endian.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "sha1.h"
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# include <byteswap.h>
+# define SWAP(n) bswap_32 (n)
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/* Initialize structure containing state of computation.  */
+void
+sha1_init_ctx (ctx)
+     struct sha1_ctx *ctx;
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+  ctx->E = 0xc3d2e1f0;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 20 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+sha1_read_ctx (ctx, resbuf)
+     const struct sha1_ctx *ctx;
+     void *resbuf;
+{
+  ((sha1_uint32 *) resbuf)[0] = SWAP (ctx->A);
+  ((sha1_uint32 *) resbuf)[1] = SWAP (ctx->B);
+  ((sha1_uint32 *) resbuf)[2] = SWAP (ctx->C);
+  ((sha1_uint32 *) resbuf)[3] = SWAP (ctx->D);
+  ((sha1_uint32 *) resbuf)[4] = SWAP (ctx->E);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+sha1_finish_ctx (ctx, resbuf)
+     struct sha1_ctx *ctx;
+     void *resbuf;
+{
+  /* Take yet unprocessed bytes into account.  */
+  sha1_uint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(sha1_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
+                                                    (ctx->total[0] >> 29));
+  *(sha1_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
+
+  /* Process last bytes.  */
+  sha1_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return sha1_read_ctx (ctx, resbuf);
+}
+
+
+void
+sha1_process_bytes (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct sha1_ctx *ctx;
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (ctx->buflen > 64)
+       {
+         sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+         ctx->buflen &= 63;
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+                 ctx->buflen);
+       }
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len >= 64)
+    {
+#if !_STRING_ARCH_unaligned
+/* To check alignment gcc has an appropriate operator.  Other
+   compilers don't.  */
+# if __GNUC__ >= 2
+#  define UNALIGNED_P(p) (((sha1_uintptr) p) % __alignof__ (sha1_uint32) != 0)
+# else
+#  define UNALIGNED_P(p) (((sha1_uintptr) p) % sizeof (sha1_uint32) != 0)
+# endif
+      if (UNALIGNED_P (buffer))
+       while (len > 64)
+         {
+           sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+           buffer = (const char *) buffer + 64;
+           len -= 64;
+         }
+      else
+#endif
+       {
+         sha1_process_block (buffer, len & ~63, ctx);
+         buffer = (const char *) buffer + (len & ~63);
+         len &= 63;
+       }
+    }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      size_t left_over = ctx->buflen;
+
+      memcpy (&ctx->buffer[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 64)
+       {
+         sha1_process_block (ctx->buffer, 64, ctx);
+         left_over -= 64;
+         memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+       }
+      ctx->buflen = left_over;
+    }
+}
+
+
+/* These are the four functions used in the four steps of the SHA1 algorithm
+   and defined in the FIPS 180-1.  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) (b ^ c ^ d)
+/* define FH(b, c, d) ((b & c) | (b & d) | (c & d)) */
+#define FH(b, c, d) (((b | c) & d) | (b & c))
+
+/* It is unfortunate that C does not provide an operator for cyclic
+   rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) (((w) << s) | ((w) >> (32 - s)))
+
+/* Magic constants.  */
+#define K0 0x5a827999
+#define K1 0x6ed9eba1
+#define K2 0x8f1bbcdc
+#define K3 0xca62c1d6
+
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+
+void
+sha1_process_block (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct sha1_ctx *ctx;
+{
+  sha1_uint32 computed_words[16];
+#define W(i) computed_words[(i) % 16]
+  const sha1_uint32 *words = buffer;
+  size_t nwords = len / sizeof (sha1_uint32);
+  const sha1_uint32 *endp = words + nwords;
+  sha1_uint32 A = ctx->A;
+  sha1_uint32 B = ctx->B;
+  sha1_uint32 C = ctx->C;
+  sha1_uint32 D = ctx->D;
+  sha1_uint32 E = ctx->E;
+
+  /* First increment the byte count.  FIPS 180-1 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp)
+    {
+      sha1_uint32 A_save = A;
+      sha1_uint32 B_save = B;
+      sha1_uint32 C_save = C;
+      sha1_uint32 D_save = D;
+      sha1_uint32 E_save = E;
+
+      /* First round: using the given function, the context and a constant
+        the next context is computed.  Because the algorithms processing
+        unit is a 32-bit word and it is determined to work on words in
+        little endian byte order we perhaps have to change the byte order
+        before the computation.  */
+
+#define OP(i, a, b, c, d, e)                                           \
+      do                                                               \
+        {                                                              \
+         W (i) = SWAP (*words);                                        \
+         e = CYCLIC (a, 5) + FF (b, c, d) + e + W (i) + K0;            \
+         ++words;                                                      \
+         b = CYCLIC (b, 30);                                           \
+        }                                                              \
+      while (0)
+
+      /* Steps 0 to 15.  */
+      OP (0, A, B, C, D, E);
+      OP (1, E, A, B, C, D);
+      OP (2, D, E, A, B, C);
+      OP (3, C, D, E, A, B);
+      OP (4, B, C, D, E, A);
+      OP (5, A, B, C, D, E);
+      OP (6, E, A, B, C, D);
+      OP (7, D, E, A, B, C);
+      OP (8, C, D, E, A, B);
+      OP (9, B, C, D, E, A);
+      OP (10, A, B, C, D, E);
+      OP (11, E, A, B, C, D);
+      OP (12, D, E, A, B, C);
+      OP (13, C, D, E, A, B);
+      OP (14, B, C, D, E, A);
+      OP (15, A, B, C, D, E);
+
+      /* For the remaining 64 steps we have a more complicated
+        computation of the input data-derived values.  Redefine the
+        macro to take an additional second argument specifying the
+        function to use and a new last parameter for the magic
+        constant.  */
+#undef OP
+#define OP(i, f, a, b, c, d, e, K) \
+      do                                                               \
+        {                                                              \
+         W (i) = CYCLIC (W (i - 3) ^ W (i - 8) ^ W (i - 14) ^ W (i - 16), 1);\
+         e = CYCLIC (a, 5) + f (b, c, d) + e + W (i) + K;              \
+         b = CYCLIC (b, 30);                                           \
+        }                                                              \
+      while (0)
+
+      /* Steps 16 to 19.  */
+      OP (16, FF, E, A, B, C, D, K0);
+      OP (17, FF, D, E, A, B, C, K0);
+      OP (18, FF, C, D, E, A, B, K0);
+      OP (19, FF, B, C, D, E, A, K0);
+
+      /* Steps 20 to 39.  */
+      OP (20, FG, A, B, C, D, E, K1);
+      OP (21, FG, E, A, B, C, D, K1);
+      OP (22, FG, D, E, A, B, C, K1);
+      OP (23, FG, C, D, E, A, B, K1);
+      OP (24, FG, B, C, D, E, A, K1);
+      OP (25, FG, A, B, C, D, E, K1);
+      OP (26, FG, E, A, B, C, D, K1);
+      OP (27, FG, D, E, A, B, C, K1);
+      OP (28, FG, C, D, E, A, B, K1);
+      OP (29, FG, B, C, D, E, A, K1);
+      OP (30, FG, A, B, C, D, E, K1);
+      OP (31, FG, E, A, B, C, D, K1);
+      OP (32, FG, D, E, A, B, C, K1);
+      OP (33, FG, C, D, E, A, B, K1);
+      OP (34, FG, B, C, D, E, A, K1);
+      OP (35, FG, A, B, C, D, E, K1);
+      OP (36, FG, E, A, B, C, D, K1);
+      OP (37, FG, D, E, A, B, C, K1);
+      OP (38, FG, C, D, E, A, B, K1);
+      OP (39, FG, B, C, D, E, A, K1);
+
+      /* Steps 40 to 59.  */
+      OP (40, FH, A, B, C, D, E, K2);
+      OP (41, FH, E, A, B, C, D, K2);
+      OP (42, FH, D, E, A, B, C, K2);
+      OP (43, FH, C, D, E, A, B, K2);
+      OP (44, FH, B, C, D, E, A, K2);
+      OP (45, FH, A, B, C, D, E, K2);
+      OP (46, FH, E, A, B, C, D, K2);
+      OP (47, FH, D, E, A, B, C, K2);
+      OP (48, FH, C, D, E, A, B, K2);
+      OP (49, FH, B, C, D, E, A, K2);
+      OP (50, FH, A, B, C, D, E, K2);
+      OP (51, FH, E, A, B, C, D, K2);
+      OP (52, FH, D, E, A, B, C, K2);
+      OP (53, FH, C, D, E, A, B, K2);
+      OP (54, FH, B, C, D, E, A, K2);
+      OP (55, FH, A, B, C, D, E, K2);
+      OP (56, FH, E, A, B, C, D, K2);
+      OP (57, FH, D, E, A, B, C, K2);
+      OP (58, FH, C, D, E, A, B, K2);
+      OP (59, FH, B, C, D, E, A, K2);
+
+      /* Steps 60 to 79.  */
+      OP (60, FG, A, B, C, D, E, K3);
+      OP (61, FG, E, A, B, C, D, K3);
+      OP (62, FG, D, E, A, B, C, K3);
+      OP (63, FG, C, D, E, A, B, K3);
+      OP (64, FG, B, C, D, E, A, K3);
+      OP (65, FG, A, B, C, D, E, K3);
+      OP (66, FG, E, A, B, C, D, K3);
+      OP (67, FG, D, E, A, B, C, K3);
+      OP (68, FG, C, D, E, A, B, K3);
+      OP (69, FG, B, C, D, E, A, K3);
+      OP (70, FG, A, B, C, D, E, K3);
+      OP (71, FG, E, A, B, C, D, K3);
+      OP (72, FG, D, E, A, B, C, K3);
+      OP (73, FG, C, D, E, A, B, K3);
+      OP (74, FG, B, C, D, E, A, K3);
+      OP (75, FG, A, B, C, D, E, K3);
+      OP (76, FG, E, A, B, C, D, K3);
+      OP (77, FG, D, E, A, B, C, K3);
+      OP (78, FG, C, D, E, A, B, K3);
+      OP (79, FG, B, C, D, E, A, K3);
+
+      /* Add the starting values of the context.  */
+      A += A_save;
+      B += B_save;
+      C += C_save;
+      D += D_save;
+      E += E_save;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
+  ctx->E = E;
+}
diff --git a/lib/sha1.h b/lib/sha1.h
new file mode 100644 (file)
index 0000000..9761754
--- /dev/null
@@ -0,0 +1,90 @@
+/* Declaration of functions and data types used for SHA1 sum computing
+   library functions.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2008.
+
+   Red Hat elfutils 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 Software Foundation; version 2 of the License.
+
+   Red Hat elfutils 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 along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifndef _SHA1_H
+#define _SHA1_H 1
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#define SHA1_DIGEST_SIZE 20
+#define SHA1_BLOCK_SIZE 64
+
+typedef uint32_t sha1_uint32;
+typedef uintptr_t sha1_uintptr;
+
+/* Structure to save state of computation between the single steps.  */
+struct sha1_ctx
+{
+  sha1_uint32 A;
+  sha1_uint32 B;
+  sha1_uint32 C;
+  sha1_uint32 D;
+  sha1_uint32 E;
+
+  sha1_uint32 total[2];
+  sha1_uint32 buflen;
+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (sha1_uint32))));
+};
+
+/* Initialize structure containing state of computation.  */
+extern void sha1_init_ctx (struct sha1_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void sha1_process_block (const void *buffer, size_t len,
+                               struct sha1_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void sha1_process_bytes (const void *buffer, size_t len,
+                               struct sha1_ctx *ctx);
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 20 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
+
+
+/* Put result from CTX in first 20 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
+
+#endif /* sha1.h */
index 6f5f43377e943bec7c3b3bb24cca3ed990a638b3..06b29781113f5b119424408dd3f5856a109454a0 100644 (file)
@@ -1,3 +1,12 @@
+2008-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+       * ld.c: Recognize sha1 argument for --build-id parameter.
+       * ldgeneric.c (create_build_id_section): Handle sha1.
+       (compute_hash_sum): New function.  Broken out of compute_build_id.
+       Take hash function and context as parameters.
+       (compute_build_id): Use compute_hash_sum for md5 and the new sha1
+       implementation.
+
 2008-01-31  Ulrich Drepper  <drepper@redhat.com>
 
        * elf32-i386.script: Add .note.ABI-tag and .note.gnu.build-id sections.
index 3b422bc649b524cabb336803695ed5762fe33e0d..a863478a8379cd2659464e5907982a8ded4dd6ba 100644 (file)
--- a/src/ld.c
+++ b/src/ld.c
@@ -172,7 +172,7 @@ Default rules of extracting from archive; weak references are not enough."),
   { "hash-style", ARGP_hash_style, "STYLE", 0,
     N_("Set hash style to sysv, gnu or both."), 0 },
   { "build-id", ARGP_build_id, "STYLE", OPTION_ARG_OPTIONAL,
-    N_("Generate build ID note (md5 (default), uuid)."), 0 },
+    N_("Generate build ID note (md5, sha1 (default), uuid)."), 0 },
 
   { NULL, 0, NULL, 0, N_("Linker Operation Control:"), 0 },
   { "verbose", 'v', NULL, 0, N_("Verbose messages."), 0 },
@@ -688,9 +688,10 @@ parse_opt_1st (int key, char *arg,
 
     case ARGP_build_id:
       if (arg == NULL)
-       ld_state.build_id = "md5";
+       ld_state.build_id = "sha1";
       else if (strcmp (arg, "uuid") != 0
               && strcmp (arg, "md5") != 0
+              && strcmp (arg, "sha1") != 0
               && !valid_hexarg (arg))
        error (EXIT_FAILURE, 0, gettext ("invalid build-ID style '%s'"), arg);
       else
index 6674887b0e72fcbe08375ec5d5fd34e6493fdf8f..bf0d06e35e1b1344cf5c5c1abb9530c449b4d2c3 100644 (file)
@@ -49,6 +49,7 @@
 #include "ld.h"
 #include "list.h"
 #include <md5.h>
+#include <sha1.h>
 #include <system.h>
 
 
@@ -4119,6 +4120,8 @@ create_build_id_section (Elf_Scn *scn)
   if (strcmp (ld_state.build_id, "md5") == 0
       || strcmp (ld_state.build_id, "uuid") == 0)
     d->d_size += 16;
+  else if (strcmp (ld_state.build_id, "sha1") == 0)
+    d->d_size += 20;
   else
     {
       assert (ld_state.build_id[0] == '0' && ld_state.build_id[1] == 'x');
@@ -4133,6 +4136,68 @@ create_build_id_section (Elf_Scn *scn)
 }
 
 
+static void
+compute_hash_sum (void (*hashfct) (const void *, size_t, void *), void *ctx)
+{
+  /* The call cannot fail.  */
+  size_t shstrndx;
+  (void) elf_getshstrndx (ld_state.outelf, &shstrndx);
+
+  const char *ident = elf_getident (ld_state.outelf, NULL);
+  bool same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB
+                          && __BYTE_ORDER == __LITTLE_ENDIAN)
+                         || (ident[EI_DATA] == ELFDATA2MSB
+                             && __BYTE_ORDER == __BIG_ENDIAN));
+
+  /* Iterate over all sections to find those which are not strippable.  */
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (ld_state.outelf, scn)) != NULL)
+    {
+      /* Get the section header.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      assert (shdr != NULL);
+
+      if (SECTION_STRIP_P (shdr, elf_strptr (ld_state.outelf, shstrndx,
+                                            shdr->sh_name), true))
+       /* The section can be stripped.  Don't use it.  */
+       continue;
+
+      /* Do not look at NOBITS sections.  */
+      if (shdr->sh_type == SHT_NOBITS)
+       continue;
+
+      /* Iterate through the list of data blocks.  */
+      Elf_Data *data = NULL;
+      while ((data = INTUSE(elf_getdata) (scn, data)) != NULL)
+       /* If the file byte order is the same as the host byte order
+          process the buffer directly.  If the data is just a stream
+          of bytes which the library will not convert we can use it
+          as well.  */
+       if (likely (same_byte_order) || data->d_type == ELF_T_BYTE)
+         hashfct (data->d_buf, data->d_size, ctx);
+       else
+         {
+           /* Convert the data to file byte order.  */
+           if (gelf_xlatetof (ld_state.outelf, data, data, ident[EI_DATA])
+               == NULL)
+             error (EXIT_FAILURE, 0, gettext ("\
+cannot convert section data to file format: %s"),
+                    elf_errmsg (-1));
+
+           hashfct (data->d_buf, data->d_size, ctx);
+
+           /* And convert it back.  */
+           if (gelf_xlatetom (ld_state.outelf, data, data, ident[EI_DATA])
+               == NULL)
+             error (EXIT_FAILURE, 0, gettext ("\
+cannot convert section data to memory format: %s"),
+                    elf_errmsg (-1));
+         }
+    }
+}
+
+
 /* Iterate over the sections */
 static void
 compute_build_id (void)
@@ -4146,75 +4211,37 @@ compute_build_id (void)
   hdr->n_type = NT_GNU_BUILD_ID;
   char *dp = mempcpy (hdr + 1, ELF_NOTE_GNU, sizeof (ELF_NOTE_GNU));
 
-  if (strcmp (ld_state.build_id, "md5") == 0)
+  if (strcmp (ld_state.build_id, "sha1") == 0)
     {
-      /* Compute the MD5 sum of various parts of the generated file.
+      /* Compute the SHA1 sum of various parts of the generated file.
         We compute the hash sum over the external representation.  */
-      struct md5_ctx ctx;
-      md5_init_ctx (&ctx);
+      struct sha1_ctx ctx;
+      sha1_init_ctx (&ctx);
 
-      /* The call cannot fail.  */
-      size_t shstrndx;
-      (void) elf_getshstrndx (ld_state.outelf, &shstrndx);
+      /* Compute the hash sum by running over all sections.  */
+      compute_hash_sum ((void (*) (const void *, size_t, void *)) sha1_process_bytes,
+                       &ctx);
 
-      const char *ident = elf_getident (ld_state.outelf, NULL);
-      bool same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB
-                              && __BYTE_ORDER == __LITTLE_ENDIAN)
-                             || (ident[EI_DATA] == ELFDATA2MSB
-                                 && __BYTE_ORDER == __BIG_ENDIAN));
+      /* We are done computing the checksum.  */
+      (void) sha1_finish_ctx (&ctx, dp);
 
-      /* Iterate over all sections to find those which are not strippable.  */
-      Elf_Scn *scn = NULL;
-      while ((scn = elf_nextscn (ld_state.outelf, scn)) != NULL)
-       {
-         /* Get the section header.  */
-         GElf_Shdr shdr_mem;
-         GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-         assert (shdr != NULL);
-
-         if (SECTION_STRIP_P (shdr,
-                              elf_strptr (ld_state.outelf, shstrndx,
-                                          shdr->sh_name), true))
-           /* The section can be stripped.  Don't use it.  */
-           continue;
-
-         /* Do not look at NOBITS sections.  */
-         if (shdr->sh_type == SHT_NOBITS)
-           continue;
-
-         /* Iterate through the list of data blocks.  */
-         Elf_Data *data = NULL;
-         while ((data = INTUSE(elf_getdata) (scn, data)) != NULL)
-           /* If the file byte order is the same as the host byte order
-              process the buffer directly.  If the data is just a stream
-              of bytes which the library will not convert we can use it
-              as well.  */
-           if (likely (same_byte_order) || data->d_type == ELF_T_BYTE)
-             md5_process_bytes (data->d_buf, data->d_size, &ctx);
-           else
-             {
-               /* Convert the data to file byte order.  */
-               if (gelf_xlatetof (ld_state.outelf, data, data, ident[EI_DATA])
-                   == NULL)
-                 error (EXIT_FAILURE, 0, gettext ("\
-cannot convert section data to file format: %s"),
-                        elf_errmsg (-1));
-
-               md5_process_bytes (data->d_buf, data->d_size, &ctx);
+      hdr->n_descsz = SHA1_DIGEST_SIZE;
+    }
+  else if (strcmp (ld_state.build_id, "md5") == 0)
+    {
+      /* Compute the MD5 sum of various parts of the generated file.
+        We compute the hash sum over the external representation.  */
+      struct md5_ctx ctx;
+      md5_init_ctx (&ctx);
 
-               /* And convert it back.  */
-               if (gelf_xlatetom (ld_state.outelf, data, data, ident[EI_DATA])
-                   == NULL)
-                 error (EXIT_FAILURE, 0, gettext ("\
-cannot convert section data to memory format: %s"),
-                        elf_errmsg (-1));
-             }
+      /* Compute the hash sum by running over all sections.  */
+      compute_hash_sum ((void (*) (const void *, size_t, void *)) md5_process_bytes,
+                       &ctx);
 
-         /* We are done computing the checksum.  */
-         (void) md5_finish_ctx (&ctx, dp);
+      /* We are done computing the checksum.  */
+      (void) md5_finish_ctx (&ctx, dp);
 
-         hdr->n_descsz = 16;
-       }
+      hdr->n_descsz = MD5_DIGEST_SIZE;
     }
   else if (strcmp (ld_state.build_id, "uuid") == 0)
     {
index 319b784977e671df142f5e76ef89b0456d4ea9a9..97865b5da4c519b2ce25c57ce29b00a8ff221e9b 100644 (file)
@@ -1,3 +1,8 @@
+2008-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+       * Makefile.am: Hook up sha1-tst.c.
+       * sha1-tst.c: New file.
+
 2008-01-21  Roland McGrath  <roland@redhat.com>
 
        * testfile45.S.bz2: Add tests for cltq, cqto.
index 42f71ce4e8e34a746ff34c252acbc170d55074af..5d5c9185498a63db5d7b1f57af82ca1f016dd192 100644 (file)
@@ -88,8 +88,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
 # run-show-ciefde.sh
 
 if !STANDALONE
-noinst_PROGRAMS += msg_tst
-TESTS += msg_tst
+noinst_PROGRAMS += msg_tst sha1-tst
+TESTS += msg_tst sha1-tst
 endif
 
 if HAVE_LIBASM
@@ -175,6 +175,7 @@ libelf = ../libelf/libelf.so
 libasm = ../libasm/libasm.so
 endif
 libebl = ../libebl/libebl.a
+libeu = ../lib/libeu.a
 endif !STANDALONE
 
 arextract_LDADD = $(libelf) $(libmudflap)
@@ -224,6 +225,7 @@ arls_LDADD = $(libelf) $(libmudflap)
 dwfl_bug_fd_leak_LDADD = $(libdw) $(libebl) $(libelf) $(libmudflap) -ldl
 dwfl_bug_report_LDADD = $(libdw) $(libebl) $(libelf) $(libmudflap) -ldl
 dwfl_addr_sect_LDADD = $(libdw) $(libebl) $(libelf) $(libmudflap) -ldl
+sha1_tst_LDADD = $(libeu) $(libmudflap)
 
 CLEANFILES = xxx *.gcno *.gcda *gconv