From c54785af87adcac067f90b1dbc238c29062cf683 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 1 Feb 2008 18:05:21 +0000 Subject: [PATCH] Implement SHA1 build-id handling in ld. --- lib/ChangeLog | 9 ++ lib/Makefile.am | 5 +- lib/sha1.c | 386 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/sha1.h | 90 +++++++++++++ src/ChangeLog | 9 ++ src/ld.c | 5 +- src/ldgeneric.c | 149 ++++++++++++--------- tests/ChangeLog | 5 + tests/Makefile.am | 6 +- 9 files changed, 597 insertions(+), 67 deletions(-) create mode 100644 lib/sha1.c create mode 100644 lib/sha1.h diff --git a/lib/ChangeLog b/lib/ChangeLog index 1697d00..c3cd0ac 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,7 +1,16 @@ +2008-02-01 Ulrich Drepper + + * 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 * 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 diff --git a/lib/Makefile.am b/lib/Makefile.am index 7ee0346..7662c38 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 index 0000000..0459cd6 --- /dev/null +++ b/lib/sha1.c @@ -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 , 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 + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include "sha1.h" + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# include +# 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 index 0000000..9761754 --- /dev/null +++ b/lib/sha1.h @@ -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 , 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 + . */ + +#ifndef _SHA1_H +#define _SHA1_H 1 + +#include +#include +#include + +#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 */ diff --git a/src/ChangeLog b/src/ChangeLog index 6f5f433..06b2978 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2008-02-01 Ulrich Drepper + + * 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 * elf32-i386.script: Add .note.ABI-tag and .note.gnu.build-id sections. diff --git a/src/ld.c b/src/ld.c index 3b422bc..a863478 100644 --- 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 diff --git a/src/ldgeneric.c b/src/ldgeneric.c index 6674887..bf0d06e 100644 --- a/src/ldgeneric.c +++ b/src/ldgeneric.c @@ -49,6 +49,7 @@ #include "ld.h" #include "list.h" #include +#include #include @@ -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) { diff --git a/tests/ChangeLog b/tests/ChangeLog index 319b784..97865b5 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2008-02-01 Ulrich Drepper + + * Makefile.am: Hook up sha1-tst.c. + * sha1-tst.c: New file. + 2008-01-21 Roland McGrath * testfile45.S.bz2: Add tests for cltq, cqto. diff --git a/tests/Makefile.am b/tests/Makefile.am index 42f71ce..5d5c918 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 -- 2.7.4