diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-cache.c | 5 | ||||
-rw-r--r-- | elf/dl-hwcaps.c | 11 | ||||
-rw-r--r-- | elf/dl-hwcaps.h | 31 | ||||
-rw-r--r-- | elf/dl-support.c | 2 | ||||
-rw-r--r-- | elf/rtld.c | 4 |
5 files changed, 50 insertions, 3 deletions
diff --git a/elf/dl-cache.c b/elf/dl-cache.c index 017c78aae3..e9632da0b3 100644 --- a/elf/dl-cache.c +++ b/elf/dl-cache.c @@ -24,6 +24,7 @@ #include <dl-procinfo.h> #include <stdint.h> #include <_itoa.h> +#include <dl-hwcaps.h> #ifndef _DL_PLATFORMS_COUNT # define _DL_PLATFORMS_COUNT 0 @@ -258,8 +259,10 @@ _dl_load_cache_lookup (const char *name) if (platform != (uint64_t) -1) platform = 1ULL << platform; + uint64_t hwcap_mask = GET_HWCAP_MASK(); + #define _DL_HWCAP_TLS_MASK (1LL << 63) - uint64_t hwcap_exclude = ~((GLRO(dl_hwcap) & GLRO(dl_hwcap_mask)) + uint64_t hwcap_exclude = ~((GLRO(dl_hwcap) & hwcap_mask) | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK); /* Only accept hwcap if it's for the right platform. */ diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c index c437397a88..ac50fd2c38 100644 --- a/elf/dl-hwcaps.c +++ b/elf/dl-hwcaps.c @@ -24,6 +24,7 @@ #include <ldsodefs.h> #include <dl-procinfo.h> +#include <dl-hwcaps.h> #ifdef _DL_FIRST_PLATFORM # define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT) @@ -37,8 +38,9 @@ internal_function _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, size_t *max_capstrlen) { + uint64_t hwcap_mask = GET_HWCAP_MASK(); /* Determine how many important bits are set. */ - uint64_t masked = GLRO(dl_hwcap) & GLRO(dl_hwcap_mask); + uint64_t masked = GLRO(dl_hwcap) & hwcap_mask; size_t cnt = platform != NULL; size_t n, m; size_t total; @@ -125,7 +127,12 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, LD_HWCAP_MASK environment variable (or default HWCAP_IMPORTANT). So there is no way to request ignoring an OS-supplied dsocap string and bit like you can ignore an OS-supplied HWCAP bit. */ - GLRO(dl_hwcap_mask) |= (uint64_t) mask << _DL_FIRST_EXTRA; + hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA; +#if HAVE_TUNABLES + TUNABLE_SET (glibc, tune, hwcap_mask, uint64_t, hwcap_mask); +#else + GLRO(dl_hwcap_mask) = hwcap_mask; +#endif size_t len; for (const char *p = dsocaps; p < dsocaps + dsocapslen; p += len + 1) { diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h new file mode 100644 index 0000000000..9ce33173f1 --- /dev/null +++ b/elf/dl-hwcaps.h @@ -0,0 +1,31 @@ +/* Hardware capability support for run-time dynamic loader. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <elf/dl-tunables.h> + +#ifdef SHARED +# if HAVE_TUNABLES +# define GET_HWCAP_MASK() \ + TUNABLE_GET (glibc, tune, hwcap_mask, uint64_t, NULL) +# else +# define GET_HWCAP_MASK() GLRO(dl_hwcap_mask) +# endif +#else +/* HWCAP_MASK is ignored in static binaries. */ +# define GET_HWCAP_MASK() (0) +#endif diff --git a/elf/dl-support.c b/elf/dl-support.c index 3c46a7a481..c22be854f4 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -164,6 +164,7 @@ uint64_t _dl_hwcap2 __attribute__ ((nocommon)); /* The value of the FPU control word the kernel will preset in hardware. */ fpu_control_t _dl_fpu_control = _FPU_DEFAULT; +#if !HAVE_TUNABLES /* This is not initialized to HWCAP_IMPORTANT, matching the definition of _dl_important_hwcaps, below, where no hwcap strings are ever used. This mask is still used to mediate the lookups in the cache @@ -171,6 +172,7 @@ fpu_control_t _dl_fpu_control = _FPU_DEFAULT; LD_HWCAP_MASK environment variable here), there is no real point in setting _dl_hwcap nonzero below, but we do anyway. */ uint64_t _dl_hwcap_mask __attribute__ ((nocommon)); +#endif /* Prevailing state of the stack. Generally this includes PF_X, indicating it's * executable but this isn't true for all platforms. */ diff --git a/elf/rtld.c b/elf/rtld.c index 319ef062d4..3746653afb 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -159,7 +159,9 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = ._dl_debug_fd = STDERR_FILENO, ._dl_use_load_bias = -2, ._dl_correct_cache_id = _DL_CACHE_DEFAULT_ID, +#if !HAVE_TUNABLES ._dl_hwcap_mask = HWCAP_IMPORTANT, +#endif ._dl_lazy = 1, ._dl_fpu_control = _FPU_DEFAULT, ._dl_pagesize = EXEC_PAGESIZE, @@ -2402,6 +2404,7 @@ process_envvars (enum mode *modep) _dl_show_auxv (); break; +#if !HAVE_TUNABLES case 10: /* Mask for the important hardware capabilities. */ if (!__libc_enable_secure @@ -2409,6 +2412,7 @@ process_envvars (enum mode *modep) GLRO(dl_hwcap_mask) = __strtoul_internal (&envline[11], NULL, 0, 0); break; +#endif case 11: /* Path where the binary is found. */ |