@@ -340,14 +340,15 @@ print_cache (const char *cache_name)
const char *cache_data;
int format = 0;
- if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
+ if (memcmp_eq (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
{
/* This can only be the new format without the old one. */
cache_new = (struct cache_file_new *) cache;
- if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
- || memcmp (cache_new->version, CACHE_VERSION,
- sizeof CACHE_VERSION - 1))
+ if (memcmp_eq (cache_new->magic, CACHEMAGIC_NEW,
+ sizeof CACHEMAGIC_NEW - 1)
+ || memcmp_eq (cache_new->version, CACHE_VERSION,
+ sizeof CACHE_VERSION - 1))
error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
check_new_cache (cache_new);
format = 1;
@@ -374,10 +375,10 @@ print_cache (const char *cache_name)
cache_new = (struct cache_file_new *) ((void *)cache + offset);
- if (memcmp (cache_new->magic, CACHEMAGIC_NEW,
- sizeof CACHEMAGIC_NEW - 1) == 0
- && memcmp (cache_new->version, CACHE_VERSION,
- sizeof CACHE_VERSION - 1) == 0)
+ if (memcmp_eq (cache_new->magic, CACHEMAGIC_NEW,
+ sizeof CACHEMAGIC_NEW - 1) == 0
+ && memcmp_eq (cache_new->version, CACHE_VERSION,
+ sizeof CACHE_VERSION - 1) == 0)
{
check_new_cache (cache_new);
cache_data = (const char *) cache_new;
@@ -1030,7 +1031,8 @@ load_aux_cache (const char *aux_cache_name)
= mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (aux_cache == MAP_FAILED
|| aux_cache_size < sizeof (struct aux_cache_file)
- || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
+ || memcmp_eq (aux_cache->magic, AUX_CACHEMAGIC,
+ sizeof AUX_CACHEMAGIC - 1)
|| aux_cache_size != (sizeof (struct aux_cache_file)
+ aux_cache->nlibs * sizeof (struct aux_cache_file_entry)
+ aux_cache->len_strings))
@@ -72,7 +72,7 @@ glibc_hwcaps_compare (uint32_t left_index, struct dl_hwcaps_priority *right)
to_compare = left_name_length;
else
to_compare = right->name_length;
- int cmp = memcmp (left_name, right->name, to_compare);
+ int cmp = memcmp_eq (left_name, right->name, to_compare);
if (cmp != 0)
return cmp;
if (left_name_length < right->name_length)
@@ -420,8 +420,8 @@ _dl_load_cache_lookup (const char *name)
- the old format with the new format in it
The following checks if the cache contains any of these formats. */
if (file != MAP_FAILED && cachesize > sizeof *cache_new
- && memcmp (file, CACHEMAGIC_VERSION_NEW,
- sizeof CACHEMAGIC_VERSION_NEW - 1) == 0
+ && memcmp_eq (file, CACHEMAGIC_VERSION_NEW,
+ sizeof CACHEMAGIC_VERSION_NEW - 1) == 0
/* Check for corruption, avoiding overflow. */
&& ((cachesize - sizeof *cache_new) / sizeof (struct file_entry_new)
>= ((struct cache_file_new *) file)->nlibs))
@@ -435,7 +435,7 @@ _dl_load_cache_lookup (const char *name)
cache = file;
}
else if (file != MAP_FAILED && cachesize > sizeof *cache
- && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
+ && memcmp_eq (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
/* Check for corruption, avoiding overflow. */
&& ((cachesize - sizeof *cache) / sizeof (struct file_entry)
>= ((struct cache_file *) file)->nlibs))
@@ -450,8 +450,8 @@ _dl_load_cache_lookup (const char *name)
cache_new = (struct cache_file_new *) ((void *) cache + offset);
if (cachesize < (offset + sizeof (struct cache_file_new))
- || memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
- sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
+ || memcmp_eq (cache_new->magic, CACHEMAGIC_VERSION_NEW,
+ sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
cache_new = (void *) -1;
else
{
@@ -170,7 +170,7 @@ unfiltered_envvar (const char *env, size_t *name_length)
{
size_t candidate_length = strlen (candidate);
if (candidate_length == envname_length
- && memcmp (candidate, env, candidate_length) == 0)
+ && memcmp_eq (candidate, env, candidate_length) == 0)
return true;
candidate += candidate_length + 1;
}
@@ -71,7 +71,7 @@ _dl_hwcaps_contains (const char *hwcaps, const char *name, size_t name_length)
_dl_hwcaps_split_init (&split, hwcaps);
while (_dl_hwcaps_split (&split))
if (split.length == name_length
- && memcmp (split.segment, name, name_length) == 0)
+ && memcmp_eq (split.segment, name, name_length) == 0)
return true;
return false;
}
@@ -170,7 +170,7 @@ is_trusted_path_normalize (const char *path, size_t len)
for (size_t idx = 0; idx < nsystem_dirs_len; ++idx)
{
if (wnp - npath >= system_dirs_len[idx]
- && memcmp (trun, npath, system_dirs_len[idx]) == 0)
+ && memcmp_eq (trun, npath, system_dirs_len[idx]) == 0)
/* Found it. */
return true;
@@ -507,7 +507,8 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
/* See if this directory is already known. */
for (dirp = GL(dl_all_dirs); dirp != NULL; dirp = dirp->next)
- if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0)
+ if (dirp->dirnamelen == len
+ && memcmp_eq (cp, dirp->dirname, len) == 0)
break;
if (dirp != NULL)
@@ -884,7 +885,7 @@ _dl_process_pt_gnu_property (struct link_map *l, int fd, const ElfW(Phdr) *ph)
/* Find the NT_GNU_PROPERTY_TYPE_0 note. */
if (note->n_namesz == 4
&& note->n_type == NT_GNU_PROPERTY_TYPE_0
- && memcmp (note + 1, "GNU", 4) == 0)
+ && memcmp_eq (note + 1, "GNU", 4) == 0)
{
/* Check for invalid property. */
if (note->n_descsz < 8
@@ -1573,7 +1574,7 @@ open_verify (const char *name, int fd,
#define ELF32_CLASS ELFCLASS32
#define ELF64_CLASS ELFCLASS64
#ifndef VALID_ELF_HEADER
-# define VALID_ELF_HEADER(hdr,exp,size) (memcmp (hdr, exp, size) == 0)
+# define VALID_ELF_HEADER(hdr,exp,size) (memcmp_eq (hdr, exp, size) == 0)
# define VALID_ELF_OSABI(osabi) (osabi == ELFOSABI_SYSV)
# define VALID_ELF_ABIVERSION(osabi,ver) (ver == 0)
#elif defined MORE_ELF_HEADER_DATA
@@ -1675,9 +1676,9 @@ open_verify (const char *name, int fd,
EI_ABIVERSION)
|| !VALID_ELF_ABIVERSION (ehdr->e_ident[EI_OSABI],
ehdr->e_ident[EI_ABIVERSION])
- || memcmp (&ehdr->e_ident[EI_PAD],
- &expected[EI_PAD],
- EI_NIDENT - EI_PAD) != 0))
+ || memcmp_eq (&ehdr->e_ident[EI_PAD],
+ &expected[EI_PAD],
+ EI_NIDENT - EI_PAD) != 0))
{
/* Something is wrong. */
const Elf32_Word *magp = (const void *) ehdr->e_ident;
@@ -1720,8 +1721,8 @@ open_verify (const char *name, int fd,
else if (!VALID_ELF_ABIVERSION (ehdr->e_ident[EI_OSABI],
ehdr->e_ident[EI_ABIVERSION]))
errstring = N_("ELF file ABI version invalid");
- else if (memcmp (&ehdr->e_ident[EI_PAD], &expected[EI_PAD],
- EI_NIDENT - EI_PAD) != 0)
+ else if (memcmp_eq (&ehdr->e_ident[EI_PAD], &expected[EI_PAD],
+ EI_NIDENT - EI_PAD) != 0)
errstring = N_("nonzero padding in e_ident");
else
/* Otherwise we don't know what went wrong. */
@@ -1802,7 +1803,8 @@ open_verify (const char *name, int fd,
}
}
- while (memcmp (abi_note, &expected_note, sizeof (expected_note)))
+ while (memcmp_eq (abi_note, &expected_note,
+ sizeof (expected_note)))
{
ElfW(Addr) note_size
= ELF_NOTE_NEXT_OFFSET (abi_note[0], abi_note[1],
@@ -2193,7 +2195,8 @@ _dl_map_object (struct link_map *loader, const char *name,
do
{
- if (memcmp (cached, dirp, system_dirs_len[cnt]) == 0)
+ if (memcmp_eq (cached, dirp,
+ system_dirs_len[cnt]) == 0)
{
/* The prefix matches. Don't use the entry. */
free (cached);
@@ -416,10 +416,10 @@ _dl_start_profile (void)
else
{
/* Test the signature in the file. */
- if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
+ if (memcmp_eq (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
|| *(uint32_t *) hist != GMON_TAG_TIME_HIST
- || memcmp (hist + sizeof (uint32_t), &hist_hdr,
- sizeof (struct gmon_hist_hdr)) != 0
+ || memcmp_eq (hist + sizeof (uint32_t), &hist_hdr,
+ sizeof (struct gmon_hist_hdr)) != 0
|| narcsp[-1] != GMON_TAG_CG_ARC)
goto wrong_format;
}
@@ -861,8 +861,9 @@ search_dir (const struct dir_entry *entry)
".#prelink#") == 0)
continue;
if (len >= sizeof (".#prelink#.XXXXXX") - 1
- && memcmp (direntry->d_name + len - sizeof (".#prelink#.XXXXXX")
- + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
+ && memcmp_eq (direntry->d_name
+ + len - sizeof (".#prelink#.XXXXXX") + 1,
+ ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
continue;
}
len += strlen (entry->path) + 2;
@@ -297,7 +297,7 @@ get_process_info (const char *exe, int dfd, long int pid)
close (fd);
- if (memcmp (e_ident, ELFMAG, SELFMAG) != 0)
+ if (memcmp_eq (e_ident, ELFMAG, SELFMAG) != 0)
{
error (0, 0, gettext ("process %lu is no ELF program"), pid);
return EXIT_FAILURE;
@@ -142,7 +142,7 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
while (abi_note [0] != 4 || abi_note [1] != 16
|| abi_note [2] != 1
- || memcmp (abi_note + 3, "GNU", 4) != 0)
+ || memcmp_eq (abi_note + 3, "GNU", 4) != 0)
{
ElfW(Addr) note_size
= ELF_NOTE_NEXT_OFFSET (abi_note[0], abi_note[1],
@@ -186,7 +186,7 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
/* Find the NT_GNU_PROPERTY_TYPE_0 note. */
if (note->n_namesz == 4
&& note->n_type == NT_GNU_PROPERTY_TYPE_0
- && memcmp (note + 1, "GNU", 4) == 0)
+ && memcmp_eq (note + 1, "GNU", 4) == 0)
{
/* Check for invalid property. */
if (note->n_descsz < 8
@@ -115,7 +115,8 @@ process_file (const char *real_file_name, const char *file_name,
{
char buf[SELFMAG];
size_t n = MIN (statbuf.st_size, SELFMAG);
- if (fread (buf, n, 1, file) == 1 && memcmp (buf, ELFMAG, n) == 0)
+ if (fread (buf, n, 1, file) == 1
+ && memcmp_eq (buf, ELFMAG, n) == 0)
error (0, 0, _("File %s is too small, not checked."), file_name);
}
fclose (file);
@@ -156,7 +157,7 @@ process_file (const char *real_file_name, const char *file_name,
}
elf_header = (ElfW(Ehdr) *) file_contents;
- if (memcmp (elf_header->e_ident, ELFMAG, SELFMAG) != 0)
+ if (memcmp_eq (elf_header->e_ident, ELFMAG, SELFMAG) != 0)
{
/* The file is neither ELF nor aout. Check if it's a linker
script, like libc.so - otherwise complain. Only search the
@@ -2619,7 +2619,7 @@ process_dl_debug (struct dl_main_state *state, const char *dl_debug)
for (cnt = 0; cnt < ndebopts; ++cnt)
if (debopts[cnt].len == len
- && memcmp (dl_debug, debopts[cnt].name, len) == 0)
+ && memcmp_eq (dl_debug, debopts[cnt].name, len) == 0)
{
GLRO(dl_debug_mask) |= debopts[cnt].mask;
state->any_debug = true;
@@ -2697,49 +2697,50 @@ process_envvars (struct dl_main_state *state)
{
case 4:
/* Warning level, verbose or not. */
- if (memcmp (envline, "WARN", 4) == 0)
+ if (memcmp_eq (envline, "WARN", 4) == 0)
GLRO(dl_verbose) = envline[5] != '\0';
break;
case 5:
/* Debugging of the dynamic linker? */
- if (memcmp (envline, "DEBUG", 5) == 0)
+ if (memcmp_eq (envline, "DEBUG", 5) == 0)
{
process_dl_debug (state, &envline[6]);
break;
}
- if (memcmp (envline, "AUDIT", 5) == 0)
+ if (memcmp_eq (envline, "AUDIT", 5) == 0)
audit_list_add_string (&state->audit_list, &envline[6]);
break;
case 7:
/* Print information about versions. */
- if (memcmp (envline, "VERBOSE", 7) == 0)
+ if (memcmp_eq (envline, "VERBOSE", 7) == 0)
{
state->version_info = envline[8] != '\0';
break;
}
/* List of objects to be preloaded. */
- if (memcmp (envline, "PRELOAD", 7) == 0)
+ if (memcmp_eq (envline, "PRELOAD", 7) == 0)
{
state->preloadlist = &envline[8];
break;
}
/* Which shared object shall be profiled. */
- if (memcmp (envline, "PROFILE", 7) == 0 && envline[8] != '\0')
+ if (memcmp_eq (envline, "PROFILE", 7) == 0
+ && envline[8] != '\0')
GLRO(dl_profile) = &envline[8];
break;
case 8:
/* Do we bind early? */
- if (memcmp (envline, "BIND_NOW", 8) == 0)
+ if (memcmp_eq (envline, "BIND_NOW", 8) == 0)
{
GLRO(dl_lazy) = envline[9] == '\0';
break;
}
- if (memcmp (envline, "BIND_NOT", 8) == 0)
+ if (memcmp_eq (envline, "BIND_NOT", 8) == 0)
GLRO(dl_bind_not) = envline[9] != '\0';
break;
@@ -2747,7 +2748,7 @@ process_envvars (struct dl_main_state *state)
/* Test whether we want to see the content of the auxiliary
array passed up from the kernel. */
if (!__libc_enable_secure
- && memcmp (envline, "SHOW_AUXV", 9) == 0)
+ && memcmp_eq (envline, "SHOW_AUXV", 9) == 0)
_dl_show_auxv ();
break;
@@ -2755,7 +2756,7 @@ process_envvars (struct dl_main_state *state)
case 10:
/* Mask for the important hardware capabilities. */
if (!__libc_enable_secure
- && memcmp (envline, "HWCAP_MASK", 10) == 0)
+ && memcmp_eq (envline, "HWCAP_MASK", 10) == 0)
GLRO(dl_hwcap_mask) = _dl_strtoul (&envline[11], NULL);
break;
#endif
@@ -2763,14 +2764,14 @@ process_envvars (struct dl_main_state *state)
case 11:
/* Path where the binary is found. */
if (!__libc_enable_secure
- && memcmp (envline, "ORIGIN_PATH", 11) == 0)
+ && memcmp_eq (envline, "ORIGIN_PATH", 11) == 0)
GLRO(dl_origin_path) = &envline[12];
break;
case 12:
/* The library search path. */
if (!__libc_enable_secure
- && memcmp (envline, "LIBRARY_PATH", 12) == 0)
+ && memcmp_eq (envline, "LIBRARY_PATH", 12) == 0)
{
state->library_path = &envline[13];
state->library_path_source = "LD_LIBRARY_PATH";
@@ -2778,14 +2779,14 @@ process_envvars (struct dl_main_state *state)
}
/* Where to place the profiling data file. */
- if (memcmp (envline, "DEBUG_OUTPUT", 12) == 0)
+ if (memcmp_eq (envline, "DEBUG_OUTPUT", 12) == 0)
{
debug_output = &envline[13];
break;
}
if (!__libc_enable_secure
- && memcmp (envline, "DYNAMIC_WEAK", 12) == 0)
+ && memcmp_eq (envline, "DYNAMIC_WEAK", 12) == 0)
GLRO(dl_dynamic_weak) = 1;
break;
@@ -2796,7 +2797,7 @@ process_envvars (struct dl_main_state *state)
EXTRA_LD_ENVVARS_13
#endif
if (!__libc_enable_secure
- && memcmp (envline, "USE_LOAD_BIAS", 13) == 0)
+ && memcmp_eq (envline, "USE_LOAD_BIAS", 13) == 0)
{
GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
break;
@@ -2806,14 +2807,14 @@ process_envvars (struct dl_main_state *state)
case 14:
/* Where to place the profiling data file. */
if (!__libc_enable_secure
- && memcmp (envline, "PROFILE_OUTPUT", 14) == 0
+ && memcmp_eq (envline, "PROFILE_OUTPUT", 14) == 0
&& envline[15] != '\0')
GLRO(dl_profile_output) = &envline[15];
break;
case 16:
/* The mode of the dynamic linker can be set. */
- if (memcmp (envline, "TRACE_PRELINKING", 16) == 0)
+ if (memcmp_eq (envline, "TRACE_PRELINKING", 16) == 0)
{
state->mode = rtld_mode_trace;
GLRO(dl_verbose) = 1;
@@ -2824,7 +2825,7 @@ process_envvars (struct dl_main_state *state)
case 20:
/* The mode of the dynamic linker can be set. */
- if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
+ if (memcmp_eq (envline, "TRACE_LOADED_OBJECTS", 20) == 0)
state->mode = rtld_mode_trace;
break;
@@ -889,22 +889,22 @@ load_profdata (const char *name, struct shobj *shobj)
hist_hdr.dimen_abbrev = 's';
/* Test whether the header of the profiling data is ok. */
- if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
+ if (memcmp_eq (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
|| *(uint32_t *) result->hist != GMON_TAG_TIME_HIST
- || memcmp (result->hist_hdr, &hist_hdr,
- sizeof (struct gmon_hist_hdr)) != 0
+ || memcmp_eq (result->hist_hdr, &hist_hdr,
+ sizeof (struct gmon_hist_hdr)) != 0
|| narcsp[-1] != GMON_TAG_CG_ARC)
{
error (0, 0, _("`%s' is no correct profile data file for `%s'"),
name, shobj->name);
if (do_test)
{
- if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0)
+ if (memcmp_eq (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0)
puts ("gmon_hdr differs");
if (*(uint32_t *) result->hist != GMON_TAG_TIME_HIST)
puts ("result->hist differs");
- if (memcmp (result->hist_hdr, &hist_hdr,
- sizeof (struct gmon_hist_hdr)) != 0)
+ if (memcmp_eq (result->hist_hdr, &hist_hdr,
+ sizeof (struct gmon_hist_hdr)) != 0)
puts ("hist_hdr differs");
if (narcsp[-1] != GMON_TAG_CG_ARC)
puts ("narcsp[-1] differs");
@@ -160,6 +160,7 @@ extern __typeof (__strsep_g) __strsep_g attribute_hidden;
extern __typeof (memchr) memchr attribute_hidden;
extern __typeof (memcmp) memcmp attribute_hidden;
+extern __typeof (__memcmpeq) __memcmpeq attribute_hidden;
extern __typeof (memcpy) memcpy attribute_hidden;
extern __typeof (memmove) memmove attribute_hidden;
extern __typeof (memset) memset attribute_hidden;
@@ -172,6 +173,8 @@ extern __typeof (strnlen) strnlen attribute_hidden;
extern __typeof (strsep) strsep attribute_hidden;
#endif
+#include <memcmp-eq.h>
+
#if (!IS_IN (libc) || !defined SHARED) \
&& !defined NO_MEMPCPY_STPCPY_REDIRECT
/* Redirect calls to __builtin_mempcpy and __builtin_stpcpy to call
new file mode 100644
@@ -0,0 +1,24 @@
+/* Function to compare byte sequences for equality. Generic version.
+ Copyright (C) 2022 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
+ <https://www.gnu.org/licenses/>. */
+
+
+static __always_inline int
+memcmp_eq (const void *s1, const void *s2, size_t n)
+{
+ return memcmp (s1, s2, n);
+}
new file mode 100644
@@ -0,0 +1,26 @@
+/* Function to compare byte sequences for equality. x86-64 version.
+ Copyright (C) 2022 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
+ <https://www.gnu.org/licenses/>. */
+
+static __always_inline int
+memcmp_eq (const void *s1, const void *s2, size_t n)
+{
+ /* Compiler can better optimize the constant size. */
+ if (__builtin_constant_p (n))
+ return memcmp (s1, s2, n);
+ return __memcmpeq (s1, s2, n);
+}
@@ -16,8 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#ifndef memcmp
+#if IS_IN (libc)
# define memcmp __memcmpeq_sse2
+#else
+# define memcmp __memcmpeq
#endif
#define USE_AS_MEMCMPEQ 1
#include "memcmp-sse2.S"