|
|
b1dca6 |
commit dcbc6b83eff5b9238170bdfed834ba934150895f
|
|
|
b1dca6 |
Author: Florian Weimer <fweimer@redhat.com>
|
|
|
b1dca6 |
Date: Thu May 28 10:20:56 2020 +0200
|
|
|
b1dca6 |
|
|
|
b1dca6 |
elf: Do not read hwcaps from the vDSO in ld.so
|
|
|
b1dca6 |
|
|
|
b1dca6 |
This was only ever used for the "nosegneg" flag. This approach for
|
|
|
b1dca6 |
passing hardware capability information creates a subtle dependency
|
|
|
b1dca6 |
between the kernel and userspace, and ld.so.cache contents. It seems
|
|
|
b1dca6 |
inappropriate for toady, where people expect to be able to run
|
|
|
b1dca6 |
system images which very different kernel versions.
|
|
|
b1dca6 |
|
|
|
b1dca6 |
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
|
b1dca6 |
|
|
|
b1dca6 |
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
|
|
b1dca6 |
index ecf00b457760e517..ae2e4ca7fe91d407 100644
|
|
|
b1dca6 |
--- a/elf/dl-hwcaps.c
|
|
|
b1dca6 |
+++ b/elf/dl-hwcaps.c
|
|
|
b1dca6 |
@@ -26,12 +26,6 @@
|
|
|
b1dca6 |
#include <dl-procinfo.h>
|
|
|
b1dca6 |
#include <dl-hwcaps.h>
|
|
|
b1dca6 |
|
|
|
b1dca6 |
-#ifdef _DL_FIRST_PLATFORM
|
|
|
b1dca6 |
-# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
|
|
|
b1dca6 |
-#else
|
|
|
b1dca6 |
-# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
|
|
|
b1dca6 |
-#endif
|
|
|
b1dca6 |
-
|
|
|
b1dca6 |
/* Return an array of useful/necessary hardware capability names. */
|
|
|
b1dca6 |
const struct r_strlenpair *
|
|
|
b1dca6 |
_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
|
|
b1dca6 |
@@ -52,116 +46,12 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
|
|
b1dca6 |
if ((masked & (1ULL << n)) != 0)
|
|
|
b1dca6 |
++cnt;
|
|
|
b1dca6 |
|
|
|
b1dca6 |
-#ifdef NEED_DL_SYSINFO_DSO
|
|
|
b1dca6 |
- /* The system-supplied DSO can contain a note of type 2, vendor "GNU".
|
|
|
b1dca6 |
- This gives us a list of names to treat as fake hwcap bits. */
|
|
|
b1dca6 |
-
|
|
|
b1dca6 |
- const char *dsocaps = NULL;
|
|
|
b1dca6 |
- size_t dsocapslen = 0;
|
|
|
b1dca6 |
- if (GLRO(dl_sysinfo_map) != NULL)
|
|
|
b1dca6 |
- {
|
|
|
b1dca6 |
- const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr;
|
|
|
b1dca6 |
- const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum;
|
|
|
b1dca6 |
- for (uint_fast16_t i = 0; i < phnum; ++i)
|
|
|
b1dca6 |
- if (phdr[i].p_type == PT_NOTE)
|
|
|
b1dca6 |
- {
|
|
|
b1dca6 |
- const ElfW(Addr) start = (phdr[i].p_vaddr
|
|
|
b1dca6 |
- + GLRO(dl_sysinfo_map)->l_addr);
|
|
|
b1dca6 |
- /* NB: Some PT_NOTE segment may have alignment value of 0
|
|
|
b1dca6 |
- or 1. gABI specifies that PT_NOTE segments should be
|
|
|
b1dca6 |
- aligned to 4 bytes in 32-bit objects and to 8 bytes in
|
|
|
b1dca6 |
- 64-bit objects. As a Linux extension, we also support
|
|
|
b1dca6 |
- 4 byte alignment in 64-bit objects. If p_align is less
|
|
|
b1dca6 |
- than 4, we treate alignment as 4 bytes since some note
|
|
|
b1dca6 |
- segments have 0 or 1 byte alignment. */
|
|
|
b1dca6 |
- ElfW(Addr) align = phdr[i].p_align;
|
|
|
b1dca6 |
- if (align < 4)
|
|
|
b1dca6 |
- align = 4;
|
|
|
b1dca6 |
- else if (align != 4 && align != 8)
|
|
|
b1dca6 |
- continue;
|
|
|
b1dca6 |
- /* The standard ELF note layout is exactly as the anonymous struct.
|
|
|
b1dca6 |
- The next element is a variable length vendor name of length
|
|
|
b1dca6 |
- VENDORLEN (with a real length rounded to ElfW(Word)), followed
|
|
|
b1dca6 |
- by the data of length DATALEN (with a real length rounded to
|
|
|
b1dca6 |
- ElfW(Word)). */
|
|
|
b1dca6 |
- const struct
|
|
|
b1dca6 |
- {
|
|
|
b1dca6 |
- ElfW(Word) vendorlen;
|
|
|
b1dca6 |
- ElfW(Word) datalen;
|
|
|
b1dca6 |
- ElfW(Word) type;
|
|
|
b1dca6 |
- } *note = (const void *) start;
|
|
|
b1dca6 |
- while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
|
|
|
b1dca6 |
- {
|
|
|
b1dca6 |
- /* The layout of the type 2, vendor "GNU" note is as follows:
|
|
|
b1dca6 |
- .long <Number of capabilities enabled by this note>
|
|
|
b1dca6 |
- .long <Capabilities mask> (as mask >> _DL_FIRST_EXTRA).
|
|
|
b1dca6 |
- .byte <The bit number for the next capability>
|
|
|
b1dca6 |
- .asciz <The name of the capability>. */
|
|
|
b1dca6 |
- if (note->type == NT_GNU_HWCAP
|
|
|
b1dca6 |
- && note->vendorlen == sizeof "GNU"
|
|
|
b1dca6 |
- && !memcmp ((note + 1), "GNU", sizeof "GNU")
|
|
|
b1dca6 |
- && note->datalen > 2 * sizeof (ElfW(Word)) + 2)
|
|
|
b1dca6 |
- {
|
|
|
b1dca6 |
- const ElfW(Word) *p
|
|
|
b1dca6 |
- = ((const void *) note
|
|
|
b1dca6 |
- + ELF_NOTE_DESC_OFFSET (sizeof "GNU", align));
|
|
|
b1dca6 |
- cnt += *p++;
|
|
|
b1dca6 |
- ++p; /* Skip mask word. */
|
|
|
b1dca6 |
- dsocaps = (const char *) p; /* Pseudo-string "name" */
|
|
|
b1dca6 |
- dsocapslen = note->datalen - sizeof *p * 2;
|
|
|
b1dca6 |
- break;
|
|
|
b1dca6 |
- }
|
|
|
b1dca6 |
- note = ((const void *) note
|
|
|
b1dca6 |
- + ELF_NOTE_NEXT_OFFSET (note->vendorlen,
|
|
|
b1dca6 |
- note->datalen, align));
|
|
|
b1dca6 |
- }
|
|
|
b1dca6 |
- if (dsocaps != NULL)
|
|
|
b1dca6 |
- break;
|
|
|
b1dca6 |
- }
|
|
|
b1dca6 |
- }
|
|
|
b1dca6 |
-#endif
|
|
|
b1dca6 |
-
|
|
|
b1dca6 |
/* For TLS enabled builds always add 'tls'. */
|
|
|
b1dca6 |
++cnt;
|
|
|
b1dca6 |
|
|
|
b1dca6 |
/* Create temporary data structure to generate result table. */
|
|
|
b1dca6 |
struct r_strlenpair temp[cnt];
|
|
|
b1dca6 |
m = 0;
|
|
|
b1dca6 |
-#ifdef NEED_DL_SYSINFO_DSO
|
|
|
b1dca6 |
- if (dsocaps != NULL)
|
|
|
b1dca6 |
- {
|
|
|
b1dca6 |
- /* dsocaps points to the .asciz string, and -1 points to the mask
|
|
|
b1dca6 |
- .long just before the string. */
|
|
|
b1dca6 |
- const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1];
|
|
|
b1dca6 |
- GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA;
|
|
|
b1dca6 |
- /* Note that we add the dsocaps to the set already chosen by the
|
|
|
b1dca6 |
- LD_HWCAP_MASK environment variable (or default HWCAP_IMPORTANT).
|
|
|
b1dca6 |
- So there is no way to request ignoring an OS-supplied dsocap
|
|
|
b1dca6 |
- string and bit like you can ignore an OS-supplied HWCAP bit. */
|
|
|
b1dca6 |
- hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA;
|
|
|
b1dca6 |
-#if HAVE_TUNABLES
|
|
|
b1dca6 |
- TUNABLE_SET (glibc, cpu, hwcap_mask, uint64_t, hwcap_mask);
|
|
|
b1dca6 |
-#else
|
|
|
b1dca6 |
- GLRO(dl_hwcap_mask) = hwcap_mask;
|
|
|
b1dca6 |
-#endif
|
|
|
b1dca6 |
- size_t len;
|
|
|
b1dca6 |
- for (const char *p = dsocaps; p < dsocaps + dsocapslen; p += len + 1)
|
|
|
b1dca6 |
- {
|
|
|
b1dca6 |
- uint_fast8_t bit = *p++;
|
|
|
b1dca6 |
- len = strlen (p);
|
|
|
b1dca6 |
-
|
|
|
b1dca6 |
- /* Skip entries that are not enabled in the mask word. */
|
|
|
b1dca6 |
- if (__glibc_likely (mask & ((ElfW(Word)) 1 << bit)))
|
|
|
b1dca6 |
- {
|
|
|
b1dca6 |
- temp[m].str = p;
|
|
|
b1dca6 |
- temp[m].len = len;
|
|
|
b1dca6 |
- ++m;
|
|
|
b1dca6 |
- }
|
|
|
b1dca6 |
- else
|
|
|
b1dca6 |
- --cnt;
|
|
|
b1dca6 |
- }
|
|
|
b1dca6 |
- }
|
|
|
b1dca6 |
-#endif
|
|
|
b1dca6 |
for (n = 0; masked != 0; ++n)
|
|
|
b1dca6 |
if ((masked & (1ULL << n)) != 0)
|
|
|
b1dca6 |
{
|