diff options
author | Chih-hung Hsieh <chh@google.com> | 2015-09-25 14:51:48 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-09-25 14:51:48 +0000 |
commit | b0121c5547604527aaeea297b54047cd14b234df (patch) | |
tree | 7d9031ee3d5796de4a1825892fc6e04ba6e36ae2 /lib | |
parent | d03895cf5f8b77c6a85abcd84ea0d80ff56be846 (diff) | |
parent | 5eafdf0f9bfd9a3c5f93414ac16bb399b6da0b7f (diff) | |
download | android_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.tar.gz android_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.tar.bz2 android_external_elfutils-b0121c5547604527aaeea297b54047cd14b234df.zip |
Merge "Move files up to match upstream source structure."
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ChangeLog | 156 | ||||
-rw-r--r-- | lib/Makefile.am | 46 | ||||
-rw-r--r-- | lib/color.c | 230 | ||||
-rw-r--r-- | lib/crc32.c | 98 | ||||
-rw-r--r-- | lib/crc32_file.c | 91 | ||||
-rw-r--r-- | lib/dynamicsizehash.c | 332 | ||||
-rw-r--r-- | lib/dynamicsizehash.h | 127 | ||||
-rw-r--r-- | lib/eu-config.h | 189 | ||||
-rw-r--r-- | lib/fixedsizehash.h | 267 | ||||
-rw-r--r-- | lib/list.h | 100 | ||||
-rw-r--r-- | lib/md5.c | 454 | ||||
-rw-r--r-- | lib/md5.h | 110 | ||||
-rw-r--r-- | lib/next_prime.c | 66 | ||||
-rw-r--r-- | lib/sha1.c | 391 | ||||
-rw-r--r-- | lib/sha1.h | 93 | ||||
-rw-r--r-- | lib/system.h | 185 | ||||
-rw-r--r-- | lib/xmalloc.c | 84 | ||||
-rw-r--r-- | lib/xstrdup.c | 43 | ||||
-rw-r--r-- | lib/xstrndup.c | 47 |
19 files changed, 3109 insertions, 0 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog new file mode 100644 index 00000000..44152131 --- /dev/null +++ b/lib/ChangeLog @@ -0,0 +1,156 @@ +2014-01-17 Lei Zhang <thestig@google.com> + + * crc32_file.c: Include config.h. + +2013-12-12 Josh Stone <jistone@redhat.com> + + * dynamicsizehash.c (lookup): Add a shortcut around division. + +2013-04-30 Jan Kratochvil <jan.kratochvil@redhat.com> + + * eu-config.h (COMPAT_VERSION_NEWPROTO): New. Twice. + +2013-04-26 Jan Kratochvil <jan.kratochvil@redhat.com> + + * system.h (LE64, BE64): Move here the definitions from + libdwfl/link_map.c. + +2013-04-24 Mark Wielaard <mjw@redhat.com> + + * Makefile.am: Use AM_CPPFLAGS instead of INCLUDES. + +2012-10-09 Adam Markey <adam@etinternational.com> + + * system.h: Changed pwrite_retry, write_retry, and pread_retry to + handle case where not all data was read/written. + +2012-10-08 Jan Kratochvil <jan.kratochvil@redhat.com> + + * system.h (eu_static_assert): New macro. + +2012-01-21 Ulrich Drepper <drepper@gmail.com> + + * Makefile.am (libeu_a_SOURCES): Add color.c. + * system.h: Declare color_argp. Define color_enum. Declare + color_* variables. + * color.c: New file. + +2011-10-02 Ulrich Drepper <drepper@gmail.com> + + * system.h: Declare __cxa_demangle. + +2011-07-09 Roland McGrath <roland@hack.frob.com> + + * sha1.c (be64_copy): New function. + (sha1_finish_ctx): Use it. + * md5.c (le64_copy): New function. + (md5_finish_ctx): Use it. + * system.h (LE32, BE32): New macros, using <endian.h> and <byteswap.h>. + * md5.c (SWAP): Use LE32. + * sha1.c (SWAP): Use BE32. + +2010-06-16 Roland McGrath <roland@redhat.com> + + * dynamicsizehash.h (HASHTYPE): New macro. + (struct): Use size_t for table sizes. + * dynamicsizehash.c: Likewise. Use HASHTYPE for hash values. + +2010-02-15 Roland McGrath <roland@redhat.com> + + * Makefile.am: Use config/eu.am for common stuff. + +2009-08-09 Roland McGrath <roland@redhat.com> + + * eu-config.h (OLD_VERSION, NEW_VERSION, COMPAT_VERSION): New macros. + +2009-01-23 Roland McGrath <roland@redhat.com> + + * eu-config.h: Add multiple inclusion protection. + +2009-01-17 Ulrich Drepper <drepper@redhat.com> + + * system.h (ARGP_PROGRAM_VERSION_HOOK_DEF): Define. + (ARGP_PROGRAM_BUG_ADDRESS_DEF): Define. + +2009-01-10 Ulrich Drepper <drepper@redhat.com> + + * eu-config.h: Remove tls_key_t, key_create, getspecific, setspecific, + once_define, and once_execute macros. Use USE_LOCKS instead of + USE_TLS. + +2008-08-25 Roland McGrath <roland@redhat.com> + + * eu-config.h [USE_TLS] (RWLOCK_CALL): New macro. + (rwlock_init, rwlock_fini, rwlock_rdlock, rwlock_wrlock, rwlock_unlock): + Use it. + +2008-08-24 Roland McGrath <roland@redhat.com> + + * eu-config.h: New file. + * Makefile.am (noinst_HEADERS): Add it. + +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> + + * Makefile.am (libeu_a_SOURCES): We don't need xstrdup in the moment. + +2005-08-28 Ulrich Drepper <drepper@redhat.com> + + * system.h: Define pwrite_retry, write_retry, and pread_retry. + +2005-08-06 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am (xmalloc_CFLAGS): Define only if !GPROF. + +2005-05-03 Roland McGrath <roland@redhat.com> + + * crc32_file.c: New file. + * Makefile.am (libeu_a_SOURCES): Add it. + * system.h: Declare crc32_file. + +2005-04-30 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Use -ffunction-sections for xmalloc.c. + +2005-02-15 Ulrich Drepper <drepper@redhat.com> + + * dynamicsizehash.c (lookup): Mark val parameter as possibly unused. + +2005-02-06 Ulrich Drepper <drepper@redhat.com> + + * fixedsizehash.h: Mark unused parameters. Correct CLASS and + const order for fshash_find. + + * Makefile.am: Cleanup AM_CFLAGS handling. Add -Wunused -Wextra. + +2005-02-05 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am [MUDFLAP] (AM_CFLAGS): Add -fpic and -fmudflap. + +2004-01-17 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Support building with mudflap. + +2003-09-22 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am (AM_CFLAGS): Add -fpic. + + * Makefile.am (noinst_HEADERS): Add list.h. + * list.h: New file. + +2003-08-11 Ulrich Drepper <drepper@redhat.com> + + * Moved to CVS archive. diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 00000000..97f295eb --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,46 @@ +## Process this file with automake to create Makefile.in +## +## Copyright (C) 1996-2011 Red Hat, Inc. +## This file is part of elfutils. +## +## This file is free software; you can redistribute it and/or modify +## it under the terms of either +## +## * the GNU Lesser General Public License as published by the Free +## Software Foundation; either version 3 of the License, or (at +## your option) any later version +## +## or +## +## * the GNU General Public License as published by the Free +## Software Foundation; either version 2 of the License, or (at +## your option) any later version +## +## or both in parallel, as here. +## +## 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 copies of the GNU General Public License and +## the GNU Lesser General Public License along with this program. If +## not, see <http://www.gnu.org/licenses/>. +## +include $(top_srcdir)/config/eu.am +AM_CFLAGS += -fpic +AM_CPPFLAGS += -I$(srcdir)/../libelf + +noinst_LIBRARIES = libeu.a + +libeu_a_SOURCES = xstrdup.c xstrndup.c xmalloc.c next_prime.c \ + crc32.c crc32_file.c md5.c sha1.c \ + color.c + +noinst_HEADERS = fixedsizehash.h system.h dynamicsizehash.h list.h md5.h \ + sha1.h eu-config.h +EXTRA_DIST = dynamicsizehash.c + +if !GPROF +xmalloc_CFLAGS = -ffunction-sections +endif diff --git a/lib/color.c b/lib/color.c new file mode 100644 index 00000000..d1309ed7 --- /dev/null +++ b/lib/color.c @@ -0,0 +1,230 @@ +/* Handling of color output. + Copyright (C) 2011 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2011. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <argp.h> +#include <error.h> +#include <libintl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "system.h" + + +/* Prototype for option handler. */ +static error_t parse_opt (int key, char *arg, struct argp_state *state); + +/* Option values. */ +#define OPT_COLOR 0x100100 + +/* Definitions of arguments for argp functions. */ +static const struct argp_option options[] = +{ + { "color", OPT_COLOR, "WHEN", OPTION_ARG_OPTIONAL, + N_("colorize the output. WHEN defaults to 'always' or can be 'auto' or 'never'"), 0 }, + + { NULL, 0, NULL, 0, NULL, 0 } +}; + +/* Parser data structure. */ +const struct argp color_argp = + { + options, parse_opt, NULL, NULL, NULL, NULL, NULL + }; + +/* Coloring mode. */ +enum color_enum color_mode; + +/* Colors to use for the various components. */ +char *color_address = ""; +char *color_bytes = ""; +char *color_mnemonic = ""; +char *color_operand = NULL; +char *color_operand1 = ""; +char *color_operand2 = ""; +char *color_operand3 = ""; +char *color_label = ""; +char *color_undef = ""; +char *color_undef_tls = ""; +char *color_undef_weak = ""; +char *color_symbol = ""; +char *color_tls = ""; +char *color_weak = ""; + +const char color_off[] = "\e[0m"; + + +/* Handle program arguments. */ +static error_t +parse_opt (int key, char *arg, + struct argp_state *state __attribute__ ((unused))) +{ + switch (key) + { + case OPT_COLOR: + if (arg == NULL) + color_mode = color_always; + else + { + static const struct + { + const char str[7]; + enum color_enum mode; + } values[] = + { + { "always", color_always }, + { "yes", color_always }, + { "force", color_always }, + { "never", color_never }, + { "no", color_never }, + { "none", color_never }, + { "auto", color_auto }, + { "tty", color_auto }, + { "if-tty", color_auto } + }; + const int nvalues = sizeof (values) / sizeof (values[0]); + int i; + for (i = 0; i < nvalues; ++i) + if (strcmp (arg, values[i].str) == 0) + { + color_mode = values[i].mode; + if (color_mode == color_auto) + color_mode + = isatty (STDOUT_FILENO) ? color_always : color_never; + break; + } + if (i == nvalues) + { + error (0, 0, dgettext ("elfutils", "\ +%s: invalid argument '%s' for '--color'\n\ +valid arguments are:\n\ + - 'always', 'yes', 'force'\n\ + - 'never', 'no', 'none'\n\ + - 'auto', 'tty', 'if-tty'\n"), + program_invocation_short_name, arg); + argp_help (&color_argp, stderr, ARGP_HELP_SEE, + program_invocation_short_name); + exit (EXIT_FAILURE); + } + } + + if (color_mode == color_always) + { + const char *env = getenv ("ELFUTILS_COLORS"); + if (env != NULL) + { + do + { + const char *start = env; + while (*env != '=' && *env != '\0') + ++env; + if (*env == '=' && env != start) + { + size_t name_len = env - start; + const char *val = ++env; + env = strchrnul (env, ':'); + if (val != env) + { + static const struct + { + unsigned char len; + const char name[sizeof (char *) - 1]; + char **varp; + } known[] = + { +#define E(name, var) { sizeof (#name) - 1, #name, &color_##var } + E (a, address), + E (b, bytes), + E (m, mnemonic), + E (o, operand), + E (o1, operand1), + E (o1, operand2), + E (o1, operand3), + E (l, label), + E (u, undef), + E (ut, undef_tls), + E (uw, undef_weak), + E (sy, symbol), + E (st, tls), + E (sw, weak), + }; + const size_t nknown = (sizeof (known) + / sizeof (known[0])); + + for (size_t i = 0; i < nknown; ++i) + if (name_len == known[i].len + && memcmp (start, known[i].name, name_len) == 0) + { + if (asprintf (known[i].varp, "\e[%.*sm", + (int) (env - val), val) < 0) + error (EXIT_FAILURE, errno, + gettext ("cannot allocate memory")); + break; + } + } + if (*env == ':') + ++env; + } + } + while (*env != '\0'); + + if (color_operand != NULL) + { + if (color_operand1[0] == '\0') + color_operand1 = color_operand; + if (color_operand2[0] == '\0') + color_operand2 = color_operand; + if (color_operand3[0] == '\0') + color_operand3 = color_operand; + } + } +#if 0 + else + { + // XXX Just for testing. + color_address = xstrdup ("\e[38;5;166;1m"); + color_bytes = xstrdup ("\e[38;5;141m"); + color_mnemonic = xstrdup ("\e[38;5;202;1m"); + color_operand1 = xstrdup ("\e[38;5;220m"); + color_operand2 = xstrdup ("\e[38;5;48m"); + color_operand3 = xstrdup ("\e[38;5;112m"); + color_label = xstrdup ("\e[38;5;21m"); + } +#endif + } + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} diff --git a/lib/crc32.c b/lib/crc32.c new file mode 100644 index 00000000..1a76b1b3 --- /dev/null +++ b/lib/crc32.c @@ -0,0 +1,98 @@ +/* Copyright (C) 2002 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <stdint.h> +#include "system.h" + + +/* Table computed with Mark Adler's makecrc.c utility. */ +static const uint32_t crc32_table[256] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d +}; + +uint32_t +crc32 (uint32_t crc, unsigned char *buf, size_t len) +{ + unsigned char *end; + + crc = ~crc; + for (end = buf + len; buf < end; ++buf) + crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); + return ~crc; +} diff --git a/lib/crc32_file.c b/lib/crc32_file.c new file mode 100644 index 00000000..c0b18e91 --- /dev/null +++ b/lib/crc32_file.c @@ -0,0 +1,91 @@ +/* Compute CRC32 checksum of file contents. + Copyright (C) 2006 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "system.h" +#include <errno.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int +crc32_file (int fd, uint32_t *resp) +{ + unsigned char buffer[1024 * 8]; + uint32_t crc = 0; + off_t off = 0; + ssize_t count; + + struct stat st; + if (fstat (fd, &st) == 0) + { + /* Try mapping in the file data. */ + size_t mapsize = st.st_size; + void *mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == MAP_FAILED && errno == ENOMEM) + { + const size_t pagesize = sysconf (_SC_PAGE_SIZE); + mapsize = ((mapsize / 2) + pagesize - 1) & -pagesize; + while (mapsize >= pagesize + && (mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE, + fd, 0)) == MAP_FAILED && errno == ENOMEM) + mapsize /= 2; + } + if (mapped != MAP_FAILED) + { + do + { + if (st.st_size <= (off_t) mapsize) + { + *resp = crc32 (crc, mapped, st.st_size); + munmap (mapped, mapsize); + return 0; + } + crc = crc32 (crc, mapped, mapsize); + off += mapsize; + st.st_size -= mapsize; + } while (mmap (mapped, mapsize, PROT_READ, MAP_FIXED|MAP_PRIVATE, + fd, off) == mapped); + munmap (mapped, mapsize); + } + } + + while ((count = TEMP_FAILURE_RETRY (pread (fd, buffer, sizeof buffer, + off))) > 0) + { + off += count; + crc = crc32 (crc, buffer, count); + } + + *resp = crc; + + return count == 0 ? 0 : -1; +} diff --git a/lib/dynamicsizehash.c b/lib/dynamicsizehash.c new file mode 100644 index 00000000..1fdff1b0 --- /dev/null +++ b/lib/dynamicsizehash.c @@ -0,0 +1,332 @@ +/* Copyright (C) 2000-2010 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <stdlib.h> +#include <system.h> + +/* Before including this file the following macros must be defined: + + NAME name of the hash table structure. + TYPE data type of the hash table entries + COMPARE comparison function taking two pointers to TYPE objects + + The following macros if present select features: + + ITERATE iterating over the table entries is possible + REVERSE iterate in reverse order of insert + */ + + +static size_t +lookup (htab, hval, val) + NAME *htab; + HASHTYPE hval; + TYPE val __attribute__ ((unused)); +{ + /* First hash function: simply take the modul but prevent zero. Small values + can skip the division, which helps performance when this is common. */ + size_t idx = 1 + (hval < htab->size ? hval : hval % htab->size); + + if (htab->table[idx].hashval != 0) + { + HASHTYPE hash; + + if (htab->table[idx].hashval == hval + && COMPARE (htab->table[idx].data, val) == 0) + return idx; + + /* Second hash function as suggested in [Knuth]. */ + hash = 1 + hval % (htab->size - 2); + + do + { + if (idx <= hash) + idx = htab->size + idx - hash; + else + idx -= hash; + + /* If entry is found use it. */ + if (htab->table[idx].hashval == hval + && COMPARE (htab->table[idx].data, val) == 0) + return idx; + } + while (htab->table[idx].hashval); + } + return idx; +} + + +static void +insert_entry_2 (NAME *htab, HASHTYPE hval, size_t idx, TYPE data) +{ +#ifdef ITERATE + if (htab->table[idx].hashval == 0) + { +# ifdef REVERSE + htab->table[idx].next = htab->first; + htab->first = &htab->table[idx]; +# else + /* Add the new value to the list. */ + if (htab->first == NULL) + htab->first = htab->table[idx].next = &htab->table[idx]; + else + { + htab->table[idx].next = htab->first->next; + htab->first = htab->first->next = &htab->table[idx]; + } +# endif + } +#endif + + htab->table[idx].hashval = hval; + htab->table[idx].data = data; + + ++htab->filled; + if (100 * htab->filled > 90 * htab->size) + { + /* Table is filled more than 90%. Resize the table. */ +#ifdef ITERATE + __typeof__ (htab->first) first; +# ifndef REVERSE + __typeof__ (htab->first) runp; +# endif +#else + size_t old_size = htab->size; +#endif +#define _TABLE(name) \ + name##_ent *table = htab->table +#define TABLE(name) _TABLE (name) + TABLE(NAME); + + htab->size = next_prime (htab->size * 2); + htab->filled = 0; +#ifdef ITERATE + first = htab->first; + htab->first = NULL; +#endif + htab->table = calloc ((1 + htab->size), sizeof (htab->table[0])); + if (htab->table == NULL) + { + /* We cannot enlarge the table. Live with what we got. This + might lead to an infinite loop at some point, though. */ + htab->table = table; + return; + } + + /* Add the old entries to the new table. When iteration is + supported we maintain the order. */ +#ifdef ITERATE +# ifdef REVERSE + while (first != NULL) + { + insert_entry_2 (htab, first->hashval, + lookup (htab, first->hashval, first->data), + first->data); + + first = first->next; + } +# else + assert (first != NULL); + runp = first = first->next; + do + insert_entry_2 (htab, runp->hashval, + lookup (htab, runp->hashval, runp->data), runp->data); + while ((runp = runp->next) != first); +# endif +#else + for (idx = 1; idx <= old_size; ++idx) + if (table[idx].hashval != 0) + insert_entry_2 (htab, table[idx].hashval, + lookup (htab, table[idx].hashval, table[idx].data), + table[idx].data); +#endif + + free (table); + } +} + + +int +#define INIT(name) _INIT (name) +#define _INIT(name) \ + name##_init +INIT(NAME) (htab, init_size) + NAME *htab; + size_t init_size; +{ + /* We need the size to be a prime. */ + init_size = next_prime (init_size); + + /* Initialize the data structure. */ + htab->size = init_size; + htab->filled = 0; +#ifdef ITERATE + htab->first = NULL; +#endif + htab->table = (void *) calloc ((init_size + 1), sizeof (htab->table[0])); + if (htab->table == NULL) + return -1; + + return 0; +} + + +int +#define FREE(name) _FREE (name) +#define _FREE(name) \ + name##_free +FREE(NAME) (htab) + NAME *htab; +{ + free (htab->table); + return 0; +} + + +int +#define INSERT(name) _INSERT (name) +#define _INSERT(name) \ + name##_insert +INSERT(NAME) (htab, hval, data) + NAME *htab; + HASHTYPE hval; + TYPE data; +{ + size_t idx; + + /* Make the hash value nonzero. */ + hval = hval ?: 1; + + idx = lookup (htab, hval, data); + + if (htab->table[idx].hashval != 0) + /* We don't want to overwrite the old value. */ + return -1; + + /* An empty bucket has been found. */ + insert_entry_2 (htab, hval, idx, data); + return 0; +} + + +#ifdef OVERWRITE +int +#define INSERT(name) _INSERT (name) +#define _INSERT(name) \ + name##_overwrite +INSERT(NAME) (htab, hval, data) + NAME *htab; + HASHTYPE hval; + TYPE data; +{ + size_t idx; + + /* Make the hash value nonzero. */ + hval = hval ?: 1; + + idx = lookup (htab, hval, data); + + /* The correct bucket has been found. */ + insert_entry_2 (htab, hval, idx, data); + return 0; +} +#endif + + +TYPE +#define FIND(name) _FIND (name) +#define _FIND(name) \ + name##_find +FIND(NAME) (htab, hval, val) + NAME *htab; + HASHTYPE hval; + TYPE val; +{ + size_t idx; + + /* Make the hash value nonzero. */ + hval = hval ?: 1; + + idx = lookup (htab, hval, val); + + if (htab->table[idx].hashval == 0) + return NULL; + + return htab->table[idx].data; +} + + +#ifdef ITERATE +# define ITERATEFCT(name) _ITERATEFCT (name) +# define _ITERATEFCT(name) \ + name##_iterate +TYPE +ITERATEFCT(NAME) (htab, ptr) + NAME *htab; + void **ptr; +{ + void *p = *ptr; + +# define TYPENAME(name) _TYPENAME (name) +# define _TYPENAME(name) name##_ent + +# ifdef REVERSE + if (p == NULL) + p = htab->first; + else + p = ((TYPENAME(NAME) *) p)->next; + + if (p == NULL) + { + *ptr = NULL; + return NULL; + } +# else + if (p == NULL) + { + if (htab->first == NULL) + return NULL; + p = htab->first->next; + } + else + { + if (p == htab->first) + return NULL; + + p = ((TYPENAME(NAME) *) p)->next; + } +# endif + + /* Prepare the next element. If possible this will pull the data + into the cache, for reading. */ + __builtin_prefetch (((TYPENAME(NAME) *) p)->next, 0, 2); + + return ((TYPENAME(NAME) *) (*ptr = p))->data; +} +#endif diff --git a/lib/dynamicsizehash.h b/lib/dynamicsizehash.h new file mode 100644 index 00000000..ccd41d0f --- /dev/null +++ b/lib/dynamicsizehash.h @@ -0,0 +1,127 @@ +/* Copyright (C) 2000-2010 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <stddef.h> + +/* Before including this file the following macros must be defined: + + NAME name of the hash table structure. + TYPE data type of the hash table entries + + The following macros if present select features: + + ITERATE iterating over the table entries is possible + HASHTYPE integer type for hash values, default unsigned long int + */ + + +/* Optionally include an entry pointing to the first used entry. */ +#ifdef ITERATE +# define FIRST(name) name##_ent *first; +# define NEXT(name) struct name##_ent *next; +#else +# define FIRST(name) +# define NEXT(name) +#endif + +#ifndef HASHTYPE +# define HASHTYPE unsigned long int +#endif + + +/* Defined separately. */ +extern size_t next_prime (size_t seed); + + +/* Table entry type. */ +#define _DYNHASHENTTYPE(name) \ + typedef struct name##_ent \ + { \ + HASHTYPE hashval; \ + TYPE data; \ + NEXT (name) \ + } name##_ent +#define DYNHASHENTTYPE(name) _DYNHASHENTTYPE (name) +DYNHASHENTTYPE (NAME); + + +/* Type of the dynamic hash table data structure. */ +#define _DYNHASHTYPE(name) \ +typedef struct \ +{ \ + size_t size; \ + size_t filled; \ + name##_ent *table; \ + FIRST (name) \ +} name +#define DYNHASHTYPE(name) _DYNHASHTYPE (name) +DYNHASHTYPE (NAME); + + + +#define _FUNCTIONS(name) \ +/* Initialize the hash table. */ \ +extern int name##_init (name *htab, size_t init_size); \ + \ +/* Free resources allocated for hash table. */ \ +extern int name##_free (name *htab); \ + \ +/* Insert new entry. */ \ +extern int name##_insert (name *htab, HASHTYPE hval, TYPE data); \ + \ +/* Insert new entry, possibly overwrite old entry. */ \ +extern int name##_overwrite (name *htab, HASHTYPE hval, TYPE data); \ + \ +/* Find entry in hash table. */ \ +extern TYPE name##_find (name *htab, HASHTYPE hval, TYPE val); +#define FUNCTIONS(name) _FUNCTIONS (name) +FUNCTIONS (NAME) + + +#ifdef ITERATE +# define _XFUNCTIONS(name) \ +/* Get next element in table. */ \ +extern TYPE name##_iterate (name *htab, void **ptr); +# define XFUNCTIONS(name) _XFUNCTIONS (name) +XFUNCTIONS (NAME) +#endif + +#ifndef NO_UNDEF +# undef DYNHASHENTTYPE +# undef DYNHASHTYPE +# undef FUNCTIONS +# undef _FUNCTIONS +# undef XFUNCTIONS +# undef _XFUNCTIONS +# undef NAME +# undef TYPE +# undef ITERATE +# undef COMPARE +# undef FIRST +# undef NEXT +#endif diff --git a/lib/eu-config.h b/lib/eu-config.h new file mode 100644 index 00000000..3afff26a --- /dev/null +++ b/lib/eu-config.h @@ -0,0 +1,189 @@ +/* Configuration definitions. + Copyright (C) 2008, 2009 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifndef EU_CONFIG_H +#define EU_CONFIG_H 1 + +#ifdef USE_LOCKS +# include <pthread.h> +# include <assert.h> +# define rwlock_define(class,name) class pthread_rwlock_t name +# define RWLOCK_CALL(call) \ + ({ int _err = pthread_rwlock_ ## call; assert_perror (_err); }) +# define rwlock_init(lock) RWLOCK_CALL (init (&lock, NULL)) +# define rwlock_fini(lock) RWLOCK_CALL (destroy (&lock)) +# define rwlock_rdlock(lock) RWLOCK_CALL (rdlock (&lock)) +# define rwlock_wrlock(lock) RWLOCK_CALL (wrlock (&lock)) +# define rwlock_unlock(lock) RWLOCK_CALL (unlock (&lock)) +#else +/* Eventually we will allow multi-threaded applications to use the + libraries. Therefore we will add the necessary locking although + the macros used expand to nothing for now. */ +# define rwlock_define(class,name) class int name +# define rwlock_init(lock) ((void) (lock)) +# define rwlock_fini(lock) ((void) (lock)) +# define rwlock_rdlock(lock) ((void) (lock)) +# define rwlock_wrlock(lock) ((void) (lock)) +# define rwlock_unlock(lock) ((void) (lock)) +#endif /* USE_LOCKS */ + +/* gettext helper macro. */ +#define N_(Str) Str + +/* Compiler-specific definitions. */ +#define strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); + +#ifdef __i386__ +# define internal_function __attribute__ ((regparm (3), stdcall)) +#else +# define internal_function /* nothing */ +#endif + +#define internal_strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))) internal_function; + +#define attribute_hidden \ + __attribute__ ((visibility ("hidden"))) + +/* Define ALLOW_UNALIGNED if the architecture allows operations on + unaligned memory locations. */ +#if defined __i386__ || defined __x86_64__ +# define ALLOW_UNALIGNED 1 +#else +# define ALLOW_UNALIGNED 0 +#endif + +#if DEBUGPRED +# ifdef __x86_64__ +asm (".section predict_data, \"aw\"; .previous\n" + ".section predict_line, \"a\"; .previous\n" + ".section predict_file, \"a\"; .previous"); +# ifndef PIC +# define debugpred__(e, E) \ + ({ long int _e = !!(e); \ + asm volatile (".pushsection predict_data; ..predictcnt%=: .quad 0; .quad 0\n" \ + ".section predict_line; .quad %c1\n" \ + ".section predict_file; .quad %c2; .popsection\n" \ + "addq $1,..predictcnt%=(,%0,8)" \ + : : "r" (_e == E), "i" (__LINE__), "i" (__FILE__)); \ + __builtin_expect (_e, E); \ + }) +# endif +# elif defined __i386__ +asm (".section predict_data, \"aw\"; .previous\n" + ".section predict_line, \"a\"; .previous\n" + ".section predict_file, \"a\"; .previous"); +# ifndef PIC +# define debugpred__(e, E) \ + ({ long int _e = !!(e); \ + asm volatile (".pushsection predict_data; ..predictcnt%=: .long 0; .long 0\n" \ + ".section predict_line; .long %c1\n" \ + ".section predict_file; .long %c2; .popsection\n" \ + "incl ..predictcnt%=(,%0,8)" \ + : : "r" (_e == E), "i" (__LINE__), "i" (__FILE__)); \ + __builtin_expect (_e, E); \ + }) +# endif +# endif +# ifdef debugpred__ +# define unlikely(e) debugpred__ (e,0) +# define likely(e) debugpred__ (e,1) +# endif +#endif +#ifndef likely +# define unlikely(expr) __builtin_expect (!!(expr), 0) +# define likely(expr) __builtin_expect (!!(expr), 1) +#endif + +#define obstack_calloc(ob, size) \ + ({ size_t _s = (size); memset (obstack_alloc (ob, _s), '\0', _s); }) +#define obstack_strdup(ob, str) \ + ({ const char *_s = (str); obstack_copy0 (ob, _s, strlen (_s)); }) +#define obstack_strndup(ob, str, n) \ + ({ const char *_s = (str); obstack_copy0 (ob, _s, strnlen (_s, n)); }) + +#if __STDC_VERSION__ >= 199901L +# define flexarr_size /* empty */ +#else +# define flexarr_size 0 +#endif + +/* Calling conventions. */ +#ifdef __i386__ +# define CALLING_CONVENTION regparm (3), stdcall +# define AND_CALLING_CONVENTION , regparm (3), stdcall +#else +# define CALLING_CONVENTION +# define AND_CALLING_CONVENTION +#endif + +/* Avoid PLT entries. */ +#ifdef PIC +# define INTUSE(name) _INTUSE(name) +# define _INTUSE(name) __##name##_internal +# define INTDEF(name) _INTDEF(name) +# define _INTDEF(name) \ + extern __typeof__ (name) __##name##_internal __attribute__ ((alias (#name))); +# define INTDECL(name) _INTDECL(name) +# define _INTDECL(name) \ + extern __typeof__ (name) __##name##_internal attribute_hidden; +#else +# define INTUSE(name) name +# define INTDEF(name) /* empty */ +# define INTDECL(name) /* empty */ +#endif + +/* This macro is used by the tests conditionalize for standalone building. */ +#define ELFUTILS_HEADER(name) <lib##name.h> + + +#ifdef SHARED +# define OLD_VERSION(name, version) \ + asm (".globl _compat." #version "." #name "\n" \ + "_compat." #version "." #name " = " #name "\n" \ + ".symver _compat." #version "." #name "," #name "@" #version); +# define NEW_VERSION(name, version) \ + asm (".symver " #name "," #name "@@@" #version); +# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \ + asm (".symver _compat." #version "." #name "," #name "@" #version); \ + __typeof (_compat_##prefix##_##name) _compat_##prefix##_##name \ + asm ("_compat." #version "." #name); +# define COMPAT_VERSION(name, version, prefix) \ + asm (".symver _compat." #version "." #name "," #name "@" #version); \ + __typeof (name) _compat_##prefix##_##name asm ("_compat." #version "." #name); +#else +# define OLD_VERSION(name, version) /* Nothing for static linking. */ +# define NEW_VERSION(name, version) /* Nothing for static linking. */ +# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \ + error "should use #ifdef SHARED" +# define COMPAT_VERSION(name, version, prefix) error "should use #ifdef SHARED" +#endif + + +#endif /* eu-config.h */ diff --git a/lib/fixedsizehash.h b/lib/fixedsizehash.h new file mode 100644 index 00000000..06ce6a25 --- /dev/null +++ b/lib/fixedsizehash.h @@ -0,0 +1,267 @@ +/* Fixed size hash table with internal linking. + Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <sys/cdefs.h> +#include <sys/param.h> + +#include <system.h> + +#define CONCAT(t1,t2) __CONCAT (t1,t2) + +/* Before including this file the following macros must be defined: + + TYPE data type of the hash table entries + HASHFCT name of the hashing function to use + HASHTYPE type used for the hashing value + COMPARE comparison function taking two pointers to TYPE objects + CLASS can be defined to `static' to avoid exporting the functions + PREFIX prefix to be used for function and data type names + STORE_POINTER if defined the table stores a pointer and not an element + of type TYPE + INSERT_HASH if defined alternate insert function which takes a hash + value is defined + NO_FINI_FCT if defined the fini function is not defined +*/ + + +/* Defined separately. */ +extern size_t next_prime (size_t seed); + + +/* Set default values. */ +#ifndef HASHTYPE +# define HASHTYPE size_t +#endif + +#ifndef CLASS +# define CLASS +#endif + +#ifndef PREFIX +# define PREFIX +#endif + + +/* The data structure. */ +struct CONCAT(PREFIX,fshash) +{ + size_t nslots; + struct CONCAT(PREFIX,fshashent) + { + HASHTYPE hval; +#ifdef STORE_POINTER +# define ENTRYP(el) (el).entry + TYPE *entry; +#else +# define ENTRYP(el) &(el).entry + TYPE entry; +#endif + } table[0]; +}; + + +/* Constructor for the hashing table. */ +CLASS struct CONCAT(PREFIX,fshash) * +CONCAT(PREFIX,fshash_init) (size_t nelems) +{ + struct CONCAT(PREFIX,fshash) *result; + /* We choose a size for the hashing table 150% over the number of + entries. This will guarantee short medium search lengths. */ + const size_t max_size_t = ~((size_t) 0); + + if (nelems >= (max_size_t / 3) * 2) + { + errno = EINVAL; + return NULL; + } + + /* Adjust the size to be used for the hashing table. */ + nelems = next_prime (MAX ((nelems * 3) / 2, 10)); + + /* Allocate the data structure for the result. */ + result = (struct CONCAT(PREFIX,fshash) *) + xcalloc (sizeof (struct CONCAT(PREFIX,fshash)) + + (nelems + 1) * sizeof (struct CONCAT(PREFIX,fshashent)), 1); + if (result == NULL) + return NULL; + + result->nslots = nelems; + + return result; +} + + +#ifndef NO_FINI_FCT +CLASS void +CONCAT(PREFIX,fshash_fini) (struct CONCAT(PREFIX,fshash) *htab) +{ + free (htab); +} +#endif + + +static struct CONCAT(PREFIX,fshashent) * +CONCAT(PREFIX,fshash_lookup) (struct CONCAT(PREFIX,fshash) *htab, + HASHTYPE hval, TYPE *data) +{ + size_t idx = 1 + hval % htab->nslots; + + if (htab->table[idx].hval != 0) + { + HASHTYPE hash; + + /* See whether this is the same entry. */ + if (htab->table[idx].hval == hval + && COMPARE (data, ENTRYP (htab->table[idx])) == 0) + return &htab->table[idx]; + + /* Second hash function as suggested in [Knuth]. */ + hash = 1 + hval % (htab->nslots - 2); + + do + { + if (idx <= hash) + idx = htab->nslots + idx - hash; + else + idx -= hash; + + if (htab->table[idx].hval == hval + && COMPARE (data, ENTRYP(htab->table[idx])) == 0) + return &htab->table[idx]; + } + while (htab->table[idx].hval != 0); + } + + return &htab->table[idx]; +} + + +CLASS int +__attribute__ ((unused)) +CONCAT(PREFIX,fshash_insert) (struct CONCAT(PREFIX,fshash) *htab, + const char *str, + size_t len __attribute__ ((unused)), TYPE *data) +{ + HASHTYPE hval = HASHFCT (str, len ?: strlen (str)); + struct CONCAT(PREFIX,fshashent) *slot; + + slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data); + if (slot->hval != 0) + /* We don't want to overwrite the old value. */ + return -1; + + slot->hval = hval; +#ifdef STORE_POINTER + slot->entry = data; +#else + slot->entry = *data; +#endif + + return 0; +} + + +#ifdef INSERT_HASH +CLASS int +__attribute__ ((unused)) +CONCAT(PREFIX,fshash_insert_hash) (struct CONCAT(PREFIX,fshash) *htab, + HASHTYPE hval, TYPE *data) +{ + struct CONCAT(PREFIX,fshashent) *slot; + + slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data); + if (slot->hval != 0) + /* We don't want to overwrite the old value. */ + return -1; + + slot->hval = hval; +#ifdef STORE_POINTER + slot->entry = data; +#else + slot->entry = *data; +#endif + + return 0; +} +#endif + + +CLASS int +__attribute__ ((unused)) +CONCAT(PREFIX,fshash_overwrite) (struct CONCAT(PREFIX,fshash) *htab, + const char *str, + size_t len __attribute__ ((unused)), + TYPE *data) +{ + HASHTYPE hval = HASHFCT (str, len ?: strlen (str)); + struct CONCAT(PREFIX,fshashent) *slot; + + slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data); + slot->hval = hval; +#ifdef STORE_POINTER + slot->entry = data; +#else + slot->entry = *data; +#endif + + return 0; +} + + +CLASS const TYPE * +CONCAT(PREFIX,fshash_find) (const struct CONCAT(PREFIX,fshash) *htab, + const char *str, + size_t len __attribute__ ((unused)), TYPE *data) +{ + HASHTYPE hval = HASHFCT (str, len ?: strlen (str)); + struct CONCAT(PREFIX,fshashent) *slot; + + slot = CONCAT(PREFIX,fshash_lookup) ((struct CONCAT(PREFIX,fshash) *) htab, + hval, data); + if (slot->hval == 0) + /* Not found. */ + return NULL; + + return ENTRYP(*slot); +} + + +/* Unset the macros we expect. */ +#undef TYPE +#undef HASHFCT +#undef HASHTYPE +#undef COMPARE +#undef CLASS +#undef PREFIX +#undef INSERT_HASH +#undef STORE_POINTER +#undef NO_FINI_FCT diff --git a/lib/list.h b/lib/list.h new file mode 100644 index 00000000..fc5c73cd --- /dev/null +++ b/lib/list.h @@ -0,0 +1,100 @@ +/* Copyright (C) 2001, 2002, 2003 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2001. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifndef LIST_H +#define LIST_H 1 + +/* Add element to the end of a circular, double-linked list. */ +#define CDBL_LIST_ADD_REAR(first, newp) \ + do { \ + __typeof (newp) _newp = (newp); \ + assert (_newp->next == NULL); \ + assert (_newp->previous == NULL); \ + if (unlikely ((first) == NULL)) \ + (first) = _newp->next = _newp->previous = _newp; \ + else \ + { \ + _newp->next = (first); \ + _newp->previous = (first)->previous; \ + _newp->previous->next = _newp->next->previous = _newp; \ + } \ + } while (0) + +/* Remove element from circular, double-linked list. */ +#define CDBL_LIST_DEL(first, elem) \ + do { \ + __typeof (elem) _elem = (elem); \ + /* Check whether the element is indeed on the list. */ \ + assert (first != NULL && _elem != NULL \ + && (first != elem \ + || ({ __typeof (elem) _runp = first->next; \ + while (_runp != first) \ + if (_runp == _elem) \ + break; \ + else \ + _runp = _runp->next; \ + _runp == _elem; }))); \ + if (unlikely (_elem->next == _elem)) \ + first = NULL; \ + else \ + { \ + _elem->next->previous = _elem->previous; \ + _elem->previous->next = _elem->next; \ + if (unlikely (first == _elem)) \ + first = _elem->next; \ + } \ + assert ((_elem->next = _elem->previous = NULL, 1)); \ + } while (0) + + +/* Add element to the front of a single-linked list. */ +#define SNGL_LIST_PUSH(first, newp) \ + do { \ + __typeof (newp) _newp = (newp); \ + assert (_newp->next == NULL); \ + _newp->next = first; \ + first = _newp; \ + } while (0) + + +/* Add element to the rear of a circular single-linked list. */ +#define CSNGL_LIST_ADD_REAR(first, newp) \ + do { \ + __typeof (newp) _newp = (newp); \ + assert (_newp->next == NULL); \ + if (unlikely ((first) == NULL)) \ + (first) = _newp->next = _newp; \ + else \ + { \ + _newp->next = (first)->next; \ + (first) = (first)->next = _newp; \ + } \ + } while (0) + + +#endif /* list.h */ diff --git a/lib/md5.c b/lib/md5.c new file mode 100644 index 00000000..1c27549c --- /dev/null +++ b/lib/md5.c @@ -0,0 +1,454 @@ +/* Functions to compute MD5 message digest of files or memory blocks. + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995-2011 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 1995. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include "md5.h" +#include "system.h" + +#define SWAP(n) LE32 (n) + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (ctx) + struct md5_ctx *ctx; +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 16 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 * +md5_read_ctx (ctx, resbuf) + const struct md5_ctx *ctx; + void *resbuf; +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + + return resbuf; +} + +static void +le64_copy (char *dest, uint64_t x) +{ + for (size_t i = 0; i < 8; ++i) + { + dest[i] = (uint8_t) x; + x >>= 8; + } +} + +/* 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 * +md5_finish_ctx (ctx, resbuf) + struct md5_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + md5_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. */ + const uint64_t bit_length = ((ctx->total[0] << 3) + + ((uint64_t) ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)) << 32)); + le64_copy (&ctx->buffer[bytes + pad], bit_length); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + + +#ifdef NEED_MD5_STREAM +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (stream, resblock) + FILE *stream; + void *resblock; +{ + /* Important: BLOCKSIZE must be a multiple of 64. */ +#define BLOCKSIZE 4096 + struct md5_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* 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, stream); + + sum += n; + } + while (sum < BLOCKSIZE && n != 0); + if (n == 0 && ferror (stream)) + return 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); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + return 0; +} +#endif + + +#ifdef NEED_MD5_BUFFER +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. 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. */ +void * +md5_buffer (buffer, len, resblock) + const char *buffer; + size_t len; + void *resblock; +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} +#endif + + +void +md5_process_bytes (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_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) + { + md5_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) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0) +# else +# define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0) +# endif + if (UNALIGNED_P (buffer)) + while (len > 64) + { + md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + md5_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) + { + md5_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 MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 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) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* 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. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* 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 = (w << s) | (w >> (32 - s))) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} diff --git a/lib/md5.h b/lib/md5.h new file mode 100644 index 00000000..f2d0f306 --- /dev/null +++ b/lib/md5.h @@ -0,0 +1,110 @@ +/* Declaration of functions and data types used for MD5 sum computing + library functions. + Copyright (C) 1995,1996,1997,1999-2001,2004,2005,2008 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 1995. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include <limits.h> +#include <stdint.h> +#include <stdio.h> + +#define MD5_DIGEST_SIZE 16 +#define MD5_BLOCK_SIZE 64 + +typedef uint32_t md5_uint32; +typedef uintptr_t md5_uintptr; + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); +}; + +/* + * The following three functions are build up the low level used in + * the functions `md5_stream' and `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void md5_init_ctx (struct md5_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 md5_process_block (const void *buffer, size_t len, + struct md5_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 md5_process_bytes (const void *buffer, size_t len, + struct md5_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 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 *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); + + +/* Put result from CTX in first 16 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 *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); + + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int md5_stream (FILE *stream, void *resblock); + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. 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. */ +extern void *md5_buffer (const char *buffer, size_t len, void *resblock); + +#endif /* md5.h */ diff --git a/lib/next_prime.c b/lib/next_prime.c new file mode 100644 index 00000000..f2c921e3 --- /dev/null +++ b/lib/next_prime.c @@ -0,0 +1,66 @@ +/* Determine prime number. + Copyright (C) 2006 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <stddef.h> + + +/* Test whether CANDIDATE is a prime. */ +static int +is_prime (size_t candidate) +{ + /* No even number and none less than 10 will be passed here. */ + size_t divn = 3; + size_t sq = divn * divn; + + while (sq < candidate && candidate % divn != 0) + { + size_t old_sq = sq; + ++divn; + sq += 4 * divn; + if (sq < old_sq) + return 1; + ++divn; + } + + return candidate % divn != 0; +} + + +/* We need primes for the table size. */ +size_t +next_prime (size_t seed) +{ + /* Make it definitely odd. */ + seed |= 1; + + while (!is_prime (seed)) + seed += 2; + + return seed; +} diff --git a/lib/sha1.c b/lib/sha1.c new file mode 100644 index 00000000..0e845629 --- /dev/null +++ b/lib/sha1.c @@ -0,0 +1,391 @@ +/* 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-2011 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2008. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> + +#include "sha1.h" +#include "system.h" + +#define SWAP(n) BE32 (n) + +/* 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; +} + +static void +be64_copy (char *dest, uint64_t x) +{ + for (size_t i = 8; i-- > 0; x >>= 8) + dest[i] = (uint8_t) x; +} + +/* 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. */ + const uint64_t bit_length = ((ctx->total[0] << 3) + + ((uint64_t) ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)) << 32)); + be64_copy (&ctx->buffer[bytes + pad], bit_length); + + /* 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 00000000..05301c80 --- /dev/null +++ b/lib/sha1.h @@ -0,0 +1,93 @@ +/* Declaration of functions and data types used for SHA1 sum computing + library functions. + Copyright (C) 2008 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2008. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#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 */ diff --git a/lib/system.h b/lib/system.h new file mode 100644 index 00000000..f31cfd03 --- /dev/null +++ b/lib/system.h @@ -0,0 +1,185 @@ +/* Declarations for common convenience functions. + Copyright (C) 2006-2011 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifndef LIB_SYSTEM_H +#define LIB_SYSTEM_H 1 + +#include <argp.h> +#include <stddef.h> +#include <stdint.h> +#include <endian.h> +#include <byteswap.h> +#include <unistd.h> + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define LE32(n) (n) +# define LE64(n) (n) +# define BE32(n) bswap_32 (n) +# define BE64(n) bswap_64 (n) +#elif __BYTE_ORDER == __BIG_ENDIAN +# define BE32(n) (n) +# define BE64(n) (n) +# define LE32(n) bswap_32 (n) +# define LE64(n) bswap_64 (n) +#else +# error "Unknown byte order" +#endif + +extern void *xmalloc (size_t) __attribute__ ((__malloc__)); +extern void *xcalloc (size_t, size_t) __attribute__ ((__malloc__)); +extern void *xrealloc (void *, size_t) __attribute__ ((__malloc__)); + +extern char *xstrdup (const char *) __attribute__ ((__malloc__)); +extern char *xstrndup (const char *, size_t) __attribute__ ((__malloc__)); + + +extern uint32_t crc32 (uint32_t crc, unsigned char *buf, size_t len); +extern int crc32_file (int fd, uint32_t *resp); + +/* A special gettext function we use if the strings are too short. */ +#define sgettext(Str) \ + ({ const char *__res = strrchr (gettext (Str), '|'); \ + __res ? __res + 1 : Str; }) + +#define gettext_noop(Str) Str + + +static inline ssize_t __attribute__ ((unused)) +pwrite_retry (int fd, const void *buf, size_t len, off_t off) +{ + ssize_t recvd = 0; + + do + { + ssize_t ret = TEMP_FAILURE_RETRY (pwrite (fd, buf + recvd, len - recvd, + off + recvd)); + if (ret <= 0) + return ret < 0 ? ret : recvd; + + recvd += ret; + } + while ((size_t) recvd < len); + + return recvd; +} + +static inline ssize_t __attribute__ ((unused)) +write_retry (int fd, const void *buf, size_t len) +{ + ssize_t recvd = 0; + + do + { + ssize_t ret = TEMP_FAILURE_RETRY (write (fd, buf + recvd, len - recvd)); + if (ret <= 0) + return ret < 0 ? ret : recvd; + + recvd += ret; + } + while ((size_t) recvd < len); + + return recvd; +} + +static inline ssize_t __attribute__ ((unused)) +pread_retry (int fd, void *buf, size_t len, off_t off) +{ + ssize_t recvd = 0; + + do + { + ssize_t ret = TEMP_FAILURE_RETRY (pread (fd, buf + recvd, len - recvd, + off + recvd)); + if (ret <= 0) + return ret < 0 ? ret : recvd; + + recvd += ret; + } + while ((size_t) recvd < len); + + return recvd; +} + + +/* We need define two variables, argp_program_version_hook and + argp_program_bug_address, in all programs. argp.h declares these + variables as non-const (which is correct in general). But we can + do better, it is not going to change. So we want to move them into + the .rodata section. Define macros to do the trick. */ +#define ARGP_PROGRAM_VERSION_HOOK_DEF \ + void (*const apvh) (FILE *, struct argp_state *) \ + __asm ("argp_program_version_hook") +#define ARGP_PROGRAM_BUG_ADDRESS_DEF \ + const char *const apba__ __asm ("argp_program_bug_address") + + +/* The demangler from libstdc++. */ +extern char *__cxa_demangle (const char *mangled_name, char *output_buffer, + size_t *length, int *status); + + + +/* Color handling. */ + +/* Command line parser. */ +extern const struct argp color_argp; + +/* Coloring mode. */ +enum color_enum + { + color_never = 0, + color_always, + color_auto + } __attribute__ ((packed)); +extern enum color_enum color_mode; + +/* Colors to use for the various components. */ +extern char *color_address; +extern char *color_bytes; +extern char *color_mnemonic; +extern char *color_operand1; +extern char *color_operand2; +extern char *color_operand3; +extern char *color_label; +extern char *color_undef; +extern char *color_undef_tls; +extern char *color_undef_weak; +extern char *color_symbol; +extern char *color_tls; +extern char *color_weak; + +extern const char color_off[]; + +/* A static assertion. This will cause a compile-time error if EXPR, + which must be a compile-time constant, is false. */ + +#define eu_static_assert(expr) \ + extern int never_defined_just_used_for_checking[(expr) ? 1 : -1] \ + __attribute__ ((unused)) + +#endif /* system.h */ diff --git a/lib/xmalloc.c b/lib/xmalloc.c new file mode 100644 index 00000000..27ccab95 --- /dev/null +++ b/lib/xmalloc.c @@ -0,0 +1,84 @@ +/* Convenience functions for allocation. + Copyright (C) 2006 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <error.h> +#include <libintl.h> +#include <stddef.h> +#include <stdlib.h> +#include <sys/types.h> +#include "system.h" + +#ifndef _ +# define _(str) gettext (str) +#endif + + +/* Allocate N bytes of memory dynamically, with error checking. */ +void * +xmalloc (n) + size_t n; +{ + void *p; + + p = malloc (n); + if (p == NULL) + error (EXIT_FAILURE, 0, _("memory exhausted")); + return p; +} + + +/* Allocate memory for N elements of S bytes, with error checking. */ +void * +xcalloc (n, s) + size_t n, s; +{ + void *p; + + p = calloc (n, s); + if (p == NULL) + error (EXIT_FAILURE, 0, _("memory exhausted")); + return p; +} + + +/* Change the size of an allocated block of memory P to N bytes, + with error checking. */ +void * +xrealloc (p, n) + void *p; + size_t n; +{ + p = realloc (p, n); + if (p == NULL) + error (EXIT_FAILURE, 0, _("memory exhausted")); + return p; +} diff --git a/lib/xstrdup.c b/lib/xstrdup.c new file mode 100644 index 00000000..d9d6010c --- /dev/null +++ b/lib/xstrdup.c @@ -0,0 +1,43 @@ +/* Convenience function for string allocation. + Copyright (C) 2006 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include "system.h" + + +/* Return a newly allocated copy of STRING. */ +char * +xstrdup (string) + const char *string; +{ + return strcpy (xmalloc (strlen (string) + 1), string); +} diff --git a/lib/xstrndup.c b/lib/xstrndup.c new file mode 100644 index 00000000..52304e65 --- /dev/null +++ b/lib/xstrndup.c @@ -0,0 +1,47 @@ +/* Convenience function for string allocation. + Copyright (C) 2006 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include "system.h" + + +/* Return a newly allocated copy of STRING. */ +char * +xstrndup (string, n) + const char *string; + size_t n; +{ + char *res; + size_t len = strnlen (string, n); + *((char *) mempcpy ((res = xmalloc (len + 1)), string, len)) = '\0'; + return res; +} |