From 323a2c0d2c6222bfc0280986340f1167e00cc81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= Date: Mon, 19 Jan 2015 21:16:27 +0100 Subject: Moved fat declarations and macros to fat-setup.h. --- ChangeLog | 7 +++ Makefile.in | 2 +- fat-setup.h | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fat-x86_64.c | 118 ++------------------------------------------------ 4 files changed, 150 insertions(+), 116 deletions(-) create mode 100644 fat-setup.h diff --git a/ChangeLog b/ChangeLog index de1bc50d..03be2018 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2015-01-19 Niels Möller + + * Makefile.in (DISTFILES): Added fat-setup.h. + + * fat-setup.h: New file, declarations moved from... + * fat-x86_64.c: ... old location + 2015-01-17 Niels Möller * fat-x86_64.c (DECLARE_FAT_FUNC, DEFINE_FAT_FUNC) diff --git a/Makefile.in b/Makefile.in index 474b5b89..216ba3d4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -219,7 +219,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h getopt_int.h \ aes-internal.h camellia-internal.h serpent-internal.h \ cast128_sboxes.h desinfo.h desCode.h \ memxor-internal.h nettle-internal.h nettle-write.h \ - gmp-glue.h ecc-internal.h \ + gmp-glue.h ecc-internal.h fat-setup.h \ mini-gmp.h mini-gmp.c asm.m4 \ nettle.texinfo nettle.info nettle.html nettle.pdf sha-example.c diff --git a/fat-setup.h b/fat-setup.h new file mode 100644 index 00000000..70ff9b6f --- /dev/null +++ b/fat-setup.h @@ -0,0 +1,139 @@ +/* fat-setup.h + + Copyright (C) 2015 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle 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. + + GNU Nettle 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/. +*/ + +/* Fat library initialization works as follows. The main function is + fat_init. It tries to do initialization only once, but since it is + idempotent and pointer updates are atomic on x86_64, there's no + harm if it is in some cases called multiple times from several + threads. + + The fat_init function checks the cpuid flags, and sets function + pointers, e.g, _nettle_aes_encrypt_vec, to point to the appropriate + implementation. + + To get everything hooked in, we use a belt-and-suspenders approach. + + We try to register fat_init as a constructor function to be called + at load time. If this is unavailable or non-working, we instead + arrange fat_init to be called lazily. + + For the actual indirection, there are two cases. + + If ifunc support is available, function pointers are statically + initialized to NULL, and we register resolver functions, e.g., + _nettle_aes_encrypt_resolve, which call fat_init, and then return + the function pointer, e.g., the value of _nettle_aes_encrypt_vec. + + If ifunc is not available, we have to define a wrapper function to + jump via the function pointer. (FIXME: For internal calls, we could + do this as a macro). We statically initialize each function pointer + to point to a special initialization function, e.g., + _nettle_aes_encrypt_init, which calls fat_init, and then invokes + the right function. This way, all pointers are setup correctly at + the first call to any fat function. +*/ + +#if HAVE_GCC_ATTRIBUTE +# define CONSTRUCTOR __attribute__ ((constructor)) +#else +# define CONSTRUCTOR +# if defined (__sun) +# pragma init(fat_init) +# endif +#endif + +#define ENV_VERBOSE "NETTLE_FAT_VERBOSE" + +/* DECLARE_FAT_FUNC(name, ftype) + * + * name is the public function, e.g., _nettle_aes_encrypt. + * ftype is its type, e.g., aes_crypt_internal_func. + * + * DECLARE_FAT_VAR(name, type, var) + * + * name is name without _nettle prefix. + * type is its type. + * var is the variant, used as a suffix on the symbol name. + * + * DEFINE_FAT_FUNC(name, rtype, prototype, args) + * + * name is the public function. + * rtype its return type. + * prototype is the list of formal arguments, with types. + * args contain the argument list without any types. + */ + +#if HAVE_LINK_IFUNC +#define IFUNC(resolve) __attribute__ ((ifunc (resolve))) +#define DECLARE_FAT_FUNC(name, ftype) \ + ftype name IFUNC(#name"_resolve"); \ + static ftype *name##_vec = NULL; + +#define DEFINE_FAT_FUNC(name, rtype, prototype, args) \ + static void_func * name##_resolve(void) \ + { \ + if (getenv (ENV_VERBOSE)) \ + fprintf (stderr, "libnettle: "#name"_resolve\n"); \ + fat_init(); \ + return (void_func *) name##_vec; \ + } + +#else /* !HAVE_LINK_IFUNC */ +#define DECLARE_FAT_FUNC(name, ftype) \ + ftype name; \ + static ftype name##_init; \ + static ftype *name##_vec = name##_init; + +#define DEFINE_FAT_FUNC(name, rtype, prototype, args) \ + rtype name prototype \ + { \ + return name##_vec args; \ + } \ + static rtype name##_init prototype { \ + if (getenv (ENV_VERBOSE)) \ + fprintf (stderr, "libnettle: "#name"_init\n"); \ + fat_init(); \ + assert (name##_vec != name##_init); \ + return name##_vec args; \ + } +#endif /* !HAVE_LINK_IFUNC */ + +#define DECLARE_FAT_FUNC_VAR(name, type, var) \ + type _nettle_##name##_##var; + +typedef void void_func (void); + +typedef void aes_crypt_internal_func (unsigned rounds, const uint32_t *keys, + const struct aes_table *T, + size_t length, uint8_t *dst, + const uint8_t *src); + +typedef void *(memxor_func)(void *dst, const void *src, size_t n); diff --git a/fat-x86_64.c b/fat-x86_64.c index cd67f366..6aab9748 100644 --- a/fat-x86_64.c +++ b/fat-x86_64.c @@ -41,121 +41,11 @@ #include "nettle-types.h" #include "aes-internal.h" - -/* Fat library initialization works as follows. The main function is - fat_init. It tries to do initialization only once, but since it is - idempotent and pointer updates are atomic on x86_64, there's no - harm if it is in some cases called multiple times from several - threads. - - The fat_init function checks the cpuid flags, and sets function - pointers, e.g, _nettle_aes_encrypt_vec, to point to the appropriate - implementation. - - To get everything hooked in, we use a belt-and-suspenders approach. - - We try to register fat_init as a constructor function to be called - at load time. If this is unavailable or non-working, we instead - arrange fat_init to be called lazily. - - For the actual indirection, there are two cases. - - If ifunc support is available, function pointers are statically - initialized to NULL, and we register resolver functions, e.g., - _nettle_aes_encrypt_resolve, which call fat_init, and then return - the function pointer, e.g., the value of _nettle_aes_encrypt_vec. - - If ifunc is not available, we have to define a wrapper function to - jump via the function pointer. (FIXME: For internal calls, we could - do this as a macro). We statically initialize each function pointer - to point to a special initialization function, e.g., - _nettle_aes_encrypt_init, which calls fat_init, and then invokes - the right function. This way, all pointers are setup correctly at - the first call to any fat function. -*/ - -#if HAVE_LINK_IFUNC -# define IFUNC(resolve) __attribute__ ((ifunc (resolve))) -# define vec_init(f) NULL -# define FAT_BOILERPLATE() -#else -# define IFUNC(resolve) -# define vec_init(f) f##_init -#endif - -#if HAVE_GCC_ATTRIBUTE -# define CONSTRUCTOR __attribute__ ((constructor)) -#else -# define CONSTRUCTOR -# if defined (__sun) -# pragma init(fat_init) -# endif -#endif - -/* DECLARE_FAT_FUNC(name, ftype) - * - * name is the public function, e.g., _nettle_aes_encrypt. - * ftype is its type, e.g., aes_crypt_internal_func. - * - * DECLARE_FAT_VAR(name, type, var) - * - * name is name without _nettle prefix. - * type is its type. - * var is the variant, used as a suffix on the symbol name. - * - * DEFINE_FAT_FUNC(name, rtype, prototype, args) - * - * name is the public function. - * rtype its return type. - * prototype is the list of formal arguments, with types. - * args contain the argument list without any types. - */ - -#if HAVE_LINK_IFUNC -#define DECLARE_FAT_FUNC(name, ftype) \ - ftype name IFUNC(#name"_resolve"); \ - static ftype *name##_vec = NULL; - -#define DEFINE_FAT_FUNC(name, rtype, prototype, args) \ - static void_func * name##_resolve(void) \ - { \ - if (getenv ("NETTLE_FAT_VERBOSE")) \ - fprintf (stderr, "libnettle: "#name"_resolve\n"); \ - fat_init(); \ - return (void_func *) name##_vec; \ - } - -#else /* !HAVE_LINK_IFUNC */ -#define DECLARE_FAT_FUNC(name, ftype) \ - ftype name; \ - static ftype name##_init; \ - static ftype *name##_vec = name##_init; - -#define DEFINE_FAT_FUNC(name, rtype, prototype, args) \ - rtype name prototype \ - { \ - return name##_vec args; \ - } \ - static rtype name##_init prototype { \ - if (getenv ("NETTLE_FAT_VERBOSE")) \ - fprintf (stderr, "libnettle: "#name"_init\n"); \ - fat_init(); \ - assert (name##_vec != name##_init); \ - return name##_vec args; \ - } -#endif /* !HAVE_LINK_IFUNC */ - -#define DECLARE_FAT_FUNC_VAR(name, type, var) \ - type _nettle_##name##_##var; +#include "memxor.h" +#include "fat-setup.h" void _nettle_cpuid (uint32_t input, uint32_t regs[4]); -typedef void void_func (void); - -typedef void aes_crypt_internal_func (unsigned rounds, const uint32_t *keys, - const struct aes_table *T, - size_t length, uint8_t *dst, - const uint8_t *src); DECLARE_FAT_FUNC(_nettle_aes_encrypt, aes_crypt_internal_func) DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, x86_64) DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, aesni) @@ -164,8 +54,6 @@ DECLARE_FAT_FUNC(_nettle_aes_decrypt, aes_crypt_internal_func) DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, x86_64) DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, aesni) -typedef void *(memxor_func)(void *dst, const void *src, size_t n); - DECLARE_FAT_FUNC(nettle_memxor, memxor_func) DECLARE_FAT_FUNC_VAR(memxor, memxor_func, x86_64) DECLARE_FAT_FUNC_VAR(memxor, memxor_func, sse2) @@ -184,7 +72,7 @@ fat_init (void) return; /* FIXME: Replace all getenv calls by getenv_secure? */ - verbose = getenv ("NETTLE_FAT_VERBOSE") != NULL; + verbose = getenv (ENV_VERBOSE) != NULL; if (verbose) fprintf (stderr, "libnettle: fat library initialization.\n"); -- cgit v1.2.1