import glibc-2.28-148.el8
This commit is contained in:
parent
afe48f68ed
commit
ada533335c
1365
SOURCES/glibc-rh1704868-1.patch
Normal file
1365
SOURCES/glibc-rh1704868-1.patch
Normal file
File diff suppressed because it is too large
Load Diff
235
SOURCES/glibc-rh1704868-2.patch
Normal file
235
SOURCES/glibc-rh1704868-2.patch
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
commit 7d4ec75e111291851620c6aa2c4460647b7fd50d
|
||||||
|
Author: Arjun Shankar <arjun@redhat.com>
|
||||||
|
Date: Fri Sep 25 14:47:06 2020 +0200
|
||||||
|
|
||||||
|
intl: Handle translation output codesets with suffixes [BZ #26383]
|
||||||
|
|
||||||
|
Commit 91927b7c7643 (Rewrite iconv option parsing [BZ #19519]) did not
|
||||||
|
handle cases where the output codeset for translations (via the `gettext'
|
||||||
|
family of functions) might have a caller specified encoding suffix such as
|
||||||
|
TRANSLIT or IGNORE. This led to a regression where translations did not
|
||||||
|
work when the codeset had a suffix.
|
||||||
|
|
||||||
|
This commit fixes the above issue by parsing any suffixes passed to
|
||||||
|
__dcigettext and adds two new test-cases to intl/tst-codeset.c to
|
||||||
|
verify correct behaviour. The iconv-internal function __gconv_create_spec
|
||||||
|
and the static iconv-internal function gconv_destroy_spec are now visible
|
||||||
|
internally within glibc and used in intl/dcigettext.c.
|
||||||
|
|
||||||
|
diff --git a/iconv/Versions b/iconv/Versions
|
||||||
|
index 8a5f4cf780b18925..d51af52fa34b8793 100644
|
||||||
|
--- a/iconv/Versions
|
||||||
|
+++ b/iconv/Versions
|
||||||
|
@@ -6,7 +6,9 @@ libc {
|
||||||
|
GLIBC_PRIVATE {
|
||||||
|
# functions shared with iconv program
|
||||||
|
__gconv_get_alias_db; __gconv_get_cache; __gconv_get_modules_db;
|
||||||
|
- __gconv_open; __gconv_create_spec;
|
||||||
|
+
|
||||||
|
+ # functions used elsewhere in glibc
|
||||||
|
+ __gconv_open; __gconv_create_spec; __gconv_destroy_spec;
|
||||||
|
|
||||||
|
# function used by the gconv modules
|
||||||
|
__gconv_transliterate;
|
||||||
|
diff --git a/iconv/gconv_charset.c b/iconv/gconv_charset.c
|
||||||
|
index 6ccd0773ccb6cd27..4ba0aa99f5dae7f7 100644
|
||||||
|
--- a/iconv/gconv_charset.c
|
||||||
|
+++ b/iconv/gconv_charset.c
|
||||||
|
@@ -216,3 +216,13 @@ out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
libc_hidden_def (__gconv_create_spec)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+__gconv_destroy_spec (struct gconv_spec *conv_spec)
|
||||||
|
+{
|
||||||
|
+ free (conv_spec->fromcode);
|
||||||
|
+ free (conv_spec->tocode);
|
||||||
|
+ return;
|
||||||
|
+}
|
||||||
|
+libc_hidden_def (__gconv_destroy_spec)
|
||||||
|
diff --git a/iconv/gconv_charset.h b/iconv/gconv_charset.h
|
||||||
|
index b85d80313030b649..4b98073389bd8707 100644
|
||||||
|
--- a/iconv/gconv_charset.h
|
||||||
|
+++ b/iconv/gconv_charset.h
|
||||||
|
@@ -48,33 +48,6 @@
|
||||||
|
#define GCONV_IGNORE_ERRORS_SUFFIX "IGNORE"
|
||||||
|
|
||||||
|
|
||||||
|
-/* This function accepts the charset names of the source and destination of the
|
||||||
|
- conversion and populates *conv_spec with an equivalent conversion
|
||||||
|
- specification that may later be used by __gconv_open. The charset names
|
||||||
|
- might contain options in the form of suffixes that alter the conversion,
|
||||||
|
- e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring
|
||||||
|
- and truncating any suffix options in fromcode, and processing and truncating
|
||||||
|
- any suffix options in tocode. Supported suffix options ("TRANSLIT" or
|
||||||
|
- "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec
|
||||||
|
- to be set to true. Unrecognized suffix options are silently discarded. If
|
||||||
|
- the function succeeds, it returns conv_spec back to the caller. It returns
|
||||||
|
- NULL upon failure. */
|
||||||
|
-struct gconv_spec *
|
||||||
|
-__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode,
|
||||||
|
- const char *tocode);
|
||||||
|
-libc_hidden_proto (__gconv_create_spec)
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* This function frees all heap memory allocated by __gconv_create_spec. */
|
||||||
|
-static void __attribute__ ((unused))
|
||||||
|
-gconv_destroy_spec (struct gconv_spec *conv_spec)
|
||||||
|
-{
|
||||||
|
- free (conv_spec->fromcode);
|
||||||
|
- free (conv_spec->tocode);
|
||||||
|
- return;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/* This function copies in-order, characters from the source 's' that are
|
||||||
|
either alpha-numeric or one in one of these: "_-.,:/" - into the destination
|
||||||
|
'wp' while dropping all other characters. In the process, it converts all
|
||||||
|
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
|
||||||
|
index 4748e9b1fa3b5426..8067a341b0903e1b 100644
|
||||||
|
--- a/iconv/gconv_int.h
|
||||||
|
+++ b/iconv/gconv_int.h
|
||||||
|
@@ -170,6 +170,27 @@ extern int __gconv_open (struct gconv_spec *conv_spec,
|
||||||
|
__gconv_t *handle, int flags);
|
||||||
|
libc_hidden_proto (__gconv_open)
|
||||||
|
|
||||||
|
+/* This function accepts the charset names of the source and destination of the
|
||||||
|
+ conversion and populates *conv_spec with an equivalent conversion
|
||||||
|
+ specification that may later be used by __gconv_open. The charset names
|
||||||
|
+ might contain options in the form of suffixes that alter the conversion,
|
||||||
|
+ e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring
|
||||||
|
+ and truncating any suffix options in fromcode, and processing and truncating
|
||||||
|
+ any suffix options in tocode. Supported suffix options ("TRANSLIT" or
|
||||||
|
+ "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec
|
||||||
|
+ to be set to true. Unrecognized suffix options are silently discarded. If
|
||||||
|
+ the function succeeds, it returns conv_spec back to the caller. It returns
|
||||||
|
+ NULL upon failure. */
|
||||||
|
+extern struct gconv_spec *
|
||||||
|
+__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode,
|
||||||
|
+ const char *tocode);
|
||||||
|
+libc_hidden_proto (__gconv_create_spec)
|
||||||
|
+
|
||||||
|
+/* This function frees all heap memory allocated by __gconv_create_spec. */
|
||||||
|
+extern void
|
||||||
|
+__gconv_destroy_spec (struct gconv_spec *conv_spec);
|
||||||
|
+libc_hidden_proto (__gconv_destroy_spec)
|
||||||
|
+
|
||||||
|
/* Free resources associated with transformation descriptor CD. */
|
||||||
|
extern int __gconv_close (__gconv_t cd)
|
||||||
|
attribute_hidden;
|
||||||
|
diff --git a/iconv/iconv_open.c b/iconv/iconv_open.c
|
||||||
|
index 59d1ef4f07ed1022..46da33bca6c24af0 100644
|
||||||
|
--- a/iconv/iconv_open.c
|
||||||
|
+++ b/iconv/iconv_open.c
|
||||||
|
@@ -39,7 +39,7 @@ iconv_open (const char *tocode, const char *fromcode)
|
||||||
|
|
||||||
|
int res = __gconv_open (&conv_spec, &cd, 0);
|
||||||
|
|
||||||
|
- gconv_destroy_spec (&conv_spec);
|
||||||
|
+ __gconv_destroy_spec (&conv_spec);
|
||||||
|
|
||||||
|
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
|
||||||
|
{
|
||||||
|
diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c
|
||||||
|
index 552efac81660e82a..e26e9d02ca4121a7 100644
|
||||||
|
--- a/iconv/iconv_prog.c
|
||||||
|
+++ b/iconv/iconv_prog.c
|
||||||
|
@@ -184,7 +184,7 @@ main (int argc, char *argv[])
|
||||||
|
/* Let's see whether we have these coded character sets. */
|
||||||
|
res = __gconv_open (&conv_spec, &cd, 0);
|
||||||
|
|
||||||
|
- gconv_destroy_spec (&conv_spec);
|
||||||
|
+ __gconv_destroy_spec (&conv_spec);
|
||||||
|
|
||||||
|
if (res != __GCONV_OK)
|
||||||
|
{
|
||||||
|
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
|
||||||
|
index ed48fc8d3e96c7ba..7ebe67b4ac2113e9 100644
|
||||||
|
--- a/intl/dcigettext.c
|
||||||
|
+++ b/intl/dcigettext.c
|
||||||
|
@@ -1121,15 +1121,18 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
|
||||||
|
|
||||||
|
# ifdef _LIBC
|
||||||
|
|
||||||
|
- struct gconv_spec conv_spec
|
||||||
|
- = { .fromcode = norm_add_slashes (charset, ""),
|
||||||
|
- .tocode = norm_add_slashes (outcharset, ""),
|
||||||
|
- /* We always want to use transliteration. */
|
||||||
|
- .translit = true,
|
||||||
|
- .ignore = false
|
||||||
|
- };
|
||||||
|
+ struct gconv_spec conv_spec;
|
||||||
|
+
|
||||||
|
+ __gconv_create_spec (&conv_spec, charset, outcharset);
|
||||||
|
+
|
||||||
|
+ /* We always want to use transliteration. */
|
||||||
|
+ conv_spec.translit = true;
|
||||||
|
+
|
||||||
|
int r = __gconv_open (&conv_spec, &convd->conv,
|
||||||
|
GCONV_AVOID_NOCONV);
|
||||||
|
+
|
||||||
|
+ __gconv_destroy_spec (&conv_spec);
|
||||||
|
+
|
||||||
|
if (__builtin_expect (r != __GCONV_OK, 0))
|
||||||
|
{
|
||||||
|
/* If the output encoding is the same there is
|
||||||
|
diff --git a/intl/tst-codeset.c b/intl/tst-codeset.c
|
||||||
|
index e71382aeeeca477b..52e4aaa6ffd3afdb 100644
|
||||||
|
--- a/intl/tst-codeset.c
|
||||||
|
+++ b/intl/tst-codeset.c
|
||||||
|
@@ -22,13 +22,11 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
- char *s;
|
||||||
|
- int result = 0;
|
||||||
|
-
|
||||||
|
unsetenv ("LANGUAGE");
|
||||||
|
unsetenv ("OUTPUT_CHARSET");
|
||||||
|
setlocale (LC_ALL, "de_DE.ISO-8859-1");
|
||||||
|
@@ -36,25 +34,21 @@ do_test (void)
|
||||||
|
bindtextdomain ("codeset", OBJPFX "domaindir");
|
||||||
|
|
||||||
|
/* Here we expect output in ISO-8859-1. */
|
||||||
|
- s = gettext ("cheese");
|
||||||
|
- if (strcmp (s, "K\344se"))
|
||||||
|
- {
|
||||||
|
- printf ("call 1 returned: %s\n", s);
|
||||||
|
- result = 1;
|
||||||
|
- }
|
||||||
|
+ TEST_COMPARE_STRING (gettext ("cheese"), "K\344se");
|
||||||
|
|
||||||
|
+ /* Here we expect output in UTF-8. */
|
||||||
|
bind_textdomain_codeset ("codeset", "UTF-8");
|
||||||
|
+ TEST_COMPARE_STRING (gettext ("cheese"), "K\303\244se");
|
||||||
|
|
||||||
|
- /* Here we expect output in UTF-8. */
|
||||||
|
- s = gettext ("cheese");
|
||||||
|
- if (strcmp (s, "K\303\244se"))
|
||||||
|
- {
|
||||||
|
- printf ("call 2 returned: %s\n", s);
|
||||||
|
- result = 1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return result;
|
||||||
|
+ /* `a with umlaut' is transliterated to `ae'. */
|
||||||
|
+ bind_textdomain_codeset ("codeset", "ASCII//TRANSLIT");
|
||||||
|
+ TEST_COMPARE_STRING (gettext ("cheese"), "Kaese");
|
||||||
|
+
|
||||||
|
+ /* Transliteration also works by default even if not set. */
|
||||||
|
+ bind_textdomain_codeset ("codeset", "ASCII");
|
||||||
|
+ TEST_COMPARE_STRING (gettext ("cheese"), "Kaese");
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-#define TEST_FUNCTION do_test ()
|
||||||
|
-#include "../test-skeleton.c"
|
||||||
|
+#include <support/test-driver.c>
|
77
SOURCES/glibc-rh1704868-3.patch
Normal file
77
SOURCES/glibc-rh1704868-3.patch
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
commit 9a99c682144bdbd40792ebf822fe9264e0376fb5
|
||||||
|
Author: Arjun Shankar <arjun@redhat.com>
|
||||||
|
Date: Wed Nov 4 12:19:38 2020 +0100
|
||||||
|
|
||||||
|
iconv: Accept redundant shift sequences in IBM1364 [BZ #26224]
|
||||||
|
|
||||||
|
The IBM1364, IBM1371, IBM1388, IBM1390 and IBM1399 character sets
|
||||||
|
share converter logic (iconvdata/ibm1364.c) which would reject
|
||||||
|
redundant shift sequences when processing input in these character
|
||||||
|
sets. This led to a hang in the iconv program (CVE-2020-27618).
|
||||||
|
|
||||||
|
This commit adjusts the converter to ignore redundant shift sequences
|
||||||
|
and adds test cases for iconv_prog hangs that would be triggered upon
|
||||||
|
their rejection. This brings the implementation in line with other
|
||||||
|
converters that also ignore redundant shift sequences (e.g. IBM930
|
||||||
|
etc., fixed in commit 692de4b3960d).
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/iconv/tst-iconv_prog.sh b/iconv/tst-iconv_prog.sh
|
||||||
|
index 8298136b7f45d855..d8db7b335c1fcca2 100644
|
||||||
|
--- a/iconv/tst-iconv_prog.sh
|
||||||
|
+++ b/iconv/tst-iconv_prog.sh
|
||||||
|
@@ -102,12 +102,16 @@ hangarray=(
|
||||||
|
"\x00\x80;-c;IBM1161;UTF-8//TRANSLIT//IGNORE"
|
||||||
|
"\x00\xdb;-c;IBM1162;UTF-8//TRANSLIT//IGNORE"
|
||||||
|
"\x00\x70;-c;IBM12712;UTF-8//TRANSLIT//IGNORE"
|
||||||
|
-# These are known hangs that are yet to be fixed:
|
||||||
|
-# "\x00\x0f;-c;IBM1364;UTF-8"
|
||||||
|
-# "\x00\x0f;-c;IBM1371;UTF-8"
|
||||||
|
-# "\x00\x0f;-c;IBM1388;UTF-8"
|
||||||
|
-# "\x00\x0f;-c;IBM1390;UTF-8"
|
||||||
|
-# "\x00\x0f;-c;IBM1399;UTF-8"
|
||||||
|
+"\x00\x0f;-c;IBM1364;UTF-8"
|
||||||
|
+"\x0e\x0e;-c;IBM1364;UTF-8"
|
||||||
|
+"\x00\x0f;-c;IBM1371;UTF-8"
|
||||||
|
+"\x0e\x0e;-c;IBM1371;UTF-8"
|
||||||
|
+"\x00\x0f;-c;IBM1388;UTF-8"
|
||||||
|
+"\x0e\x0e;-c;IBM1388;UTF-8"
|
||||||
|
+"\x00\x0f;-c;IBM1390;UTF-8"
|
||||||
|
+"\x0e\x0e;-c;IBM1390;UTF-8"
|
||||||
|
+"\x00\x0f;-c;IBM1399;UTF-8"
|
||||||
|
+"\x0e\x0e;-c;IBM1399;UTF-8"
|
||||||
|
"\x00\x53;-c;IBM16804;UTF-8//TRANSLIT//IGNORE"
|
||||||
|
"\x00\x41;-c;IBM274;UTF-8//TRANSLIT//IGNORE"
|
||||||
|
"\x00\x41;-c;IBM275;UTF-8//TRANSLIT//IGNORE"
|
||||||
|
diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c
|
||||||
|
index 517fe60813be0472..ecc3f8ddddbdbc8c 100644
|
||||||
|
--- a/iconvdata/ibm1364.c
|
||||||
|
+++ b/iconvdata/ibm1364.c
|
||||||
|
@@ -158,24 +158,14 @@ enum
|
||||||
|
\
|
||||||
|
if (__builtin_expect (ch, 0) == SO) \
|
||||||
|
{ \
|
||||||
|
- /* Shift OUT, change to DBCS converter. */ \
|
||||||
|
- if (curcs == db) \
|
||||||
|
- { \
|
||||||
|
- result = __GCONV_ILLEGAL_INPUT; \
|
||||||
|
- break; \
|
||||||
|
- } \
|
||||||
|
+ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \
|
||||||
|
curcs = db; \
|
||||||
|
++inptr; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
if (__builtin_expect (ch, 0) == SI) \
|
||||||
|
{ \
|
||||||
|
- /* Shift IN, change to SBCS converter. */ \
|
||||||
|
- if (curcs == sb) \
|
||||||
|
- { \
|
||||||
|
- result = __GCONV_ILLEGAL_INPUT; \
|
||||||
|
- break; \
|
||||||
|
- } \
|
||||||
|
+ /* Shift IN, change to SBCS converter (redundant escape okay). */ \
|
||||||
|
curcs = sb; \
|
||||||
|
++inptr; \
|
||||||
|
continue; \
|
66
SOURCES/glibc-rh1704868-4.patch
Normal file
66
SOURCES/glibc-rh1704868-4.patch
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
commit cce35a50c1de0cec5cd1f6c18979ff6ee3ea1dd1
|
||||||
|
Author: Arjun Shankar <arjun@redhat.com>
|
||||||
|
Date: Mon Nov 11 14:57:23 2019 +0100
|
||||||
|
|
||||||
|
support: Add xsetlocale function
|
||||||
|
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 37d5dcc92a5c6dee..6afaa6836c944398 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -148,6 +148,7 @@ libsupport-routines = \
|
||||||
|
xrealloc \
|
||||||
|
xrecvfrom \
|
||||||
|
xsendto \
|
||||||
|
+ xsetlocale \
|
||||||
|
xsetsockopt \
|
||||||
|
xsigaction \
|
||||||
|
xsignal \
|
||||||
|
diff --git a/support/support.h b/support/support.h
|
||||||
|
index 61a10c34982134ff..97d142e9b6f68188 100644
|
||||||
|
--- a/support/support.h
|
||||||
|
+++ b/support/support.h
|
||||||
|
@@ -91,6 +91,7 @@ char *xasprintf (const char *format, ...)
|
||||||
|
__attribute__ ((format (printf, 1, 2), malloc));
|
||||||
|
char *xstrdup (const char *);
|
||||||
|
char *xstrndup (const char *, size_t);
|
||||||
|
+char *xsetlocale (int category, const char *locale);
|
||||||
|
|
||||||
|
/* These point to the TOP of the source/build tree, not your (or
|
||||||
|
support's) subdirectory. */
|
||||||
|
diff --git a/support/xsetlocale.c b/support/xsetlocale.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..063ed4b0d63af884
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/xsetlocale.c
|
||||||
|
@@ -0,0 +1,30 @@
|
||||||
|
+/* setlocale with error checking.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#include <support/check.h>
|
||||||
|
+
|
||||||
|
+#include <locale.h>
|
||||||
|
+
|
||||||
|
+char *
|
||||||
|
+xsetlocale (int category, const char *locale)
|
||||||
|
+{
|
||||||
|
+ char *p = setlocale (category, locale);
|
||||||
|
+ if (p == NULL)
|
||||||
|
+ FAIL_EXIT1 ("error: setlocale (%d, \"%s\")\n", category, locale);
|
||||||
|
+ return p;
|
||||||
|
+}
|
35
SOURCES/glibc-rh1704868-5.patch
Normal file
35
SOURCES/glibc-rh1704868-5.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
The patch (glibc-rh1704868-1.patch) for commit 91927b7c7643
|
||||||
|
(Rewrite iconv option parsing) contains a test that depends on
|
||||||
|
commit 513aaa0d782f (Add Transliterations for Unicode Misc.
|
||||||
|
Mathematical Symbols-A/B), which is not applied in RHEL-8. This
|
||||||
|
patch edits the test so as not to depend on the unapplied patch
|
||||||
|
and its additional transliterations.
|
||||||
|
|
||||||
|
diff --git a/iconv/tst-iconv-opt.c b/iconv/tst-iconv-opt.c
|
||||||
|
index 669d812a6a9b8749..21e6d887501450a7 100644
|
||||||
|
--- a/iconv/tst-iconv-opt.c
|
||||||
|
+++ b/iconv/tst-iconv-opt.c
|
||||||
|
@@ -82,18 +82,18 @@ char u2a_ignore[] = "UTF-8 text with couple f non-ASCII characters";
|
||||||
|
|
||||||
|
/* 3. Invalid UTF-8 input and some corresponding expected outputs. \xff is
|
||||||
|
invalid UTF-8. It's followed by some valid but non-ASCII UTF-8. */
|
||||||
|
-char iutf8[] = "Invalid UTF-8 \xff\u27E6text\u27E7";
|
||||||
|
+char iutf8[] = "Invalid UTF-8 \xff\u00B7text\u00B7";
|
||||||
|
char iu2a[] = "Invalid UTF-8 ";
|
||||||
|
char iu2a_ignore[] = "Invalid UTF-8 text";
|
||||||
|
-char iu2a_both[] = "Invalid UTF-8 [|text|]";
|
||||||
|
+char iu2a_both[] = "Invalid UTF-8 .text.";
|
||||||
|
|
||||||
|
/* 4. Another invalid UTF-8 input and corresponding expected outputs. This time
|
||||||
|
the valid non-ASCII UTF-8 characters appear before the invalid \xff. */
|
||||||
|
-char jutf8[] = "Invalid \u27E6UTF-8\u27E7 \xfftext";
|
||||||
|
+char jutf8[] = "Invalid \u00B7UTF-8\u00B7 \xfftext";
|
||||||
|
char ju2a[] = "Invalid ";
|
||||||
|
-char ju2a_translit[] = "Invalid [|UTF-8|] ";
|
||||||
|
+char ju2a_translit[] = "Invalid .UTF-8. ";
|
||||||
|
char ju2a_ignore[] = "Invalid UTF-8 text";
|
||||||
|
-char ju2a_both[] = "Invalid [|UTF-8|] text";
|
||||||
|
+char ju2a_both[] = "Invalid .UTF-8. text";
|
||||||
|
|
||||||
|
/* We also test option handling for character set names that have the form
|
||||||
|
"A/B". In this test, we test conversions "ISO-10646/UTF-8", and either
|
53
SOURCES/glibc-rh1817513-1.patch
Normal file
53
SOURCES/glibc-rh1817513-1.patch
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
commit 82c80ac2ebf9acc81ec460adfd951d4884836c7c
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Wed Aug 1 04:57:34 2018 -0700
|
||||||
|
|
||||||
|
x86: Rename get_common_indeces to get_common_indices
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
* sysdeps/x86/cpu-features.c (get_common_indeces): Renamed to
|
||||||
|
...
|
||||||
|
(get_common_indices): This.
|
||||||
|
(init_cpu_features): Updated.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index ac74f408343191b0..41f2d15fa5c8a756 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -56,7 +56,7 @@ get_extended_indices (struct cpu_features *cpu_features)
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-get_common_indeces (struct cpu_features *cpu_features,
|
||||||
|
+get_common_indices (struct cpu_features *cpu_features,
|
||||||
|
unsigned int *family, unsigned int *model,
|
||||||
|
unsigned int *extended_model, unsigned int *stepping)
|
||||||
|
{
|
||||||
|
@@ -234,7 +234,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
|
||||||
|
kind = arch_kind_intel;
|
||||||
|
|
||||||
|
- get_common_indeces (cpu_features, &family, &model, &extended_model,
|
||||||
|
+ get_common_indices (cpu_features, &family, &model, &extended_model,
|
||||||
|
&stepping);
|
||||||
|
|
||||||
|
get_extended_indices (cpu_features);
|
||||||
|
@@ -356,7 +356,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
|
||||||
|
kind = arch_kind_amd;
|
||||||
|
|
||||||
|
- get_common_indeces (cpu_features, &family, &model, &extended_model,
|
||||||
|
+ get_common_indices (cpu_features, &family, &model, &extended_model,
|
||||||
|
&stepping);
|
||||||
|
|
||||||
|
get_extended_indices (cpu_features);
|
||||||
|
@@ -393,7 +393,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kind = arch_kind_other;
|
||||||
|
- get_common_indeces (cpu_features, NULL, NULL, NULL, NULL);
|
||||||
|
+ get_common_indices (cpu_features, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Support i586 if CX8 is available. */
|
41
SOURCES/glibc-rh1817513-10.patch
Normal file
41
SOURCES/glibc-rh1817513-10.patch
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
commit 2dd8e58cc533ee840d37725b11bc0dc0308a5dc0
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Sun Oct 21 00:37:11 2018 -0700
|
||||||
|
|
||||||
|
x86: Don't include <x86intrin.h>
|
||||||
|
|
||||||
|
Use __builtin_ia32_rdtsc directly since including <x86intrin.h> makes
|
||||||
|
building glibc very slow. On Intel Core i5-6260U, this patch reduces
|
||||||
|
x86-64 build time from 8 minutes 33 seconds to 3 minutes 48 seconds
|
||||||
|
with "make -j4" and GCC 8.2.1.
|
||||||
|
|
||||||
|
* sysdeps/x86/hp-timing.h: Don't include <x86intrin.h>.
|
||||||
|
(HP_TIMING_NOW): Replace _rdtsc with __builtin_ia32_rdtsc.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/hp-timing.h b/sysdeps/x86/hp-timing.h
|
||||||
|
index 1c20e9d8289cc15b..77a1360748ca4535 100644
|
||||||
|
--- a/sysdeps/x86/hp-timing.h
|
||||||
|
+++ b/sysdeps/x86/hp-timing.h
|
||||||
|
@@ -22,8 +22,6 @@
|
||||||
|
#include <isa.h>
|
||||||
|
|
||||||
|
#if MINIMUM_ISA == 686 || MINIMUM_ISA == 8664
|
||||||
|
-# include <x86intrin.h>
|
||||||
|
-
|
||||||
|
/* We always assume having the timestamp register. */
|
||||||
|
# define HP_TIMING_AVAIL (1)
|
||||||
|
# define HP_SMALL_TIMING_AVAIL (1)
|
||||||
|
@@ -38,8 +36,11 @@ typedef unsigned long long int hp_timing_t;
|
||||||
|
might not be 100% accurate since there might be some more instructions
|
||||||
|
running in this moment. This could be changed by using a barrier like
|
||||||
|
'cpuid' right before the `rdtsc' instruciton. But we are not interested
|
||||||
|
- in accurate clock cycles here so we don't do this. */
|
||||||
|
-# define HP_TIMING_NOW(Var) ((Var) = _rdtsc ())
|
||||||
|
+ in accurate clock cycles here so we don't do this.
|
||||||
|
+
|
||||||
|
+ NB: Use __builtin_ia32_rdtsc directly since including <x86intrin.h>
|
||||||
|
+ makes building glibc very slow. */
|
||||||
|
+# define HP_TIMING_NOW(Var) ((Var) = __builtin_ia32_rdtsc ())
|
||||||
|
|
||||||
|
# include <hp-timing-common.h>
|
||||||
|
#else
|
82
SOURCES/glibc-rh1817513-100.patch
Normal file
82
SOURCES/glibc-rh1817513-100.patch
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
commit bb5fd5ce64b598085bdb8a05cb53777480fe093c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Oct 9 10:13:14 2020 +0200
|
||||||
|
|
||||||
|
elf: Do not pass GLRO(dl_platform), GLRO(dl_platformlen) to _dl_important_hwcaps
|
||||||
|
|
||||||
|
In the current code, the function can easily obtain the information
|
||||||
|
on its own.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
||||||
|
index ae2e4ca7fe91d407..82ee89c36a1eb4ab 100644
|
||||||
|
--- a/elf/dl-hwcaps.c
|
||||||
|
+++ b/elf/dl-hwcaps.c
|
||||||
|
@@ -28,13 +28,12 @@
|
||||||
|
|
||||||
|
/* Return an array of useful/necessary hardware capability names. */
|
||||||
|
const struct r_strlenpair *
|
||||||
|
-_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||||
|
- size_t *max_capstrlen)
|
||||||
|
+_dl_important_hwcaps (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) & hwcap_mask;
|
||||||
|
- size_t cnt = platform != NULL;
|
||||||
|
+ size_t cnt = GLRO (dl_platform) != NULL;
|
||||||
|
size_t n, m;
|
||||||
|
size_t total;
|
||||||
|
struct r_strlenpair *result;
|
||||||
|
@@ -60,10 +59,10 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||||
|
masked ^= 1ULL << n;
|
||||||
|
++m;
|
||||||
|
}
|
||||||
|
- if (platform != NULL)
|
||||||
|
+ if (GLRO (dl_platform) != NULL)
|
||||||
|
{
|
||||||
|
- temp[m].str = platform;
|
||||||
|
- temp[m].len = platform_len;
|
||||||
|
+ temp[m].str = GLRO (dl_platform);
|
||||||
|
+ temp[m].len = GLRO (dl_platformlen);
|
||||||
|
++m;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||||
|
index 2eb4f35b2467f7d8..d2be21ea7d1545fe 100644
|
||||||
|
--- a/elf/dl-load.c
|
||||||
|
+++ b/elf/dl-load.c
|
||||||
|
@@ -697,8 +697,7 @@ _dl_init_paths (const char *llp, const char *source)
|
||||||
|
|
||||||
|
#ifdef SHARED
|
||||||
|
/* Get the capabilities. */
|
||||||
|
- capstr = _dl_important_hwcaps (GLRO(dl_platform), GLRO(dl_platformlen),
|
||||||
|
- &ncapstr, &max_capstrlen);
|
||||||
|
+ capstr = _dl_important_hwcaps (&ncapstr, &max_capstrlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* First set up the rest of the default search directory entries. */
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index aa006afafaf46dee..2c9fdeb286bdaadf 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -1069,12 +1069,12 @@ extern void _dl_show_auxv (void) attribute_hidden;
|
||||||
|
other. */
|
||||||
|
extern char *_dl_next_ld_env_entry (char ***position) attribute_hidden;
|
||||||
|
|
||||||
|
-/* Return an array with the names of the important hardware capabilities. */
|
||||||
|
-extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
|
||||||
|
- size_t paltform_len,
|
||||||
|
- size_t *sz,
|
||||||
|
- size_t *max_capstrlen)
|
||||||
|
- attribute_hidden;
|
||||||
|
+/* Return an array with the names of the important hardware
|
||||||
|
+ capabilities. The length of the array is written to *SZ, and the
|
||||||
|
+ maximum of all strings length is written to *MAX_CAPSTRLEN. */
|
||||||
|
+const struct r_strlenpair *_dl_important_hwcaps (size_t *sz,
|
||||||
|
+ size_t *max_capstrlen)
|
||||||
|
+ attribute_hidden;
|
||||||
|
|
||||||
|
/* Look up NAME in ld.so.cache and return the file name stored there,
|
||||||
|
or null if none is found. Caller must free returned string. */
|
65
SOURCES/glibc-rh1817513-101.patch
Normal file
65
SOURCES/glibc-rh1817513-101.patch
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
commit 7674695cf7e28528be7243ceb30c9a600bbaa7b5
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Oct 8 08:19:15 2020 -0700
|
||||||
|
|
||||||
|
<sys/platform/x86.h>: Add Intel UINTR support
|
||||||
|
|
||||||
|
Add Intel UINTR support to <sys/platform/x86.h>.
|
||||||
|
|
||||||
|
diff --git a/manual/platform.texi b/manual/platform.texi
|
||||||
|
index 95b0ed0642c9f8a9..0dd12a4353a93bf2 100644
|
||||||
|
--- a/manual/platform.texi
|
||||||
|
+++ b/manual/platform.texi
|
||||||
|
@@ -583,6 +583,9 @@ using a TSC deadline value.
|
||||||
|
@item
|
||||||
|
@code{TSXLDTRK} -- TSXLDTRK instructions.
|
||||||
|
|
||||||
|
+@item
|
||||||
|
+@code{UINTR} -- User interrupts.
|
||||||
|
+
|
||||||
|
@item
|
||||||
|
@code{UMIP} -- User-mode instruction prevention.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
index bcc81ab5f8ac8265..2760b81a56e6c7d7 100644
|
||||||
|
--- a/sysdeps/x86/sys/platform/x86.h
|
||||||
|
+++ b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
@@ -241,7 +241,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
#define bit_cpu_AVX512_4VNNIW (1u << 2)
|
||||||
|
#define bit_cpu_AVX512_4FMAPS (1u << 3)
|
||||||
|
#define bit_cpu_FSRM (1u << 4)
|
||||||
|
-#define bit_cpu_INDEX_7_EDX_5 (1u << 5)
|
||||||
|
+#define bit_cpu_UINTR (1u << 5)
|
||||||
|
#define bit_cpu_INDEX_7_EDX_6 (1u << 6)
|
||||||
|
#define bit_cpu_INDEX_7_EDX_7 (1u << 7)
|
||||||
|
#define bit_cpu_AVX512_VP2INTERSECT (1u << 8)
|
||||||
|
@@ -460,7 +460,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
#define index_cpu_AVX512_4VNNIW COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_AVX512_4FMAPS COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_FSRM COMMON_CPUID_INDEX_7
|
||||||
|
-#define index_cpu_INDEX_7_EDX_5 COMMON_CPUID_INDEX_7
|
||||||
|
+#define index_cpu_UINTR COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_INDEX_7_EDX_6 COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_INDEX_7_EDX_7 COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_AVX512_VP2INTERSECT COMMON_CPUID_INDEX_7
|
||||||
|
@@ -679,7 +679,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
#define reg_AVX512_4VNNIW edx
|
||||||
|
#define reg_AVX512_4FMAPS edx
|
||||||
|
#define reg_FSRM edx
|
||||||
|
-#define reg_INDEX_7_EDX_5 edx
|
||||||
|
+#define reg_UINTR edx
|
||||||
|
#define reg_INDEX_7_EDX_6 edx
|
||||||
|
#define reg_INDEX_7_EDX_7 edx
|
||||||
|
#define reg_AVX512_VP2INTERSECT edx
|
||||||
|
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
index 3ec94e0c9a191f36..6fa092a8c10486a0 100644
|
||||||
|
--- a/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
@@ -180,6 +180,7 @@ do_test (void)
|
||||||
|
CHECK_CPU_FEATURE (AVX512_4VNNIW);
|
||||||
|
CHECK_CPU_FEATURE (AVX512_4FMAPS);
|
||||||
|
CHECK_CPU_FEATURE (FSRM);
|
||||||
|
+ CHECK_CPU_FEATURE (UINTR);
|
||||||
|
CHECK_CPU_FEATURE (AVX512_VP2INTERSECT);
|
||||||
|
CHECK_CPU_FEATURE (MD_CLEAR);
|
||||||
|
CHECK_CPU_FEATURE (SERIALIZE);
|
86
SOURCES/glibc-rh1817513-102.patch
Normal file
86
SOURCES/glibc-rh1817513-102.patch
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
commit ebe454bcca6a5421512ad228595a5391506e990a
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Oct 8 08:24:47 2020 -0700
|
||||||
|
|
||||||
|
<sys/platform/x86.h>: Add AVX512_FP16 support
|
||||||
|
|
||||||
|
Add AVX512_FP16 support to <sys/platform/x86.h>.
|
||||||
|
|
||||||
|
diff --git a/manual/platform.texi b/manual/platform.texi
|
||||||
|
index 0dd12a4353a93bf2..4f5fdff9d9ef16fd 100644
|
||||||
|
--- a/manual/platform.texi
|
||||||
|
+++ b/manual/platform.texi
|
||||||
|
@@ -210,6 +210,9 @@ The supported processor features are:
|
||||||
|
@item
|
||||||
|
@code{AVX512_BITALG} -- The AVX512_BITALG instruction extensions.
|
||||||
|
|
||||||
|
+@item
|
||||||
|
+@code{AVX512_FP16} -- The AVX512_FP16 instruction extensions.
|
||||||
|
+
|
||||||
|
@item
|
||||||
|
@code{AVX512_IFMA} -- The AVX512_IFMA instruction extensions.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index 7f2ff00f2b4b45f2..67f137259fccf4ad 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -175,6 +175,8 @@ update_usable (struct cpu_features *cpu_features)
|
||||||
|
AVX512_VP2INTERSECT);
|
||||||
|
/* Determine if AVX512_BF16 is usable. */
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, AVX512_BF16);
|
||||||
|
+ /* Determine if AVX512_FP16 is usable. */
|
||||||
|
+ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_FP16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
index 2760b81a56e6c7d7..0b18257e20105ea4 100644
|
||||||
|
--- a/sysdeps/x86/sys/platform/x86.h
|
||||||
|
+++ b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
@@ -259,7 +259,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
#define bit_cpu_IBT (1u << 20)
|
||||||
|
#define bit_cpu_INDEX_7_EDX_21 (1u << 21)
|
||||||
|
#define bit_cpu_AMX_BF16 (1u << 22)
|
||||||
|
-#define bit_cpu_INDEX_7_EDX_23 (1u << 23)
|
||||||
|
+#define bit_cpu_AVX512_FP16 (1u << 23)
|
||||||
|
#define bit_cpu_AMX_TILE (1u << 24)
|
||||||
|
#define bit_cpu_AMX_INT8 (1u << 25)
|
||||||
|
#define bit_cpu_IBRS_IBPB (1u << 26)
|
||||||
|
@@ -478,7 +478,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
#define index_cpu_IBT COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_INDEX_7_EDX_21 COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_AMX_BF16 COMMON_CPUID_INDEX_7
|
||||||
|
-#define index_cpu_INDEX_7_EDX_23 COMMON_CPUID_INDEX_7
|
||||||
|
+#define index_cpu_AVX512_FP16 COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_AMX_TILE COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_AMX_INT8 COMMON_CPUID_INDEX_7
|
||||||
|
#define index_cpu_IBRS_IBPB COMMON_CPUID_INDEX_7
|
||||||
|
@@ -697,7 +697,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
#define reg_IBT edx
|
||||||
|
#define reg_INDEX_7_EDX_21 edx
|
||||||
|
#define reg_AMX_BF16 edx
|
||||||
|
-#define reg_INDEX_7_EDX_23 edx
|
||||||
|
+#define reg_AVX512_FP16 edx
|
||||||
|
#define reg_AMX_TILE edx
|
||||||
|
#define reg_AMX_INT8 edx
|
||||||
|
#define reg_IBRS_IBPB edx
|
||||||
|
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
index 6fa092a8c10486a0..bcdeb243a82c4adc 100644
|
||||||
|
--- a/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
@@ -189,6 +189,7 @@ do_test (void)
|
||||||
|
CHECK_CPU_FEATURE (PCONFIG);
|
||||||
|
CHECK_CPU_FEATURE (IBT);
|
||||||
|
CHECK_CPU_FEATURE (AMX_BF16);
|
||||||
|
+ CHECK_CPU_FEATURE (AVX512_FP16);
|
||||||
|
CHECK_CPU_FEATURE (AMX_TILE);
|
||||||
|
CHECK_CPU_FEATURE (AMX_INT8);
|
||||||
|
CHECK_CPU_FEATURE (IBRS_IBPB);
|
||||||
|
@@ -343,6 +344,7 @@ do_test (void)
|
||||||
|
CHECK_CPU_FEATURE_USABLE (TSXLDTRK);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (PCONFIG);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (AMX_BF16);
|
||||||
|
+ CHECK_CPU_FEATURE_USABLE (AVX512_FP16);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (AMX_TILE);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (AMX_INT8);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (IBRS_IBPB);
|
83
SOURCES/glibc-rh1817513-103.patch
Normal file
83
SOURCES/glibc-rh1817513-103.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
commit 875a50ff63b2c86af770949d563ee851d08eb46e
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Oct 8 08:33:45 2020 -0700
|
||||||
|
|
||||||
|
<sys/platform/x86.h>: Add AVX-VNNI support
|
||||||
|
|
||||||
|
Add AVX-VNNI support to <sys/platform/x86.h>.
|
||||||
|
|
||||||
|
diff --git a/manual/platform.texi b/manual/platform.texi
|
||||||
|
index 4f5fdff9d9ef16fd..283f255679643d3e 100644
|
||||||
|
--- a/manual/platform.texi
|
||||||
|
+++ b/manual/platform.texi
|
||||||
|
@@ -198,6 +198,9 @@ The supported processor features are:
|
||||||
|
@item
|
||||||
|
@code{AVX2} -- The AVX2 instruction extensions.
|
||||||
|
|
||||||
|
+@item
|
||||||
|
+@code{AVX_VNNI} -- The AVX-VNNI instruction extensions.
|
||||||
|
+
|
||||||
|
@item
|
||||||
|
@code{AVX512_4FMAPS} -- The AVX512_4FMAPS instruction extensions.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index 67f137259fccf4ad..3e5b9341c9756009 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -119,6 +119,8 @@ update_usable (struct cpu_features *cpu_features)
|
||||||
|
cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load]
|
||||||
|
|= bit_arch_AVX_Fast_Unaligned_Load;
|
||||||
|
}
|
||||||
|
+ /* Determine if AVX-VNNI is usable. */
|
||||||
|
+ CPU_FEATURE_SET_USABLE (cpu_features, AVX_VNNI);
|
||||||
|
/* Determine if FMA is usable. */
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, FMA);
|
||||||
|
/* Determine if VAES is usable. */
|
||||||
|
diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
index 0b18257e20105ea4..0942ad7a7f7d4ce2 100644
|
||||||
|
--- a/sysdeps/x86/sys/platform/x86.h
|
||||||
|
+++ b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
@@ -311,6 +311,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* COMMON_CPUID_INDEX_7_ECX_1. */
|
||||||
|
|
||||||
|
/* EAX. */
|
||||||
|
+#define bit_cpu_AVX_VNNI (1u << 4)
|
||||||
|
#define bit_cpu_AVX512_BF16 (1u << 5)
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
@@ -530,6 +531,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* COMMON_CPUID_INDEX_7_ECX_1. */
|
||||||
|
|
||||||
|
/* EAX. */
|
||||||
|
+#define index_cpu_AVX_VNNI COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
#define index_cpu_AVX512_BF16 COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
@@ -749,6 +751,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* COMMON_CPUID_INDEX_7_ECX_1. */
|
||||||
|
|
||||||
|
/* EAX. */
|
||||||
|
+#define reg_AVX_VNNI eax
|
||||||
|
#define reg_AVX512_BF16 eax
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
index bcdeb243a82c4adc..8894d9f08ac36633 100644
|
||||||
|
--- a/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
@@ -219,6 +219,7 @@ do_test (void)
|
||||||
|
CHECK_CPU_FEATURE (XFD);
|
||||||
|
CHECK_CPU_FEATURE (INVARIANT_TSC);
|
||||||
|
CHECK_CPU_FEATURE (WBNOINVD);
|
||||||
|
+ CHECK_CPU_FEATURE (AVX_VNNI);
|
||||||
|
CHECK_CPU_FEATURE (AVX512_BF16);
|
||||||
|
CHECK_CPU_FEATURE (AESKLE);
|
||||||
|
CHECK_CPU_FEATURE (WIDE_KL);
|
||||||
|
@@ -374,6 +375,7 @@ do_test (void)
|
||||||
|
CHECK_CPU_FEATURE_USABLE (XFD);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (INVARIANT_TSC);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (WBNOINVD);
|
||||||
|
+ CHECK_CPU_FEATURE_USABLE (AVX_VNNI);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (AVX512_BF16);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (AESKLE);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (WIDE_KL);
|
62
SOURCES/glibc-rh1817513-104.patch
Normal file
62
SOURCES/glibc-rh1817513-104.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
commit c712401bc641b66d9bd558884751d8979e2e0e96
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Oct 8 08:38:03 2020 -0700
|
||||||
|
|
||||||
|
<sys/platform/x86.h>: Add Intel HRESET support
|
||||||
|
|
||||||
|
Add Intel HRESET support to <sys/platform/x86.h>.
|
||||||
|
|
||||||
|
diff --git a/manual/platform.texi b/manual/platform.texi
|
||||||
|
index 283f255679643d3e..1e44525552f5bda5 100644
|
||||||
|
--- a/manual/platform.texi
|
||||||
|
+++ b/manual/platform.texi
|
||||||
|
@@ -346,6 +346,9 @@ extensions.
|
||||||
|
@item
|
||||||
|
@code{HTT} -- Max APIC IDs reserved field is Valid.
|
||||||
|
|
||||||
|
+@item
|
||||||
|
+@code{HRESET} -- History reset.
|
||||||
|
+
|
||||||
|
@item
|
||||||
|
@code{HYBRID} -- Hybrid processor.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
index 0942ad7a7f7d4ce2..357c6f1c5605d82d 100644
|
||||||
|
--- a/sysdeps/x86/sys/platform/x86.h
|
||||||
|
+++ b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
@@ -313,6 +313,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* EAX. */
|
||||||
|
#define bit_cpu_AVX_VNNI (1u << 4)
|
||||||
|
#define bit_cpu_AVX512_BF16 (1u << 5)
|
||||||
|
+#define bit_cpu_HRESET (1u << 22)
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
|
||||||
|
@@ -533,6 +534,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* EAX. */
|
||||||
|
#define index_cpu_AVX_VNNI COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
#define index_cpu_AVX512_BF16 COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
+#define index_cpu_HRESET COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
|
||||||
|
@@ -753,6 +755,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* EAX. */
|
||||||
|
#define reg_AVX_VNNI eax
|
||||||
|
#define reg_AVX512_BF16 eax
|
||||||
|
+#define reg_HRESET eax
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
index 8894d9f08ac36633..1516af1d461a801b 100644
|
||||||
|
--- a/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
@@ -221,6 +221,7 @@ do_test (void)
|
||||||
|
CHECK_CPU_FEATURE (WBNOINVD);
|
||||||
|
CHECK_CPU_FEATURE (AVX_VNNI);
|
||||||
|
CHECK_CPU_FEATURE (AVX512_BF16);
|
||||||
|
+ CHECK_CPU_FEATURE (HRESET);
|
||||||
|
CHECK_CPU_FEATURE (AESKLE);
|
||||||
|
CHECK_CPU_FEATURE (WIDE_KL);
|
||||||
|
|
107
SOURCES/glibc-rh1817513-105.patch
Normal file
107
SOURCES/glibc-rh1817513-105.patch
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
commit 428985c436f442e91e27173bccaf28f547233586
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Oct 8 08:50:44 2020 -0700
|
||||||
|
|
||||||
|
<sys/platform/x86.h>: Add FSRCS/FSRS/FZLRM support
|
||||||
|
|
||||||
|
Add Fast Short REP CMP and SCA (FSRCS), Fast Short REP STO (FSRS) and
|
||||||
|
Fast Zero-Length REP MOV (FZLRM) support to <sys/platform/x86.h>.
|
||||||
|
|
||||||
|
diff --git a/manual/platform.texi b/manual/platform.texi
|
||||||
|
index 1e44525552f5bda5..8fec2933d6442823 100644
|
||||||
|
--- a/manual/platform.texi
|
||||||
|
+++ b/manual/platform.texi
|
||||||
|
@@ -331,12 +331,21 @@ extensions.
|
||||||
|
@item
|
||||||
|
@code{FSGSBASE} -- RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions.
|
||||||
|
|
||||||
|
+@item
|
||||||
|
+@code{FSRCS} -- Fast Short REP CMP and SCA.
|
||||||
|
+
|
||||||
|
@item
|
||||||
|
@code{FSRM} -- Fast Short REP MOV.
|
||||||
|
|
||||||
|
+@item
|
||||||
|
+@code{FSRS} -- Fast Short REP STO.
|
||||||
|
+
|
||||||
|
@item
|
||||||
|
@code{FXSR} -- FXSAVE and FXRSTOR instructions.
|
||||||
|
|
||||||
|
+@item
|
||||||
|
+@code{FZLRM} -- Fast Zero-Length REP MOV.
|
||||||
|
+
|
||||||
|
@item
|
||||||
|
@code{GFNI} -- GFNI instruction extensions.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index 3e5b9341c9756009..5f0548fe08134236 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -93,6 +93,9 @@ update_usable (struct cpu_features *cpu_features)
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, TBM);
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, RDTSCP);
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, WBNOINVD);
|
||||||
|
+ CPU_FEATURE_SET_USABLE (cpu_features, FZLRM);
|
||||||
|
+ CPU_FEATURE_SET_USABLE (cpu_features, FSRS);
|
||||||
|
+ CPU_FEATURE_SET_USABLE (cpu_features, FSRCS);
|
||||||
|
|
||||||
|
/* Can we call xgetbv? */
|
||||||
|
if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE))
|
||||||
|
diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
index 357c6f1c5605d82d..e5cc7c683a20b5a0 100644
|
||||||
|
--- a/sysdeps/x86/sys/platform/x86.h
|
||||||
|
+++ b/sysdeps/x86/sys/platform/x86.h
|
||||||
|
@@ -313,6 +313,9 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* EAX. */
|
||||||
|
#define bit_cpu_AVX_VNNI (1u << 4)
|
||||||
|
#define bit_cpu_AVX512_BF16 (1u << 5)
|
||||||
|
+#define bit_cpu_FZLRM (1u << 10)
|
||||||
|
+#define bit_cpu_FSRS (1u << 11)
|
||||||
|
+#define bit_cpu_FSRCS (1u << 12)
|
||||||
|
#define bit_cpu_HRESET (1u << 22)
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
@@ -534,6 +537,9 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* EAX. */
|
||||||
|
#define index_cpu_AVX_VNNI COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
#define index_cpu_AVX512_BF16 COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
+#define index_cpu_FZLRM COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
+#define index_cpu_FSRS COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
+#define index_cpu_FSRCS COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
#define index_cpu_HRESET COMMON_CPUID_INDEX_7_ECX_1
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
@@ -755,6 +761,9 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int)
|
||||||
|
/* EAX. */
|
||||||
|
#define reg_AVX_VNNI eax
|
||||||
|
#define reg_AVX512_BF16 eax
|
||||||
|
+#define reg_FZLRM eax
|
||||||
|
+#define reg_FSRS eax
|
||||||
|
+#define reg_FSRCS eax
|
||||||
|
#define reg_HRESET eax
|
||||||
|
|
||||||
|
/* COMMON_CPUID_INDEX_19. */
|
||||||
|
diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
index 1516af1d461a801b..2763deb6d008597f 100644
|
||||||
|
--- a/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/tst-get-cpu-features.c
|
||||||
|
@@ -221,6 +221,9 @@ do_test (void)
|
||||||
|
CHECK_CPU_FEATURE (WBNOINVD);
|
||||||
|
CHECK_CPU_FEATURE (AVX_VNNI);
|
||||||
|
CHECK_CPU_FEATURE (AVX512_BF16);
|
||||||
|
+ CHECK_CPU_FEATURE (FZLRM);
|
||||||
|
+ CHECK_CPU_FEATURE (FSRS);
|
||||||
|
+ CHECK_CPU_FEATURE (FSRCS);
|
||||||
|
CHECK_CPU_FEATURE (HRESET);
|
||||||
|
CHECK_CPU_FEATURE (AESKLE);
|
||||||
|
CHECK_CPU_FEATURE (WIDE_KL);
|
||||||
|
@@ -378,6 +381,9 @@ do_test (void)
|
||||||
|
CHECK_CPU_FEATURE_USABLE (WBNOINVD);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (AVX_VNNI);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (AVX512_BF16);
|
||||||
|
+ CHECK_CPU_FEATURE_USABLE (FZLRM);
|
||||||
|
+ CHECK_CPU_FEATURE_USABLE (FSRS);
|
||||||
|
+ CHECK_CPU_FEATURE_USABLE (FSRCS);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (AESKLE);
|
||||||
|
CHECK_CPU_FEATURE_USABLE (WIDE_KL);
|
||||||
|
|
18
SOURCES/glibc-rh1817513-106.patch
Normal file
18
SOURCES/glibc-rh1817513-106.patch
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
commit 21181d1c7b181c4bb71e587c7944e100d923b393
|
||||||
|
Author: Matheus Castanho <msc@linux.ibm.com>
|
||||||
|
Date: Mon Oct 12 11:28:18 2020 +0200
|
||||||
|
|
||||||
|
elf: Add missing <dl-procinfo.h> header to elf/dl-usage.c
|
||||||
|
|
||||||
|
diff --git a/elf/dl-usage.c b/elf/dl-usage.c
|
||||||
|
index c07f43835bd771cf..796ad38b43c2211b 100644
|
||||||
|
--- a/elf/dl-usage.c
|
||||||
|
+++ b/elf/dl-usage.c
|
||||||
|
@@ -22,6 +22,7 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
+#include <dl-procinfo.h>
|
||||||
|
#include <dl-hwcaps.h>
|
||||||
|
|
||||||
|
void
|
2017
SOURCES/glibc-rh1817513-107.patch
Normal file
2017
SOURCES/glibc-rh1817513-107.patch
Normal file
File diff suppressed because it is too large
Load Diff
364
SOURCES/glibc-rh1817513-108.patch
Normal file
364
SOURCES/glibc-rh1817513-108.patch
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
commit de1a9197af7f67a89f929dcadb8ceca8c3846b1c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Oct 30 11:57:59 2020 +0100
|
||||||
|
|
||||||
|
elf: Unify old and new format cache handling code in ld.so
|
||||||
|
|
||||||
|
struct file_entry_new starts with the fields of struct file_entry,
|
||||||
|
so the code can be shared if the size computation is made dynamic.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
|
||||||
|
index ef37ca18fa9fb6e0..366a051dfcd26132 100644
|
||||||
|
--- a/elf/dl-cache.c
|
||||||
|
+++ b/elf/dl-cache.c
|
||||||
|
@@ -35,103 +35,141 @@ static struct cache_file *cache;
|
||||||
|
static struct cache_file_new *cache_new;
|
||||||
|
static size_t cachesize;
|
||||||
|
|
||||||
|
-/* 1 if cache_data + PTR points into the cache. */
|
||||||
|
-#define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
|
||||||
|
-
|
||||||
|
-#define SEARCH_CACHE(cache) \
|
||||||
|
-/* We use binary search since the table is sorted in the cache file. \
|
||||||
|
- The first matching entry in the table is returned. \
|
||||||
|
- It is important to use the same algorithm as used while generating \
|
||||||
|
- the cache file. */ \
|
||||||
|
-do \
|
||||||
|
- { \
|
||||||
|
- left = 0; \
|
||||||
|
- right = cache->nlibs - 1; \
|
||||||
|
- \
|
||||||
|
- while (left <= right) \
|
||||||
|
- { \
|
||||||
|
- __typeof__ (cache->libs[0].key) key; \
|
||||||
|
- \
|
||||||
|
- middle = (left + right) / 2; \
|
||||||
|
- \
|
||||||
|
- key = cache->libs[middle].key; \
|
||||||
|
- \
|
||||||
|
- /* Make sure string table indices are not bogus before using \
|
||||||
|
- them. */ \
|
||||||
|
- if (! _dl_cache_verify_ptr (key)) \
|
||||||
|
- { \
|
||||||
|
- cmpres = 1; \
|
||||||
|
- break; \
|
||||||
|
- } \
|
||||||
|
- \
|
||||||
|
- /* Actually compare the entry with the key. */ \
|
||||||
|
- cmpres = _dl_cache_libcmp (name, cache_data + key); \
|
||||||
|
- if (__glibc_unlikely (cmpres == 0)) \
|
||||||
|
- { \
|
||||||
|
- /* Found it. LEFT now marks the last entry for which we \
|
||||||
|
- know the name is correct. */ \
|
||||||
|
- left = middle; \
|
||||||
|
- \
|
||||||
|
- /* There might be entries with this name before the one we \
|
||||||
|
- found. So we have to find the beginning. */ \
|
||||||
|
- while (middle > 0) \
|
||||||
|
- { \
|
||||||
|
- __typeof__ (cache->libs[0].key) key; \
|
||||||
|
- \
|
||||||
|
- key = cache->libs[middle - 1].key; \
|
||||||
|
- /* Make sure string table indices are not bogus before \
|
||||||
|
- using them. */ \
|
||||||
|
- if (! _dl_cache_verify_ptr (key) \
|
||||||
|
- /* Actually compare the entry. */ \
|
||||||
|
- || _dl_cache_libcmp (name, cache_data + key) != 0) \
|
||||||
|
- break; \
|
||||||
|
- --middle; \
|
||||||
|
- } \
|
||||||
|
- \
|
||||||
|
- do \
|
||||||
|
- { \
|
||||||
|
- int flags; \
|
||||||
|
- __typeof__ (cache->libs[0]) *lib = &cache->libs[middle]; \
|
||||||
|
- \
|
||||||
|
- /* Only perform the name test if necessary. */ \
|
||||||
|
- if (middle > left \
|
||||||
|
- /* We haven't seen this string so far. Test whether the \
|
||||||
|
- index is ok and whether the name matches. Otherwise \
|
||||||
|
- we are done. */ \
|
||||||
|
- && (! _dl_cache_verify_ptr (lib->key) \
|
||||||
|
- || (_dl_cache_libcmp (name, cache_data + lib->key) \
|
||||||
|
- != 0))) \
|
||||||
|
- break; \
|
||||||
|
- \
|
||||||
|
- flags = lib->flags; \
|
||||||
|
- if (_dl_cache_check_flags (flags) \
|
||||||
|
- && _dl_cache_verify_ptr (lib->value)) \
|
||||||
|
- { \
|
||||||
|
- if (best == NULL || flags == GLRO(dl_correct_cache_id)) \
|
||||||
|
- { \
|
||||||
|
- HWCAP_CHECK; \
|
||||||
|
- best = cache_data + lib->value; \
|
||||||
|
- \
|
||||||
|
- if (flags == GLRO(dl_correct_cache_id)) \
|
||||||
|
- /* We've found an exact match for the shared \
|
||||||
|
- object and no general `ELF' release. Stop \
|
||||||
|
- searching. */ \
|
||||||
|
- break; \
|
||||||
|
- } \
|
||||||
|
- } \
|
||||||
|
- } \
|
||||||
|
- while (++middle <= right); \
|
||||||
|
- break; \
|
||||||
|
- } \
|
||||||
|
- \
|
||||||
|
- if (cmpres < 0) \
|
||||||
|
- left = middle + 1; \
|
||||||
|
- else \
|
||||||
|
- right = middle - 1; \
|
||||||
|
- } \
|
||||||
|
- } \
|
||||||
|
-while (0)
|
||||||
|
+/* True if PTR is a valid string table index. */
|
||||||
|
+static inline bool
|
||||||
|
+_dl_cache_verify_ptr (uint32_t ptr, size_t string_table_size)
|
||||||
|
+{
|
||||||
|
+ return ptr < string_table_size;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Compute the address of the element INDEX of the array at LIBS.
|
||||||
|
+ Conceptually, this is &LIBS[INDEX], but use ENTRY_SIZE for the size
|
||||||
|
+ of *LIBS. */
|
||||||
|
+static inline const struct file_entry *
|
||||||
|
+_dl_cache_file_entry (const struct file_entry *libs, size_t entry_size,
|
||||||
|
+ size_t index)
|
||||||
|
+{
|
||||||
|
+ return (const void *) libs + index * entry_size;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* We use binary search since the table is sorted in the cache file.
|
||||||
|
+ The first matching entry in the table is returned. It is important
|
||||||
|
+ to use the same algorithm as used while generating the cache file.
|
||||||
|
+ STRING_TABLE_SIZE indicates the maximum offset in STRING_TABLE at
|
||||||
|
+ which data is mapped; it is not exact. */
|
||||||
|
+static const char *
|
||||||
|
+search_cache (const char *string_table, uint32_t string_table_size,
|
||||||
|
+ struct file_entry *libs, uint32_t nlibs, uint32_t entry_size,
|
||||||
|
+ const char *name)
|
||||||
|
+{
|
||||||
|
+ /* Used by the HWCAP check in the struct file_entry_new case. */
|
||||||
|
+ uint64_t platform = _dl_string_platform (GLRO (dl_platform));
|
||||||
|
+ 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) & hwcap_mask)
|
||||||
|
+ | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK);
|
||||||
|
+
|
||||||
|
+ int left = 0;
|
||||||
|
+ int right = nlibs - 1;
|
||||||
|
+ const char *best = NULL;
|
||||||
|
+
|
||||||
|
+ while (left <= right)
|
||||||
|
+ {
|
||||||
|
+ int middle = (left + right) / 2;
|
||||||
|
+ uint32_t key = _dl_cache_file_entry (libs, entry_size, middle)->key;
|
||||||
|
+
|
||||||
|
+ /* Make sure string table indices are not bogus before using
|
||||||
|
+ them. */
|
||||||
|
+ if (!_dl_cache_verify_ptr (key, string_table_size))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ /* Actually compare the entry with the key. */
|
||||||
|
+ int cmpres = _dl_cache_libcmp (name, string_table + key);
|
||||||
|
+ if (__glibc_unlikely (cmpres == 0))
|
||||||
|
+ {
|
||||||
|
+ /* Found it. LEFT now marks the last entry for which we
|
||||||
|
+ know the name is correct. */
|
||||||
|
+ left = middle;
|
||||||
|
+
|
||||||
|
+ /* There might be entries with this name before the one we
|
||||||
|
+ found. So we have to find the beginning. */
|
||||||
|
+ while (middle > 0)
|
||||||
|
+ {
|
||||||
|
+ key = _dl_cache_file_entry (libs, entry_size, middle - 1)->key;
|
||||||
|
+ /* Make sure string table indices are not bogus before
|
||||||
|
+ using them. */
|
||||||
|
+ if (!_dl_cache_verify_ptr (key, string_table_size)
|
||||||
|
+ /* Actually compare the entry. */
|
||||||
|
+ || _dl_cache_libcmp (name, string_table + key) != 0)
|
||||||
|
+ break;
|
||||||
|
+ --middle;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ do
|
||||||
|
+ {
|
||||||
|
+ int flags;
|
||||||
|
+ const struct file_entry *lib
|
||||||
|
+ = _dl_cache_file_entry (libs, entry_size, middle);
|
||||||
|
+
|
||||||
|
+ /* Only perform the name test if necessary. */
|
||||||
|
+ if (middle > left
|
||||||
|
+ /* We haven't seen this string so far. Test whether the
|
||||||
|
+ index is ok and whether the name matches. Otherwise
|
||||||
|
+ we are done. */
|
||||||
|
+ && (! _dl_cache_verify_ptr (lib->key, string_table_size)
|
||||||
|
+ || (_dl_cache_libcmp (name, string_table + lib->key)
|
||||||
|
+ != 0)))
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ flags = lib->flags;
|
||||||
|
+ if (_dl_cache_check_flags (flags)
|
||||||
|
+ && _dl_cache_verify_ptr (lib->value, string_table_size))
|
||||||
|
+ {
|
||||||
|
+ if (best == NULL || flags == GLRO (dl_correct_cache_id))
|
||||||
|
+ {
|
||||||
|
+ if (entry_size >= sizeof (struct file_entry_new))
|
||||||
|
+ {
|
||||||
|
+ /* The entry is large enough to include
|
||||||
|
+ HWCAP data. Check it. */
|
||||||
|
+ struct file_entry_new *libnew
|
||||||
|
+ = (struct file_entry_new *) lib;
|
||||||
|
+
|
||||||
|
+ if (libnew->hwcap & hwcap_exclude)
|
||||||
|
+ continue;
|
||||||
|
+ if (GLRO (dl_osversion)
|
||||||
|
+ && libnew->osversion > GLRO (dl_osversion))
|
||||||
|
+ continue;
|
||||||
|
+ if (_DL_PLATFORMS_COUNT
|
||||||
|
+ && (libnew->hwcap & _DL_HWCAP_PLATFORM) != 0
|
||||||
|
+ && ((libnew->hwcap & _DL_HWCAP_PLATFORM)
|
||||||
|
+ != platform))
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ best = string_table + lib->value;
|
||||||
|
+
|
||||||
|
+ if (flags == GLRO (dl_correct_cache_id))
|
||||||
|
+ /* We've found an exact match for the shared
|
||||||
|
+ object and no general `ELF' release. Stop
|
||||||
|
+ searching. */
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ while (++middle <= right);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ if (cmpres < 0)
|
||||||
|
+ left = middle + 1;
|
||||||
|
+ else
|
||||||
|
+ right = middle - 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return best;
|
||||||
|
+}
|
||||||
|
|
||||||
|
int
|
||||||
|
_dl_cache_libcmp (const char *p1, const char *p2)
|
||||||
|
@@ -182,12 +220,6 @@ _dl_cache_libcmp (const char *p1, const char *p2)
|
||||||
|
char *
|
||||||
|
_dl_load_cache_lookup (const char *name)
|
||||||
|
{
|
||||||
|
- int left, right, middle;
|
||||||
|
- int cmpres;
|
||||||
|
- const char *cache_data;
|
||||||
|
- uint32_t cache_data_size;
|
||||||
|
- const char *best;
|
||||||
|
-
|
||||||
|
/* Print a message if the loading of libs is traced. */
|
||||||
|
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
|
||||||
|
_dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
|
||||||
|
@@ -247,51 +279,22 @@ _dl_load_cache_lookup (const char *name)
|
||||||
|
/* Previously looked for the cache file and didn't find it. */
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
- best = NULL;
|
||||||
|
-
|
||||||
|
+ const char *best;
|
||||||
|
if (cache_new != (void *) -1)
|
||||||
|
{
|
||||||
|
- uint64_t platform;
|
||||||
|
-
|
||||||
|
- /* This is where the strings start. */
|
||||||
|
- cache_data = (const char *) cache_new;
|
||||||
|
-
|
||||||
|
- /* Now we can compute how large the string table is. */
|
||||||
|
- cache_data_size = (const char *) cache + cachesize - cache_data;
|
||||||
|
-
|
||||||
|
- platform = _dl_string_platform (GLRO(dl_platform));
|
||||||
|
- 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) & hwcap_mask)
|
||||||
|
- | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK);
|
||||||
|
-
|
||||||
|
- /* Only accept hwcap if it's for the right platform. */
|
||||||
|
-#define HWCAP_CHECK \
|
||||||
|
- if (lib->hwcap & hwcap_exclude) \
|
||||||
|
- continue; \
|
||||||
|
- if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion)) \
|
||||||
|
- continue; \
|
||||||
|
- if (_DL_PLATFORMS_COUNT \
|
||||||
|
- && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0 \
|
||||||
|
- && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform) \
|
||||||
|
- continue
|
||||||
|
- SEARCH_CACHE (cache_new);
|
||||||
|
+ const char *string_table = (const char *) cache_new;
|
||||||
|
+ best = search_cache (string_table, cachesize,
|
||||||
|
+ &cache_new->libs[0].entry, cache_new->nlibs,
|
||||||
|
+ sizeof (cache_new->libs[0]), name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- /* This is where the strings start. */
|
||||||
|
- cache_data = (const char *) &cache->libs[cache->nlibs];
|
||||||
|
-
|
||||||
|
- /* Now we can compute how large the string table is. */
|
||||||
|
- cache_data_size = (const char *) cache + cachesize - cache_data;
|
||||||
|
-
|
||||||
|
-#undef HWCAP_CHECK
|
||||||
|
-#define HWCAP_CHECK do {} while (0)
|
||||||
|
- SEARCH_CACHE (cache);
|
||||||
|
+ const char *string_table = (const char *) &cache->libs[cache->nlibs];
|
||||||
|
+ uint32_t string_table_size
|
||||||
|
+ = (const char *) cache + cachesize - string_table;
|
||||||
|
+ best = search_cache (string_table, string_table_size,
|
||||||
|
+ &cache->libs[0], cache->nlibs,
|
||||||
|
+ sizeof (cache->libs[0]), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print our result if wanted. */
|
||||||
|
diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
|
||||||
|
index cf43f1cf3b441bc7..3c5730dfe42c7c88 100644
|
||||||
|
--- a/sysdeps/generic/dl-cache.h
|
||||||
|
+++ b/sysdeps/generic/dl-cache.h
|
||||||
|
@@ -59,8 +59,8 @@
|
||||||
|
*/
|
||||||
|
struct file_entry
|
||||||
|
{
|
||||||
|
- int flags; /* This is 1 for an ELF library. */
|
||||||
|
- unsigned int key, value; /* String table indices. */
|
||||||
|
+ int32_t flags; /* This is 1 for an ELF library. */
|
||||||
|
+ uint32_t key, value; /* String table indices. */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cache_file
|
||||||
|
@@ -77,8 +77,17 @@ struct cache_file
|
||||||
|
|
||||||
|
struct file_entry_new
|
||||||
|
{
|
||||||
|
- int32_t flags; /* This is 1 for an ELF library. */
|
||||||
|
- uint32_t key, value; /* String table indices. */
|
||||||
|
+ union
|
||||||
|
+ {
|
||||||
|
+ /* Fields shared with struct file_entry. */
|
||||||
|
+ struct file_entry entry;
|
||||||
|
+ /* Also expose these fields directly. */
|
||||||
|
+ struct
|
||||||
|
+ {
|
||||||
|
+ int32_t flags; /* This is 1 for an ELF library. */
|
||||||
|
+ uint32_t key, value; /* String table indices. */
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
uint32_t osversion; /* Required OS version. */
|
||||||
|
uint64_t hwcap; /* Hwcap entry. */
|
||||||
|
};
|
67
SOURCES/glibc-rh1817513-109.patch
Normal file
67
SOURCES/glibc-rh1817513-109.patch
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
commit 5e598c2bbf938eac0f4045f5143f9dd723646672
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Oct 30 18:40:28 2020 +0100
|
||||||
|
|
||||||
|
elf: In ldconfig, extract the new_sub_entry function from search_dir
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||||
|
index 7c8fd29387463a8a..be730ceb075f6c1f 100644
|
||||||
|
--- a/elf/ldconfig.c
|
||||||
|
+++ b/elf/ldconfig.c
|
||||||
|
@@ -328,6 +328,23 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
|
||||||
|
"Andreas Jaeger");
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Allocate a new subdirectory with full path PATH under ENTRY, using
|
||||||
|
+ inode data from *ST. */
|
||||||
|
+static struct dir_entry *
|
||||||
|
+new_sub_entry (const struct dir_entry *entry, const char *path,
|
||||||
|
+ const struct stat64 *st)
|
||||||
|
+{
|
||||||
|
+ struct dir_entry *new_entry = xmalloc (sizeof (struct dir_entry));
|
||||||
|
+ new_entry->from_file = entry->from_file;
|
||||||
|
+ new_entry->from_line = entry->from_line;
|
||||||
|
+ new_entry->path = xstrdup (path);
|
||||||
|
+ new_entry->flag = entry->flag;
|
||||||
|
+ new_entry->next = NULL;
|
||||||
|
+ new_entry->ino = st->st_ino;
|
||||||
|
+ new_entry->dev = st->st_dev;
|
||||||
|
+ return new_entry;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Add a single directory entry. */
|
||||||
|
static void
|
||||||
|
add_single_dir (struct dir_entry *entry, int verbose)
|
||||||
|
@@ -823,26 +840,17 @@ search_dir (const struct dir_entry *entry)
|
||||||
|
|
||||||
|
if (is_dir && is_hwcap_platform (direntry->d_name))
|
||||||
|
{
|
||||||
|
- /* Handle subdirectory later. */
|
||||||
|
- struct dir_entry *new_entry;
|
||||||
|
-
|
||||||
|
- new_entry = xmalloc (sizeof (struct dir_entry));
|
||||||
|
- new_entry->from_file = entry->from_file;
|
||||||
|
- new_entry->from_line = entry->from_line;
|
||||||
|
- new_entry->path = xstrdup (file_name);
|
||||||
|
- new_entry->flag = entry->flag;
|
||||||
|
- new_entry->next = NULL;
|
||||||
|
if (!is_link
|
||||||
|
&& direntry->d_type != DT_UNKNOWN
|
||||||
|
&& __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
|
||||||
|
{
|
||||||
|
error (0, errno, _("Cannot lstat %s"), file_name);
|
||||||
|
- free (new_entry->path);
|
||||||
|
- free (new_entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- new_entry->ino = lstat_buf.st_ino;
|
||||||
|
- new_entry->dev = lstat_buf.st_dev;
|
||||||
|
+
|
||||||
|
+ /* Handle subdirectory later. */
|
||||||
|
+ struct dir_entry *new_entry = new_sub_entry (entry, file_name,
|
||||||
|
+ &lstat_buf);
|
||||||
|
add_single_dir (new_entry, 0);
|
||||||
|
continue;
|
||||||
|
}
|
79
SOURCES/glibc-rh1817513-11.patch
Normal file
79
SOURCES/glibc-rh1817513-11.patch
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
commit 7cc65773f04e0f4252428c40dcbb784a39b58cd1
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Wed Oct 24 02:19:15 2018 -0700
|
||||||
|
|
||||||
|
x86: Support RDTSCP for benchtests
|
||||||
|
|
||||||
|
RDTSCP waits until all previous instructions have executed and all
|
||||||
|
previous loads are globally visible before reading the counter. RDTSC
|
||||||
|
doesn't wait until all previous instructions have been executed before
|
||||||
|
reading the counter. All x86 processors since 2010 support RDTSCP
|
||||||
|
instruction. This patch adds RDTSCP support to benchtests.
|
||||||
|
|
||||||
|
* benchtests/Makefile (CPPFLAGS-nonlib): Add -DUSE_RDTSCP if
|
||||||
|
USE_RDTSCP is defined.
|
||||||
|
* sysdeps/x86/hp-timing.h (HP_TIMING_NOW): Use RDTSCP if
|
||||||
|
USE_RDTSCP is defined.
|
||||||
|
|
||||||
|
diff --git a/benchtests/Makefile b/benchtests/Makefile
|
||||||
|
index 28d6b0c43f5bd390..bde0caf140e8cf17 100644
|
||||||
|
--- a/benchtests/Makefile
|
||||||
|
+++ b/benchtests/Makefile
|
||||||
|
@@ -131,6 +131,12 @@ CPPFLAGS-nonlib += -DDURATION=$(BENCH_DURATION) -D_ISOMAC
|
||||||
|
# HP_TIMING if it is available.
|
||||||
|
ifdef USE_CLOCK_GETTIME
|
||||||
|
CPPFLAGS-nonlib += -DUSE_CLOCK_GETTIME
|
||||||
|
+else
|
||||||
|
+# On x86 processors, use RDTSCP, instead of RDTSC, to measure performance
|
||||||
|
+# of functions. All x86 processors since 2010 support RDTSCP instruction.
|
||||||
|
+ifdef USE_RDTSCP
|
||||||
|
+CPPFLAGS-nonlib += -DUSE_RDTSCP
|
||||||
|
+endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
DETAILED_OPT :=
|
||||||
|
diff --git a/benchtests/README b/benchtests/README
|
||||||
|
index 4ddff794d136f65f..aaf0b659e2b25627 100644
|
||||||
|
--- a/benchtests/README
|
||||||
|
+++ b/benchtests/README
|
||||||
|
@@ -34,6 +34,15 @@ the benchmark to use clock_gettime by invoking make as follows:
|
||||||
|
|
||||||
|
Again, one must run `make bench-clean' before changing the measurement method.
|
||||||
|
|
||||||
|
+On x86 processors, RDTSCP instruction provides more precise timing data
|
||||||
|
+than RDTSC instruction. All x86 processors since 2010 support RDTSCP
|
||||||
|
+instruction. One can force the benchmark to use RDTSCP by invoking make
|
||||||
|
+as follows:
|
||||||
|
+
|
||||||
|
+ $ make USE_RDTSCP=1 bench
|
||||||
|
+
|
||||||
|
+One must run `make bench-clean' before changing the measurement method.
|
||||||
|
+
|
||||||
|
Running benchmarks on another target:
|
||||||
|
====================================
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/hp-timing.h b/sysdeps/x86/hp-timing.h
|
||||||
|
index 77a1360748ca4535..0aa6f5e3f83e0d34 100644
|
||||||
|
--- a/sysdeps/x86/hp-timing.h
|
||||||
|
+++ b/sysdeps/x86/hp-timing.h
|
||||||
|
@@ -40,7 +40,19 @@ typedef unsigned long long int hp_timing_t;
|
||||||
|
|
||||||
|
NB: Use __builtin_ia32_rdtsc directly since including <x86intrin.h>
|
||||||
|
makes building glibc very slow. */
|
||||||
|
-# define HP_TIMING_NOW(Var) ((Var) = __builtin_ia32_rdtsc ())
|
||||||
|
+# ifdef USE_RDTSCP
|
||||||
|
+/* RDTSCP waits until all previous instructions have executed and all
|
||||||
|
+ previous loads are globally visible before reading the counter.
|
||||||
|
+ RDTSC doesn't wait until all previous instructions have been executed
|
||||||
|
+ before reading the counter. */
|
||||||
|
+# define HP_TIMING_NOW(Var) \
|
||||||
|
+ (__extension__ ({ \
|
||||||
|
+ unsigned int __aux; \
|
||||||
|
+ (Var) = __builtin_ia32_rdtscp (&__aux); \
|
||||||
|
+ }))
|
||||||
|
+# else
|
||||||
|
+# define HP_TIMING_NOW(Var) ((Var) = __builtin_ia32_rdtsc ())
|
||||||
|
+# endif
|
||||||
|
|
||||||
|
# include <hp-timing-common.h>
|
||||||
|
#else
|
22
SOURCES/glibc-rh1817513-110.patch
Normal file
22
SOURCES/glibc-rh1817513-110.patch
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
commit df5f473ed5ee95e3179fcb239e33e971619626cd
|
||||||
|
Author: Shuo Wang <wangshuo47@huawei.com>
|
||||||
|
Date: Tue Nov 24 16:42:18 2020 -0300
|
||||||
|
|
||||||
|
elf: Fix uninitialized variable for _dl_write
|
||||||
|
|
||||||
|
Variable ret in elf/dl-write.c is uninitialized, which should get
|
||||||
|
return value from __writev.
|
||||||
|
|
||||||
|
diff --git a/elf/dl-write.c b/elf/dl-write.c
|
||||||
|
index 7350aff0035d4fbc..9b741c8a8fe12f6c 100644
|
||||||
|
--- a/elf/dl-write.c
|
||||||
|
+++ b/elf/dl-write.c
|
||||||
|
@@ -41,7 +41,7 @@ _dl_write (int fd, const void *buffer, size_t length)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
||||||
|
- __writev (fd, &iov, 1);
|
||||||
|
+ ret = __writev (fd, &iov, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
ret = -errno;
|
||||||
|
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
85
SOURCES/glibc-rh1817513-111.patch
Normal file
85
SOURCES/glibc-rh1817513-111.patch
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
commit 603ae243f6fe03208a3bb92adecf72403367bd95
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Nov 26 16:59:44 2020 +0100
|
||||||
|
|
||||||
|
support: Add support_copy_file
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 895b83a426369b0c..35b21b19a248ba7f 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -46,6 +46,7 @@ libsupport-routines = \
|
||||||
|
support_capture_subprocess \
|
||||||
|
support_capture_subprocess_check \
|
||||||
|
support_chroot \
|
||||||
|
+ support_copy_file \
|
||||||
|
support_copy_file_range \
|
||||||
|
support_descriptor_supports_holes \
|
||||||
|
support_descriptors \
|
||||||
|
diff --git a/support/support.h b/support/support.h
|
||||||
|
index 3af87f85fe1b762d..6f7f804847f67600 100644
|
||||||
|
--- a/support/support.h
|
||||||
|
+++ b/support/support.h
|
||||||
|
@@ -115,6 +115,11 @@ extern const char support_install_rootsbindir[];
|
||||||
|
/* Corresponds to the install's compiled locale directory. */
|
||||||
|
extern const char support_complocaledir_prefix[];
|
||||||
|
|
||||||
|
+/* Copies the file at the path FROM to TO. If TO does not exist, it
|
||||||
|
+ is created. If TO is a regular file, it is truncated before
|
||||||
|
+ copying. The file mode is copied, but the permissions are not. */
|
||||||
|
+extern void support_copy_file (const char *from, const char *to);
|
||||||
|
+
|
||||||
|
extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *,
|
||||||
|
size_t, unsigned int);
|
||||||
|
|
||||||
|
diff --git a/support/support_copy_file.c b/support/support_copy_file.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..c93e1e58c81b749d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/support_copy_file.c
|
||||||
|
@@ -0,0 +1,43 @@
|
||||||
|
+/* Copy a file from one path to another.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+support_copy_file (const char *from, const char *to)
|
||||||
|
+{
|
||||||
|
+ struct stat64 st;
|
||||||
|
+ xstat (from, &st);
|
||||||
|
+ int fd_from = xopen (from, O_RDONLY, 0);
|
||||||
|
+ mode_t mode = st.st_mode & 0777;
|
||||||
|
+ int fd_to = xopen (to, O_WRONLY | O_TRUNC | O_CREAT, mode);
|
||||||
|
+ ssize_t ret = support_copy_file_range (fd_from, NULL, fd_to, NULL,
|
||||||
|
+ st.st_size, 0);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ FAIL_EXIT1 ("copying from \"%s\" to \"%s\": %m", from, to);
|
||||||
|
+ if (ret != st.st_size)
|
||||||
|
+ FAIL_EXIT1 ("copying from \"%s\" to \"%s\": only %zd of %llu bytes copied",
|
||||||
|
+ from, to, ret, (unsigned long long int) st.st_size);
|
||||||
|
+ if (fchmod (fd_to, mode) < 0)
|
||||||
|
+ FAIL_EXIT1 ("fchmod on %s to 0%o: %m", to, mode);
|
||||||
|
+ xclose (fd_to);
|
||||||
|
+ xclose (fd_from);
|
||||||
|
+}
|
152
SOURCES/glibc-rh1817513-112.patch
Normal file
152
SOURCES/glibc-rh1817513-112.patch
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
commit db07fae8250401adb2b97ab3e53d41da2a6bd767
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Nov 26 16:59:44 2020 +0100
|
||||||
|
|
||||||
|
elf: Introduce enum opt_format in the ldconfig implementation
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/cache.c b/elf/cache.c
|
||||||
|
index c4cd825c30e00e8e..edcdd4b7cc1a6a0b 100644
|
||||||
|
--- a/elf/cache.c
|
||||||
|
+++ b/elf/cache.c
|
||||||
|
@@ -321,13 +321,13 @@ save_cache (const char *cache_name)
|
||||||
|
struct cache_file *file_entries = NULL;
|
||||||
|
size_t file_entries_size = 0;
|
||||||
|
|
||||||
|
- if (opt_format != 2)
|
||||||
|
+ if (opt_format != opt_format_new)
|
||||||
|
{
|
||||||
|
/* struct cache_file_new is 64-bit aligned on some arches while
|
||||||
|
only 32-bit aligned on other arches. Duplicate last old
|
||||||
|
cache entry so that new cache in ld.so.cache can be used by
|
||||||
|
both. */
|
||||||
|
- if (opt_format != 0)
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
cache_entry_old_count = (cache_entry_old_count + 1) & ~1;
|
||||||
|
|
||||||
|
/* And the list of all entries in the old format. */
|
||||||
|
@@ -345,7 +345,7 @@ save_cache (const char *cache_name)
|
||||||
|
struct cache_file_new *file_entries_new = NULL;
|
||||||
|
size_t file_entries_new_size = 0;
|
||||||
|
|
||||||
|
- if (opt_format != 0)
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
{
|
||||||
|
/* And the list of all entries in the new format. */
|
||||||
|
file_entries_new_size = sizeof (struct cache_file_new)
|
||||||
|
@@ -370,7 +370,7 @@ save_cache (const char *cache_name)
|
||||||
|
table, we have to adjust all string indices for this so that
|
||||||
|
old libc5/glibc 2 dynamic linkers just ignore them. */
|
||||||
|
unsigned int str_offset;
|
||||||
|
- if (opt_format != 0)
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
str_offset = file_entries_new_size;
|
||||||
|
else
|
||||||
|
str_offset = 0;
|
||||||
|
@@ -385,13 +385,13 @@ save_cache (const char *cache_name)
|
||||||
|
entry = entry->next, ++idx_new)
|
||||||
|
{
|
||||||
|
/* First the library. */
|
||||||
|
- if (opt_format != 2 && entry->hwcap == 0)
|
||||||
|
+ if (opt_format != opt_format_new && entry->hwcap == 0)
|
||||||
|
{
|
||||||
|
file_entries->libs[idx_old].flags = entry->flags;
|
||||||
|
/* XXX: Actually we can optimize here and remove duplicates. */
|
||||||
|
file_entries->libs[idx_old].key = str_offset + pad;
|
||||||
|
}
|
||||||
|
- if (opt_format != 0)
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
{
|
||||||
|
/* We could subtract file_entries_new_size from str_offset -
|
||||||
|
not doing so makes the code easier, the string table
|
||||||
|
@@ -407,9 +407,9 @@ save_cache (const char *cache_name)
|
||||||
|
str = mempcpy (str, entry->lib, len);
|
||||||
|
str_offset += len;
|
||||||
|
/* Then the path. */
|
||||||
|
- if (opt_format != 2 && entry->hwcap == 0)
|
||||||
|
+ if (opt_format != opt_format_new && entry->hwcap == 0)
|
||||||
|
file_entries->libs[idx_old].value = str_offset + pad;
|
||||||
|
- if (opt_format != 0)
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
file_entries_new->libs[idx_new].value = str_offset;
|
||||||
|
len = strlen (entry->path) + 1;
|
||||||
|
str = mempcpy (str, entry->path, len);
|
||||||
|
@@ -420,7 +420,7 @@ save_cache (const char *cache_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Duplicate last old cache entry if needed. */
|
||||||
|
- if (opt_format != 2
|
||||||
|
+ if (opt_format != opt_format_new
|
||||||
|
&& idx_old < cache_entry_old_count)
|
||||||
|
file_entries->libs[idx_old] = file_entries->libs[idx_old - 1];
|
||||||
|
|
||||||
|
@@ -438,16 +438,16 @@ save_cache (const char *cache_name)
|
||||||
|
temp_name);
|
||||||
|
|
||||||
|
/* Write contents. */
|
||||||
|
- if (opt_format != 2)
|
||||||
|
+ if (opt_format != opt_format_new)
|
||||||
|
{
|
||||||
|
if (write (fd, file_entries, file_entries_size)
|
||||||
|
!= (ssize_t) file_entries_size)
|
||||||
|
error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
|
||||||
|
}
|
||||||
|
- if (opt_format != 0)
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
{
|
||||||
|
/* Align cache. */
|
||||||
|
- if (opt_format != 2)
|
||||||
|
+ if (opt_format != opt_format_new)
|
||||||
|
{
|
||||||
|
char zero[pad];
|
||||||
|
memset (zero, '\0', pad);
|
||||||
|
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||||
|
index be730ceb075f6c1f..0fa5aef83f9cd86c 100644
|
||||||
|
--- a/elf/ldconfig.c
|
||||||
|
+++ b/elf/ldconfig.c
|
||||||
|
@@ -100,8 +100,7 @@ static int opt_print_cache;
|
||||||
|
int opt_verbose;
|
||||||
|
|
||||||
|
/* Format to support. */
|
||||||
|
-/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */
|
||||||
|
-int opt_format = 2;
|
||||||
|
+enum opt_format opt_format = opt_format_new;
|
||||||
|
|
||||||
|
/* Build cache. */
|
||||||
|
static int opt_build_cache = 1;
|
||||||
|
@@ -281,11 +280,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (strcmp (arg, "old") == 0)
|
||||||
|
- opt_format = 0;
|
||||||
|
+ opt_format = opt_format_old;
|
||||||
|
else if (strcmp (arg, "compat") == 0)
|
||||||
|
- opt_format = 1;
|
||||||
|
+ opt_format = opt_format_compat;
|
||||||
|
else if (strcmp (arg, "new") == 0)
|
||||||
|
- opt_format = 2;
|
||||||
|
+ opt_format = opt_format_new;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ARGP_ERR_UNKNOWN;
|
||||||
|
diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h
|
||||||
|
index 6774212110d23eae..b15b142511829436 100644
|
||||||
|
--- a/sysdeps/generic/ldconfig.h
|
||||||
|
+++ b/sysdeps/generic/ldconfig.h
|
||||||
|
@@ -90,7 +90,14 @@ extern char *chroot_canon (const char *chroot, const char *name);
|
||||||
|
/* Declared in ldconfig.c. */
|
||||||
|
extern int opt_verbose;
|
||||||
|
|
||||||
|
-extern int opt_format;
|
||||||
|
+enum opt_format
|
||||||
|
+ {
|
||||||
|
+ opt_format_old = 0, /* Use struct cache_file. */
|
||||||
|
+ opt_format_compat = 1, /* Use both, old format followed by new. */
|
||||||
|
+ opt_format_new = 2, /* Use struct cache_file_new. */
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+extern enum opt_format opt_format;
|
||||||
|
|
||||||
|
/* Prototypes for a few program-wide used functions. */
|
||||||
|
#include <programs/xmalloc.h>
|
1111
SOURCES/glibc-rh1817513-113.patch
Normal file
1111
SOURCES/glibc-rh1817513-113.patch
Normal file
File diff suppressed because it is too large
Load Diff
190
SOURCES/glibc-rh1817513-114.patch
Normal file
190
SOURCES/glibc-rh1817513-114.patch
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
commit 84ba719b260551918965d0a433914de683087645
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 4 09:13:43 2020 +0100
|
||||||
|
|
||||||
|
elf: Add endianness markup to ld.so.cache (bug 27008)
|
||||||
|
|
||||||
|
Use a reserved byte in the new format cache header to indicate whether
|
||||||
|
the file is in little endian or big endian format. Eventually, this
|
||||||
|
information could be used to provide a unified cache for qemu-user
|
||||||
|
and similiar scenarios.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/cache.c b/elf/cache.c
|
||||||
|
index edcdd4b7cc1a6a0b..28e4889d006d2f0b 100644
|
||||||
|
--- a/elf/cache.c
|
||||||
|
+++ b/elf/cache.c
|
||||||
|
@@ -152,6 +152,14 @@ print_entry (const char *lib, int flag, unsigned int osversion,
|
||||||
|
printf (") => %s\n", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Print an error and exit if the new-file cache is internally
|
||||||
|
+ inconsistent. */
|
||||||
|
+static void
|
||||||
|
+check_new_cache (struct cache_file_new *cache)
|
||||||
|
+{
|
||||||
|
+ if (! cache_file_new_matches_endian (cache))
|
||||||
|
+ error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n"));
|
||||||
|
+}
|
||||||
|
|
||||||
|
/* Print the whole cache file, if a file contains the new cache format
|
||||||
|
hidden in the old one, print the contents of the new format. */
|
||||||
|
@@ -193,6 +201,7 @@ print_cache (const char *cache_name)
|
||||||
|
|| memcmp (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;
|
||||||
|
/* This is where the strings start. */
|
||||||
|
cache_data = (const char *) cache_new;
|
||||||
|
@@ -222,6 +231,7 @@ print_cache (const char *cache_name)
|
||||||
|
&& memcmp (cache_new->version, CACHE_VERSION,
|
||||||
|
sizeof CACHE_VERSION - 1) == 0)
|
||||||
|
{
|
||||||
|
+ check_new_cache (cache_new);
|
||||||
|
cache_data = (const char *) cache_new;
|
||||||
|
format = 1;
|
||||||
|
}
|
||||||
|
@@ -361,6 +371,7 @@ save_cache (const char *cache_name)
|
||||||
|
|
||||||
|
file_entries_new->nlibs = cache_entry_count;
|
||||||
|
file_entries_new->len_strings = total_strlen;
|
||||||
|
+ file_entries_new->flags = cache_file_new_flags_endian_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pad for alignment of cache_file_new. */
|
||||||
|
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
|
||||||
|
index 366a051dfcd26132..de063faa8b2c88ae 100644
|
||||||
|
--- a/elf/dl-cache.c
|
||||||
|
+++ b/elf/dl-cache.c
|
||||||
|
@@ -242,6 +242,11 @@ _dl_load_cache_lookup (const char *name)
|
||||||
|
&& ((cachesize - sizeof *cache_new) / sizeof (struct file_entry_new)
|
||||||
|
>= ((struct cache_file_new *) file)->nlibs))
|
||||||
|
{
|
||||||
|
+ if (! cache_file_new_matches_endian (file))
|
||||||
|
+ {
|
||||||
|
+ __munmap (file, cachesize);
|
||||||
|
+ file = (void *) -1;
|
||||||
|
+ }
|
||||||
|
cache_new = file;
|
||||||
|
cache = file;
|
||||||
|
}
|
||||||
|
@@ -263,7 +268,20 @@ _dl_load_cache_lookup (const char *name)
|
||||||
|
if (cachesize < (offset + sizeof (struct cache_file_new))
|
||||||
|
|| memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
|
||||||
|
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
|
||||||
|
- cache_new = (void *) -1;
|
||||||
|
+ cache_new = (void *) -1;
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ if (! cache_file_new_matches_endian (cache_new))
|
||||||
|
+ {
|
||||||
|
+ /* The old-format part of the cache is bogus as well
|
||||||
|
+ if the endianness does not match. (But it is
|
||||||
|
+ unclear how the new header can be located if the
|
||||||
|
+ endianess does not match.) */
|
||||||
|
+ cache = (void *) -1;
|
||||||
|
+ cache_new = (void *) -1;
|
||||||
|
+ __munmap (file, cachesize);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
|
||||||
|
index 3c5730dfe42c7c88..6ecfd6da0e59329c 100644
|
||||||
|
--- a/sysdeps/generic/dl-cache.h
|
||||||
|
+++ b/sysdeps/generic/dl-cache.h
|
||||||
|
@@ -16,6 +16,11 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+#ifndef _DL_CACHE_H
|
||||||
|
+#define _DL_CACHE_H
|
||||||
|
+
|
||||||
|
+#include <endian.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef _DL_CACHE_DEFAULT_ID
|
||||||
|
@@ -92,17 +97,72 @@ struct file_entry_new
|
||||||
|
uint64_t hwcap; /* Hwcap entry. */
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* See flags member of struct cache_file_new below. */
|
||||||
|
+enum
|
||||||
|
+ {
|
||||||
|
+ /* No endianness information available. An old ldconfig version
|
||||||
|
+ without endianness support wrote the file. */
|
||||||
|
+ cache_file_new_flags_endian_unset = 0,
|
||||||
|
+
|
||||||
|
+ /* Cache is invalid and should be ignored. */
|
||||||
|
+ cache_file_new_flags_endian_invalid = 1,
|
||||||
|
+
|
||||||
|
+ /* Cache format is little endian. */
|
||||||
|
+ cache_file_new_flags_endian_little = 2,
|
||||||
|
+
|
||||||
|
+ /* Cache format is big endian. */
|
||||||
|
+ cache_file_new_flags_endian_big = 3,
|
||||||
|
+
|
||||||
|
+ /* Bit mask to extract the cache_file_new_flags_endian_*
|
||||||
|
+ values. */
|
||||||
|
+ cache_file_new_flags_endian_mask = 3,
|
||||||
|
+
|
||||||
|
+ /* Expected value of the endian bits in the flags member for the
|
||||||
|
+ current architecture. */
|
||||||
|
+ cache_file_new_flags_endian_current
|
||||||
|
+ = (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
+ ? cache_file_new_flags_endian_little
|
||||||
|
+ : cache_file_new_flags_endian_big),
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
struct cache_file_new
|
||||||
|
{
|
||||||
|
char magic[sizeof CACHEMAGIC_NEW - 1];
|
||||||
|
char version[sizeof CACHE_VERSION - 1];
|
||||||
|
uint32_t nlibs; /* Number of entries. */
|
||||||
|
uint32_t len_strings; /* Size of string table. */
|
||||||
|
- uint32_t unused[5]; /* Leave space for future extensions
|
||||||
|
+
|
||||||
|
+ /* flags & cache_file_new_flags_endian_mask is one of the values
|
||||||
|
+ cache_file_new_flags_endian_unset, cache_file_new_flags_endian_invalid,
|
||||||
|
+ cache_file_new_flags_endian_little, cache_file_new_flags_endian_big.
|
||||||
|
+
|
||||||
|
+ The remaining bits are unused and should be generated as zero and
|
||||||
|
+ ignored by readers. */
|
||||||
|
+ uint8_t flags;
|
||||||
|
+
|
||||||
|
+ uint8_t padding_unsed[3]; /* Not used, for future extensions. */
|
||||||
|
+
|
||||||
|
+ uint32_t unused[4]; /* Leave space for future extensions
|
||||||
|
and align to 8 byte boundary. */
|
||||||
|
struct file_entry_new libs[0]; /* Entries describing libraries. */
|
||||||
|
/* After this the string table of size len_strings is found. */
|
||||||
|
};
|
||||||
|
+_Static_assert (sizeof (struct cache_file_new) == 48,
|
||||||
|
+ "size of struct cache_file_new");
|
||||||
|
+
|
||||||
|
+/* Returns false if *CACHE has the wrong endianness for this
|
||||||
|
+ architecture, and true if the endianness matches (or is
|
||||||
|
+ unknown). */
|
||||||
|
+static inline bool
|
||||||
|
+cache_file_new_matches_endian (const struct cache_file_new *cache)
|
||||||
|
+{
|
||||||
|
+ /* A zero value for cache->flags means that no endianness
|
||||||
|
+ information is available. */
|
||||||
|
+ return cache->flags == 0
|
||||||
|
+ || ((cache->flags & cache_file_new_flags_endian_big)
|
||||||
|
+ == cache_file_new_flags_endian_current);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
/* Used to align cache_file_new. */
|
||||||
|
#define ALIGN_CACHE(addr) \
|
||||||
|
@@ -110,3 +170,5 @@ struct cache_file_new
|
||||||
|
& (~(__alignof__ (struct cache_file_new) - 1)))
|
||||||
|
|
||||||
|
extern int _dl_cache_libcmp (const char *p1, const char *p2) attribute_hidden;
|
||||||
|
+
|
||||||
|
+#endif /* _DL_CACHE_H */
|
312
SOURCES/glibc-rh1817513-115.patch
Normal file
312
SOURCES/glibc-rh1817513-115.patch
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
commit dfb3f101c5ef23adf60d389058a2b33e23303d04
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 4 09:13:43 2020 +0100
|
||||||
|
|
||||||
|
elf: Add extension mechanism to ld.so.cache
|
||||||
|
|
||||||
|
A previously unused new-format header field is used to record
|
||||||
|
the address of an extension directory.
|
||||||
|
|
||||||
|
This change adds a demo extension which records the version of
|
||||||
|
ldconfig which builds a file.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/cache.c b/elf/cache.c
|
||||||
|
index 28e4889d006d2f0b..5a8f1ad70cc3fead 100644
|
||||||
|
--- a/elf/cache.c
|
||||||
|
+++ b/elf/cache.c
|
||||||
|
@@ -15,6 +15,7 @@
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
+#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <error.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
@@ -33,6 +34,7 @@
|
||||||
|
|
||||||
|
#include <ldconfig.h>
|
||||||
|
#include <dl-cache.h>
|
||||||
|
+#include <version.h>
|
||||||
|
|
||||||
|
struct cache_entry
|
||||||
|
{
|
||||||
|
@@ -161,6 +163,21 @@ check_new_cache (struct cache_file_new *cache)
|
||||||
|
error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Print the extension information at the cache at start address
|
||||||
|
+ FILE_BASE, of length FILE_SIZE bytes. The new-format cache header
|
||||||
|
+ is at CACHE, and the file name for diagnostics is CACHE_NAME. */
|
||||||
|
+static void
|
||||||
|
+print_extensions (struct cache_extension_all_loaded *ext)
|
||||||
|
+{
|
||||||
|
+ if (ext->sections[cache_extension_tag_generator].base != NULL)
|
||||||
|
+ {
|
||||||
|
+ fputs (_("Cache generated by: "), stdout);
|
||||||
|
+ fwrite (ext->sections[cache_extension_tag_generator].base, 1,
|
||||||
|
+ ext->sections[cache_extension_tag_generator].size, stdout);
|
||||||
|
+ putchar ('\n');
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Print the whole cache file, if a file contains the new cache format
|
||||||
|
hidden in the old one, print the contents of the new format. */
|
||||||
|
void
|
||||||
|
@@ -250,6 +267,11 @@ print_cache (const char *cache_name)
|
||||||
|
}
|
||||||
|
else if (format == 1)
|
||||||
|
{
|
||||||
|
+ struct cache_extension_all_loaded ext;
|
||||||
|
+ if (!cache_extension_load (cache_new, cache, cache_size, &ext))
|
||||||
|
+ error (EXIT_FAILURE, 0,
|
||||||
|
+ _("Malformed extension data in cache file %s\n"), cache_name);
|
||||||
|
+
|
||||||
|
printf (_("%d libs found in cache `%s'\n"),
|
||||||
|
cache_new->nlibs, cache_name);
|
||||||
|
|
||||||
|
@@ -260,6 +282,7 @@ print_cache (const char *cache_name)
|
||||||
|
cache_new->libs[i].osversion,
|
||||||
|
cache_new->libs[i].hwcap,
|
||||||
|
cache_data + cache_new->libs[i].value);
|
||||||
|
+ print_extensions (&ext);
|
||||||
|
}
|
||||||
|
/* Cleanup. */
|
||||||
|
munmap (cache, cache_size);
|
||||||
|
@@ -301,6 +324,45 @@ compare (const struct cache_entry *e1, const struct cache_entry *e2)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Size of the cache extension directory. All tags are assumed to be
|
||||||
|
+ present. */
|
||||||
|
+enum
|
||||||
|
+ {
|
||||||
|
+ cache_extension_size = (offsetof (struct cache_extension, sections)
|
||||||
|
+ + (cache_extension_count
|
||||||
|
+ * sizeof (struct cache_extension_section)))
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+/* Write the cache extensions to FD. The extension directory is
|
||||||
|
+ assumed to be located at CACHE_EXTENSION_OFFSET. */
|
||||||
|
+static void
|
||||||
|
+write_extensions (int fd, uint32_t cache_extension_offset)
|
||||||
|
+{
|
||||||
|
+ assert ((cache_extension_offset % 4) == 0);
|
||||||
|
+
|
||||||
|
+ struct cache_extension *ext = xmalloc (cache_extension_size);
|
||||||
|
+ ext->magic = cache_extension_magic;
|
||||||
|
+ ext->count = cache_extension_count;
|
||||||
|
+
|
||||||
|
+ for (int i = 0; i < cache_extension_count; ++i)
|
||||||
|
+ {
|
||||||
|
+ ext->sections[i].tag = i;
|
||||||
|
+ ext->sections[i].flags = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const char *generator
|
||||||
|
+ = "ldconfig " PKGVERSION RELEASE " release version " VERSION;
|
||||||
|
+ ext->sections[cache_extension_tag_generator].offset
|
||||||
|
+ = cache_extension_offset + cache_extension_size;
|
||||||
|
+ ext->sections[cache_extension_tag_generator].size = strlen (generator);
|
||||||
|
+
|
||||||
|
+ if (write (fd, ext, cache_extension_size) != cache_extension_size
|
||||||
|
+ || write (fd, generator, strlen (generator)) != strlen (generator))
|
||||||
|
+ error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
|
||||||
|
+
|
||||||
|
+ free (ext);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Save the contents of the cache. */
|
||||||
|
void
|
||||||
|
save_cache (const char *cache_name)
|
||||||
|
@@ -435,6 +497,25 @@ save_cache (const char *cache_name)
|
||||||
|
&& idx_old < cache_entry_old_count)
|
||||||
|
file_entries->libs[idx_old] = file_entries->libs[idx_old - 1];
|
||||||
|
|
||||||
|
+ /* Compute the location of the extension directory. This
|
||||||
|
+ implementation puts the directory after the string table. The
|
||||||
|
+ size computation matches the write calls below. The extension
|
||||||
|
+ directory does not exist with format 0, so the value does not
|
||||||
|
+ matter. */
|
||||||
|
+ uint32_t extension_offset = 0;
|
||||||
|
+ if (opt_format != opt_format_new)
|
||||||
|
+ extension_offset += file_entries_size;
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
+ {
|
||||||
|
+ if (opt_format != opt_format_new)
|
||||||
|
+ extension_offset += pad;
|
||||||
|
+ extension_offset += file_entries_new_size;
|
||||||
|
+ }
|
||||||
|
+ extension_offset += total_strlen;
|
||||||
|
+ extension_offset = roundup (extension_offset, 4); /* Provide alignment. */
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
+ file_entries_new->extension_offset = extension_offset;
|
||||||
|
+
|
||||||
|
/* Write out the cache. */
|
||||||
|
|
||||||
|
/* Write cache first to a temporary file and rename it later. */
|
||||||
|
@@ -473,6 +554,14 @@ save_cache (const char *cache_name)
|
||||||
|
if (write (fd, strings, total_strlen) != (ssize_t) total_strlen)
|
||||||
|
error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
|
||||||
|
|
||||||
|
+ if (opt_format != opt_format_old)
|
||||||
|
+ {
|
||||||
|
+ /* Align file position to 4. */
|
||||||
|
+ off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET);
|
||||||
|
+ assert ((unsigned long long int) (extension_offset - old_offset) < 4);
|
||||||
|
+ write_extensions (fd, extension_offset);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Make sure user can always read cache file */
|
||||||
|
if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
|
||||||
|
error (EXIT_FAILURE, errno,
|
||||||
|
diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
|
||||||
|
index 6ecfd6da0e59329c..259e843724531630 100644
|
||||||
|
--- a/sysdeps/generic/dl-cache.h
|
||||||
|
+++ b/sysdeps/generic/dl-cache.h
|
||||||
|
@@ -21,7 +21,9 @@
|
||||||
|
|
||||||
|
#include <endian.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
+#include <string.h>
|
||||||
|
|
||||||
|
#ifndef _DL_CACHE_DEFAULT_ID
|
||||||
|
# define _DL_CACHE_DEFAULT_ID 3
|
||||||
|
@@ -142,7 +144,11 @@ struct cache_file_new
|
||||||
|
|
||||||
|
uint8_t padding_unsed[3]; /* Not used, for future extensions. */
|
||||||
|
|
||||||
|
- uint32_t unused[4]; /* Leave space for future extensions
|
||||||
|
+ /* File offset of the extension directory. See struct
|
||||||
|
+ cache_extension below. Must be a multiple of four. */
|
||||||
|
+ uint32_t extension_offset;
|
||||||
|
+
|
||||||
|
+ uint32_t unused[3]; /* Leave space for future extensions
|
||||||
|
and align to 8 byte boundary. */
|
||||||
|
struct file_entry_new libs[0]; /* Entries describing libraries. */
|
||||||
|
/* After this the string table of size len_strings is found. */
|
||||||
|
@@ -164,6 +170,121 @@ cache_file_new_matches_endian (const struct cache_file_new *cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+/* Randomly chosen magic value, which allows for additional
|
||||||
|
+ consistency verification. */
|
||||||
|
+enum { cache_extension_magic = (uint32_t) -358342284 };
|
||||||
|
+
|
||||||
|
+/* Tag values for different kinds of extension sections. Similar to
|
||||||
|
+ SHT_* constants. */
|
||||||
|
+enum cache_extension_tag
|
||||||
|
+ {
|
||||||
|
+ /* Array of bytes containing the glibc version that generated this
|
||||||
|
+ cache file. */
|
||||||
|
+ cache_extension_tag_generator,
|
||||||
|
+
|
||||||
|
+ /* Total number of known cache extension tags. */
|
||||||
|
+ cache_extension_count
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+/* Element in the array following struct cache_extension. Similar to
|
||||||
|
+ an ELF section header. */
|
||||||
|
+struct cache_extension_section
|
||||||
|
+{
|
||||||
|
+ /* Type of the extension section. A enum cache_extension_tag value. */
|
||||||
|
+ uint32_t tag;
|
||||||
|
+
|
||||||
|
+ /* Extension-specific flags. Currently generated as zero. */
|
||||||
|
+ uint32_t flags;
|
||||||
|
+
|
||||||
|
+ /* Offset from the start of the file for the data in this extension
|
||||||
|
+ section. Specific extensions can have alignment constraints. */
|
||||||
|
+ uint32_t offset;
|
||||||
|
+
|
||||||
|
+ /* Length in bytes of the extension data. Specific extensions may
|
||||||
|
+ have size requirements. */
|
||||||
|
+ uint32_t size;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* The extension directory in the cache. An array of struct
|
||||||
|
+ cache_extension_section entries. */
|
||||||
|
+struct cache_extension
|
||||||
|
+{
|
||||||
|
+ uint32_t magic; /* Always cache_extension_magic. */
|
||||||
|
+ uint32_t count; /* Number of following entries. */
|
||||||
|
+
|
||||||
|
+ /* count section descriptors of type struct cache_extension_section
|
||||||
|
+ follow. */
|
||||||
|
+ struct cache_extension_section sections[];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* A relocated version of struct cache_extension_section. */
|
||||||
|
+struct cache_extension_loaded
|
||||||
|
+{
|
||||||
|
+ /* Address and size of this extension section. base is NULL if the
|
||||||
|
+ section is missing from the file. */
|
||||||
|
+ const void *base;
|
||||||
|
+ size_t size;
|
||||||
|
+
|
||||||
|
+ /* Flags from struct cache_extension_section. */
|
||||||
|
+ uint32_t flags;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* All supported extension sections, relocated. Filled in by
|
||||||
|
+ cache_extension_load below. */
|
||||||
|
+struct cache_extension_all_loaded
|
||||||
|
+{
|
||||||
|
+ struct cache_extension_loaded sections[cache_extension_count];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static bool __attribute__ ((unused))
|
||||||
|
+cache_extension_load (const struct cache_file_new *cache,
|
||||||
|
+ const void *file_base, size_t file_size,
|
||||||
|
+ struct cache_extension_all_loaded *loaded)
|
||||||
|
+{
|
||||||
|
+ memset (loaded, 0, sizeof (*loaded));
|
||||||
|
+ if (cache->extension_offset == 0)
|
||||||
|
+ /* No extensions present. This is not a format error. */
|
||||||
|
+ return true;
|
||||||
|
+ if ((cache->extension_offset % 4) != 0)
|
||||||
|
+ /* Extension offset is misaligned. */
|
||||||
|
+ return false;
|
||||||
|
+ size_t size_tmp;
|
||||||
|
+ if (__builtin_add_overflow (cache->extension_offset,
|
||||||
|
+ sizeof (struct cache_extension), &size_tmp)
|
||||||
|
+ || size_tmp > file_size)
|
||||||
|
+ /* Extension extends beyond the end of the file. */
|
||||||
|
+ return false;
|
||||||
|
+ const struct cache_extension *ext = file_base + cache->extension_offset;
|
||||||
|
+ if (ext->magic != cache_extension_magic)
|
||||||
|
+ return false;
|
||||||
|
+ if (__builtin_mul_overflow (ext->count,
|
||||||
|
+ sizeof (struct cache_extension_section),
|
||||||
|
+ &size_tmp)
|
||||||
|
+ || __builtin_add_overflow (cache->extension_offset
|
||||||
|
+ + sizeof (struct cache_extension), size_tmp,
|
||||||
|
+ &size_tmp)
|
||||||
|
+ || size_tmp > file_size)
|
||||||
|
+ /* Extension array extends beyond the end of the file. */
|
||||||
|
+ return false;
|
||||||
|
+ for (uint32_t i = 0; i < ext->count; ++i)
|
||||||
|
+ {
|
||||||
|
+ if (__builtin_add_overflow (ext->sections[i].offset,
|
||||||
|
+ ext->sections[i].size, &size_tmp)
|
||||||
|
+ || size_tmp > file_size)
|
||||||
|
+ /* Extension data extends beyond the end of the file. */
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ uint32_t tag = ext->sections[i].tag;
|
||||||
|
+ if (tag >= cache_extension_count)
|
||||||
|
+ /* Tag is out of range and unrecognized. */
|
||||||
|
+ continue;
|
||||||
|
+ loaded->sections[tag].base = file_base + ext->sections[i].offset;
|
||||||
|
+ loaded->sections[tag].size = ext->sections[i].size;
|
||||||
|
+ loaded->sections[tag].flags = ext->sections[i].flags;
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Used to align cache_file_new. */
|
||||||
|
#define ALIGN_CACHE(addr) \
|
||||||
|
(((addr) + __alignof__ (struct cache_file_new) -1) \
|
544
SOURCES/glibc-rh1817513-116.patch
Normal file
544
SOURCES/glibc-rh1817513-116.patch
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
commit 785969a047ad2f23f758901c6816422573544453
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 4 09:13:43 2020 +0100
|
||||||
|
|
||||||
|
elf: Implement a string table for ldconfig, with tail merging
|
||||||
|
|
||||||
|
This will be used in ldconfig to reduce the ld.so.cache size slightly.
|
||||||
|
|
||||||
|
Tail merging is an optimization where a pointer points into another
|
||||||
|
string if the first string is a suffix of the second string.
|
||||||
|
|
||||||
|
The hash function FNV-1a was chosen because it is simple and achieves
|
||||||
|
good dispersion even for short strings (so that the hash table bucket
|
||||||
|
count can be a power of two). It is clearly superior to the hsearch
|
||||||
|
hash and the ELF hash in this regard.
|
||||||
|
|
||||||
|
The hash table uses chaining for collision resolution.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index f795617780b393ec..abb3e9d1179ef5cd 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -163,7 +163,7 @@ tests-container = \
|
||||||
|
|
||||||
|
tests := tst-tls9 tst-leaks1 \
|
||||||
|
tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
|
||||||
|
- tst-auxv
|
||||||
|
+ tst-auxv tst-stringtable
|
||||||
|
tests-internal := tst-tls1 tst-tls2 $(tests-static-internal)
|
||||||
|
tests-static := $(tests-static-normal) $(tests-static-internal)
|
||||||
|
|
||||||
|
diff --git a/elf/stringtable.c b/elf/stringtable.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..099347d73ee70b8f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/stringtable.c
|
||||||
|
@@ -0,0 +1,209 @@
|
||||||
|
+/* String tables for ld.so.cache construction. Implementation.
|
||||||
|
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published
|
||||||
|
+ by the Free Software Foundation; version 2 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program 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 a copy of the GNU General Public License
|
||||||
|
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <assert.h>
|
||||||
|
+#include <error.h>
|
||||||
|
+#include <ldconfig.h>
|
||||||
|
+#include <libintl.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <stringtable.h>
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+stringtable_init (struct stringtable *table)
|
||||||
|
+{
|
||||||
|
+ table->count = 0;
|
||||||
|
+
|
||||||
|
+ /* This needs to be a power of two. 128 is sufficient to keep track
|
||||||
|
+ of 42 DSOs without resizing (assuming two strings per DSOs).
|
||||||
|
+ glibc itself comes with more than 20 DSOs, so 64 would likely to
|
||||||
|
+ be too small. */
|
||||||
|
+ table->allocated = 128;
|
||||||
|
+
|
||||||
|
+ table->entries = xcalloc (table->allocated, sizeof (table->entries[0]));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* 32-bit FNV-1a hash function. */
|
||||||
|
+static uint32_t
|
||||||
|
+fnv1a (const char *string, size_t length)
|
||||||
|
+{
|
||||||
|
+ const unsigned char *p = (const unsigned char *) string;
|
||||||
|
+ uint32_t hash = 2166136261U;
|
||||||
|
+ for (size_t i = 0; i < length; ++i)
|
||||||
|
+ {
|
||||||
|
+ hash ^= p[i];
|
||||||
|
+ hash *= 16777619U;
|
||||||
|
+ }
|
||||||
|
+ return hash;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Double the capacity of the hash table. */
|
||||||
|
+static void
|
||||||
|
+stringtable_rehash (struct stringtable *table)
|
||||||
|
+{
|
||||||
|
+ /* This computation cannot overflow because the old total in-memory
|
||||||
|
+ size of the hash table is larger than the computed value. */
|
||||||
|
+ uint32_t new_allocated = table->allocated * 2;
|
||||||
|
+ struct stringtable_entry **new_entries
|
||||||
|
+ = xcalloc (new_allocated, sizeof (table->entries[0]));
|
||||||
|
+
|
||||||
|
+ uint32_t mask = new_allocated - 1;
|
||||||
|
+ for (uint32_t i = 0; i < table->allocated; ++i)
|
||||||
|
+ for (struct stringtable_entry *e = table->entries[i]; e != NULL; )
|
||||||
|
+ {
|
||||||
|
+ struct stringtable_entry *next = e->next;
|
||||||
|
+ uint32_t hash = fnv1a (e->string, e->length);
|
||||||
|
+ uint32_t new_index = hash & mask;
|
||||||
|
+ e->next = new_entries[new_index];
|
||||||
|
+ new_entries[new_index] = e;
|
||||||
|
+ e = next;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free (table->entries);
|
||||||
|
+ table->entries = new_entries;
|
||||||
|
+ table->allocated = new_allocated;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct stringtable_entry *
|
||||||
|
+stringtable_add (struct stringtable *table, const char *string)
|
||||||
|
+{
|
||||||
|
+ /* Check for a zero-initialized table. */
|
||||||
|
+ if (table->allocated == 0)
|
||||||
|
+ stringtable_init (table);
|
||||||
|
+
|
||||||
|
+ size_t length = strlen (string);
|
||||||
|
+ if (length > (1U << 30))
|
||||||
|
+ error (EXIT_FAILURE, 0, _("String table string is too long"));
|
||||||
|
+ uint32_t hash = fnv1a (string, length);
|
||||||
|
+
|
||||||
|
+ /* Return a previously-existing entry. */
|
||||||
|
+ for (struct stringtable_entry *e
|
||||||
|
+ = table->entries[hash & (table->allocated - 1)];
|
||||||
|
+ e != NULL; e = e->next)
|
||||||
|
+ if (e->length == length && memcmp (e->string, string, length) == 0)
|
||||||
|
+ return e;
|
||||||
|
+
|
||||||
|
+ /* Increase the size of the table if necessary. Keep utilization
|
||||||
|
+ below two thirds. */
|
||||||
|
+ if (table->count >= (1U << 30))
|
||||||
|
+ error (EXIT_FAILURE, 0, _("String table has too many entries"));
|
||||||
|
+ if (table->count * 3 > table->allocated * 2)
|
||||||
|
+ stringtable_rehash (table);
|
||||||
|
+
|
||||||
|
+ /* Add the new table entry. */
|
||||||
|
+ ++table->count;
|
||||||
|
+ struct stringtable_entry *e
|
||||||
|
+ = xmalloc (offsetof (struct stringtable_entry, string) + length + 1);
|
||||||
|
+ uint32_t index = hash & (table->allocated - 1);
|
||||||
|
+ e->next = table->entries[index];
|
||||||
|
+ table->entries[index] = e;
|
||||||
|
+ e->length = length;
|
||||||
|
+ e->offset = 0;
|
||||||
|
+ memcpy (e->string, string, length + 1);
|
||||||
|
+ return e;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Sort reversed strings in reverse lexicographic order. This is used
|
||||||
|
+ for tail merging. */
|
||||||
|
+static int
|
||||||
|
+finalize_compare (const void *l, const void *r)
|
||||||
|
+{
|
||||||
|
+ struct stringtable_entry *left = *(struct stringtable_entry **) l;
|
||||||
|
+ struct stringtable_entry *right = *(struct stringtable_entry **) r;
|
||||||
|
+ size_t to_compare;
|
||||||
|
+ if (left->length < right->length)
|
||||||
|
+ to_compare = left->length;
|
||||||
|
+ else
|
||||||
|
+ to_compare = right->length;
|
||||||
|
+ for (size_t i = 1; i <= to_compare; ++i)
|
||||||
|
+ {
|
||||||
|
+ unsigned char lch = left->string[left->length - i];
|
||||||
|
+ unsigned char rch = right->string[right->length - i];
|
||||||
|
+ if (lch != rch)
|
||||||
|
+ return rch - lch;
|
||||||
|
+ }
|
||||||
|
+ if (left->length == right->length)
|
||||||
|
+ return 0;
|
||||||
|
+ else if (left->length < right->length)
|
||||||
|
+ /* Longer strings should come first. */
|
||||||
|
+ return 1;
|
||||||
|
+ else
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+stringtable_finalize (struct stringtable *table,
|
||||||
|
+ struct stringtable_finalized *result)
|
||||||
|
+{
|
||||||
|
+ if (table->count == 0)
|
||||||
|
+ {
|
||||||
|
+ result->strings = xstrdup ("");
|
||||||
|
+ result->size = 0;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Optimize the order of the strings. */
|
||||||
|
+ struct stringtable_entry **array = xcalloc (table->count, sizeof (*array));
|
||||||
|
+ {
|
||||||
|
+ size_t j = 0;
|
||||||
|
+ for (uint32_t i = 0; i < table->allocated; ++i)
|
||||||
|
+ for (struct stringtable_entry *e = table->entries[i]; e != NULL;
|
||||||
|
+ e = e->next)
|
||||||
|
+ {
|
||||||
|
+ array[j] = e;
|
||||||
|
+ ++j;
|
||||||
|
+ }
|
||||||
|
+ assert (j == table->count);
|
||||||
|
+ }
|
||||||
|
+ qsort (array, table->count, sizeof (*array), finalize_compare);
|
||||||
|
+
|
||||||
|
+ /* Assign offsets, using tail merging (sharing suffixes) if possible. */
|
||||||
|
+ array[0]->offset = 0;
|
||||||
|
+ for (uint32_t j = 1; j < table->count; ++j)
|
||||||
|
+ {
|
||||||
|
+ struct stringtable_entry *previous = array[j - 1];
|
||||||
|
+ struct stringtable_entry *current = array[j];
|
||||||
|
+ if (previous->length >= current->length
|
||||||
|
+ && memcmp (&previous->string[previous->length - current->length],
|
||||||
|
+ current->string, current->length) == 0)
|
||||||
|
+ current->offset = (previous->offset + previous->length
|
||||||
|
+ - current->length);
|
||||||
|
+ else if (__builtin_add_overflow (previous->offset,
|
||||||
|
+ previous->length + 1,
|
||||||
|
+ ¤t->offset))
|
||||||
|
+ error (EXIT_FAILURE, 0, _("String table is too large"));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Allocate the result string. */
|
||||||
|
+ {
|
||||||
|
+ struct stringtable_entry *last = array[table->count - 1];
|
||||||
|
+ if (__builtin_add_overflow (last->offset, last->length + 1,
|
||||||
|
+ &result->size))
|
||||||
|
+ error (EXIT_FAILURE, 0, _("String table is too large"));
|
||||||
|
+ }
|
||||||
|
+ /* The strings are copied from the hash table, so the array is no
|
||||||
|
+ longer needed. */
|
||||||
|
+ free (array);
|
||||||
|
+ result->strings = xcalloc (result->size, 1);
|
||||||
|
+
|
||||||
|
+ /* Copy the strings. */
|
||||||
|
+ for (uint32_t i = 0; i < table->allocated; ++i)
|
||||||
|
+ for (struct stringtable_entry *e = table->entries[i]; e != NULL;
|
||||||
|
+ e = e->next)
|
||||||
|
+ if (result->strings[e->offset] == '\0')
|
||||||
|
+ memcpy (&result->strings[e->offset], e->string, e->length + 1);
|
||||||
|
+}
|
||||||
|
diff --git a/elf/stringtable.h b/elf/stringtable.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..7d57d1bda9602947
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/stringtable.h
|
||||||
|
@@ -0,0 +1,64 @@
|
||||||
|
+/* String tables for ld.so.cache construction.
|
||||||
|
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published
|
||||||
|
+ by the Free Software Foundation; version 2 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program 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 a copy of the GNU General Public License
|
||||||
|
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#ifndef _STRINGTABLE_H
|
||||||
|
+#define _STRINGTABLE_H
|
||||||
|
+
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+
|
||||||
|
+/* An entry in the string table. Only the length and string fields are
|
||||||
|
+ expected to be used outside the string table code. */
|
||||||
|
+struct stringtable_entry
|
||||||
|
+{
|
||||||
|
+ struct stringtable_entry *next; /* For collision resolution. */
|
||||||
|
+ uint32_t length; /* Length of then string. */
|
||||||
|
+ uint32_t offset; /* From start of finalized table. */
|
||||||
|
+ char string[]; /* Null-terminated string. */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* A string table. Zero-initialization produces a valid atable. */
|
||||||
|
+struct stringtable
|
||||||
|
+{
|
||||||
|
+ struct stringtable_entry **entries; /* Array of hash table buckets. */
|
||||||
|
+ uint32_t count; /* Number of elements in the table. */
|
||||||
|
+ uint32_t allocated; /* Length of the entries array. */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Adds STRING to TABLE. May return the address of an existing entry. */
|
||||||
|
+struct stringtable_entry *stringtable_add (struct stringtable *table,
|
||||||
|
+ const char *string);
|
||||||
|
+
|
||||||
|
+/* Result of stringtable_finalize. SIZE bytes at STRINGS should be
|
||||||
|
+ written to the file. */
|
||||||
|
+struct stringtable_finalized
|
||||||
|
+{
|
||||||
|
+ char *strings;
|
||||||
|
+ size_t size;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Assigns offsets to string table entries and computes the serialized
|
||||||
|
+ form of the string table. */
|
||||||
|
+void stringtable_finalize (struct stringtable *table,
|
||||||
|
+ struct stringtable_finalized *result);
|
||||||
|
+
|
||||||
|
+/* Deallocate the string table (but not the TABLE pointer itself).
|
||||||
|
+ (The table can be re-used for adding more strings without
|
||||||
|
+ initialization.) */
|
||||||
|
+void stringtable_free (struct stringtable *table);
|
||||||
|
+
|
||||||
|
+#endif /* _STRINGTABLE_H */
|
||||||
|
diff --git a/elf/stringtable_free.c b/elf/stringtable_free.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..8588a254705d4df8
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/stringtable_free.c
|
||||||
|
@@ -0,0 +1,33 @@
|
||||||
|
+/* String tables for ld.so.cache construction. Deallocation (for tests only).
|
||||||
|
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published
|
||||||
|
+ by the Free Software Foundation; version 2 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program 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 a copy of the GNU General Public License
|
||||||
|
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <stringtable.h>
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+stringtable_free (struct stringtable *table)
|
||||||
|
+{
|
||||||
|
+ for (uint32_t i = 0; i < table->allocated; ++i)
|
||||||
|
+ for (struct stringtable_entry *e = table->entries[i]; e != NULL; )
|
||||||
|
+ {
|
||||||
|
+ struct stringtable_entry *next = e->next;
|
||||||
|
+ free (e);
|
||||||
|
+ e = next;
|
||||||
|
+ }
|
||||||
|
+ free (table->entries);
|
||||||
|
+ *table = (struct stringtable) { 0, };
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-stringtable.c b/elf/tst-stringtable.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..3731086037567d57
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-stringtable.c
|
||||||
|
@@ -0,0 +1,181 @@
|
||||||
|
+/* Unit test for ldconfig string tables.
|
||||||
|
+ Copyright (C) 2020 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published
|
||||||
|
+ by the Free Software Foundation; version 2 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program 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 a copy of the GNU General Public License
|
||||||
|
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <array_length.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <stringtable.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* Empty string table. */
|
||||||
|
+ {
|
||||||
|
+ struct stringtable s = { 0, };
|
||||||
|
+ struct stringtable_finalized f;
|
||||||
|
+ stringtable_finalize (&s, &f);
|
||||||
|
+ TEST_COMPARE_STRING (f.strings, "");
|
||||||
|
+ TEST_COMPARE (f.size, 0);
|
||||||
|
+ free (f.strings);
|
||||||
|
+ stringtable_free (&s);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* String table with one empty string. */
|
||||||
|
+ {
|
||||||
|
+ struct stringtable s = { 0, };
|
||||||
|
+ struct stringtable_entry *e = stringtable_add (&s, "");
|
||||||
|
+ TEST_COMPARE_STRING (e->string, "");
|
||||||
|
+ TEST_COMPARE (e->length, 0);
|
||||||
|
+ TEST_COMPARE (s.count, 1);
|
||||||
|
+
|
||||||
|
+ struct stringtable_finalized f;
|
||||||
|
+ stringtable_finalize (&s, &f);
|
||||||
|
+ TEST_COMPARE (e->offset, 0);
|
||||||
|
+ TEST_COMPARE_STRING (f.strings, "");
|
||||||
|
+ TEST_COMPARE (f.size, 1);
|
||||||
|
+ free (f.strings);
|
||||||
|
+ stringtable_free (&s);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* String table with one non-empty string. */
|
||||||
|
+ {
|
||||||
|
+ struct stringtable s = { 0, };
|
||||||
|
+ struct stringtable_entry *e = stringtable_add (&s, "name");
|
||||||
|
+ TEST_COMPARE_STRING (e->string, "name");
|
||||||
|
+ TEST_COMPARE (e->length, 4);
|
||||||
|
+ TEST_COMPARE (s.count, 1);
|
||||||
|
+
|
||||||
|
+ struct stringtable_finalized f;
|
||||||
|
+ stringtable_finalize (&s, &f);
|
||||||
|
+ TEST_COMPARE (e->offset, 0);
|
||||||
|
+ TEST_COMPARE_STRING (f.strings, "name");
|
||||||
|
+ TEST_COMPARE (f.size, 5);
|
||||||
|
+ free (f.strings);
|
||||||
|
+ stringtable_free (&s);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Two strings, one is a prefix of the other. Tail-merging can only
|
||||||
|
+ happen in one way in this case. */
|
||||||
|
+ {
|
||||||
|
+ struct stringtable s = { 0, };
|
||||||
|
+ struct stringtable_entry *suffix = stringtable_add (&s, "suffix");
|
||||||
|
+ TEST_COMPARE_STRING (suffix->string, "suffix");
|
||||||
|
+ TEST_COMPARE (suffix->length, 6);
|
||||||
|
+ TEST_COMPARE (s.count, 1);
|
||||||
|
+
|
||||||
|
+ struct stringtable_entry *prefix
|
||||||
|
+ = stringtable_add (&s, "prefix-suffix");
|
||||||
|
+ TEST_COMPARE_STRING (prefix->string, "prefix-suffix");
|
||||||
|
+ TEST_COMPARE (prefix->length, strlen ("prefix-suffix"));
|
||||||
|
+ TEST_COMPARE (s.count, 2);
|
||||||
|
+
|
||||||
|
+ struct stringtable_finalized f;
|
||||||
|
+ stringtable_finalize (&s, &f);
|
||||||
|
+ TEST_COMPARE (prefix->offset, 0);
|
||||||
|
+ TEST_COMPARE (suffix->offset, strlen ("prefix-"));
|
||||||
|
+ TEST_COMPARE_STRING (f.strings, "prefix-suffix");
|
||||||
|
+ TEST_COMPARE (f.size, sizeof ("prefix-suffix"));
|
||||||
|
+ free (f.strings);
|
||||||
|
+ stringtable_free (&s);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* String table with various shared prefixes. Triggers hash
|
||||||
|
+ resizing. */
|
||||||
|
+ {
|
||||||
|
+ enum { count = 1500 };
|
||||||
|
+ char *strings[2 * count];
|
||||||
|
+ struct stringtable_entry *entries[2 * count];
|
||||||
|
+ struct stringtable s = { 0, };
|
||||||
|
+ for (int i = 0; i < count; ++i)
|
||||||
|
+ {
|
||||||
|
+ strings[i] = xasprintf ("%d", i);
|
||||||
|
+ entries[i] = stringtable_add (&s, strings[i]);
|
||||||
|
+ TEST_COMPARE (entries[i]->length, strlen (strings[i]));
|
||||||
|
+ TEST_COMPARE_STRING (entries[i]->string, strings[i]);
|
||||||
|
+ strings[i + count] = xasprintf ("prefix/%d", i);
|
||||||
|
+ entries[i + count] = stringtable_add (&s, strings[i + count]);
|
||||||
|
+ TEST_COMPARE (entries[i + count]->length, strlen (strings[i + count]));
|
||||||
|
+ TEST_COMPARE_STRING (entries[i + count]->string, strings[i + count]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ struct stringtable_finalized f;
|
||||||
|
+ stringtable_finalize (&s, &f);
|
||||||
|
+
|
||||||
|
+ for (int i = 0; i < 2 * count; ++i)
|
||||||
|
+ {
|
||||||
|
+ TEST_COMPARE (entries[i]->length, strlen (strings[i]));
|
||||||
|
+ TEST_COMPARE_STRING (entries[i]->string, strings[i]);
|
||||||
|
+ TEST_COMPARE_STRING (f.strings + entries[i]->offset, strings[i]);
|
||||||
|
+ free (strings[i]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free (f.strings);
|
||||||
|
+ stringtable_free (&s);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Verify that maximum tail merging happens. */
|
||||||
|
+ {
|
||||||
|
+ struct stringtable s = { 0, };
|
||||||
|
+ const char *strings[] = {
|
||||||
|
+ "",
|
||||||
|
+ "a",
|
||||||
|
+ "b",
|
||||||
|
+ "aa",
|
||||||
|
+ "aaa",
|
||||||
|
+ "aa",
|
||||||
|
+ "bb",
|
||||||
|
+ "b",
|
||||||
|
+ "a",
|
||||||
|
+ "ba",
|
||||||
|
+ "baa",
|
||||||
|
+ };
|
||||||
|
+ struct stringtable_entry *entries[array_length (strings)];
|
||||||
|
+ for (int i = 0; i < array_length (strings); ++i)
|
||||||
|
+ entries[i] = stringtable_add (&s, strings[i]);
|
||||||
|
+ for (int i = 0; i < array_length (strings); ++i)
|
||||||
|
+ TEST_COMPARE_STRING (entries[i]->string, strings[i]);
|
||||||
|
+
|
||||||
|
+ struct stringtable_finalized f;
|
||||||
|
+ stringtable_finalize (&s, &f);
|
||||||
|
+
|
||||||
|
+ /* There are only four different strings, "aaa", "ba", "baa",
|
||||||
|
+ "bb". The rest is shared in an unspecified fashion. */
|
||||||
|
+ TEST_COMPARE (f.size, 4 + 3 + 4 + 3);
|
||||||
|
+
|
||||||
|
+ for (int i = 0; i < array_length (strings); ++i)
|
||||||
|
+ {
|
||||||
|
+ TEST_COMPARE_STRING (entries[i]->string, strings[i]);
|
||||||
|
+ TEST_COMPARE_STRING (f.strings + entries[i]->offset, strings[i]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free (f.strings);
|
||||||
|
+ stringtable_free (&s);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
+
|
||||||
|
+/* Re-compile the string table implementation here. It is not
|
||||||
|
+ possible to link against the actual build because it was built for
|
||||||
|
+ use in ldconfig. */
|
||||||
|
+#define _(arg) arg
|
||||||
|
+#include "stringtable.c"
|
||||||
|
+#include "stringtable_free.c"
|
209
SOURCES/glibc-rh1817513-117.patch
Normal file
209
SOURCES/glibc-rh1817513-117.patch
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
commit 73b6e50a22dea9ae6144beaaa675d2ac62c281ca
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 4 09:13:43 2020 +0100
|
||||||
|
|
||||||
|
elf: Implement tail merging of strings in ldconfig
|
||||||
|
|
||||||
|
This simplifies the string table construction in elf/cache.c
|
||||||
|
because there is no more need to keep track of offsets explicitly;
|
||||||
|
the string table implementation does this internally.
|
||||||
|
|
||||||
|
This change slightly reduces the size of the cache on disk. The
|
||||||
|
file format does not change as a result. The strings are
|
||||||
|
null-terminated, without explicit length, so tail merging is
|
||||||
|
transparent to readers.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index abb3e9d1179ef5cd..a3e802a9a99b759c 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -112,7 +112,8 @@ others-static += ldconfig
|
||||||
|
others += ldconfig
|
||||||
|
install-rootsbin += ldconfig
|
||||||
|
|
||||||
|
-ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs
|
||||||
|
+ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs \
|
||||||
|
+ stringtable
|
||||||
|
extra-objs += $(ldconfig-modules:=.o)
|
||||||
|
others-extras = $(ldconfig-modules)
|
||||||
|
endif
|
||||||
|
diff --git a/elf/cache.c b/elf/cache.c
|
||||||
|
index 5a8f1ad70cc3fead..f773cacacf26db1c 100644
|
||||||
|
--- a/elf/cache.c
|
||||||
|
+++ b/elf/cache.c
|
||||||
|
@@ -35,11 +35,15 @@
|
||||||
|
#include <ldconfig.h>
|
||||||
|
#include <dl-cache.h>
|
||||||
|
#include <version.h>
|
||||||
|
+#include <stringtable.h>
|
||||||
|
+
|
||||||
|
+/* Used to store library names, paths, and other strings. */
|
||||||
|
+static struct stringtable strings;
|
||||||
|
|
||||||
|
struct cache_entry
|
||||||
|
{
|
||||||
|
- char *lib; /* Library name. */
|
||||||
|
- char *path; /* Path to find library. */
|
||||||
|
+ struct stringtable_entry *lib; /* Library name. */
|
||||||
|
+ struct stringtable_entry *path; /* Path to find library. */
|
||||||
|
int flags; /* Flags to indicate kind of library. */
|
||||||
|
unsigned int osversion; /* Required OS version. */
|
||||||
|
uint64_t hwcap; /* Important hardware capabilities. */
|
||||||
|
@@ -300,7 +304,7 @@ static int
|
||||||
|
compare (const struct cache_entry *e1, const struct cache_entry *e2)
|
||||||
|
{
|
||||||
|
/* We need to swap entries here to get the correct sort order. */
|
||||||
|
- int res = _dl_cache_libcmp (e2->lib, e1->lib);
|
||||||
|
+ int res = _dl_cache_libcmp (e2->lib->string, e1->lib->string);
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
if (e1->flags < e2->flags)
|
||||||
|
@@ -369,26 +373,24 @@ save_cache (const char *cache_name)
|
||||||
|
{
|
||||||
|
/* The cache entries are sorted already, save them in this order. */
|
||||||
|
|
||||||
|
- /* Count the length of all strings. */
|
||||||
|
- /* The old format doesn't contain hwcap entries and doesn't contain
|
||||||
|
- libraries in subdirectories with hwcaps entries. Count therefore
|
||||||
|
- also all entries with hwcap == 0. */
|
||||||
|
- size_t total_strlen = 0;
|
||||||
|
struct cache_entry *entry;
|
||||||
|
/* Number of cache entries. */
|
||||||
|
int cache_entry_count = 0;
|
||||||
|
- /* Number of normal cache entries. */
|
||||||
|
+ /* The old format doesn't contain hwcap entries and doesn't contain
|
||||||
|
+ libraries in subdirectories with hwcaps entries. Count therefore
|
||||||
|
+ also all entries with hwcap == 0. */
|
||||||
|
int cache_entry_old_count = 0;
|
||||||
|
|
||||||
|
for (entry = entries; entry != NULL; entry = entry->next)
|
||||||
|
{
|
||||||
|
- /* Account the final NULs. */
|
||||||
|
- total_strlen += strlen (entry->lib) + strlen (entry->path) + 2;
|
||||||
|
++cache_entry_count;
|
||||||
|
if (entry->hwcap == 0)
|
||||||
|
++cache_entry_old_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ struct stringtable_finalized strings_finalized;
|
||||||
|
+ stringtable_finalize (&strings, &strings_finalized);
|
||||||
|
+
|
||||||
|
/* Create the on disk cache structure. */
|
||||||
|
struct cache_file *file_entries = NULL;
|
||||||
|
size_t file_entries_size = 0;
|
||||||
|
@@ -432,7 +434,7 @@ save_cache (const char *cache_name)
|
||||||
|
sizeof CACHE_VERSION - 1);
|
||||||
|
|
||||||
|
file_entries_new->nlibs = cache_entry_count;
|
||||||
|
- file_entries_new->len_strings = total_strlen;
|
||||||
|
+ file_entries_new->len_strings = strings_finalized.size;
|
||||||
|
file_entries_new->flags = cache_file_new_flags_endian_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -449,20 +451,20 @@ save_cache (const char *cache_name)
|
||||||
|
str_offset = 0;
|
||||||
|
|
||||||
|
/* An array for all strings. */
|
||||||
|
- char *strings = xmalloc (total_strlen);
|
||||||
|
- char *str = strings;
|
||||||
|
int idx_old;
|
||||||
|
int idx_new;
|
||||||
|
|
||||||
|
for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
|
||||||
|
entry = entry->next, ++idx_new)
|
||||||
|
{
|
||||||
|
- /* First the library. */
|
||||||
|
if (opt_format != opt_format_new && entry->hwcap == 0)
|
||||||
|
{
|
||||||
|
file_entries->libs[idx_old].flags = entry->flags;
|
||||||
|
/* XXX: Actually we can optimize here and remove duplicates. */
|
||||||
|
file_entries->libs[idx_old].key = str_offset + pad;
|
||||||
|
+ file_entries->libs[idx_new].key = str_offset + entry->lib->offset;
|
||||||
|
+ file_entries->libs[idx_new].value
|
||||||
|
+ = str_offset + entry->path->offset;
|
||||||
|
}
|
||||||
|
if (opt_format != opt_format_old)
|
||||||
|
{
|
||||||
|
@@ -473,20 +475,12 @@ save_cache (const char *cache_name)
|
||||||
|
file_entries_new->libs[idx_new].flags = entry->flags;
|
||||||
|
file_entries_new->libs[idx_new].osversion = entry->osversion;
|
||||||
|
file_entries_new->libs[idx_new].hwcap = entry->hwcap;
|
||||||
|
- file_entries_new->libs[idx_new].key = str_offset;
|
||||||
|
+ file_entries_new->libs[idx_new].key
|
||||||
|
+ = str_offset + entry->lib->offset;
|
||||||
|
+ file_entries_new->libs[idx_new].value
|
||||||
|
+ = str_offset + entry->path->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
- size_t len = strlen (entry->lib) + 1;
|
||||||
|
- str = mempcpy (str, entry->lib, len);
|
||||||
|
- str_offset += len;
|
||||||
|
- /* Then the path. */
|
||||||
|
- if (opt_format != opt_format_new && entry->hwcap == 0)
|
||||||
|
- file_entries->libs[idx_old].value = str_offset + pad;
|
||||||
|
- if (opt_format != opt_format_old)
|
||||||
|
- file_entries_new->libs[idx_new].value = str_offset;
|
||||||
|
- len = strlen (entry->path) + 1;
|
||||||
|
- str = mempcpy (str, entry->path, len);
|
||||||
|
- str_offset += len;
|
||||||
|
/* Ignore entries with hwcap for old format. */
|
||||||
|
if (entry->hwcap == 0)
|
||||||
|
++idx_old;
|
||||||
|
@@ -511,7 +505,7 @@ save_cache (const char *cache_name)
|
||||||
|
extension_offset += pad;
|
||||||
|
extension_offset += file_entries_new_size;
|
||||||
|
}
|
||||||
|
- extension_offset += total_strlen;
|
||||||
|
+ extension_offset += strings_finalized.size;
|
||||||
|
extension_offset = roundup (extension_offset, 4); /* Provide alignment. */
|
||||||
|
if (opt_format != opt_format_old)
|
||||||
|
file_entries_new->extension_offset = extension_offset;
|
||||||
|
@@ -551,7 +545,8 @@ save_cache (const char *cache_name)
|
||||||
|
error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (write (fd, strings, total_strlen) != (ssize_t) total_strlen)
|
||||||
|
+ if (write (fd, strings_finalized.strings, strings_finalized.size)
|
||||||
|
+ != (ssize_t) strings_finalized.size)
|
||||||
|
error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
|
||||||
|
|
||||||
|
if (opt_format != opt_format_old)
|
||||||
|
@@ -580,7 +575,7 @@ save_cache (const char *cache_name)
|
||||||
|
/* Free all allocated memory. */
|
||||||
|
free (file_entries_new);
|
||||||
|
free (file_entries);
|
||||||
|
- free (strings);
|
||||||
|
+ free (strings_finalized.strings);
|
||||||
|
|
||||||
|
while (entries)
|
||||||
|
{
|
||||||
|
@@ -596,14 +591,19 @@ void
|
||||||
|
add_to_cache (const char *path, const char *lib, int flags,
|
||||||
|
unsigned int osversion, uint64_t hwcap)
|
||||||
|
{
|
||||||
|
- size_t liblen = strlen (lib) + 1;
|
||||||
|
- size_t len = liblen + strlen (path) + 1;
|
||||||
|
- struct cache_entry *new_entry
|
||||||
|
- = xmalloc (sizeof (struct cache_entry) + liblen + len);
|
||||||
|
-
|
||||||
|
- new_entry->lib = memcpy ((char *) (new_entry + 1), lib, liblen);
|
||||||
|
- new_entry->path = new_entry->lib + liblen;
|
||||||
|
- snprintf (new_entry->path, len, "%s/%s", path, lib);
|
||||||
|
+ struct cache_entry *new_entry = xmalloc (sizeof (*new_entry));
|
||||||
|
+
|
||||||
|
+ struct stringtable_entry *path_interned;
|
||||||
|
+ {
|
||||||
|
+ char *p;
|
||||||
|
+ if (asprintf (&p, "%s/%s", path, lib) < 0)
|
||||||
|
+ error (EXIT_FAILURE, errno, _("Could not create library path"));
|
||||||
|
+ path_interned = stringtable_add (&strings, p);
|
||||||
|
+ free (p);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ new_entry->lib = stringtable_add (&strings, lib);
|
||||||
|
+ new_entry->path = path_interned;
|
||||||
|
new_entry->flags = flags;
|
||||||
|
new_entry->osversion = osversion;
|
||||||
|
new_entry->hwcap = hwcap;
|
778
SOURCES/glibc-rh1817513-118.patch
Normal file
778
SOURCES/glibc-rh1817513-118.patch
Normal file
@ -0,0 +1,778 @@
|
|||||||
|
commit b44ac4f4c7a8bbe5eaa2701aa9452eaf2c96e1dd
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 4 09:13:43 2020 +0100
|
||||||
|
|
||||||
|
elf: Process glibc-hwcaps subdirectories in ldconfig
|
||||||
|
|
||||||
|
Libraries from these subdirectories are added to the cache
|
||||||
|
with a special hwcap bit DL_CACHE_HWCAP_EXTENSION, so that
|
||||||
|
they are ignored by older dynamic loaders.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/cache.c b/elf/cache.c
|
||||||
|
index f773cacacf26db1c..dde3d7fefa4105f9 100644
|
||||||
|
--- a/elf/cache.c
|
||||||
|
+++ b/elf/cache.c
|
||||||
|
@@ -40,6 +40,105 @@
|
||||||
|
/* Used to store library names, paths, and other strings. */
|
||||||
|
static struct stringtable strings;
|
||||||
|
|
||||||
|
+/* Keeping track of "glibc-hwcaps" subdirectories. During cache
|
||||||
|
+ construction, a linear search by name is performed to deduplicate
|
||||||
|
+ entries. */
|
||||||
|
+struct glibc_hwcaps_subdirectory
|
||||||
|
+{
|
||||||
|
+ struct glibc_hwcaps_subdirectory *next;
|
||||||
|
+
|
||||||
|
+ /* Interned string with the subdirectory name. */
|
||||||
|
+ struct stringtable_entry *name;
|
||||||
|
+
|
||||||
|
+ /* Array index in the cache_extension_tag_glibc_hwcaps section in
|
||||||
|
+ the stored cached file. This is computed after all the
|
||||||
|
+ subdirectories have been processed, so that subdirectory names in
|
||||||
|
+ the extension section can be sorted. */
|
||||||
|
+ uint32_t section_index;
|
||||||
|
+
|
||||||
|
+ /* True if the subdirectory is actually used for anything. */
|
||||||
|
+ bool used;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+const char *
|
||||||
|
+glibc_hwcaps_subdirectory_name (const struct glibc_hwcaps_subdirectory *dir)
|
||||||
|
+{
|
||||||
|
+ return dir->name->string;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Linked list of known hwcaps subdirecty names. */
|
||||||
|
+static struct glibc_hwcaps_subdirectory *hwcaps;
|
||||||
|
+
|
||||||
|
+struct glibc_hwcaps_subdirectory *
|
||||||
|
+new_glibc_hwcaps_subdirectory (const char *name)
|
||||||
|
+{
|
||||||
|
+ struct stringtable_entry *name_interned = stringtable_add (&strings, name);
|
||||||
|
+ for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
|
||||||
|
+ if (p->name == name_interned)
|
||||||
|
+ return p;
|
||||||
|
+ struct glibc_hwcaps_subdirectory *p = xmalloc (sizeof (*p));
|
||||||
|
+ p->next = hwcaps;
|
||||||
|
+ p->name = name_interned;
|
||||||
|
+ p->section_index = 0;
|
||||||
|
+ p->used = false;
|
||||||
|
+ hwcaps = p;
|
||||||
|
+ return p;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Helper for sorting struct glibc_hwcaps_subdirectory elements by
|
||||||
|
+ name. */
|
||||||
|
+static int
|
||||||
|
+assign_glibc_hwcaps_indices_compare (const void *l, const void *r)
|
||||||
|
+{
|
||||||
|
+ const struct glibc_hwcaps_subdirectory *left
|
||||||
|
+ = *(struct glibc_hwcaps_subdirectory **)l;
|
||||||
|
+ const struct glibc_hwcaps_subdirectory *right
|
||||||
|
+ = *(struct glibc_hwcaps_subdirectory **)r;
|
||||||
|
+ return strcmp (glibc_hwcaps_subdirectory_name (left),
|
||||||
|
+ glibc_hwcaps_subdirectory_name (right));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Count the number of hwcaps subdirectories which are actually
|
||||||
|
+ used. */
|
||||||
|
+static size_t
|
||||||
|
+glibc_hwcaps_count (void)
|
||||||
|
+{
|
||||||
|
+ size_t count = 0;
|
||||||
|
+ for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
|
||||||
|
+ if (p->used)
|
||||||
|
+ ++count;
|
||||||
|
+ return count;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Compute the section_index fields for all */
|
||||||
|
+static void
|
||||||
|
+assign_glibc_hwcaps_indices (void)
|
||||||
|
+{
|
||||||
|
+ /* Convert the linked list into an array, so that we can use qsort.
|
||||||
|
+ Only copy the subdirectories which are actually used. */
|
||||||
|
+ size_t count = glibc_hwcaps_count ();
|
||||||
|
+ struct glibc_hwcaps_subdirectory **array
|
||||||
|
+ = xmalloc (sizeof (*array) * count);
|
||||||
|
+ {
|
||||||
|
+ size_t i = 0;
|
||||||
|
+ for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
|
||||||
|
+ if (p->used)
|
||||||
|
+ {
|
||||||
|
+ array[i] = p;
|
||||||
|
+ ++i;
|
||||||
|
+ }
|
||||||
|
+ assert (i == count);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ qsort (array, count, sizeof (*array), assign_glibc_hwcaps_indices_compare);
|
||||||
|
+
|
||||||
|
+ /* Assign the array indices. */
|
||||||
|
+ for (size_t i = 0; i < count; ++i)
|
||||||
|
+ array[i]->section_index = i;
|
||||||
|
+
|
||||||
|
+ free (array);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct cache_entry
|
||||||
|
{
|
||||||
|
struct stringtable_entry *lib; /* Library name. */
|
||||||
|
@@ -48,6 +147,10 @@ struct cache_entry
|
||||||
|
unsigned int osversion; /* Required OS version. */
|
||||||
|
uint64_t hwcap; /* Important hardware capabilities. */
|
||||||
|
int bits_hwcap; /* Number of bits set in hwcap. */
|
||||||
|
+
|
||||||
|
+ /* glibc-hwcaps subdirectory. If not NULL, hwcap must be zero. */
|
||||||
|
+ struct glibc_hwcaps_subdirectory *hwcaps;
|
||||||
|
+
|
||||||
|
struct cache_entry *next; /* Next entry in list. */
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -60,7 +163,7 @@ static const char *flag_descr[] =
|
||||||
|
/* Print a single entry. */
|
||||||
|
static void
|
||||||
|
print_entry (const char *lib, int flag, unsigned int osversion,
|
||||||
|
- uint64_t hwcap, const char *key)
|
||||||
|
+ uint64_t hwcap, const char *hwcap_string, const char *key)
|
||||||
|
{
|
||||||
|
printf ("\t%s (", lib);
|
||||||
|
switch (flag & FLAG_TYPE_MASK)
|
||||||
|
@@ -132,7 +235,9 @@ print_entry (const char *lib, int flag, unsigned int osversion,
|
||||||
|
printf (",%d", flag & FLAG_REQUIRED_MASK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- if (hwcap != 0)
|
||||||
|
+ if (hwcap_string != NULL)
|
||||||
|
+ printf (", hwcap: \"%s\"", hwcap_string);
|
||||||
|
+ else if (hwcap != 0)
|
||||||
|
printf (", hwcap: %#.16" PRIx64, hwcap);
|
||||||
|
if (osversion != 0)
|
||||||
|
{
|
||||||
|
@@ -158,6 +263,29 @@ print_entry (const char *lib, int flag, unsigned int osversion,
|
||||||
|
printf (") => %s\n", key);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Returns the string with the name of the glibcs-hwcaps subdirectory
|
||||||
|
+ associated with ENTRY->hwcap. file_base must be the base address
|
||||||
|
+ for string table indices. */
|
||||||
|
+static const char *
|
||||||
|
+glibc_hwcaps_string (struct cache_extension_all_loaded *ext,
|
||||||
|
+ const void *file_base, size_t file_size,
|
||||||
|
+ struct file_entry_new *entry)
|
||||||
|
+{
|
||||||
|
+ const uint32_t *hwcaps_array
|
||||||
|
+ = ext->sections[cache_extension_tag_glibc_hwcaps].base;
|
||||||
|
+ if (dl_cache_hwcap_extension (entry) && hwcaps_array != NULL)
|
||||||
|
+ {
|
||||||
|
+ uint32_t index = (uint32_t) entry->hwcap;
|
||||||
|
+ if (index < ext->sections[cache_extension_tag_glibc_hwcaps].size / 4)
|
||||||
|
+ {
|
||||||
|
+ uint32_t string_table_index = hwcaps_array[index];
|
||||||
|
+ if (string_table_index < file_size)
|
||||||
|
+ return file_base + string_table_index;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Print an error and exit if the new-file cache is internally
|
||||||
|
inconsistent. */
|
||||||
|
static void
|
||||||
|
@@ -167,9 +295,7 @@ check_new_cache (struct cache_file_new *cache)
|
||||||
|
error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Print the extension information at the cache at start address
|
||||||
|
- FILE_BASE, of length FILE_SIZE bytes. The new-format cache header
|
||||||
|
- is at CACHE, and the file name for diagnostics is CACHE_NAME. */
|
||||||
|
+/* Print the extension information in *EXT. */
|
||||||
|
static void
|
||||||
|
print_extensions (struct cache_extension_all_loaded *ext)
|
||||||
|
{
|
||||||
|
@@ -266,7 +392,7 @@ print_cache (const char *cache_name)
|
||||||
|
/* Print everything. */
|
||||||
|
for (unsigned int i = 0; i < cache->nlibs; i++)
|
||||||
|
print_entry (cache_data + cache->libs[i].key,
|
||||||
|
- cache->libs[i].flags, 0, 0,
|
||||||
|
+ cache->libs[i].flags, 0, 0, NULL,
|
||||||
|
cache_data + cache->libs[i].value);
|
||||||
|
}
|
||||||
|
else if (format == 1)
|
||||||
|
@@ -281,11 +407,16 @@ print_cache (const char *cache_name)
|
||||||
|
|
||||||
|
/* Print everything. */
|
||||||
|
for (unsigned int i = 0; i < cache_new->nlibs; i++)
|
||||||
|
- print_entry (cache_data + cache_new->libs[i].key,
|
||||||
|
- cache_new->libs[i].flags,
|
||||||
|
- cache_new->libs[i].osversion,
|
||||||
|
- cache_new->libs[i].hwcap,
|
||||||
|
- cache_data + cache_new->libs[i].value);
|
||||||
|
+ {
|
||||||
|
+ const char *hwcaps_string
|
||||||
|
+ = glibc_hwcaps_string (&ext, cache, cache_size,
|
||||||
|
+ &cache_new->libs[i]);
|
||||||
|
+ print_entry (cache_data + cache_new->libs[i].key,
|
||||||
|
+ cache_new->libs[i].flags,
|
||||||
|
+ cache_new->libs[i].osversion,
|
||||||
|
+ cache_new->libs[i].hwcap, hwcaps_string,
|
||||||
|
+ cache_data + cache_new->libs[i].value);
|
||||||
|
+ }
|
||||||
|
print_extensions (&ext);
|
||||||
|
}
|
||||||
|
/* Cleanup. */
|
||||||
|
@@ -311,8 +442,23 @@ compare (const struct cache_entry *e1, const struct cache_entry *e2)
|
||||||
|
return 1;
|
||||||
|
else if (e1->flags > e2->flags)
|
||||||
|
return -1;
|
||||||
|
+ /* Keep the glibc-hwcaps extension entries before the regular
|
||||||
|
+ entries, and sort them by their names. search_cache in
|
||||||
|
+ dl-cache.c stops searching once the first non-extension entry
|
||||||
|
+ is found, so the extension entries need to come first. */
|
||||||
|
+ else if (e1->hwcaps != NULL && e2->hwcaps == NULL)
|
||||||
|
+ return -1;
|
||||||
|
+ else if (e1->hwcaps == NULL && e2->hwcaps != NULL)
|
||||||
|
+ return 1;
|
||||||
|
+ else if (e1->hwcaps != NULL && e2->hwcaps != NULL)
|
||||||
|
+ {
|
||||||
|
+ res = strcmp (glibc_hwcaps_subdirectory_name (e1->hwcaps),
|
||||||
|
+ glibc_hwcaps_subdirectory_name (e2->hwcaps));
|
||||||
|
+ if (res != 0)
|
||||||
|
+ return res;
|
||||||
|
+ }
|
||||||
|
/* Sort by most specific hwcap. */
|
||||||
|
- else if (e2->bits_hwcap > e1->bits_hwcap)
|
||||||
|
+ if (e2->bits_hwcap > e1->bits_hwcap)
|
||||||
|
return 1;
|
||||||
|
else if (e2->bits_hwcap < e1->bits_hwcap)
|
||||||
|
return -1;
|
||||||
|
@@ -337,30 +483,65 @@ enum
|
||||||
|
* sizeof (struct cache_extension_section)))
|
||||||
|
};
|
||||||
|
|
||||||
|
-/* Write the cache extensions to FD. The extension directory is
|
||||||
|
- assumed to be located at CACHE_EXTENSION_OFFSET. */
|
||||||
|
+/* Write the cache extensions to FD. The string table is shifted by
|
||||||
|
+ STRING_TABLE_OFFSET. The extension directory is assumed to be
|
||||||
|
+ located at CACHE_EXTENSION_OFFSET. assign_glibc_hwcaps_indices
|
||||||
|
+ must have been called. */
|
||||||
|
static void
|
||||||
|
-write_extensions (int fd, uint32_t cache_extension_offset)
|
||||||
|
+write_extensions (int fd, uint32_t str_offset,
|
||||||
|
+ uint32_t cache_extension_offset)
|
||||||
|
{
|
||||||
|
assert ((cache_extension_offset % 4) == 0);
|
||||||
|
|
||||||
|
+ /* The length and contents of the glibc-hwcaps section. */
|
||||||
|
+ uint32_t hwcaps_count = glibc_hwcaps_count ();
|
||||||
|
+ uint32_t hwcaps_offset = cache_extension_offset + cache_extension_size;
|
||||||
|
+ uint32_t hwcaps_size = hwcaps_count * sizeof (uint32_t);
|
||||||
|
+ uint32_t *hwcaps_array = xmalloc (hwcaps_size);
|
||||||
|
+ for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
|
||||||
|
+ if (p->used)
|
||||||
|
+ hwcaps_array[p->section_index] = str_offset + p->name->offset;
|
||||||
|
+
|
||||||
|
+ /* This is the offset of the generator string. */
|
||||||
|
+ uint32_t generator_offset = hwcaps_offset;
|
||||||
|
+ if (hwcaps_count == 0)
|
||||||
|
+ /* There is no section for the hwcaps subdirectories. */
|
||||||
|
+ generator_offset -= sizeof (struct cache_extension_section);
|
||||||
|
+ else
|
||||||
|
+ /* The string table indices for the hwcaps subdirectories shift
|
||||||
|
+ the generator string backwards. */
|
||||||
|
+ generator_offset += hwcaps_size;
|
||||||
|
+
|
||||||
|
struct cache_extension *ext = xmalloc (cache_extension_size);
|
||||||
|
ext->magic = cache_extension_magic;
|
||||||
|
- ext->count = cache_extension_count;
|
||||||
|
|
||||||
|
- for (int i = 0; i < cache_extension_count; ++i)
|
||||||
|
- {
|
||||||
|
- ext->sections[i].tag = i;
|
||||||
|
- ext->sections[i].flags = 0;
|
||||||
|
- }
|
||||||
|
+ /* Extension index current being filled. */
|
||||||
|
+ size_t xid = 0;
|
||||||
|
|
||||||
|
const char *generator
|
||||||
|
= "ldconfig " PKGVERSION RELEASE " release version " VERSION;
|
||||||
|
- ext->sections[cache_extension_tag_generator].offset
|
||||||
|
- = cache_extension_offset + cache_extension_size;
|
||||||
|
- ext->sections[cache_extension_tag_generator].size = strlen (generator);
|
||||||
|
+ ext->sections[xid].tag = cache_extension_tag_generator;
|
||||||
|
+ ext->sections[xid].flags = 0;
|
||||||
|
+ ext->sections[xid].offset = generator_offset;
|
||||||
|
+ ext->sections[xid].size = strlen (generator);
|
||||||
|
+
|
||||||
|
+ if (hwcaps_count > 0)
|
||||||
|
+ {
|
||||||
|
+ ++xid;
|
||||||
|
+ ext->sections[xid].tag = cache_extension_tag_glibc_hwcaps;
|
||||||
|
+ ext->sections[xid].flags = 0;
|
||||||
|
+ ext->sections[xid].offset = hwcaps_offset;
|
||||||
|
+ ext->sections[xid].size = hwcaps_size;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ++xid;
|
||||||
|
+ ext->count = xid;
|
||||||
|
+ assert (xid <= cache_extension_count);
|
||||||
|
|
||||||
|
- if (write (fd, ext, cache_extension_size) != cache_extension_size
|
||||||
|
+ size_t ext_size = (offsetof (struct cache_extension, sections)
|
||||||
|
+ + xid * sizeof (struct cache_extension_section));
|
||||||
|
+ if (write (fd, ext, ext_size) != ext_size
|
||||||
|
+ || write (fd, hwcaps_array, hwcaps_size) != hwcaps_size
|
||||||
|
|| write (fd, generator, strlen (generator)) != strlen (generator))
|
||||||
|
error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
|
||||||
|
|
||||||
|
@@ -373,6 +554,8 @@ save_cache (const char *cache_name)
|
||||||
|
{
|
||||||
|
/* The cache entries are sorted already, save them in this order. */
|
||||||
|
|
||||||
|
+ assign_glibc_hwcaps_indices ();
|
||||||
|
+
|
||||||
|
struct cache_entry *entry;
|
||||||
|
/* Number of cache entries. */
|
||||||
|
int cache_entry_count = 0;
|
||||||
|
@@ -474,7 +657,11 @@ save_cache (const char *cache_name)
|
||||||
|
struct. */
|
||||||
|
file_entries_new->libs[idx_new].flags = entry->flags;
|
||||||
|
file_entries_new->libs[idx_new].osversion = entry->osversion;
|
||||||
|
- file_entries_new->libs[idx_new].hwcap = entry->hwcap;
|
||||||
|
+ if (entry->hwcaps == NULL)
|
||||||
|
+ file_entries_new->libs[idx_new].hwcap = entry->hwcap;
|
||||||
|
+ else
|
||||||
|
+ file_entries_new->libs[idx_new].hwcap
|
||||||
|
+ = DL_CACHE_HWCAP_EXTENSION | entry->hwcaps->section_index;
|
||||||
|
file_entries_new->libs[idx_new].key
|
||||||
|
= str_offset + entry->lib->offset;
|
||||||
|
file_entries_new->libs[idx_new].value
|
||||||
|
@@ -554,7 +741,7 @@ save_cache (const char *cache_name)
|
||||||
|
/* Align file position to 4. */
|
||||||
|
off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET);
|
||||||
|
assert ((unsigned long long int) (extension_offset - old_offset) < 4);
|
||||||
|
- write_extensions (fd, extension_offset);
|
||||||
|
+ write_extensions (fd, str_offset, extension_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure user can always read cache file */
|
||||||
|
@@ -588,27 +775,35 @@ save_cache (const char *cache_name)
|
||||||
|
|
||||||
|
/* Add one library to the cache. */
|
||||||
|
void
|
||||||
|
-add_to_cache (const char *path, const char *lib, int flags,
|
||||||
|
- unsigned int osversion, uint64_t hwcap)
|
||||||
|
+add_to_cache (const char *path, const char *filename, const char *soname,
|
||||||
|
+ int flags, unsigned int osversion, uint64_t hwcap,
|
||||||
|
+ struct glibc_hwcaps_subdirectory *hwcaps)
|
||||||
|
{
|
||||||
|
struct cache_entry *new_entry = xmalloc (sizeof (*new_entry));
|
||||||
|
|
||||||
|
struct stringtable_entry *path_interned;
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
- if (asprintf (&p, "%s/%s", path, lib) < 0)
|
||||||
|
+ if (asprintf (&p, "%s/%s", path, filename) < 0)
|
||||||
|
error (EXIT_FAILURE, errno, _("Could not create library path"));
|
||||||
|
path_interned = stringtable_add (&strings, p);
|
||||||
|
free (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
- new_entry->lib = stringtable_add (&strings, lib);
|
||||||
|
+ new_entry->lib = stringtable_add (&strings, soname);
|
||||||
|
new_entry->path = path_interned;
|
||||||
|
new_entry->flags = flags;
|
||||||
|
new_entry->osversion = osversion;
|
||||||
|
new_entry->hwcap = hwcap;
|
||||||
|
+ new_entry->hwcaps = hwcaps;
|
||||||
|
new_entry->bits_hwcap = 0;
|
||||||
|
|
||||||
|
+ if (hwcaps != NULL)
|
||||||
|
+ {
|
||||||
|
+ assert (hwcap == 0);
|
||||||
|
+ hwcaps->used = true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Count the number of bits set in the masked value. */
|
||||||
|
for (size_t i = 0;
|
||||||
|
(~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
|
||||||
|
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||||
|
index 0fa5aef83f9cd86c..8c66d7e5426d8cc4 100644
|
||||||
|
--- a/elf/ldconfig.c
|
||||||
|
+++ b/elf/ldconfig.c
|
||||||
|
@@ -16,6 +16,7 @@
|
||||||
|
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#define PROCINFO_CLASS static
|
||||||
|
+#include <assert.h>
|
||||||
|
#include <alloca.h>
|
||||||
|
#include <argp.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
@@ -41,6 +42,7 @@
|
||||||
|
|
||||||
|
#include <ldconfig.h>
|
||||||
|
#include <dl-cache.h>
|
||||||
|
+#include <dl-hwcaps.h>
|
||||||
|
|
||||||
|
#include <dl-procinfo.h>
|
||||||
|
|
||||||
|
@@ -85,6 +87,10 @@ struct dir_entry
|
||||||
|
dev_t dev;
|
||||||
|
const char *from_file;
|
||||||
|
int from_line;
|
||||||
|
+
|
||||||
|
+ /* Non-NULL for subdirectories under a glibc-hwcaps subdirectory. */
|
||||||
|
+ struct glibc_hwcaps_subdirectory *hwcaps;
|
||||||
|
+
|
||||||
|
struct dir_entry *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -338,17 +344,20 @@ new_sub_entry (const struct dir_entry *entry, const char *path,
|
||||||
|
new_entry->from_line = entry->from_line;
|
||||||
|
new_entry->path = xstrdup (path);
|
||||||
|
new_entry->flag = entry->flag;
|
||||||
|
+ new_entry->hwcaps = NULL;
|
||||||
|
new_entry->next = NULL;
|
||||||
|
new_entry->ino = st->st_ino;
|
||||||
|
new_entry->dev = st->st_dev;
|
||||||
|
return new_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Add a single directory entry. */
|
||||||
|
-static void
|
||||||
|
+/* Add a single directory entry. Return true if the directory is
|
||||||
|
+ actually added (because it is not a duplicate). */
|
||||||
|
+static bool
|
||||||
|
add_single_dir (struct dir_entry *entry, int verbose)
|
||||||
|
{
|
||||||
|
struct dir_entry *ptr, *prev;
|
||||||
|
+ bool added = true;
|
||||||
|
|
||||||
|
ptr = dir_entries;
|
||||||
|
prev = ptr;
|
||||||
|
@@ -368,6 +377,7 @@ add_single_dir (struct dir_entry *entry, int verbose)
|
||||||
|
ptr->flag = entry->flag;
|
||||||
|
free (entry->path);
|
||||||
|
free (entry);
|
||||||
|
+ added = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev = ptr;
|
||||||
|
@@ -378,6 +388,73 @@ add_single_dir (struct dir_entry *entry, int verbose)
|
||||||
|
dir_entries = entry;
|
||||||
|
else if (ptr == NULL)
|
||||||
|
prev->next = entry;
|
||||||
|
+ return added;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Check if PATH contains a "glibc-hwcaps" subdirectory. If so, queue
|
||||||
|
+ its subdirectories for glibc-hwcaps processing. */
|
||||||
|
+static void
|
||||||
|
+add_glibc_hwcaps_subdirectories (struct dir_entry *entry, const char *path)
|
||||||
|
+{
|
||||||
|
+ /* glibc-hwcaps subdirectories do not nest. */
|
||||||
|
+ assert (entry->hwcaps == NULL);
|
||||||
|
+
|
||||||
|
+ char *glibc_hwcaps;
|
||||||
|
+ if (asprintf (&glibc_hwcaps, "%s/" GLIBC_HWCAPS_SUBDIRECTORY, path) < 0)
|
||||||
|
+ error (EXIT_FAILURE, errno, _("Could not form glibc-hwcaps path"));
|
||||||
|
+
|
||||||
|
+ DIR *dir = opendir (glibc_hwcaps);
|
||||||
|
+ if (dir != NULL)
|
||||||
|
+ {
|
||||||
|
+ while (true)
|
||||||
|
+ {
|
||||||
|
+ errno = 0;
|
||||||
|
+ struct dirent64 *e = readdir64 (dir);
|
||||||
|
+ if (e == NULL)
|
||||||
|
+ {
|
||||||
|
+ if (errno == 0)
|
||||||
|
+ break;
|
||||||
|
+ else
|
||||||
|
+ error (EXIT_FAILURE, errno, _("Listing directory %s"), path);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Ignore hidden subdirectories, including "." and "..", and
|
||||||
|
+ regular files. File names containing a ':' cannot be
|
||||||
|
+ looked up by the dynamic loader, so skip those as
|
||||||
|
+ well. */
|
||||||
|
+ if (e->d_name[0] == '.' || e->d_type == DT_REG
|
||||||
|
+ || strchr (e->d_name, ':') != NULL)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ /* See if this entry eventually resolves to a directory. */
|
||||||
|
+ struct stat64 st;
|
||||||
|
+ if (fstatat64 (dirfd (dir), e->d_name, &st, 0) < 0)
|
||||||
|
+ /* Ignore unreadable entries. */
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (S_ISDIR (st.st_mode))
|
||||||
|
+ {
|
||||||
|
+ /* This is a directory, so it needs to be scanned for
|
||||||
|
+ libraries, associated with the hwcaps implied by the
|
||||||
|
+ subdirectory name. */
|
||||||
|
+ char *new_path;
|
||||||
|
+ if (asprintf (&new_path, "%s/" GLIBC_HWCAPS_SUBDIRECTORY "/%s",
|
||||||
|
+ /* Use non-canonicalized path here. */
|
||||||
|
+ entry->path, e->d_name) < 0)
|
||||||
|
+ error (EXIT_FAILURE, errno,
|
||||||
|
+ _("Could not form glibc-hwcaps path"));
|
||||||
|
+ struct dir_entry *new_entry = new_sub_entry (entry, new_path,
|
||||||
|
+ &st);
|
||||||
|
+ free (new_path);
|
||||||
|
+ new_entry->hwcaps = new_glibc_hwcaps_subdirectory (e->d_name);
|
||||||
|
+ add_single_dir (new_entry, 0);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ closedir (dir);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free (glibc_hwcaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add one directory to the list of directories to process. */
|
||||||
|
@@ -386,6 +463,7 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
struct dir_entry *entry = xmalloc (sizeof (struct dir_entry));
|
||||||
|
+ entry->hwcaps = NULL;
|
||||||
|
entry->next = NULL;
|
||||||
|
|
||||||
|
entry->from_file = strdup (from_file);
|
||||||
|
@@ -443,7 +521,9 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
|
||||||
|
entry->ino = stat_buf.st_ino;
|
||||||
|
entry->dev = stat_buf.st_dev;
|
||||||
|
|
||||||
|
- add_single_dir (entry, 1);
|
||||||
|
+ if (add_single_dir (entry, 1))
|
||||||
|
+ /* Add glibc-hwcaps subdirectories if present. */
|
||||||
|
+ add_glibc_hwcaps_subdirectories (entry, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_chroot)
|
||||||
|
@@ -695,15 +775,27 @@ struct dlib_entry
|
||||||
|
static void
|
||||||
|
search_dir (const struct dir_entry *entry)
|
||||||
|
{
|
||||||
|
- uint64_t hwcap = path_hwcap (entry->path);
|
||||||
|
- if (opt_verbose)
|
||||||
|
+ uint64_t hwcap;
|
||||||
|
+ if (entry->hwcaps == NULL)
|
||||||
|
{
|
||||||
|
- if (hwcap != 0)
|
||||||
|
- printf ("%s: (hwcap: %#.16" PRIx64 ")", entry->path, hwcap);
|
||||||
|
- else
|
||||||
|
- printf ("%s:", entry->path);
|
||||||
|
- printf (_(" (from %s:%d)\n"), entry->from_file, entry->from_line);
|
||||||
|
+ hwcap = path_hwcap (entry->path);
|
||||||
|
+ if (opt_verbose)
|
||||||
|
+ {
|
||||||
|
+ if (hwcap != 0)
|
||||||
|
+ printf ("%s: (hwcap: %#.16" PRIx64 ")", entry->path, hwcap);
|
||||||
|
+ else
|
||||||
|
+ printf ("%s:", entry->path);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ hwcap = 0;
|
||||||
|
+ if (opt_verbose)
|
||||||
|
+ printf ("%s: (hwcap: \"%s\")", entry->path,
|
||||||
|
+ glibc_hwcaps_subdirectory_name (entry->hwcaps));
|
||||||
|
+ }
|
||||||
|
+ if (opt_verbose)
|
||||||
|
+ printf (_(" (from %s:%d)\n"), entry->from_file, entry->from_line);
|
||||||
|
|
||||||
|
char *dir_name;
|
||||||
|
char *real_file_name;
|
||||||
|
@@ -745,13 +837,15 @@ search_dir (const struct dir_entry *entry)
|
||||||
|
&& direntry->d_type != DT_DIR)
|
||||||
|
continue;
|
||||||
|
/* Does this file look like a shared library or is it a hwcap
|
||||||
|
- subdirectory? The dynamic linker is also considered as
|
||||||
|
+ subdirectory (if not already processing a glibc-hwcaps
|
||||||
|
+ subdirectory)? The dynamic linker is also considered as
|
||||||
|
shared library. */
|
||||||
|
if (((strncmp (direntry->d_name, "lib", 3) != 0
|
||||||
|
&& strncmp (direntry->d_name, "ld-", 3) != 0)
|
||||||
|
|| strstr (direntry->d_name, ".so") == NULL)
|
||||||
|
&& (direntry->d_type == DT_REG
|
||||||
|
- || !is_hwcap_platform (direntry->d_name)))
|
||||||
|
+ || (entry->hwcaps == NULL
|
||||||
|
+ && !is_hwcap_platform (direntry->d_name))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
size_t len = strlen (direntry->d_name);
|
||||||
|
@@ -799,7 +893,7 @@ search_dir (const struct dir_entry *entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat64 stat_buf;
|
||||||
|
- int is_dir;
|
||||||
|
+ bool is_dir;
|
||||||
|
int is_link = S_ISLNK (lstat_buf.st_mode);
|
||||||
|
if (is_link)
|
||||||
|
{
|
||||||
|
@@ -837,7 +931,10 @@ search_dir (const struct dir_entry *entry)
|
||||||
|
else
|
||||||
|
is_dir = S_ISDIR (lstat_buf.st_mode);
|
||||||
|
|
||||||
|
- if (is_dir && is_hwcap_platform (direntry->d_name))
|
||||||
|
+ /* No descending into subdirectories if this directory is a
|
||||||
|
+ glibc-hwcaps subdirectory (which are not recursive). */
|
||||||
|
+ if (entry->hwcaps == NULL
|
||||||
|
+ && is_dir && is_hwcap_platform (direntry->d_name))
|
||||||
|
{
|
||||||
|
if (!is_link
|
||||||
|
&& direntry->d_type != DT_UNKNOWN
|
||||||
|
@@ -1028,13 +1125,31 @@ search_dir (const struct dir_entry *entry)
|
||||||
|
struct dlib_entry *dlib_ptr;
|
||||||
|
for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
|
||||||
|
{
|
||||||
|
- /* Don't create links to links. */
|
||||||
|
- if (dlib_ptr->is_link == 0)
|
||||||
|
- create_links (dir_name, entry->path, dlib_ptr->name,
|
||||||
|
- dlib_ptr->soname);
|
||||||
|
+ /* The cached file name is the soname for non-glibc-hwcaps
|
||||||
|
+ subdirectories (relying on symbolic links; this helps with
|
||||||
|
+ library updates that change the file name), and the actual
|
||||||
|
+ file for glibc-hwcaps subdirectories. */
|
||||||
|
+ const char *filename;
|
||||||
|
+ if (entry->hwcaps == NULL)
|
||||||
|
+ {
|
||||||
|
+ /* Don't create links to links. */
|
||||||
|
+ if (dlib_ptr->is_link == 0)
|
||||||
|
+ create_links (dir_name, entry->path, dlib_ptr->name,
|
||||||
|
+ dlib_ptr->soname);
|
||||||
|
+ filename = dlib_ptr->soname;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* Do not create links in glibc-hwcaps subdirectories, but
|
||||||
|
+ still log the cache addition. */
|
||||||
|
+ if (opt_verbose)
|
||||||
|
+ printf ("\t%s -> %s\n", dlib_ptr->soname, dlib_ptr->name);
|
||||||
|
+ filename = dlib_ptr->name;
|
||||||
|
+ }
|
||||||
|
if (opt_build_cache)
|
||||||
|
- add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag,
|
||||||
|
- dlib_ptr->osversion, hwcap);
|
||||||
|
+ add_to_cache (entry->path, filename, dlib_ptr->soname,
|
||||||
|
+ dlib_ptr->flag, dlib_ptr->osversion,
|
||||||
|
+ hwcap, entry->hwcaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free all resources. */
|
||||||
|
diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
|
||||||
|
index 259e843724531630..6adbe3c79a32a4ec 100644
|
||||||
|
--- a/sysdeps/generic/dl-cache.h
|
||||||
|
+++ b/sysdeps/generic/dl-cache.h
|
||||||
|
@@ -99,6 +99,23 @@ struct file_entry_new
|
||||||
|
uint64_t hwcap; /* Hwcap entry. */
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* This bit in the hwcap field of struct file_entry_new indicates that
|
||||||
|
+ the lower 32 bits contain an index into the
|
||||||
|
+ cache_extension_tag_glibc_hwcaps section. Older glibc versions do
|
||||||
|
+ not know about this HWCAP bit, so they will ignore these
|
||||||
|
+ entries. */
|
||||||
|
+#define DL_CACHE_HWCAP_EXTENSION (1ULL << 62)
|
||||||
|
+
|
||||||
|
+/* Return true if the ENTRY->hwcap value indicates that
|
||||||
|
+ DL_CACHE_HWCAP_EXTENSION is used. */
|
||||||
|
+static inline bool
|
||||||
|
+dl_cache_hwcap_extension (struct file_entry_new *entry)
|
||||||
|
+{
|
||||||
|
+ /* If DL_CACHE_HWCAP_EXTENSION is set, but other bits as well, this
|
||||||
|
+ is a different kind of extension. */
|
||||||
|
+ return (entry->hwcap >> 32) == (DL_CACHE_HWCAP_EXTENSION >> 32);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* See flags member of struct cache_file_new below. */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
@@ -182,6 +199,17 @@ enum cache_extension_tag
|
||||||
|
cache file. */
|
||||||
|
cache_extension_tag_generator,
|
||||||
|
|
||||||
|
+ /* glibc-hwcaps subdirectory information. An array of uint32_t
|
||||||
|
+ values, which are indices into the string table. The strings
|
||||||
|
+ are sorted lexicographically (according to strcmp). The extra
|
||||||
|
+ level of indirection (instead of using string table indices
|
||||||
|
+ directly) allows the dynamic loader to compute the preference
|
||||||
|
+ order of the hwcaps names more efficiently.
|
||||||
|
+
|
||||||
|
+ For this section, 4-byte alignment is required, and the section
|
||||||
|
+ size must be a multiple of 4. */
|
||||||
|
+ cache_extension_tag_glibc_hwcaps,
|
||||||
|
+
|
||||||
|
/* Total number of known cache extension tags. */
|
||||||
|
cache_extension_count
|
||||||
|
};
|
||||||
|
@@ -236,6 +264,27 @@ struct cache_extension_all_loaded
|
||||||
|
struct cache_extension_loaded sections[cache_extension_count];
|
||||||
|
};
|
||||||
|
|
||||||
|
+/* Performs basic data validation based on section tag, and removes
|
||||||
|
+ the sections which are invalid. */
|
||||||
|
+static void
|
||||||
|
+cache_extension_verify (struct cache_extension_all_loaded *loaded)
|
||||||
|
+{
|
||||||
|
+ {
|
||||||
|
+ /* Section must not be empty, it must be aligned at 4 bytes, and
|
||||||
|
+ the size must be a multiple of 4. */
|
||||||
|
+ struct cache_extension_loaded *hwcaps
|
||||||
|
+ = &loaded->sections[cache_extension_tag_glibc_hwcaps];
|
||||||
|
+ if (hwcaps->size == 0
|
||||||
|
+ || ((uintptr_t) hwcaps->base % 4) != 0
|
||||||
|
+ || (hwcaps->size % 4) != 0)
|
||||||
|
+ {
|
||||||
|
+ hwcaps->base = NULL;
|
||||||
|
+ hwcaps->size = 0;
|
||||||
|
+ hwcaps->flags = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static bool __attribute__ ((unused))
|
||||||
|
cache_extension_load (const struct cache_file_new *cache,
|
||||||
|
const void *file_base, size_t file_size,
|
||||||
|
@@ -282,6 +331,7 @@ cache_extension_load (const struct cache_file_new *cache,
|
||||||
|
loaded->sections[tag].size = ext->sections[i].size;
|
||||||
|
loaded->sections[tag].flags = ext->sections[i].flags;
|
||||||
|
}
|
||||||
|
+ cache_extension_verify (loaded);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h
|
||||||
|
index b15b142511829436..a8d22f143f867a3e 100644
|
||||||
|
--- a/sysdeps/generic/ldconfig.h
|
||||||
|
+++ b/sysdeps/generic/ldconfig.h
|
||||||
|
@@ -57,8 +57,22 @@ extern void init_cache (void);
|
||||||
|
|
||||||
|
extern void save_cache (const char *cache_name);
|
||||||
|
|
||||||
|
-extern void add_to_cache (const char *path, const char *lib, int flags,
|
||||||
|
- unsigned int osversion, uint64_t hwcap);
|
||||||
|
+struct glibc_hwcaps_subdirectory;
|
||||||
|
+
|
||||||
|
+/* Return a struct describing the subdirectory for NAME. Reuse an
|
||||||
|
+ existing struct if it exists. */
|
||||||
|
+struct glibc_hwcaps_subdirectory *new_glibc_hwcaps_subdirectory
|
||||||
|
+ (const char *name);
|
||||||
|
+
|
||||||
|
+/* Returns the name that was specified when
|
||||||
|
+ add_glibc_hwcaps_subdirectory was called. */
|
||||||
|
+const char *glibc_hwcaps_subdirectory_name
|
||||||
|
+ (const struct glibc_hwcaps_subdirectory *);
|
||||||
|
+
|
||||||
|
+extern void add_to_cache (const char *path, const char *filename,
|
||||||
|
+ const char *soname,
|
||||||
|
+ int flags, unsigned int osversion, uint64_t hwcap,
|
||||||
|
+ struct glibc_hwcaps_subdirectory *);
|
||||||
|
|
||||||
|
extern void init_aux_cache (void);
|
||||||
|
|
659
SOURCES/glibc-rh1817513-119.patch
Normal file
659
SOURCES/glibc-rh1817513-119.patch
Normal file
@ -0,0 +1,659 @@
|
|||||||
|
commit 600d9e0c87940da9b0fdeff492bf888df852d40c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 4 09:13:43 2020 +0100
|
||||||
|
|
||||||
|
elf: Add glibc-hwcaps subdirectory support to ld.so cache processing
|
||||||
|
|
||||||
|
This recognizes the DL_CACHE_HWCAP_EXTENSION flag in cache entries,
|
||||||
|
and picks the supported cache entry with the highest priority.
|
||||||
|
|
||||||
|
The elf/tst-glibc-hwcaps-prepend-cache test documents a non-desired
|
||||||
|
aspect of the current cache implementation: If the cache selects a DSO
|
||||||
|
that does not exist on disk, _dl_map_object falls back to open_path,
|
||||||
|
which may or may not find an alternative implementation. This is an
|
||||||
|
existing limitation that also applies to the legacy hwcaps processing
|
||||||
|
for ld.so.cache.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index a3e802a9a99b759c..f67b231c0f8e3aff 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -162,6 +162,12 @@ tst-tls1-static-non-pie-no-pie = yes
|
||||||
|
tests-container = \
|
||||||
|
tst-ldconfig-bad-aux-cache
|
||||||
|
|
||||||
|
+ifeq (no,$(build-hardcoded-path-in-tests))
|
||||||
|
+# This is an ld.so.cache test, and RPATH/RUNPATH in the executable
|
||||||
|
+# interferes with its test objectives.
|
||||||
|
+tests-container += tst-glibc-hwcaps-prepend-cache
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
tests := tst-tls9 tst-leaks1 \
|
||||||
|
tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
|
||||||
|
tst-auxv tst-stringtable
|
||||||
|
@@ -1784,6 +1790,14 @@ $(objpfx)tst-glibc-hwcaps-prepend.out: \
|
||||||
|
$< > $@; \
|
||||||
|
$(evaluate-test)
|
||||||
|
|
||||||
|
+# Like tst-glibc-hwcaps-prepend, but uses a container and loads the
|
||||||
|
+# library via ld.so.cache. Test setup is contained in the test
|
||||||
|
+# itself.
|
||||||
|
+$(objpfx)tst-glibc-hwcaps-prepend-cache: $(libdl)
|
||||||
|
+$(objpfx)tst-glibc-hwcaps-prepend-cache.out: \
|
||||||
|
+ $(objpfx)tst-glibc-hwcaps-prepend-cache $(objpfx)libmarkermod1-1.so \
|
||||||
|
+ $(objpfx)libmarkermod1-2.so $(objpfx)libmarkermod1-3.so
|
||||||
|
+
|
||||||
|
# tst-glibc-hwcaps-mask checks that --glibc-hwcaps-mask can be used to
|
||||||
|
# suppress all auto-detected subdirectories.
|
||||||
|
$(objpfx)tst-glibc-hwcaps-mask: $(objpfx)libmarkermod1-1.so
|
||||||
|
@@ -1795,3 +1809,7 @@ $(objpfx)tst-glibc-hwcaps-mask.out: \
|
||||||
|
--glibc-hwcaps-mask does-not-exist \
|
||||||
|
$< > $@; \
|
||||||
|
$(evaluate-test)
|
||||||
|
+
|
||||||
|
+# Generic dependency for sysdeps implementation of
|
||||||
|
+# tst-glibc-hwcaps-cache.
|
||||||
|
+$(objpfx)tst-glibc-hwcaps-cache.out: $(objpfx)tst-glibc-hwcaps
|
||||||
|
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
|
||||||
|
index de063faa8b2c88ae..e75afdaee23226e6 100644
|
||||||
|
--- a/elf/dl-cache.c
|
||||||
|
+++ b/elf/dl-cache.c
|
||||||
|
@@ -35,6 +35,144 @@ static struct cache_file *cache;
|
||||||
|
static struct cache_file_new *cache_new;
|
||||||
|
static size_t cachesize;
|
||||||
|
|
||||||
|
+#ifdef SHARED
|
||||||
|
+/* This is used to cache the priorities of glibc-hwcaps
|
||||||
|
+ subdirectories. The elements of _dl_cache_priorities correspond to
|
||||||
|
+ the strings in the cache_extension_tag_glibc_hwcaps section. */
|
||||||
|
+static uint32_t *glibc_hwcaps_priorities;
|
||||||
|
+static uint32_t glibc_hwcaps_priorities_length;
|
||||||
|
+static uint32_t glibc_hwcaps_priorities_allocated;
|
||||||
|
+
|
||||||
|
+/* True if the full malloc was used to allocated the array. */
|
||||||
|
+static bool glibc_hwcaps_priorities_malloced;
|
||||||
|
+
|
||||||
|
+/* Deallocate the glibc_hwcaps_priorities array. */
|
||||||
|
+static void
|
||||||
|
+glibc_hwcaps_priorities_free (void)
|
||||||
|
+{
|
||||||
|
+ /* When the minimal malloc is in use, free does not do anything,
|
||||||
|
+ so it does not make sense to call it. */
|
||||||
|
+ if (glibc_hwcaps_priorities_malloced)
|
||||||
|
+ free (glibc_hwcaps_priorities);
|
||||||
|
+ glibc_hwcaps_priorities = NULL;
|
||||||
|
+ glibc_hwcaps_priorities_allocated = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Ordered comparison of a hwcaps string from the cache on the left
|
||||||
|
+ (identified by its string table index) and a _dl_hwcaps_priorities
|
||||||
|
+ element on the right. */
|
||||||
|
+static int
|
||||||
|
+glibc_hwcaps_compare (uint32_t left_index, struct dl_hwcaps_priority *right)
|
||||||
|
+{
|
||||||
|
+ const char *left_name = (const char *) cache + left_index;
|
||||||
|
+ uint32_t left_name_length = strlen (left_name);
|
||||||
|
+ uint32_t to_compare;
|
||||||
|
+ if (left_name_length < right->name_length)
|
||||||
|
+ to_compare = left_name_length;
|
||||||
|
+ else
|
||||||
|
+ to_compare = right->name_length;
|
||||||
|
+ int cmp = memcmp (left_name, right->name, to_compare);
|
||||||
|
+ if (cmp != 0)
|
||||||
|
+ return cmp;
|
||||||
|
+ if (left_name_length < right->name_length)
|
||||||
|
+ return -1;
|
||||||
|
+ else if (left_name_length > right->name_length)
|
||||||
|
+ return 1;
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Initialize the glibc_hwcaps_priorities array and its length,
|
||||||
|
+ glibc_hwcaps_priorities_length. */
|
||||||
|
+static void
|
||||||
|
+glibc_hwcaps_priorities_init (void)
|
||||||
|
+{
|
||||||
|
+ struct cache_extension_all_loaded ext;
|
||||||
|
+ if (!cache_extension_load (cache_new, cache, cachesize, &ext))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ uint32_t length = (ext.sections[cache_extension_tag_glibc_hwcaps].size
|
||||||
|
+ / sizeof (uint32_t));
|
||||||
|
+ if (length > glibc_hwcaps_priorities_allocated)
|
||||||
|
+ {
|
||||||
|
+ glibc_hwcaps_priorities_free ();
|
||||||
|
+
|
||||||
|
+ uint32_t *new_allocation = malloc (length * sizeof (uint32_t));
|
||||||
|
+ if (new_allocation == NULL)
|
||||||
|
+ /* This effectively disables hwcaps on memory allocation
|
||||||
|
+ errors. */
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ glibc_hwcaps_priorities = new_allocation;
|
||||||
|
+ glibc_hwcaps_priorities_allocated = length;
|
||||||
|
+ glibc_hwcaps_priorities_malloced = __rtld_malloc_is_complete ();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Compute the priorities for the subdirectories by merging the
|
||||||
|
+ array in the cache with the dl_hwcaps_priorities array. */
|
||||||
|
+ const uint32_t *left = ext.sections[cache_extension_tag_glibc_hwcaps].base;
|
||||||
|
+ const uint32_t *left_end = left + length;
|
||||||
|
+ struct dl_hwcaps_priority *right = _dl_hwcaps_priorities;
|
||||||
|
+ struct dl_hwcaps_priority *right_end = right + _dl_hwcaps_priorities_length;
|
||||||
|
+ uint32_t *result = glibc_hwcaps_priorities;
|
||||||
|
+
|
||||||
|
+ while (left < left_end && right < right_end)
|
||||||
|
+ {
|
||||||
|
+ if (*left < cachesize)
|
||||||
|
+ {
|
||||||
|
+ int cmp = glibc_hwcaps_compare (*left, right);
|
||||||
|
+ if (cmp == 0)
|
||||||
|
+ {
|
||||||
|
+ *result = right->priority;
|
||||||
|
+ ++result;
|
||||||
|
+ ++left;
|
||||||
|
+ ++right;
|
||||||
|
+ }
|
||||||
|
+ else if (cmp < 0)
|
||||||
|
+ {
|
||||||
|
+ *result = 0;
|
||||||
|
+ ++result;
|
||||||
|
+ ++left;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ ++right;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ *result = 0;
|
||||||
|
+ ++result;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ while (left < left_end)
|
||||||
|
+ {
|
||||||
|
+ *result = 0;
|
||||||
|
+ ++result;
|
||||||
|
+ ++left;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ glibc_hwcaps_priorities_length = length;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Return the priority of the cache_extension_tag_glibc_hwcaps section
|
||||||
|
+ entry at INDEX. Zero means do not use. Otherwise, lower values
|
||||||
|
+ indicate greater preference. */
|
||||||
|
+static uint32_t
|
||||||
|
+glibc_hwcaps_priority (uint32_t index)
|
||||||
|
+{
|
||||||
|
+ /* This does not need to repeated initialization attempts because
|
||||||
|
+ this function is only called if there is glibc-hwcaps data in the
|
||||||
|
+ cache, so the first call initializes the glibc_hwcaps_priorities
|
||||||
|
+ array. */
|
||||||
|
+ if (glibc_hwcaps_priorities_length == 0)
|
||||||
|
+ glibc_hwcaps_priorities_init ();
|
||||||
|
+
|
||||||
|
+ if (index < glibc_hwcaps_priorities_length)
|
||||||
|
+ return glibc_hwcaps_priorities[index];
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+#endif /* SHARED */
|
||||||
|
+
|
||||||
|
/* True if PTR is a valid string table index. */
|
||||||
|
static inline bool
|
||||||
|
_dl_cache_verify_ptr (uint32_t ptr, size_t string_table_size)
|
||||||
|
@@ -74,6 +212,9 @@ search_cache (const char *string_table, uint32_t string_table_size,
|
||||||
|
int left = 0;
|
||||||
|
int right = nlibs - 1;
|
||||||
|
const char *best = NULL;
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ uint32_t best_priority = 0;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
while (left <= right)
|
||||||
|
{
|
||||||
|
@@ -129,6 +270,11 @@ search_cache (const char *string_table, uint32_t string_table_size,
|
||||||
|
{
|
||||||
|
if (best == NULL || flags == GLRO (dl_correct_cache_id))
|
||||||
|
{
|
||||||
|
+ /* Named/extension hwcaps get slightly different
|
||||||
|
+ treatment: We keep searching for a better
|
||||||
|
+ match. */
|
||||||
|
+ bool named_hwcap = false;
|
||||||
|
+
|
||||||
|
if (entry_size >= sizeof (struct file_entry_new))
|
||||||
|
{
|
||||||
|
/* The entry is large enough to include
|
||||||
|
@@ -136,7 +282,18 @@ search_cache (const char *string_table, uint32_t string_table_size,
|
||||||
|
struct file_entry_new *libnew
|
||||||
|
= (struct file_entry_new *) lib;
|
||||||
|
|
||||||
|
- if (libnew->hwcap & hwcap_exclude)
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ named_hwcap = dl_cache_hwcap_extension (libnew);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ /* The entries with named/extension hwcaps
|
||||||
|
+ have been exhausted. Return the best
|
||||||
|
+ match encountered so far if there is
|
||||||
|
+ one. */
|
||||||
|
+ if (!named_hwcap && best != NULL)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ if ((libnew->hwcap & hwcap_exclude) && !named_hwcap)
|
||||||
|
continue;
|
||||||
|
if (GLRO (dl_osversion)
|
||||||
|
&& libnew->osversion > GLRO (dl_osversion))
|
||||||
|
@@ -146,14 +303,41 @@ search_cache (const char *string_table, uint32_t string_table_size,
|
||||||
|
&& ((libnew->hwcap & _DL_HWCAP_PLATFORM)
|
||||||
|
!= platform))
|
||||||
|
continue;
|
||||||
|
+
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ /* For named hwcaps, determine the priority
|
||||||
|
+ and see if beats what has been found so
|
||||||
|
+ far. */
|
||||||
|
+ if (named_hwcap)
|
||||||
|
+ {
|
||||||
|
+ uint32_t entry_priority
|
||||||
|
+ = glibc_hwcaps_priority (libnew->hwcap);
|
||||||
|
+ if (entry_priority == 0)
|
||||||
|
+ /* Not usable at all. Skip. */
|
||||||
|
+ continue;
|
||||||
|
+ else if (best == NULL
|
||||||
|
+ || entry_priority < best_priority)
|
||||||
|
+ /* This entry is of higher priority
|
||||||
|
+ than the previous one, or it is the
|
||||||
|
+ first entry. */
|
||||||
|
+ best_priority = entry_priority;
|
||||||
|
+ else
|
||||||
|
+ /* An entry has already been found,
|
||||||
|
+ but it is a better match. */
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+#endif /* SHARED */
|
||||||
|
}
|
||||||
|
|
||||||
|
best = string_table + lib->value;
|
||||||
|
|
||||||
|
- if (flags == GLRO (dl_correct_cache_id))
|
||||||
|
+ if (flags == GLRO (dl_correct_cache_id)
|
||||||
|
+ && !named_hwcap)
|
||||||
|
/* We've found an exact match for the shared
|
||||||
|
object and no general `ELF' release. Stop
|
||||||
|
- searching. */
|
||||||
|
+ searching, but not if a named (extension)
|
||||||
|
+ hwcap is used. In this case, an entry with
|
||||||
|
+ a higher priority may come up later. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -346,5 +530,9 @@ _dl_unload_cache (void)
|
||||||
|
__munmap (cache, cachesize);
|
||||||
|
cache = NULL;
|
||||||
|
}
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ /* This marks the glibc_hwcaps_priorities array as out-of-date. */
|
||||||
|
+ glibc_hwcaps_priorities_length = 0;
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
||||||
|
index e57d0d2d41741021..098173a84c43c1fd 100644
|
||||||
|
--- a/elf/dl-hwcaps.c
|
||||||
|
+++ b/elf/dl-hwcaps.c
|
||||||
|
@@ -89,6 +89,81 @@ copy_hwcaps (struct copy_hwcaps *target, const char *hwcaps,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct dl_hwcaps_priority *_dl_hwcaps_priorities;
|
||||||
|
+uint32_t _dl_hwcaps_priorities_length;
|
||||||
|
+
|
||||||
|
+/* Allocate _dl_hwcaps_priorities and fill it with data. */
|
||||||
|
+static void
|
||||||
|
+compute_priorities (size_t total_count, const char *prepend,
|
||||||
|
+ uint32_t bitmask, const char *mask)
|
||||||
|
+{
|
||||||
|
+ _dl_hwcaps_priorities = malloc (total_count
|
||||||
|
+ * sizeof (*_dl_hwcaps_priorities));
|
||||||
|
+ if (_dl_hwcaps_priorities == NULL)
|
||||||
|
+ _dl_signal_error (ENOMEM, NULL, NULL,
|
||||||
|
+ N_("cannot create HWCAP priorities"));
|
||||||
|
+ _dl_hwcaps_priorities_length = total_count;
|
||||||
|
+
|
||||||
|
+ /* First the prepended subdirectories. */
|
||||||
|
+ size_t i = 0;
|
||||||
|
+ {
|
||||||
|
+ struct dl_hwcaps_split sp;
|
||||||
|
+ _dl_hwcaps_split_init (&sp, prepend);
|
||||||
|
+ while (_dl_hwcaps_split (&sp))
|
||||||
|
+ {
|
||||||
|
+ _dl_hwcaps_priorities[i].name = sp.segment;
|
||||||
|
+ _dl_hwcaps_priorities[i].name_length = sp.length;
|
||||||
|
+ _dl_hwcaps_priorities[i].priority = i + 1;
|
||||||
|
+ ++i;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Then the built-in subdirectories that are actually active. */
|
||||||
|
+ {
|
||||||
|
+ struct dl_hwcaps_split_masked sp;
|
||||||
|
+ _dl_hwcaps_split_masked_init (&sp, _dl_hwcaps_subdirs, bitmask, mask);
|
||||||
|
+ while (_dl_hwcaps_split_masked (&sp))
|
||||||
|
+ {
|
||||||
|
+ _dl_hwcaps_priorities[i].name = sp.split.segment;
|
||||||
|
+ _dl_hwcaps_priorities[i].name_length = sp.split.length;
|
||||||
|
+ _dl_hwcaps_priorities[i].priority = i + 1;
|
||||||
|
+ ++i;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ assert (i == total_count);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Sort the _dl_hwcaps_priorities array by name. */
|
||||||
|
+static void
|
||||||
|
+sort_priorities_by_name (void)
|
||||||
|
+{
|
||||||
|
+ /* Insertion sort. There is no need to link qsort into the dynamic
|
||||||
|
+ loader for such a short array. */
|
||||||
|
+ for (size_t i = 1; i < _dl_hwcaps_priorities_length; ++i)
|
||||||
|
+ for (size_t j = i; j > 0; --j)
|
||||||
|
+ {
|
||||||
|
+ struct dl_hwcaps_priority *previous = _dl_hwcaps_priorities + j - 1;
|
||||||
|
+ struct dl_hwcaps_priority *current = _dl_hwcaps_priorities + j;
|
||||||
|
+
|
||||||
|
+ /* Bail out if current is greater or equal to the previous
|
||||||
|
+ value. */
|
||||||
|
+ uint32_t to_compare;
|
||||||
|
+ if (current->name_length < previous->name_length)
|
||||||
|
+ to_compare = current->name_length;
|
||||||
|
+ else
|
||||||
|
+ to_compare = previous->name_length;
|
||||||
|
+ int cmp = memcmp (current->name, previous->name, to_compare);
|
||||||
|
+ if (cmp >= 0
|
||||||
|
+ || (cmp == 0 && current->name_length >= previous->name_length))
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ /* Swap *previous and *current. */
|
||||||
|
+ struct dl_hwcaps_priority tmp = *previous;
|
||||||
|
+ *previous = *current;
|
||||||
|
+ *current = tmp;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Return an array of useful/necessary hardware capability names. */
|
||||||
|
const struct r_strlenpair *
|
||||||
|
_dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||||
|
@@ -111,6 +186,9 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||||
|
update_hwcaps_counts (&hwcaps_counts, glibc_hwcaps_prepend, -1, NULL);
|
||||||
|
update_hwcaps_counts (&hwcaps_counts, _dl_hwcaps_subdirs,
|
||||||
|
hwcaps_subdirs_active, glibc_hwcaps_mask);
|
||||||
|
+ compute_priorities (hwcaps_counts.count, glibc_hwcaps_prepend,
|
||||||
|
+ hwcaps_subdirs_active, glibc_hwcaps_mask);
|
||||||
|
+ sort_priorities_by_name ();
|
||||||
|
|
||||||
|
/* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix
|
||||||
|
and a "/" suffix once stored in the result. */
|
||||||
|
diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h
|
||||||
|
index 3fcfbceb1a8fc1c8..769ecab3f886c6c4 100644
|
||||||
|
--- a/elf/dl-hwcaps.h
|
||||||
|
+++ b/elf/dl-hwcaps.h
|
||||||
|
@@ -132,4 +132,23 @@ _dl_hwcaps_subdirs_build_bitmask (int subdirs, int active)
|
||||||
|
return mask ^ ((1U << inactive) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Pre-computed glibc-hwcaps subdirectory priorities. Used in
|
||||||
|
+ dl-cache.c to quickly find the proprieties for the stored HWCAP
|
||||||
|
+ names. */
|
||||||
|
+struct dl_hwcaps_priority
|
||||||
|
+{
|
||||||
|
+ /* The name consists of name_length bytes at name (not necessarily
|
||||||
|
+ null-terminated). */
|
||||||
|
+ const char *name;
|
||||||
|
+ uint32_t name_length;
|
||||||
|
+
|
||||||
|
+ /* Priority of this name. A positive number. */
|
||||||
|
+ uint32_t priority;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Pre-computed hwcaps priorities. Set up by
|
||||||
|
+ _dl_important_hwcaps. */
|
||||||
|
+extern struct dl_hwcaps_priority *_dl_hwcaps_priorities attribute_hidden;
|
||||||
|
+extern uint32_t _dl_hwcaps_priorities_length attribute_hidden;
|
||||||
|
+
|
||||||
|
#endif /* _DL_HWCAPS_H */
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-cache.c b/elf/tst-glibc-hwcaps-cache.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..4bad56afc03451fc
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-glibc-hwcaps-cache.c
|
||||||
|
@@ -0,0 +1,45 @@
|
||||||
|
+/* Wrapper to invoke tst-glibc-hwcaps in a container, to test ld.so.cache.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+/* This program is just a wrapper that runs ldconfig followed by
|
||||||
|
+ tst-glibc-hwcaps. The actual test is provided via an
|
||||||
|
+ implementation in a sysdeps subdirectory. */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main (int argc, char **argv)
|
||||||
|
+{
|
||||||
|
+ /* Run ldconfig to populate the cache. */
|
||||||
|
+ {
|
||||||
|
+ char *command = xasprintf ("%s/ldconfig", support_install_rootsbindir);
|
||||||
|
+ if (system (command) != 0)
|
||||||
|
+ return 1;
|
||||||
|
+ free (command);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Reuse tst-glibc-hwcaps. Since this code is running in a
|
||||||
|
+ container, we can launch it directly. */
|
||||||
|
+ char *path = xasprintf ("%s/elf/tst-glibc-hwcaps", support_objdir_root);
|
||||||
|
+ execv (path, argv);
|
||||||
|
+ printf ("error: execv of %s failed: %m\n", path);
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-cache.root/etc/ld.so.conf b/elf/tst-glibc-hwcaps-cache.root/etc/ld.so.conf
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..e1e74dbda2bf3dfa
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-glibc-hwcaps-cache.root/etc/ld.so.conf
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+# This file was created to suppress a warning from ldconfig:
|
||||||
|
+# /sbin/ldconfig: Warning: ignoring configuration file that cannot be opened: /etc/ld.so.conf: No such file or directory
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-cache.root/postclean.req b/elf/tst-glibc-hwcaps-cache.root/postclean.req
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..e69de29bb2d1d643
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..6356d152089cdd9a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+# test-container does not support scripts in sysdeps directories, so
|
||||||
|
+# collect everything in one file.
|
||||||
|
+
|
||||||
|
+cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so
|
||||||
|
+cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so
|
||||||
|
+cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-prepend-cache.c b/elf/tst-glibc-hwcaps-prepend-cache.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..40509cebe2b5ba27
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-glibc-hwcaps-prepend-cache.c
|
||||||
|
@@ -0,0 +1,149 @@
|
||||||
|
+/* Test that --glibc-hwcaps-prepend works, using dlopen and /etc/ld.so.cache.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <dlfcn.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/xdlfcn.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+
|
||||||
|
+/* Invoke /sbin/ldconfig with some error checking. */
|
||||||
|
+static void
|
||||||
|
+run_ldconfig (void)
|
||||||
|
+{
|
||||||
|
+ char *command = xasprintf ("%s/ldconfig", support_install_rootsbindir);
|
||||||
|
+ TEST_COMPARE (system (command), 0);
|
||||||
|
+ free (command);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* The library under test. */
|
||||||
|
+#define SONAME "libmarkermod1.so"
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ if (dlopen (SONAME, RTLD_NOW) != NULL)
|
||||||
|
+ FAIL_EXIT1 (SONAME " is already on the search path");
|
||||||
|
+
|
||||||
|
+ /* Install the default implementation of libmarkermod1.so. */
|
||||||
|
+ xmkdirp ("/etc", 0777);
|
||||||
|
+ support_write_file_string ("/etc/ld.so.conf", "/glibc-test/lib\n");
|
||||||
|
+ xmkdirp ("/glibc-test/lib/glibc-hwcaps/prepend2", 0777);
|
||||||
|
+ xmkdirp ("/glibc-test/lib/glibc-hwcaps/prepend3", 0777);
|
||||||
|
+ {
|
||||||
|
+ char *src = xasprintf ("%s/elf/libmarkermod1-1.so", support_objdir_root);
|
||||||
|
+ support_copy_file (src, "/glibc-test/lib/" SONAME);
|
||||||
|
+ free (src);
|
||||||
|
+ }
|
||||||
|
+ run_ldconfig ();
|
||||||
|
+ {
|
||||||
|
+ /* The default implementation can now be loaded. */
|
||||||
|
+ void *handle = xdlopen (SONAME, RTLD_NOW);
|
||||||
|
+ int (*marker1) (void) = xdlsym (handle, "marker1");
|
||||||
|
+ TEST_COMPARE (marker1 (), 1);
|
||||||
|
+ xdlclose (handle);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Add the first override to the directory that is searched last. */
|
||||||
|
+ {
|
||||||
|
+ char *src = xasprintf ("%s/elf/libmarkermod1-2.so", support_objdir_root);
|
||||||
|
+ support_copy_file (src, "/glibc-test/lib/glibc-hwcaps/prepend2/"
|
||||||
|
+ SONAME);
|
||||||
|
+ free (src);
|
||||||
|
+ }
|
||||||
|
+ {
|
||||||
|
+ /* This is still the first implementation. The cache has not been
|
||||||
|
+ updated. */
|
||||||
|
+ void *handle = xdlopen (SONAME, RTLD_NOW);
|
||||||
|
+ int (*marker1) (void) = xdlsym (handle, "marker1");
|
||||||
|
+ TEST_COMPARE (marker1 (), 1);
|
||||||
|
+ xdlclose (handle);
|
||||||
|
+ }
|
||||||
|
+ run_ldconfig ();
|
||||||
|
+ {
|
||||||
|
+ /* After running ldconfig, it is the second implementation. */
|
||||||
|
+ void *handle = xdlopen (SONAME, RTLD_NOW);
|
||||||
|
+ int (*marker1) (void) = xdlsym (handle, "marker1");
|
||||||
|
+ TEST_COMPARE (marker1 (), 2);
|
||||||
|
+ xdlclose (handle);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Add the second override to the directory that is searched first. */
|
||||||
|
+ {
|
||||||
|
+ char *src = xasprintf ("%s/elf/libmarkermod1-3.so", support_objdir_root);
|
||||||
|
+ support_copy_file (src, "/glibc-test/lib/glibc-hwcaps/prepend3/"
|
||||||
|
+ SONAME);
|
||||||
|
+ free (src);
|
||||||
|
+ }
|
||||||
|
+ {
|
||||||
|
+ /* This is still the second implementation. */
|
||||||
|
+ void *handle = xdlopen (SONAME, RTLD_NOW);
|
||||||
|
+ int (*marker1) (void) = xdlsym (handle, "marker1");
|
||||||
|
+ TEST_COMPARE (marker1 (), 2);
|
||||||
|
+ xdlclose (handle);
|
||||||
|
+ }
|
||||||
|
+ run_ldconfig ();
|
||||||
|
+ {
|
||||||
|
+ /* After running ldconfig, it is the third implementation. */
|
||||||
|
+ void *handle = xdlopen (SONAME, RTLD_NOW);
|
||||||
|
+ int (*marker1) (void) = xdlsym (handle, "marker1");
|
||||||
|
+ TEST_COMPARE (marker1 (), 3);
|
||||||
|
+ xdlclose (handle);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Remove the second override again, without running ldconfig.
|
||||||
|
+ Ideally, this would revert to implementation 2. However, in the
|
||||||
|
+ current implementation, the cache returns exactly one file name
|
||||||
|
+ which does not exist after unlinking, so the dlopen fails. */
|
||||||
|
+ xunlink ("/glibc-test/lib/glibc-hwcaps/prepend3/" SONAME);
|
||||||
|
+ TEST_VERIFY (dlopen (SONAME, RTLD_NOW) == NULL);
|
||||||
|
+ run_ldconfig ();
|
||||||
|
+ {
|
||||||
|
+ /* After running ldconfig, the second implementation is available
|
||||||
|
+ once more. */
|
||||||
|
+ void *handle = xdlopen (SONAME, RTLD_NOW);
|
||||||
|
+ int (*marker1) (void) = xdlsym (handle, "marker1");
|
||||||
|
+ TEST_COMPARE (marker1 (), 2);
|
||||||
|
+ xdlclose (handle);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+prepare (int argc, char **argv)
|
||||||
|
+{
|
||||||
|
+ const char *no_restart = "no-restart";
|
||||||
|
+ if (argc == 2 && strcmp (argv[1], no_restart) == 0)
|
||||||
|
+ return;
|
||||||
|
+ /* Re-execute the test with an explicit loader invocation. */
|
||||||
|
+ execl (support_objdir_elf_ldso,
|
||||||
|
+ support_objdir_elf_ldso,
|
||||||
|
+ "--glibc-hwcaps-prepend", "prepend3:prepend2",
|
||||||
|
+ argv[0], no_restart,
|
||||||
|
+ NULL);
|
||||||
|
+ printf ("error: execv of %s failed: %m\n", argv[0]);
|
||||||
|
+ _exit (1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define PREPARE prepare
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-prepend-cache.root/postclean.req b/elf/tst-glibc-hwcaps-prepend-cache.root/postclean.req
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..e69de29bb2d1d643
|
38
SOURCES/glibc-rh1817513-12.patch
Normal file
38
SOURCES/glibc-rh1817513-12.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
commit 2954daf00bb4dc27c69a48e6798d5960ea320741
|
||||||
|
Author: Andreas Schwab <schwab@suse.de>
|
||||||
|
Date: Tue Oct 23 09:40:14 2018 +0200
|
||||||
|
|
||||||
|
Add more checks for valid ld.so.cache file (bug 18093)
|
||||||
|
|
||||||
|
diff --git a/elf/cache.c b/elf/cache.c
|
||||||
|
index e63979da7d25560c..c4cd825c30e00e8e 100644
|
||||||
|
--- a/elf/cache.c
|
||||||
|
+++ b/elf/cache.c
|
||||||
|
@@ -199,6 +199,11 @@ print_cache (const char *cache_name)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
+ /* Check for corruption, avoiding overflow. */
|
||||||
|
+ if ((cache_size - sizeof (struct cache_file)) / sizeof (struct file_entry)
|
||||||
|
+ < cache->nlibs)
|
||||||
|
+ error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
|
||||||
|
+
|
||||||
|
size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
|
||||||
|
+ (cache->nlibs
|
||||||
|
* sizeof (struct file_entry)));
|
||||||
|
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
|
||||||
|
index 6ee5153ff9514872..6dd99a35b9f97cfb 100644
|
||||||
|
--- a/elf/dl-cache.c
|
||||||
|
+++ b/elf/dl-cache.c
|
||||||
|
@@ -204,7 +204,10 @@ _dl_load_cache_lookup (const char *name)
|
||||||
|
- only the new format
|
||||||
|
The following checks if the cache contains any of these formats. */
|
||||||
|
if (file != MAP_FAILED && cachesize > sizeof *cache
|
||||||
|
- && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
|
||||||
|
+ && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
|
||||||
|
+ /* Check for corruption, avoiding overflow. */
|
||||||
|
+ && ((cachesize - sizeof *cache) / sizeof (struct file_entry)
|
||||||
|
+ >= ((struct cache_file *) file)->nlibs))
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
/* Looks ok. */
|
249
SOURCES/glibc-rh1817513-120.patch
Normal file
249
SOURCES/glibc-rh1817513-120.patch
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
commit f267e1c9dd7fb8852cc32d6eafd96bbcfd5cbb2b
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 4 09:13:43 2020 +0100
|
||||||
|
|
||||||
|
x86_64: Add glibc-hwcaps support
|
||||||
|
|
||||||
|
The subdirectories match those in the x86-64 psABI:
|
||||||
|
|
||||||
|
https://gitlab.com/x86-psABIs/x86-64-ABI/-/commit/77566eb03bc6a326811cb7e9a6b9396884b67c7c
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index f67b231c0f8e3aff..7f2fc73877f0a4c8 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -1751,7 +1751,7 @@ $(objpfx)argv0test.out: tst-rtld-argv0.sh $(objpfx)ld.so \
|
||||||
|
# glibc-hwcaps mechanism for this architecture). Used to obtain test
|
||||||
|
# coverage for some glibc-hwcaps tests for the widest possible range
|
||||||
|
# of systems.
|
||||||
|
-glibc-hwcaps-first-subdirs-for-tests =
|
||||||
|
+glibc-hwcaps-first-subdirs-for-tests = x86-64-v2
|
||||||
|
|
||||||
|
# The test modules are parameterized by preprocessor macros.
|
||||||
|
LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
index 6356d152089cdd9a..66d6942402b7233b 100644
|
||||||
|
--- a/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
+++ b/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
@@ -4,3 +4,13 @@
|
||||||
|
cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so
|
||||||
|
cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so
|
||||||
|
cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so
|
||||||
|
+
|
||||||
|
+mkdirp 0770 $L/glibc-hwcaps/x86-64-v2
|
||||||
|
+cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so
|
||||||
|
+mkdirp 0770 $L/glibc-hwcaps/x86-64-v3
|
||||||
|
+cp $B/elf/libmarkermod3-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod3.so
|
||||||
|
+cp $B/elf/libmarkermod3-3.so $L/glibc-hwcaps/x86-64-v3/libmarkermod3.so
|
||||||
|
+mkdirp 0770 $L/glibc-hwcaps/x86-64-v4
|
||||||
|
+cp $B/elf/libmarkermod4-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod4.so
|
||||||
|
+cp $B/elf/libmarkermod4-3.so $L/glibc-hwcaps/x86-64-v3/libmarkermod4.so
|
||||||
|
+cp $B/elf/libmarkermod4-4.so $L/glibc-hwcaps/x86-64-v4/libmarkermod4.so
|
||||||
|
diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile
|
||||||
|
index 42b97c5cc73892cc..d1d7cb9d2eeca9c5 100644
|
||||||
|
--- a/sysdeps/x86_64/Makefile
|
||||||
|
+++ b/sysdeps/x86_64/Makefile
|
||||||
|
@@ -144,8 +144,47 @@ CFLAGS-tst-auditmod10b.c += $(AVX512-CFLAGS)
|
||||||
|
CFLAGS-tst-avx512-aux.c += $(AVX512-CFLAGS)
|
||||||
|
CFLAGS-tst-avx512mod.c += $(AVX512-CFLAGS)
|
||||||
|
endif
|
||||||
|
+
|
||||||
|
+$(objpfx)tst-glibc-hwcaps: $(objpfx)libmarkermod2-1.so \
|
||||||
|
+ $(objpfx)libmarkermod3-1.so $(objpfx)libmarkermod4-1.so
|
||||||
|
+$(objpfx)tst-glibc-hwcaps.out: \
|
||||||
|
+ $(objpfx)libmarkermod2.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod2.so \
|
||||||
|
+ $(objpfx)libmarkermod3.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod3.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/x86-64-v3/libmarkermod3.so \
|
||||||
|
+ $(objpfx)libmarkermod4.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod4.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/x86-64-v3/libmarkermod4.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/x86-64-v4/libmarkermod4.so \
|
||||||
|
+
|
||||||
|
+$(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod2.so: $(objpfx)libmarkermod2-2.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod3.so: $(objpfx)libmarkermod3-2.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/x86-64-v3/libmarkermod3.so: $(objpfx)libmarkermod3-3.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod4.so: $(objpfx)libmarkermod4-2.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/x86-64-v3/libmarkermod4.so: $(objpfx)libmarkermod4-3.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/x86-64-v4/libmarkermod4.so: $(objpfx)libmarkermod4-4.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+
|
||||||
|
+ifeq (no,$(build-hardcoded-path-in-tests))
|
||||||
|
+# This is an ld.so.cache test, and RPATH/RUNPATH in the executable
|
||||||
|
+# interferes with its test objectives.
|
||||||
|
+tests-container += tst-glibc-hwcaps-cache
|
||||||
|
endif
|
||||||
|
|
||||||
|
+endif # $(subdir) == elf
|
||||||
|
+
|
||||||
|
ifeq ($(subdir),csu)
|
||||||
|
gen-as-const-headers += tlsdesc.sym rtld-offsets.sym
|
||||||
|
endif
|
||||||
|
diff --git a/sysdeps/x86_64/dl-hwcaps-subdirs.c b/sysdeps/x86_64/dl-hwcaps-subdirs.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..8810a822efe36962
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86_64/dl-hwcaps-subdirs.c
|
||||||
|
@@ -0,0 +1,66 @@
|
||||||
|
+/* Architecture-specific glibc-hwcaps subdirectories. x86 version.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <dl-hwcaps.h>
|
||||||
|
+#include <cpu-features.h>
|
||||||
|
+
|
||||||
|
+const char _dl_hwcaps_subdirs[] = "x86-64-v4:x86-64-v3:x86-64-v2";
|
||||||
|
+enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs. */
|
||||||
|
+
|
||||||
|
+uint32_t
|
||||||
|
+_dl_hwcaps_subdirs_active (void)
|
||||||
|
+{
|
||||||
|
+ int active = 0;
|
||||||
|
+
|
||||||
|
+ /* Test in reverse preference order. */
|
||||||
|
+
|
||||||
|
+ /* x86-64-v2. */
|
||||||
|
+ if (!(CPU_FEATURE_USABLE (CMPXCHG16B)
|
||||||
|
+ && CPU_FEATURE_USABLE (LAHF64_SAHF64)
|
||||||
|
+ && CPU_FEATURE_USABLE (POPCNT)
|
||||||
|
+ && CPU_FEATURE_USABLE (SSE3)
|
||||||
|
+ && CPU_FEATURE_USABLE (SSE4_1)
|
||||||
|
+ && CPU_FEATURE_USABLE (SSE4_2)
|
||||||
|
+ && CPU_FEATURE_USABLE (SSSE3)))
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+ ++active;
|
||||||
|
+
|
||||||
|
+ /* x86-64-v3. */
|
||||||
|
+ if (!(CPU_FEATURE_USABLE (AVX)
|
||||||
|
+ && CPU_FEATURE_USABLE (AVX2)
|
||||||
|
+ && CPU_FEATURE_USABLE (BMI1)
|
||||||
|
+ && CPU_FEATURE_USABLE (BMI2)
|
||||||
|
+ && CPU_FEATURE_USABLE (F16C)
|
||||||
|
+ && CPU_FEATURE_USABLE (FMA)
|
||||||
|
+ && CPU_FEATURE_USABLE (LZCNT)
|
||||||
|
+ && CPU_FEATURE_USABLE (MOVBE)
|
||||||
|
+ && CPU_FEATURE_USABLE (OSXSAVE)))
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+ ++active;
|
||||||
|
+
|
||||||
|
+ /* x86-64-v4. */
|
||||||
|
+ if (!(CPU_FEATURE_USABLE (AVX512F)
|
||||||
|
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||||
|
+ && CPU_FEATURE_USABLE (AVX512CD)
|
||||||
|
+ && CPU_FEATURE_USABLE (AVX512DQ)
|
||||||
|
+ && CPU_FEATURE_USABLE (AVX512VL)))
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+ ++active;
|
||||||
|
+
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+}
|
||||||
|
diff --git a/sysdeps/x86_64/tst-glibc-hwcaps.c b/sysdeps/x86_64/tst-glibc-hwcaps.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..3075a8286dc30768
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/x86_64/tst-glibc-hwcaps.c
|
||||||
|
@@ -0,0 +1,76 @@
|
||||||
|
+/* glibc-hwcaps subdirectory test. x86_64 version.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <sys/param.h>
|
||||||
|
+#include <sys/platform/x86.h>
|
||||||
|
+
|
||||||
|
+extern int marker2 (void);
|
||||||
|
+extern int marker3 (void);
|
||||||
|
+extern int marker4 (void);
|
||||||
|
+
|
||||||
|
+/* Return the x86-64-vN level, 1 for the baseline. */
|
||||||
|
+static int
|
||||||
|
+compute_level (void)
|
||||||
|
+{
|
||||||
|
+ const struct cpu_features *cpu_features
|
||||||
|
+ = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX);
|
||||||
|
+
|
||||||
|
+ if (!(CPU_FEATURE_USABLE_P (cpu_features, CMPXCHG16B)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, LAHF64_SAHF64)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, POPCNT)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, MMX)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, SSE)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, SSE2)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, SSE3)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, SSSE3)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, SSE4_2)))
|
||||||
|
+ return 1;
|
||||||
|
+ if (!(CPU_FEATURE_USABLE_P (cpu_features, AVX)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI1)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, F16C)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, FMA)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, MOVBE)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE)))
|
||||||
|
+ return 2;
|
||||||
|
+ if (!(CPU_FEATURE_USABLE_P (cpu_features, AVX512F)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX512CD)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX512DQ)
|
||||||
|
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)))
|
||||||
|
+ return 3;
|
||||||
|
+ return 4;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ int level = compute_level ();
|
||||||
|
+ printf ("info: detected x86-64 micro-architecture level: %d\n", level);
|
||||||
|
+ TEST_COMPARE (marker2 (), MIN (level, 2));
|
||||||
|
+ TEST_COMPARE (marker3 (), MIN (level, 3));
|
||||||
|
+ TEST_COMPARE (marker4 (), MIN (level, 4));
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
21
SOURCES/glibc-rh1817513-121.patch
Normal file
21
SOURCES/glibc-rh1817513-121.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
commit 4f4bd9e47ba98ccfeeaa8c600c0b0c8bbabcebb3
|
||||||
|
Author: Matheus Castanho <msc@linux.ibm.com>
|
||||||
|
Date: Fri Dec 4 09:48:56 2020 -0300
|
||||||
|
|
||||||
|
elf: Add missing <stddef.h> header to elf/dl-hwcaps.h
|
||||||
|
|
||||||
|
The lack of this header makes size_t unavailable on builds configured
|
||||||
|
with --disable-tunables, causing compilation errors.
|
||||||
|
|
||||||
|
diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h
|
||||||
|
index 769ecab3f886c6c4..9a34088c17e97d7f 100644
|
||||||
|
--- a/elf/dl-hwcaps.h
|
||||||
|
+++ b/elf/dl-hwcaps.h
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
#define _DL_HWCAPS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
|
||||||
|
#include <elf/dl-tunables.h>
|
||||||
|
|
20
SOURCES/glibc-rh1817513-122.patch
Normal file
20
SOURCES/glibc-rh1817513-122.patch
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
commit 2976082a385a7fb3d0294c6acf745b4f93e834ee
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Dec 3 15:02:44 2020 -0800
|
||||||
|
|
||||||
|
x86: Set RDRAND usable if CPU supports RDRAND
|
||||||
|
|
||||||
|
Set RDRAND usable if CPU supports RDRAND.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index 4c9c15a44b618fed..805d00a43309fc23 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -85,6 +85,7 @@ update_usable (struct cpu_features *cpu_features)
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, WAITPKG);
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, GFNI);
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, RDPID);
|
||||||
|
+ CPU_FEATURE_SET_USABLE (cpu_features, RDRAND);
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, CLDEMOTE);
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, MOVDIRI);
|
||||||
|
CPU_FEATURE_SET_USABLE (cpu_features, MOVDIR64B);
|
65
SOURCES/glibc-rh1817513-123.patch
Normal file
65
SOURCES/glibc-rh1817513-123.patch
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
commit 93fda28693f0d9060b0aa71eeacaacfe9f16896e
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Dec 3 15:02:44 2020 -0800
|
||||||
|
|
||||||
|
x86: Adjust tst-cpu-features-supports.c for GCC 11
|
||||||
|
|
||||||
|
Check HAS_CPU_FEATURE instead of CPU_FEATURE_USABLE for FSGSBASE, IBT,
|
||||||
|
LM, SHSTK and XSAVES since FSGSBASE requires kernel support, IBT/SHSTK/LM
|
||||||
|
require OS support and XSAVES is supervisor-mode only.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c
|
||||||
|
index bf881b531f4bc2ed..287cf01fbdfaeda1 100644
|
||||||
|
--- a/sysdeps/x86/tst-cpu-features-supports.c
|
||||||
|
+++ b/sysdeps/x86/tst-cpu-features-supports.c
|
||||||
|
@@ -40,6 +40,11 @@ check_supports (int supports, int usable, const char *supports_name,
|
||||||
|
#define CHECK_SUPPORTS(str, name) \
|
||||||
|
check_supports (__builtin_cpu_supports (#str), \
|
||||||
|
CPU_FEATURE_USABLE (name), \
|
||||||
|
+ #str, "CPU_FEATURE_USABLE (" #name ")");
|
||||||
|
+
|
||||||
|
+#define CHECK_CPU_SUPPORTS(str, name) \
|
||||||
|
+ check_supports (__builtin_cpu_supports (#str), \
|
||||||
|
+ HAS_CPU_FEATURE (name), \
|
||||||
|
#str, "HAS_CPU_FEATURE (" #name ")");
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -118,7 +123,7 @@ do_test (int argc, char **argv)
|
||||||
|
fails += CHECK_SUPPORTS (fma4, FMA4);
|
||||||
|
#endif
|
||||||
|
#if __GNUC_PREREQ (11, 0)
|
||||||
|
- fails += CHECK_SUPPORTS (fsgsbase, FSGSBASE);
|
||||||
|
+ fails += CHECK_CPU_SUPPORTS (fsgsbase, FSGSBASE);
|
||||||
|
fails += CHECK_SUPPORTS (fxsave, FXSR);
|
||||||
|
#endif
|
||||||
|
#if __GNUC_PREREQ (8, 0)
|
||||||
|
@@ -126,9 +131,9 @@ do_test (int argc, char **argv)
|
||||||
|
#endif
|
||||||
|
#if __GNUC_PREREQ (11, 0)
|
||||||
|
fails += CHECK_SUPPORTS (hle, HLE);
|
||||||
|
- fails += CHECK_SUPPORTS (ibt, IBT);
|
||||||
|
+ fails += CHECK_CPU_SUPPORTS (ibt, IBT);
|
||||||
|
fails += CHECK_SUPPORTS (lahf_lm, LAHF64_SAHF64);
|
||||||
|
- fails += CHECK_SUPPORTS (lm, LM);
|
||||||
|
+ fails += CHECK_CPU_SUPPORTS (lm, LM);
|
||||||
|
fails += CHECK_SUPPORTS (lwp, LWP);
|
||||||
|
fails += CHECK_SUPPORTS (lzcnt, LZCNT);
|
||||||
|
#endif
|
||||||
|
@@ -150,7 +155,7 @@ do_test (int argc, char **argv)
|
||||||
|
fails += CHECK_SUPPORTS (rtm, RTM);
|
||||||
|
fails += CHECK_SUPPORTS (serialize, SERIALIZE);
|
||||||
|
fails += CHECK_SUPPORTS (sha, SHA);
|
||||||
|
- fails += CHECK_SUPPORTS (shstk, SHSTK);
|
||||||
|
+ fails += CHECK_CPU_SUPPORTS (shstk, SHSTK);
|
||||||
|
#endif
|
||||||
|
fails += CHECK_SUPPORTS (sse, SSE);
|
||||||
|
fails += CHECK_SUPPORTS (sse2, SSE2);
|
||||||
|
@@ -180,7 +185,7 @@ do_test (int argc, char **argv)
|
||||||
|
fails += CHECK_SUPPORTS (xsave, XSAVE);
|
||||||
|
fails += CHECK_SUPPORTS (xsavec, XSAVEC);
|
||||||
|
fails += CHECK_SUPPORTS (xsaveopt, XSAVEOPT);
|
||||||
|
- fails += CHECK_SUPPORTS (xsaves, XSAVES);
|
||||||
|
+ fails += CHECK_CPU_SUPPORTS (xsaves, XSAVES);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf ("%d differences between __builtin_cpu_supports and glibc code.\n",
|
187
SOURCES/glibc-rh1817513-124.patch
Normal file
187
SOURCES/glibc-rh1817513-124.patch
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
commit 4c38c1a229bc3628269ad98bd7e8d31d118d91f6
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Dec 4 09:13:43 2020 +0100
|
||||||
|
|
||||||
|
powerpc64le: Add glibc-hwcaps support
|
||||||
|
|
||||||
|
The "power10" and "power9" subdirectories are selected in a way
|
||||||
|
that matches the -mcpu=power10 and -mcpu=power9 options of GCC.
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 7f2fc73877f0a4c8..57e3a8982297f79a 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -1751,7 +1751,7 @@ $(objpfx)argv0test.out: tst-rtld-argv0.sh $(objpfx)ld.so \
|
||||||
|
# glibc-hwcaps mechanism for this architecture). Used to obtain test
|
||||||
|
# coverage for some glibc-hwcaps tests for the widest possible range
|
||||||
|
# of systems.
|
||||||
|
-glibc-hwcaps-first-subdirs-for-tests = x86-64-v2
|
||||||
|
+glibc-hwcaps-first-subdirs-for-tests = power9 x86-64-v2
|
||||||
|
|
||||||
|
# The test modules are parameterized by preprocessor macros.
|
||||||
|
LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
index 66d6942402b7233b..6a4675f9bd30e02f 100644
|
||||||
|
--- a/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
+++ b/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
@@ -5,6 +5,12 @@ cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so
|
||||||
|
cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so
|
||||||
|
cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so
|
||||||
|
|
||||||
|
+mkdirp 0770 $L/glibc-hwcaps/power9
|
||||||
|
+cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/power9/libmarkermod2.so
|
||||||
|
+mkdirp 0770 $L/glibc-hwcaps/power10
|
||||||
|
+cp $B/elf/libmarkermod3-2.so $L/glibc-hwcaps/power9/libmarkermod3.so
|
||||||
|
+cp $B/elf/libmarkermod3-3.so $L/glibc-hwcaps/power10/libmarkermod3.so
|
||||||
|
+
|
||||||
|
mkdirp 0770 $L/glibc-hwcaps/x86-64-v2
|
||||||
|
cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so
|
||||||
|
mkdirp 0770 $L/glibc-hwcaps/x86-64-v3
|
||||||
|
diff --git a/sysdeps/powerpc/powerpc64/le/Makefile b/sysdeps/powerpc/powerpc64/le/Makefile
|
||||||
|
index f59db1ca3c8ed454..7a4be6bfef729914 100644
|
||||||
|
--- a/sysdeps/powerpc/powerpc64/le/Makefile
|
||||||
|
+++ b/sysdeps/powerpc/powerpc64/le/Makefile
|
||||||
|
@@ -82,3 +82,31 @@ CFLAGS-printf_fp.c = -mfloat128
|
||||||
|
CFLAGS-printf_fphex.c = -mfloat128
|
||||||
|
CFLAGS-printf_size.c = -mfloat128
|
||||||
|
endif
|
||||||
|
+
|
||||||
|
+ifeq ($(subdir),elf)
|
||||||
|
+$(objpfx)tst-glibc-hwcaps: \
|
||||||
|
+ $(objpfx)libmarkermod2-1.so $(objpfx)libmarkermod3-1.so
|
||||||
|
+$(objpfx)tst-glibc-hwcaps.out: \
|
||||||
|
+ $(objpfx)libmarkermod2.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/power9/libmarkermod2.so \
|
||||||
|
+ $(objpfx)libmarkermod3.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/power9/libmarkermod3.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/power10/libmarkermod3.so \
|
||||||
|
+
|
||||||
|
+$(objpfx)glibc-hwcaps/power9/libmarkermod2.so: $(objpfx)libmarkermod2-2.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/power9/libmarkermod3.so: $(objpfx)libmarkermod3-2.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/power10/libmarkermod3.so: $(objpfx)libmarkermod3-3.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+
|
||||||
|
+ifeq (no,$(build-hardcoded-path-in-tests))
|
||||||
|
+# This is an ld.so.cache test, and RPATH/RUNPATH in the executable
|
||||||
|
+# interferes with its test objectives.
|
||||||
|
+tests-container += tst-glibc-hwcaps-cache
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
+endif # $(subdir) == elf
|
||||||
|
diff --git a/sysdeps/powerpc/powerpc64/le/dl-hwcaps-subdirs.c b/sysdeps/powerpc/powerpc64/le/dl-hwcaps-subdirs.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..6a21d77649f44dd4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/powerpc/powerpc64/le/dl-hwcaps-subdirs.c
|
||||||
|
@@ -0,0 +1,46 @@
|
||||||
|
+/* Architecture-specific glibc-hwcaps subdirectories. powerpc64le version.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <dl-hwcaps.h>
|
||||||
|
+#include <ldsodefs.h>
|
||||||
|
+
|
||||||
|
+const char _dl_hwcaps_subdirs[] = "power10:power9";
|
||||||
|
+enum { subdirs_count = 2 }; /* Number of components in _dl_hwcaps_subdirs. */
|
||||||
|
+
|
||||||
|
+uint32_t
|
||||||
|
+_dl_hwcaps_subdirs_active (void)
|
||||||
|
+{
|
||||||
|
+ int active = 0;
|
||||||
|
+
|
||||||
|
+ /* Test in reverse preference order. Altivec and VSX are implied by
|
||||||
|
+ the powerpc64le ABI definition. */
|
||||||
|
+
|
||||||
|
+ /* POWER9. GCC enables float128 hardware support for -mcpu=power9. */
|
||||||
|
+ if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_00) == 0
|
||||||
|
+ || (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_IEEE128) == 0)
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+ ++active;
|
||||||
|
+
|
||||||
|
+ /* POWER10. GCC defines __MMA__ for -mcpu=power10. */
|
||||||
|
+ if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_1) == 0
|
||||||
|
+ || (GLRO (dl_hwcap2) & PPC_FEATURE2_MMA) == 0)
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+ ++active;
|
||||||
|
+
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+}
|
||||||
|
diff --git a/sysdeps/powerpc/powerpc64/le/tst-glibc-hwcaps.c b/sysdeps/powerpc/powerpc64/le/tst-glibc-hwcaps.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..e510fca80a22aaeb
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/powerpc/powerpc64/le/tst-glibc-hwcaps.c
|
||||||
|
@@ -0,0 +1,54 @@
|
||||||
|
+/* glibc-hwcaps subdirectory test. powerpc64le version.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <sys/auxv.h>
|
||||||
|
+#include <sys/param.h>
|
||||||
|
+
|
||||||
|
+extern int marker2 (void);
|
||||||
|
+extern int marker3 (void);
|
||||||
|
+
|
||||||
|
+/* Return the POWER level, 8 for the baseline. */
|
||||||
|
+static int
|
||||||
|
+compute_level (void)
|
||||||
|
+{
|
||||||
|
+ const char *platform = (const char *) getauxval (AT_PLATFORM);
|
||||||
|
+ if (strcmp (platform, "power8") == 0)
|
||||||
|
+ return 8;
|
||||||
|
+ if (strcmp (platform, "power9") == 0)
|
||||||
|
+ return 9;
|
||||||
|
+ if (strcmp (platform, "power10") == 0)
|
||||||
|
+ return 10;
|
||||||
|
+ printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform);
|
||||||
|
+ /* Assume that the new platform supports POWER10. */
|
||||||
|
+ return 10;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ int level = compute_level ();
|
||||||
|
+ printf ("info: detected POWER level: %d\n", level);
|
||||||
|
+ TEST_COMPARE (marker2 (), MIN (level - 7, 2));
|
||||||
|
+ TEST_COMPARE (marker3 (), MIN (level - 7, 3));
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
21
SOURCES/glibc-rh1817513-125.patch
Normal file
21
SOURCES/glibc-rh1817513-125.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
commit 0d4ed9d40efa84e8dc88e64cf337c8e95af7b045
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Dec 9 18:56:14 2020 +0100
|
||||||
|
|
||||||
|
elf: Fix incorrect comparison in sort_priorities_by_name
|
||||||
|
|
||||||
|
Reported-By: Stefan Liebler <stli@linux.ibm.com>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
||||||
|
index 098173a84c43c1fd..50d764ae8707f46d 100644
|
||||||
|
--- a/elf/dl-hwcaps.c
|
||||||
|
+++ b/elf/dl-hwcaps.c
|
||||||
|
@@ -153,7 +153,7 @@ sort_priorities_by_name (void)
|
||||||
|
else
|
||||||
|
to_compare = previous->name_length;
|
||||||
|
int cmp = memcmp (current->name, previous->name, to_compare);
|
||||||
|
- if (cmp >= 0
|
||||||
|
+ if (cmp > 0
|
||||||
|
|| (cmp == 0 && current->name_length >= previous->name_length))
|
||||||
|
break;
|
||||||
|
|
25
SOURCES/glibc-rh1817513-126.patch
Normal file
25
SOURCES/glibc-rh1817513-126.patch
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
commit 1bb8d05b9c751f6909e85ee96f6c78d536987bfd
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Dec 10 12:24:53 2020 +0100
|
||||||
|
|
||||||
|
elf: Fix run-time dependencies of tst-dlopen-fail-2
|
||||||
|
|
||||||
|
The misattributed dependencies can cause failures in parallel testing
|
||||||
|
if the dependencies have not been built yet.
|
||||||
|
|
||||||
|
Fixes commit a332bd1518af518c984fad73eba6f46dc5b2b2d4
|
||||||
|
("elf: Add elf/tst-dlopenfail-2 [BZ #25396]").
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 57e3a8982297f79a..63c61ad63677ec63 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -1655,7 +1655,7 @@ $(objpfx)tst-dlopenfailmod1.so: \
|
||||||
|
LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so
|
||||||
|
$(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library)
|
||||||
|
$(objpfx)tst-dlopenfail-2: $(libdl)
|
||||||
|
-$(objpfx)tst-dlopenfail.out: \
|
||||||
|
+$(objpfx)tst-dlopenfail-2.out: \
|
||||||
|
$(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so \
|
||||||
|
$(objpfx)tst-dlopenfailmod3.so
|
||||||
|
|
241
SOURCES/glibc-rh1817513-127.patch
Normal file
241
SOURCES/glibc-rh1817513-127.patch
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
commit fdf8fbca455ca3ef57235bde907bcc6a624ac5aa
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Dec 10 13:51:18 2020 +0100
|
||||||
|
|
||||||
|
s390x: Add glibc-hwcaps support
|
||||||
|
|
||||||
|
Subdirectories z13, z14, z15 can be selected, mostly based on the
|
||||||
|
level of support for vector instructions.
|
||||||
|
|
||||||
|
Co-Authored-By: Stefan Liebler <stli@linux.ibm.com>
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 63c61ad63677ec63..67029930dd2cb461 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -1751,7 +1751,7 @@ $(objpfx)argv0test.out: tst-rtld-argv0.sh $(objpfx)ld.so \
|
||||||
|
# glibc-hwcaps mechanism for this architecture). Used to obtain test
|
||||||
|
# coverage for some glibc-hwcaps tests for the widest possible range
|
||||||
|
# of systems.
|
||||||
|
-glibc-hwcaps-first-subdirs-for-tests = power9 x86-64-v2
|
||||||
|
+glibc-hwcaps-first-subdirs-for-tests = power9 x86-64-v2 z13
|
||||||
|
|
||||||
|
# The test modules are parameterized by preprocessor macros.
|
||||||
|
LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so
|
||||||
|
diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
index 6a4675f9bd30e02f..c3271f61f9e50f2e 100644
|
||||||
|
--- a/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
+++ b/elf/tst-glibc-hwcaps-cache.script
|
||||||
|
@@ -11,6 +11,16 @@ mkdirp 0770 $L/glibc-hwcaps/power10
|
||||||
|
cp $B/elf/libmarkermod3-2.so $L/glibc-hwcaps/power9/libmarkermod3.so
|
||||||
|
cp $B/elf/libmarkermod3-3.so $L/glibc-hwcaps/power10/libmarkermod3.so
|
||||||
|
|
||||||
|
+mkdirp 0770 $L/glibc-hwcaps/z13
|
||||||
|
+cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/z13/libmarkermod2.so
|
||||||
|
+mkdirp 0770 $L/glibc-hwcaps/z14
|
||||||
|
+cp $B/elf/libmarkermod3-2.so $L/glibc-hwcaps/z13/libmarkermod3.so
|
||||||
|
+cp $B/elf/libmarkermod3-3.so $L/glibc-hwcaps/z14/libmarkermod3.so
|
||||||
|
+mkdirp 0770 $L/glibc-hwcaps/z15
|
||||||
|
+cp $B/elf/libmarkermod4-2.so $L/glibc-hwcaps/z13/libmarkermod4.so
|
||||||
|
+cp $B/elf/libmarkermod4-3.so $L/glibc-hwcaps/z14/libmarkermod4.so
|
||||||
|
+cp $B/elf/libmarkermod4-4.so $L/glibc-hwcaps/z15/libmarkermod4.so
|
||||||
|
+
|
||||||
|
mkdirp 0770 $L/glibc-hwcaps/x86-64-v2
|
||||||
|
cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so
|
||||||
|
mkdirp 0770 $L/glibc-hwcaps/x86-64-v3
|
||||||
|
diff --git a/sysdeps/s390/s390-64/Makefile b/sysdeps/s390/s390-64/Makefile
|
||||||
|
index b4d793bb3dd1f703..e5da26871c862e63 100644
|
||||||
|
--- a/sysdeps/s390/s390-64/Makefile
|
||||||
|
+++ b/sysdeps/s390/s390-64/Makefile
|
||||||
|
@@ -6,4 +6,43 @@ ifeq ($(subdir),elf)
|
||||||
|
CFLAGS-rtld.c += -Wno-uninitialized -Wno-unused
|
||||||
|
CFLAGS-dl-load.c += -Wno-unused
|
||||||
|
CFLAGS-dl-reloc.c += -Wno-unused
|
||||||
|
+
|
||||||
|
+$(objpfx)tst-glibc-hwcaps: $(objpfx)libmarkermod2-1.so \
|
||||||
|
+ $(objpfx)libmarkermod3-1.so $(objpfx)libmarkermod4-1.so
|
||||||
|
+$(objpfx)tst-glibc-hwcaps.out: \
|
||||||
|
+ $(objpfx)libmarkermod2.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/z13/libmarkermod2.so \
|
||||||
|
+ $(objpfx)libmarkermod3.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/z13/libmarkermod3.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/z14/libmarkermod3.so \
|
||||||
|
+ $(objpfx)libmarkermod4.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/z13/libmarkermod4.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/z14/libmarkermod4.so \
|
||||||
|
+ $(objpfx)glibc-hwcaps/z15/libmarkermod4.so \
|
||||||
|
+
|
||||||
|
+$(objpfx)glibc-hwcaps/z13/libmarkermod2.so: $(objpfx)libmarkermod2-2.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/z13/libmarkermod3.so: $(objpfx)libmarkermod3-2.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/z14/libmarkermod3.so: $(objpfx)libmarkermod3-3.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/z13/libmarkermod4.so: $(objpfx)libmarkermod4-2.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/z14/libmarkermod4.so: $(objpfx)libmarkermod4-3.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+$(objpfx)glibc-hwcaps/z15/libmarkermod4.so: $(objpfx)libmarkermod4-4.so
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ cp $< $@
|
||||||
|
+
|
||||||
|
+ifeq (no,$(build-hardcoded-path-in-tests))
|
||||||
|
+# This is an ld.so.cache test, and RPATH/RUNPATH in the executable
|
||||||
|
+# interferes with its test objectives.
|
||||||
|
+tests-container += tst-glibc-hwcaps-cache
|
||||||
|
endif
|
||||||
|
+
|
||||||
|
+endif # $(subdir) == elf
|
||||||
|
diff --git a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..3673808a458350ad
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c
|
||||||
|
@@ -0,0 +1,54 @@
|
||||||
|
+/* Architecture-specific glibc-hwcaps subdirectories. s390x version.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <dl-hwcaps.h>
|
||||||
|
+#include <ldsodefs.h>
|
||||||
|
+
|
||||||
|
+const char _dl_hwcaps_subdirs[] = "z15:z14:z13";
|
||||||
|
+enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs. */
|
||||||
|
+
|
||||||
|
+uint32_t
|
||||||
|
+_dl_hwcaps_subdirs_active (void)
|
||||||
|
+{
|
||||||
|
+ int active = 0;
|
||||||
|
+
|
||||||
|
+ /* Test in reverse preference order. */
|
||||||
|
+
|
||||||
|
+ /* z13. */
|
||||||
|
+ if (!(GLRO (dl_hwcap) & HWCAP_S390_VX))
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+ ++active;
|
||||||
|
+
|
||||||
|
+ /* z14. */
|
||||||
|
+ if (!((GLRO (dl_hwcap) & HWCAP_S390_VXD)
|
||||||
|
+ && (GLRO (dl_hwcap) & HWCAP_S390_VXE)
|
||||||
|
+ && (GLRO (dl_hwcap) & HWCAP_S390_GS)))
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+ ++active;
|
||||||
|
+
|
||||||
|
+ /* z15.
|
||||||
|
+ Note: We do not list HWCAP_S390_SORT and HWCAP_S390_DFLT here as,
|
||||||
|
+ according to the Principles of Operation, those may be replaced or removed
|
||||||
|
+ in future. */
|
||||||
|
+ if (!((GLRO (dl_hwcap) & HWCAP_S390_VXRS_EXT2)
|
||||||
|
+ && (GLRO (dl_hwcap) & HWCAP_S390_VXRS_PDE)))
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+ ++active;
|
||||||
|
+
|
||||||
|
+ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active);
|
||||||
|
+}
|
||||||
|
diff --git a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..690f0d5fab36eb59
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c
|
||||||
|
@@ -0,0 +1,82 @@
|
||||||
|
+/* glibc-hwcaps subdirectory test. s390x version.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <sys/auxv.h>
|
||||||
|
+#include <sys/param.h>
|
||||||
|
+
|
||||||
|
+extern int marker2 (void);
|
||||||
|
+extern int marker3 (void);
|
||||||
|
+extern int marker4 (void);
|
||||||
|
+
|
||||||
|
+/* Return the arch level, 10 for the baseline libmarkermod*.so's. */
|
||||||
|
+static int
|
||||||
|
+compute_level (void)
|
||||||
|
+{
|
||||||
|
+ const char *platform = (const char *) getauxval (AT_PLATFORM);
|
||||||
|
+
|
||||||
|
+ /* The arch* versions refer to the edition of the Principles of
|
||||||
|
+ Operation, and they are off by two when compared with the recent
|
||||||
|
+ product names. (The code below should not be considered an
|
||||||
|
+ accurate mapping to Principles of Operation editions for earlier
|
||||||
|
+ AT_PLATFORM strings). */
|
||||||
|
+ if (strcmp (platform, "z900") == 0)
|
||||||
|
+ return 10;
|
||||||
|
+ if (strcmp (platform, "z990") == 0)
|
||||||
|
+ return 10;
|
||||||
|
+ if (strcmp (platform, "z9-109") == 0)
|
||||||
|
+ return 10;
|
||||||
|
+ if (strcmp (platform, "z10") == 0)
|
||||||
|
+ return 10;
|
||||||
|
+ if (strcmp (platform, "z196") == 0)
|
||||||
|
+ return 10;
|
||||||
|
+ if (strcmp (platform, "zEC12") == 0)
|
||||||
|
+ return 10;
|
||||||
|
+
|
||||||
|
+ /* If we are running on z13 or newer and the kernel was booted with novx,
|
||||||
|
+ then AT_PLATFORM is z13 or newer, but _dl_hwcaps_subdirs_active will
|
||||||
|
+ return zero and the _dl_hwcaps_subdirs are not searched. */
|
||||||
|
+ const unsigned long int hwcap = getauxval (AT_HWCAP);
|
||||||
|
+ if ((hwcap & HWCAP_S390_VX) == 0)
|
||||||
|
+ return 10;
|
||||||
|
+
|
||||||
|
+ if (strcmp (platform, "z13") == 0)
|
||||||
|
+ return 11;
|
||||||
|
+ if (strcmp (platform, "z14") == 0)
|
||||||
|
+ return 12;
|
||||||
|
+ if (strcmp (platform, "z15") == 0)
|
||||||
|
+ return 13;
|
||||||
|
+ printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform);
|
||||||
|
+ /* Assume that the new platform supports z15. */
|
||||||
|
+ return 13;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ int level = compute_level ();
|
||||||
|
+ printf ("info: detected architecture level: arch%d\n", level);
|
||||||
|
+ TEST_COMPARE (marker2 (), MIN (level - 9, 2));
|
||||||
|
+ TEST_COMPARE (marker3 (), MIN (level - 9, 3));
|
||||||
|
+ TEST_COMPARE (marker4 (), MIN (level - 9, 4));
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
83
SOURCES/glibc-rh1817513-128.patch
Normal file
83
SOURCES/glibc-rh1817513-128.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
commit 97476447edff96e526daa1a22d6ed3665181ff93
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Wed Oct 23 17:52:26 2019 -0400
|
||||||
|
|
||||||
|
Install charmaps uncompressed in testroot
|
||||||
|
|
||||||
|
The testroot does not have a gunzip command, so the charmap files
|
||||||
|
should not be installed gzipped else they cannot be used (and thus
|
||||||
|
tested). With this patch, installing with INSTALL_UNCOMPRESSED=yes
|
||||||
|
installs uncompressed charmaps instead.
|
||||||
|
|
||||||
|
Note that we must purge the $(symbolic_link_list) as it contains
|
||||||
|
references to $(DESTDIR), which we change during the testroot
|
||||||
|
installation.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 3748d6f7cfb6223b..6d73241bbc811c13 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -398,8 +398,15 @@ ifeq ($(run-built-tests),yes)
|
||||||
|
$(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\
|
||||||
|
done
|
||||||
|
endif
|
||||||
|
+ # $(symbolic-link-list) is a file that encodes $(DESTDIR) so we
|
||||||
|
+ # have to purge it
|
||||||
|
+ rm -f $(symbolic-link-list)
|
||||||
|
+ # Setting INSTALL_UNCOMPRESSED causes localedata/Makefile to
|
||||||
|
+ # install the charmaps uncompressed, as the testroot does not
|
||||||
|
+ # provide a gunzip program.
|
||||||
|
$(MAKE) install DESTDIR=$(objpfx)testroot.pristine \
|
||||||
|
- subdirs='$(sorted-subdirs)'
|
||||||
|
+ INSTALL_UNCOMPRESSED=yes subdirs='$(sorted-subdirs)'
|
||||||
|
+ rm -f $(symbolic-link-list)
|
||||||
|
touch $(objpfx)testroot.pristine/install.stamp
|
||||||
|
|
||||||
|
tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special))
|
||||||
|
diff --git a/localedata/Makefile b/localedata/Makefile
|
||||||
|
index 0fed95dcae6a9183..14fcc37fed21e740 100644
|
||||||
|
--- a/localedata/Makefile
|
||||||
|
+++ b/localedata/Makefile
|
||||||
|
@@ -167,9 +167,17 @@ endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Files to install.
|
||||||
|
+ifeq ($(INSTALL_UNCOMPRESSED),yes)
|
||||||
|
+# This option is for testing inside the testroot container, as the
|
||||||
|
+# container does not include a working gunzip program.
|
||||||
|
+install-others := $(addprefix $(inst_i18ndir)/, \
|
||||||
|
+ $(charmaps) \
|
||||||
|
+ $(locales))
|
||||||
|
+else
|
||||||
|
install-others := $(addprefix $(inst_i18ndir)/, \
|
||||||
|
$(addsuffix .gz, $(charmaps)) \
|
||||||
|
$(locales))
|
||||||
|
+endif
|
||||||
|
|
||||||
|
tests: $(objdir)/iconvdata/gconv-modules
|
||||||
|
|
||||||
|
@@ -282,12 +290,22 @@ endif
|
||||||
|
|
||||||
|
include ../Rules
|
||||||
|
|
||||||
|
+ifeq ($(INSTALL_UNCOMPRESSED),yes)
|
||||||
|
+# Install the charmap files as-is. This option is for testing inside
|
||||||
|
+# the testroot container, as the container does not include a working
|
||||||
|
+# gunzip program.
|
||||||
|
+$(inst_i18ndir)/charmaps/%: charmaps/% $(+force)
|
||||||
|
+ $(make-target-directory)
|
||||||
|
+ rm -f $@
|
||||||
|
+ $(INSTALL_DATA) $< $@
|
||||||
|
+else
|
||||||
|
# Install the charmap files in gzipped format.
|
||||||
|
$(inst_i18ndir)/charmaps/%.gz: charmaps/% $(+force)
|
||||||
|
$(make-target-directory)
|
||||||
|
rm -f $(@:.gz=) $@
|
||||||
|
$(INSTALL_DATA) $< $(@:.gz=)
|
||||||
|
gzip -9n $(@:.gz=)
|
||||||
|
+endif
|
||||||
|
|
||||||
|
# Install the locale source files in the appropriate directory.
|
||||||
|
$(inst_i18ndir)/locales/%: locales/% $(+force); $(do-install)
|
121
SOURCES/glibc-rh1817513-129.patch
Normal file
121
SOURCES/glibc-rh1817513-129.patch
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
commit de42613540de8d3d70b5f14a14923cab7bd694d0
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon May 25 18:17:27 2020 +0200
|
||||||
|
|
||||||
|
elf: Turn _dl_printf, _dl_error_printf, _dl_fatal_printf into functions
|
||||||
|
|
||||||
|
This change makes it easier to set a breakpoint on these calls.
|
||||||
|
|
||||||
|
This also addresses the issue that including <ldsodefs.h> without
|
||||||
|
<unistd.h> does not result usable _dl_*printf macros because of the
|
||||||
|
use of the STD*_FILENO macros there.
|
||||||
|
|
||||||
|
(The private symbol for _dl_fatal_printf will go away again
|
||||||
|
once the exception handling implementation is unified between
|
||||||
|
libc and ld.so.)
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/Versions b/elf/Versions
|
||||||
|
index 3be879c4adfa74c7..be88c48e6d45a937 100644
|
||||||
|
--- a/elf/Versions
|
||||||
|
+++ b/elf/Versions
|
||||||
|
@@ -58,7 +58,7 @@ ld {
|
||||||
|
_dl_allocate_tls; _dl_allocate_tls_init;
|
||||||
|
_dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info;
|
||||||
|
_dl_deallocate_tls; _dl_make_stack_executable;
|
||||||
|
- _dl_rtld_di_serinfo; _dl_starting_up;
|
||||||
|
+ _dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf;
|
||||||
|
_rtld_global; _rtld_global_ro;
|
||||||
|
|
||||||
|
# Only here for gdb while a better method is developed.
|
||||||
|
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
|
||||||
|
index 3f28de3ee9d68368..508630e444d2a00c 100644
|
||||||
|
--- a/elf/dl-misc.c
|
||||||
|
+++ b/elf/dl-misc.c
|
||||||
|
@@ -302,6 +302,37 @@ _dl_dprintf (int fd, const char *fmt, ...)
|
||||||
|
va_end (arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+_dl_printf (const char *fmt, ...)
|
||||||
|
+{
|
||||||
|
+ va_list arg;
|
||||||
|
+
|
||||||
|
+ va_start (arg, fmt);
|
||||||
|
+ _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg);
|
||||||
|
+ va_end (arg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+_dl_error_printf (const char *fmt, ...)
|
||||||
|
+{
|
||||||
|
+ va_list arg;
|
||||||
|
+
|
||||||
|
+ va_start (arg, fmt);
|
||||||
|
+ _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
|
||||||
|
+ va_end (arg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+_dl_fatal_printf (const char *fmt, ...)
|
||||||
|
+{
|
||||||
|
+ va_list arg;
|
||||||
|
+
|
||||||
|
+ va_start (arg, fmt);
|
||||||
|
+ _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
|
||||||
|
+ va_end (arg);
|
||||||
|
+ _exit (127);
|
||||||
|
+}
|
||||||
|
+rtld_hidden_def (_dl_fatal_printf)
|
||||||
|
|
||||||
|
/* Test whether given NAME matches any of the names of the given object. */
|
||||||
|
int
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index 77923499d3de4366..6cbbaa808a596f77 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -762,24 +762,19 @@ ssize_t _dl_write (int fd, const void *buffer, size_t length)
|
||||||
|
|
||||||
|
/* Write a message on the specified descriptor standard output. The
|
||||||
|
parameters are interpreted as for a `printf' call. */
|
||||||
|
-#define _dl_printf(fmt, args...) \
|
||||||
|
- _dl_dprintf (STDOUT_FILENO, fmt, ##args)
|
||||||
|
+void _dl_printf (const char *fmt, ...)
|
||||||
|
+ attribute_hidden __attribute__ ((__format__ (__printf__, 1, 2)));
|
||||||
|
|
||||||
|
/* Write a message on the specified descriptor standard error. The
|
||||||
|
parameters are interpreted as for a `printf' call. */
|
||||||
|
-#define _dl_error_printf(fmt, args...) \
|
||||||
|
- _dl_dprintf (STDERR_FILENO, fmt, ##args)
|
||||||
|
+void _dl_error_printf (const char *fmt, ...)
|
||||||
|
+ attribute_hidden __attribute__ ((__format__ (__printf__, 1, 2)));
|
||||||
|
|
||||||
|
/* Write a message on the specified descriptor standard error and exit
|
||||||
|
the program. The parameters are interpreted as for a `printf' call. */
|
||||||
|
-#define _dl_fatal_printf(fmt, args...) \
|
||||||
|
- do \
|
||||||
|
- { \
|
||||||
|
- _dl_dprintf (STDERR_FILENO, fmt, ##args); \
|
||||||
|
- _exit (127); \
|
||||||
|
- } \
|
||||||
|
- while (1)
|
||||||
|
-
|
||||||
|
+void _dl_fatal_printf (const char *fmt, ...)
|
||||||
|
+ __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__));
|
||||||
|
+rtld_hidden_proto (_dl_fatal_printf)
|
||||||
|
|
||||||
|
/* An exception raised by the _dl_signal_error function family and
|
||||||
|
caught by _dl_catch_error function family. Exceptions themselves
|
||||||
|
diff --git a/sysdeps/mach/hurd/i386/localplt.data b/sysdeps/mach/hurd/i386/localplt.data
|
||||||
|
index 4b9dbf5acc088cff..eb79216e3b494486 100644
|
||||||
|
--- a/sysdeps/mach/hurd/i386/localplt.data
|
||||||
|
+++ b/sysdeps/mach/hurd/i386/localplt.data
|
||||||
|
@@ -43,6 +43,7 @@ ld.so: _dl_allocate_tls_init
|
||||||
|
ld.so: _dl_exception_create
|
||||||
|
ld.so: _dl_exception_create_format
|
||||||
|
ld.so: _dl_exception_free
|
||||||
|
+ld.so: _dl_fatal_printf
|
||||||
|
ld.so: _dl_find_dso_for_object
|
||||||
|
ld.so: _dl_init_first
|
||||||
|
ld.so: _dl_mcount
|
199
SOURCES/glibc-rh1817513-13.patch
Normal file
199
SOURCES/glibc-rh1817513-13.patch
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
commit a5275ba5378c9256d18e582572b4315e8edfcbfb
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Nov 29 14:15:01 2018 -0800
|
||||||
|
|
||||||
|
_dl_exception_create_format: Support %x/%lx/%zx
|
||||||
|
|
||||||
|
Add support for %x, %lx and %zx to _dl_exception_create_format and pad
|
||||||
|
to the full width with 0.
|
||||||
|
|
||||||
|
* elf/Makefile (tests-internal): Add tst-create_format1.
|
||||||
|
* elf/dl-exception.c (_dl_exception_create_format): Support
|
||||||
|
%x, %lx and %zx.
|
||||||
|
* elf/tst-create_format1.c: New file.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
(Different backport order of tests.)
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 89dff92adfc417f5..6d1962b2e4deb871 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -198,7 +198,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
|
tests-internal += loadtest unload unload2 circleload1 \
|
||||||
|
neededtest neededtest2 neededtest3 neededtest4 \
|
||||||
|
tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \
|
||||||
|
- tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym
|
||||||
|
+ tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym \
|
||||||
|
+ tst-create_format1
|
||||||
|
tests-container += tst-pldd
|
||||||
|
ifeq ($(build-hardcoded-path-in-tests),yes)
|
||||||
|
tests += tst-dlopen-aout
|
||||||
|
diff --git a/elf/dl-exception.c b/elf/dl-exception.c
|
||||||
|
index 1c63e4a3a65b6d55..1e41d89a7db52683 100644
|
||||||
|
--- a/elf/dl-exception.c
|
||||||
|
+++ b/elf/dl-exception.c
|
||||||
|
@@ -111,6 +111,20 @@ _dl_exception_create_format (struct dl_exception *exception, const char *objname
|
||||||
|
case 's':
|
||||||
|
length += strlen (va_arg (ap, const char *));
|
||||||
|
break;
|
||||||
|
+ /* Recognize the l modifier. It is only important on some
|
||||||
|
+ platforms where long and int have a different size. We
|
||||||
|
+ can use the same code for size_t. */
|
||||||
|
+ case 'l':
|
||||||
|
+ case 'z':
|
||||||
|
+ if (p[1] == 'x')
|
||||||
|
+ {
|
||||||
|
+ length += LONG_WIDTH / 4;
|
||||||
|
+ ++p;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ case 'x':
|
||||||
|
+ length += INT_WIDTH / 4;
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
/* Assumed to be '%'. */
|
||||||
|
++length;
|
||||||
|
@@ -167,6 +181,32 @@ _dl_exception_create_format (struct dl_exception *exception, const char *objname
|
||||||
|
*wptr = '%';
|
||||||
|
++wptr;
|
||||||
|
break;
|
||||||
|
+ case 'x':
|
||||||
|
+ {
|
||||||
|
+ unsigned long int num = va_arg (ap, unsigned int);
|
||||||
|
+ char *start = wptr;
|
||||||
|
+ wptr += INT_WIDTH / 4;
|
||||||
|
+ char *cp = _itoa (num, wptr, 16, 0);
|
||||||
|
+ /* Pad to the full width with 0. */
|
||||||
|
+ while (cp != start)
|
||||||
|
+ *--cp = '0';
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ case 'l':
|
||||||
|
+ case 'z':
|
||||||
|
+ if (p[1] == 'x')
|
||||||
|
+ {
|
||||||
|
+ unsigned long int num = va_arg (ap, unsigned long int);
|
||||||
|
+ char *start = wptr;
|
||||||
|
+ wptr += LONG_WIDTH / 4;
|
||||||
|
+ char *cp = _itoa (num, wptr, 16, 0);
|
||||||
|
+ /* Pad to the full width with 0. */
|
||||||
|
+ while (cp != start)
|
||||||
|
+ *--cp = '0';
|
||||||
|
+ ++p;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* FALLTHROUGH */
|
||||||
|
default:
|
||||||
|
_dl_fatal_printf ("Fatal error:"
|
||||||
|
" invalid format in exception string\n");
|
||||||
|
diff --git a/elf/tst-create_format1.c b/elf/tst-create_format1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..8b9edfdc69ea4ced
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-create_format1.c
|
||||||
|
@@ -0,0 +1,103 @@
|
||||||
|
+/* Check _dl_exception_create_format.
|
||||||
|
+ Copyright (C) 2018 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 <ldsodefs.h>
|
||||||
|
+#include <array_length.h>
|
||||||
|
+
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+#include <support/capture_subprocess.h>
|
||||||
|
+
|
||||||
|
+#define TEST(es, objn, fmt, ...) \
|
||||||
|
+ ({ \
|
||||||
|
+ struct dl_exception exception; \
|
||||||
|
+ _dl_exception_create_format (&exception, objn, fmt, __VA_ARGS__); \
|
||||||
|
+ TEST_COMPARE_STRING (exception.objname, objn == NULL ? "" : objn); \
|
||||||
|
+ TEST_COMPARE_STRING (exception.errstring, es); \
|
||||||
|
+ _dl_exception_free (&exception); \
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+do_test_invalid_conversion (void *closure)
|
||||||
|
+{
|
||||||
|
+ TEST ("(null)", NULL, "%p", NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Exit status after abnormal termination. */
|
||||||
|
+static int invalid_status;
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+init_invalid_status (void)
|
||||||
|
+{
|
||||||
|
+ pid_t pid = xfork ();
|
||||||
|
+ if (pid == 0)
|
||||||
|
+ _exit (127);
|
||||||
|
+ xwaitpid (pid, &invalid_status, 0);
|
||||||
|
+ if (WIFEXITED (invalid_status))
|
||||||
|
+ invalid_status = WEXITSTATUS (invalid_status);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ init_invalid_status ();
|
||||||
|
+
|
||||||
|
+ TEST ("test", NULL, "%s", "test");
|
||||||
|
+ TEST ("test-test", NULL, "%s-test", "test");
|
||||||
|
+ TEST ("test", "test", "%s", "test");
|
||||||
|
+ TEST ("test-test", "test", "%s-test", "test");
|
||||||
|
+
|
||||||
|
+ TEST ("test%", NULL, "%s%%", "test");
|
||||||
|
+ TEST ("test%-test", NULL, "%s%%-test", "test");
|
||||||
|
+ TEST ("test%", "test", "%s%%", "test");
|
||||||
|
+ TEST ("test%-test", "test", "%s%%-test", "test");
|
||||||
|
+
|
||||||
|
+ TEST ("0000007b", NULL, "%x", 123);
|
||||||
|
+ TEST ("0000007b-test", NULL, "%x-test", 123);
|
||||||
|
+ TEST ("0000007b", "test", "%x", 123);
|
||||||
|
+ TEST ("0000007b-test", "test", "%x-test", 123);
|
||||||
|
+
|
||||||
|
+#define TEST_LONG(es, objn, fmt, ...) \
|
||||||
|
+ ({ \
|
||||||
|
+ if (sizeof (int) == sizeof (long int)) \
|
||||||
|
+ TEST (es, objn, fmt, __VA_ARGS__); \
|
||||||
|
+ else \
|
||||||
|
+ TEST ("ffffffff" es, objn, fmt, __VA_ARGS__); \
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
+ TEST_LONG ("fffffffd", NULL, "%lx", (long int)~2ul);
|
||||||
|
+ TEST_LONG ("fffffffd-test", NULL, "%lx-test", (long int)~2ul);
|
||||||
|
+ TEST_LONG ("fffffffd", "test", "%lx", (long int)~2ul);
|
||||||
|
+ TEST_LONG ("fffffffd-test", "test", "%lx-test", (long int)~2ul);
|
||||||
|
+
|
||||||
|
+ TEST_LONG ("fffffffe", NULL, "%zx", (size_t)~1ul);
|
||||||
|
+ TEST_LONG ("fffffffe-test", NULL, "%zx-test", (size_t)~1ul);
|
||||||
|
+ TEST_LONG ("fffffffe", "test", "%zx", (size_t)~1ul);
|
||||||
|
+ TEST_LONG ("fffffffe-test", "test", "%zx-test", (size_t)~1ul);
|
||||||
|
+
|
||||||
|
+ struct support_capture_subprocess result;
|
||||||
|
+ result = support_capture_subprocess (do_test_invalid_conversion, NULL);
|
||||||
|
+ support_capture_subprocess_check (&result, "dl-exception",
|
||||||
|
+ invalid_status, sc_allow_stderr);
|
||||||
|
+ TEST_COMPARE_STRING (result.err.buffer,
|
||||||
|
+ "Fatal error: invalid format in exception string\n");
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
22
SOURCES/glibc-rh1817513-130.patch
Normal file
22
SOURCES/glibc-rh1817513-130.patch
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
commit 8dddf0bd5a3d57fba8da27e93f3d1a7032fce184
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Oct 30 17:44:09 2019 +0100
|
||||||
|
|
||||||
|
resolv/tst-idna_name_classify: Isolate from system libraries
|
||||||
|
|
||||||
|
Loading NSS modules from static binaries uses installed system
|
||||||
|
libraries if LD_LIBRARY_PATH is not set.
|
||||||
|
|
||||||
|
diff --git a/inet/Makefile b/inet/Makefile
|
||||||
|
index 7782913b4c06f057..62d25f853538bb08 100644
|
||||||
|
--- a/inet/Makefile
|
||||||
|
+++ b/inet/Makefile
|
||||||
|
@@ -112,4 +112,8 @@ ifeq ($(build-static-nss),yes)
|
||||||
|
CFLAGS += -DSTATIC_NSS
|
||||||
|
endif
|
||||||
|
|
||||||
|
+# The test uses dlopen indirectly and would otherwise load system
|
||||||
|
+# objects.
|
||||||
|
+tst-idna_name_classify-ENV = \
|
||||||
|
+ LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf
|
||||||
|
$(objpfx)tst-idna_name_classify.out: $(gen-locales)
|
21
SOURCES/glibc-rh1817513-131.patch
Normal file
21
SOURCES/glibc-rh1817513-131.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
commit 880433de13fa31e52587720f81b762a6c7797e4e
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Dec 10 15:47:26 2020 +0100
|
||||||
|
|
||||||
|
elf: Include <sys/param.h> in cache.c
|
||||||
|
|
||||||
|
The roundup macro is defined there. Relying on an indirect
|
||||||
|
definition is brittle.
|
||||||
|
|
||||||
|
diff --git a/elf/cache.c b/elf/cache.c
|
||||||
|
index dde3d7fefa4105f9..fdfedb0964bcd217 100644
|
||||||
|
--- a/elf/cache.c
|
||||||
|
+++ b/elf/cache.c
|
||||||
|
@@ -29,6 +29,7 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
+#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
33
SOURCES/glibc-rh1817513-132.patch
Normal file
33
SOURCES/glibc-rh1817513-132.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
commit 2ee7711bdd7de9dd30073b223ce29d5cd50320f6
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Sun Dec 13 04:56:41 2020 -0800
|
||||||
|
|
||||||
|
x86: Remove the default REP MOVSB threshold tunable value [BZ #27061]
|
||||||
|
|
||||||
|
Since we can't tell if the tunable value is set by user or not:
|
||||||
|
|
||||||
|
https://sourceware.org/bugzilla/show_bug.cgi?id=27069
|
||||||
|
|
||||||
|
remove the default REP MOVSB threshold tunable value so that the correct
|
||||||
|
default value will be set correctly by init_cacheinfo ().
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list
|
||||||
|
index e066313a1d1dd009..89bf296626658900 100644
|
||||||
|
--- a/sysdeps/x86/dl-tunables.list
|
||||||
|
+++ b/sysdeps/x86/dl-tunables.list
|
||||||
|
@@ -39,9 +39,11 @@ glibc {
|
||||||
|
# REP MOVSB. Since larger register size can move more data with a
|
||||||
|
# single load and store, the threshold is higher with larger register
|
||||||
|
# size. Note: Since the REP MOVSB threshold must be greater than 8
|
||||||
|
- # times of vector size, the minium value must be updated at run-time.
|
||||||
|
+ # times of vector size and the default value is 2048 * (vector size
|
||||||
|
+ # / 16), the default value and the minimum value must be updated at
|
||||||
|
+ # run-time. NB: Don't set the default value since we can't tell if
|
||||||
|
+ # the tunable value is set by user or not [BZ #27069].
|
||||||
|
minval: 1
|
||||||
|
- default: 2048
|
||||||
|
}
|
||||||
|
x86_rep_stosb_threshold {
|
||||||
|
type: SIZE_T
|
18
SOURCES/glibc-rh1817513-133.patch
Normal file
18
SOURCES/glibc-rh1817513-133.patch
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
commit 8a30bb4e0604aefcf28f20360fc8ba8ef8604b9c
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Dec 23 12:07:20 2020 +0100
|
||||||
|
|
||||||
|
elf: Account for glibc-hwcaps/ prefix in _dl_important_hwcaps
|
||||||
|
|
||||||
|
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
||||||
|
index 50d764ae8707f46d..2fc4ae67a0f5d051 100644
|
||||||
|
--- a/elf/dl-hwcaps.c
|
||||||
|
+++ b/elf/dl-hwcaps.c
|
||||||
|
@@ -192,6 +192,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||||
|
|
||||||
|
/* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix
|
||||||
|
and a "/" suffix once stored in the result. */
|
||||||
|
+ hwcaps_counts.maximum_length += strlen (GLIBC_HWCAPS_PREFIX) + 1;
|
||||||
|
size_t total = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
|
||||||
|
+ hwcaps_counts.total_length);
|
||||||
|
|
22
SOURCES/glibc-rh1817513-14.patch
Normal file
22
SOURCES/glibc-rh1817513-14.patch
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
commit ce7387cc250a408d3fbb7a6fff7ad4d977166b00
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu Nov 29 20:03:46 2018 -0800
|
||||||
|
|
||||||
|
elf/dl-exception.c: Include <_itoa.h> for _itoa prototype
|
||||||
|
|
||||||
|
Tested with build-many-glibcs.py.
|
||||||
|
|
||||||
|
* elf/dl-exception.c: Include <_itoa.h>.
|
||||||
|
|
||||||
|
diff --git a/elf/dl-exception.c b/elf/dl-exception.c
|
||||||
|
index 1e41d89a7db52683..3e8e0ba3f1442005 100644
|
||||||
|
--- a/elf/dl-exception.c
|
||||||
|
+++ b/elf/dl-exception.c
|
||||||
|
@@ -23,6 +23,7 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
+#include <_itoa.h>
|
||||||
|
|
||||||
|
/* This message we return as a last resort. We define the string in a
|
||||||
|
variable since we have to avoid freeing it and so have to enable
|
1820
SOURCES/glibc-rh1817513-15.patch
Normal file
1820
SOURCES/glibc-rh1817513-15.patch
Normal file
File diff suppressed because it is too large
Load Diff
146
SOURCES/glibc-rh1817513-16.patch
Normal file
146
SOURCES/glibc-rh1817513-16.patch
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
commit b2e93de0ffedcfe2cfba100d47a4d4f6f85cea0b
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Tue Dec 4 00:03:12 2018 -0500
|
||||||
|
|
||||||
|
test-container: add "su" command to run test as root, add unshare hints
|
||||||
|
|
||||||
|
* support/test-container.c (check_for_unshare_hints): New.
|
||||||
|
(main): Call it if unshare fails. Add support for "su" scriptlet
|
||||||
|
command.
|
||||||
|
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index fe0ebbd07df83da7..1d1aebeaf3412573 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -88,15 +88,22 @@ int verbose = 0;
|
||||||
|
* mytest.root/ is rsync'd into container
|
||||||
|
* mytest.root/preclean.req causes fresh rsync (with delete) before
|
||||||
|
test if present
|
||||||
|
- * mytest.root/mytset.script has a list of "commands" to run:
|
||||||
|
+ * mytest.root/mytest.script has a list of "commands" to run:
|
||||||
|
syntax:
|
||||||
|
# comment
|
||||||
|
+ su
|
||||||
|
mv FILE FILE
|
||||||
|
cp FILE FILE
|
||||||
|
rm FILE
|
||||||
|
FILE must start with $B/, $S/, $I/, $L/, or /
|
||||||
|
(expands to build dir, source dir, install dir, library dir
|
||||||
|
(in container), or container's root)
|
||||||
|
+ details:
|
||||||
|
+ - '#': A comment.
|
||||||
|
+ - 'su': Enables running test as root in the container.
|
||||||
|
+ - 'mv': A minimal move files command.
|
||||||
|
+ - 'cp': A minimal copy files command.
|
||||||
|
+ - 'rm': A minimal remove files command.
|
||||||
|
* mytest.root/postclean.req causes fresh rsync (with delete) after
|
||||||
|
test if present
|
||||||
|
|
||||||
|
@@ -349,6 +356,7 @@ recursive_remove (char *path)
|
||||||
|
|
||||||
|
switch (child) {
|
||||||
|
case -1:
|
||||||
|
+ perror("fork");
|
||||||
|
FAIL_EXIT1 ("Unable to fork");
|
||||||
|
case 0:
|
||||||
|
/* Child. */
|
||||||
|
@@ -610,6 +618,47 @@ rsync (char *src, char *dest, int and_delete)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+
|
||||||
|
+/* See if we can detect what the user needs to do to get unshare
|
||||||
|
+ support working for us. */
|
||||||
|
+void
|
||||||
|
+check_for_unshare_hints (void)
|
||||||
|
+{
|
||||||
|
+ FILE *f;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ /* Default Debian Linux disables user namespaces, but allows a way
|
||||||
|
+ to enable them. */
|
||||||
|
+ f = fopen ("/proc/sys/kernel/unprivileged_userns_clone", "r");
|
||||||
|
+ if (f != NULL)
|
||||||
|
+ {
|
||||||
|
+ i = 99; /* Sentinel. */
|
||||||
|
+ fscanf (f, "%d", &i);
|
||||||
|
+ if (i == 0)
|
||||||
|
+ {
|
||||||
|
+ printf ("To enable test-container, please run this as root:\n");
|
||||||
|
+ printf (" echo 1 > /proc/sys/kernel/unprivileged_userns_clone\n");
|
||||||
|
+ }
|
||||||
|
+ fclose (f);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* ALT Linux has an alternate way of doing the same. */
|
||||||
|
+ f = fopen ("/proc/sys/kernel/userns_restrict", "r");
|
||||||
|
+ if (f != NULL)
|
||||||
|
+ {
|
||||||
|
+ i = 99; /* Sentinel. */
|
||||||
|
+ fscanf (f, "%d", &i);
|
||||||
|
+ if (i == 1)
|
||||||
|
+ {
|
||||||
|
+ printf ("To enable test-container, please run this as root:\n");
|
||||||
|
+ printf (" echo 0 > /proc/sys/kernel/userns_restrict\n");
|
||||||
|
+ }
|
||||||
|
+ fclose (f);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
@@ -628,6 +677,8 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
|
uid_t original_uid;
|
||||||
|
gid_t original_gid;
|
||||||
|
+ /* If set, the test runs as root instead of the user running the testsuite. */
|
||||||
|
+ int be_su = 0;
|
||||||
|
int UMAP;
|
||||||
|
int GMAP;
|
||||||
|
/* Used for "%lld %lld 1" so need not be large. */
|
||||||
|
@@ -857,6 +908,10 @@ main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
maybe_xunlink (the_words[1]);
|
||||||
|
}
|
||||||
|
+ else if (nt == 1 && strcmp (the_words[0], "su") == 0)
|
||||||
|
+ {
|
||||||
|
+ be_su = 1;
|
||||||
|
+ }
|
||||||
|
else if (nt > 0 && the_words[0][0] != '#')
|
||||||
|
{
|
||||||
|
printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]);
|
||||||
|
@@ -910,7 +965,12 @@ main (int argc, char **argv)
|
||||||
|
/* Older kernels may not support all the options, or security
|
||||||
|
policy may block this call. */
|
||||||
|
if (errno == EINVAL || errno == EPERM)
|
||||||
|
- FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (errno));
|
||||||
|
+ {
|
||||||
|
+ int saved_errno = errno;
|
||||||
|
+ if (errno == EPERM)
|
||||||
|
+ check_for_unshare_hints ();
|
||||||
|
+ FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno));
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
FAIL_EXIT1 ("unable to unshare user/fs: %s", strerror (errno));
|
||||||
|
}
|
||||||
|
@@ -981,7 +1041,7 @@ main (int argc, char **argv)
|
||||||
|
FAIL_EXIT1 ("can't write to /proc/self/uid_map\n");
|
||||||
|
|
||||||
|
sprintf (tmp, "%lld %lld 1\n",
|
||||||
|
- (long long) original_uid, (long long) original_uid);
|
||||||
|
+ (long long) (be_su ? 0 : original_uid), (long long) original_uid);
|
||||||
|
write (UMAP, tmp, strlen (tmp));
|
||||||
|
xclose (UMAP);
|
||||||
|
|
||||||
|
@@ -1002,7 +1062,7 @@ main (int argc, char **argv)
|
||||||
|
FAIL_EXIT1 ("can't write to /proc/self/gid_map\n");
|
||||||
|
|
||||||
|
sprintf (tmp, "%lld %lld 1\n",
|
||||||
|
- (long long) original_gid, (long long) original_gid);
|
||||||
|
+ (long long) (be_su ? 0 : original_gid), (long long) original_gid);
|
||||||
|
write (GMAP, tmp, strlen (tmp));
|
||||||
|
xclose (GMAP);
|
||||||
|
|
1559
SOURCES/glibc-rh1817513-17.patch
Normal file
1559
SOURCES/glibc-rh1817513-17.patch
Normal file
File diff suppressed because it is too large
Load Diff
191
SOURCES/glibc-rh1817513-18.patch
Normal file
191
SOURCES/glibc-rh1817513-18.patch
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
commit 32db86d558193ad4ad5a00926ce3c350c89eb8df
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Tue Feb 12 10:30:34 2019 +0000
|
||||||
|
|
||||||
|
Add fall-through comments.
|
||||||
|
|
||||||
|
This patch adds fall-through comments in some cases where -Wextra
|
||||||
|
produces implicit-fallthrough warnings.
|
||||||
|
|
||||||
|
The patch is non-exhaustive. Apart from architecture-specific code
|
||||||
|
for non-x86_64 architectures, it does not change sunrpc/xdr.c (legacy
|
||||||
|
code, probably should have such changes, but left to be dealt with
|
||||||
|
separately), or places that already had comments about the
|
||||||
|
fall-through but not matching the form expected by
|
||||||
|
-Wimplicit-fallthrough=3 (the default level with -Wextra; my
|
||||||
|
inclination is to adjust those comments to match rather than
|
||||||
|
downgrading to -Wimplicit-fallthrough=1 to allow any comment), or one
|
||||||
|
place where I thought the implicit fallthrough was not correct and so
|
||||||
|
should be handled separately as a bug fix. I think the key thing to
|
||||||
|
consider in review of this patch is whether the fall-through is indeed
|
||||||
|
intended and correct in each place where such a comment is added.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
* elf/dl-exception.c (_dl_exception_create_format): Add
|
||||||
|
fall-through comments.
|
||||||
|
* elf/ldconfig.c (parse_conf_include): Likewise.
|
||||||
|
* elf/rtld.c (print_statistics): Likewise.
|
||||||
|
* locale/programs/charmap.c (parse_charmap): Likewise.
|
||||||
|
* misc/mntent_r.c (__getmntent_r): Likewise.
|
||||||
|
* posix/wordexp.c (parse_arith): Likewise.
|
||||||
|
(parse_backtick): Likewise.
|
||||||
|
* resolv/ns_ttl.c (ns_parse_ttl): Likewise.
|
||||||
|
* sysdeps/x86/cpu-features.c (init_cpu_features): Likewise.
|
||||||
|
* sysdeps/x86_64/dl-machine.h (elf_machine_rela): Likewise.
|
||||||
|
|
||||||
|
diff --git a/elf/dl-exception.c b/elf/dl-exception.c
|
||||||
|
index 3e8e0ba3f1442005..d24bf30a5cf39bc2 100644
|
||||||
|
--- a/elf/dl-exception.c
|
||||||
|
+++ b/elf/dl-exception.c
|
||||||
|
@@ -123,6 +123,7 @@ _dl_exception_create_format (struct dl_exception *exception, const char *objname
|
||||||
|
++p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 'x':
|
||||||
|
length += INT_WIDTH / 4;
|
||||||
|
break;
|
||||||
|
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||||
|
index fbdd814edf59bc77..ed7d9ab0412d93fd 100644
|
||||||
|
--- a/elf/ldconfig.c
|
||||||
|
+++ b/elf/ldconfig.c
|
||||||
|
@@ -1228,6 +1228,7 @@ parse_conf_include (const char *config_file, unsigned int lineno,
|
||||||
|
|
||||||
|
case GLOB_NOSPACE:
|
||||||
|
errno = ENOMEM;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case GLOB_ABORTED:
|
||||||
|
if (opt_verbose)
|
||||||
|
error (0, errno, _("%s:%u: cannot read directory %s"),
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index 7f030f75a22c532e..8bb5f548a0ff8eb4 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -2734,8 +2734,10 @@ print_statistics (hp_timing_t *rtld_total_timep)
|
||||||
|
{
|
||||||
|
case 3:
|
||||||
|
*wp++ = *cp++;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 2:
|
||||||
|
*wp++ = *cp++;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 1:
|
||||||
|
*wp++ = '.';
|
||||||
|
*wp++ = *cp++;
|
||||||
|
@@ -2797,8 +2799,10 @@ print_statistics (hp_timing_t *rtld_total_timep)
|
||||||
|
{
|
||||||
|
case 3:
|
||||||
|
*wp++ = *cp++;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 2:
|
||||||
|
*wp++ = *cp++;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 1:
|
||||||
|
*wp++ = '.';
|
||||||
|
*wp++ = *cp++;
|
||||||
|
diff --git a/locale/programs/charmap.c b/locale/programs/charmap.c
|
||||||
|
index 2d54dd3c027d11d2..8041a0e5d292f3f5 100644
|
||||||
|
--- a/locale/programs/charmap.c
|
||||||
|
+++ b/locale/programs/charmap.c
|
||||||
|
@@ -713,6 +713,7 @@ only WIDTH definitions are allowed to follow the CHARMAP definition"));
|
||||||
|
state = 95;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
+ /* Fall through. */
|
||||||
|
|
||||||
|
case 96:
|
||||||
|
if (nowtok != tok_number)
|
||||||
|
diff --git a/misc/mntent_r.c b/misc/mntent_r.c
|
||||||
|
index 7bb224f044150ab4..add39d4537eaccb5 100644
|
||||||
|
--- a/misc/mntent_r.c
|
||||||
|
+++ b/misc/mntent_r.c
|
||||||
|
@@ -167,8 +167,10 @@ get_mnt_entry (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
mp->mnt_freq = 0;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 1:
|
||||||
|
mp->mnt_passno = 0;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 2:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff --git a/posix/wordexp.c b/posix/wordexp.c
|
||||||
|
index 7548e0329fdeafaa..048a8068544c81fa 100644
|
||||||
|
--- a/posix/wordexp.c
|
||||||
|
+++ b/posix/wordexp.c
|
||||||
|
@@ -799,6 +799,7 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
++paren_depth;
|
||||||
|
+ /* Fall through. */
|
||||||
|
default:
|
||||||
|
expr = w_addchar (expr, &expr_length, &expr_maxlen, words[*offset]);
|
||||||
|
if (expr == NULL)
|
||||||
|
@@ -2127,6 +2128,7 @@ parse_backtick (char **word, size_t *word_length, size_t *max_length,
|
||||||
|
|
||||||
|
case '\'':
|
||||||
|
squoting = 1 - squoting;
|
||||||
|
+ /* Fall through. */
|
||||||
|
default:
|
||||||
|
comm = w_addchar (comm, &comm_length, &comm_maxlen, words[*offset]);
|
||||||
|
if (comm == NULL)
|
||||||
|
diff --git a/resolv/ns_ttl.c b/resolv/ns_ttl.c
|
||||||
|
index 079948790b94b05e..d29d9dc00cfcab2c 100644
|
||||||
|
--- a/resolv/ns_ttl.c
|
||||||
|
+++ b/resolv/ns_ttl.c
|
||||||
|
@@ -113,9 +113,13 @@ ns_parse_ttl(const char *src, u_long *dst) {
|
||||||
|
ch = toupper(ch);
|
||||||
|
switch (ch) {
|
||||||
|
case 'W': tmp *= 7;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 'D': tmp *= 24;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 'H': tmp *= 60;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 'M': tmp *= 60;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 'S': break;
|
||||||
|
default: goto einval;
|
||||||
|
}
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index 3a02a9c7d08f9603..ade37a9bb3de86cc 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -374,6 +374,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
of Core i3/i5/i7 processors if AVX is available. */
|
||||||
|
if (!CPU_FEATURES_CPU_P (cpu_features, AVX))
|
||||||
|
break;
|
||||||
|
+ /* Fall through. */
|
||||||
|
|
||||||
|
case 0x1a:
|
||||||
|
case 0x1e:
|
||||||
|
@@ -401,6 +402,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
/* Xeon E7 v3 with stepping >= 4 has working TSX. */
|
||||||
|
if (stepping >= 4)
|
||||||
|
break;
|
||||||
|
+ /* Fall through. */
|
||||||
|
case 0x3c:
|
||||||
|
case 0x45:
|
||||||
|
case 0x46:
|
||||||
|
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
|
||||||
|
index 1942ed5061d18c68..23afb3c05dbe17d6 100644
|
||||||
|
--- a/sysdeps/x86_64/dl-machine.h
|
||||||
|
+++ b/sysdeps/x86_64/dl-machine.h
|
||||||
|
@@ -347,6 +347,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
||||||
|
/* Set to symbol size plus addend. */
|
||||||
|
value = sym->st_size;
|
||||||
|
# endif
|
||||||
|
+ /* Fall through. */
|
||||||
|
case R_X86_64_GLOB_DAT:
|
||||||
|
case R_X86_64_JUMP_SLOT:
|
||||||
|
*reloc_addr = value + reloc->r_addend;
|
||||||
|
@@ -460,6 +461,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
||||||
|
/* Set to symbol size plus addend. */
|
||||||
|
value = sym->st_size;
|
||||||
|
# endif
|
||||||
|
+ /* Fall through. */
|
||||||
|
case R_X86_64_32:
|
||||||
|
value += reloc->r_addend;
|
||||||
|
*(unsigned int *) reloc_addr = value;
|
408
SOURCES/glibc-rh1817513-19.patch
Normal file
408
SOURCES/glibc-rh1817513-19.patch
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
commit 3b856d093f5197637a5927c37d6c07dad8c86d45
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Tue Feb 12 13:36:56 2019 +0100
|
||||||
|
|
||||||
|
elf: Ignore LD_AUDIT interfaces if la_version returns 0 [BZ #24122]
|
||||||
|
|
||||||
|
This change moves the audit module loading and early notification into
|
||||||
|
separate functions out of dl_main.
|
||||||
|
|
||||||
|
It restores the bug fix from commit
|
||||||
|
8e889c5da3c5981c5a46a93fec02de40131ac5a6 ("elf: Fix LD_AUDIT for
|
||||||
|
modules with invalid version (BZ#24122)") which was reverted in commit
|
||||||
|
83e6b59625f45db1eee93e5684091f740c52a083 ("[elf] Revert 8e889c5da3
|
||||||
|
(BZ#24122)").
|
||||||
|
|
||||||
|
The actual bug fix is the separate error message for the case when
|
||||||
|
la_version returns zero. The dynamic linker error message (which is
|
||||||
|
NULL in this case) is no longer used. Based on the intended use of
|
||||||
|
version zero (ignore this module due to explicit request), the message
|
||||||
|
is only printed if debugging is enabled.
|
||||||
|
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index 8bb5f548a0ff8eb4..375e0de8fa2e049e 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -864,6 +864,205 @@ handle_preload_list (const char *preloadlist, struct link_map *main_map,
|
||||||
|
return npreloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Called if the audit DSO cannot be used: if it does not have the
|
||||||
|
+ appropriate interfaces, or it expects a more recent version library
|
||||||
|
+ version than what the dynamic linker provides. */
|
||||||
|
+static void
|
||||||
|
+unload_audit_module (struct link_map *map, int original_tls_idx)
|
||||||
|
+{
|
||||||
|
+#ifndef NDEBUG
|
||||||
|
+ Lmid_t ns = map->l_ns;
|
||||||
|
+#endif
|
||||||
|
+ _dl_close (map);
|
||||||
|
+
|
||||||
|
+ /* Make sure the namespace has been cleared entirely. */
|
||||||
|
+ assert (GL(dl_ns)[ns]._ns_loaded == NULL);
|
||||||
|
+ assert (GL(dl_ns)[ns]._ns_nloaded == 0);
|
||||||
|
+
|
||||||
|
+ GL(dl_tls_max_dtv_idx) = original_tls_idx;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Called to print an error message if loading of an audit module
|
||||||
|
+ failed. */
|
||||||
|
+static void
|
||||||
|
+report_audit_module_load_error (const char *name, const char *err_str,
|
||||||
|
+ bool malloced)
|
||||||
|
+{
|
||||||
|
+ _dl_error_printf ("\
|
||||||
|
+ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||||
|
+ name, err_str);
|
||||||
|
+ if (malloced)
|
||||||
|
+ free ((char *) err_str);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Load one audit module. */
|
||||||
|
+static void
|
||||||
|
+load_audit_module (const char *name, struct audit_ifaces **last_audit)
|
||||||
|
+{
|
||||||
|
+ int original_tls_idx = GL(dl_tls_max_dtv_idx);
|
||||||
|
+
|
||||||
|
+ struct dlmopen_args dlmargs;
|
||||||
|
+ dlmargs.fname = name;
|
||||||
|
+ dlmargs.map = NULL;
|
||||||
|
+
|
||||||
|
+ const char *objname;
|
||||||
|
+ const char *err_str = NULL;
|
||||||
|
+ bool malloced;
|
||||||
|
+ _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit, &dlmargs);
|
||||||
|
+ if (__glibc_unlikely (err_str != NULL))
|
||||||
|
+ {
|
||||||
|
+ report_audit_module_load_error (name, err_str, malloced);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ struct lookup_args largs;
|
||||||
|
+ largs.name = "la_version";
|
||||||
|
+ largs.map = dlmargs.map;
|
||||||
|
+ _dl_catch_error (&objname, &err_str, &malloced, lookup_doit, &largs);
|
||||||
|
+ if (__glibc_likely (err_str != NULL))
|
||||||
|
+ {
|
||||||
|
+ unload_audit_module (dlmargs.map, original_tls_idx);
|
||||||
|
+ report_audit_module_load_error (name, err_str, malloced);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ unsigned int (*laversion) (unsigned int) = largs.result;
|
||||||
|
+
|
||||||
|
+ /* A null symbol indicates that something is very wrong with the
|
||||||
|
+ loaded object because defined symbols are supposed to have a
|
||||||
|
+ valid, non-null address. */
|
||||||
|
+ assert (laversion != NULL);
|
||||||
|
+
|
||||||
|
+ unsigned int lav = laversion (LAV_CURRENT);
|
||||||
|
+ if (lav == 0)
|
||||||
|
+ {
|
||||||
|
+ /* Only print an error message if debugging because this can
|
||||||
|
+ happen deliberately. */
|
||||||
|
+ if (GLRO(dl_debug_mask) & DL_DEBUG_FILES)
|
||||||
|
+ _dl_debug_printf ("\
|
||||||
|
+file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
|
||||||
|
+ dlmargs.map->l_name, dlmargs.map->l_ns);
|
||||||
|
+ unload_audit_module (dlmargs.map, original_tls_idx);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (lav > LAV_CURRENT)
|
||||||
|
+ {
|
||||||
|
+ _dl_debug_printf ("\
|
||||||
|
+ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n",
|
||||||
|
+ name, lav, LAV_CURRENT);
|
||||||
|
+ unload_audit_module (dlmargs.map, original_tls_idx);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ enum { naudit_ifaces = 8 };
|
||||||
|
+ union
|
||||||
|
+ {
|
||||||
|
+ struct audit_ifaces ifaces;
|
||||||
|
+ void (*fptr[naudit_ifaces]) (void);
|
||||||
|
+ } *newp = malloc (sizeof (*newp));
|
||||||
|
+ if (newp == NULL)
|
||||||
|
+ _dl_fatal_printf ("Out of memory while loading audit modules\n");
|
||||||
|
+
|
||||||
|
+ /* Names of the auditing interfaces. All in one
|
||||||
|
+ long string. */
|
||||||
|
+ static const char audit_iface_names[] =
|
||||||
|
+ "la_activity\0"
|
||||||
|
+ "la_objsearch\0"
|
||||||
|
+ "la_objopen\0"
|
||||||
|
+ "la_preinit\0"
|
||||||
|
+#if __ELF_NATIVE_CLASS == 32
|
||||||
|
+ "la_symbind32\0"
|
||||||
|
+#elif __ELF_NATIVE_CLASS == 64
|
||||||
|
+ "la_symbind64\0"
|
||||||
|
+#else
|
||||||
|
+# error "__ELF_NATIVE_CLASS must be defined"
|
||||||
|
+#endif
|
||||||
|
+#define STRING(s) __STRING (s)
|
||||||
|
+ "la_" STRING (ARCH_LA_PLTENTER) "\0"
|
||||||
|
+ "la_" STRING (ARCH_LA_PLTEXIT) "\0"
|
||||||
|
+ "la_objclose\0";
|
||||||
|
+ unsigned int cnt = 0;
|
||||||
|
+ const char *cp = audit_iface_names;
|
||||||
|
+ do
|
||||||
|
+ {
|
||||||
|
+ largs.name = cp;
|
||||||
|
+ _dl_catch_error (&objname, &err_str, &malloced, lookup_doit, &largs);
|
||||||
|
+
|
||||||
|
+ /* Store the pointer. */
|
||||||
|
+ if (err_str == NULL && largs.result != NULL)
|
||||||
|
+ {
|
||||||
|
+ newp->fptr[cnt] = largs.result;
|
||||||
|
+
|
||||||
|
+ /* The dynamic linker link map is statically allocated,
|
||||||
|
+ initialize the data now. */
|
||||||
|
+ GL(dl_rtld_map).l_audit[cnt].cookie = (intptr_t) &GL(dl_rtld_map);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ newp->fptr[cnt] = NULL;
|
||||||
|
+ ++cnt;
|
||||||
|
+
|
||||||
|
+ cp = rawmemchr (cp, '\0') + 1;
|
||||||
|
+ }
|
||||||
|
+ while (*cp != '\0');
|
||||||
|
+ assert (cnt == naudit_ifaces);
|
||||||
|
+
|
||||||
|
+ /* Now append the new auditing interface to the list. */
|
||||||
|
+ newp->ifaces.next = NULL;
|
||||||
|
+ if (*last_audit == NULL)
|
||||||
|
+ *last_audit = GLRO(dl_audit) = &newp->ifaces;
|
||||||
|
+ else
|
||||||
|
+ *last_audit = (*last_audit)->next = &newp->ifaces;
|
||||||
|
+ ++GLRO(dl_naudit);
|
||||||
|
+
|
||||||
|
+ /* Mark the DSO as being used for auditing. */
|
||||||
|
+ dlmargs.map->l_auditing = 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Notify the the audit modules that the object MAP has already been
|
||||||
|
+ loaded. */
|
||||||
|
+static void
|
||||||
|
+notify_audit_modules_of_loaded_object (struct link_map *map)
|
||||||
|
+{
|
||||||
|
+ struct audit_ifaces *afct = GLRO(dl_audit);
|
||||||
|
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
+ {
|
||||||
|
+ if (afct->objopen != NULL)
|
||||||
|
+ {
|
||||||
|
+ map->l_audit[cnt].bindflags
|
||||||
|
+ = afct->objopen (map, LM_ID_BASE, &map->l_audit[cnt].cookie);
|
||||||
|
+ map->l_audit_any_plt |= map->l_audit[cnt].bindflags != 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ afct = afct->next;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Load all audit modules. */
|
||||||
|
+static void
|
||||||
|
+load_audit_modules (struct link_map *main_map)
|
||||||
|
+{
|
||||||
|
+ struct audit_ifaces *last_audit = NULL;
|
||||||
|
+ struct audit_list_iter al_iter;
|
||||||
|
+ audit_list_iter_init (&al_iter);
|
||||||
|
+
|
||||||
|
+ while (true)
|
||||||
|
+ {
|
||||||
|
+ const char *name = audit_list_iter_next (&al_iter);
|
||||||
|
+ if (name == NULL)
|
||||||
|
+ break;
|
||||||
|
+ load_audit_module (name, &last_audit);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Notify audit modules of the initially loaded modules (the main
|
||||||
|
+ program and the dynamic linker itself). */
|
||||||
|
+ if (GLRO(dl_naudit) > 0)
|
||||||
|
+ {
|
||||||
|
+ notify_audit_modules_of_loaded_object (main_map);
|
||||||
|
+ notify_audit_modules_of_loaded_object (&GL(dl_rtld_map));
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
dl_main (const ElfW(Phdr) *phdr,
|
||||||
|
ElfW(Word) phnum,
|
||||||
|
@@ -1402,10 +1601,6 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
if (__glibc_unlikely (audit_list != NULL)
|
||||||
|
|| __glibc_unlikely (audit_list_string != NULL))
|
||||||
|
{
|
||||||
|
- struct audit_ifaces *last_audit = NULL;
|
||||||
|
- struct audit_list_iter al_iter;
|
||||||
|
- audit_list_iter_init (&al_iter);
|
||||||
|
-
|
||||||
|
/* Since we start using the auditing DSOs right away we need to
|
||||||
|
initialize the data structures now. */
|
||||||
|
tcbp = init_tls ();
|
||||||
|
@@ -1417,164 +1612,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
security_init ();
|
||||||
|
need_security_init = false;
|
||||||
|
|
||||||
|
- while (true)
|
||||||
|
- {
|
||||||
|
- const char *name = audit_list_iter_next (&al_iter);
|
||||||
|
- if (name == NULL)
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
- int tls_idx = GL(dl_tls_max_dtv_idx);
|
||||||
|
-
|
||||||
|
- /* Now it is time to determine the layout of the static TLS
|
||||||
|
- block and allocate it for the initial thread. Note that we
|
||||||
|
- always allocate the static block, we never defer it even if
|
||||||
|
- no DF_STATIC_TLS bit is set. The reason is that we know
|
||||||
|
- glibc will use the static model. */
|
||||||
|
- struct dlmopen_args dlmargs;
|
||||||
|
- dlmargs.fname = name;
|
||||||
|
- dlmargs.map = NULL;
|
||||||
|
-
|
||||||
|
- const char *objname;
|
||||||
|
- const char *err_str = NULL;
|
||||||
|
- bool malloced;
|
||||||
|
- (void) _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit,
|
||||||
|
- &dlmargs);
|
||||||
|
- if (__glibc_unlikely (err_str != NULL))
|
||||||
|
- {
|
||||||
|
- not_loaded:
|
||||||
|
- _dl_error_printf ("\
|
||||||
|
-ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||||
|
- name, err_str);
|
||||||
|
- if (malloced)
|
||||||
|
- free ((char *) err_str);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- struct lookup_args largs;
|
||||||
|
- largs.name = "la_version";
|
||||||
|
- largs.map = dlmargs.map;
|
||||||
|
-
|
||||||
|
- /* Check whether the interface version matches. */
|
||||||
|
- (void) _dl_catch_error (&objname, &err_str, &malloced,
|
||||||
|
- lookup_doit, &largs);
|
||||||
|
-
|
||||||
|
- unsigned int (*laversion) (unsigned int);
|
||||||
|
- unsigned int lav;
|
||||||
|
- if (err_str == NULL
|
||||||
|
- && (laversion = largs.result) != NULL
|
||||||
|
- && (lav = laversion (LAV_CURRENT)) > 0
|
||||||
|
- && lav <= LAV_CURRENT)
|
||||||
|
- {
|
||||||
|
- /* Allocate structure for the callback function pointers.
|
||||||
|
- This call can never fail. */
|
||||||
|
- union
|
||||||
|
- {
|
||||||
|
- struct audit_ifaces ifaces;
|
||||||
|
-#define naudit_ifaces 8
|
||||||
|
- void (*fptr[naudit_ifaces]) (void);
|
||||||
|
- } *newp = malloc (sizeof (*newp));
|
||||||
|
-
|
||||||
|
- /* Names of the auditing interfaces. All in one
|
||||||
|
- long string. */
|
||||||
|
- static const char audit_iface_names[] =
|
||||||
|
- "la_activity\0"
|
||||||
|
- "la_objsearch\0"
|
||||||
|
- "la_objopen\0"
|
||||||
|
- "la_preinit\0"
|
||||||
|
-#if __ELF_NATIVE_CLASS == 32
|
||||||
|
- "la_symbind32\0"
|
||||||
|
-#elif __ELF_NATIVE_CLASS == 64
|
||||||
|
- "la_symbind64\0"
|
||||||
|
-#else
|
||||||
|
-# error "__ELF_NATIVE_CLASS must be defined"
|
||||||
|
-#endif
|
||||||
|
-#define STRING(s) __STRING (s)
|
||||||
|
- "la_" STRING (ARCH_LA_PLTENTER) "\0"
|
||||||
|
- "la_" STRING (ARCH_LA_PLTEXIT) "\0"
|
||||||
|
- "la_objclose\0";
|
||||||
|
- unsigned int cnt = 0;
|
||||||
|
- const char *cp = audit_iface_names;
|
||||||
|
- do
|
||||||
|
- {
|
||||||
|
- largs.name = cp;
|
||||||
|
- (void) _dl_catch_error (&objname, &err_str, &malloced,
|
||||||
|
- lookup_doit, &largs);
|
||||||
|
-
|
||||||
|
- /* Store the pointer. */
|
||||||
|
- if (err_str == NULL && largs.result != NULL)
|
||||||
|
- {
|
||||||
|
- newp->fptr[cnt] = largs.result;
|
||||||
|
-
|
||||||
|
- /* The dynamic linker link map is statically
|
||||||
|
- allocated, initialize the data now. */
|
||||||
|
- GL(dl_rtld_map).l_audit[cnt].cookie
|
||||||
|
- = (intptr_t) &GL(dl_rtld_map);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- newp->fptr[cnt] = NULL;
|
||||||
|
- ++cnt;
|
||||||
|
-
|
||||||
|
- cp = (char *) rawmemchr (cp, '\0') + 1;
|
||||||
|
- }
|
||||||
|
- while (*cp != '\0');
|
||||||
|
- assert (cnt == naudit_ifaces);
|
||||||
|
-
|
||||||
|
- /* Now append the new auditing interface to the list. */
|
||||||
|
- newp->ifaces.next = NULL;
|
||||||
|
- if (last_audit == NULL)
|
||||||
|
- last_audit = GLRO(dl_audit) = &newp->ifaces;
|
||||||
|
- else
|
||||||
|
- last_audit = last_audit->next = &newp->ifaces;
|
||||||
|
- ++GLRO(dl_naudit);
|
||||||
|
-
|
||||||
|
- /* Mark the DSO as being used for auditing. */
|
||||||
|
- dlmargs.map->l_auditing = 1;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- /* We cannot use the DSO, it does not have the
|
||||||
|
- appropriate interfaces or it expects something
|
||||||
|
- more recent. */
|
||||||
|
-#ifndef NDEBUG
|
||||||
|
- Lmid_t ns = dlmargs.map->l_ns;
|
||||||
|
-#endif
|
||||||
|
- _dl_close (dlmargs.map);
|
||||||
|
-
|
||||||
|
- /* Make sure the namespace has been cleared entirely. */
|
||||||
|
- assert (GL(dl_ns)[ns]._ns_loaded == NULL);
|
||||||
|
- assert (GL(dl_ns)[ns]._ns_nloaded == 0);
|
||||||
|
-
|
||||||
|
- GL(dl_tls_max_dtv_idx) = tls_idx;
|
||||||
|
- goto not_loaded;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* If we have any auditing modules, announce that we already
|
||||||
|
- have two objects loaded. */
|
||||||
|
- if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||||
|
- {
|
||||||
|
- struct link_map *ls[2] = { main_map, &GL(dl_rtld_map) };
|
||||||
|
-
|
||||||
|
- for (unsigned int outer = 0; outer < 2; ++outer)
|
||||||
|
- {
|
||||||
|
- struct audit_ifaces *afct = GLRO(dl_audit);
|
||||||
|
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
- {
|
||||||
|
- if (afct->objopen != NULL)
|
||||||
|
- {
|
||||||
|
- ls[outer]->l_audit[cnt].bindflags
|
||||||
|
- = afct->objopen (ls[outer], LM_ID_BASE,
|
||||||
|
- &ls[outer]->l_audit[cnt].cookie);
|
||||||
|
-
|
||||||
|
- ls[outer]->l_audit_any_plt
|
||||||
|
- |= ls[outer]->l_audit[cnt].bindflags != 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- afct = afct->next;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ load_audit_modules (main_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep track of the currently loaded modules to count how many
|
401
SOURCES/glibc-rh1817513-2.patch
Normal file
401
SOURCES/glibc-rh1817513-2.patch
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
commit dce452dc5278f2985d21315721a6ba802537b862
|
||||||
|
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||||
|
Date: Thu Aug 2 23:49:19 2018 +0530
|
||||||
|
|
||||||
|
Rename the glibc.tune namespace to glibc.cpu
|
||||||
|
|
||||||
|
The glibc.tune namespace is vaguely named since it is a 'tunable', so
|
||||||
|
give it a more specific name that describes what it refers to. Rename
|
||||||
|
the tunable namespace to 'cpu' to more accurately reflect what it
|
||||||
|
encompasses. Also rename glibc.tune.cpu to glibc.cpu.name since
|
||||||
|
glibc.cpu.cpu is weird.
|
||||||
|
|
||||||
|
* NEWS: Mention the change.
|
||||||
|
* elf/dl-tunables.list: Rename tune namespace to cpu.
|
||||||
|
* sysdeps/powerpc/dl-tunables.list: Likewise.
|
||||||
|
* sysdeps/x86/dl-tunables.list: Likewise.
|
||||||
|
* sysdeps/aarch64/dl-tunables.list: Rename tune.cpu to
|
||||||
|
cpu.name.
|
||||||
|
* elf/dl-hwcaps.c (_dl_important_hwcaps): Adjust.
|
||||||
|
* elf/dl-hwcaps.h (GET_HWCAP_MASK): Likewise.
|
||||||
|
* manual/README.tunables: Likewise.
|
||||||
|
* manual/tunables.texi: Likewise.
|
||||||
|
* sysdeps/powerpc/cpu-features.c: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/aarch64/cpu-features.c
|
||||||
|
(init_cpu_features): Likewise.
|
||||||
|
* sysdeps/x86/cpu-features.c: Likewise.
|
||||||
|
* sysdeps/x86/cpu-features.h: Likewise.
|
||||||
|
* sysdeps/x86/cpu-tunables.c: Likewise.
|
||||||
|
* sysdeps/x86_64/Makefile: Likewise.
|
||||||
|
* sysdeps/x86/dl-cet.c: Likewise.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
manual/tunables.texi
|
||||||
|
(Earlier backport of non-temporal memcpy threshold.)
|
||||||
|
sysdeps/x86/Makefile
|
||||||
|
(Earlier CET backports.)
|
||||||
|
|
||||||
|
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
||||||
|
index 23482a88a1c9bca9..ecf00b457760e517 100644
|
||||||
|
--- a/elf/dl-hwcaps.c
|
||||||
|
+++ b/elf/dl-hwcaps.c
|
||||||
|
@@ -140,7 +140,7 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||||
|
string and bit like you can ignore an OS-supplied HWCAP bit. */
|
||||||
|
hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA;
|
||||||
|
#if HAVE_TUNABLES
|
||||||
|
- TUNABLE_SET (glibc, tune, hwcap_mask, uint64_t, hwcap_mask);
|
||||||
|
+ TUNABLE_SET (glibc, cpu, hwcap_mask, uint64_t, hwcap_mask);
|
||||||
|
#else
|
||||||
|
GLRO(dl_hwcap_mask) = hwcap_mask;
|
||||||
|
#endif
|
||||||
|
diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h
|
||||||
|
index 17f0da4c73772425..d69ee11dc27bb5e5 100644
|
||||||
|
--- a/elf/dl-hwcaps.h
|
||||||
|
+++ b/elf/dl-hwcaps.h
|
||||||
|
@@ -19,7 +19,7 @@
|
||||||
|
#include <elf/dl-tunables.h>
|
||||||
|
|
||||||
|
#if HAVE_TUNABLES
|
||||||
|
-# define GET_HWCAP_MASK() TUNABLE_GET (glibc, tune, hwcap_mask, uint64_t, NULL)
|
||||||
|
+# define GET_HWCAP_MASK() TUNABLE_GET (glibc, cpu, hwcap_mask, uint64_t, NULL)
|
||||||
|
#else
|
||||||
|
# ifdef SHARED
|
||||||
|
# define GET_HWCAP_MASK() GLRO(dl_hwcap_mask)
|
||||||
|
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
|
||||||
|
index 1ff6fcb6f24f93a8..b7cc79f8bfe0a7c6 100644
|
||||||
|
--- a/elf/dl-tunables.list
|
||||||
|
+++ b/elf/dl-tunables.list
|
||||||
|
@@ -91,7 +91,7 @@ glibc {
|
||||||
|
security_level: SXID_IGNORE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- tune {
|
||||||
|
+ cpu {
|
||||||
|
hwcap_mask {
|
||||||
|
type: UINT_64
|
||||||
|
env_alias: LD_HWCAP_MASK
|
||||||
|
diff --git a/manual/README.tunables b/manual/README.tunables
|
||||||
|
index 3967679f432a6378..f87a31a65e0a3455 100644
|
||||||
|
--- a/manual/README.tunables
|
||||||
|
+++ b/manual/README.tunables
|
||||||
|
@@ -105,11 +105,11 @@ where 'check' is the tunable name, 'int32_t' is the C type of the tunable and
|
||||||
|
To get and set tunables in a different namespace from that module, use the full
|
||||||
|
form of the macros as follows:
|
||||||
|
|
||||||
|
- val = TUNABLE_GET_FULL (glibc, tune, hwcap_mask, uint64_t, NULL)
|
||||||
|
+ val = TUNABLE_GET_FULL (glibc, cpu, hwcap_mask, uint64_t, NULL)
|
||||||
|
|
||||||
|
- TUNABLE_SET_FULL (glibc, tune, hwcap_mask, uint64_t, val)
|
||||||
|
+ TUNABLE_SET_FULL (glibc, cpu, hwcap_mask, uint64_t, val)
|
||||||
|
|
||||||
|
-where 'glibc' is the top namespace, 'tune' is the tunable namespace and the
|
||||||
|
+where 'glibc' is the top namespace, 'cpu' is the tunable namespace and the
|
||||||
|
remaining arguments are the same as the short form macros.
|
||||||
|
|
||||||
|
When TUNABLE_NAMESPACE is not defined in a module, TUNABLE_GET is equivalent to
|
||||||
|
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||||
|
index 3e1e519dff153b09..ef10d2872cfc244e 100644
|
||||||
|
--- a/manual/tunables.texi
|
||||||
|
+++ b/manual/tunables.texi
|
||||||
|
@@ -307,23 +307,23 @@ The default value of this tunable is @samp{3}.
|
||||||
|
@cindex non_temporal_threshold tunables
|
||||||
|
@cindex tunables, non_temporal_threshold
|
||||||
|
|
||||||
|
-@deftp {Tunable namespace} glibc.tune
|
||||||
|
+@deftp {Tunable namespace} glibc.cpu
|
||||||
|
Behavior of @theglibc{} can be tuned to assume specific hardware capabilities
|
||||||
|
-by setting the following tunables in the @code{tune} namespace:
|
||||||
|
+by setting the following tunables in the @code{cpu} namespace:
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.hwcap_mask
|
||||||
|
+@deftp Tunable glibc.cpu.hwcap_mask
|
||||||
|
This tunable supersedes the @env{LD_HWCAP_MASK} environment variable and is
|
||||||
|
identical in features.
|
||||||
|
|
||||||
|
The @code{AT_HWCAP} key in the Auxiliary Vector specifies instruction set
|
||||||
|
extensions available in the processor at runtime for some architectures. The
|
||||||
|
-@code{glibc.tune.hwcap_mask} tunable allows the user to mask out those
|
||||||
|
+@code{glibc.cpu.hwcap_mask} tunable allows the user to mask out those
|
||||||
|
capabilities at runtime, thus disabling use of those extensions.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.hwcaps
|
||||||
|
-The @code{glibc.tune.hwcaps=-xxx,yyy,-zzz...} tunable allows the user to
|
||||||
|
+@deftp Tunable glibc.cpu.hwcaps
|
||||||
|
+The @code{glibc.cpu.hwcaps=-xxx,yyy,-zzz...} tunable allows the user to
|
||||||
|
enable CPU/ARCH feature @code{yyy}, disable CPU/ARCH feature @code{xxx}
|
||||||
|
and @code{zzz} where the feature name is case-sensitive and has to match
|
||||||
|
the ones in @code{sysdeps/x86/cpu-features.h}.
|
||||||
|
@@ -331,8 +331,8 @@ the ones in @code{sysdeps/x86/cpu-features.h}.
|
||||||
|
This tunable is specific to i386 and x86-64.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.cached_memopt
|
||||||
|
-The @code{glibc.tune.cached_memopt=[0|1]} tunable allows the user to
|
||||||
|
+@deftp Tunable glibc.cpu.cached_memopt
|
||||||
|
+The @code{glibc.cpu.cached_memopt=[0|1]} tunable allows the user to
|
||||||
|
enable optimizations recommended for cacheable memory. If set to
|
||||||
|
@code{1}, @theglibc{} assumes that the process memory image consists
|
||||||
|
of cacheable (non-device) memory only. The default, @code{0},
|
||||||
|
@@ -341,8 +341,8 @@ indicates that the process may use device memory.
|
||||||
|
This tunable is specific to powerpc, powerpc64 and powerpc64le.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.cpu
|
||||||
|
-The @code{glibc.tune.cpu=xxx} tunable allows the user to tell @theglibc{} to
|
||||||
|
+@deftp Tunable glibc.cpu.name
|
||||||
|
+The @code{glibc.cpu.name=xxx} tunable allows the user to tell @theglibc{} to
|
||||||
|
assume that the CPU is @code{xxx} where xxx may have one of these values:
|
||||||
|
@code{generic}, @code{falkor}, @code{thunderxt88}, @code{thunderx2t99},
|
||||||
|
@code{thunderx2t99p1}.
|
||||||
|
@@ -350,20 +350,20 @@ assume that the CPU is @code{xxx} where xxx may have one of these values:
|
||||||
|
This tunable is specific to aarch64.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.x86_data_cache_size
|
||||||
|
-The @code{glibc.tune.x86_data_cache_size} tunable allows the user to set
|
||||||
|
+@deftp Tunable glibc.cpu.x86_data_cache_size
|
||||||
|
+The @code{glibc.cpu.x86_data_cache_size} tunable allows the user to set
|
||||||
|
data cache size in bytes for use in memory and string routines.
|
||||||
|
|
||||||
|
This tunable is specific to i386 and x86-64.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.x86_shared_cache_size
|
||||||
|
-The @code{glibc.tune.x86_shared_cache_size} tunable allows the user to
|
||||||
|
+@deftp Tunable glibc.cpu.x86_shared_cache_size
|
||||||
|
+The @code{glibc.cpu.x86_shared_cache_size} tunable allows the user to
|
||||||
|
set shared cache size in bytes for use in memory and string routines.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.x86_non_temporal_threshold
|
||||||
|
-The @code{glibc.tune.x86_non_temporal_threshold} tunable allows the user
|
||||||
|
+@deftp Tunable glibc.cpu.x86_non_temporal_threshold
|
||||||
|
+The @code{glibc.cpu.x86_non_temporal_threshold} tunable allows the user
|
||||||
|
to set threshold in bytes for non temporal store. Non temporal stores
|
||||||
|
give a hint to the hardware to move data directly to memory without
|
||||||
|
displacing other data from the cache. This tunable is used by some
|
||||||
|
@@ -373,8 +373,8 @@ like memmove and memcpy.
|
||||||
|
This tunable is specific to i386 and x86-64.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.x86_ibt
|
||||||
|
-The @code{glibc.tune.x86_ibt} tunable allows the user to control how
|
||||||
|
+@deftp Tunable glibc.cpu.x86_ibt
|
||||||
|
+The @code{glibc.cpu.x86_ibt} tunable allows the user to control how
|
||||||
|
indirect branch tracking (IBT) should be enabled. Accepted values are
|
||||||
|
@code{on}, @code{off}, and @code{permissive}. @code{on} always turns
|
||||||
|
on IBT regardless of whether IBT is enabled in the executable and its
|
||||||
|
@@ -386,8 +386,8 @@ IBT on non-CET executables and shared libraries.
|
||||||
|
This tunable is specific to i386 and x86-64.
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
-@deftp Tunable glibc.tune.x86_shstk
|
||||||
|
-The @code{glibc.tune.x86_shstk} tunable allows the user to control how
|
||||||
|
+@deftp Tunable glibc.cpu.x86_shstk
|
||||||
|
+The @code{glibc.cpu.x86_shstk} tunable allows the user to control how
|
||||||
|
the shadow stack (SHSTK) should be enabled. Accepted values are
|
||||||
|
@code{on}, @code{off}, and @code{permissive}. @code{on} always turns on
|
||||||
|
SHSTK regardless of whether SHSTK is enabled in the executable and its
|
||||||
|
diff --git a/sysdeps/aarch64/dl-tunables.list b/sysdeps/aarch64/dl-tunables.list
|
||||||
|
index f6a88168cc5ec7e6..cfcf940ebd15a9aa 100644
|
||||||
|
--- a/sysdeps/aarch64/dl-tunables.list
|
||||||
|
+++ b/sysdeps/aarch64/dl-tunables.list
|
||||||
|
@@ -17,8 +17,8 @@
|
||||||
|
# <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
glibc {
|
||||||
|
- tune {
|
||||||
|
- cpu {
|
||||||
|
+ cpu {
|
||||||
|
+ name {
|
||||||
|
type: STRING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/sysdeps/powerpc/cpu-features.c b/sysdeps/powerpc/cpu-features.c
|
||||||
|
index 955d4778a69db607..ad809b9815eb68f0 100644
|
||||||
|
--- a/sysdeps/powerpc/cpu-features.c
|
||||||
|
+++ b/sysdeps/powerpc/cpu-features.c
|
||||||
|
@@ -30,7 +30,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
tunables is enable, since for this case user can explicit disable
|
||||||
|
unaligned optimizations. */
|
||||||
|
#if HAVE_TUNABLES
|
||||||
|
- int32_t cached_memfunc = TUNABLE_GET (glibc, tune, cached_memopt, int32_t,
|
||||||
|
+ int32_t cached_memfunc = TUNABLE_GET (glibc, cpu, cached_memopt, int32_t,
|
||||||
|
NULL);
|
||||||
|
cpu_features->use_cached_memopt = (cached_memfunc > 0);
|
||||||
|
#else
|
||||||
|
diff --git a/sysdeps/powerpc/dl-tunables.list b/sysdeps/powerpc/dl-tunables.list
|
||||||
|
index d26636a16bfcd6d9..b3372555f75f8e38 100644
|
||||||
|
--- a/sysdeps/powerpc/dl-tunables.list
|
||||||
|
+++ b/sysdeps/powerpc/dl-tunables.list
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
# <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
glibc {
|
||||||
|
- tune {
|
||||||
|
+ cpu {
|
||||||
|
cached_memopt {
|
||||||
|
type: INT_32
|
||||||
|
minval: 0
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
|
||||||
|
index 39eba0186f55b5de..b4f348509eb1c6b3 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
|
||||||
|
@@ -57,7 +57,7 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
|
||||||
|
#if HAVE_TUNABLES
|
||||||
|
/* Get the tunable override. */
|
||||||
|
- const char *mcpu = TUNABLE_GET (glibc, tune, cpu, const char *, NULL);
|
||||||
|
+ const char *mcpu = TUNABLE_GET (glibc, cpu, name, const char *, NULL);
|
||||||
|
if (mcpu != NULL)
|
||||||
|
midr = get_midr_from_mcpu (mcpu);
|
||||||
|
#endif
|
||||||
|
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
|
||||||
|
index d5f821e0831997ac..a936134a577e42a5 100644
|
||||||
|
--- a/sysdeps/x86/Makefile
|
||||||
|
+++ b/sysdeps/x86/Makefile
|
||||||
|
@@ -84,21 +84,21 @@ LDFLAGS-tst-cet-legacy-mod-6c.so = -Wl,--enable-new-dtags,-z,nodelete
|
||||||
|
ifneq (no,$(have-tunables))
|
||||||
|
$(objpfx)tst-cet-legacy-4a: $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-4a.out: $(objpfx)tst-cet-legacy-mod-4.so
|
||||||
|
-tst-cet-legacy-4a-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=permissive
|
||||||
|
+tst-cet-legacy-4a-ENV = GLIBC_TUNABLES=glibc.cpu.x86_shstk=permissive
|
||||||
|
$(objpfx)tst-cet-legacy-4b: $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-4b.out: $(objpfx)tst-cet-legacy-mod-4.so
|
||||||
|
-tst-cet-legacy-4b-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=on
|
||||||
|
+tst-cet-legacy-4b-ENV = GLIBC_TUNABLES=glibc.cpu.x86_shstk=on
|
||||||
|
$(objpfx)tst-cet-legacy-4c: $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-4c.out: $(objpfx)tst-cet-legacy-mod-4.so
|
||||||
|
-tst-cet-legacy-4c-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=off
|
||||||
|
+tst-cet-legacy-4c-ENV = GLIBC_TUNABLES=glibc.cpu.x86_shstk=off
|
||||||
|
$(objpfx)tst-cet-legacy-5b: $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-5b.out: $(objpfx)tst-cet-legacy-mod-5a.so \
|
||||||
|
$(objpfx)tst-cet-legacy-mod-5b.so
|
||||||
|
-tst-cet-legacy-5b-ENV = GLIBC_TUNABLES=glibc.tune.x86_ibt=off:glibc.tune.x86_shstk=off
|
||||||
|
+tst-cet-legacy-5b-ENV = GLIBC_TUNABLES=glibc.cpu.x86_ibt=off:glibc.cpu.x86_shstk=off
|
||||||
|
$(objpfx)tst-cet-legacy-6b: $(libdl)
|
||||||
|
$(objpfx)tst-cet-legacy-6b.out: $(objpfx)tst-cet-legacy-mod-6a.so \
|
||||||
|
$(objpfx)tst-cet-legacy-mod-6b.so
|
||||||
|
-tst-cet-legacy-6b-ENV = GLIBC_TUNABLES=glibc.tune.x86_ibt=off:glibc.tune.x86_shstk=off
|
||||||
|
+tst-cet-legacy-6b-ENV = GLIBC_TUNABLES=glibc.cpu.x86_ibt=off:glibc.cpu.x86_shstk=off
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index 41f2d15fa5c8a756..3b268efbce627e6c 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
#include <libc-pointer-arith.h>
|
||||||
|
|
||||||
|
#if HAVE_TUNABLES
|
||||||
|
-# define TUNABLE_NAMESPACE tune
|
||||||
|
+# define TUNABLE_NAMESPACE cpu
|
||||||
|
# include <unistd.h> /* Get STDOUT_FILENO for _dl_printf. */
|
||||||
|
# include <elf/dl-tunables.h>
|
||||||
|
|
||||||
|
@@ -424,7 +424,7 @@ no_cpuid:
|
||||||
|
|
||||||
|
/* Reuse dl_platform, dl_hwcap and dl_hwcap_mask for x86. */
|
||||||
|
#if !HAVE_TUNABLES && defined SHARED
|
||||||
|
- /* The glibc.tune.hwcap_mask tunable is initialized already, so no need to do
|
||||||
|
+ /* The glibc.cpu.hwcap_mask tunable is initialized already, so no need to do
|
||||||
|
this. */
|
||||||
|
GLRO(dl_hwcap_mask) = HWCAP_IMPORTANT;
|
||||||
|
#endif
|
||||||
|
@@ -499,7 +499,7 @@ no_cpuid:
|
||||||
|
/* Disable IBT and/or SHSTK if they are enabled by kernel, but
|
||||||
|
disabled by environment variable:
|
||||||
|
|
||||||
|
- GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK
|
||||||
|
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
|
||||||
|
*/
|
||||||
|
unsigned int cet_feature = 0;
|
||||||
|
if (!HAS_CPU_FEATURE (IBT))
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
|
||||||
|
index 347a4b118d007fd8..4c6d08c709eea204 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.h
|
||||||
|
+++ b/sysdeps/x86/cpu-features.h
|
||||||
|
@@ -141,7 +141,7 @@ struct cpu_features
|
||||||
|
unsigned long int xsave_state_size;
|
||||||
|
/* The full state size for XSAVE when XSAVEC is disabled by
|
||||||
|
|
||||||
|
- GLIBC_TUNABLES=glibc.tune.hwcaps=-XSAVEC_Usable
|
||||||
|
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
|
||||||
|
*/
|
||||||
|
unsigned int xsave_state_full_size;
|
||||||
|
unsigned int feature[FEATURE_INDEX_MAX];
|
||||||
|
diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
|
||||||
|
index fad6726882fa7e2d..2e5d37753713e975 100644
|
||||||
|
--- a/sysdeps/x86/cpu-tunables.c
|
||||||
|
+++ b/sysdeps/x86/cpu-tunables.c
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#if HAVE_TUNABLES
|
||||||
|
-# define TUNABLE_NAMESPACE tune
|
||||||
|
+# define TUNABLE_NAMESPACE cpu
|
||||||
|
# include <stdbool.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <unistd.h> /* Get STDOUT_FILENO for _dl_printf. */
|
||||||
|
@@ -116,7 +116,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
|
||||||
|
the hardware which wasn't available when the selection was made.
|
||||||
|
The environment variable:
|
||||||
|
|
||||||
|
- GLIBC_TUNABLES=glibc.tune.hwcaps=-xxx,yyy,-zzz,....
|
||||||
|
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,-zzz,....
|
||||||
|
|
||||||
|
can be used to enable CPU/ARCH feature yyy, disable CPU/ARCH feature
|
||||||
|
yyy and zzz, where the feature name is case-sensitive and has to
|
||||||
|
diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
|
||||||
|
index ebc0d577e414c807..d481bddc27e5d7cc 100644
|
||||||
|
--- a/sysdeps/x86/dl-cet.c
|
||||||
|
+++ b/sysdeps/x86/dl-cet.c
|
||||||
|
@@ -72,7 +72,7 @@ dl_cet_check (struct link_map *m, const char *program)
|
||||||
|
/* Enable IBT and SHSTK only if they are enabled in executable.
|
||||||
|
NB: IBT and SHSTK may be disabled by environment variable:
|
||||||
|
|
||||||
|
- GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK
|
||||||
|
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
|
||||||
|
*/
|
||||||
|
enable_ibt &= (HAS_CPU_FEATURE (IBT)
|
||||||
|
&& (enable_ibt_type == cet_always_on
|
||||||
|
diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list
|
||||||
|
index 73886b1352316854..2a457d0eec9c3122 100644
|
||||||
|
--- a/sysdeps/x86/dl-tunables.list
|
||||||
|
+++ b/sysdeps/x86/dl-tunables.list
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
# <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
glibc {
|
||||||
|
- tune {
|
||||||
|
+ cpu {
|
||||||
|
hwcaps {
|
||||||
|
type: STRING
|
||||||
|
}
|
||||||
|
diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile
|
||||||
|
index 9f1562f1b25a2df5..d51cf03ac92ebcc2 100644
|
||||||
|
--- a/sysdeps/x86_64/Makefile
|
||||||
|
+++ b/sysdeps/x86_64/Makefile
|
||||||
|
@@ -57,7 +57,7 @@ modules-names += x86_64/tst-x86_64mod-1
|
||||||
|
LDFLAGS-tst-x86_64mod-1.so = -Wl,-soname,tst-x86_64mod-1.so
|
||||||
|
ifneq (no,$(have-tunables))
|
||||||
|
# Test the state size for XSAVE when XSAVEC is disabled.
|
||||||
|
-tst-x86_64-1-ENV = GLIBC_TUNABLES=glibc.tune.hwcaps=-XSAVEC_Usable
|
||||||
|
+tst-x86_64-1-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(objpfx)tst-x86_64-1: $(objpfx)x86_64/tst-x86_64mod-1.so
|
||||||
|
@@ -74,7 +74,7 @@ $(objpfx)tst-platform-1.out: $(objpfx)x86_64/tst-platformmod-2.so
|
||||||
|
# Turn off AVX512F_Usable and AVX2_Usable so that GLRO(dl_platform) is
|
||||||
|
# always set to x86_64.
|
||||||
|
tst-platform-1-ENV = LD_PRELOAD=$(objpfx)\$$PLATFORM/tst-platformmod-2.so \
|
||||||
|
- GLIBC_TUNABLES=glibc.tune.hwcaps=-AVX512F_Usable,-AVX2_Usable
|
||||||
|
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX512F_Usable,-AVX2_Usable
|
||||||
|
endif
|
||||||
|
|
||||||
|
tests += tst-audit3 tst-audit4 tst-audit5 tst-audit6 tst-audit7 \
|
179
SOURCES/glibc-rh1817513-20.patch
Normal file
179
SOURCES/glibc-rh1817513-20.patch
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
commit b3fbfe81961a1d14d7b54d1c9757e1f487073bcb
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Tue Feb 12 13:51:43 2019 +0100
|
||||||
|
|
||||||
|
elf: Test for LD_AUDIT module returning zero from la_version [BZ #24122]
|
||||||
|
|
||||||
|
This includes the original test case from commit
|
||||||
|
8e889c5da3c5981c5a46a93fec02de40131ac5a6 ("elf: Fix LD_AUDIT for
|
||||||
|
modules with invalid version (BZ#24122)).
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
(Different backport order of tests.)
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 6d1962b2e4deb871..4e1356b9172aee02 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -191,6 +191,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
|
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
||||||
|
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
||||||
|
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
||||||
|
+ tst-audit13 \
|
||||||
|
tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \
|
||||||
|
tst-dlopenfail tst-dlopenfail-2 \
|
||||||
|
tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen
|
||||||
|
@@ -300,7 +301,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
|
tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
|
||||||
|
tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
|
||||||
|
tst-absolute-zero-lib tst-big-note-lib \
|
||||||
|
- tst-sonamemove-linkmod1 \
|
||||||
|
+ tst-audit13mod1 tst-sonamemove-linkmod1 \
|
||||||
|
tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
|
||||||
|
tst-initlazyfailmod tst-finilazyfailmod \
|
||||||
|
tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
|
||||||
|
@@ -1428,6 +1429,10 @@ tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so
|
||||||
|
$(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so
|
||||||
|
LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map
|
||||||
|
|
||||||
|
+$(objpfx)tst-audit13.out: $(objpfx)tst-audit13mod1.so
|
||||||
|
+LDFLAGS-tst-audit13mod1.so = -Wl,-z,lazy
|
||||||
|
+tst-audit13-ENV = LD_AUDIT=$(objpfx)tst-audit13mod1.so
|
||||||
|
+
|
||||||
|
# tst-sonamemove links against an older implementation of the library.
|
||||||
|
LDFLAGS-tst-sonamemove-linkmod1.so = \
|
||||||
|
-Wl,--version-script=tst-sonamemove-linkmod1.map \
|
||||||
|
diff --git a/elf/tst-audit13.c b/elf/tst-audit13.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..6f587baf581ce32c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-audit13.c
|
||||||
|
@@ -0,0 +1,28 @@
|
||||||
|
+/* Check for invalid audit version (BZ#24122).
|
||||||
|
+ Copyright (C) 2019 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 <stdio.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ puts ("plt call");
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-audit13mod1.c b/elf/tst-audit13mod1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..cf017e235c7ae030
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-audit13mod1.c
|
||||||
|
@@ -0,0 +1,93 @@
|
||||||
|
+/* Check for invalid audit version (BZ#24122).
|
||||||
|
+ Copyright (C) 2019 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 <link.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+la_version (unsigned int version)
|
||||||
|
+{
|
||||||
|
+ /* The audit specification says that a version of 0 or a version
|
||||||
|
+ greater than any version supported by the dynamic loader shall
|
||||||
|
+ cause the module to be ignored. */
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+la_activity (uintptr_t *cookie, unsigned int flag)
|
||||||
|
+{
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+char *
|
||||||
|
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
|
||||||
|
+{
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t * cookie)
|
||||||
|
+{
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+la_preinit (uintptr_t * cookie)
|
||||||
|
+{
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+uintptr_t
|
||||||
|
+#if __ELF_NATIVE_CLASS == 32
|
||||||
|
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
||||||
|
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
|
||||||
|
+#else
|
||||||
|
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
|
||||||
|
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
|
||||||
|
+#endif
|
||||||
|
+{
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+la_objclose (uintptr_t * cookie)
|
||||||
|
+{
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <tst-audit.h>
|
||||||
|
+#if (!defined (pltenter) || !defined (pltexit) || !defined (La_regs) \
|
||||||
|
+ || !defined (La_retval) || !defined (int_retval))
|
||||||
|
+# error "architecture specific code needed in sysdeps/CPU/tst-audit.h"
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ElfW(Addr)
|
||||||
|
+pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
|
||||||
|
+ uintptr_t *defcook, La_regs *regs, unsigned int *flags,
|
||||||
|
+ const char *symname, long int *framesizep)
|
||||||
|
+{
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
|
||||||
|
+ uintptr_t *defcook, const La_regs *inregs, La_retval *outregs,
|
||||||
|
+ const char *symname)
|
||||||
|
+{
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+}
|
29
SOURCES/glibc-rh1817513-21.patch
Normal file
29
SOURCES/glibc-rh1817513-21.patch
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
commit 86140c6223b5d14d773cf3050ffd0d14977c2c2d
|
||||||
|
Author: Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Date: Wed Feb 13 13:34:24 2019 +0000
|
||||||
|
|
||||||
|
Avoid fall-through in test-container if execlp fails.
|
||||||
|
|
||||||
|
One of the implicit-fallthrough warnings from compiling glibc with
|
||||||
|
-Wextra appears to indicate an actual bug: the test-container code
|
||||||
|
could fall through inappropriately if execlp returns (which only
|
||||||
|
occurs on error). This patch adds appropriate error handling in this
|
||||||
|
case to avoid that fall-through.
|
||||||
|
|
||||||
|
Tested for x86_64.
|
||||||
|
|
||||||
|
* support/test-container.c (recursive_remove): Use FAIL_EXIT1 if
|
||||||
|
execlp returns.
|
||||||
|
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index 1d1aebeaf3412573..f0d9e3060e80bda5 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -361,6 +361,7 @@ recursive_remove (char *path)
|
||||||
|
case 0:
|
||||||
|
/* Child. */
|
||||||
|
execlp ("rm", "rm", "-rf", path, NULL);
|
||||||
|
+ FAIL_EXIT1 ("exec rm: %m");
|
||||||
|
default:
|
||||||
|
/* Parent. */
|
||||||
|
waitpid (child, &status, 0);
|
223
SOURCES/glibc-rh1817513-22.patch
Normal file
223
SOURCES/glibc-rh1817513-22.patch
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
commit 77b6f5534778b5403c87fa5415625aeb4c3cbf44
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Wed Jan 16 17:30:07 2019 +0000
|
||||||
|
|
||||||
|
linux: Assume clock_getres CLOCK_{PROCESS,THREAD}_CPUTIME_ID
|
||||||
|
|
||||||
|
The Linux 3.2 clock_getres kernel code (kernel/posix-cpu-timers.c)
|
||||||
|
issued for clock_getres CLOCK_PROCESS_CPUTIME_ID (process_cpu_clock_getres)
|
||||||
|
and CLOCK_THREAD_CPUTIME_ID (thread_cpu_clock_getres) call
|
||||||
|
posix_cpu_clock_getres. And it fails on check_clock only if an invalid
|
||||||
|
clock is used (not the case) or if we pass an invalid the pid/tid in
|
||||||
|
29 msb of clock_id (not the case either).
|
||||||
|
|
||||||
|
This patch assumes that clock_getres syscall always support
|
||||||
|
CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID, so there is no need
|
||||||
|
to fallback to hp-timing support for _SC_MONOTONIC_CLOCK neither to issue
|
||||||
|
the syscall to certify the clock_id is supported bt the kernel. This
|
||||||
|
allows simplify the sysconf support to always use the syscall.
|
||||||
|
|
||||||
|
it also removes ia64 itc drift check and assume kernel handles it correctly.
|
||||||
|
|
||||||
|
Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu.
|
||||||
|
|
||||||
|
* sysdeps/unix/sysv/linux/ia64/has_cpuclock.c: Remove file.
|
||||||
|
* sysdeps/unix/sysv/linux/ia64/sysconf.c: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/sysconf.c (has_cpuclock): Remove function.
|
||||||
|
(__sysconf): Assume kernel support for _SC_MONOTONIC_CLOCK,
|
||||||
|
_SC_CPUTIME, and _SC_THREAD_CPUTIME.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
sysdeps/unix/sysv/linux/ia64/has_cpuclock.c
|
||||||
|
sysdeps/unix/sysv/linux/ia64/sysconf.c
|
||||||
|
(Removal after copyright year update.)
|
||||||
|
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/ia64/has_cpuclock.c b/sysdeps/unix/sysv/linux/ia64/has_cpuclock.c
|
||||||
|
deleted file mode 100644
|
||||||
|
index 75f3ef9f4d1366fb..0000000000000000
|
||||||
|
--- a/sysdeps/unix/sysv/linux/ia64/has_cpuclock.c
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,51 +0,0 @@
|
||||||
|
-/* Copyright (C) 2000-2018 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 <errno.h>
|
||||||
|
-#include <fcntl.h>
|
||||||
|
-#include <unistd.h>
|
||||||
|
-#include <sys/stat.h>
|
||||||
|
-#include <sys/types.h>
|
||||||
|
-#include <not-cancel.h>
|
||||||
|
-
|
||||||
|
-static int itc_usable;
|
||||||
|
-
|
||||||
|
-static int
|
||||||
|
-has_cpuclock (void)
|
||||||
|
-{
|
||||||
|
- if (__builtin_expect (itc_usable == 0, 0))
|
||||||
|
- {
|
||||||
|
- int newval = 1;
|
||||||
|
- int fd = __open_nocancel ("/proc/sal/itc_drift", O_RDONLY);
|
||||||
|
- if (__builtin_expect (fd != -1, 1))
|
||||||
|
- {
|
||||||
|
- char buf[16];
|
||||||
|
- /* We expect the file to contain a single digit followed by
|
||||||
|
- a newline. If the format changes we better not rely on
|
||||||
|
- the file content. */
|
||||||
|
- if (__read_nocancel (fd, buf, sizeof buf) != 2
|
||||||
|
- || buf[0] != '0' || buf[1] != '\n')
|
||||||
|
- newval = -1;
|
||||||
|
-
|
||||||
|
- __close_nocancel_nostatus (fd);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- itc_usable = newval;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return itc_usable;
|
||||||
|
-}
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/ia64/sysconf.c b/sysdeps/unix/sysv/linux/ia64/sysconf.c
|
||||||
|
deleted file mode 100644
|
||||||
|
index 6c39db5a4af3e15a..0000000000000000
|
||||||
|
--- a/sysdeps/unix/sysv/linux/ia64/sysconf.c
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,30 +0,0 @@
|
||||||
|
-/* Get file-specific information about a file. Linux/ia64 version.
|
||||||
|
- Copyright (C) 2003-2018 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 <assert.h>
|
||||||
|
-#include <stdbool.h>
|
||||||
|
-#include <stdlib.h>
|
||||||
|
-#include <unistd.h>
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-#include "has_cpuclock.c"
|
||||||
|
-#define HAS_CPUCLOCK(name) (has_cpuclock () ? _POSIX_VERSION : -1)
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* Now the generic Linux version. */
|
||||||
|
-#include <sysdeps/unix/sysv/linux/sysconf.c>
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c
|
||||||
|
index 4e49ebaa7a25748c..6fab1601034e4724 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/sysconf.c
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/sysconf.c
|
||||||
|
@@ -35,34 +35,6 @@
|
||||||
|
static long int posix_sysconf (int name);
|
||||||
|
|
||||||
|
|
||||||
|
-#ifndef HAS_CPUCLOCK
|
||||||
|
-static long int
|
||||||
|
-has_cpuclock (int name)
|
||||||
|
-{
|
||||||
|
-# if defined __NR_clock_getres || HP_TIMING_AVAIL
|
||||||
|
- /* If we have HP_TIMING, we will fall back on that if the system
|
||||||
|
- call does not work, so we support it either way. */
|
||||||
|
-# if !HP_TIMING_AVAIL
|
||||||
|
- /* Check using the clock_getres system call. */
|
||||||
|
- struct timespec ts;
|
||||||
|
- INTERNAL_SYSCALL_DECL (err);
|
||||||
|
- int r = INTERNAL_SYSCALL (clock_getres, err, 2,
|
||||||
|
- (name == _SC_CPUTIME
|
||||||
|
- ? CLOCK_PROCESS_CPUTIME_ID
|
||||||
|
- : CLOCK_THREAD_CPUTIME_ID),
|
||||||
|
- &ts);
|
||||||
|
- if (INTERNAL_SYSCALL_ERROR_P (r, err))
|
||||||
|
- return -1;
|
||||||
|
-# endif
|
||||||
|
- return _POSIX_VERSION;
|
||||||
|
-# else
|
||||||
|
- return -1;
|
||||||
|
-# endif
|
||||||
|
-}
|
||||||
|
-# define HAS_CPUCLOCK(name) has_cpuclock (name)
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/* Get the value of the system variable NAME. */
|
||||||
|
long int
|
||||||
|
__sysconf (int name)
|
||||||
|
@@ -71,29 +43,20 @@ __sysconf (int name)
|
||||||
|
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
- struct rlimit rlimit;
|
||||||
|
-#ifdef __NR_clock_getres
|
||||||
|
case _SC_MONOTONIC_CLOCK:
|
||||||
|
- /* Check using the clock_getres system call. */
|
||||||
|
- {
|
||||||
|
- struct timespec ts;
|
||||||
|
- INTERNAL_SYSCALL_DECL (err);
|
||||||
|
- int r;
|
||||||
|
- r = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts);
|
||||||
|
- return INTERNAL_SYSCALL_ERROR_P (r, err) ? -1 : _POSIX_VERSION;
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
case _SC_CPUTIME:
|
||||||
|
case _SC_THREAD_CPUTIME:
|
||||||
|
- return HAS_CPUCLOCK (name);
|
||||||
|
+ return _POSIX_VERSION;
|
||||||
|
|
||||||
|
case _SC_ARG_MAX:
|
||||||
|
- /* Use getrlimit to get the stack limit. */
|
||||||
|
- if (__getrlimit (RLIMIT_STACK, &rlimit) == 0)
|
||||||
|
- return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4);
|
||||||
|
+ {
|
||||||
|
+ struct rlimit rlimit;
|
||||||
|
+ /* Use getrlimit to get the stack limit. */
|
||||||
|
+ if (__getrlimit (RLIMIT_STACK, &rlimit) == 0)
|
||||||
|
+ return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4);
|
||||||
|
|
||||||
|
- return legacy_ARG_MAX;
|
||||||
|
+ return legacy_ARG_MAX;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
case _SC_NGROUPS_MAX:
|
||||||
|
/* Try to read the information from the /proc/sys/kernel/ngroups_max
|
||||||
|
@@ -102,11 +65,14 @@ __sysconf (int name)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case _SC_SIGQUEUE_MAX:
|
||||||
|
- if (__getrlimit (RLIMIT_SIGPENDING, &rlimit) == 0)
|
||||||
|
- return rlimit.rlim_cur;
|
||||||
|
+ {
|
||||||
|
+ struct rlimit rlimit;
|
||||||
|
+ if (__getrlimit (RLIMIT_SIGPENDING, &rlimit) == 0)
|
||||||
|
+ return rlimit.rlim_cur;
|
||||||
|
|
||||||
|
- /* The /proc/sys/kernel/rtsig-max file contains the answer. */
|
||||||
|
- procfname = "/proc/sys/kernel/rtsig-max";
|
||||||
|
+ /* The /proc/sys/kernel/rtsig-max file contains the answer. */
|
||||||
|
+ procfname = "/proc/sys/kernel/rtsig-max";
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
211
SOURCES/glibc-rh1817513-23.patch
Normal file
211
SOURCES/glibc-rh1817513-23.patch
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
commit 359653aaacad463d916323f03c0ac3c47405aafa
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Wed Jan 16 18:10:56 2019 +0000
|
||||||
|
|
||||||
|
Do not use HP_TIMING_NOW for random bits
|
||||||
|
|
||||||
|
This patch removes the HP_TIMING_BITS usage for fast random bits and replace
|
||||||
|
with clock_gettime (CLOCK_MONOTONIC). It has unspecified starting time and
|
||||||
|
nano-second accuracy, so its randomness is significantly better than
|
||||||
|
gettimeofday.
|
||||||
|
|
||||||
|
Althoug it should incur in more overhead (specially for architecture that
|
||||||
|
support hp-timing), the symbol is also common implemented as a vDSO.
|
||||||
|
|
||||||
|
Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. I also
|
||||||
|
checked on a i686-gnu build.
|
||||||
|
|
||||||
|
* include/random-bits.h: New file.
|
||||||
|
* resolv/res_mkquery.c [HP_TIMING_AVAIL] (RANDOM_BITS,
|
||||||
|
(__res_context_mkquery): Remove usage hp-timing usage and replace with
|
||||||
|
random_bits.
|
||||||
|
* resolv/res_send.c [HP_TIMING_AVAIL] (nameserver_offset): Likewise.
|
||||||
|
* sysdeps/posix/tempname.c [HP_TIMING_AVAIL] (__gen_tempname):
|
||||||
|
Likewise.
|
||||||
|
|
||||||
|
diff --git a/include/random-bits.h b/include/random-bits.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..a0651a5a34f80a8d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/random-bits.h
|
||||||
|
@@ -0,0 +1,41 @@
|
||||||
|
+/* Fast pseudo-random bits based on clock_gettime.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#ifndef _RANDOM_BITS_H
|
||||||
|
+# define _RANDOM_BITS_H
|
||||||
|
+
|
||||||
|
+#include <time.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+
|
||||||
|
+/* Provides fast pseudo-random bits through clock_gettime. It has unspecified
|
||||||
|
+ starting time, nano-second accuracy, its randomness is significantly better
|
||||||
|
+ than gettimeofday, and for mostly architectures it is implemented through
|
||||||
|
+ vDSO instead of a syscall. Since the source is a system clock, the upper
|
||||||
|
+ bits will have less entropy. */
|
||||||
|
+static inline uint32_t
|
||||||
|
+random_bits (void)
|
||||||
|
+{
|
||||||
|
+ struct timespec tv;
|
||||||
|
+ __clock_gettime (CLOCK_MONOTONIC, &tv);
|
||||||
|
+ /* Shuffle the lower bits to minimize the clock bias. */
|
||||||
|
+ uint32_t ret = tv.tv_nsec ^ tv.tv_sec;
|
||||||
|
+ ret ^= (ret << 24) | (ret >> 8);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
|
||||||
|
index 213abeefadf7ece5..4471a8838b1de7ee 100644
|
||||||
|
--- a/resolv/res_mkquery.c
|
||||||
|
+++ b/resolv/res_mkquery.c
|
||||||
|
@@ -82,6 +82,7 @@
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
@@ -92,12 +93,7 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <shlib-compat.h>
|
||||||
|
-
|
||||||
|
-#include <hp-timing.h>
|
||||||
|
-#include <stdint.h>
|
||||||
|
-#if HP_TIMING_AVAIL
|
||||||
|
-# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; }
|
||||||
|
-#endif
|
||||||
|
+#include <random-bits.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
__res_context_mkquery (struct resolv_context *ctx, int op, const char *dname,
|
||||||
|
@@ -120,16 +116,7 @@ __res_context_mkquery (struct resolv_context *ctx, int op, const char *dname,
|
||||||
|
/* We randomize the IDs every time. The old code just incremented
|
||||||
|
by one after the initial randomization which still predictable if
|
||||||
|
the application does multiple requests. */
|
||||||
|
- int randombits;
|
||||||
|
-#ifdef RANDOM_BITS
|
||||||
|
- RANDOM_BITS (randombits);
|
||||||
|
-#else
|
||||||
|
- struct timeval tv;
|
||||||
|
- __gettimeofday (&tv, NULL);
|
||||||
|
- randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
- hp->id = randombits;
|
||||||
|
+ hp->id = random_bits ();
|
||||||
|
hp->opcode = op;
|
||||||
|
hp->rd = (ctx->resp->options & RES_RECURSE) != 0;
|
||||||
|
hp->rcode = NOERROR;
|
||||||
|
diff --git a/resolv/res_send.c b/resolv/res_send.c
|
||||||
|
index ac19627634281c2f..55e7fa438e7baac1 100644
|
||||||
|
--- a/resolv/res_send.c
|
||||||
|
+++ b/resolv/res_send.c
|
||||||
|
@@ -109,7 +109,7 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <kernel-features.h>
|
||||||
|
#include <libc-diag.h>
|
||||||
|
-#include <hp-timing.h>
|
||||||
|
+#include <random-bits.h>
|
||||||
|
|
||||||
|
#if PACKETSZ > 65536
|
||||||
|
#define MAXPACKET PACKETSZ
|
||||||
|
@@ -309,15 +309,7 @@ nameserver_offset (struct __res_state *statp)
|
||||||
|
if ((offset & 1) == 0)
|
||||||
|
{
|
||||||
|
/* Initialization is required. */
|
||||||
|
-#if HP_TIMING_AVAIL
|
||||||
|
- uint64_t ticks;
|
||||||
|
- HP_TIMING_NOW (ticks);
|
||||||
|
- offset = ticks;
|
||||||
|
-#else
|
||||||
|
- struct timeval tv;
|
||||||
|
- __gettimeofday (&tv, NULL);
|
||||||
|
- offset = ((tv.tv_sec << 8) ^ tv.tv_usec);
|
||||||
|
-#endif
|
||||||
|
+ offset = random_bits ();
|
||||||
|
/* The lowest bit is the most random. Preserve it. */
|
||||||
|
offset <<= 1;
|
||||||
|
|
||||||
|
diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c
|
||||||
|
index 432262a03b6ecc23..3d26f378021680ae 100644
|
||||||
|
--- a/sysdeps/posix/tempname.c
|
||||||
|
+++ b/sysdeps/posix/tempname.c
|
||||||
|
@@ -71,22 +71,15 @@
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _LIBC
|
||||||
|
-# include <hp-timing.h>
|
||||||
|
-# if HP_TIMING_AVAIL
|
||||||
|
-# define RANDOM_BITS(Var) \
|
||||||
|
- if (__glibc_unlikely (value == UINT64_C (0))) \
|
||||||
|
- { \
|
||||||
|
- /* If this is the first time this function is used initialize \
|
||||||
|
- the variable we accumulate the value in to some somewhat \
|
||||||
|
- random value. If we'd not do this programs at startup time \
|
||||||
|
- might have a reduced set of possible names, at least on slow \
|
||||||
|
- machines. */ \
|
||||||
|
- struct timeval tv; \
|
||||||
|
- __gettimeofday (&tv, NULL); \
|
||||||
|
- value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \
|
||||||
|
- } \
|
||||||
|
- HP_TIMING_NOW (Var)
|
||||||
|
-# endif
|
||||||
|
+# include <random-bits.h>
|
||||||
|
+# define RANDOM_BITS(Var) ((Var) = random_bits ())
|
||||||
|
+# else
|
||||||
|
+# define RANDOM_BITS(Var) \
|
||||||
|
+ { \
|
||||||
|
+ struct timeval tv; \
|
||||||
|
+ __gettimeofday (&tv, NULL); \
|
||||||
|
+ (Var) = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \
|
||||||
|
+ }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Use the widest available unsigned type if uint64_t is not
|
||||||
|
@@ -193,8 +186,7 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *XXXXXX;
|
||||||
|
- static uint64_t value;
|
||||||
|
- uint64_t random_time_bits;
|
||||||
|
+ uint64_t value;
|
||||||
|
unsigned int count;
|
||||||
|
int fd = -1;
|
||||||
|
int save_errno = errno;
|
||||||
|
@@ -227,16 +219,8 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
|
||||||
|
XXXXXX = &tmpl[len - 6 - suffixlen];
|
||||||
|
|
||||||
|
/* Get some more or less random data. */
|
||||||
|
-#ifdef RANDOM_BITS
|
||||||
|
- RANDOM_BITS (random_time_bits);
|
||||||
|
-#else
|
||||||
|
- {
|
||||||
|
- struct timeval tv;
|
||||||
|
- __gettimeofday (&tv, NULL);
|
||||||
|
- random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
- value += random_time_bits ^ __getpid ();
|
||||||
|
+ RANDOM_BITS (value);
|
||||||
|
+ value ^= (uint64_t)__getpid () << 32;
|
||||||
|
|
||||||
|
for (count = 0; count < attempts; value += 7777, ++count)
|
||||||
|
{
|
702
SOURCES/glibc-rh1817513-24.patch
Normal file
702
SOURCES/glibc-rh1817513-24.patch
Normal file
@ -0,0 +1,702 @@
|
|||||||
|
commit 1e372ded4f83362509c8672ff501cba871bb1edc
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Thu Jan 24 12:46:59 2019 +0000
|
||||||
|
|
||||||
|
Refactor hp-timing rtld usage
|
||||||
|
|
||||||
|
This patch refactor how hp-timing is used on loader code for statistics
|
||||||
|
report. The HP_TIMING_AVAIL and HP_SMALL_TIMING_AVAIL are removed and
|
||||||
|
HP_TIMING_INLINE is used instead to check for hp-timing avaliability.
|
||||||
|
For alpha, which only defines HP_SMALL_TIMING_AVAIL, the HP_TIMING_INLINE
|
||||||
|
is set iff for IS_IN(rtld).
|
||||||
|
|
||||||
|
Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. I also
|
||||||
|
checked the builds for all afected ABIs.
|
||||||
|
|
||||||
|
* benchtests/bench-timing.h: Replace HP_TIMING_AVAIL with
|
||||||
|
HP_TIMING_INLINE.
|
||||||
|
* nptl/descr.h: Likewise.
|
||||||
|
* elf/rtld.c (RLTD_TIMING_DECLARE, RTLD_TIMING_NOW, RTLD_TIMING_DIFF,
|
||||||
|
RTLD_TIMING_ACCUM_NT, RTLD_TIMING_SET): Define.
|
||||||
|
(dl_start_final_info, _dl_start_final, dl_main, print_statistics):
|
||||||
|
Abstract hp-timing usage with RTLD_* macros.
|
||||||
|
* sysdeps/alpha/hp-timing.h (HP_TIMING_INLINE): Define iff IS_IN(rtld).
|
||||||
|
(HP_TIMING_AVAIL, HP_SMALL_TIMING_AVAIL): Remove.
|
||||||
|
* sysdeps/generic/hp-timing.h (HP_TIMING_AVAIL, HP_SMALL_TIMING_AVAIL,
|
||||||
|
HP_TIMING_NONAVAIL): Likewise.
|
||||||
|
* sysdeps/ia64/hp-timing.h (HP_TIMING_AVAIL, HP_SMALL_TIMING_AVAIL):
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/powerpc/powerpc32/power4/hp-timing.h (HP_TIMING_AVAIL,
|
||||||
|
HP_SMALL_TIMING_AVAIL): Likewise.
|
||||||
|
* sysdeps/powerpc/powerpc64/hp-timing.h (HP_TIMING_AVAIL,
|
||||||
|
HP_SMALL_TIMING_AVAIL): Likewise.
|
||||||
|
* sysdeps/sparc/sparc32/sparcv9/hp-timing.h (HP_TIMING_AVAIL,
|
||||||
|
HP_SMALL_TIMING_AVAIL): Likewise.
|
||||||
|
* sysdeps/sparc/sparc64/hp-timing.h (HP_TIMING_AVAIL,
|
||||||
|
HP_SMALL_TIMING_AVAIL): Likewise.
|
||||||
|
* sysdeps/x86/hp-timing.h (HP_TIMING_AVAIL, HP_SMALL_TIMING_AVAIL):
|
||||||
|
Likewise.
|
||||||
|
* sysdeps/generic/hp-timing-common.h: Update comment with
|
||||||
|
HP_TIMING_AVAIL removal.
|
||||||
|
|
||||||
|
diff --git a/benchtests/bench-timing.h b/benchtests/bench-timing.h
|
||||||
|
index 96cde1e8be2e0c2f..8ba6be51d5b6d4e1 100644
|
||||||
|
--- a/benchtests/bench-timing.h
|
||||||
|
+++ b/benchtests/bench-timing.h
|
||||||
|
@@ -21,7 +21,7 @@
|
||||||
|
#include <hp-timing.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
-#if HP_TIMING_AVAIL && !defined USE_CLOCK_GETTIME
|
||||||
|
+#if HP_TIMING_INLINE && !defined USE_CLOCK_GETTIME
|
||||||
|
# define GL(x) _##x
|
||||||
|
# define GLRO(x) _##x
|
||||||
|
typedef hp_timing_t timing_t;
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index 375e0de8fa2e049e..ffbd8f4553bb3425 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -46,6 +46,49 @@
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
+/* Only enables rtld profiling for architectures which provides non generic
|
||||||
|
+ hp-timing support. The generic support requires either syscall
|
||||||
|
+ (clock_gettime), which will incur in extra overhead on loading time.
|
||||||
|
+ Using vDSO is also an option, but it will require extra support on loader
|
||||||
|
+ to setup the vDSO pointer before its usage. */
|
||||||
|
+#if HP_TIMING_INLINE
|
||||||
|
+# define RLTD_TIMING_DECLARE(var, classifier,...) \
|
||||||
|
+ classifier hp_timing_t var __VA_ARGS__
|
||||||
|
+# define RTLD_TIMING_VAR(var) RLTD_TIMING_DECLARE (var, )
|
||||||
|
+# define RTLD_TIMING_SET(var, value) (var) = (value)
|
||||||
|
+# define RTLD_TIMING_REF(var) &(var)
|
||||||
|
+
|
||||||
|
+static inline void
|
||||||
|
+rtld_timer_start (hp_timing_t *var)
|
||||||
|
+{
|
||||||
|
+ HP_TIMING_NOW (*var);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void
|
||||||
|
+rtld_timer_stop (hp_timing_t *var, hp_timing_t start)
|
||||||
|
+{
|
||||||
|
+ hp_timing_t stop;
|
||||||
|
+ HP_TIMING_NOW (stop);
|
||||||
|
+ HP_TIMING_DIFF (*var, start, stop);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void
|
||||||
|
+rtld_timer_accum (hp_timing_t *sum, hp_timing_t start)
|
||||||
|
+{
|
||||||
|
+ hp_timing_t stop;
|
||||||
|
+ rtld_timer_stop (&stop, start);
|
||||||
|
+ HP_TIMING_ACCUM_NT(*sum, stop);
|
||||||
|
+}
|
||||||
|
+#else
|
||||||
|
+# define RLTD_TIMING_DECLARE(var, classifier...)
|
||||||
|
+# define RTLD_TIMING_SET(var, value)
|
||||||
|
+# define RTLD_TIMING_VAR(var)
|
||||||
|
+# define RTLD_TIMING_REF(var) 0
|
||||||
|
+# define rtld_timer_start(var)
|
||||||
|
+# define rtld_timer_stop(var, start)
|
||||||
|
+# define rtld_timer_accum(sum, start)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Avoid PLT use for our local calls at startup. */
|
||||||
|
extern __typeof (__mempcpy) __mempcpy attribute_hidden;
|
||||||
|
|
||||||
|
@@ -62,7 +105,7 @@ static void print_missing_version (int errcode, const char *objname,
|
||||||
|
const char *errsting);
|
||||||
|
|
||||||
|
/* Print the various times we collected. */
|
||||||
|
-static void print_statistics (hp_timing_t *total_timep);
|
||||||
|
+static void print_statistics (const hp_timing_t *total_timep);
|
||||||
|
|
||||||
|
/* Add audit objects. */
|
||||||
|
static void process_dl_audit (char *str);
|
||||||
|
@@ -303,11 +346,9 @@ static struct libname_list _dl_rtld_libname;
|
||||||
|
static struct libname_list _dl_rtld_libname2;
|
||||||
|
|
||||||
|
/* Variable for statistics. */
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
-static hp_timing_t relocate_time;
|
||||||
|
-static hp_timing_t load_time attribute_relro;
|
||||||
|
-static hp_timing_t start_time attribute_relro;
|
||||||
|
-#endif
|
||||||
|
+RLTD_TIMING_DECLARE (relocate_time, static);
|
||||||
|
+RLTD_TIMING_DECLARE (load_time, static, attribute_relro);
|
||||||
|
+RLTD_TIMING_DECLARE (start_time, static, attribute_relro);
|
||||||
|
|
||||||
|
/* Additional definitions needed by TLS initialization. */
|
||||||
|
#ifdef TLS_INIT_HELPER
|
||||||
|
@@ -335,9 +376,7 @@ static ElfW(Addr) _dl_start_final (void *arg);
|
||||||
|
struct dl_start_final_info
|
||||||
|
{
|
||||||
|
struct link_map l;
|
||||||
|
-#if !defined HP_TIMING_NONAVAIL && HP_TIMING_INLINE
|
||||||
|
- hp_timing_t start_time;
|
||||||
|
-#endif
|
||||||
|
+ RTLD_TIMING_VAR (start_time);
|
||||||
|
};
|
||||||
|
static ElfW(Addr) _dl_start_final (void *arg,
|
||||||
|
struct dl_start_final_info *info);
|
||||||
|
@@ -371,16 +410,11 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
|
||||||
|
{
|
||||||
|
ElfW(Addr) start_addr;
|
||||||
|
|
||||||
|
- if (HP_SMALL_TIMING_AVAIL)
|
||||||
|
- {
|
||||||
|
- /* If it hasn't happen yet record the startup time. */
|
||||||
|
- if (! HP_TIMING_INLINE)
|
||||||
|
- HP_TIMING_NOW (start_time);
|
||||||
|
-#if !defined DONT_USE_BOOTSTRAP_MAP && !defined HP_TIMING_NONAVAIL
|
||||||
|
- else
|
||||||
|
- start_time = info->start_time;
|
||||||
|
+ /* If it hasn't happen yet record the startup time. */
|
||||||
|
+ rtld_timer_start (&start_time);
|
||||||
|
+#if !defined DONT_USE_BOOTSTRAP_MAP
|
||||||
|
+ RTLD_TIMING_SET (start_time, info->start_time);
|
||||||
|
#endif
|
||||||
|
- }
|
||||||
|
|
||||||
|
/* Transfer data about ourselves to the permanent link_map structure. */
|
||||||
|
#ifndef DONT_USE_BOOTSTRAP_MAP
|
||||||
|
@@ -412,27 +446,11 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
|
||||||
|
entry point on the same stack we entered on. */
|
||||||
|
start_addr = _dl_sysdep_start (arg, &dl_main);
|
||||||
|
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
- hp_timing_t rtld_total_time;
|
||||||
|
- if (HP_SMALL_TIMING_AVAIL)
|
||||||
|
- {
|
||||||
|
- hp_timing_t end_time;
|
||||||
|
-
|
||||||
|
- /* Get the current time. */
|
||||||
|
- HP_TIMING_NOW (end_time);
|
||||||
|
-
|
||||||
|
- /* Compute the difference. */
|
||||||
|
- HP_TIMING_DIFF (rtld_total_time, start_time, end_time);
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))
|
||||||
|
{
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
- print_statistics (&rtld_total_time);
|
||||||
|
-#else
|
||||||
|
- print_statistics (NULL);
|
||||||
|
-#endif
|
||||||
|
+ RTLD_TIMING_VAR (rtld_total_time);
|
||||||
|
+ rtld_timer_stop (&rtld_total_time, start_time);
|
||||||
|
+ print_statistics (RTLD_TIMING_REF(rtld_total_time));
|
||||||
|
}
|
||||||
|
|
||||||
|
return start_addr;
|
||||||
|
@@ -457,11 +475,10 @@ _dl_start (void *arg)
|
||||||
|
#define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
|
||||||
|
#include "dynamic-link.h"
|
||||||
|
|
||||||
|
- if (HP_TIMING_INLINE && HP_SMALL_TIMING_AVAIL)
|
||||||
|
#ifdef DONT_USE_BOOTSTRAP_MAP
|
||||||
|
- HP_TIMING_NOW (start_time);
|
||||||
|
+ rtld_timer_start (&start_time);
|
||||||
|
#else
|
||||||
|
- HP_TIMING_NOW (info.start_time);
|
||||||
|
+ rtld_timer_start (&info.start_time);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Partly clean the `bootstrap_map' structure up. Don't use
|
||||||
|
@@ -1078,11 +1095,6 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
|
unsigned int i;
|
||||||
|
bool prelinked = false;
|
||||||
|
bool rtld_is_main = false;
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
- hp_timing_t start;
|
||||||
|
- hp_timing_t stop;
|
||||||
|
- hp_timing_t diff;
|
||||||
|
-#endif
|
||||||
|
void *tcbp = NULL;
|
||||||
|
|
||||||
|
GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
|
||||||
|
@@ -1256,12 +1268,11 @@ of this helper program; chances are you did not intend to run this program.\n\
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- HP_TIMING_NOW (start);
|
||||||
|
+ RTLD_TIMING_VAR (start);
|
||||||
|
+ rtld_timer_start (&start);
|
||||||
|
_dl_map_object (NULL, rtld_progname, lt_executable, 0,
|
||||||
|
__RTLD_OPENEXEC, LM_ID_BASE);
|
||||||
|
- HP_TIMING_NOW (stop);
|
||||||
|
-
|
||||||
|
- HP_TIMING_DIFF (load_time, start, stop);
|
||||||
|
+ rtld_timer_stop (&load_time, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now the map for the main executable is available. */
|
||||||
|
@@ -1664,20 +1675,18 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
|
||||||
|
if (__glibc_unlikely (preloadlist != NULL))
|
||||||
|
{
|
||||||
|
- HP_TIMING_NOW (start);
|
||||||
|
+ RTLD_TIMING_VAR (start);
|
||||||
|
+ rtld_timer_start (&start);
|
||||||
|
npreloads += handle_preload_list (preloadlist, main_map, "LD_PRELOAD");
|
||||||
|
- HP_TIMING_NOW (stop);
|
||||||
|
- HP_TIMING_DIFF (diff, start, stop);
|
||||||
|
- HP_TIMING_ACCUM_NT (load_time, diff);
|
||||||
|
+ rtld_timer_accum (&load_time, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (__glibc_unlikely (preloadarg != NULL))
|
||||||
|
{
|
||||||
|
- HP_TIMING_NOW (start);
|
||||||
|
+ RTLD_TIMING_VAR (start);
|
||||||
|
+ rtld_timer_start (&start);
|
||||||
|
npreloads += handle_preload_list (preloadarg, main_map, "--preload");
|
||||||
|
- HP_TIMING_NOW (stop);
|
||||||
|
- HP_TIMING_DIFF (diff, start, stop);
|
||||||
|
- HP_TIMING_ACCUM_NT (load_time, diff);
|
||||||
|
+ rtld_timer_accum (&load_time, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There usually is no ld.so.preload file, it should only be used
|
||||||
|
@@ -1737,7 +1746,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
file[file_size - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
- HP_TIMING_NOW (start);
|
||||||
|
+ RTLD_TIMING_VAR (start);
|
||||||
|
+ rtld_timer_start (&start);
|
||||||
|
|
||||||
|
if (file != problem)
|
||||||
|
{
|
||||||
|
@@ -1755,9 +1765,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
npreloads += do_preload (p, main_map, preload_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
- HP_TIMING_NOW (stop);
|
||||||
|
- HP_TIMING_DIFF (diff, start, stop);
|
||||||
|
- HP_TIMING_ACCUM_NT (load_time, diff);
|
||||||
|
+ rtld_timer_accum (&load_time, start);
|
||||||
|
|
||||||
|
/* We don't need the file anymore. */
|
||||||
|
__munmap (file, file_size);
|
||||||
|
@@ -1781,11 +1789,12 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
/* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
|
||||||
|
specified some libraries to load, these are inserted before the actual
|
||||||
|
dependencies in the executable's searchlist for symbol resolution. */
|
||||||
|
- HP_TIMING_NOW (start);
|
||||||
|
- _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
|
||||||
|
- HP_TIMING_NOW (stop);
|
||||||
|
- HP_TIMING_DIFF (diff, start, stop);
|
||||||
|
- HP_TIMING_ACCUM_NT (load_time, diff);
|
||||||
|
+ {
|
||||||
|
+ RTLD_TIMING_VAR (start);
|
||||||
|
+ rtld_timer_start (&start);
|
||||||
|
+ _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
|
||||||
|
+ rtld_timer_accum (&load_time, start);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Mark all objects as being in the global scope. */
|
||||||
|
for (i = main_map->l_searchlist.r_nlist; i > 0; )
|
||||||
|
@@ -2178,12 +2187,10 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
|
||||||
|
{
|
||||||
|
ElfW(Rela) *conflict, *conflictend;
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
- hp_timing_t start;
|
||||||
|
- hp_timing_t stop;
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
- HP_TIMING_NOW (start);
|
||||||
|
+ RTLD_TIMING_VAR (start);
|
||||||
|
+ rtld_timer_start (&start);
|
||||||
|
+
|
||||||
|
assert (main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL);
|
||||||
|
conflict = (ElfW(Rela) *)
|
||||||
|
main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr;
|
||||||
|
@@ -2191,8 +2198,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
((char *) conflict
|
||||||
|
+ main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val);
|
||||||
|
_dl_resolve_conflicts (main_map, conflict, conflictend);
|
||||||
|
- HP_TIMING_NOW (stop);
|
||||||
|
- HP_TIMING_DIFF (relocate_time, start, stop);
|
||||||
|
+
|
||||||
|
+ rtld_timer_stop (&relocate_time, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2220,15 +2227,12 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
know that because it is self-contained). */
|
||||||
|
|
||||||
|
int consider_profiling = GLRO(dl_profile) != NULL;
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
- hp_timing_t start;
|
||||||
|
- hp_timing_t stop;
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
/* If we are profiling we also must do lazy reloaction. */
|
||||||
|
GLRO(dl_lazy) |= consider_profiling;
|
||||||
|
|
||||||
|
- HP_TIMING_NOW (start);
|
||||||
|
+ RTLD_TIMING_VAR (start);
|
||||||
|
+ rtld_timer_start (&start);
|
||||||
|
unsigned i = main_map->l_searchlist.r_nlist;
|
||||||
|
while (i-- > 0)
|
||||||
|
{
|
||||||
|
@@ -2255,9 +2259,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
if (l->l_tls_blocksize != 0 && tls_init_tp_called)
|
||||||
|
_dl_add_to_slotinfo (l, true);
|
||||||
|
}
|
||||||
|
- HP_TIMING_NOW (stop);
|
||||||
|
-
|
||||||
|
- HP_TIMING_DIFF (relocate_time, start, stop);
|
||||||
|
+ rtld_timer_stop (&relocate_time, start);
|
||||||
|
|
||||||
|
/* Now enable profiling if needed. Like the previous call,
|
||||||
|
this has to go here because the calls it makes should use the
|
||||||
|
@@ -2300,19 +2302,14 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
re-relocation, we might call a user-supplied function
|
||||||
|
(e.g. calloc from _dl_relocate_object) that uses TLS data. */
|
||||||
|
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
- hp_timing_t start;
|
||||||
|
- hp_timing_t stop;
|
||||||
|
- hp_timing_t add;
|
||||||
|
-#endif
|
||||||
|
+ RTLD_TIMING_VAR (start);
|
||||||
|
+ rtld_timer_start (&start);
|
||||||
|
|
||||||
|
- HP_TIMING_NOW (start);
|
||||||
|
/* Mark the link map as not yet relocated again. */
|
||||||
|
GL(dl_rtld_map).l_relocated = 0;
|
||||||
|
_dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
|
||||||
|
- HP_TIMING_NOW (stop);
|
||||||
|
- HP_TIMING_DIFF (add, start, stop);
|
||||||
|
- HP_TIMING_ACCUM_NT (relocate_time, add);
|
||||||
|
+
|
||||||
|
+ rtld_timer_accum (&relocate_time, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do any necessary cleanups for the startup OS interface code.
|
||||||
|
@@ -2744,46 +2741,51 @@ process_envvars (enum mode *modep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if HP_TIMING_INLINE
|
||||||
|
+static void
|
||||||
|
+print_statistics_item (const char *title, hp_timing_t time,
|
||||||
|
+ hp_timing_t total)
|
||||||
|
+{
|
||||||
|
+ char cycles[HP_TIMING_PRINT_SIZE];
|
||||||
|
+ HP_TIMING_PRINT (cycles, sizeof (cycles), time);
|
||||||
|
+
|
||||||
|
+ char relative[3 * sizeof (hp_timing_t) + 2];
|
||||||
|
+ char *cp = _itoa ((1000ULL * time) / total, relative + sizeof (relative),
|
||||||
|
+ 10, 0);
|
||||||
|
+ /* Sets the decimal point. */
|
||||||
|
+ char *wp = relative;
|
||||||
|
+ switch (relative + sizeof (relative) - cp)
|
||||||
|
+ {
|
||||||
|
+ case 3:
|
||||||
|
+ *wp++ = *cp++;
|
||||||
|
+ /* Fall through. */
|
||||||
|
+ case 2:
|
||||||
|
+ *wp++ = *cp++;
|
||||||
|
+ /* Fall through. */
|
||||||
|
+ case 1:
|
||||||
|
+ *wp++ = '.';
|
||||||
|
+ *wp++ = *cp++;
|
||||||
|
+ }
|
||||||
|
+ *wp = '\0';
|
||||||
|
+ _dl_debug_printf ("%s: %s cycles (%s%%)\n", title, cycles, relative);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* Print the various times we collected. */
|
||||||
|
static void
|
||||||
|
__attribute ((noinline))
|
||||||
|
-print_statistics (hp_timing_t *rtld_total_timep)
|
||||||
|
+print_statistics (const hp_timing_t *rtld_total_timep)
|
||||||
|
{
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
- char buf[200];
|
||||||
|
- char *cp;
|
||||||
|
- char *wp;
|
||||||
|
-
|
||||||
|
- /* Total time rtld used. */
|
||||||
|
- if (HP_SMALL_TIMING_AVAIL)
|
||||||
|
- {
|
||||||
|
- HP_TIMING_PRINT (buf, sizeof (buf), *rtld_total_timep);
|
||||||
|
- _dl_debug_printf ("\nruntime linker statistics:\n"
|
||||||
|
- " total startup time in dynamic loader: %s\n", buf);
|
||||||
|
-
|
||||||
|
- /* Print relocation statistics. */
|
||||||
|
- char pbuf[30];
|
||||||
|
- HP_TIMING_PRINT (buf, sizeof (buf), relocate_time);
|
||||||
|
- cp = _itoa ((1000ULL * relocate_time) / *rtld_total_timep,
|
||||||
|
- pbuf + sizeof (pbuf), 10, 0);
|
||||||
|
- wp = pbuf;
|
||||||
|
- switch (pbuf + sizeof (pbuf) - cp)
|
||||||
|
- {
|
||||||
|
- case 3:
|
||||||
|
- *wp++ = *cp++;
|
||||||
|
- /* Fall through. */
|
||||||
|
- case 2:
|
||||||
|
- *wp++ = *cp++;
|
||||||
|
- /* Fall through. */
|
||||||
|
- case 1:
|
||||||
|
- *wp++ = '.';
|
||||||
|
- *wp++ = *cp++;
|
||||||
|
- }
|
||||||
|
- *wp = '\0';
|
||||||
|
- _dl_debug_printf ("\
|
||||||
|
- time needed for relocation: %s (%s%%)\n", buf, pbuf);
|
||||||
|
- }
|
||||||
|
+#if HP_TIMING_INLINE
|
||||||
|
+ {
|
||||||
|
+ char cycles[HP_TIMING_PRINT_SIZE];
|
||||||
|
+ HP_TIMING_PRINT (cycles, sizeof (cycles), *rtld_total_timep);
|
||||||
|
+ _dl_debug_printf ("\nruntime linker statistics:\n"
|
||||||
|
+ " total startup time in dynamic loader: %s cycles\n",
|
||||||
|
+ cycles);
|
||||||
|
+ print_statistics_item (" time needed for relocation",
|
||||||
|
+ relocate_time, *rtld_total_timep);
|
||||||
|
+ }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned long int num_relative_relocations = 0;
|
||||||
|
@@ -2824,31 +2826,8 @@ print_statistics (hp_timing_t *rtld_total_timep)
|
||||||
|
GL(dl_num_cache_relocations),
|
||||||
|
num_relative_relocations);
|
||||||
|
|
||||||
|
-#ifndef HP_TIMING_NONAVAIL
|
||||||
|
- /* Time spend while loading the object and the dependencies. */
|
||||||
|
- if (HP_SMALL_TIMING_AVAIL)
|
||||||
|
- {
|
||||||
|
- char pbuf[30];
|
||||||
|
- HP_TIMING_PRINT (buf, sizeof (buf), load_time);
|
||||||
|
- cp = _itoa ((1000ULL * load_time) / *rtld_total_timep,
|
||||||
|
- pbuf + sizeof (pbuf), 10, 0);
|
||||||
|
- wp = pbuf;
|
||||||
|
- switch (pbuf + sizeof (pbuf) - cp)
|
||||||
|
- {
|
||||||
|
- case 3:
|
||||||
|
- *wp++ = *cp++;
|
||||||
|
- /* Fall through. */
|
||||||
|
- case 2:
|
||||||
|
- *wp++ = *cp++;
|
||||||
|
- /* Fall through. */
|
||||||
|
- case 1:
|
||||||
|
- *wp++ = '.';
|
||||||
|
- *wp++ = *cp++;
|
||||||
|
- }
|
||||||
|
- *wp = '\0';
|
||||||
|
- _dl_debug_printf ("\
|
||||||
|
- time needed to load objects: %s (%s%%)\n",
|
||||||
|
- buf, pbuf);
|
||||||
|
- }
|
||||||
|
+#if HP_TIMING_INLINE
|
||||||
|
+ print_statistics_item (" time needed to load objects",
|
||||||
|
+ load_time, *rtld_total_timep);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
diff --git a/nptl/descr.h b/nptl/descr.h
|
||||||
|
index c3b81d8b27839502..98ba730bfeb7e4dd 100644
|
||||||
|
--- a/nptl/descr.h
|
||||||
|
+++ b/nptl/descr.h
|
||||||
|
@@ -342,7 +342,7 @@ struct pthread
|
||||||
|
/* Lock for synchronizing setxid calls. */
|
||||||
|
unsigned int setxid_futex;
|
||||||
|
|
||||||
|
-#if HP_TIMING_AVAIL
|
||||||
|
+#if HP_TIMING_INLINE
|
||||||
|
hp_timing_t cpuclock_offset_ununsed;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diff --git a/sysdeps/alpha/hp-timing.h b/sysdeps/alpha/hp-timing.h
|
||||||
|
index 62284e003acbca64..d6b603e2c51d1688 100644
|
||||||
|
--- a/sysdeps/alpha/hp-timing.h
|
||||||
|
+++ b/sysdeps/alpha/hp-timing.h
|
||||||
|
@@ -17,16 +17,13 @@
|
||||||
|
License along with the GNU C Library. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
-#ifndef _HP_TIMING_H
|
||||||
|
-#define _HP_TIMING_H 1
|
||||||
|
+#ifndef _HP_TIMING_ALPHA_H
|
||||||
|
+#define _HP_TIMING_ALPHA_H 1
|
||||||
|
|
||||||
|
+#if IS_IN(rtld)
|
||||||
|
/* We always have the timestamp register, but it's got only a 4 second
|
||||||
|
range. Use it for ld.so profiling only. */
|
||||||
|
-#define HP_TIMING_AVAIL (0)
|
||||||
|
-#define HP_SMALL_TIMING_AVAIL (1)
|
||||||
|
-
|
||||||
|
-/* We indeed have inlined functions. */
|
||||||
|
-#define HP_TIMING_INLINE (1)
|
||||||
|
+# define HP_TIMING_INLINE (1)
|
||||||
|
|
||||||
|
/* We use 32 bit values for the times. */
|
||||||
|
typedef unsigned int hp_timing_t;
|
||||||
|
@@ -34,13 +31,16 @@ typedef unsigned int hp_timing_t;
|
||||||
|
/* The "rpcc" instruction returns a 32-bit counting half and a 32-bit
|
||||||
|
"virtual cycle counter displacement". Subtracting the two gives us
|
||||||
|
a virtual cycle count. */
|
||||||
|
-#define HP_TIMING_NOW(VAR) \
|
||||||
|
+# define HP_TIMING_NOW(VAR) \
|
||||||
|
do { \
|
||||||
|
unsigned long int x_; \
|
||||||
|
asm volatile ("rpcc %0" : "=r"(x_)); \
|
||||||
|
(VAR) = (int) (x_) - (int) (x_ >> 32); \
|
||||||
|
} while (0)
|
||||||
|
+# include <hp-timing-common.h>
|
||||||
|
|
||||||
|
-#include <hp-timing-common.h>
|
||||||
|
+#else
|
||||||
|
+# include <sysdeps/generic/hp-timing.h>
|
||||||
|
+#endif /* IS_IN(rtld) */
|
||||||
|
|
||||||
|
#endif /* hp-timing.h */
|
||||||
|
diff --git a/sysdeps/generic/hp-timing-common.h b/sysdeps/generic/hp-timing-common.h
|
||||||
|
index 505c6bf5d2ee9395..ce338c990bd9fccd 100644
|
||||||
|
--- a/sysdeps/generic/hp-timing-common.h
|
||||||
|
+++ b/sysdeps/generic/hp-timing-common.h
|
||||||
|
@@ -20,8 +20,6 @@
|
||||||
|
/* In case a platform supports timers in the hardware the following macros
|
||||||
|
and types must be defined:
|
||||||
|
|
||||||
|
- - HP_TIMING_AVAIL: test for availability.
|
||||||
|
-
|
||||||
|
- HP_TIMING_INLINE: this macro is non-zero if the functionality is not
|
||||||
|
implemented using function calls but instead uses some inlined code
|
||||||
|
which might simply consist of a few assembler instructions. We have to
|
||||||
|
@@ -47,16 +45,16 @@
|
||||||
|
/* Accumulate ADD into SUM. No attempt is made to be thread-safe. */
|
||||||
|
#define HP_TIMING_ACCUM_NT(Sum, Diff) ((Sum) += (Diff))
|
||||||
|
|
||||||
|
+#define HP_TIMING_PRINT_SIZE (3 * sizeof (hp_timing_t) + 1)
|
||||||
|
+
|
||||||
|
/* Write a decimal representation of the timing value into the given string. */
|
||||||
|
#define HP_TIMING_PRINT(Dest, Len, Val) \
|
||||||
|
do { \
|
||||||
|
- char __buf[20]; \
|
||||||
|
+ char __buf[HP_TIMING_PRINT_SIZE]; \
|
||||||
|
char *__dest = (Dest); \
|
||||||
|
size_t __len = (Len); \
|
||||||
|
char *__cp = _itoa ((Val), __buf + sizeof (__buf), 10, 0); \
|
||||||
|
size_t __cp_len = MIN (__buf + sizeof (__buf) - __cp, __len); \
|
||||||
|
memcpy (__dest, __cp, __cp_len); \
|
||||||
|
- memcpy (__dest + __cp_len, " cycles", \
|
||||||
|
- MIN (__len - __cp_len, sizeof (" cycles"))); \
|
||||||
|
__dest[__len - 1] = '\0'; \
|
||||||
|
} while (0)
|
||||||
|
diff --git a/sysdeps/generic/hp-timing.h b/sysdeps/generic/hp-timing.h
|
||||||
|
index e2c02c2bc0fd1564..97598099db29d69d 100644
|
||||||
|
--- a/sysdeps/generic/hp-timing.h
|
||||||
|
+++ b/sysdeps/generic/hp-timing.h
|
||||||
|
@@ -25,8 +25,6 @@
|
||||||
|
the system call might be too high. */
|
||||||
|
|
||||||
|
/* Provide dummy definitions. */
|
||||||
|
-#define HP_TIMING_AVAIL (0)
|
||||||
|
-#define HP_SMALL_TIMING_AVAIL (0)
|
||||||
|
#define HP_TIMING_INLINE (0)
|
||||||
|
typedef int hp_timing_t;
|
||||||
|
#define HP_TIMING_NOW(var)
|
||||||
|
@@ -34,7 +32,4 @@ typedef int hp_timing_t;
|
||||||
|
#define HP_TIMING_ACCUM_NT(Sum, Diff)
|
||||||
|
#define HP_TIMING_PRINT(Buf, Len, Val)
|
||||||
|
|
||||||
|
-/* Since this implementation is not available we tell the user about it. */
|
||||||
|
-#define HP_TIMING_NONAVAIL 1
|
||||||
|
-
|
||||||
|
#endif /* hp-timing.h */
|
||||||
|
diff --git a/sysdeps/ia64/hp-timing.h b/sysdeps/ia64/hp-timing.h
|
||||||
|
index d8d1d7bf2c21f6e6..5ebbbc45746d5cf2 100644
|
||||||
|
--- a/sysdeps/ia64/hp-timing.h
|
||||||
|
+++ b/sysdeps/ia64/hp-timing.h
|
||||||
|
@@ -20,10 +20,6 @@
|
||||||
|
#ifndef _HP_TIMING_H
|
||||||
|
#define _HP_TIMING_H 1
|
||||||
|
|
||||||
|
-/* We always assume having the timestamp register. */
|
||||||
|
-#define HP_TIMING_AVAIL (1)
|
||||||
|
-#define HP_SMALL_TIMING_AVAIL (1)
|
||||||
|
-
|
||||||
|
/* We indeed have inlined functions. */
|
||||||
|
#define HP_TIMING_INLINE (1)
|
||||||
|
|
||||||
|
diff --git a/sysdeps/powerpc/powerpc32/power4/hp-timing.h b/sysdeps/powerpc/powerpc32/power4/hp-timing.h
|
||||||
|
index 10efcac481349ee3..0e81f4fe6a46ab86 100644
|
||||||
|
--- a/sysdeps/powerpc/powerpc32/power4/hp-timing.h
|
||||||
|
+++ b/sysdeps/powerpc/powerpc32/power4/hp-timing.h
|
||||||
|
@@ -20,10 +20,6 @@
|
||||||
|
#ifndef _HP_TIMING_H
|
||||||
|
#define _HP_TIMING_H 1
|
||||||
|
|
||||||
|
-/* We always assume having the timestamp register. */
|
||||||
|
-#define HP_TIMING_AVAIL (1)
|
||||||
|
-#define HP_SMALL_TIMING_AVAIL (1)
|
||||||
|
-
|
||||||
|
/* We indeed have inlined functions. */
|
||||||
|
#define HP_TIMING_INLINE (1)
|
||||||
|
|
||||||
|
diff --git a/sysdeps/powerpc/powerpc64/hp-timing.h b/sysdeps/powerpc/powerpc64/hp-timing.h
|
||||||
|
index c0aa3642f6ff1a42..77fe5e85bb32c163 100644
|
||||||
|
--- a/sysdeps/powerpc/powerpc64/hp-timing.h
|
||||||
|
+++ b/sysdeps/powerpc/powerpc64/hp-timing.h
|
||||||
|
@@ -20,10 +20,6 @@
|
||||||
|
#ifndef _HP_TIMING_H
|
||||||
|
#define _HP_TIMING_H 1
|
||||||
|
|
||||||
|
-/* We always assume having the timestamp register. */
|
||||||
|
-#define HP_TIMING_AVAIL (1)
|
||||||
|
-#define HP_SMALL_TIMING_AVAIL (1)
|
||||||
|
-
|
||||||
|
/* We indeed have inlined functions. */
|
||||||
|
#define HP_TIMING_INLINE (1)
|
||||||
|
|
||||||
|
diff --git a/sysdeps/sparc/sparc32/sparcv9/hp-timing.h b/sysdeps/sparc/sparc32/sparcv9/hp-timing.h
|
||||||
|
index 42451966f6192bcb..aedf9c031a0daad9 100644
|
||||||
|
--- a/sysdeps/sparc/sparc32/sparcv9/hp-timing.h
|
||||||
|
+++ b/sysdeps/sparc/sparc32/sparcv9/hp-timing.h
|
||||||
|
@@ -20,8 +20,6 @@
|
||||||
|
#ifndef _HP_TIMING_H
|
||||||
|
#define _HP_TIMING_H 1
|
||||||
|
|
||||||
|
-#define HP_TIMING_AVAIL (1)
|
||||||
|
-#define HP_SMALL_TIMING_AVAIL (1)
|
||||||
|
#define HP_TIMING_INLINE (1)
|
||||||
|
|
||||||
|
typedef unsigned long long int hp_timing_t;
|
||||||
|
diff --git a/sysdeps/sparc/sparc64/hp-timing.h b/sysdeps/sparc/sparc64/hp-timing.h
|
||||||
|
index 66325641067e1198..ee22729063745944 100644
|
||||||
|
--- a/sysdeps/sparc/sparc64/hp-timing.h
|
||||||
|
+++ b/sysdeps/sparc/sparc64/hp-timing.h
|
||||||
|
@@ -20,8 +20,6 @@
|
||||||
|
#ifndef _HP_TIMING_H
|
||||||
|
#define _HP_TIMING_H 1
|
||||||
|
|
||||||
|
-#define HP_TIMING_AVAIL (1)
|
||||||
|
-#define HP_SMALL_TIMING_AVAIL (1)
|
||||||
|
#define HP_TIMING_INLINE (1)
|
||||||
|
|
||||||
|
typedef unsigned long int hp_timing_t;
|
||||||
|
diff --git a/sysdeps/x86/hp-timing.h b/sysdeps/x86/hp-timing.h
|
||||||
|
index 0aa6f5e3f83e0d34..4dbd2aa8af69f95e 100644
|
||||||
|
--- a/sysdeps/x86/hp-timing.h
|
||||||
|
+++ b/sysdeps/x86/hp-timing.h
|
||||||
|
@@ -22,10 +22,6 @@
|
||||||
|
#include <isa.h>
|
||||||
|
|
||||||
|
#if MINIMUM_ISA == 686 || MINIMUM_ISA == 8664
|
||||||
|
-/* We always assume having the timestamp register. */
|
||||||
|
-# define HP_TIMING_AVAIL (1)
|
||||||
|
-# define HP_SMALL_TIMING_AVAIL (1)
|
||||||
|
-
|
||||||
|
/* We indeed have inlined functions. */
|
||||||
|
# define HP_TIMING_INLINE (1)
|
||||||
|
|
113
SOURCES/glibc-rh1817513-25.patch
Normal file
113
SOURCES/glibc-rh1817513-25.patch
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
commit b2af6fb2ed23930c148bae382ca85fad4d1cf32e
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Tue Apr 30 16:11:57 2019 -0300
|
||||||
|
|
||||||
|
elf: Fix elf/tst-pldd with --enable-hardcoded-path-in-tests (BZ#24506)
|
||||||
|
|
||||||
|
The elf/tst-pldd (added by 1a4c27355e146 to fix BZ#18035) test does
|
||||||
|
not expect the hardcoded paths that are output by pldd when the test
|
||||||
|
is built with --enable-hardcoded-path-in-tests. Instead of showing
|
||||||
|
the ABI installed library names for loader and libc (such as
|
||||||
|
ld-linux-x86-64.so.2 and libc.so.6 for x86_64), pldd shows the default
|
||||||
|
built ld.so and libc.so.
|
||||||
|
|
||||||
|
It makes the tests fail with an invalid expected loader/libc name.
|
||||||
|
|
||||||
|
This patch fixes the elf-pldd test by adding the canonical ld.so and
|
||||||
|
libc.so names in the expected list of possible outputs when parsing
|
||||||
|
the result output from pldd. The test now handles both default
|
||||||
|
build and --enable-hardcoded-path-in-tests option.
|
||||||
|
|
||||||
|
Checked on x86_64-linux-gnu (built with and without
|
||||||
|
--enable-hardcoded-path-in-tests) and i686-linux-gnu.
|
||||||
|
|
||||||
|
* elf/tst-pldd.c (in_str_list): New function.
|
||||||
|
(do_test): Add default names for ld and libc as one option.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/tst-pldd.c
|
||||||
|
(Original backport uses spaces instead of tabs.)
|
||||||
|
|
||||||
|
diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c
|
||||||
|
index 0f51c95935ffb2cf..40abee9efb9e7484 100644
|
||||||
|
--- a/elf/tst-pldd.c
|
||||||
|
+++ b/elf/tst-pldd.c
|
||||||
|
@@ -20,7 +20,6 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
-#include <libgen.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <array_length.h>
|
||||||
|
@@ -39,6 +38,15 @@ target_process (void *arg)
|
||||||
|
/* The test runs in a container because pldd does not support tracing
|
||||||
|
a binary started by the loader iself (as with testrun.sh). */
|
||||||
|
|
||||||
|
+static bool
|
||||||
|
+in_str_list (const char *libname, const char *const strlist[])
|
||||||
|
+{
|
||||||
|
+ for (const char *const *str = strlist; *str != NULL; str++)
|
||||||
|
+ if (strcmp (libname, *str) == 0)
|
||||||
|
+ return true;
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
@@ -82,26 +90,32 @@ do_test (void)
|
||||||
|
{
|
||||||
|
/* Ignore vDSO. */
|
||||||
|
if (buffer[0] != '/')
|
||||||
|
- continue;
|
||||||
|
-
|
||||||
|
- /* Remove newline so baseline (buffer) can compare against the
|
||||||
|
- LD_SO and LIBC_SO macros unmodified. */
|
||||||
|
- if (buffer[strlen(buffer)-1] == '\n')
|
||||||
|
- buffer[strlen(buffer)-1] = '\0';
|
||||||
|
-
|
||||||
|
- if (strcmp (basename (buffer), LD_SO) == 0)
|
||||||
|
- {
|
||||||
|
- TEST_COMPARE (interpreter_found, false);
|
||||||
|
- interpreter_found = true;
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (strcmp (basename (buffer), LIBC_SO) == 0)
|
||||||
|
- {
|
||||||
|
- TEST_COMPARE (libc_found, false);
|
||||||
|
- libc_found = true;
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ /* Remove newline so baseline (buffer) can compare against the
|
||||||
|
+ LD_SO and LIBC_SO macros unmodified. */
|
||||||
|
+ if (buffer[strlen(buffer)-1] == '\n')
|
||||||
|
+ buffer[strlen(buffer)-1] = '\0';
|
||||||
|
+
|
||||||
|
+ const char *libname = basename (buffer);
|
||||||
|
+
|
||||||
|
+ /* It checks for default names in case of build configure with
|
||||||
|
+ --enable-hardcoded-path-in-tests (BZ #24506). */
|
||||||
|
+ if (in_str_list (libname,
|
||||||
|
+ (const char *const []) { "ld.so", LD_SO, NULL }))
|
||||||
|
+ {
|
||||||
|
+ TEST_COMPARE (interpreter_found, false);
|
||||||
|
+ interpreter_found = true;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (in_str_list (libname,
|
||||||
|
+ (const char *const []) { "libc.so", LIBC_SO, NULL }))
|
||||||
|
+ {
|
||||||
|
+ TEST_COMPARE (libc_found, false);
|
||||||
|
+ libc_found = true;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
TEST_COMPARE (interpreter_found, true);
|
||||||
|
TEST_COMPARE (libc_found, true);
|
54
SOURCES/glibc-rh1817513-26.patch
Normal file
54
SOURCES/glibc-rh1817513-26.patch
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
commit da2b83ef6ba6f4c974664f69e715cc85b9173938
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Mon May 13 13:13:46 2019 -0300
|
||||||
|
|
||||||
|
elf: Fix tst-pldd for non-default --prefix and/or --bindir (BZ#24544)
|
||||||
|
|
||||||
|
Use a new libsupport support_bindir_prefix instead of a hardcoded
|
||||||
|
/usr/bin to create the pldd path on container directory.
|
||||||
|
|
||||||
|
Checked on x86_64-linux-gnu with default and non-default --prefix and
|
||||||
|
--bindir paths, as well with --enable-hardcoded-path-in-tests.
|
||||||
|
|
||||||
|
[BZ #24544]
|
||||||
|
* elf/tst-pldd.c (do_test): Use support_bindir_prefix instead of
|
||||||
|
pre-defined value.
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c
|
||||||
|
index 40abee9efb9e7484..e2de31282a131166 100644
|
||||||
|
--- a/elf/tst-pldd.c
|
||||||
|
+++ b/elf/tst-pldd.c
|
||||||
|
@@ -18,6 +18,7 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
@@ -28,6 +29,7 @@
|
||||||
|
#include <support/subprocess.h>
|
||||||
|
#include <support/capture_subprocess.h>
|
||||||
|
#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
target_process (void *arg)
|
||||||
|
@@ -60,12 +62,14 @@ do_test (void)
|
||||||
|
char pid[3 * sizeof (uint32_t) + 1];
|
||||||
|
snprintf (pid, array_length (pid), "%d", target.pid);
|
||||||
|
|
||||||
|
- const char prog[] = "/usr/bin/pldd";
|
||||||
|
+ char *prog = xasprintf ("%s/pldd", support_bindir_prefix);
|
||||||
|
|
||||||
|
pldd = support_capture_subprogram (prog,
|
||||||
|
(char *const []) { (char *) prog, pid, NULL });
|
||||||
|
|
||||||
|
support_capture_subprocess_check (&pldd, "pldd", 0, sc_allow_stdout);
|
||||||
|
+
|
||||||
|
+ free (prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check 'pldd' output. The test is expected to be linked against only
|
49
SOURCES/glibc-rh1817513-27.patch
Normal file
49
SOURCES/glibc-rh1817513-27.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
commit 75c51570c710aa9c6df6b7a1e131392e1408c63f
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon May 20 21:08:40 2019 +0200
|
||||||
|
|
||||||
|
support: Expose sbindir as support_sbindir_prefix
|
||||||
|
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 6afaa6836c944398..65b16299573af1ed 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -178,6 +178,7 @@ CFLAGS-support_paths.c = \
|
||||||
|
-DINSTDIR_PATH=\"$(prefix)\" \
|
||||||
|
-DLIBDIR_PATH=\"$(libdir)\" \
|
||||||
|
-DBINDIR_PATH=\"$(bindir)\" \
|
||||||
|
+ -DSBINDIR_PATH=\"$(sbindir)\" \
|
||||||
|
-DROOTSBINDIR_PATH=\"$(rootsbindir)\"
|
||||||
|
|
||||||
|
ifeq (,$(CXX))
|
||||||
|
diff --git a/support/support.h b/support/support.h
|
||||||
|
index 97d142e9b6f68188..121cc9e9b7c98ca6 100644
|
||||||
|
--- a/support/support.h
|
||||||
|
+++ b/support/support.h
|
||||||
|
@@ -109,6 +109,8 @@ extern const char support_libdir_prefix[];
|
||||||
|
/* Corresponds to the install's bin/ directory. */
|
||||||
|
extern const char support_bindir_prefix[];
|
||||||
|
/* Corresponds to the install's sbin/ directory. */
|
||||||
|
+extern const char support_sbindir_prefix[];
|
||||||
|
+/* Corresponds to the install's sbin/ directory (without prefix). */
|
||||||
|
extern const char support_install_rootsbindir[];
|
||||||
|
|
||||||
|
extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *,
|
||||||
|
diff --git a/support/support_paths.c b/support/support_paths.c
|
||||||
|
index a37a0720dc7339f0..eb2390227433aa70 100644
|
||||||
|
--- a/support/support_paths.c
|
||||||
|
+++ b/support/support_paths.c
|
||||||
|
@@ -65,6 +65,13 @@ const char support_bindir_prefix[] = BINDIR_PATH;
|
||||||
|
# error please -DBINDIR_PATH=something in the Makefile
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifdef SBINDIR_PATH
|
||||||
|
+/* Corresponds to the install's bin/ directory. */
|
||||||
|
+const char support_sbindir_prefix[] = SBINDIR_PATH;
|
||||||
|
+#else
|
||||||
|
+# error please -DSBINDIR_PATH=something in the Makefile
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#ifdef ROOTSBINDIR_PATH
|
||||||
|
/* Corresponds to the install's sbin/ directory. */
|
||||||
|
const char support_install_rootsbindir[] = ROOTSBINDIR_PATH;
|
58
SOURCES/glibc-rh1817513-28.patch
Normal file
58
SOURCES/glibc-rh1817513-28.patch
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
commit d039da1c00e01f8d3c3d74f439a971eb73e3045e
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Wed Jun 26 15:07:18 2019 -0700
|
||||||
|
|
||||||
|
x86: Add sysdeps/x86/dl-lookupcfg.h
|
||||||
|
|
||||||
|
Since sysdeps/i386/dl-lookupcfg.h and sysdeps/x86_64/dl-lookupcfg.h are
|
||||||
|
identical, we can replace them with sysdeps/x86/dl-lookupcfg.h.
|
||||||
|
|
||||||
|
* sysdeps/i386/dl-lookupcfg.h: Moved to ...
|
||||||
|
* sysdeps/x86/dl-lookupcfg.h: Here.
|
||||||
|
* sysdeps/x86_64/dl-lookupcfg.h: Removed.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
sysdeps/x86_64/dl-lookupcfg.h
|
||||||
|
(Removal after copyright year update.)
|
||||||
|
|
||||||
|
diff --git a/sysdeps/i386/dl-lookupcfg.h b/sysdeps/x86/dl-lookupcfg.h
|
||||||
|
similarity index 100%
|
||||||
|
rename from sysdeps/i386/dl-lookupcfg.h
|
||||||
|
rename to sysdeps/x86/dl-lookupcfg.h
|
||||||
|
diff --git a/sysdeps/x86_64/dl-lookupcfg.h b/sysdeps/x86_64/dl-lookupcfg.h
|
||||||
|
deleted file mode 100644
|
||||||
|
index 5399cf25abde592d..0000000000000000
|
||||||
|
--- a/sysdeps/x86_64/dl-lookupcfg.h
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,31 +0,0 @@
|
||||||
|
-/* Configuration of lookup functions.
|
||||||
|
- Copyright (C) 2005-2018 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/>. */
|
||||||
|
-
|
||||||
|
-#define DL_UNMAP_IS_SPECIAL
|
||||||
|
-
|
||||||
|
-#include_next <dl-lookupcfg.h>
|
||||||
|
-
|
||||||
|
-/* Address of protected data defined in the shared library may be
|
||||||
|
- external due to copy relocation. */
|
||||||
|
-#define DL_EXTERN_PROTECTED_DATA
|
||||||
|
-
|
||||||
|
-struct link_map;
|
||||||
|
-
|
||||||
|
-extern void _dl_unmap (struct link_map *map) attribute_hidden;
|
||||||
|
-
|
||||||
|
-#define DL_UNMAP(map) _dl_unmap (map)
|
109
SOURCES/glibc-rh1817513-29.patch
Normal file
109
SOURCES/glibc-rh1817513-29.patch
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
commit 23d2e5faf0bca6d9b31bef4aa162b95ee64cbfc6
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Aug 15 14:37:50 2019 +0200
|
||||||
|
|
||||||
|
elf: Self-dlopen failure with explict loader invocation [BZ #24900]
|
||||||
|
|
||||||
|
In case of an explicit loader invocation, ld.so essentially performs
|
||||||
|
a dlopen call to load the main executable. Since the pathname of
|
||||||
|
the executable is known at this point, it gets stored in the link
|
||||||
|
map. In regular mode, the pathname is not known and "" is used
|
||||||
|
instead.
|
||||||
|
|
||||||
|
As a result, if a program calls dlopen on the pathname of the main
|
||||||
|
program, the dlopen call succeeds and returns a handle for the main
|
||||||
|
map. This results in an unnecessary difference between glibc
|
||||||
|
testing (without --enable-hardcoded-path-in-tests) and production
|
||||||
|
usage.
|
||||||
|
|
||||||
|
This commit discards the names when building the link map in
|
||||||
|
_dl_new_object for the main executable, but it still determines
|
||||||
|
the origin at this point in case of an explict loader invocation.
|
||||||
|
The reason is that the specified pathname has to be used; the kernel
|
||||||
|
has a different notion of the main executable.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
elf/tst-dlopen-aout.c
|
||||||
|
(Differences due to the complicated history of the test.
|
||||||
|
The new test elf/tst-dlopen-aout-container is not backported
|
||||||
|
here.)
|
||||||
|
|
||||||
|
diff --git a/elf/dl-object.c b/elf/dl-object.c
|
||||||
|
index b37bcc1295f475f6..f6544a8fec45bdce 100644
|
||||||
|
--- a/elf/dl-object.c
|
||||||
|
+++ b/elf/dl-object.c
|
||||||
|
@@ -57,14 +57,30 @@ struct link_map *
|
||||||
|
_dl_new_object (char *realname, const char *libname, int type,
|
||||||
|
struct link_map *loader, int mode, Lmid_t nsid)
|
||||||
|
{
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ unsigned int naudit;
|
||||||
|
+ if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
|
||||||
|
+ {
|
||||||
|
+ assert (type == lt_executable);
|
||||||
|
+ assert (nsid == LM_ID_BASE);
|
||||||
|
+
|
||||||
|
+ /* Ignore the specified libname for the main executable. It is
|
||||||
|
+ only known with an explicit loader invocation. */
|
||||||
|
+ libname = "";
|
||||||
|
+
|
||||||
|
+ /* We create the map for the executable before we know whether
|
||||||
|
+ we have auditing libraries and if yes, how many. Assume the
|
||||||
|
+ worst. */
|
||||||
|
+ naudit = DL_NNS;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ naudit = GLRO (dl_naudit);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
size_t libname_len = strlen (libname) + 1;
|
||||||
|
struct link_map *new;
|
||||||
|
struct libname_list *newname;
|
||||||
|
#ifdef SHARED
|
||||||
|
- /* We create the map for the executable before we know whether we have
|
||||||
|
- auditing libraries and if yes, how many. Assume the worst. */
|
||||||
|
- unsigned int naudit = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC)
|
||||||
|
- ? DL_NNS : 0);
|
||||||
|
size_t audit_space = naudit * sizeof (new->l_audit[0]);
|
||||||
|
#else
|
||||||
|
# define audit_space 0
|
||||||
|
@@ -91,8 +107,20 @@ _dl_new_object (char *realname, const char *libname, int type,
|
||||||
|
and won't get dumped during core file generation. Therefore to assist
|
||||||
|
gdb and to create more self-contained core files we adjust l_name to
|
||||||
|
point at the newly allocated copy (which will get dumped) instead of
|
||||||
|
- the ld.so rodata copy. */
|
||||||
|
- new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;
|
||||||
|
+ the ld.so rodata copy.
|
||||||
|
+
|
||||||
|
+ Furthermore, in case of explicit loader invocation, discard the
|
||||||
|
+ name of the main executable, to match the regular behavior, where
|
||||||
|
+ name of the executable is not known. */
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ if (*realname != '\0' && (mode & __RTLD_OPENEXEC) == 0)
|
||||||
|
+#else
|
||||||
|
+ if (*realname != '\0')
|
||||||
|
+#endif
|
||||||
|
+ new->l_name = realname;
|
||||||
|
+ else
|
||||||
|
+ new->l_name = (char *) newname->name + libname_len - 1;
|
||||||
|
+
|
||||||
|
new->l_type = type;
|
||||||
|
/* If we set the bit now since we know it is never used we avoid
|
||||||
|
dirtying the cache line later. */
|
||||||
|
@@ -149,7 +177,14 @@ _dl_new_object (char *realname, const char *libname, int type,
|
||||||
|
|
||||||
|
new->l_local_scope[0] = &new->l_searchlist;
|
||||||
|
|
||||||
|
- /* Don't try to find the origin for the main map which has the name "". */
|
||||||
|
+ /* Determine the origin. If allocating the link map for the main
|
||||||
|
+ executable, the realname is not known and "". In this case, the
|
||||||
|
+ origin needs to be determined by other means. However, in case
|
||||||
|
+ of an explicit loader invocation, the pathname of the main
|
||||||
|
+ executable is known and needs to be processed here: From the
|
||||||
|
+ point of view of the kernel, the main executable is the
|
||||||
|
+ dynamic loader, and this would lead to a computation of the wrong
|
||||||
|
+ origin. */
|
||||||
|
if (realname[0] != '\0')
|
||||||
|
{
|
||||||
|
size_t realname_len = strlen (realname) + 1;
|
56
SOURCES/glibc-rh1817513-3.patch
Normal file
56
SOURCES/glibc-rh1817513-3.patch
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
commit ae67f2e562603a0b58f59aef4f31aa33de05ba88
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Fri Aug 3 06:40:48 2018 -0700
|
||||||
|
|
||||||
|
x86: Cleanup cpu-features-offsets.sym
|
||||||
|
|
||||||
|
Remove the unused macros. There is no code changes in libc.so nor
|
||||||
|
ld.so on i686 and x86-64.
|
||||||
|
|
||||||
|
* sysdeps/x86/cpu-features-offsets.sym
|
||||||
|
(rtld_global_ro_offsetof): Removed.
|
||||||
|
(CPU_FEATURES_SIZE): Likewise.
|
||||||
|
(CPUID_OFFSET): Likewise.
|
||||||
|
(CPUID_SIZE): Likewise.
|
||||||
|
(CPUID_EAX_OFFSET): Likewise.
|
||||||
|
(CPUID_EBX_OFFSET): Likewise.
|
||||||
|
(CPUID_ECX_OFFSET): Likewise.
|
||||||
|
(CPUID_EDX_OFFSET): Likewise.
|
||||||
|
(FAMILY_OFFSET): Likewise.
|
||||||
|
(MODEL_OFFSET): Likewise.
|
||||||
|
(FEATURE_OFFSET): Likewise.
|
||||||
|
(FEATURE_SIZ): Likewise.
|
||||||
|
(COMMON_CPUID_INDEX_1): Likewise.
|
||||||
|
(COMMON_CPUID_INDEX_7): Likewise.
|
||||||
|
(FEATURE_INDEX_1): Likewise.
|
||||||
|
(RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET): Updated.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features-offsets.sym b/sysdeps/x86/cpu-features-offsets.sym
|
||||||
|
index 33dd094e37f0fec7..6d03cea8e8fcdc36 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features-offsets.sym
|
||||||
|
+++ b/sysdeps/x86/cpu-features-offsets.sym
|
||||||
|
@@ -2,23 +2,5 @@
|
||||||
|
|
||||||
|
#include <ldsodefs.h>
|
||||||
|
|
||||||
|
-#define rtld_global_ro_offsetof(mem) offsetof (struct rtld_global_ro, mem)
|
||||||
|
-
|
||||||
|
-RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET rtld_global_ro_offsetof (_dl_x86_cpu_features)
|
||||||
|
-
|
||||||
|
-CPU_FEATURES_SIZE sizeof (struct cpu_features)
|
||||||
|
-CPUID_OFFSET offsetof (struct cpu_features, cpuid)
|
||||||
|
-CPUID_SIZE sizeof (struct cpuid_registers)
|
||||||
|
-CPUID_EAX_OFFSET offsetof (struct cpuid_registers, eax)
|
||||||
|
-CPUID_EBX_OFFSET offsetof (struct cpuid_registers, ebx)
|
||||||
|
-CPUID_ECX_OFFSET offsetof (struct cpuid_registers, ecx)
|
||||||
|
-CPUID_EDX_OFFSET offsetof (struct cpuid_registers, edx)
|
||||||
|
-FAMILY_OFFSET offsetof (struct cpu_features, family)
|
||||||
|
-MODEL_OFFSET offsetof (struct cpu_features, model)
|
||||||
|
+RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET offsetof (struct rtld_global_ro, _dl_x86_cpu_features)
|
||||||
|
XSAVE_STATE_SIZE_OFFSET offsetof (struct cpu_features, xsave_state_size)
|
||||||
|
-FEATURE_OFFSET offsetof (struct cpu_features, feature)
|
||||||
|
-FEATURE_SIZE sizeof (unsigned int)
|
||||||
|
-
|
||||||
|
-COMMON_CPUID_INDEX_1
|
||||||
|
-COMMON_CPUID_INDEX_7
|
||||||
|
-FEATURE_INDEX_1
|
141
SOURCES/glibc-rh1817513-30.patch
Normal file
141
SOURCES/glibc-rh1817513-30.patch
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
commit edd8d70b91e1ccef549a7c668499596cc4d56ad1
|
||||||
|
Author: Mihailo Stojanovic <mihailo.stojanovic@rt-rk.com>
|
||||||
|
Date: Fri Aug 23 16:47:27 2019 +0000
|
||||||
|
|
||||||
|
[MIPS] Raise highest supported EI_ABIVERSION value [BZ #24916]
|
||||||
|
|
||||||
|
This bumps the highest valid EI_ABIVERSION value to ABSOLUTE ABI.
|
||||||
|
|
||||||
|
New testcase loads the symbol from the GOT with the "lb" instruction
|
||||||
|
so that the EI_ABIVERSION header field of the shared object is set
|
||||||
|
to ABSOLUTE (it doesn't actually check the value of the symbol), and
|
||||||
|
makes sure that the main executable is executed without "ABI version
|
||||||
|
invalid" error.
|
||||||
|
|
||||||
|
Tested for all three ABIs (o32, n32, n64) using both static linker which
|
||||||
|
handles undefined weak symbols correctly [1] (and sets the EI_ABIVERSION
|
||||||
|
of the test module) and the one that doesn't (EI_ABIVERSION left as 0).
|
||||||
|
|
||||||
|
[1] https://sourceware.org/ml/binutils/2018-07/msg00268.html
|
||||||
|
|
||||||
|
[BZ #24916]
|
||||||
|
* sysdeps/mips/Makefile [$(subdir) = elf] (tests): Add
|
||||||
|
tst-undefined-weak.
|
||||||
|
[$(subdir) = elf] (modules-names): Add tst-undefined-weak-lib.
|
||||||
|
[$(subdir) = elf] ($(objpfx)tst-undefined-weak): Add dependency.
|
||||||
|
* sysdeps/mips/tst-undefined-weak-lib.S: New file.
|
||||||
|
* sysdeps/mips/tst-undefined-weak.c: Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/mips/ldsodefs.h (VALID_ELF_ABIVERSION):
|
||||||
|
Increment highest valid ABIVERSION value.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile
|
||||||
|
index 7ac6fa50311d60b7..6ad69e9ef9e88728 100644
|
||||||
|
--- a/sysdeps/mips/Makefile
|
||||||
|
+++ b/sysdeps/mips/Makefile
|
||||||
|
@@ -82,3 +82,10 @@ $(objpfx)tst-mode-switch-2: $(shared-thread-library)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
+
|
||||||
|
+ifeq ($(subdir),elf)
|
||||||
|
+tests += tst-undefined-weak
|
||||||
|
+modules-names += tst-undefined-weak-lib
|
||||||
|
+
|
||||||
|
+$(objpfx)tst-undefined-weak: $(objpfx)tst-undefined-weak-lib.so
|
||||||
|
+endif
|
||||||
|
diff --git a/sysdeps/mips/tst-undefined-weak-lib.S b/sysdeps/mips/tst-undefined-weak-lib.S
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..a175ebf90e01b372
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/mips/tst-undefined-weak-lib.S
|
||||||
|
@@ -0,0 +1,43 @@
|
||||||
|
+/* Undefined weak symbol loading shared module.
|
||||||
|
+ Copyright (C) 2019 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 <sgidefs.h>
|
||||||
|
+
|
||||||
|
+ .text
|
||||||
|
+ .globl x
|
||||||
|
+ .set nomips16
|
||||||
|
+ .set nomicromips
|
||||||
|
+ .ent x
|
||||||
|
+ .type x, @function
|
||||||
|
+x:
|
||||||
|
+ .set noreorder
|
||||||
|
+#if _MIPS_SIM == _ABIO32
|
||||||
|
+ .cpload $25
|
||||||
|
+ jr $31
|
||||||
|
+ lb $2,%got(a)($28)
|
||||||
|
+#else
|
||||||
|
+ .cpsetup $25,$24,x
|
||||||
|
+ lb $2,%got_disp(a)($28)
|
||||||
|
+ jr $31
|
||||||
|
+ .cpreturn
|
||||||
|
+#endif
|
||||||
|
+ .set reorder
|
||||||
|
+ .end x
|
||||||
|
+ .size x, .-x
|
||||||
|
+ .weak a
|
||||||
|
+ .hidden a
|
||||||
|
diff --git a/sysdeps/mips/tst-undefined-weak.c b/sysdeps/mips/tst-undefined-weak.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..1231da6912508c19
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/mips/tst-undefined-weak.c
|
||||||
|
@@ -0,0 +1,28 @@
|
||||||
|
+/* Undefined weak symbol loading main executable.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+int *x (void);
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ x ();
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/mips/ldsodefs.h b/sysdeps/unix/sysv/linux/mips/ldsodefs.h
|
||||||
|
index 68a0a99bb1f1ec85..d2912cadabfd6877 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/mips/ldsodefs.h
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/mips/ldsodefs.h
|
||||||
|
@@ -34,7 +34,7 @@ extern void _dl_static_init (struct link_map *map);
|
||||||
|
#undef VALID_ELF_ABIVERSION
|
||||||
|
#define VALID_ELF_ABIVERSION(osabi,ver) \
|
||||||
|
(ver == 0 \
|
||||||
|
- || (osabi == ELFOSABI_SYSV && ver < 4) \
|
||||||
|
+ || (osabi == ELFOSABI_SYSV && ver < 5) \
|
||||||
|
|| (osabi == ELFOSABI_GNU && ver < LIBC_ABI_MAX))
|
||||||
|
|
||||||
|
#endif /* ldsodefs.h */
|
241
SOURCES/glibc-rh1817513-31.patch
Normal file
241
SOURCES/glibc-rh1817513-31.patch
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
commit 23c1c256ae7b0f010d0fcaff60682b620887b164
|
||||||
|
Author: Mihailo Stojanovic <mihailo.stojanovic@rt-rk.com>
|
||||||
|
Date: Thu Aug 29 20:11:42 2019 +0000
|
||||||
|
|
||||||
|
MIPS support for GNU hash
|
||||||
|
|
||||||
|
This patch is a reimplementation of [1], which was submitted back in
|
||||||
|
2015. Copyright issue has been sorted [2] last year. It proposed a new
|
||||||
|
section (.gnu.xhash) and related dynamic tag (GT_GNU_XHASH). The new
|
||||||
|
section would be virtually identical to the existing .gnu.hash except
|
||||||
|
for the translation table (xlat) which would contain correct MIPS
|
||||||
|
.dynsym indexes corresponding to the hashvals in chains. This is because
|
||||||
|
MIPS ABI imposes a different ordering of the dynsyms than the one
|
||||||
|
expected by the .gnu.hash section. Another addition would be a leading
|
||||||
|
word at the beggining of the section, which would contain the number of
|
||||||
|
entries in the translation table.
|
||||||
|
|
||||||
|
In this patch, the new section name and dynamic tag are changed to
|
||||||
|
reflect the fact that the section should be treated as MIPS specific
|
||||||
|
(.MIPS.xhash and DT_MIPS_XHASH).
|
||||||
|
|
||||||
|
This patch addresses the alignment issue reported in [3] which is caused
|
||||||
|
by the leading word of the .MIPS.xhash section. Leading word is now
|
||||||
|
removed in the corresponding binutils patch, and the number of entries
|
||||||
|
in the translation table is computed using DT_MIPS_SYMTABNO dynamic tag.
|
||||||
|
|
||||||
|
Since the MIPS specific dl-lookup.c file was removed following the
|
||||||
|
initial patch submission, I opted for the definition of three new macros
|
||||||
|
in the generic ldsodefs.h. ELF_MACHINE_GNU_HASH_ADDRIDX defines the
|
||||||
|
index of the dynamic tag in the l_info array. ELF_MACHINE_HASH_SYMIDX is
|
||||||
|
used to calculate the index of a symbol in GNU hash. On MIPS, it is
|
||||||
|
defined to look up the symbol index in the translation table.
|
||||||
|
ELF_MACHINE_XHASH_SETUP is defined for MIPS only. It initializes the
|
||||||
|
.MIPS.xhash pointer in the link_map_machine struct.
|
||||||
|
|
||||||
|
The other major change is bumping the highest EI_ABIVERSION value for
|
||||||
|
MIPS to suggest that the dynamic linker now supports GNU hash.
|
||||||
|
|
||||||
|
The patch was tested by running the glibc testsuite for the three MIPS
|
||||||
|
ABIs (o32, n32 and n64) and for x86_64-linux-gnu.
|
||||||
|
|
||||||
|
[1] https://sourceware.org/ml/binutils/2015-10/msg00057.html
|
||||||
|
[2] https://sourceware.org/ml/binutils/2018-03/msg00025.html
|
||||||
|
[3] https://sourceware.org/ml/binutils/2016-01/msg00006.html
|
||||||
|
|
||||||
|
* elf/dl-addr.c (determine_info): Calculate the symbol index
|
||||||
|
using the newly defined ELF_MACHINE_HASH_SYMIDX macro.
|
||||||
|
* elf/dl-lookup.c (do_lookup_x): Ditto.
|
||||||
|
(_dl_setup_hash): Initialize MIPS xhash translation table.
|
||||||
|
* elf/elf.h (SHT_MIPS_XHASH): New define.
|
||||||
|
(DT_MIPS_XHASH): New define.
|
||||||
|
* sysdeps/generic/ldsodefs.h (ELF_MACHINE_GNU_HASH_ADDRIDX): New
|
||||||
|
define.
|
||||||
|
(ELF_MACHINE_HASH_SYMIDX): Ditto.
|
||||||
|
(ELF_MACHINE_XHASH_SETUP): Ditto.
|
||||||
|
* sysdeps/mips/ldsodefs.h (ELF_MACHINE_GNU_HASH_ADDRIDX): New
|
||||||
|
define.
|
||||||
|
(ELF_MACHINE_HASH_SYMIDX): Ditto.
|
||||||
|
(ELF_MACHINE_XHASH_SETUP): Ditto.
|
||||||
|
* sysdeps/mips/linkmap.h (struct link_map_machine): New member.
|
||||||
|
* sysdeps/unix/sysv/linux/mips/ldsodefs.h: Increment valid ABI
|
||||||
|
version.
|
||||||
|
* sysdeps/unix/sysv/linux/mips/libc-abis: New ABI version.
|
||||||
|
|
||||||
|
diff --git a/elf/dl-addr.c b/elf/dl-addr.c
|
||||||
|
index e6c7d020945c51d2..b146fed09a46ff76 100644
|
||||||
|
--- a/elf/dl-addr.c
|
||||||
|
+++ b/elf/dl-addr.c
|
||||||
|
@@ -42,7 +42,7 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
|
||||||
|
ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
|
||||||
|
|
||||||
|
const ElfW(Sym) *matchsym = NULL;
|
||||||
|
- if (match->l_info[ADDRIDX (DT_GNU_HASH)] != NULL)
|
||||||
|
+ if (match->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL)
|
||||||
|
{
|
||||||
|
/* We look at all symbol table entries referenced by the hash
|
||||||
|
table. */
|
||||||
|
@@ -57,6 +57,7 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
|
||||||
|
{
|
||||||
|
/* The hash table never references local symbols so
|
||||||
|
we can omit that test here. */
|
||||||
|
+ symndx = ELF_MACHINE_HASH_SYMIDX (match, hasharr);
|
||||||
|
if ((symtab[symndx].st_shndx != SHN_UNDEF
|
||||||
|
|| symtab[symndx].st_value != 0)
|
||||||
|
&& symtab[symndx].st_shndx != SHN_ABS
|
||||||
|
@@ -65,8 +66,6 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
|
||||||
|
matchsym, addr)
|
||||||
|
&& symtab[symndx].st_name < strtabsize)
|
||||||
|
matchsym = (ElfW(Sym) *) &symtab[symndx];
|
||||||
|
-
|
||||||
|
- ++symndx;
|
||||||
|
}
|
||||||
|
while ((*hasharr++ & 1u) == 0);
|
||||||
|
}
|
||||||
|
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
||||||
|
index 01724a54f8840f9f..42fdaed99296137f 100644
|
||||||
|
--- a/elf/dl-lookup.c
|
||||||
|
+++ b/elf/dl-lookup.c
|
||||||
|
@@ -432,7 +432,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
||||||
|
do
|
||||||
|
if (((*hasharr ^ new_hash) >> 1) == 0)
|
||||||
|
{
|
||||||
|
- symidx = hasharr - map->l_gnu_chain_zero;
|
||||||
|
+ symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
|
||||||
|
sym = check_match (undef_name, ref, version, flags,
|
||||||
|
type_class, &symtab[symidx], symidx,
|
||||||
|
strtab, map, &versioned_sym,
|
||||||
|
@@ -961,10 +961,10 @@ _dl_setup_hash (struct link_map *map)
|
||||||
|
{
|
||||||
|
Elf_Symndx *hash;
|
||||||
|
|
||||||
|
- if (__glibc_likely (map->l_info[ADDRIDX (DT_GNU_HASH)] != NULL))
|
||||||
|
+ if (__glibc_likely (map->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL))
|
||||||
|
{
|
||||||
|
Elf32_Word *hash32
|
||||||
|
- = (void *) D_PTR (map, l_info[ADDRIDX (DT_GNU_HASH)]);
|
||||||
|
+ = (void *) D_PTR (map, l_info[ELF_MACHINE_GNU_HASH_ADDRIDX]);
|
||||||
|
map->l_nbuckets = *hash32++;
|
||||||
|
Elf32_Word symbias = *hash32++;
|
||||||
|
Elf32_Word bitmask_nwords = *hash32++;
|
||||||
|
@@ -979,6 +979,10 @@ _dl_setup_hash (struct link_map *map)
|
||||||
|
map->l_gnu_buckets = hash32;
|
||||||
|
hash32 += map->l_nbuckets;
|
||||||
|
map->l_gnu_chain_zero = hash32 - symbias;
|
||||||
|
+
|
||||||
|
+ /* Initialize MIPS xhash translation table. */
|
||||||
|
+ ELF_MACHINE_XHASH_SETUP (hash32, symbias, map);
|
||||||
|
+
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/elf/elf.h b/elf/elf.h
|
||||||
|
index 74f7f479ce817040..d6506ea1c7160dea 100644
|
||||||
|
--- a/elf/elf.h
|
||||||
|
+++ b/elf/elf.h
|
||||||
|
@@ -1698,6 +1698,7 @@ typedef struct
|
||||||
|
#define SHT_MIPS_EH_REGION 0x70000027
|
||||||
|
#define SHT_MIPS_XLATE_OLD 0x70000028
|
||||||
|
#define SHT_MIPS_PDR_EXCEPTION 0x70000029
|
||||||
|
+#define SHT_MIPS_XHASH 0x7000002b
|
||||||
|
|
||||||
|
/* Legal values for sh_flags field of Elf32_Shdr. */
|
||||||
|
|
||||||
|
@@ -1945,7 +1946,9 @@ typedef struct
|
||||||
|
in a PIE as it stores a relative offset from the address of the tag
|
||||||
|
rather than an absolute address. */
|
||||||
|
#define DT_MIPS_RLD_MAP_REL 0x70000035
|
||||||
|
-#define DT_MIPS_NUM 0x36
|
||||||
|
+/* GNU-style hash table with xlat. */
|
||||||
|
+#define DT_MIPS_XHASH 0x70000036
|
||||||
|
+#define DT_MIPS_NUM 0x37
|
||||||
|
|
||||||
|
/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
|
||||||
|
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index f0185ce0d16c0f69..3bdbdd6e67dacc85 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -47,6 +47,23 @@ __BEGIN_DECLS
|
||||||
|
#define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
|
||||||
|
+ DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
|
||||||
|
|
||||||
|
+/* Type of GNU hash which the machine uses. */
|
||||||
|
+#ifndef ELF_MACHINE_GNU_HASH_ADDRIDX
|
||||||
|
+# define ELF_MACHINE_GNU_HASH_ADDRIDX ADDRIDX (DT_GNU_HASH)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+/* Calculate the index of a symbol in GNU hash. */
|
||||||
|
+#ifndef ELF_MACHINE_HASH_SYMIDX
|
||||||
|
+# define ELF_MACHINE_HASH_SYMIDX(map, hasharr) \
|
||||||
|
+ ((hasharr) - (map)->l_gnu_chain_zero)
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+/* Setup MIPS xhash. Defined only for MIPS. */
|
||||||
|
+#ifndef ELF_MACHINE_XHASH_SETUP
|
||||||
|
+# define ELF_MACHINE_XHASH_SETUP(hash32, symbias, map) \
|
||||||
|
+ ((void) (hash32), (void) (symbias), (void) (map))
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* We use this macro to refer to ELF types independent of the native wordsize.
|
||||||
|
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
|
||||||
|
#define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type)
|
||||||
|
diff --git a/sysdeps/mips/ldsodefs.h b/sysdeps/mips/ldsodefs.h
|
||||||
|
index c6e5ce7e660325c1..35043b7c6d416c50 100644
|
||||||
|
--- a/sysdeps/mips/ldsodefs.h
|
||||||
|
+++ b/sysdeps/mips/ldsodefs.h
|
||||||
|
@@ -26,6 +26,21 @@ struct La_mips_32_retval;
|
||||||
|
struct La_mips_64_regs;
|
||||||
|
struct La_mips_64_retval;
|
||||||
|
|
||||||
|
+#define ELF_MACHINE_GNU_HASH_ADDRIDX (DT_MIPS_XHASH - DT_LOPROC + DT_NUM)
|
||||||
|
+
|
||||||
|
+/* Calculate the index of a symbol in MIPS xhash. */
|
||||||
|
+#define ELF_MACHINE_HASH_SYMIDX(map, hasharr) \
|
||||||
|
+ ((map)->l_mach.mips_xlat_zero[(hasharr) - (map)->l_gnu_chain_zero])
|
||||||
|
+
|
||||||
|
+/* Setup MIPS xhash. */
|
||||||
|
+#define ELF_MACHINE_XHASH_SETUP(hash32, symbias, map) \
|
||||||
|
+ do \
|
||||||
|
+ { \
|
||||||
|
+ (hash32) += (map)->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val - (symbias); \
|
||||||
|
+ (map)->l_mach.mips_xlat_zero = (hash32) - (symbias); \
|
||||||
|
+ } \
|
||||||
|
+ while (0)
|
||||||
|
+
|
||||||
|
#define ARCH_PLTENTER_MEMBERS \
|
||||||
|
Elf32_Addr (*mips_o32_gnu_pltenter) (Elf32_Sym *, unsigned int, \
|
||||||
|
uintptr_t *, uintptr_t *, \
|
||||||
|
diff --git a/sysdeps/mips/linkmap.h b/sysdeps/mips/linkmap.h
|
||||||
|
index 1fb9678a6d1625fd..1e640c3ba9bd18e4 100644
|
||||||
|
--- a/sysdeps/mips/linkmap.h
|
||||||
|
+++ b/sysdeps/mips/linkmap.h
|
||||||
|
@@ -3,4 +3,5 @@ struct link_map_machine
|
||||||
|
ElfW(Addr) plt; /* Address of .plt */
|
||||||
|
ElfW(Word) fpabi; /* FP ABI of the object */
|
||||||
|
unsigned int odd_spreg; /* Does the object require odd_spreg support? */
|
||||||
|
+ const Elf32_Word *mips_xlat_zero; /* .MIPS.xhash */
|
||||||
|
};
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/mips/ldsodefs.h b/sysdeps/unix/sysv/linux/mips/ldsodefs.h
|
||||||
|
index d2912cadabfd6877..03f3e12f202a0563 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/mips/ldsodefs.h
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/mips/ldsodefs.h
|
||||||
|
@@ -34,7 +34,7 @@ extern void _dl_static_init (struct link_map *map);
|
||||||
|
#undef VALID_ELF_ABIVERSION
|
||||||
|
#define VALID_ELF_ABIVERSION(osabi,ver) \
|
||||||
|
(ver == 0 \
|
||||||
|
- || (osabi == ELFOSABI_SYSV && ver < 5) \
|
||||||
|
+ || (osabi == ELFOSABI_SYSV && ver < 6) \
|
||||||
|
|| (osabi == ELFOSABI_GNU && ver < LIBC_ABI_MAX))
|
||||||
|
|
||||||
|
#endif /* ldsodefs.h */
|
||||||
|
diff --git a/sysdeps/unix/sysv/linux/mips/libc-abis b/sysdeps/unix/sysv/linux/mips/libc-abis
|
||||||
|
index eaea558720f42a48..c0b67dae3ece1511 100644
|
||||||
|
--- a/sysdeps/unix/sysv/linux/mips/libc-abis
|
||||||
|
+++ b/sysdeps/unix/sysv/linux/mips/libc-abis
|
||||||
|
@@ -16,3 +16,5 @@ UNIQUE
|
||||||
|
MIPS_O32_FP64 mips*-*-linux*
|
||||||
|
# Absolute (SHN_ABS) symbols working correctly.
|
||||||
|
ABSOLUTE
|
||||||
|
+# GNU-style hash table with translation table.
|
||||||
|
+MIPS_XHASH
|
254
SOURCES/glibc-rh1817513-32.patch
Normal file
254
SOURCES/glibc-rh1817513-32.patch
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
commit 2f9046fb059e94fe254c9a4ff5bcd52182069e44
|
||||||
|
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||||
|
Date: Wed Sep 18 12:40:00 2019 +0200
|
||||||
|
|
||||||
|
Add UNSUPPORTED check in elf/tst-pldd.
|
||||||
|
|
||||||
|
The testcase forks a child process and runs pldd with PID of
|
||||||
|
this child. On systems where /proc/sys/kernel/yama/ptrace_scope
|
||||||
|
differs from zero, pldd will fail with
|
||||||
|
/usr/bin/pldd: cannot attach to process 3: Operation not permitted
|
||||||
|
|
||||||
|
This patch checks if ptrace_scope exists, is zero "classic ptrace permissions"
|
||||||
|
or one "restricted ptrace". If ptrace_scope exists and has a higher
|
||||||
|
restriction, then the test is marked as UNSUPPORTED.
|
||||||
|
|
||||||
|
The case "restricted ptrace" is handled by rearranging the processes involved
|
||||||
|
during the test. Now we have the following process tree:
|
||||||
|
-parent: do_test (performs output checks)
|
||||||
|
--subprocess 1: pldd_process (becomes pldd via execve)
|
||||||
|
---subprocess 2: target_process (ptraced via pldd)
|
||||||
|
|
||||||
|
ChangeLog:
|
||||||
|
|
||||||
|
* elf/tst-pldd.c (do_test): Add UNSUPPORTED check.
|
||||||
|
Rearrange subprocesses.
|
||||||
|
(pldd_process): New function.
|
||||||
|
* support/Makefile (libsupport-routines): Add support_ptrace.
|
||||||
|
* support/xptrace.h: New file.
|
||||||
|
* support/support_ptrace.c: Likewise.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/tst-pldd.c
|
||||||
|
(Original backport uses spaces instead of tabs.)
|
||||||
|
|
||||||
|
diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c
|
||||||
|
index e2de31282a131166..f381cb0fa7e6b93d 100644
|
||||||
|
--- a/elf/tst-pldd.c
|
||||||
|
+++ b/elf/tst-pldd.c
|
||||||
|
@@ -30,6 +30,11 @@
|
||||||
|
#include <support/capture_subprocess.h>
|
||||||
|
#include <support/check.h>
|
||||||
|
#include <support/support.h>
|
||||||
|
+#include <support/xptrace.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+#include <sys/mman.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <signal.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
target_process (void *arg)
|
||||||
|
@@ -37,6 +42,34 @@ target_process (void *arg)
|
||||||
|
pause ();
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+pldd_process (void *arg)
|
||||||
|
+{
|
||||||
|
+ pid_t *target_pid_ptr = (pid_t *) arg;
|
||||||
|
+
|
||||||
|
+ /* Create a copy of current test to check with pldd. As the
|
||||||
|
+ target_process is a child of this pldd_process, pldd is also able
|
||||||
|
+ to attach to target_process if YAMA is configured to 1 =
|
||||||
|
+ "restricted ptrace". */
|
||||||
|
+ struct support_subprocess target = support_subprocess (target_process, NULL);
|
||||||
|
+
|
||||||
|
+ /* Store the pid of target-process as do_test needs it in order to
|
||||||
|
+ e.g. terminate it at end of the test. */
|
||||||
|
+ *target_pid_ptr = target.pid;
|
||||||
|
+
|
||||||
|
+ /* Three digits per byte plus null terminator. */
|
||||||
|
+ char pid[3 * sizeof (uint32_t) + 1];
|
||||||
|
+ snprintf (pid, array_length (pid), "%d", target.pid);
|
||||||
|
+
|
||||||
|
+ char *prog = xasprintf ("%s/pldd", support_bindir_prefix);
|
||||||
|
+
|
||||||
|
+ /* Run pldd and use the pid of target_process as argument. */
|
||||||
|
+ execve (prog, (char *const []) { (char *) prog, pid, NULL },
|
||||||
|
+ (char *const []) { NULL });
|
||||||
|
+
|
||||||
|
+ FAIL_EXIT1 ("Returned from execve: errno=%d=%m\n", errno);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* The test runs in a container because pldd does not support tracing
|
||||||
|
a binary started by the loader iself (as with testrun.sh). */
|
||||||
|
|
||||||
|
@@ -52,25 +85,22 @@ in_str_list (const char *libname, const char *const strlist[])
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
- /* Create a copy of current test to check with pldd. */
|
||||||
|
- struct support_subprocess target = support_subprocess (target_process, NULL);
|
||||||
|
-
|
||||||
|
- /* Run 'pldd' on test subprocess. */
|
||||||
|
- struct support_capture_subprocess pldd;
|
||||||
|
+ /* Check if our subprocess can be debugged with ptrace. */
|
||||||
|
{
|
||||||
|
- /* Three digits per byte plus null terminator. */
|
||||||
|
- char pid[3 * sizeof (uint32_t) + 1];
|
||||||
|
- snprintf (pid, array_length (pid), "%d", target.pid);
|
||||||
|
-
|
||||||
|
- char *prog = xasprintf ("%s/pldd", support_bindir_prefix);
|
||||||
|
-
|
||||||
|
- pldd = support_capture_subprogram (prog,
|
||||||
|
- (char *const []) { (char *) prog, pid, NULL });
|
||||||
|
+ int ptrace_scope = support_ptrace_scope ();
|
||||||
|
+ if (ptrace_scope >= 2)
|
||||||
|
+ FAIL_UNSUPPORTED ("/proc/sys/kernel/yama/ptrace_scope >= 2");
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- support_capture_subprocess_check (&pldd, "pldd", 0, sc_allow_stdout);
|
||||||
|
+ pid_t *target_pid_ptr = (pid_t *) xmmap (NULL, sizeof (pid_t),
|
||||||
|
+ PROT_READ | PROT_WRITE,
|
||||||
|
+ MAP_SHARED | MAP_ANONYMOUS, -1);
|
||||||
|
|
||||||
|
- free (prog);
|
||||||
|
- }
|
||||||
|
+ /* Run 'pldd' on test subprocess which will be created in pldd_process.
|
||||||
|
+ The pid of the subprocess will be written to target_pid_ptr. */
|
||||||
|
+ struct support_capture_subprocess pldd;
|
||||||
|
+ pldd = support_capture_subprocess (pldd_process, target_pid_ptr);
|
||||||
|
+ support_capture_subprocess_check (&pldd, "pldd", 0, sc_allow_stdout);
|
||||||
|
|
||||||
|
/* Check 'pldd' output. The test is expected to be linked against only
|
||||||
|
loader and libc. */
|
||||||
|
@@ -85,15 +115,15 @@ do_test (void)
|
||||||
|
/* First line is in the form of <pid>: <full path of executable> */
|
||||||
|
TEST_COMPARE (fscanf (out, "%u: " STRINPUT (512), &pid, buffer), 2);
|
||||||
|
|
||||||
|
- TEST_COMPARE (pid, target.pid);
|
||||||
|
+ TEST_COMPARE (pid, *target_pid_ptr);
|
||||||
|
TEST_COMPARE (strcmp (basename (buffer), "tst-pldd"), 0);
|
||||||
|
|
||||||
|
/* It expects only one loader and libc loaded by the program. */
|
||||||
|
bool interpreter_found = false, libc_found = false;
|
||||||
|
while (fgets (buffer, array_length (buffer), out) != NULL)
|
||||||
|
{
|
||||||
|
- /* Ignore vDSO. */
|
||||||
|
- if (buffer[0] != '/')
|
||||||
|
+ /* Ignore vDSO. */
|
||||||
|
+ if (buffer[0] != '/')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Remove newline so baseline (buffer) can compare against the
|
||||||
|
@@ -128,7 +158,9 @@ do_test (void)
|
||||||
|
}
|
||||||
|
|
||||||
|
support_capture_subprocess_free (&pldd);
|
||||||
|
- support_process_terminate (&target);
|
||||||
|
+ if (kill (*target_pid_ptr, SIGKILL) != 0)
|
||||||
|
+ FAIL_EXIT1 ("Unable to kill target_process: errno=%d=%m\n", errno);
|
||||||
|
+ xmunmap (target_pid_ptr, sizeof (pid_t));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 65b16299573af1ed..79d03bd6bfe02540 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -58,6 +58,7 @@ libsupport-routines = \
|
||||||
|
support_format_hostent \
|
||||||
|
support_format_netent \
|
||||||
|
support_isolate_in_subprocess \
|
||||||
|
+ support_ptrace \
|
||||||
|
support_openpty \
|
||||||
|
support_paths \
|
||||||
|
support_quote_blob \
|
||||||
|
diff --git a/support/support_ptrace.c b/support/support_ptrace.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..616b08cff33022ef
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/support_ptrace.c
|
||||||
|
@@ -0,0 +1,44 @@
|
||||||
|
+/* Support functions handling ptrace_scope.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xstdio.h>
|
||||||
|
+#include <support/xptrace.h>
|
||||||
|
+#include <sys/prctl.h>
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+support_ptrace_scope (void)
|
||||||
|
+{
|
||||||
|
+ int ptrace_scope = -1;
|
||||||
|
+
|
||||||
|
+#ifdef __linux__
|
||||||
|
+ /* YAMA may be not enabled. Otherwise it contains a value from 0 to 3:
|
||||||
|
+ - 0 classic ptrace permissions
|
||||||
|
+ - 1 restricted ptrace
|
||||||
|
+ - 2 admin-only attach
|
||||||
|
+ - 3 no attach */
|
||||||
|
+ FILE *f = fopen ("/proc/sys/kernel/yama/ptrace_scope", "r");
|
||||||
|
+ if (f != NULL)
|
||||||
|
+ {
|
||||||
|
+ TEST_COMPARE (fscanf (f, "%d", &ptrace_scope), 1);
|
||||||
|
+ xfclose (f);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ return ptrace_scope;
|
||||||
|
+}
|
||||||
|
diff --git a/support/xptrace.h b/support/xptrace.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..7af892680578fffd
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/xptrace.h
|
||||||
|
@@ -0,0 +1,32 @@
|
||||||
|
+/* Support functions handling ptrace_scope.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#ifndef SUPPORT_PTRACE_H
|
||||||
|
+#define SUPPORT_PTRACE_H
|
||||||
|
+
|
||||||
|
+#include <sys/cdefs.h>
|
||||||
|
+
|
||||||
|
+__BEGIN_DECLS
|
||||||
|
+
|
||||||
|
+/* Return the current YAMA mode set on the machine (0 to 3) or -1
|
||||||
|
+ if YAMA is not supported. */
|
||||||
|
+int support_ptrace_scope (void);
|
||||||
|
+
|
||||||
|
+__END_DECLS
|
||||||
|
+
|
||||||
|
+#endif
|
29
SOURCES/glibc-rh1817513-33.patch
Normal file
29
SOURCES/glibc-rh1817513-33.patch
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
commit 64fab3633aecc8eadc1338aa8953f8b2f37e3ebf
|
||||||
|
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||||
|
Date: Thu Sep 19 12:26:18 2019 +0200
|
||||||
|
|
||||||
|
Fix building support_ptrace.c on i686-gnu.
|
||||||
|
|
||||||
|
On i686-gnu the build is broken:
|
||||||
|
In file included from support_ptrace.c:22:
|
||||||
|
../include/sys/prctl.h:2:15: fatal error: sys/prctl.h: No such file or directory
|
||||||
|
#include_next <sys/prctl.h>
|
||||||
|
|
||||||
|
This patch just removes the unused prctl.h inclusion.
|
||||||
|
|
||||||
|
ChangeLog:
|
||||||
|
|
||||||
|
* support/support_ptrace.c: Remove inclusion of sys/prctl.h.
|
||||||
|
|
||||||
|
diff --git a/support/support_ptrace.c b/support/support_ptrace.c
|
||||||
|
index 616b08cff33022ef..a733adf2c8dfd073 100644
|
||||||
|
--- a/support/support_ptrace.c
|
||||||
|
+++ b/support/support_ptrace.c
|
||||||
|
@@ -19,7 +19,6 @@
|
||||||
|
#include <support/check.h>
|
||||||
|
#include <support/xstdio.h>
|
||||||
|
#include <support/xptrace.h>
|
||||||
|
-#include <sys/prctl.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
support_ptrace_scope (void)
|
155
SOURCES/glibc-rh1817513-34.patch
Normal file
155
SOURCES/glibc-rh1817513-34.patch
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
commit 4052fa22f69c0964bb42c0f13daa791617253de5
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Wed Oct 2 14:46:46 2019 -0400
|
||||||
|
|
||||||
|
Add wait-for-debugger test harness hooks
|
||||||
|
|
||||||
|
If WAIT_FOR_DEBUGGER is set to a non-zero value in the environment,
|
||||||
|
any test that runs will print some useful gdb information and wait
|
||||||
|
for gdb to attach to it and clear the "wait_for_debugger" variable.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/support_test_main.c b/support/support_test_main.c
|
||||||
|
index fa3c2e06dee5ae0f..def84d803928176b 100644
|
||||||
|
--- a/support/support_test_main.c
|
||||||
|
+++ b/support/support_test_main.c
|
||||||
|
@@ -19,6 +19,7 @@
|
||||||
|
#include <support/test-driver.h>
|
||||||
|
#include <support/check.h>
|
||||||
|
#include <support/temp_file-internal.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
@@ -36,6 +37,8 @@
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
+#include <xstdio.h>
|
||||||
|
+
|
||||||
|
static const struct option default_options[] =
|
||||||
|
{
|
||||||
|
TEST_DEFAULT_OPTIONS
|
||||||
|
@@ -176,10 +179,55 @@ signal_handler (int sig)
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* This must be volatile as it will be modified by the debugger. */
|
||||||
|
+static volatile int wait_for_debugger = 0;
|
||||||
|
+
|
||||||
|
/* Run test_function or test_function_argv. */
|
||||||
|
static int
|
||||||
|
run_test_function (int argc, char **argv, const struct test_config *config)
|
||||||
|
{
|
||||||
|
+ const char *wfd = getenv("WAIT_FOR_DEBUGGER");
|
||||||
|
+ if (wfd != NULL)
|
||||||
|
+ wait_for_debugger = atoi (wfd);
|
||||||
|
+ if (wait_for_debugger)
|
||||||
|
+ {
|
||||||
|
+ pid_t mypid;
|
||||||
|
+ FILE *gdb_script;
|
||||||
|
+ char *gdb_script_name;
|
||||||
|
+ int inside_container = 0;
|
||||||
|
+
|
||||||
|
+ mypid = getpid();
|
||||||
|
+ if (mypid < 3)
|
||||||
|
+ {
|
||||||
|
+ const char *outside_pid = getenv("PID_OUTSIDE_CONTAINER");
|
||||||
|
+ if (outside_pid)
|
||||||
|
+ {
|
||||||
|
+ mypid = atoi (outside_pid);
|
||||||
|
+ inside_container = 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ gdb_script_name = (char *) xmalloc (strlen (argv[0]) + strlen (".gdb") + 1);
|
||||||
|
+ sprintf (gdb_script_name, "%s.gdb", argv[0]);
|
||||||
|
+ gdb_script = xfopen (gdb_script_name, "w");
|
||||||
|
+
|
||||||
|
+ fprintf (stderr, "Waiting for debugger, test process is pid %d\n", mypid);
|
||||||
|
+ fprintf (stderr, "gdb -x %s\n", gdb_script_name);
|
||||||
|
+ if (inside_container)
|
||||||
|
+ fprintf (gdb_script, "set sysroot %s/testroot.root\n", support_objdir_root);
|
||||||
|
+ fprintf (gdb_script, "file\n");
|
||||||
|
+ fprintf (gdb_script, "file %s\n", argv[0]);
|
||||||
|
+ fprintf (gdb_script, "symbol-file %s\n", argv[0]);
|
||||||
|
+ fprintf (gdb_script, "exec-file %s\n", argv[0]);
|
||||||
|
+ fprintf (gdb_script, "attach %ld\n", (long int) mypid);
|
||||||
|
+ fprintf (gdb_script, "set wait_for_debugger = 0\n");
|
||||||
|
+ fclose (gdb_script);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Wait for the debugger to set wait_for_debugger to zero. */
|
||||||
|
+ while (wait_for_debugger)
|
||||||
|
+ usleep (1000);
|
||||||
|
+
|
||||||
|
if (config->test_function != NULL)
|
||||||
|
return config->test_function ();
|
||||||
|
else if (config->test_function_argv != NULL)
|
||||||
|
@@ -229,6 +277,11 @@ support_test_main (int argc, char **argv, const struct test_config *config)
|
||||||
|
unsigned int timeoutfactor = 1;
|
||||||
|
pid_t termpid;
|
||||||
|
|
||||||
|
+ /* If we're debugging the test, we need to disable timeouts and use
|
||||||
|
+ the initial pid (esp if we're running inside a container). */
|
||||||
|
+ if (getenv("WAIT_FOR_DEBUGGER") != NULL)
|
||||||
|
+ direct = 1;
|
||||||
|
+
|
||||||
|
if (!config->no_mallopt)
|
||||||
|
{
|
||||||
|
/* Make uses of freed and uninitialized memory known. Do not
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index f0d9e3060e80bda5..6503cea90309b9b0 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -676,6 +676,9 @@ main (int argc, char **argv)
|
||||||
|
char *so_base;
|
||||||
|
int do_postclean = 0;
|
||||||
|
|
||||||
|
+ int pipes[2];
|
||||||
|
+ char pid_buf[20];
|
||||||
|
+
|
||||||
|
uid_t original_uid;
|
||||||
|
gid_t original_gid;
|
||||||
|
/* If set, the test runs as root instead of the user running the testsuite. */
|
||||||
|
@@ -999,6 +1002,11 @@ main (int argc, char **argv)
|
||||||
|
if (chdir (new_cwd_path) < 0)
|
||||||
|
FAIL_EXIT1 ("Can't cd to new %s - ", new_cwd_path);
|
||||||
|
|
||||||
|
+ /* This is to pass the "outside" PID to the child, which will be PID
|
||||||
|
+ 1. */
|
||||||
|
+ if (pipe2 (pipes, O_CLOEXEC) < 0)
|
||||||
|
+ FAIL_EXIT1 ("Can't create pid pipe");
|
||||||
|
+
|
||||||
|
/* To complete the containerization, we need to fork () at least
|
||||||
|
once. We can't exec, nor can we somehow link the new child to
|
||||||
|
our parent. So we run the child and propogate it's exit status
|
||||||
|
@@ -1010,6 +1018,12 @@ main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Parent. */
|
||||||
|
int status;
|
||||||
|
+
|
||||||
|
+ /* Send the child's "outside" pid to it. */
|
||||||
|
+ write (pipes[1], &child, sizeof(child));
|
||||||
|
+ close (pipes[0]);
|
||||||
|
+ close (pipes[1]);
|
||||||
|
+
|
||||||
|
waitpid (child, &status, 0);
|
||||||
|
|
||||||
|
if (WIFEXITED (status))
|
||||||
|
@@ -1028,6 +1042,14 @@ main (int argc, char **argv)
|
||||||
|
/* The rest is the child process, which is now PID 1 and "in" the
|
||||||
|
new root. */
|
||||||
|
|
||||||
|
+ /* Get our "outside" pid from our parent. We use this to help with
|
||||||
|
+ debugging from outside the container. */
|
||||||
|
+ read (pipes[0], &child, sizeof(child));
|
||||||
|
+ close (pipes[0]);
|
||||||
|
+ close (pipes[1]);
|
||||||
|
+ sprintf (pid_buf, "%lu", (long unsigned)child);
|
||||||
|
+ setenv ("PID_OUTSIDE_CONTAINER", pid_buf, 0);
|
||||||
|
+
|
||||||
|
maybe_xmkdir ("/tmp", 0755);
|
||||||
|
|
||||||
|
/* Now that we're pid 1 (effectively "root") we can mount /proc */
|
421
SOURCES/glibc-rh1817513-35.patch
Normal file
421
SOURCES/glibc-rh1817513-35.patch
Normal file
@ -0,0 +1,421 @@
|
|||||||
|
commit c7bf5ceab6ec776ac7350d3b0190776bf532ac54
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Sat Nov 2 21:55:35 2019 +0100
|
||||||
|
|
||||||
|
Properly initialize audit cookie for the dynamic loader [BZ #25157]
|
||||||
|
|
||||||
|
The l_audit array is indexed by audit module, not audit function.
|
||||||
|
|
||||||
|
Change-Id: I180eb3573dc1c57433750f5d8cb18271460ba5f2
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
(Test backport differences.)
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 4e1356b9172aee02..4ab73dc48d9ac126 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -192,7 +192,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
|
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
||||||
|
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
||||||
|
tst-audit13 \
|
||||||
|
- tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \
|
||||||
|
+ tst-sonamemove-link tst-sonamemove-dlopen \
|
||||||
|
+ tst-auditmany tst-initfinilazyfail \
|
||||||
|
tst-dlopenfail tst-dlopenfail-2 \
|
||||||
|
tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen
|
||||||
|
# reldep9
|
||||||
|
@@ -303,6 +304,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
|
tst-absolute-zero-lib tst-big-note-lib \
|
||||||
|
tst-audit13mod1 tst-sonamemove-linkmod1 \
|
||||||
|
tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
|
||||||
|
+ tst-auditmanymod1 tst-auditmanymod2 tst-auditmanymod3 \
|
||||||
|
+ tst-auditmanymod4 tst-auditmanymod5 tst-auditmanymod6 \
|
||||||
|
+ tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \
|
||||||
|
tst-initlazyfailmod tst-finilazyfailmod \
|
||||||
|
tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
|
||||||
|
tst-dlopenfailmod3 \
|
||||||
|
@@ -1433,6 +1437,14 @@ $(objpfx)tst-audit13.out: $(objpfx)tst-audit13mod1.so
|
||||||
|
LDFLAGS-tst-audit13mod1.so = -Wl,-z,lazy
|
||||||
|
tst-audit13-ENV = LD_AUDIT=$(objpfx)tst-audit13mod1.so
|
||||||
|
|
||||||
|
+$(objpfx)tst-auditmany.out: $(objpfx)tst-auditmanymod1.so \
|
||||||
|
+ $(objpfx)tst-auditmanymod2.so $(objpfx)tst-auditmanymod3.so \
|
||||||
|
+ $(objpfx)tst-auditmanymod4.so $(objpfx)tst-auditmanymod5.so \
|
||||||
|
+ $(objpfx)tst-auditmanymod6.so $(objpfx)tst-auditmanymod7.so \
|
||||||
|
+ $(objpfx)tst-auditmanymod8.so $(objpfx)tst-auditmanymod9.so
|
||||||
|
+tst-auditmany-ENV = \
|
||||||
|
+ LD_AUDIT=tst-auditmanymod1.so:tst-auditmanymod2.so:tst-auditmanymod3.so:tst-auditmanymod4.so:tst-auditmanymod5.so:tst-auditmanymod6.so:tst-auditmanymod7.so:tst-auditmanymod8.so:tst-auditmanymod9.so
|
||||||
|
+
|
||||||
|
# tst-sonamemove links against an older implementation of the library.
|
||||||
|
LDFLAGS-tst-sonamemove-linkmod1.so = \
|
||||||
|
-Wl,--version-script=tst-sonamemove-linkmod1.map \
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index ffbd8f4553bb3425..f557f39a70669c09 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -1008,13 +1008,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
|
||||||
|
|
||||||
|
/* Store the pointer. */
|
||||||
|
if (err_str == NULL && largs.result != NULL)
|
||||||
|
- {
|
||||||
|
- newp->fptr[cnt] = largs.result;
|
||||||
|
-
|
||||||
|
- /* The dynamic linker link map is statically allocated,
|
||||||
|
- initialize the data now. */
|
||||||
|
- GL(dl_rtld_map).l_audit[cnt].cookie = (intptr_t) &GL(dl_rtld_map);
|
||||||
|
- }
|
||||||
|
+ newp->fptr[cnt] = largs.result;
|
||||||
|
else
|
||||||
|
newp->fptr[cnt] = NULL;
|
||||||
|
++cnt;
|
||||||
|
@@ -1030,6 +1024,12 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
|
||||||
|
*last_audit = GLRO(dl_audit) = &newp->ifaces;
|
||||||
|
else
|
||||||
|
*last_audit = (*last_audit)->next = &newp->ifaces;
|
||||||
|
+
|
||||||
|
+ /* The dynamic linker link map is statically allocated, initialize
|
||||||
|
+ the data now. */
|
||||||
|
+ GL (dl_rtld_map).l_audit[GLRO (dl_naudit)].cookie
|
||||||
|
+ = (intptr_t) &GL (dl_rtld_map);
|
||||||
|
+
|
||||||
|
++GLRO(dl_naudit);
|
||||||
|
|
||||||
|
/* Mark the DSO as being used for auditing. */
|
||||||
|
diff --git a/elf/tst-auditmany.c b/elf/tst-auditmany.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..9d68105b9e707b46
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmany.c
|
||||||
|
@@ -0,0 +1,26 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Main program.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+/* It does not make sense to use the test harness for this test
|
||||||
|
+ because the testing happens in auditors. */
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main (void)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-auditmanymod.h b/elf/tst-auditmanymod.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..d1d89e08431ce32f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod.h
|
||||||
|
@@ -0,0 +1,64 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor template.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+/* The macro MOD must be defined to the number of this auditor (an
|
||||||
|
+ integer) before including this file. */
|
||||||
|
+
|
||||||
|
+#include <link.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+
|
||||||
|
+/* Error counter for delayed error reporting. */
|
||||||
|
+static int errors;
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+la_version (unsigned int version)
|
||||||
|
+{
|
||||||
|
+ return version;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+la_objopen (struct link_map *map, Lmid_t lmid,
|
||||||
|
+ uintptr_t *cookie)
|
||||||
|
+{
|
||||||
|
+ struct link_map *cookie_map = (struct link_map *) *cookie;
|
||||||
|
+ printf ("info: %d, la_objopen: map=%p name=%s cookie=%p:%p diff=%td\n",
|
||||||
|
+ MOD, map, map->l_name, cookie, cookie_map,
|
||||||
|
+ (char *) cookie - (char *) map);
|
||||||
|
+ fflush (stdout);
|
||||||
|
+ if (map != cookie_map)
|
||||||
|
+ {
|
||||||
|
+ printf ("error: %d, la_objopen:"
|
||||||
|
+ " map address does not match cookie value\n",
|
||||||
|
+ MOD);
|
||||||
|
+ fflush (stdout);
|
||||||
|
+ ++errors;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+extern unsigned int
|
||||||
|
+la_objclose (uintptr_t *__cookie)
|
||||||
|
+{
|
||||||
|
+ if (errors != 0)
|
||||||
|
+ {
|
||||||
|
+ printf ("error: exiting due to previous errors");
|
||||||
|
+ _exit (1);
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-auditmanymod1.c b/elf/tst-auditmanymod1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..c7de49d446a7e52d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod1.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 1.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 1
|
||||||
|
+#include "tst-auditmanymod.h"
|
||||||
|
diff --git a/elf/tst-auditmanymod2.c b/elf/tst-auditmanymod2.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..4254f022a177b844
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod2.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 2.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 2
|
||||||
|
+#include "tst-auditmanymod.h"
|
||||||
|
diff --git a/elf/tst-auditmanymod3.c b/elf/tst-auditmanymod3.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..ee90f4eb3a5c1b35
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod3.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 3.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 3
|
||||||
|
+#include "tst-auditmanymod.h"
|
||||||
|
diff --git a/elf/tst-auditmanymod4.c b/elf/tst-auditmanymod4.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..6379fa1d55014998
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod4.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 4.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 4
|
||||||
|
+#include "tst-auditmanymod.h"
|
||||||
|
diff --git a/elf/tst-auditmanymod5.c b/elf/tst-auditmanymod5.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..17c0f617aa4d1893
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod5.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 5.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 5
|
||||||
|
+#include "tst-auditmanymod.h"
|
||||||
|
diff --git a/elf/tst-auditmanymod6.c b/elf/tst-auditmanymod6.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..86bc6801a4454742
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod6.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 6.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 6
|
||||||
|
+#include "tst-auditmanymod.h"
|
||||||
|
diff --git a/elf/tst-auditmanymod7.c b/elf/tst-auditmanymod7.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..92b0bf6006876dff
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod7.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 7.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 7
|
||||||
|
+#include "tst-auditmanymod.h"
|
||||||
|
diff --git a/elf/tst-auditmanymod8.c b/elf/tst-auditmanymod8.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..d42f884d2f24f4c0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod8.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 8.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 8
|
||||||
|
+#include "tst-auditmanymod.h"
|
||||||
|
diff --git a/elf/tst-auditmanymod9.c b/elf/tst-auditmanymod9.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..6bee81d69c6d3c22
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditmanymod9.c
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+/* Check cookie initialization for many auditors. Auditor 9.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+#define MOD 9
|
||||||
|
+#include "tst-auditmanymod.h"
|
340
SOURCES/glibc-rh1817513-36.patch
Normal file
340
SOURCES/glibc-rh1817513-36.patch
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
commit e1d559f337de2c8ab68a6749dfe873477c883807
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Sat Nov 2 20:04:02 2019 +0100
|
||||||
|
|
||||||
|
Introduce link_map_audit_state accessor function
|
||||||
|
|
||||||
|
To improve GCC 10 compatibility, it is necessary to remove the l_audit
|
||||||
|
zero-length array from the end of struct link_map. In preparation of
|
||||||
|
that, this commit introduces an accessor function for the audit state,
|
||||||
|
so that it is possible to change the representation of the audit state
|
||||||
|
without adjusting the code that accesses it.
|
||||||
|
|
||||||
|
Tested on x86_64-linux-gnu. Built on i686-gnu.
|
||||||
|
|
||||||
|
Change-Id: Id815673c29950fc011ae5301d7cde12624f658df
|
||||||
|
|
||||||
|
diff --git a/csu/libc-start.c b/csu/libc-start.c
|
||||||
|
index 494132368f8fe486..dfbf195328239a17 100644
|
||||||
|
--- a/csu/libc-start.c
|
||||||
|
+++ b/csu/libc-start.c
|
||||||
|
@@ -272,7 +272,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->preinit != NULL)
|
||||||
|
- afct->preinit (&head->l_audit[cnt].cookie);
|
||||||
|
+ afct->preinit (&link_map_audit_state (head, cnt)->cookie);
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||||
|
index a9ecdff62dba88fb..1ece0ae1dd062d1e 100644
|
||||||
|
--- a/elf/dl-close.c
|
||||||
|
+++ b/elf/dl-close.c
|
||||||
|
@@ -305,8 +305,12 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->objclose != NULL)
|
||||||
|
- /* Return value is ignored. */
|
||||||
|
- (void) afct->objclose (&imap->l_audit[cnt].cookie);
|
||||||
|
+ {
|
||||||
|
+ struct auditstate *state
|
||||||
|
+ = link_map_audit_state (imap, cnt);
|
||||||
|
+ /* Return value is ignored. */
|
||||||
|
+ (void) afct->objclose (&state->cookie);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
@@ -481,7 +485,10 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->activity != NULL)
|
||||||
|
- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_DELETE);
|
||||||
|
+ {
|
||||||
|
+ struct auditstate *state = link_map_audit_state (head, cnt);
|
||||||
|
+ afct->activity (&state->cookie, LA_ACT_DELETE);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
@@ -781,7 +788,10 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->activity != NULL)
|
||||||
|
- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
|
||||||
|
+ {
|
||||||
|
+ struct auditstate *state = link_map_audit_state (head, cnt);
|
||||||
|
+ afct->activity (&state->cookie, LA_ACT_CONSISTENT);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
|
||||||
|
index 3cfc262400da4db9..915ceb104e1c81d6 100644
|
||||||
|
--- a/elf/dl-fini.c
|
||||||
|
+++ b/elf/dl-fini.c
|
||||||
|
@@ -152,9 +152,12 @@ _dl_fini (void)
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->objclose != NULL)
|
||||||
|
- /* Return value is ignored. */
|
||||||
|
- (void) afct->objclose (&l->l_audit[cnt].cookie);
|
||||||
|
-
|
||||||
|
+ {
|
||||||
|
+ struct auditstate *state
|
||||||
|
+ = link_map_audit_state (l, cnt);
|
||||||
|
+ /* Return value is ignored. */
|
||||||
|
+ (void) afct->objclose (&state->cookie);
|
||||||
|
+ }
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||||
|
index b190b28e32e47391..8f8869ff524ab9f2 100644
|
||||||
|
--- a/elf/dl-load.c
|
||||||
|
+++ b/elf/dl-load.c
|
||||||
|
@@ -979,7 +979,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->activity != NULL)
|
||||||
|
- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_ADD);
|
||||||
|
+ afct->activity (&link_map_audit_state (head, cnt)->cookie,
|
||||||
|
+ LA_ACT_ADD);
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
@@ -1418,10 +1419,9 @@ cannot enable executable stack as shared object requires");
|
||||||
|
{
|
||||||
|
if (afct->objopen != NULL)
|
||||||
|
{
|
||||||
|
- l->l_audit[cnt].bindflags
|
||||||
|
- = afct->objopen (l, nsid, &l->l_audit[cnt].cookie);
|
||||||
|
-
|
||||||
|
- l->l_audit_any_plt |= l->l_audit[cnt].bindflags != 0;
|
||||||
|
+ struct auditstate *state = link_map_audit_state (l, cnt);
|
||||||
|
+ state->bindflags = afct->objopen (l, nsid, &state->cookie);
|
||||||
|
+ l->l_audit_any_plt |= state->bindflags != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
@@ -1527,8 +1527,8 @@ open_verify (const char *name, int fd,
|
||||||
|
{
|
||||||
|
if (afct->objsearch != NULL)
|
||||||
|
{
|
||||||
|
- name = afct->objsearch (name, &loader->l_audit[cnt].cookie,
|
||||||
|
- whatcode);
|
||||||
|
+ struct auditstate *state = link_map_audit_state (loader, cnt);
|
||||||
|
+ name = afct->objsearch (name, &state->cookie, whatcode);
|
||||||
|
if (name == NULL)
|
||||||
|
/* Ignore the path. */
|
||||||
|
return -1;
|
||||||
|
@@ -1998,8 +1998,8 @@ _dl_map_object (struct link_map *loader, const char *name,
|
||||||
|
if (afct->objsearch != NULL)
|
||||||
|
{
|
||||||
|
const char *before = name;
|
||||||
|
- name = afct->objsearch (name, &loader->l_audit[cnt].cookie,
|
||||||
|
- LA_SER_ORIG);
|
||||||
|
+ struct auditstate *state = link_map_audit_state (loader, cnt);
|
||||||
|
+ name = afct->objsearch (name, &state->cookie, LA_SER_ORIG);
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
/* Do not try anything further. */
|
||||||
|
diff --git a/elf/dl-object.c b/elf/dl-object.c
|
||||||
|
index f6544a8fec45bdce..05a7750c65305771 100644
|
||||||
|
--- a/elf/dl-object.c
|
||||||
|
+++ b/elf/dl-object.c
|
||||||
|
@@ -81,7 +81,7 @@ _dl_new_object (char *realname, const char *libname, int type,
|
||||||
|
struct link_map *new;
|
||||||
|
struct libname_list *newname;
|
||||||
|
#ifdef SHARED
|
||||||
|
- size_t audit_space = naudit * sizeof (new->l_audit[0]);
|
||||||
|
+ size_t audit_space = naudit * sizeof (struct auditstate);
|
||||||
|
#else
|
||||||
|
# define audit_space 0
|
||||||
|
#endif
|
||||||
|
@@ -134,10 +134,8 @@ _dl_new_object (char *realname, const char *libname, int type,
|
||||||
|
|
||||||
|
#ifdef SHARED
|
||||||
|
for (unsigned int cnt = 0; cnt < naudit; ++cnt)
|
||||||
|
- {
|
||||||
|
- new->l_audit[cnt].cookie = (uintptr_t) new;
|
||||||
|
- /* new->l_audit[cnt].bindflags = 0; */
|
||||||
|
- }
|
||||||
|
+ /* No need to initialize bindflags due to calloc. */
|
||||||
|
+ link_map_audit_state (new, cnt)->cookie = (uintptr_t) new;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* new->l_global = 0; We use calloc therefore not necessary. */
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index 46a4c1e5a3f8d2dd..7113c4a04f0fddbc 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -589,7 +589,10 @@ dl_open_worker (void *a)
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->activity != NULL)
|
||||||
|
- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
|
||||||
|
+ {
|
||||||
|
+ struct auditstate *state = link_map_audit_state (head, cnt);
|
||||||
|
+ afct->activity (&state->cookie, LA_ACT_CONSISTENT);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
|
||||||
|
index 3d2f4a7a76e616e3..72b03e000dcf190e 100644
|
||||||
|
--- a/elf/dl-runtime.c
|
||||||
|
+++ b/elf/dl-runtime.c
|
||||||
|
@@ -325,15 +325,18 @@ _dl_profile_fixup (
|
||||||
|
{
|
||||||
|
/* XXX Check whether both DSOs must request action or
|
||||||
|
only one */
|
||||||
|
- if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0
|
||||||
|
- && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0)
|
||||||
|
+ struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||||
|
+ struct auditstate *result_state
|
||||||
|
+ = link_map_audit_state (result, cnt);
|
||||||
|
+ if ((l_state->bindflags & LA_FLG_BINDFROM) != 0
|
||||||
|
+ && (result_state->bindflags & LA_FLG_BINDTO) != 0)
|
||||||
|
{
|
||||||
|
if (afct->symbind != NULL)
|
||||||
|
{
|
||||||
|
uintptr_t new_value
|
||||||
|
= afct->symbind (&sym, reloc_result->boundndx,
|
||||||
|
- &l->l_audit[cnt].cookie,
|
||||||
|
- &result->l_audit[cnt].cookie,
|
||||||
|
+ &l_state->cookie,
|
||||||
|
+ &result_state->cookie,
|
||||||
|
&flags,
|
||||||
|
strtab2 + defsym->st_name);
|
||||||
|
if (new_value != (uintptr_t) sym.st_value)
|
||||||
|
@@ -421,10 +424,13 @@ _dl_profile_fixup (
|
||||||
|
& (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
|
||||||
|
{
|
||||||
|
long int new_framesize = -1;
|
||||||
|
+ struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||||
|
+ struct auditstate *bound_state
|
||||||
|
+ = link_map_audit_state (reloc_result->bound, cnt);
|
||||||
|
uintptr_t new_value
|
||||||
|
= afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
|
||||||
|
- &l->l_audit[cnt].cookie,
|
||||||
|
- &reloc_result->bound->l_audit[cnt].cookie,
|
||||||
|
+ &l_state->cookie,
|
||||||
|
+ &bound_state->cookie,
|
||||||
|
regs, &flags, symname,
|
||||||
|
&new_framesize);
|
||||||
|
if (new_value != (uintptr_t) sym.st_value)
|
||||||
|
@@ -504,9 +510,11 @@ _dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
|
||||||
|
&& (reloc_result->enterexit
|
||||||
|
& (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
|
||||||
|
{
|
||||||
|
+ struct auditstate *l_state = link_map_audit_state (l, cnt);
|
||||||
|
+ struct auditstate *bound_state
|
||||||
|
+ = link_map_audit_state (reloc_result->bound, cnt);
|
||||||
|
afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
|
||||||
|
- &l->l_audit[cnt].cookie,
|
||||||
|
- &reloc_result->bound->l_audit[cnt].cookie,
|
||||||
|
+ &l_state->cookie, &bound_state->cookie,
|
||||||
|
inregs, outregs, symname);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
|
||||||
|
index 189628adc05aedf1..286cf7e27fd59f20 100644
|
||||||
|
--- a/elf/dl-sym.c
|
||||||
|
+++ b/elf/dl-sym.c
|
||||||
|
@@ -198,17 +198,20 @@ RTLD_NEXT used in code not dynamically loaded"));
|
||||||
|
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
+ struct auditstate *match_audit
|
||||||
|
+ = link_map_audit_state (match, cnt);
|
||||||
|
+ struct auditstate *result_audit
|
||||||
|
+ = link_map_audit_state (result, cnt);
|
||||||
|
if (afct->symbind != NULL
|
||||||
|
- && ((match->l_audit[cnt].bindflags & LA_FLG_BINDFROM)
|
||||||
|
- != 0
|
||||||
|
- || ((result->l_audit[cnt].bindflags & LA_FLG_BINDTO)
|
||||||
|
+ && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
|
||||||
|
+ || ((result_audit->bindflags & LA_FLG_BINDTO)
|
||||||
|
!= 0)))
|
||||||
|
{
|
||||||
|
unsigned int flags = altvalue | LA_SYMB_DLSYM;
|
||||||
|
uintptr_t new_value
|
||||||
|
= afct->symbind (&sym, ndx,
|
||||||
|
- &match->l_audit[cnt].cookie,
|
||||||
|
- &result->l_audit[cnt].cookie,
|
||||||
|
+ &match_audit->cookie,
|
||||||
|
+ &result_audit->cookie,
|
||||||
|
&flags, strtab + ref->st_name);
|
||||||
|
if (new_value != (uintptr_t) sym.st_value)
|
||||||
|
{
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index f557f39a70669c09..18335bc666f2b89d 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -1025,9 +1025,9 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
|
||||||
|
else
|
||||||
|
*last_audit = (*last_audit)->next = &newp->ifaces;
|
||||||
|
|
||||||
|
- /* The dynamic linker link map is statically allocated, initialize
|
||||||
|
- the data now. */
|
||||||
|
- GL (dl_rtld_map).l_audit[GLRO (dl_naudit)].cookie
|
||||||
|
+ /* The dynamic linker link map is statically allocated, so the
|
||||||
|
+ cookie in _dl_new_object has not happened. */
|
||||||
|
+ link_map_audit_state (&GL (dl_rtld_map), GLRO (dl_naudit))->cookie
|
||||||
|
= (intptr_t) &GL (dl_rtld_map);
|
||||||
|
|
||||||
|
++GLRO(dl_naudit);
|
||||||
|
@@ -1046,9 +1046,9 @@ notify_audit_modules_of_loaded_object (struct link_map *map)
|
||||||
|
{
|
||||||
|
if (afct->objopen != NULL)
|
||||||
|
{
|
||||||
|
- map->l_audit[cnt].bindflags
|
||||||
|
- = afct->objopen (map, LM_ID_BASE, &map->l_audit[cnt].cookie);
|
||||||
|
- map->l_audit_any_plt |= map->l_audit[cnt].bindflags != 0;
|
||||||
|
+ struct auditstate *state = link_map_audit_state (map, cnt);
|
||||||
|
+ state->bindflags = afct->objopen (map, LM_ID_BASE, &state->cookie);
|
||||||
|
+ map->l_audit_any_plt |= state->bindflags != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
@@ -1660,7 +1660,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->activity != NULL)
|
||||||
|
- afct->activity (&main_map->l_audit[cnt].cookie, LA_ACT_ADD);
|
||||||
|
+ afct->activity (&link_map_audit_state (main_map, cnt)->cookie,
|
||||||
|
+ LA_ACT_ADD);
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
@@ -2331,7 +2332,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
{
|
||||||
|
if (afct->activity != NULL)
|
||||||
|
- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT);
|
||||||
|
+ afct->activity (&link_map_audit_state (head, cnt)->cookie,
|
||||||
|
+ LA_ACT_CONSISTENT);
|
||||||
|
|
||||||
|
afct = afct->next;
|
||||||
|
}
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index 3bdbdd6e67dacc85..a8fb0d211426e4b1 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -1197,7 +1197,13 @@ rtld_active (void)
|
||||||
|
initialized and active ld.so copy. */
|
||||||
|
return GLRO(dl_init_all_dirs) != NULL;
|
||||||
|
}
|
||||||
|
-#endif
|
||||||
|
+
|
||||||
|
+static inline struct auditstate *
|
||||||
|
+link_map_audit_state (struct link_map *l, size_t index)
|
||||||
|
+{
|
||||||
|
+ return &l->l_audit[index];
|
||||||
|
+}
|
||||||
|
+#endif /* SHARED */
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
80
SOURCES/glibc-rh1817513-37.patch
Normal file
80
SOURCES/glibc-rh1817513-37.patch
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
commit 4a2ab5843a5cc4a5db1b3b79916a520ea8b115dc
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Nov 8 15:48:51 2019 +0100
|
||||||
|
|
||||||
|
dlsym: Do not determine caller link map if not needed
|
||||||
|
|
||||||
|
Obtaining the link map is potentially very slow because it requires
|
||||||
|
iterating over all loaded objects in the current implementation. If
|
||||||
|
the caller supplied an explicit handle (i.e., not one of the RTLD_*
|
||||||
|
constants), the dlsym implementation does not need the identity of the
|
||||||
|
caller (except in the special case of auditing), so this change
|
||||||
|
avoids computing it in that case.
|
||||||
|
|
||||||
|
Even in the minimal case (dlsym called from a main program linked with
|
||||||
|
-dl), this shows a small speedup, perhaps around five percent. The
|
||||||
|
performance improvement can be arbitrarily large in principle (if
|
||||||
|
_dl_find_dso_for_object has to iterate over many link maps).
|
||||||
|
|
||||||
|
Change-Id: Ide5d9e2cc7ac25a0ffae8fb4c26def0c898efa29
|
||||||
|
|
||||||
|
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
|
||||||
|
index 286cf7e27fd59f20..b133850a3c6657a4 100644
|
||||||
|
--- a/elf/dl-sym.c
|
||||||
|
+++ b/elf/dl-sym.c
|
||||||
|
@@ -80,6 +80,18 @@ call_dl_lookup (void *ptr)
|
||||||
|
args->flags, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Return the link map containing the caller address. */
|
||||||
|
+static inline struct link_map *
|
||||||
|
+find_caller_link_map (ElfW(Addr) caller)
|
||||||
|
+{
|
||||||
|
+ struct link_map *l = _dl_find_dso_for_object (caller);
|
||||||
|
+ if (l != NULL)
|
||||||
|
+ return l;
|
||||||
|
+ else
|
||||||
|
+ /* If the address is not recognized the call comes from the main
|
||||||
|
+ program (we hope). */
|
||||||
|
+ return GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||||
|
+}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
do_sym (void *handle, const char *name, void *who,
|
||||||
|
@@ -89,13 +101,13 @@ do_sym (void *handle, const char *name, void *who,
|
||||||
|
lookup_t result;
|
||||||
|
ElfW(Addr) caller = (ElfW(Addr)) who;
|
||||||
|
|
||||||
|
- struct link_map *l = _dl_find_dso_for_object (caller);
|
||||||
|
- /* If the address is not recognized the call comes from the main
|
||||||
|
- program (we hope). */
|
||||||
|
- struct link_map *match = l ? l : GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||||
|
+ /* Link map of the caller if needed. */
|
||||||
|
+ struct link_map *match = NULL;
|
||||||
|
|
||||||
|
if (handle == RTLD_DEFAULT)
|
||||||
|
{
|
||||||
|
+ match = find_caller_link_map (caller);
|
||||||
|
+
|
||||||
|
/* Search the global scope. We have the simple case where
|
||||||
|
we look up in the scope of an object which was part of
|
||||||
|
the initial binary. And then the more complex part
|
||||||
|
@@ -128,6 +140,8 @@ do_sym (void *handle, const char *name, void *who,
|
||||||
|
}
|
||||||
|
else if (handle == RTLD_NEXT)
|
||||||
|
{
|
||||||
|
+ match = find_caller_link_map (caller);
|
||||||
|
+
|
||||||
|
if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded))
|
||||||
|
{
|
||||||
|
if (match == NULL
|
||||||
|
@@ -187,6 +201,9 @@ RTLD_NEXT used in code not dynamically loaded"));
|
||||||
|
unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
|
||||||
|
l_info[DT_SYMTAB]));
|
||||||
|
|
||||||
|
+ if (match == NULL)
|
||||||
|
+ match = find_caller_link_map (caller);
|
||||||
|
+
|
||||||
|
if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
|
||||||
|
{
|
||||||
|
unsigned int altvalue = 0;
|
211
SOURCES/glibc-rh1817513-38.patch
Normal file
211
SOURCES/glibc-rh1817513-38.patch
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
commit 4f79b3e2fb3eba003240ec38a0e68702b9a60b86
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Mon Feb 3 14:49:25 2020 -0500
|
||||||
|
|
||||||
|
test-container: add exec, cwd
|
||||||
|
|
||||||
|
exec <path_to_test_binary> [optional_argv_0]
|
||||||
|
|
||||||
|
copies test binary to specified location and runs it from
|
||||||
|
there. If the second argument is provided, that will
|
||||||
|
be used for argv[0]
|
||||||
|
|
||||||
|
cwd <directory>
|
||||||
|
|
||||||
|
attempts to chdir(directory) before running test
|
||||||
|
|
||||||
|
Note: "cwd" not "cd" as it takes effect just before the
|
||||||
|
test binary runs, not when it's encountered in the script,
|
||||||
|
so it can't be used as a path shortcut like "cd" would imply.
|
||||||
|
|
||||||
|
cleanup: use xstrdup() instead of strdup()
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index 6503cea90309b9b0..9488ec7b4a824380 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -95,6 +95,8 @@ int verbose = 0;
|
||||||
|
mv FILE FILE
|
||||||
|
cp FILE FILE
|
||||||
|
rm FILE
|
||||||
|
+ cwd PATH
|
||||||
|
+ exec FILE
|
||||||
|
FILE must start with $B/, $S/, $I/, $L/, or /
|
||||||
|
(expands to build dir, source dir, install dir, library dir
|
||||||
|
(in container), or container's root)
|
||||||
|
@@ -104,6 +106,8 @@ int verbose = 0;
|
||||||
|
- 'mv': A minimal move files command.
|
||||||
|
- 'cp': A minimal copy files command.
|
||||||
|
- 'rm': A minimal remove files command.
|
||||||
|
+ - 'cwd': set test working directory
|
||||||
|
+ - 'exec': change test binary location (may end in /)
|
||||||
|
* mytest.root/postclean.req causes fresh rsync (with delete) after
|
||||||
|
test if present
|
||||||
|
|
||||||
|
@@ -147,7 +151,7 @@ maybe_xmkdir (const char *path, mode_t mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Temporarily concatenate multiple strings into one. Allows up to 10
|
||||||
|
- temporary results; use strdup () if you need them to be
|
||||||
|
+ temporary results; use xstrdup () if you need them to be
|
||||||
|
permanent. */
|
||||||
|
static char *
|
||||||
|
concat (const char *str, ...)
|
||||||
|
@@ -670,11 +674,13 @@ main (int argc, char **argv)
|
||||||
|
char *new_objdir_path;
|
||||||
|
char *new_srcdir_path;
|
||||||
|
char **new_child_proc;
|
||||||
|
+ char *new_child_exec;
|
||||||
|
char *command_root;
|
||||||
|
char *command_base;
|
||||||
|
char *command_basename;
|
||||||
|
char *so_base;
|
||||||
|
int do_postclean = 0;
|
||||||
|
+ char *change_cwd = NULL;
|
||||||
|
|
||||||
|
int pipes[2];
|
||||||
|
char pid_buf[20];
|
||||||
|
@@ -701,7 +707,7 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
- fprintf (stderr, "Usage: containerize <program to run> <args...>\n");
|
||||||
|
+ fprintf (stderr, "Usage: test-container <program to run> <args...>\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -746,12 +752,13 @@ main (int argc, char **argv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- pristine_root_path = strdup (concat (support_objdir_root,
|
||||||
|
+ pristine_root_path = xstrdup (concat (support_objdir_root,
|
||||||
|
"/testroot.pristine", NULL));
|
||||||
|
- new_root_path = strdup (concat (support_objdir_root,
|
||||||
|
+ new_root_path = xstrdup (concat (support_objdir_root,
|
||||||
|
"/testroot.root", NULL));
|
||||||
|
new_cwd_path = get_current_dir_name ();
|
||||||
|
new_child_proc = argv + 1;
|
||||||
|
+ new_child_exec = argv[1];
|
||||||
|
|
||||||
|
lock_fd = open (concat (pristine_root_path, "/lock.fd", NULL),
|
||||||
|
O_CREAT | O_TRUNC | O_RDWR, 0666);
|
||||||
|
@@ -778,10 +785,10 @@ main (int argc, char **argv)
|
||||||
|
command_root = concat (support_srcdir_root,
|
||||||
|
argv[1] + strlen (support_objdir_root),
|
||||||
|
".root", NULL);
|
||||||
|
- command_root = strdup (command_root);
|
||||||
|
+ command_root = xstrdup (command_root);
|
||||||
|
|
||||||
|
/* This cuts off the ".root" we appended above. */
|
||||||
|
- command_base = strdup (command_root);
|
||||||
|
+ command_base = xstrdup (command_root);
|
||||||
|
command_base[strlen (command_base) - 5] = 0;
|
||||||
|
|
||||||
|
/* This is the basename of the test we're running. */
|
||||||
|
@@ -792,7 +799,7 @@ main (int argc, char **argv)
|
||||||
|
++command_basename;
|
||||||
|
|
||||||
|
/* Shared object base directory. */
|
||||||
|
- so_base = strdup (argv[1]);
|
||||||
|
+ so_base = xstrdup (argv[1]);
|
||||||
|
if (strrchr (so_base, '/') != NULL)
|
||||||
|
strrchr (so_base, '/')[1] = 0;
|
||||||
|
|
||||||
|
@@ -806,9 +813,9 @@ main (int argc, char **argv)
|
||||||
|
&& S_ISDIR (st.st_mode))
|
||||||
|
rsync (command_root, new_root_path, 0);
|
||||||
|
|
||||||
|
- new_objdir_path = strdup (concat (new_root_path,
|
||||||
|
+ new_objdir_path = xstrdup (concat (new_root_path,
|
||||||
|
support_objdir_root, NULL));
|
||||||
|
- new_srcdir_path = strdup (concat (new_root_path,
|
||||||
|
+ new_srcdir_path = xstrdup (concat (new_root_path,
|
||||||
|
support_srcdir_root, NULL));
|
||||||
|
|
||||||
|
/* new_cwd_path starts with '/' so no "/" needed between the two. */
|
||||||
|
@@ -868,7 +875,10 @@ main (int argc, char **argv)
|
||||||
|
the_words[i] = concat (new_root_path,
|
||||||
|
support_libdir_prefix,
|
||||||
|
the_words[i] + 2, NULL);
|
||||||
|
- else if (the_words[i][0] == '/')
|
||||||
|
+ /* "exec" and "cwd" use inside-root paths. */
|
||||||
|
+ else if (strcmp (the_words[0], "exec") != 0
|
||||||
|
+ && strcmp (the_words[0], "cwd") != 0
|
||||||
|
+ && the_words[i][0] == '/')
|
||||||
|
the_words[i] = concat (new_root_path,
|
||||||
|
the_words[i], NULL);
|
||||||
|
}
|
||||||
|
@@ -912,13 +922,49 @@ main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
maybe_xunlink (the_words[1]);
|
||||||
|
}
|
||||||
|
+ else if (nt >= 2 && strcmp (the_words[0], "exec") == 0)
|
||||||
|
+ {
|
||||||
|
+ /* The first argument is the desired location and name
|
||||||
|
+ of the test binary as we wish to exec it; we will
|
||||||
|
+ copy the binary there. The second (optional)
|
||||||
|
+ argument is the value to pass as argv[0], it
|
||||||
|
+ defaults to the same as the first argument. */
|
||||||
|
+ char *new_exec_path = the_words[1];
|
||||||
|
+
|
||||||
|
+ /* If the new exec path ends with a slash, that's the
|
||||||
|
+ * directory, and use the old test base name. */
|
||||||
|
+ if (new_exec_path [strlen(new_exec_path) - 1] == '/')
|
||||||
|
+ new_exec_path = concat (new_exec_path,
|
||||||
|
+ basename (new_child_proc[0]),
|
||||||
|
+ NULL);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ /* new_child_proc is in the build tree, so has the
|
||||||
|
+ same path inside the chroot as outside. The new
|
||||||
|
+ exec path is, by definition, relative to the
|
||||||
|
+ chroot. */
|
||||||
|
+ copy_one_file (new_child_proc[0], concat (new_root_path,
|
||||||
|
+ new_exec_path,
|
||||||
|
+ NULL));
|
||||||
|
+
|
||||||
|
+ new_child_exec = xstrdup (new_exec_path);
|
||||||
|
+ if (the_words[2])
|
||||||
|
+ new_child_proc[0] = xstrdup (the_words[2]);
|
||||||
|
+ else
|
||||||
|
+ new_child_proc[0] = new_child_exec;
|
||||||
|
+ }
|
||||||
|
+ else if (nt == 2 && strcmp (the_words[0], "cwd") == 0)
|
||||||
|
+ {
|
||||||
|
+ change_cwd = xstrdup (the_words[1]);
|
||||||
|
+ }
|
||||||
|
else if (nt == 1 && strcmp (the_words[0], "su") == 0)
|
||||||
|
{
|
||||||
|
be_su = 1;
|
||||||
|
}
|
||||||
|
else if (nt > 0 && the_words[0][0] != '#')
|
||||||
|
{
|
||||||
|
- printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]);
|
||||||
|
+ fprintf (stderr, "\033[31minvalid [%s]\033[0m\n", the_words[0]);
|
||||||
|
+ exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose (f);
|
||||||
|
@@ -1089,11 +1135,17 @@ main (int argc, char **argv)
|
||||||
|
write (GMAP, tmp, strlen (tmp));
|
||||||
|
xclose (GMAP);
|
||||||
|
|
||||||
|
+ if (change_cwd)
|
||||||
|
+ {
|
||||||
|
+ if (chdir (change_cwd) < 0)
|
||||||
|
+ FAIL_EXIT1 ("Can't cd to %s inside container - ", change_cwd);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Now run the child. */
|
||||||
|
- execvp (new_child_proc[0], new_child_proc);
|
||||||
|
+ execvp (new_child_exec, new_child_proc);
|
||||||
|
|
||||||
|
/* Or don't run the child? */
|
||||||
|
- FAIL_EXIT1 ("Unable to exec %s\n", new_child_proc[0]);
|
||||||
|
+ FAIL_EXIT1 ("Unable to exec %s\n", new_child_exec);
|
||||||
|
|
||||||
|
/* Because gcc won't know error () never returns... */
|
||||||
|
exit (EXIT_UNSUPPORTED);
|
50
SOURCES/glibc-rh1817513-39.patch
Normal file
50
SOURCES/glibc-rh1817513-39.patch
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
commit abcc039d2e26b3c9c723d6419e086753a791b3d5
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Feb 7 20:06:32 2020 +0100
|
||||||
|
|
||||||
|
elf: Introduce the rtld-stubbed-symbols makefile variable
|
||||||
|
|
||||||
|
This generalizes a mechanism used for stack-protector support, so
|
||||||
|
that it can be applied to other symbols if required.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 4ab73dc48d9ac126..a1ea44f231d8cec5 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -474,21 +474,25 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os)
|
||||||
|
# are compiled with special flags, and puts these modules into rtld-libc.a
|
||||||
|
# for us. Then we do the real link using rtld-libc.a instead of libc_pic.a.
|
||||||
|
|
||||||
|
-# If the compiler can do SSP, build the mapfile with dummy __stack_chk_fail
|
||||||
|
-# and __stack_chk_fail_local symbols defined, to prevent the real things
|
||||||
|
-# being dragged into rtld even though rtld is never built with stack-
|
||||||
|
-# protection.
|
||||||
|
+# These symbols need to be stubbed out during symbol discovery because
|
||||||
|
+# their implementation is provided differently in rtld, and the symbol
|
||||||
|
+# discovery mechanism is not compatible with the libc implementation
|
||||||
|
+# when compiled for libc.
|
||||||
|
+rtld-stubbed-symbols =
|
||||||
|
+
|
||||||
|
+# The GCC arguments that implement $(rtld-stubbed-symbols).
|
||||||
|
+rtld-stubbed-symbols-args = \
|
||||||
|
+ $(patsubst %,-Wl$(comma)--defsym=%=0, $(rtld-stubbed-symbols))
|
||||||
|
|
||||||
|
ifeq ($(have-ssp),yes)
|
||||||
|
-dummy-stack-chk-fail := -Wl,--defsym='__stack_chk_fail=0' \
|
||||||
|
- -Wl,--defsym='__stack_chk_fail_local=0'
|
||||||
|
-else
|
||||||
|
-dummy-stack-chk-fail :=
|
||||||
|
+# rtld is not built with the stack protector, so these references will
|
||||||
|
+# go away in the rebuilds.
|
||||||
|
+rtld-stubbed-symbols += __stack_chk_fail __stack_chk_fail_local
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(objpfx)librtld.map: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a
|
||||||
|
@-rm -f $@T
|
||||||
|
- $(reloc-link) -o $@.o $(dummy-stack-chk-fail) \
|
||||||
|
+ $(reloc-link) -o $@.o $(rtld-stubbed-symbols-args) \
|
||||||
|
'-Wl,-(' $^ -lgcc '-Wl,-)' -Wl,-Map,$@T
|
||||||
|
rm -f $@.o
|
||||||
|
mv -f $@T $@
|
64
SOURCES/glibc-rh1817513-4.patch
Normal file
64
SOURCES/glibc-rh1817513-4.patch
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
commit 430388d5dc0e1861b869096f4f5d946d7d74232a
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Fri Aug 3 08:04:49 2018 -0700
|
||||||
|
|
||||||
|
x86: Don't include <init-arch.h> in assembly codes
|
||||||
|
|
||||||
|
There is no need to include <init-arch.h> in assembly codes since all
|
||||||
|
x86 IFUNC selector functions are written in C. Tested on i686 and
|
||||||
|
x86-64. There is no code change in libc.so, ld.so and libmvec.so.
|
||||||
|
|
||||||
|
* sysdeps/i386/i686/multiarch/bzero-ia32.S: Don't include
|
||||||
|
<init-arch.h>.
|
||||||
|
* sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S: Likewise.
|
||||||
|
* sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S: Likewise.
|
||||||
|
* sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S: Likewise.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/i386/i686/multiarch/bzero-ia32.S b/sysdeps/i386/i686/multiarch/bzero-ia32.S
|
||||||
|
index 68ff9e1e903f7c4c..94d13e88f7532bc0 100644
|
||||||
|
--- a/sysdeps/i386/i686/multiarch/bzero-ia32.S
|
||||||
|
+++ b/sysdeps/i386/i686/multiarch/bzero-ia32.S
|
||||||
|
@@ -17,7 +17,6 @@
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
-#include <init-arch.h>
|
||||||
|
|
||||||
|
#if IS_IN (libc)
|
||||||
|
# define __bzero __bzero_ia32
|
||||||
|
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S
|
||||||
|
index b64c3390d6169d18..87536a06a3ed54c6 100644
|
||||||
|
--- a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S
|
||||||
|
+++ b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S
|
||||||
|
@@ -17,7 +17,6 @@
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
-#include <init-arch.h>
|
||||||
|
|
||||||
|
#define _ZGVeN8v_sin _ZGVeN8v_sin_avx2_wrapper
|
||||||
|
#include "../svml_d_sin8_core.S"
|
||||||
|
diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S
|
||||||
|
index e0b7fd787fa6428d..16713ba7142ecad6 100644
|
||||||
|
--- a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S
|
||||||
|
+++ b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S
|
||||||
|
@@ -17,7 +17,6 @@
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
-#include <init-arch.h>
|
||||||
|
|
||||||
|
#define _ZGVeN16v_expf _ZGVeN16v_expf_avx2_wrapper
|
||||||
|
#include "../svml_s_expf16_core.S"
|
||||||
|
diff --git a/sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S
|
||||||
|
index be6671759beaaa84..56b81f5cc5288808 100644
|
||||||
|
--- a/sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S
|
||||||
|
+++ b/sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S
|
||||||
|
@@ -19,7 +19,6 @@
|
||||||
|
|
||||||
|
#include <sysdep.h>
|
||||||
|
#include <shlib-compat.h>
|
||||||
|
-#include <init-arch.h>
|
||||||
|
|
||||||
|
#if IS_IN (libc)
|
||||||
|
# define MEMSET_SYMBOL(p,s) p##_sse2_##s
|
248
SOURCES/glibc-rh1817513-40.patch
Normal file
248
SOURCES/glibc-rh1817513-40.patch
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
commit c76147afe917ef7d309ee893f8f017a3c2934aac
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Sat Feb 8 15:00:28 2020 +0100
|
||||||
|
|
||||||
|
elf: Extract _dl_sym_post, _dl_sym_find_caller_map from elf/dl-sym.c
|
||||||
|
|
||||||
|
The definitions are moved into a new file, elf/dl-sym-post.h, so that
|
||||||
|
this code can be used by the dynamic loader as well.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-sym-post.h b/elf/dl-sym-post.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..4c4f574633497789
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/dl-sym-post.h
|
||||||
|
@@ -0,0 +1,106 @@
|
||||||
|
+/* Post-processing of a symbol produced by dlsym, dlvsym.
|
||||||
|
+ Copyright (C) 1999-2020 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/>. */
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Return the link map containing the caller address. */
|
||||||
|
+static struct link_map *
|
||||||
|
+_dl_sym_find_caller_link_map (ElfW(Addr) caller)
|
||||||
|
+{
|
||||||
|
+ struct link_map *l = _dl_find_dso_for_object (caller);
|
||||||
|
+ if (l != NULL)
|
||||||
|
+ return l;
|
||||||
|
+ else
|
||||||
|
+ /* If the address is not recognized the call comes from the main
|
||||||
|
+ program (we hope). */
|
||||||
|
+ return GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Translates RESULT, *REF, VALUE into a symbol address from the point
|
||||||
|
+ of view of MATCH. Performs IFUNC resolution and auditing if
|
||||||
|
+ necessary. If MATCH is NULL, CALLER is used to determine it. */
|
||||||
|
+static void *
|
||||||
|
+_dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value,
|
||||||
|
+ ElfW(Addr) caller, struct link_map *match)
|
||||||
|
+{
|
||||||
|
+ /* Resolve indirect function address. */
|
||||||
|
+ if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC))
|
||||||
|
+ {
|
||||||
|
+ DL_FIXUP_VALUE_TYPE fixup
|
||||||
|
+ = DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value);
|
||||||
|
+ fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup));
|
||||||
|
+ value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ /* Auditing checkpoint: we have a new binding. Provide the
|
||||||
|
+ auditing libraries the possibility to change the value and
|
||||||
|
+ tell us whether further auditing is wanted. */
|
||||||
|
+ if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||||
|
+ {
|
||||||
|
+ const char *strtab = (const char *) D_PTR (result,
|
||||||
|
+ l_info[DT_STRTAB]);
|
||||||
|
+ /* Compute index of the symbol entry in the symbol table of
|
||||||
|
+ the DSO with the definition. */
|
||||||
|
+ unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
|
||||||
|
+ l_info[DT_SYMTAB]));
|
||||||
|
+
|
||||||
|
+ if (match == NULL)
|
||||||
|
+ match = _dl_sym_find_caller_link_map (caller);
|
||||||
|
+
|
||||||
|
+ if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
|
||||||
|
+ {
|
||||||
|
+ unsigned int altvalue = 0;
|
||||||
|
+ struct audit_ifaces *afct = GLRO(dl_audit);
|
||||||
|
+ /* Synthesize a symbol record where the st_value field is
|
||||||
|
+ the result. */
|
||||||
|
+ ElfW(Sym) sym = *ref;
|
||||||
|
+ sym.st_value = (ElfW(Addr)) value;
|
||||||
|
+
|
||||||
|
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
+ {
|
||||||
|
+ struct auditstate *match_audit
|
||||||
|
+ = link_map_audit_state (match, cnt);
|
||||||
|
+ struct auditstate *result_audit
|
||||||
|
+ = link_map_audit_state (result, cnt);
|
||||||
|
+ if (afct->symbind != NULL
|
||||||
|
+ && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
|
||||||
|
+ || ((result_audit->bindflags & LA_FLG_BINDTO)
|
||||||
|
+ != 0)))
|
||||||
|
+ {
|
||||||
|
+ unsigned int flags = altvalue | LA_SYMB_DLSYM;
|
||||||
|
+ uintptr_t new_value
|
||||||
|
+ = afct->symbind (&sym, ndx,
|
||||||
|
+ &match_audit->cookie,
|
||||||
|
+ &result_audit->cookie,
|
||||||
|
+ &flags, strtab + ref->st_name);
|
||||||
|
+ if (new_value != (uintptr_t) sym.st_value)
|
||||||
|
+ {
|
||||||
|
+ altvalue = LA_SYMB_ALTVALUE;
|
||||||
|
+ sym.st_value = new_value;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ afct = afct->next;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ value = (void *) sym.st_value;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ return value;
|
||||||
|
+}
|
||||||
|
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
|
||||||
|
index b133850a3c6657a4..5698fd7874a0ce48 100644
|
||||||
|
--- a/elf/dl-sym.c
|
||||||
|
+++ b/elf/dl-sym.c
|
||||||
|
@@ -28,6 +28,7 @@
|
||||||
|
#include <sysdep-cancel.h>
|
||||||
|
#include <dl-tls.h>
|
||||||
|
#include <dl-irel.h>
|
||||||
|
+#include <dl-sym-post.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SHARED
|
||||||
|
@@ -80,19 +81,6 @@ call_dl_lookup (void *ptr)
|
||||||
|
args->flags, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Return the link map containing the caller address. */
|
||||||
|
-static inline struct link_map *
|
||||||
|
-find_caller_link_map (ElfW(Addr) caller)
|
||||||
|
-{
|
||||||
|
- struct link_map *l = _dl_find_dso_for_object (caller);
|
||||||
|
- if (l != NULL)
|
||||||
|
- return l;
|
||||||
|
- else
|
||||||
|
- /* If the address is not recognized the call comes from the main
|
||||||
|
- program (we hope). */
|
||||||
|
- return GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void *
|
||||||
|
do_sym (void *handle, const char *name, void *who,
|
||||||
|
struct r_found_version *vers, int flags)
|
||||||
|
@@ -106,7 +94,7 @@ do_sym (void *handle, const char *name, void *who,
|
||||||
|
|
||||||
|
if (handle == RTLD_DEFAULT)
|
||||||
|
{
|
||||||
|
- match = find_caller_link_map (caller);
|
||||||
|
+ match = _dl_sym_find_caller_link_map (caller);
|
||||||
|
|
||||||
|
/* Search the global scope. We have the simple case where
|
||||||
|
we look up in the scope of an object which was part of
|
||||||
|
@@ -140,7 +128,7 @@ do_sym (void *handle, const char *name, void *who,
|
||||||
|
}
|
||||||
|
else if (handle == RTLD_NEXT)
|
||||||
|
{
|
||||||
|
- match = find_caller_link_map (caller);
|
||||||
|
+ match = _dl_sym_find_caller_link_map (caller);
|
||||||
|
|
||||||
|
if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded))
|
||||||
|
{
|
||||||
|
@@ -179,73 +167,7 @@ RTLD_NEXT used in code not dynamically loaded"));
|
||||||
|
#endif
|
||||||
|
value = DL_SYMBOL_ADDRESS (result, ref);
|
||||||
|
|
||||||
|
- /* Resolve indirect function address. */
|
||||||
|
- if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC))
|
||||||
|
- {
|
||||||
|
- DL_FIXUP_VALUE_TYPE fixup
|
||||||
|
- = DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value);
|
||||||
|
- fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup));
|
||||||
|
- value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-#ifdef SHARED
|
||||||
|
- /* Auditing checkpoint: we have a new binding. Provide the
|
||||||
|
- auditing libraries the possibility to change the value and
|
||||||
|
- tell us whether further auditing is wanted. */
|
||||||
|
- if (__glibc_unlikely (GLRO(dl_naudit) > 0))
|
||||||
|
- {
|
||||||
|
- const char *strtab = (const char *) D_PTR (result,
|
||||||
|
- l_info[DT_STRTAB]);
|
||||||
|
- /* Compute index of the symbol entry in the symbol table of
|
||||||
|
- the DSO with the definition. */
|
||||||
|
- unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
|
||||||
|
- l_info[DT_SYMTAB]));
|
||||||
|
-
|
||||||
|
- if (match == NULL)
|
||||||
|
- match = find_caller_link_map (caller);
|
||||||
|
-
|
||||||
|
- if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
|
||||||
|
- {
|
||||||
|
- unsigned int altvalue = 0;
|
||||||
|
- struct audit_ifaces *afct = GLRO(dl_audit);
|
||||||
|
- /* Synthesize a symbol record where the st_value field is
|
||||||
|
- the result. */
|
||||||
|
- ElfW(Sym) sym = *ref;
|
||||||
|
- sym.st_value = (ElfW(Addr)) value;
|
||||||
|
-
|
||||||
|
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
|
||||||
|
- {
|
||||||
|
- struct auditstate *match_audit
|
||||||
|
- = link_map_audit_state (match, cnt);
|
||||||
|
- struct auditstate *result_audit
|
||||||
|
- = link_map_audit_state (result, cnt);
|
||||||
|
- if (afct->symbind != NULL
|
||||||
|
- && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
|
||||||
|
- || ((result_audit->bindflags & LA_FLG_BINDTO)
|
||||||
|
- != 0)))
|
||||||
|
- {
|
||||||
|
- unsigned int flags = altvalue | LA_SYMB_DLSYM;
|
||||||
|
- uintptr_t new_value
|
||||||
|
- = afct->symbind (&sym, ndx,
|
||||||
|
- &match_audit->cookie,
|
||||||
|
- &result_audit->cookie,
|
||||||
|
- &flags, strtab + ref->st_name);
|
||||||
|
- if (new_value != (uintptr_t) sym.st_value)
|
||||||
|
- {
|
||||||
|
- altvalue = LA_SYMB_ALTVALUE;
|
||||||
|
- sym.st_value = new_value;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- afct = afct->next;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- value = (void *) sym.st_value;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
- return value;
|
||||||
|
+ return _dl_sym_post (result, ref, value, caller, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
1102
SOURCES/glibc-rh1817513-41.patch
Normal file
1102
SOURCES/glibc-rh1817513-41.patch
Normal file
File diff suppressed because it is too large
Load Diff
46
SOURCES/glibc-rh1817513-42.patch
Normal file
46
SOURCES/glibc-rh1817513-42.patch
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
commit 758599bc9dcc5764e862bd9e1613c5d1e6efc5d3
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Feb 26 15:58:23 2020 +0100
|
||||||
|
|
||||||
|
elf: Apply attribute_relro to pointers in elf/dl-minimal.c
|
||||||
|
|
||||||
|
The present code leaves the function pointers unprotected, but moves
|
||||||
|
some of the static functions into .data.rel.ro instead. This causes
|
||||||
|
the linker to produce an allocatable, executable, writable section
|
||||||
|
and eventually an RWX load segment. Not only do we really do not
|
||||||
|
want that, it also breaks valgrind because valgrind does not load
|
||||||
|
debuginfo from the mmap interceptor if all it sees are RX and RWX
|
||||||
|
mappings.
|
||||||
|
|
||||||
|
Fixes commit 3a0ecccb599a6b1ad4b149dc569c0080e92d057b ("ld.so: Do not
|
||||||
|
export free/calloc/malloc/realloc functions [BZ #25486]").
|
||||||
|
|
||||||
|
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
|
||||||
|
index 95ea7b024044864f..4335f1bd24289b01 100644
|
||||||
|
--- a/elf/dl-minimal.c
|
||||||
|
+++ b/elf/dl-minimal.c
|
||||||
|
@@ -39,16 +39,16 @@
|
||||||
|
implementation below. Before the final relocation,
|
||||||
|
__rtld_malloc_init_real is called to replace the pointers with the
|
||||||
|
real implementation. */
|
||||||
|
-__typeof (calloc) *__rtld_calloc;
|
||||||
|
-__typeof (free) *__rtld_free;
|
||||||
|
-__typeof (malloc) *__rtld_malloc;
|
||||||
|
-__typeof (realloc) *__rtld_realloc;
|
||||||
|
+__typeof (calloc) *__rtld_calloc attribute_relro;
|
||||||
|
+__typeof (free) *__rtld_free attribute_relro;
|
||||||
|
+__typeof (malloc) *__rtld_malloc attribute_relro;
|
||||||
|
+__typeof (realloc) *__rtld_realloc attribute_relro;
|
||||||
|
|
||||||
|
/* Defined below. */
|
||||||
|
-static __typeof (calloc) rtld_calloc attribute_relro;
|
||||||
|
-static __typeof (free) rtld_free attribute_relro;
|
||||||
|
-static __typeof (malloc) rtld_malloc attribute_relro;
|
||||||
|
-static __typeof (realloc) rtld_realloc attribute_relro;
|
||||||
|
+static __typeof (calloc) rtld_calloc;
|
||||||
|
+static __typeof (free) rtld_free;
|
||||||
|
+static __typeof (malloc) rtld_malloc;
|
||||||
|
+static __typeof (realloc) rtld_realloc;
|
||||||
|
|
||||||
|
void
|
||||||
|
__rtld_malloc_init_stubs (void)
|
356
SOURCES/glibc-rh1817513-43.patch
Normal file
356
SOURCES/glibc-rh1817513-43.patch
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
commit dfe9aa91564c1bf2a23b5589a5db42f9da5d29b5
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Tue Nov 19 17:17:05 2019 -0300
|
||||||
|
|
||||||
|
support: Add support_process_state_wait
|
||||||
|
|
||||||
|
It allows parent process to wait for child state using a polling
|
||||||
|
strategy over procfs on Linux. The polling is used over ptrace to
|
||||||
|
avoid the need to handle signals on the target pid and to handle some
|
||||||
|
system specific limitation (such as YAMA).
|
||||||
|
|
||||||
|
The polling has some limitations, such as resource consumption due
|
||||||
|
the procfs read in a loop and the lack of synchronization after the
|
||||||
|
state is obtained.
|
||||||
|
|
||||||
|
The interface idea is to simplify some sleep synchronization waitid
|
||||||
|
tests and is to reduce timeouts by replacing arbitrary waits.
|
||||||
|
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 79d03bd6bfe02540..117cfdd4f22fc405 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -58,6 +58,7 @@ libsupport-routines = \
|
||||||
|
support_format_hostent \
|
||||||
|
support_format_netent \
|
||||||
|
support_isolate_in_subprocess \
|
||||||
|
+ support_process_state \
|
||||||
|
support_ptrace \
|
||||||
|
support_openpty \
|
||||||
|
support_paths \
|
||||||
|
@@ -90,6 +91,7 @@ libsupport-routines = \
|
||||||
|
xfopen \
|
||||||
|
xfork \
|
||||||
|
xftruncate \
|
||||||
|
+ xgetline \
|
||||||
|
xgetsockname \
|
||||||
|
xlisten \
|
||||||
|
xlseek \
|
||||||
|
@@ -217,6 +219,7 @@ tests = \
|
||||||
|
tst-support_capture_subprocess \
|
||||||
|
tst-support_descriptors \
|
||||||
|
tst-support_format_dns_packet \
|
||||||
|
+ tst-support-process_state \
|
||||||
|
tst-support_quote_blob \
|
||||||
|
tst-support_quote_string \
|
||||||
|
tst-support_record_failure \
|
||||||
|
diff --git a/support/process_state.h b/support/process_state.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..6c19afdbb7462277
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/process_state.h
|
||||||
|
@@ -0,0 +1,43 @@
|
||||||
|
+/* Wait for process state.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#ifndef SUPPORT_PROCESS_STATE_H
|
||||||
|
+#define SUPPORT_PROCESS_STATE_H
|
||||||
|
+
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+
|
||||||
|
+enum support_process_state
|
||||||
|
+{
|
||||||
|
+ support_process_state_running = 0x01, /* R (running). */
|
||||||
|
+ support_process_state_sleeping = 0x02, /* S (sleeping). */
|
||||||
|
+ support_process_state_disk_sleep = 0x04, /* D (disk sleep). */
|
||||||
|
+ support_process_state_stopped = 0x08, /* T (stopped). */
|
||||||
|
+ support_process_state_tracing_stop = 0x10, /* t (tracing stop). */
|
||||||
|
+ support_process_state_dead = 0x20, /* X (dead). */
|
||||||
|
+ support_process_state_zombie = 0x40, /* Z (zombie). */
|
||||||
|
+ support_process_state_parked = 0x80, /* P (parked). */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Wait for process PID to reach state STATE. It can be a combination of
|
||||||
|
+ multiple possible states ('process_state_running | process_state_sleeping')
|
||||||
|
+ where the function return when any of these state are observed.
|
||||||
|
+ For an invalid state not represented by SUPPORT_PROCESS_STATE, it fallbacks
|
||||||
|
+ to a 2 second sleep. */
|
||||||
|
+void support_process_state_wait (pid_t pid, enum support_process_state state);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff --git a/support/support_process_state.c b/support/support_process_state.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..76dc798728ece0d9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/support_process_state.c
|
||||||
|
@@ -0,0 +1,92 @@
|
||||||
|
+/* Wait for process state.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <time.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+
|
||||||
|
+#include <array_length.h>
|
||||||
|
+
|
||||||
|
+#include <support/process_state.h>
|
||||||
|
+#include <support/xstdio.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+support_process_state_wait (pid_t pid, enum support_process_state state)
|
||||||
|
+{
|
||||||
|
+#ifdef __linux__
|
||||||
|
+ /* For Linux it does a polling check on /proc/<pid>/status checking on
|
||||||
|
+ third field. */
|
||||||
|
+
|
||||||
|
+ /* It mimics the kernel states from fs/proc/array.c */
|
||||||
|
+ static const struct process_states
|
||||||
|
+ {
|
||||||
|
+ enum support_process_state s;
|
||||||
|
+ char v;
|
||||||
|
+ } process_states[] = {
|
||||||
|
+ { support_process_state_running, 'R' },
|
||||||
|
+ { support_process_state_sleeping, 'S' },
|
||||||
|
+ { support_process_state_disk_sleep, 'D' },
|
||||||
|
+ { support_process_state_stopped, 'T' },
|
||||||
|
+ { support_process_state_tracing_stop, 't' },
|
||||||
|
+ { support_process_state_dead, 'X' },
|
||||||
|
+ { support_process_state_zombie, 'Z' },
|
||||||
|
+ { support_process_state_parked, 'P' },
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ char spath[sizeof ("/proc/" + 3) * sizeof (pid_t) + sizeof ("/status") + 1];
|
||||||
|
+ snprintf (spath, sizeof (spath), "/proc/%i/status", pid);
|
||||||
|
+
|
||||||
|
+ FILE *fstatus = xfopen (spath, "r");
|
||||||
|
+ char *line = NULL;
|
||||||
|
+ size_t linesiz = 0;
|
||||||
|
+
|
||||||
|
+ for (;;)
|
||||||
|
+ {
|
||||||
|
+ char cur_state = -1;
|
||||||
|
+ while (xgetline (&line, &linesiz, fstatus) != -1)
|
||||||
|
+ if (strncmp (line, "State:", strlen ("State:")) == 0)
|
||||||
|
+ {
|
||||||
|
+ TEST_COMPARE (sscanf (line, "%*s %c", &cur_state), 1);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* Fallback to nanosleep for invalid state. */
|
||||||
|
+ if (cur_state == -1)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ for (size_t i = 0; i < array_length (process_states); ++i)
|
||||||
|
+ if (state & process_states[i].s && cur_state == process_states[i].v)
|
||||||
|
+ {
|
||||||
|
+ free (line);
|
||||||
|
+ xfclose (fstatus);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rewind (fstatus);
|
||||||
|
+ fflush (fstatus);
|
||||||
|
+
|
||||||
|
+ if (nanosleep (&(struct timespec) { 0, 10000000 }, NULL) != 0)
|
||||||
|
+ FAIL_EXIT1 ("nanosleep: %m");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free (line);
|
||||||
|
+ xfclose (fstatus);
|
||||||
|
+ /* Fallback to nanosleep if an invalid state is found. */
|
||||||
|
+#endif
|
||||||
|
+ nanosleep (&(struct timespec) { 2, 0 }, NULL);
|
||||||
|
+}
|
||||||
|
diff --git a/support/tst-support-process_state.c b/support/tst-support-process_state.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..3fc103ab9205ddb0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/tst-support-process_state.c
|
||||||
|
@@ -0,0 +1,105 @@
|
||||||
|
+/* Wait for process state tests.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <sys/wait.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.h>
|
||||||
|
+#include <support/process_state.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xsignal.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+
|
||||||
|
+#ifndef WEXITED
|
||||||
|
+# define WEXITED 0
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sigusr1_handler (int signo)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+test_child (void)
|
||||||
|
+{
|
||||||
|
+ xsignal (SIGUSR1, sigusr1_handler);
|
||||||
|
+
|
||||||
|
+ raise (SIGSTOP);
|
||||||
|
+
|
||||||
|
+ TEST_COMPARE (pause (), -1);
|
||||||
|
+ TEST_COMPARE (errno, EINTR);
|
||||||
|
+
|
||||||
|
+ while (1)
|
||||||
|
+ asm ("");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ pid_t pid = xfork ();
|
||||||
|
+ if (pid == 0)
|
||||||
|
+ {
|
||||||
|
+ test_child ();
|
||||||
|
+ _exit (127);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Adding process_state_tracing_stop ('t') allows the test to work under
|
||||||
|
+ trace programs such as ptrace. */
|
||||||
|
+ enum support_process_state stop_state = support_process_state_stopped
|
||||||
|
+ | support_process_state_tracing_stop;
|
||||||
|
+
|
||||||
|
+ if (test_verbose)
|
||||||
|
+ printf ("info: waiting pid %d, state_stopped/state_tracing_stop\n",
|
||||||
|
+ (int) pid);
|
||||||
|
+ support_process_state_wait (pid, stop_state);
|
||||||
|
+
|
||||||
|
+ if (kill (pid, SIGCONT) != 0)
|
||||||
|
+ FAIL_RET ("kill (%d, SIGCONT): %m\n", pid);
|
||||||
|
+
|
||||||
|
+ if (test_verbose)
|
||||||
|
+ printf ("info: waiting pid %d, state_sleeping\n", (int) pid);
|
||||||
|
+ support_process_state_wait (pid, support_process_state_sleeping);
|
||||||
|
+
|
||||||
|
+ if (kill (pid, SIGUSR1) != 0)
|
||||||
|
+ FAIL_RET ("kill (%d, SIGUSR1): %m\n", pid);
|
||||||
|
+
|
||||||
|
+ if (test_verbose)
|
||||||
|
+ printf ("info: waiting pid %d, state_running\n", (int) pid);
|
||||||
|
+ support_process_state_wait (pid, support_process_state_running);
|
||||||
|
+
|
||||||
|
+ if (kill (pid, SIGKILL) != 0)
|
||||||
|
+ FAIL_RET ("kill (%d, SIGKILL): %m\n", pid);
|
||||||
|
+
|
||||||
|
+ if (test_verbose)
|
||||||
|
+ printf ("info: waiting pid %d, state_zombie\n", (int) pid);
|
||||||
|
+ support_process_state_wait (pid, support_process_state_zombie);
|
||||||
|
+
|
||||||
|
+ siginfo_t info;
|
||||||
|
+ int r = waitid (P_PID, pid, &info, WEXITED);
|
||||||
|
+ TEST_COMPARE (r, 0);
|
||||||
|
+ TEST_COMPARE (info.si_signo, SIGCHLD);
|
||||||
|
+ TEST_COMPARE (info.si_code, CLD_KILLED);
|
||||||
|
+ TEST_COMPARE (info.si_status, SIGKILL);
|
||||||
|
+ TEST_COMPARE (info.si_pid, pid);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/support/xgetline.c b/support/xgetline.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..180bc2db95a9c5d4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/support/xgetline.c
|
||||||
|
@@ -0,0 +1,33 @@
|
||||||
|
+/* fopen with error checking.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <support/xstdio.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+
|
||||||
|
+ssize_t
|
||||||
|
+xgetline (char **lineptr, size_t *n, FILE *stream)
|
||||||
|
+{
|
||||||
|
+ int old_errno = errno;
|
||||||
|
+ errno = 0;
|
||||||
|
+ size_t ret = getline (lineptr, n, stream);
|
||||||
|
+ if (!feof (stream) && ferror (stream))
|
||||||
|
+ FAIL_EXIT1 ("getline failed: %m");
|
||||||
|
+ errno = old_errno;
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
diff --git a/support/xstdio.h b/support/xstdio.h
|
||||||
|
index e7d0274474706380..9446b1f27b0f881e 100644
|
||||||
|
--- a/support/xstdio.h
|
||||||
|
+++ b/support/xstdio.h
|
||||||
|
@@ -27,6 +27,8 @@ __BEGIN_DECLS
|
||||||
|
FILE *xfopen (const char *path, const char *mode);
|
||||||
|
void xfclose (FILE *);
|
||||||
|
|
||||||
|
+ssize_t xgetline (char **lineptr, size_t *n, FILE *stream);
|
||||||
|
+
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* SUPPORT_XSTDIO_H */
|
24
SOURCES/glibc-rh1817513-44.patch
Normal file
24
SOURCES/glibc-rh1817513-44.patch
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
commit 083d644d420f49c992667f4c7a54848ad3dee54d
|
||||||
|
Author: Michael Hudson-Doyle <michael.hudson@canonical.com>
|
||||||
|
Date: Wed Mar 11 13:05:25 2020 +1300
|
||||||
|
|
||||||
|
test-container: print errno when execvp fails
|
||||||
|
|
||||||
|
I'm debugging a situation where lots of tests using test-container fail
|
||||||
|
and it's possible knowing errno would help understand why.
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index 9488ec7b4a824380..9eff8baeef0e9d8a 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -1145,7 +1145,7 @@ main (int argc, char **argv)
|
||||||
|
execvp (new_child_exec, new_child_proc);
|
||||||
|
|
||||||
|
/* Or don't run the child? */
|
||||||
|
- FAIL_EXIT1 ("Unable to exec %s\n", new_child_exec);
|
||||||
|
+ FAIL_EXIT1 ("Unable to exec %s: %s\n", new_child_exec, strerror (errno));
|
||||||
|
|
||||||
|
/* Because gcc won't know error () never returns... */
|
||||||
|
exit (EXIT_UNSUPPORTED);
|
106
SOURCES/glibc-rh1817513-45.patch
Normal file
106
SOURCES/glibc-rh1817513-45.patch
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
commit b7176cc2aff4a8883e4834ddf65f8a6fdb1f160e
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Wed Feb 19 12:31:38 2020 -0500
|
||||||
|
|
||||||
|
ldconfig: trace origin paths with -v
|
||||||
|
|
||||||
|
With this patch, -v turns on a "from" trace for each directory
|
||||||
|
searched, that tells you WHY that directory is being searched -
|
||||||
|
is it a builtin, from the command line, or from some config file?
|
||||||
|
|
||||||
|
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||||
|
index ed7d9ab0412d93fd..5e6516688a1c192a 100644
|
||||||
|
--- a/elf/ldconfig.c
|
||||||
|
+++ b/elf/ldconfig.c
|
||||||
|
@@ -79,6 +79,8 @@ struct dir_entry
|
||||||
|
int flag;
|
||||||
|
ino64_t ino;
|
||||||
|
dev_t dev;
|
||||||
|
+ const char *from_file;
|
||||||
|
+ int from_line;
|
||||||
|
struct dir_entry *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -344,7 +346,12 @@ add_single_dir (struct dir_entry *entry, int verbose)
|
||||||
|
if (ptr->ino == entry->ino && ptr->dev == entry->dev)
|
||||||
|
{
|
||||||
|
if (opt_verbose && verbose)
|
||||||
|
- error (0, 0, _("Path `%s' given more than once"), entry->path);
|
||||||
|
+ {
|
||||||
|
+ error (0, 0, _("Path `%s' given more than once"), entry->path);
|
||||||
|
+ fprintf (stderr, _("(from %s:%d and %s:%d)\n"),
|
||||||
|
+ entry->from_file, entry->from_line,
|
||||||
|
+ ptr->from_file, ptr->from_line);
|
||||||
|
+ }
|
||||||
|
/* Use the newer information. */
|
||||||
|
ptr->flag = entry->flag;
|
||||||
|
free (entry->path);
|
||||||
|
@@ -363,12 +370,15 @@ add_single_dir (struct dir_entry *entry, int verbose)
|
||||||
|
|
||||||
|
/* Add one directory to the list of directories to process. */
|
||||||
|
static void
|
||||||
|
-add_dir (const char *line)
|
||||||
|
+add_dir_1 (const char *line, const char *from_file, int from_line)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
struct dir_entry *entry = xmalloc (sizeof (struct dir_entry));
|
||||||
|
entry->next = NULL;
|
||||||
|
|
||||||
|
+ entry->from_file = strdup (from_file);
|
||||||
|
+ entry->from_line = from_line;
|
||||||
|
+
|
||||||
|
/* Search for an '=' sign. */
|
||||||
|
entry->path = xstrdup (line);
|
||||||
|
char *equal_sign = strchr (entry->path, '=');
|
||||||
|
@@ -428,6 +438,11 @@ add_dir (const char *line)
|
||||||
|
free (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+add_dir (const char *line)
|
||||||
|
+{
|
||||||
|
+ add_dir_1 (line, "<builtin>", 0);
|
||||||
|
+}
|
||||||
|
|
||||||
|
static int
|
||||||
|
chroot_stat (const char *real_path, const char *path, struct stat64 *st)
|
||||||
|
@@ -672,9 +687,10 @@ search_dir (const struct dir_entry *entry)
|
||||||
|
if (opt_verbose)
|
||||||
|
{
|
||||||
|
if (hwcap != 0)
|
||||||
|
- printf ("%s: (hwcap: %#.16" PRIx64 ")\n", entry->path, hwcap);
|
||||||
|
+ printf ("%s: (hwcap: %#.16" PRIx64 ")", entry->path, hwcap);
|
||||||
|
else
|
||||||
|
- printf ("%s:\n", entry->path);
|
||||||
|
+ printf ("%s:", entry->path);
|
||||||
|
+ printf (_(" (from %s:%d)\n"), entry->from_file, entry->from_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *dir_name;
|
||||||
|
@@ -815,6 +831,8 @@ search_dir (const struct dir_entry *entry)
|
||||||
|
struct dir_entry *new_entry;
|
||||||
|
|
||||||
|
new_entry = xmalloc (sizeof (struct dir_entry));
|
||||||
|
+ new_entry->from_file = entry->from_file;
|
||||||
|
+ new_entry->from_line = entry->from_line;
|
||||||
|
new_entry->path = xstrdup (file_name);
|
||||||
|
new_entry->flag = entry->flag;
|
||||||
|
new_entry->next = NULL;
|
||||||
|
@@ -1174,7 +1192,7 @@ Warning: ignoring configuration file that cannot be opened: %s"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
- add_dir (cp);
|
||||||
|
+ add_dir_1 (cp, filename, lineno);
|
||||||
|
}
|
||||||
|
while (!feof_unlocked (file));
|
||||||
|
|
||||||
|
@@ -1282,7 +1300,7 @@ main (int argc, char **argv)
|
||||||
|
_("relative path `%s' used to build cache"),
|
||||||
|
argv[i]);
|
||||||
|
else
|
||||||
|
- add_dir (argv[i]);
|
||||||
|
+ add_dir_1 (argv[i], "<cmdline>", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The last entry in hwcap_extra is reserved for the "tls" pseudo-hwcap which
|
83
SOURCES/glibc-rh1817513-46.patch
Normal file
83
SOURCES/glibc-rh1817513-46.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
commit cea56af185eae45b1f0963351e3d4daa1cbde521
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Apr 2 17:09:36 2020 +0200
|
||||||
|
|
||||||
|
support: Change xgetline to return 0 on EOF
|
||||||
|
|
||||||
|
The advantage is that the buffer will always contain the number
|
||||||
|
of characters as returned from the function, which allows one to use
|
||||||
|
a sequence like
|
||||||
|
|
||||||
|
/* No more audit module output. */
|
||||||
|
line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
TEST_COMPARE_BLOB ("", 0, buffer, line_length);
|
||||||
|
|
||||||
|
to check for an expected EOF, while also reporting any unexpected
|
||||||
|
extra data encountered.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/support_process_state.c b/support/support_process_state.c
|
||||||
|
index 76dc798728ece0d9..e303c78fc874b2f9 100644
|
||||||
|
--- a/support/support_process_state.c
|
||||||
|
+++ b/support/support_process_state.c
|
||||||
|
@@ -59,7 +59,7 @@ support_process_state_wait (pid_t pid, enum support_process_state state)
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
char cur_state = -1;
|
||||||
|
- while (xgetline (&line, &linesiz, fstatus) != -1)
|
||||||
|
+ while (xgetline (&line, &linesiz, fstatus) > 0)
|
||||||
|
if (strncmp (line, "State:", strlen ("State:")) == 0)
|
||||||
|
{
|
||||||
|
TEST_COMPARE (sscanf (line, "%*s %c", &cur_state), 1);
|
||||||
|
diff --git a/support/xgetline.c b/support/xgetline.c
|
||||||
|
index 180bc2db95a9c5d4..d91c09ac108b4c75 100644
|
||||||
|
--- a/support/xgetline.c
|
||||||
|
+++ b/support/xgetline.c
|
||||||
|
@@ -18,16 +18,22 @@
|
||||||
|
|
||||||
|
#include <support/xstdio.h>
|
||||||
|
#include <support/check.h>
|
||||||
|
-#include <errno.h>
|
||||||
|
|
||||||
|
-ssize_t
|
||||||
|
+size_t
|
||||||
|
xgetline (char **lineptr, size_t *n, FILE *stream)
|
||||||
|
{
|
||||||
|
- int old_errno = errno;
|
||||||
|
- errno = 0;
|
||||||
|
- size_t ret = getline (lineptr, n, stream);
|
||||||
|
- if (!feof (stream) && ferror (stream))
|
||||||
|
- FAIL_EXIT1 ("getline failed: %m");
|
||||||
|
- errno = old_errno;
|
||||||
|
+ TEST_VERIFY (!ferror (stream));
|
||||||
|
+ ssize_t ret = getline (lineptr, n, stream);
|
||||||
|
+ if (ferror (stream))
|
||||||
|
+ {
|
||||||
|
+ TEST_VERIFY (ret < 0);
|
||||||
|
+ FAIL_EXIT1 ("getline: %m");
|
||||||
|
+ }
|
||||||
|
+ if (feof (stream))
|
||||||
|
+ {
|
||||||
|
+ TEST_VERIFY (ret <= 0);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ TEST_VERIFY (ret > 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
diff --git a/support/xstdio.h b/support/xstdio.h
|
||||||
|
index 9446b1f27b0f881e..36071cf78822ec8d 100644
|
||||||
|
--- a/support/xstdio.h
|
||||||
|
+++ b/support/xstdio.h
|
||||||
|
@@ -27,7 +27,10 @@ __BEGIN_DECLS
|
||||||
|
FILE *xfopen (const char *path, const char *mode);
|
||||||
|
void xfclose (FILE *);
|
||||||
|
|
||||||
|
-ssize_t xgetline (char **lineptr, size_t *n, FILE *stream);
|
||||||
|
+/* Read a line from FP, using getline. *BUFFER must be NULL, or a
|
||||||
|
+ heap-allocated pointer of *LENGTH bytes. Return the number of
|
||||||
|
+ bytes in the line if a line was read, or 0 on EOF. */
|
||||||
|
+size_t xgetline (char **lineptr, size_t *n, FILE *stream);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
373
SOURCES/glibc-rh1817513-47.patch
Normal file
373
SOURCES/glibc-rh1817513-47.patch
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
commit 4c6e0415ef206a595c62d5d37e3b9a821782c533
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Apr 3 13:17:48 2020 +0200
|
||||||
|
|
||||||
|
elf: Simplify handling of lists of audit strings
|
||||||
|
|
||||||
|
All list elements are colon-separated strings, and there is a hard
|
||||||
|
upper limit for the number of audit modules, so it is possible to
|
||||||
|
pre-allocate a fixed-size array of strings to which the LD_AUDIT
|
||||||
|
environment variable and --audit arguments are added.
|
||||||
|
|
||||||
|
Also eliminate the global variables for the audit list because
|
||||||
|
the list is only needed briefly during startup.
|
||||||
|
|
||||||
|
There is a slight behavior change: All duplicate LD_AUDIT environment
|
||||||
|
variables are now processed, not just the last one as before. However,
|
||||||
|
such environment vectors are invalid anyway.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index f755dc30331f799f..c39cb8f2cd4bb1cc 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -43,6 +43,7 @@
|
||||||
|
#include <stap-probe.h>
|
||||||
|
#include <stackinfo.h>
|
||||||
|
#include <not-cancel.h>
|
||||||
|
+#include <array_length.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
@@ -107,8 +108,53 @@ static void print_missing_version (int errcode, const char *objname,
|
||||||
|
/* Print the various times we collected. */
|
||||||
|
static void print_statistics (const hp_timing_t *total_timep);
|
||||||
|
|
||||||
|
-/* Add audit objects. */
|
||||||
|
-static void process_dl_audit (char *str);
|
||||||
|
+/* Length limits for names and paths, to protect the dynamic linker,
|
||||||
|
+ particularly when __libc_enable_secure is active. */
|
||||||
|
+#ifdef NAME_MAX
|
||||||
|
+# define SECURE_NAME_LIMIT NAME_MAX
|
||||||
|
+#else
|
||||||
|
+# define SECURE_NAME_LIMIT 255
|
||||||
|
+#endif
|
||||||
|
+#ifdef PATH_MAX
|
||||||
|
+# define SECURE_PATH_LIMIT PATH_MAX
|
||||||
|
+#else
|
||||||
|
+# define SECURE_PATH_LIMIT 1024
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+/* Strings containing colon-separated lists of audit modules. */
|
||||||
|
+struct audit_list
|
||||||
|
+{
|
||||||
|
+ /* Array of strings containing colon-separated path lists. Each
|
||||||
|
+ audit module needs its own namespace, so pre-allocate the largest
|
||||||
|
+ possible list. */
|
||||||
|
+ const char *audit_strings[DL_NNS];
|
||||||
|
+
|
||||||
|
+ /* Number of entries added to audit_strings. */
|
||||||
|
+ size_t length;
|
||||||
|
+
|
||||||
|
+ /* Index into the audit_strings array (for the iteration phase). */
|
||||||
|
+ size_t current_index;
|
||||||
|
+
|
||||||
|
+ /* Tail of audit_strings[current_index] which still needs
|
||||||
|
+ processing. */
|
||||||
|
+ const char *current_tail;
|
||||||
|
+
|
||||||
|
+ /* Scratch buffer for returning a name which is part of the strings
|
||||||
|
+ in audit_strings. */
|
||||||
|
+ char fname[SECURE_NAME_LIMIT];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Creates an empty audit list. */
|
||||||
|
+static void audit_list_init (struct audit_list *);
|
||||||
|
+
|
||||||
|
+/* Add a string to the end of the audit list, for later parsing. Must
|
||||||
|
+ not be called after audit_list_next. */
|
||||||
|
+static void audit_list_add_string (struct audit_list *, const char *);
|
||||||
|
+
|
||||||
|
+/* Extract the next audit module from the audit list. Only modules
|
||||||
|
+ for which dso_name_valid_for_suid is true are returned. Must be
|
||||||
|
+ called after all the audit_list_add_string calls. */
|
||||||
|
+static const char *audit_list_next (struct audit_list *);
|
||||||
|
|
||||||
|
/* This is a list of all the modes the dynamic loader can be in. */
|
||||||
|
enum mode { normal, list, verify, trace };
|
||||||
|
@@ -116,7 +162,7 @@ enum mode { normal, list, verify, trace };
|
||||||
|
/* Process all environments variables the dynamic linker must recognize.
|
||||||
|
Since all of them start with `LD_' we are a bit smarter while finding
|
||||||
|
all the entries. */
|
||||||
|
-static void process_envvars (enum mode *modep);
|
||||||
|
+static void process_envvars (enum mode *modep, struct audit_list *);
|
||||||
|
|
||||||
|
#ifdef DL_ARGV_NOT_RELRO
|
||||||
|
int _dl_argc attribute_hidden;
|
||||||
|
@@ -144,19 +190,6 @@ uintptr_t __pointer_chk_guard_local
|
||||||
|
strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-/* Length limits for names and paths, to protect the dynamic linker,
|
||||||
|
- particularly when __libc_enable_secure is active. */
|
||||||
|
-#ifdef NAME_MAX
|
||||||
|
-# define SECURE_NAME_LIMIT NAME_MAX
|
||||||
|
-#else
|
||||||
|
-# define SECURE_NAME_LIMIT 255
|
||||||
|
-#endif
|
||||||
|
-#ifdef PATH_MAX
|
||||||
|
-# define SECURE_PATH_LIMIT PATH_MAX
|
||||||
|
-#else
|
||||||
|
-# define SECURE_PATH_LIMIT 1024
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
/* Check that AT_SECURE=0, or that the passed name does not contain
|
||||||
|
directories and is not overly long. Reject empty names
|
||||||
|
unconditionally. */
|
||||||
|
@@ -174,89 +207,75 @@ dso_name_valid_for_suid (const char *p)
|
||||||
|
return *p != '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* LD_AUDIT variable contents. Must be processed before the
|
||||||
|
- audit_list below. */
|
||||||
|
-const char *audit_list_string;
|
||||||
|
-
|
||||||
|
-/* Cyclic list of auditing DSOs. audit_list->next is the first
|
||||||
|
- element. */
|
||||||
|
-static struct audit_list
|
||||||
|
+static void
|
||||||
|
+audit_list_init (struct audit_list *list)
|
||||||
|
{
|
||||||
|
- const char *name;
|
||||||
|
- struct audit_list *next;
|
||||||
|
-} *audit_list;
|
||||||
|
+ list->length = 0;
|
||||||
|
+ list->current_index = 0;
|
||||||
|
+ list->current_tail = NULL;
|
||||||
|
+}
|
||||||
|
|
||||||
|
-/* Iterator for audit_list_string followed by audit_list. */
|
||||||
|
-struct audit_list_iter
|
||||||
|
+static void
|
||||||
|
+audit_list_add_string (struct audit_list *list, const char *string)
|
||||||
|
{
|
||||||
|
- /* Tail of audit_list_string still needing processing, or NULL. */
|
||||||
|
- const char *audit_list_tail;
|
||||||
|
+ /* Empty strings do not load anything. */
|
||||||
|
+ if (*string == '\0')
|
||||||
|
+ return;
|
||||||
|
|
||||||
|
- /* The list element returned in the previous iteration. NULL before
|
||||||
|
- the first element. */
|
||||||
|
- struct audit_list *previous;
|
||||||
|
+ if (list->length == array_length (list->audit_strings))
|
||||||
|
+ _dl_fatal_printf ("Fatal glibc error: Too many audit modules requested\n");
|
||||||
|
|
||||||
|
- /* Scratch buffer for returning a name which is part of
|
||||||
|
- audit_list_string. */
|
||||||
|
- char fname[SECURE_NAME_LIMIT];
|
||||||
|
-};
|
||||||
|
+ list->audit_strings[list->length++] = string;
|
||||||
|
|
||||||
|
-/* Initialize an audit list iterator. */
|
||||||
|
-static void
|
||||||
|
-audit_list_iter_init (struct audit_list_iter *iter)
|
||||||
|
-{
|
||||||
|
- iter->audit_list_tail = audit_list_string;
|
||||||
|
- iter->previous = NULL;
|
||||||
|
+ /* Initialize processing of the first string for
|
||||||
|
+ audit_list_next. */
|
||||||
|
+ if (list->length == 1)
|
||||||
|
+ list->current_tail = string;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Iterate through both audit_list_string and audit_list. */
|
||||||
|
static const char *
|
||||||
|
-audit_list_iter_next (struct audit_list_iter *iter)
|
||||||
|
+audit_list_next (struct audit_list *list)
|
||||||
|
{
|
||||||
|
- if (iter->audit_list_tail != NULL)
|
||||||
|
+ if (list->current_tail == NULL)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ while (true)
|
||||||
|
{
|
||||||
|
- /* First iterate over audit_list_string. */
|
||||||
|
- while (*iter->audit_list_tail != '\0')
|
||||||
|
+ /* Advance to the next string in audit_strings if the current
|
||||||
|
+ string has been exhausted. */
|
||||||
|
+ while (*list->current_tail == '\0')
|
||||||
|
{
|
||||||
|
- /* Split audit list at colon. */
|
||||||
|
- size_t len = strcspn (iter->audit_list_tail, ":");
|
||||||
|
- if (len > 0 && len < sizeof (iter->fname))
|
||||||
|
+ ++list->current_index;
|
||||||
|
+ if (list->current_index == list->length)
|
||||||
|
{
|
||||||
|
- memcpy (iter->fname, iter->audit_list_tail, len);
|
||||||
|
- iter->fname[len] = '\0';
|
||||||
|
+ list->current_tail = NULL;
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
- else
|
||||||
|
- /* Do not return this name to the caller. */
|
||||||
|
- iter->fname[0] = '\0';
|
||||||
|
-
|
||||||
|
- /* Skip over the substring and the following delimiter. */
|
||||||
|
- iter->audit_list_tail += len;
|
||||||
|
- if (*iter->audit_list_tail == ':')
|
||||||
|
- ++iter->audit_list_tail;
|
||||||
|
-
|
||||||
|
- /* If the name is valid, return it. */
|
||||||
|
- if (dso_name_valid_for_suid (iter->fname))
|
||||||
|
- return iter->fname;
|
||||||
|
- /* Otherwise, wrap around and try the next name. */
|
||||||
|
+ list->current_tail = list->audit_strings[list->current_index];
|
||||||
|
}
|
||||||
|
- /* Fall through to the procesing of audit_list. */
|
||||||
|
- }
|
||||||
|
|
||||||
|
- if (iter->previous == NULL)
|
||||||
|
- {
|
||||||
|
- if (audit_list == NULL)
|
||||||
|
- /* No pre-parsed audit list. */
|
||||||
|
- return NULL;
|
||||||
|
- /* Start of audit list. The first list element is at
|
||||||
|
- audit_list->next (cyclic list). */
|
||||||
|
- iter->previous = audit_list->next;
|
||||||
|
- return iter->previous->name;
|
||||||
|
+ /* Split the in-string audit list at the next colon colon. */
|
||||||
|
+ size_t len = strcspn (list->current_tail, ":");
|
||||||
|
+ if (len > 0 && len < sizeof (list->fname))
|
||||||
|
+ {
|
||||||
|
+ memcpy (list->fname, list->current_tail, len);
|
||||||
|
+ list->fname[len] = '\0';
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ /* Mark the name as unusable for dso_name_valid_for_suid. */
|
||||||
|
+ list->fname[0] = '\0';
|
||||||
|
+
|
||||||
|
+ /* Skip over the substring and the following delimiter. */
|
||||||
|
+ list->current_tail += len;
|
||||||
|
+ if (*list->current_tail == ':')
|
||||||
|
+ ++list->current_tail;
|
||||||
|
+
|
||||||
|
+ /* If the name is valid, return it. */
|
||||||
|
+ if (dso_name_valid_for_suid (list->fname))
|
||||||
|
+ return list->fname;
|
||||||
|
+
|
||||||
|
+ /* Otherwise wrap around to find the next list element. . */
|
||||||
|
}
|
||||||
|
- if (iter->previous == audit_list)
|
||||||
|
- /* Cyclic list wrap-around. */
|
||||||
|
- return NULL;
|
||||||
|
- iter->previous = iter->previous->next;
|
||||||
|
- return iter->previous->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set nonzero during loading and initialization of executable and
|
||||||
|
@@ -1060,15 +1079,13 @@ notify_audit_modules_of_loaded_object (struct link_map *map)
|
||||||
|
|
||||||
|
/* Load all audit modules. */
|
||||||
|
static void
|
||||||
|
-load_audit_modules (struct link_map *main_map)
|
||||||
|
+load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
|
||||||
|
{
|
||||||
|
struct audit_ifaces *last_audit = NULL;
|
||||||
|
- struct audit_list_iter al_iter;
|
||||||
|
- audit_list_iter_init (&al_iter);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
- const char *name = audit_list_iter_next (&al_iter);
|
||||||
|
+ const char *name = audit_list_next (audit_list);
|
||||||
|
if (name == NULL)
|
||||||
|
break;
|
||||||
|
load_audit_module (name, &last_audit);
|
||||||
|
@@ -1100,6 +1117,9 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
|
bool rtld_is_main = false;
|
||||||
|
void *tcbp = NULL;
|
||||||
|
|
||||||
|
+ struct audit_list audit_list;
|
||||||
|
+ audit_list_init (&audit_list);
|
||||||
|
+
|
||||||
|
GL(dl_init_static_tls) = &_dl_nothread_init_static_tls;
|
||||||
|
|
||||||
|
#if defined SHARED && defined _LIBC_REENTRANT \
|
||||||
|
@@ -1113,7 +1133,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
|
GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable;
|
||||||
|
|
||||||
|
/* Process the environment variable which control the behaviour. */
|
||||||
|
- process_envvars (&mode);
|
||||||
|
+ process_envvars (&mode, &audit_list);
|
||||||
|
|
||||||
|
/* Set up a flag which tells we are just starting. */
|
||||||
|
_dl_starting_up = 1;
|
||||||
|
@@ -1185,7 +1205,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
|
}
|
||||||
|
else if (! strcmp (_dl_argv[1], "--audit") && _dl_argc > 2)
|
||||||
|
{
|
||||||
|
- process_dl_audit (_dl_argv[2]);
|
||||||
|
+ audit_list_add_string (&audit_list, _dl_argv[2]);
|
||||||
|
|
||||||
|
_dl_skip_args += 2;
|
||||||
|
_dl_argc -= 2;
|
||||||
|
@@ -1612,8 +1632,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
|
||||||
|
/* If we have auditing DSOs to load, do it now. */
|
||||||
|
bool need_security_init = true;
|
||||||
|
- if (__glibc_unlikely (audit_list != NULL)
|
||||||
|
- || __glibc_unlikely (audit_list_string != NULL))
|
||||||
|
+ if (audit_list.length > 0)
|
||||||
|
{
|
||||||
|
/* Since we start using the auditing DSOs right away we need to
|
||||||
|
initialize the data structures now. */
|
||||||
|
@@ -1626,7 +1645,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
security_init ();
|
||||||
|
need_security_init = false;
|
||||||
|
|
||||||
|
- load_audit_modules (main_map);
|
||||||
|
+ load_audit_modules (main_map, &audit_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep track of the currently loaded modules to count how many
|
||||||
|
@@ -2500,30 +2519,6 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-process_dl_audit (char *str)
|
||||||
|
-{
|
||||||
|
- /* The parameter is a colon separated list of DSO names. */
|
||||||
|
- char *p;
|
||||||
|
-
|
||||||
|
- while ((p = (strsep) (&str, ":")) != NULL)
|
||||||
|
- if (dso_name_valid_for_suid (p))
|
||||||
|
- {
|
||||||
|
- /* This is using the local malloc, not the system malloc. The
|
||||||
|
- memory can never be freed. */
|
||||||
|
- struct audit_list *newp = malloc (sizeof (*newp));
|
||||||
|
- newp->name = p;
|
||||||
|
-
|
||||||
|
- if (audit_list == NULL)
|
||||||
|
- audit_list = newp->next = newp;
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- newp->next = audit_list->next;
|
||||||
|
- audit_list = audit_list->next = newp;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* Process all environments variables the dynamic linker must recognize.
|
||||||
|
Since all of them start with `LD_' we are a bit smarter while finding
|
||||||
|
all the entries. */
|
||||||
|
@@ -2531,7 +2526,7 @@ extern char **_environ attribute_hidden;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
-process_envvars (enum mode *modep)
|
||||||
|
+process_envvars (enum mode *modep, struct audit_list *audit_list)
|
||||||
|
{
|
||||||
|
char **runp = _environ;
|
||||||
|
char *envline;
|
||||||
|
@@ -2571,7 +2566,7 @@ process_envvars (enum mode *modep)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (memcmp (envline, "AUDIT", 5) == 0)
|
||||||
|
- audit_list_string = &envline[6];
|
||||||
|
+ audit_list_add_string (audit_list, &envline[6]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
379
SOURCES/glibc-rh1817513-48.patch
Normal file
379
SOURCES/glibc-rh1817513-48.patch
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
commit 8f7a75d700af809eeb4363895078fabfb3a9d7c3
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon Feb 17 16:49:40 2020 +0100
|
||||||
|
|
||||||
|
elf: Implement DT_AUDIT, DT_DEPAUDIT support [BZ #24943]
|
||||||
|
|
||||||
|
binutils ld has supported --audit, --depaudit for a long time,
|
||||||
|
only support in glibc has been missing.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
elf/Makefile
|
||||||
|
(Test backport differences.)
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 5b0aeccb0a53c182..a6601ba84c8f4017 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -195,7 +195,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||||
|
tst-sonamemove-link tst-sonamemove-dlopen \
|
||||||
|
tst-auditmany tst-initfinilazyfail \
|
||||||
|
tst-dlopenfail tst-dlopenfail-2 \
|
||||||
|
- tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen
|
||||||
|
+ tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \
|
||||||
|
+ tst-audit14 tst-audit15 tst-audit16
|
||||||
|
# reldep9
|
||||||
|
tests-internal += loadtest unload unload2 circleload1 \
|
||||||
|
neededtest neededtest2 neededtest3 neededtest4 \
|
||||||
|
@@ -310,7 +311,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
|
tst-initlazyfailmod tst-finilazyfailmod \
|
||||||
|
tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
|
||||||
|
tst-dlopenfailmod3 \
|
||||||
|
- tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee
|
||||||
|
+ tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee \
|
||||||
|
+ tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3
|
||||||
|
|
||||||
|
# Most modules build with _ISOMAC defined, but those filtered out
|
||||||
|
# depend on internal headers.
|
||||||
|
@@ -1453,6 +1455,22 @@ $(objpfx)tst-auditmany.out: $(objpfx)tst-auditmanymod1.so \
|
||||||
|
tst-auditmany-ENV = \
|
||||||
|
LD_AUDIT=tst-auditmanymod1.so:tst-auditmanymod2.so:tst-auditmanymod3.so:tst-auditmanymod4.so:tst-auditmanymod5.so:tst-auditmanymod6.so:tst-auditmanymod7.so:tst-auditmanymod8.so:tst-auditmanymod9.so
|
||||||
|
|
||||||
|
+LDFLAGS-tst-audit14 = -Wl,--audit=tst-auditlogmod-1.so
|
||||||
|
+$(objpfx)tst-auditlogmod-1.so: $(libsupport)
|
||||||
|
+$(objpfx)tst-audit14.out: $(objpfx)tst-auditlogmod-1.so
|
||||||
|
+LDFLAGS-tst-audit15 = \
|
||||||
|
+ -Wl,--audit=tst-auditlogmod-1.so,--depaudit=tst-auditlogmod-2.so
|
||||||
|
+$(objpfx)tst-auditlogmod-2.so: $(libsupport)
|
||||||
|
+$(objpfx)tst-audit15.out: \
|
||||||
|
+ $(objpfx)tst-auditlogmod-1.so $(objpfx)tst-auditlogmod-2.so
|
||||||
|
+LDFLAGS-tst-audit16 = \
|
||||||
|
+ -Wl,--audit=tst-auditlogmod-1.so:tst-auditlogmod-2.so \
|
||||||
|
+ -Wl,--depaudit=tst-auditlogmod-3.so
|
||||||
|
+$(objpfx)tst-auditlogmod-3.so: $(libsupport)
|
||||||
|
+$(objpfx)tst-audit16.out: \
|
||||||
|
+ $(objpfx)tst-auditlogmod-1.so $(objpfx)tst-auditlogmod-2.so \
|
||||||
|
+ $(objpfx)tst-auditlogmod-3.so
|
||||||
|
+
|
||||||
|
# tst-sonamemove links against an older implementation of the library.
|
||||||
|
LDFLAGS-tst-sonamemove-linkmod1.so = \
|
||||||
|
-Wl,--version-script=tst-sonamemove-linkmod1.map \
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index c39cb8f2cd4bb1cc..d44facf5343b3301 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -151,9 +151,17 @@ static void audit_list_init (struct audit_list *);
|
||||||
|
not be called after audit_list_next. */
|
||||||
|
static void audit_list_add_string (struct audit_list *, const char *);
|
||||||
|
|
||||||
|
+/* Add the audit strings from the link map, found in the dynamic
|
||||||
|
+ segment at TG (either DT_AUDIT and DT_DEPAUDIT). Must be called
|
||||||
|
+ before audit_list_next. */
|
||||||
|
+static void audit_list_add_dynamic_tag (struct audit_list *,
|
||||||
|
+ struct link_map *,
|
||||||
|
+ unsigned int tag);
|
||||||
|
+
|
||||||
|
/* Extract the next audit module from the audit list. Only modules
|
||||||
|
for which dso_name_valid_for_suid is true are returned. Must be
|
||||||
|
- called after all the audit_list_add_string calls. */
|
||||||
|
+ called after all the audit_list_add_string,
|
||||||
|
+ audit_list_add_dynamic_tags calls. */
|
||||||
|
static const char *audit_list_next (struct audit_list *);
|
||||||
|
|
||||||
|
/* This is a list of all the modes the dynamic loader can be in. */
|
||||||
|
@@ -233,6 +241,16 @@ audit_list_add_string (struct audit_list *list, const char *string)
|
||||||
|
list->current_tail = string;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+audit_list_add_dynamic_tag (struct audit_list *list, struct link_map *main_map,
|
||||||
|
+ unsigned int tag)
|
||||||
|
+{
|
||||||
|
+ ElfW(Dyn) *info = main_map->l_info[ADDRIDX (tag)];
|
||||||
|
+ const char *strtab = (const char *) D_PTR (main_map, l_info[DT_STRTAB]);
|
||||||
|
+ if (info != NULL)
|
||||||
|
+ audit_list_add_string (list, strtab + info->d_un.d_val);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const char *
|
||||||
|
audit_list_next (struct audit_list *list)
|
||||||
|
{
|
||||||
|
@@ -1630,6 +1648,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
/* Assign a module ID. Do this before loading any audit modules. */
|
||||||
|
GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
|
||||||
|
|
||||||
|
+ audit_list_add_dynamic_tag (&audit_list, main_map, DT_AUDIT);
|
||||||
|
+ audit_list_add_dynamic_tag (&audit_list, main_map, DT_DEPAUDIT);
|
||||||
|
+
|
||||||
|
/* If we have auditing DSOs to load, do it now. */
|
||||||
|
bool need_security_init = true;
|
||||||
|
if (audit_list.length > 0)
|
||||||
|
diff --git a/elf/tst-audit14.c b/elf/tst-audit14.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..27ff8db9480a98cc
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-audit14.c
|
||||||
|
@@ -0,0 +1,46 @@
|
||||||
|
+/* Main program with DT_AUDIT. One audit module.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xstdio.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* Verify what the audit module has written. This test assumes that
|
||||||
|
+ standard output has been redirected to a regular file. */
|
||||||
|
+ FILE *fp = xfopen ("/dev/stdout", "r");
|
||||||
|
+
|
||||||
|
+ char *buffer = NULL;
|
||||||
|
+ size_t buffer_length = 0;
|
||||||
|
+ size_t line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ const char *message = "info: tst-auditlogmod-1.so loaded\n";
|
||||||
|
+ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length);
|
||||||
|
+
|
||||||
|
+ /* No more audit module output. */
|
||||||
|
+ line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ TEST_COMPARE_BLOB ("", 0, buffer, line_length);
|
||||||
|
+
|
||||||
|
+ free (buffer);
|
||||||
|
+ xfclose (fp);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-audit15.c b/elf/tst-audit15.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..cbd1589ec40653d1
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-audit15.c
|
||||||
|
@@ -0,0 +1,50 @@
|
||||||
|
+/* Main program with DT_AUDIT and DT_DEPAUDIT. Two audit modules.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xstdio.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* Verify what the audit modules have written. This test assumes
|
||||||
|
+ that standard output has been redirected to a regular file. */
|
||||||
|
+ FILE *fp = xfopen ("/dev/stdout", "r");
|
||||||
|
+
|
||||||
|
+ char *buffer = NULL;
|
||||||
|
+ size_t buffer_length = 0;
|
||||||
|
+ size_t line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ const char *message = "info: tst-auditlogmod-1.so loaded\n";
|
||||||
|
+ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length);
|
||||||
|
+
|
||||||
|
+ line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ message = "info: tst-auditlogmod-2.so loaded\n";
|
||||||
|
+ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length);
|
||||||
|
+
|
||||||
|
+ /* No more audit module output. */
|
||||||
|
+ line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ TEST_COMPARE_BLOB ("", 0, buffer, line_length);
|
||||||
|
+
|
||||||
|
+ free (buffer);
|
||||||
|
+ xfclose (fp);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-audit16.c b/elf/tst-audit16.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..dd6ce189ea6fffa3
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-audit16.c
|
||||||
|
@@ -0,0 +1,54 @@
|
||||||
|
+/* Main program with DT_AUDIT and DT_DEPAUDIT. Three audit modules.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/xstdio.h>
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* Verify what the audit modules have written. This test assumes
|
||||||
|
+ that standard output has been redirected to a regular file. */
|
||||||
|
+ FILE *fp = xfopen ("/dev/stdout", "r");
|
||||||
|
+
|
||||||
|
+ char *buffer = NULL;
|
||||||
|
+ size_t buffer_length = 0;
|
||||||
|
+ size_t line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ const char *message = "info: tst-auditlogmod-1.so loaded\n";
|
||||||
|
+ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length);
|
||||||
|
+
|
||||||
|
+ line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ message = "info: tst-auditlogmod-2.so loaded\n";
|
||||||
|
+ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length);
|
||||||
|
+
|
||||||
|
+ line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ message = "info: tst-auditlogmod-3.so loaded\n";
|
||||||
|
+ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length);
|
||||||
|
+
|
||||||
|
+ /* No more audit module output. */
|
||||||
|
+ line_length = xgetline (&buffer, &buffer_length, fp);
|
||||||
|
+ TEST_COMPARE_BLOB ("", 0, buffer, line_length);
|
||||||
|
+
|
||||||
|
+ free (buffer);
|
||||||
|
+ xfclose (fp);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/elf/tst-auditlogmod-1.c b/elf/tst-auditlogmod-1.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..db9dac4c01a58dcd
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditlogmod-1.c
|
||||||
|
@@ -0,0 +1,27 @@
|
||||||
|
+/* Audit module which logs that it was loaded. Variant 1.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <link.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+la_version (unsigned int v)
|
||||||
|
+{
|
||||||
|
+ write_message ("info: tst-auditlogmod-1.so loaded\n");
|
||||||
|
+ return LAV_CURRENT;
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-auditlogmod-2.c b/elf/tst-auditlogmod-2.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..871c22641c47fed0
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditlogmod-2.c
|
||||||
|
@@ -0,0 +1,27 @@
|
||||||
|
+/* Audit module which logs that it was loaded. Variant 2.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <link.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+la_version (unsigned int v)
|
||||||
|
+{
|
||||||
|
+ write_message ("info: tst-auditlogmod-2.so loaded\n");
|
||||||
|
+ return LAV_CURRENT;
|
||||||
|
+}
|
||||||
|
diff --git a/elf/tst-auditlogmod-3.c b/elf/tst-auditlogmod-3.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..da2ee19d4ab9e861
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-auditlogmod-3.c
|
||||||
|
@@ -0,0 +1,27 @@
|
||||||
|
+/* Audit module which logs that it was loaded. Variant 3.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <link.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+
|
||||||
|
+unsigned int
|
||||||
|
+la_version (unsigned int v)
|
||||||
|
+{
|
||||||
|
+ write_message ("info: tst-auditlogmod-3.so loaded\n");
|
||||||
|
+ return LAV_CURRENT;
|
||||||
|
+}
|
163
SOURCES/glibc-rh1817513-49.patch
Normal file
163
SOURCES/glibc-rh1817513-49.patch
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
commit 50a2d83c08a94a10f88a1fedeb7a6e3667a6b732
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Apr 24 22:13:03 2020 +0200
|
||||||
|
|
||||||
|
elf: Introduce <elf_machine_sym_no_match.h>
|
||||||
|
|
||||||
|
MIPS needs to ignore certain existing symbols during symbol lookup.
|
||||||
|
The old scheme uses the ELF_MACHINE_SYM_NO_MATCH macro, with an
|
||||||
|
inline function, within its own header, with a sysdeps override for
|
||||||
|
MIPS. This allows re-use of the function from another file (without
|
||||||
|
having to include <dl-machine.h> or providing the default definition
|
||||||
|
for ELF_MACHINE_SYM_NO_MATCH).
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
||||||
|
index e4c479de9a1fd6ec..47acd134600b44b5 100644
|
||||||
|
--- a/elf/dl-lookup.c
|
||||||
|
+++ b/elf/dl-lookup.c
|
||||||
|
@@ -28,18 +28,12 @@
|
||||||
|
#include <libc-lock.h>
|
||||||
|
#include <tls.h>
|
||||||
|
#include <atomic.h>
|
||||||
|
+#include <elf_machine_sym_no_match.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
-/* Return nonzero if check_match should consider SYM to fail to match a
|
||||||
|
- symbol reference for some machine-specific reason. */
|
||||||
|
-#ifndef ELF_MACHINE_SYM_NO_MATCH
|
||||||
|
-# define ELF_MACHINE_SYM_NO_MATCH(sym) 0
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
#define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag))
|
||||||
|
|
||||||
|
-
|
||||||
|
struct sym_val
|
||||||
|
{
|
||||||
|
const ElfW(Sym) *s;
|
||||||
|
@@ -78,7 +72,7 @@ check_match (const char *const undef_name,
|
||||||
|
if (__glibc_unlikely ((sym->st_value == 0 /* No value. */
|
||||||
|
&& sym->st_shndx != SHN_ABS
|
||||||
|
&& stt != STT_TLS)
|
||||||
|
- || ELF_MACHINE_SYM_NO_MATCH (sym)
|
||||||
|
+ || elf_machine_sym_no_match (sym)
|
||||||
|
|| (type_class & (sym->st_shndx == SHN_UNDEF))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
diff --git a/sysdeps/generic/elf_machine_sym_no_match.h b/sysdeps/generic/elf_machine_sym_no_match.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..27155de4c0358460
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/generic/elf_machine_sym_no_match.h
|
||||||
|
@@ -0,0 +1,34 @@
|
||||||
|
+/* Function to ignore certain symbol matches for machine-specific reasons.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
|
||||||
|
+#define _ELF_MACHINE_SYM_NO_MATCH_H
|
||||||
|
+
|
||||||
|
+#include <link.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
+
|
||||||
|
+/* This can be customized to ignore certain symbols during lookup in
|
||||||
|
+ case there are machine-specific rules to disregard some
|
||||||
|
+ symbols. */
|
||||||
|
+static inline bool
|
||||||
|
+elf_machine_sym_no_match (const ElfW(Sym) *sym)
|
||||||
|
+{
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */
|
||||||
|
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
|
||||||
|
index 91fc640388a735c7..b41e10647d81843b 100644
|
||||||
|
--- a/sysdeps/mips/dl-machine.h
|
||||||
|
+++ b/sysdeps/mips/dl-machine.h
|
||||||
|
@@ -467,21 +467,6 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc,
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* The semantics of zero/non-zero values of undefined symbols differs
|
||||||
|
- depending on whether the non-PIC ABI is in use. Under the non-PIC
|
||||||
|
- ABI, a non-zero value indicates that there is an address reference
|
||||||
|
- to the symbol and thus it must always be resolved (except when
|
||||||
|
- resolving a jump slot relocation) to the PLT entry whose address is
|
||||||
|
- provided as the symbol's value; a zero value indicates that this
|
||||||
|
- canonical-address behaviour is not required. Yet under the classic
|
||||||
|
- MIPS psABI, a zero value indicates that there is an address
|
||||||
|
- reference to the function and the dynamic linker must resolve the
|
||||||
|
- symbol immediately upon loading. To avoid conflict, symbols for
|
||||||
|
- which the dynamic linker must assume the non-PIC ABI semantics are
|
||||||
|
- marked with the STO_MIPS_PLT flag. */
|
||||||
|
-#define ELF_MACHINE_SYM_NO_MATCH(sym) \
|
||||||
|
- ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT))
|
||||||
|
-
|
||||||
|
#endif /* !dl_machine_h */
|
||||||
|
|
||||||
|
#ifdef RESOLVE_MAP
|
||||||
|
diff --git a/sysdeps/mips/elf_machine_sym_no_match.h b/sysdeps/mips/elf_machine_sym_no_match.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..9d09e5fa2db1ff6c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/sysdeps/mips/elf_machine_sym_no_match.h
|
||||||
|
@@ -0,0 +1,43 @@
|
||||||
|
+/* MIPS-specific handling of undefined symbols.
|
||||||
|
+ Copyright (C) 2008-2020 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/>. */
|
||||||
|
+
|
||||||
|
+#ifndef _ELF_MACHINE_SYM_NO_MATCH_H
|
||||||
|
+#define _ELF_MACHINE_SYM_NO_MATCH_H
|
||||||
|
+
|
||||||
|
+#include <link.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
+
|
||||||
|
+/* The semantics of zero/non-zero values of undefined symbols differs
|
||||||
|
+ depending on whether the non-PIC ABI is in use. Under the non-PIC
|
||||||
|
+ ABI, a non-zero value indicates that there is an address reference
|
||||||
|
+ to the symbol and thus it must always be resolved (except when
|
||||||
|
+ resolving a jump slot relocation) to the PLT entry whose address is
|
||||||
|
+ provided as the symbol's value; a zero value indicates that this
|
||||||
|
+ canonical-address behaviour is not required. Yet under the classic
|
||||||
|
+ MIPS psABI, a zero value indicates that there is an address
|
||||||
|
+ reference to the function and the dynamic linker must resolve the
|
||||||
|
+ symbol immediately upon loading. To avoid conflict, symbols for
|
||||||
|
+ which the dynamic linker must assume the non-PIC ABI semantics are
|
||||||
|
+ marked with the STO_MIPS_PLT flag. */
|
||||||
|
+static inline bool
|
||||||
|
+elf_machine_sym_no_match (const ElfW(Sym) *sym)
|
||||||
|
+{
|
||||||
|
+ return sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */
|
82
SOURCES/glibc-rh1817513-5.patch
Normal file
82
SOURCES/glibc-rh1817513-5.patch
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
commit fb4c32aef64500c65c7fc95ca06d7e17d467be45
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Mon Aug 6 06:25:28 2018 -0700
|
||||||
|
|
||||||
|
x86: Move STATE_SAVE_OFFSET/STATE_SAVE_MASK to sysdep.h
|
||||||
|
|
||||||
|
Move STATE_SAVE_OFFSET and STATE_SAVE_MASK to sysdep.h to make
|
||||||
|
sysdeps/x86/cpu-features.h a C header file.
|
||||||
|
|
||||||
|
* sysdeps/x86/cpu-features.h (STATE_SAVE_OFFSET): Removed.
|
||||||
|
(STATE_SAVE_MASK): Likewise.
|
||||||
|
Don't check __ASSEMBLER__ to include <cpu-features-offsets.h>.
|
||||||
|
* sysdeps/x86/sysdep.h (STATE_SAVE_OFFSET): New.
|
||||||
|
(STATE_SAVE_MASK): Likewise.
|
||||||
|
* sysdeps/x86_64/dl-trampoline.S: Include <cpu-features-offsets.h>
|
||||||
|
instead of <cpu-features.h>.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
|
||||||
|
index 4c6d08c709eea204..d342664c64ab7aa1 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.h
|
||||||
|
+++ b/sysdeps/x86/cpu-features.h
|
||||||
|
@@ -92,18 +92,6 @@
|
||||||
|
/* The current maximum size of the feature integer bit array. */
|
||||||
|
#define FEATURE_INDEX_MAX 1
|
||||||
|
|
||||||
|
-/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need
|
||||||
|
- space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be
|
||||||
|
- aligned to 16 bytes for fxsave and 64 bytes for xsave. */
|
||||||
|
-#define STATE_SAVE_OFFSET (8 * 7 + 8)
|
||||||
|
-
|
||||||
|
-/* Save SSE, AVX, AVX512, mask and bound registers. */
|
||||||
|
-#define STATE_SAVE_MASK \
|
||||||
|
- ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7))
|
||||||
|
-
|
||||||
|
-#ifdef __ASSEMBLER__
|
||||||
|
-# include <cpu-features-offsets.h>
|
||||||
|
-#else /* __ASSEMBLER__ */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
COMMON_CPUID_INDEX_1 = 0,
|
||||||
|
@@ -267,8 +255,6 @@ extern const struct cpu_features *__get_cpu_features (void)
|
||||||
|
# define index_arch_XSAVEC_Usable FEATURE_INDEX_1
|
||||||
|
# define index_arch_Prefer_FSRM FEATURE_INDEX_1
|
||||||
|
|
||||||
|
-#endif /* !__ASSEMBLER__ */
|
||||||
|
-
|
||||||
|
#ifdef __x86_64__
|
||||||
|
# define HAS_CPUID 1
|
||||||
|
#elif defined __i586__ || defined __pentium__
|
||||||
|
diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h
|
||||||
|
index 8776ad8374e056d3..f41f4ebd425cfbaf 100644
|
||||||
|
--- a/sysdeps/x86/sysdep.h
|
||||||
|
+++ b/sysdeps/x86/sysdep.h
|
||||||
|
@@ -48,6 +48,15 @@ enum cf_protection_level
|
||||||
|
# define SHSTK_ENABLED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need
|
||||||
|
+ space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be
|
||||||
|
+ aligned to 16 bytes for fxsave and 64 bytes for xsave. */
|
||||||
|
+#define STATE_SAVE_OFFSET (8 * 7 + 8)
|
||||||
|
+
|
||||||
|
+/* Save SSE, AVX, AVX512, mask and bound registers. */
|
||||||
|
+#define STATE_SAVE_MASK \
|
||||||
|
+ ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7))
|
||||||
|
+
|
||||||
|
#ifdef __ASSEMBLER__
|
||||||
|
|
||||||
|
/* Syntactic details of assembler. */
|
||||||
|
diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S
|
||||||
|
index ef1425cbb909529a..fd918510fe155733 100644
|
||||||
|
--- a/sysdeps/x86_64/dl-trampoline.S
|
||||||
|
+++ b/sysdeps/x86_64/dl-trampoline.S
|
||||||
|
@@ -18,7 +18,7 @@
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <sysdep.h>
|
||||||
|
-#include <cpu-features.h>
|
||||||
|
+#include <cpu-features-offsets.h>
|
||||||
|
#include <link-defines.h>
|
||||||
|
|
||||||
|
#ifndef DL_STACK_ALIGNMENT
|
538
SOURCES/glibc-rh1817513-50.patch
Normal file
538
SOURCES/glibc-rh1817513-50.patch
Normal file
@ -0,0 +1,538 @@
|
|||||||
|
commit ec935dea6332cb22f9881cd1162bad156173f4b0
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Fri Apr 24 22:31:15 2020 +0200
|
||||||
|
|
||||||
|
elf: Implement __libc_early_init
|
||||||
|
|
||||||
|
This function is defined in libc.so, and the dynamic loader calls
|
||||||
|
right after relocation has been finished, before any ELF constructors
|
||||||
|
or the preinit function is invoked. It is also used in the static
|
||||||
|
build for initializing parts of the static libc.
|
||||||
|
|
||||||
|
To locate __libc_early_init, a direct symbol lookup function is used,
|
||||||
|
_dl_lookup_direct. It does not search the entire symbol scope and
|
||||||
|
consults merely a single link map. This function could also be used
|
||||||
|
to implement lookups in the vDSO (as an optimization).
|
||||||
|
|
||||||
|
A per-namespace variable (libc_map) is added for locating libc.so,
|
||||||
|
to avoid repeated traversals of the search scope. It is similar to
|
||||||
|
GL(dl_initfirst). An alternative would have been to thread a context
|
||||||
|
argument from _dl_open down to _dl_map_object_from_fd (where libc.so
|
||||||
|
is identified). This could have avoided the global variable, but
|
||||||
|
the change would be larger as a result. It would not have been
|
||||||
|
possible to use this to replace GL(dl_initfirst) because that global
|
||||||
|
variable is used to pass the function pointer past the stack switch
|
||||||
|
from dl_main to the main program. Replacing that requires adding
|
||||||
|
a new argument to _dl_init, which in turn needs changes to the
|
||||||
|
architecture-specific libc.so startup code written in assembler.
|
||||||
|
|
||||||
|
__libc_early_init should not be used to replace _dl_var_init (as
|
||||||
|
it exists today on some architectures). Instead, _dl_lookup_direct
|
||||||
|
should be used to look up a new variable symbol in libc.so, and
|
||||||
|
that should then be initialized from the dynamic loader, immediately
|
||||||
|
after the object has been loaded in _dl_map_object_from_fd (before
|
||||||
|
relocation is run). This way, more IFUNC resolvers which depend on
|
||||||
|
these variables will work.
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/csu/init-first.c b/csu/init-first.c
|
||||||
|
index 289373f9d8bd98f4..544229151ef79c67 100644
|
||||||
|
--- a/csu/init-first.c
|
||||||
|
+++ b/csu/init-first.c
|
||||||
|
@@ -16,7 +16,6 @@
|
||||||
|
License along with the GNU C Library; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
-#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
@@ -80,9 +79,6 @@ _init (int argc, char **argv, char **envp)
|
||||||
|
|
||||||
|
__init_misc (argc, argv, envp);
|
||||||
|
|
||||||
|
- /* Initialize ctype data. */
|
||||||
|
- __ctype_init ();
|
||||||
|
-
|
||||||
|
#if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
|
||||||
|
__libc_global_ctors ();
|
||||||
|
#endif
|
||||||
|
diff --git a/csu/libc-start.c b/csu/libc-start.c
|
||||||
|
index dfbf195328239a17..d9c3248219d8f84f 100644
|
||||||
|
--- a/csu/libc-start.c
|
||||||
|
+++ b/csu/libc-start.c
|
||||||
|
@@ -22,6 +22,7 @@
|
||||||
|
#include <ldsodefs.h>
|
||||||
|
#include <exit-thread.h>
|
||||||
|
#include <libc-internal.h>
|
||||||
|
+#include <elf/libc-early-init.h>
|
||||||
|
|
||||||
|
#include <elf/dl-tunables.h>
|
||||||
|
|
||||||
|
@@ -238,6 +239,10 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||||
|
__cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL);
|
||||||
|
|
||||||
|
#ifndef SHARED
|
||||||
|
+ /* Perform early initialization. In the shared case, this function
|
||||||
|
+ is called from the dynamic loader as early as possible. */
|
||||||
|
+ __libc_early_init ();
|
||||||
|
+
|
||||||
|
/* Call the initializer of the libc. This is only needed here if we
|
||||||
|
are compiling for the static library in which case we haven't
|
||||||
|
run the constructors in `_dl_start_user'. */
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index a6601ba84c8f4017..cbced7605ebe2443 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -25,7 +25,7 @@ headers = elf.h bits/elfclass.h link.h bits/link.h
|
||||||
|
routines = $(all-dl-routines) dl-support dl-iteratephdr \
|
||||||
|
dl-addr dl-addr-obj enbl-secure dl-profstub \
|
||||||
|
dl-origin dl-libc dl-sym dl-sysdep dl-error \
|
||||||
|
- dl-reloc-static-pie
|
||||||
|
+ dl-reloc-static-pie libc_early_init
|
||||||
|
|
||||||
|
# The core dynamic linking functions are in libc for the static and
|
||||||
|
# profiled libraries.
|
||||||
|
@@ -33,7 +33,8 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \
|
||||||
|
runtime init fini debug misc \
|
||||||
|
version profile tls origin scope \
|
||||||
|
execstack open close trampoline \
|
||||||
|
- exception sort-maps)
|
||||||
|
+ exception sort-maps lookup-direct \
|
||||||
|
+ call-libc-early-init)
|
||||||
|
ifeq (yes,$(use-ldconfig))
|
||||||
|
dl-routines += dl-cache
|
||||||
|
endif
|
||||||
|
diff --git a/elf/Versions b/elf/Versions
|
||||||
|
index 705489fc51f4ac5f..3be879c4adfa74c7 100644
|
||||||
|
--- a/elf/Versions
|
||||||
|
+++ b/elf/Versions
|
||||||
|
@@ -26,6 +26,7 @@ libc {
|
||||||
|
_dl_open_hook; _dl_open_hook2;
|
||||||
|
_dl_sym; _dl_vsym;
|
||||||
|
__libc_dlclose; __libc_dlopen_mode; __libc_dlsym; __libc_dlvsym;
|
||||||
|
+ __libc_early_init;
|
||||||
|
|
||||||
|
# Internal error handling support. Interposes the functions in ld.so.
|
||||||
|
_dl_signal_exception; _dl_catch_exception;
|
||||||
|
diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..41e9ad9aad8b5b46
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/dl-call-libc-early-init.c
|
||||||
|
@@ -0,0 +1,41 @@
|
||||||
|
+/* Invoke the early initialization function in libc.so.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <assert.h>
|
||||||
|
+#include <ldsodefs.h>
|
||||||
|
+#include <libc-early-init.h>
|
||||||
|
+#include <link.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+_dl_call_libc_early_init (struct link_map *libc_map)
|
||||||
|
+{
|
||||||
|
+ /* There is nothing to do if we did not actually load libc.so. */
|
||||||
|
+ if (libc_map == NULL)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ const ElfW(Sym) *sym
|
||||||
|
+ = _dl_lookup_direct (libc_map, "__libc_early_init",
|
||||||
|
+ 0x069682ac, /* dl_new_hash output. */
|
||||||
|
+ "GLIBC_PRIVATE",
|
||||||
|
+ 0x0963cf85); /* _dl_elf_hash output. */
|
||||||
|
+ assert (sym != NULL);
|
||||||
|
+ __typeof (__libc_early_init) *early_init
|
||||||
|
+ = DL_SYMBOL_ADDRESS (libc_map, sym);
|
||||||
|
+ early_init ();
|
||||||
|
+}
|
||||||
|
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||||
|
index 8f8869ff524ab9f2..64da5323d0e368c1 100644
|
||||||
|
--- a/elf/dl-load.c
|
||||||
|
+++ b/elf/dl-load.c
|
||||||
|
@@ -30,6 +30,7 @@
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
+#include <gnu/lib-names.h>
|
||||||
|
|
||||||
|
/* Type for the buffer we put the ELF header and hopefully the program
|
||||||
|
header. This buffer does not really have to be too large. In most
|
||||||
|
@@ -1390,6 +1391,14 @@ cannot enable executable stack as shared object requires");
|
||||||
|
add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||||
|
+ l->l_info[DT_SONAME]->d_un.d_val));
|
||||||
|
|
||||||
|
+ /* If we have newly loaded libc.so, update the namespace
|
||||||
|
+ description. */
|
||||||
|
+ if (GL(dl_ns)[nsid].libc_map == NULL
|
||||||
|
+ && l->l_info[DT_SONAME] != NULL
|
||||||
|
+ && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||||
|
+ + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
|
||||||
|
+ GL(dl_ns)[nsid].libc_map = l;
|
||||||
|
+
|
||||||
|
/* _dl_close can only eventually undo the module ID assignment (via
|
||||||
|
remove_slotinfo) if this function returns a pointer to a link
|
||||||
|
map. Therefore, delay this step until all possibilities for
|
||||||
|
diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..5637ae89de8a9d61
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/dl-lookup-direct.c
|
||||||
|
@@ -0,0 +1,116 @@
|
||||||
|
+/* Look up a symbol in a single specified object.
|
||||||
|
+ Copyright (C) 1995-2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <ldsodefs.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <elf_machine_sym_no_match.h>
|
||||||
|
+#include <dl-hash.h>
|
||||||
|
+
|
||||||
|
+/* This function corresponds to do_lookup_x in elf/dl-lookup.c. The
|
||||||
|
+ variant here is simplified because it requires symbol
|
||||||
|
+ versioning. */
|
||||||
|
+static const ElfW(Sym) *
|
||||||
|
+check_match (const struct link_map *const map, const char *const undef_name,
|
||||||
|
+ const char *version, uint32_t version_hash,
|
||||||
|
+ const Elf_Symndx symidx)
|
||||||
|
+{
|
||||||
|
+ const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
|
||||||
|
+ const ElfW(Sym) *sym = &symtab[symidx];
|
||||||
|
+
|
||||||
|
+ unsigned int stt = ELFW(ST_TYPE) (sym->st_info);
|
||||||
|
+ if (__glibc_unlikely ((sym->st_value == 0 /* No value. */
|
||||||
|
+ && sym->st_shndx != SHN_ABS
|
||||||
|
+ && stt != STT_TLS)
|
||||||
|
+ || elf_machine_sym_no_match (sym)))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC,
|
||||||
|
+ STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no
|
||||||
|
+ code/data definitions. */
|
||||||
|
+#define ALLOWED_STT \
|
||||||
|
+ ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \
|
||||||
|
+ | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC))
|
||||||
|
+ if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0))
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
|
||||||
|
+
|
||||||
|
+ if (strcmp (strtab + sym->st_name, undef_name) != 0)
|
||||||
|
+ /* Not the symbol we are looking for. */
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff;
|
||||||
|
+ if (map->l_versions[ndx].hash != version_hash
|
||||||
|
+ || strcmp (map->l_versions[ndx].name, version) != 0)
|
||||||
|
+ /* It's not the version we want. */
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ return sym;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* This function corresponds to do_lookup_x in elf/dl-lookup.c. The
|
||||||
|
+ variant here is simplified because it does not search object
|
||||||
|
+ dependencies. It is optimized for a successful lookup. */
|
||||||
|
+const ElfW(Sym) *
|
||||||
|
+_dl_lookup_direct (struct link_map *map,
|
||||||
|
+ const char *undef_name, uint32_t new_hash,
|
||||||
|
+ const char *version, uint32_t version_hash)
|
||||||
|
+{
|
||||||
|
+ const ElfW(Addr) *bitmask = map->l_gnu_bitmask;
|
||||||
|
+ if (__glibc_likely (bitmask != NULL))
|
||||||
|
+ {
|
||||||
|
+ Elf32_Word bucket = map->l_gnu_buckets[new_hash % map->l_nbuckets];
|
||||||
|
+ if (bucket != 0)
|
||||||
|
+ {
|
||||||
|
+ const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket];
|
||||||
|
+
|
||||||
|
+ do
|
||||||
|
+ if (((*hasharr ^ new_hash) >> 1) == 0)
|
||||||
|
+ {
|
||||||
|
+ Elf_Symndx symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr);
|
||||||
|
+ const ElfW(Sym) *sym = check_match (map, undef_name,
|
||||||
|
+ version, version_hash,
|
||||||
|
+ symidx);
|
||||||
|
+ if (sym != NULL)
|
||||||
|
+ return sym;
|
||||||
|
+ }
|
||||||
|
+ while ((*hasharr++ & 1u) == 0);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* Fallback code for lack of GNU_HASH support. */
|
||||||
|
+ uint32_t old_hash = _dl_elf_hash (undef_name);
|
||||||
|
+
|
||||||
|
+ /* Use the old SysV-style hash table. Search the appropriate
|
||||||
|
+ hash bucket in this object's symbol table for a definition
|
||||||
|
+ for the same symbol name. */
|
||||||
|
+ for (Elf_Symndx symidx = map->l_buckets[old_hash % map->l_nbuckets];
|
||||||
|
+ symidx != STN_UNDEF;
|
||||||
|
+ symidx = map->l_chain[symidx])
|
||||||
|
+ {
|
||||||
|
+ const ElfW(Sym) *sym = check_match (map, undef_name,
|
||||||
|
+ version, version_hash, symidx);
|
||||||
|
+ if (sym != NULL)
|
||||||
|
+ return sym;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index 7113c4a04f0fddbc..1a77ec833cad6c55 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -34,6 +34,7 @@
|
||||||
|
#include <atomic.h>
|
||||||
|
#include <libc-internal.h>
|
||||||
|
#include <array_length.h>
|
||||||
|
+#include <libc-early-init.h>
|
||||||
|
|
||||||
|
#include <dl-dst.h>
|
||||||
|
#include <dl-prop.h>
|
||||||
|
@@ -57,6 +58,13 @@ struct dl_open_args
|
||||||
|
(non-negative). */
|
||||||
|
unsigned int original_global_scope_pending_adds;
|
||||||
|
|
||||||
|
+ /* Set to true by dl_open_worker if libc.so was already loaded into
|
||||||
|
+ the namespace at the time dl_open_worker was called. This is
|
||||||
|
+ used to determine whether libc.so early initialization has
|
||||||
|
+ already been done before, and whether to roll back the cached
|
||||||
|
+ libc_map value in the namespace in case of a dlopen failure. */
|
||||||
|
+ bool libc_already_loaded;
|
||||||
|
+
|
||||||
|
/* Original parameters to the program and the current environment. */
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
@@ -500,6 +508,11 @@ dl_open_worker (void *a)
|
||||||
|
args->nsid = call_map->l_ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* The namespace ID is now known. Keep track of whether libc.so was
|
||||||
|
+ already loaded, to determine whether it is necessary to call the
|
||||||
|
+ early initialization routine (or clear libc_map on error). */
|
||||||
|
+ args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL;
|
||||||
|
+
|
||||||
|
/* Retain the old value, so that it can be restored. */
|
||||||
|
args->original_global_scope_pending_adds
|
||||||
|
= GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds;
|
||||||
|
@@ -734,6 +747,11 @@ dl_open_worker (void *a)
|
||||||
|
if (relocation_in_progress)
|
||||||
|
LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
|
||||||
|
|
||||||
|
+ /* If libc.so was not there before, attempt to call its early
|
||||||
|
+ initialization routine. */
|
||||||
|
+ if (!args->libc_already_loaded)
|
||||||
|
+ _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map);
|
||||||
|
+
|
||||||
|
#ifndef SHARED
|
||||||
|
DL_STATIC_INIT (new);
|
||||||
|
#endif
|
||||||
|
@@ -828,6 +846,8 @@ no more namespaces available for dlmopen()"));
|
||||||
|
args.caller_dlopen = caller_dlopen;
|
||||||
|
args.map = NULL;
|
||||||
|
args.nsid = nsid;
|
||||||
|
+ /* args.libc_already_loaded is always assigned by dl_open_worker
|
||||||
|
+ (before any explicit/non-local returns). */
|
||||||
|
args.argc = argc;
|
||||||
|
args.argv = argv;
|
||||||
|
args.env = env;
|
||||||
|
@@ -856,6 +876,11 @@ no more namespaces available for dlmopen()"));
|
||||||
|
/* See if an error occurred during loading. */
|
||||||
|
if (__glibc_unlikely (exception.errstring != NULL))
|
||||||
|
{
|
||||||
|
+ /* Avoid keeping around a dangling reference to the libc.so link
|
||||||
|
+ map in case it has been cached in libc_map. */
|
||||||
|
+ if (!args.libc_already_loaded)
|
||||||
|
+ GL(dl_ns)[nsid].libc_map = NULL;
|
||||||
|
+
|
||||||
|
/* Remove the object from memory. It may be in an inconsistent
|
||||||
|
state if relocation failed, for example. */
|
||||||
|
if (args.map)
|
||||||
|
diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..5185fa8895c0e11a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/libc-early-init.h
|
||||||
|
@@ -0,0 +1,35 @@
|
||||||
|
+/* Early initialization of libc.so.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#ifndef _LIBC_EARLY_INIT_H
|
||||||
|
+#define _LIBC_EARLY_INIT_H
|
||||||
|
+
|
||||||
|
+struct link_map;
|
||||||
|
+
|
||||||
|
+/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
|
||||||
|
+ and call this function. */
|
||||||
|
+void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden;
|
||||||
|
+
|
||||||
|
+/* In the shared case, this function is defined in libc.so and invoked
|
||||||
|
+ from ld.so (or on the fist static dlopen) after complete relocation
|
||||||
|
+ of a new loaded libc.so, but before user-defined ELF constructors
|
||||||
|
+ run. In the static case, this function is called directly from the
|
||||||
|
+ startup code. */
|
||||||
|
+void __libc_early_init (void);
|
||||||
|
+
|
||||||
|
+#endif /* _LIBC_EARLY_INIT_H */
|
||||||
|
diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..7f4ca332b805a22c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/libc_early_init.c
|
||||||
|
@@ -0,0 +1,27 @@
|
||||||
|
+/* Early initialization of libc.so, libc.so side.
|
||||||
|
+ Copyright (C) 2020 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/>. */
|
||||||
|
+
|
||||||
|
+#include <ctype.h>
|
||||||
|
+#include <libc-early-init.h>
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+__libc_early_init (void)
|
||||||
|
+{
|
||||||
|
+ /* Initialize ctype data. */
|
||||||
|
+ __ctype_init ();
|
||||||
|
+}
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index d44facf5343b3301..a40d5f17db0dac8b 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -44,6 +44,7 @@
|
||||||
|
#include <stackinfo.h>
|
||||||
|
#include <not-cancel.h>
|
||||||
|
#include <array_length.h>
|
||||||
|
+#include <libc-early-init.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
@@ -2365,6 +2366,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
rtld_timer_accum (&relocate_time, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Relocation is complete. Perform early libc initialization. */
|
||||||
|
+ _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map);
|
||||||
|
+
|
||||||
|
/* Do any necessary cleanups for the startup OS interface code.
|
||||||
|
We do these now so that no calls are made after rtld re-relocation
|
||||||
|
which might be resolved to different functions than we expect.
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index a8fb0d211426e4b1..ccec08929e4ad4e7 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -336,6 +336,10 @@ struct rtld_global
|
||||||
|
recursive dlopen calls from ELF constructors. */
|
||||||
|
unsigned int _ns_global_scope_pending_adds;
|
||||||
|
|
||||||
|
+ /* Once libc.so has been loaded into the namespace, this points to
|
||||||
|
+ its link map. */
|
||||||
|
+ struct link_map *libc_map;
|
||||||
|
+
|
||||||
|
/* Search table for unique objects. */
|
||||||
|
struct unique_sym_table
|
||||||
|
{
|
||||||
|
@@ -943,6 +947,19 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef,
|
||||||
|
attribute_hidden;
|
||||||
|
|
||||||
|
|
||||||
|
+/* Restricted version of _dl_lookup_symbol_x. Searches MAP (and only
|
||||||
|
+ MAP) for the symbol UNDEF_NAME, with GNU hash NEW_HASH (computed
|
||||||
|
+ with dl_new_hash), symbol version VERSION, and symbol version hash
|
||||||
|
+ VERSION_HASH (computed with _dl_elf_hash). Returns a pointer to
|
||||||
|
+ the symbol table entry in MAP on success, or NULL on failure. MAP
|
||||||
|
+ must have symbol versioning information, or otherwise the result is
|
||||||
|
+ undefined. */
|
||||||
|
+const ElfW(Sym) *_dl_lookup_direct (struct link_map *map,
|
||||||
|
+ const char *undef_name,
|
||||||
|
+ uint32_t new_hash,
|
||||||
|
+ const char *version,
|
||||||
|
+ uint32_t version_hash) attribute_hidden;
|
||||||
|
+
|
||||||
|
/* Add the new link_map NEW to the end of the namespace list. */
|
||||||
|
extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid)
|
||||||
|
attribute_hidden;
|
||||||
|
diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
|
||||||
|
index f8ad2ceb8e324f92..1636a40ee5d78858 100644
|
||||||
|
--- a/sysdeps/mach/hurd/i386/init-first.c
|
||||||
|
+++ b/sysdeps/mach/hurd/i386/init-first.c
|
||||||
|
@@ -17,7 +17,6 @@
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
-#include <ctype.h>
|
||||||
|
#include <hurd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
@@ -84,9 +83,6 @@ posixland_init (int argc, char **argv, char **envp)
|
||||||
|
#endif
|
||||||
|
__init_misc (argc, argv, envp);
|
||||||
|
|
||||||
|
- /* Initialize ctype data. */
|
||||||
|
- __ctype_init ();
|
||||||
|
-
|
||||||
|
#if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS
|
||||||
|
__libc_global_ctors ();
|
||||||
|
#endif
|
688
SOURCES/glibc-rh1817513-51.patch
Normal file
688
SOURCES/glibc-rh1817513-51.patch
Normal file
@ -0,0 +1,688 @@
|
|||||||
|
commit 92954ffa5a5662fbfde14febd7e5dcc358c85470
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Wed Jan 8 13:24:42 2020 -0500
|
||||||
|
|
||||||
|
localedef: Add verbose messages for failure paths.
|
||||||
|
|
||||||
|
During testing of localedef running in a minimal container
|
||||||
|
there were several error cases which were hard to diagnose
|
||||||
|
since they appeared as strerror (errno) values printed by the
|
||||||
|
higher level functions. This change adds three new verbose
|
||||||
|
messages for potential failure paths. The new messages give
|
||||||
|
the user the opportunity to use -v and display additional
|
||||||
|
information about why localedef might be failing. I found
|
||||||
|
these messages useful myself while writing a localedef
|
||||||
|
container test for --no-hard-links.
|
||||||
|
|
||||||
|
Since the changes cleanup the code that handle codeset
|
||||||
|
normalization we add tst-localedef-path-norm which contains
|
||||||
|
many sub-tests to verify the correct expected normalization of
|
||||||
|
codeset strings both when installing to default paths (the
|
||||||
|
only time normalization is enabled) and installing to absolute
|
||||||
|
paths. During the refactoring I created at least one
|
||||||
|
buffer-overflow which valgrind caught, but these tests did not
|
||||||
|
catch because the exec in the container had a very clean heap
|
||||||
|
with zero-initialized memory. However, between valgrind and
|
||||||
|
the tests the results are clean.
|
||||||
|
|
||||||
|
The new tst-localedef-path-norm passes without regression on
|
||||||
|
x86_64.
|
||||||
|
|
||||||
|
Change-Id: I28b9f680711ff00252a2cb15625b774cc58ecb9d
|
||||||
|
|
||||||
|
diff --git a/include/programs/xasprintf.h b/include/programs/xasprintf.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..53193ba3837f7418
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/programs/xasprintf.h
|
||||||
|
@@ -0,0 +1,24 @@
|
||||||
|
+/* asprintf with out of memory checking
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published
|
||||||
|
+ by the Free Software Foundation; version 2 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program 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 a copy of the GNU General Public License
|
||||||
|
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#ifndef _XASPRINTF_H
|
||||||
|
+#define _XASPRINTF_H 1
|
||||||
|
+
|
||||||
|
+extern char *xasprintf (const char *format, ...)
|
||||||
|
+ __attribute__ ((__format__ (__printf__, 1, 2), __warn_unused_result__));
|
||||||
|
+
|
||||||
|
+#endif /* xasprintf.h */
|
||||||
|
diff --git a/locale/Makefile b/locale/Makefile
|
||||||
|
index 23a71321b6646c49..4278350cdc7be28d 100644
|
||||||
|
--- a/locale/Makefile
|
||||||
|
+++ b/locale/Makefile
|
||||||
|
@@ -28,6 +28,7 @@ routines = setlocale findlocale loadlocale loadarchive \
|
||||||
|
localeconv nl_langinfo nl_langinfo_l mb_cur_max \
|
||||||
|
newlocale duplocale freelocale uselocale
|
||||||
|
tests = tst-C-locale tst-locname tst-duplocale
|
||||||
|
+tests-container = tst-localedef-path-norm
|
||||||
|
categories = ctype messages monetary numeric time paper name \
|
||||||
|
address telephone measurement identification collate
|
||||||
|
aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \
|
||||||
|
@@ -54,7 +55,7 @@ localedef-modules := localedef $(categories:%=ld-%) \
|
||||||
|
localedef-aux := md5
|
||||||
|
locale-modules := locale locale-spec
|
||||||
|
lib-modules := charmap-dir simple-hash xmalloc xstrdup \
|
||||||
|
- record-status
|
||||||
|
+ record-status xasprintf
|
||||||
|
|
||||||
|
|
||||||
|
GPERF = gperf
|
||||||
|
diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c
|
||||||
|
index d718d2e9f47382bc..9a57d2cb435b25ed 100644
|
||||||
|
--- a/locale/programs/localedef.c
|
||||||
|
+++ b/locale/programs/localedef.c
|
||||||
|
@@ -174,14 +174,14 @@ static struct argp argp =
|
||||||
|
|
||||||
|
/* Prototypes for local functions. */
|
||||||
|
static void error_print (void);
|
||||||
|
-static const char *construct_output_path (char *path);
|
||||||
|
-static const char *normalize_codeset (const char *codeset, size_t name_len);
|
||||||
|
+static char *construct_output_path (char *path);
|
||||||
|
+static char *normalize_codeset (const char *codeset, size_t name_len);
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
- const char *output_path;
|
||||||
|
+ char *output_path;
|
||||||
|
int cannot_write_why;
|
||||||
|
struct charmap_t *charmap;
|
||||||
|
struct localedef_t global;
|
||||||
|
@@ -226,7 +226,8 @@ main (int argc, char *argv[])
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The parameter describes the output path of the constructed files.
|
||||||
|
- If the described files cannot be written return a NULL pointer. */
|
||||||
|
+ If the described files cannot be written return a NULL pointer.
|
||||||
|
+ We don't free output_path because we will exit. */
|
||||||
|
output_path = construct_output_path (argv[remaining]);
|
||||||
|
if (output_path == NULL && ! no_archive)
|
||||||
|
error (4, errno, _("cannot create directory for output files"));
|
||||||
|
@@ -424,20 +425,16 @@ more_help (int key, const char *text, void *input)
|
||||||
|
{
|
||||||
|
case ARGP_KEY_HELP_EXTRA:
|
||||||
|
/* We print some extra information. */
|
||||||
|
- if (asprintf (&tp, gettext ("\
|
||||||
|
+ tp = xasprintf (gettext ("\
|
||||||
|
For bug reporting instructions, please see:\n\
|
||||||
|
-%s.\n"), REPORT_BUGS_TO) < 0)
|
||||||
|
- return NULL;
|
||||||
|
- if (asprintf (&cp, gettext ("\
|
||||||
|
+%s.\n"), REPORT_BUGS_TO);
|
||||||
|
+ cp = xasprintf (gettext ("\
|
||||||
|
System's directory for character maps : %s\n\
|
||||||
|
repertoire maps: %s\n\
|
||||||
|
locale path : %s\n\
|
||||||
|
%s"),
|
||||||
|
- CHARMAP_PATH, REPERTOIREMAP_PATH, LOCALE_PATH, tp) < 0)
|
||||||
|
- {
|
||||||
|
- free (tp);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ CHARMAP_PATH, REPERTOIREMAP_PATH, LOCALE_PATH, tp);
|
||||||
|
+ free (tp);
|
||||||
|
return cp;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
@@ -467,15 +464,13 @@ error_print (void)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-/* The parameter to localedef describes the output path. If it does
|
||||||
|
- contain a '/' character it is a relative path. Otherwise it names the
|
||||||
|
- locale this definition is for. */
|
||||||
|
-static const char *
|
||||||
|
+/* The parameter to localedef describes the output path. If it does contain a
|
||||||
|
+ '/' character it is a relative path. Otherwise it names the locale this
|
||||||
|
+ definition is for. The returned path must be freed by the caller. */
|
||||||
|
+static char *
|
||||||
|
construct_output_path (char *path)
|
||||||
|
{
|
||||||
|
- const char *normal = NULL;
|
||||||
|
char *result;
|
||||||
|
- char *endp;
|
||||||
|
|
||||||
|
if (strchr (path, '/') == NULL)
|
||||||
|
{
|
||||||
|
@@ -483,50 +478,44 @@ construct_output_path (char *path)
|
||||||
|
contains a reference to the codeset. This should be
|
||||||
|
normalized. */
|
||||||
|
char *startp;
|
||||||
|
+ char *endp = NULL;
|
||||||
|
+ char *normal = NULL;
|
||||||
|
|
||||||
|
startp = path;
|
||||||
|
- /* We must be prepared for finding a CEN name or a location of
|
||||||
|
- the introducing `.' where it is not possible anymore. */
|
||||||
|
+ /* Either we have a '@' which starts a CEN name or '.' which starts the
|
||||||
|
+ codeset specification. The CEN name starts with '@' and may also have
|
||||||
|
+ a codeset specification, but we do not normalize the string after '@'.
|
||||||
|
+ If we only find the codeset specification then we normalize only the codeset
|
||||||
|
+ specification (but not anything after a subsequent '@'). */
|
||||||
|
while (*startp != '\0' && *startp != '@' && *startp != '.')
|
||||||
|
++startp;
|
||||||
|
if (*startp == '.')
|
||||||
|
{
|
||||||
|
/* We found a codeset specification. Now find the end. */
|
||||||
|
endp = ++startp;
|
||||||
|
+
|
||||||
|
+ /* Stop at the first '@', and don't normalize anything past that. */
|
||||||
|
while (*endp != '\0' && *endp != '@')
|
||||||
|
++endp;
|
||||||
|
|
||||||
|
if (endp > startp)
|
||||||
|
normal = normalize_codeset (startp, endp - startp);
|
||||||
|
}
|
||||||
|
- else
|
||||||
|
- /* This is to keep gcc quiet. */
|
||||||
|
- endp = NULL;
|
||||||
|
|
||||||
|
- /* We put an additional '\0' at the end of the string because at
|
||||||
|
- the end of the function we need another byte for the trailing
|
||||||
|
- '/'. */
|
||||||
|
- ssize_t n;
|
||||||
|
if (normal == NULL)
|
||||||
|
- n = asprintf (&result, "%s%s/%s%c", output_prefix ?: "",
|
||||||
|
- COMPLOCALEDIR, path, '\0');
|
||||||
|
+ result = xasprintf ("%s%s/%s/", output_prefix ?: "",
|
||||||
|
+ COMPLOCALEDIR, path);
|
||||||
|
else
|
||||||
|
- n = asprintf (&result, "%s%s/%.*s%s%s%c",
|
||||||
|
- output_prefix ?: "", COMPLOCALEDIR,
|
||||||
|
- (int) (startp - path), path, normal, endp, '\0');
|
||||||
|
-
|
||||||
|
- if (n < 0)
|
||||||
|
- return NULL;
|
||||||
|
-
|
||||||
|
- endp = result + n - 1;
|
||||||
|
+ result = xasprintf ("%s%s/%.*s%s%s/",
|
||||||
|
+ output_prefix ?: "", COMPLOCALEDIR,
|
||||||
|
+ (int) (startp - path), path, normal, endp ?: "");
|
||||||
|
+ /* Free the allocated normalized codeset name. */
|
||||||
|
+ free (normal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
- /* This is a user path. Please note the additional byte in the
|
||||||
|
- memory allocation. */
|
||||||
|
- size_t len = strlen (path) + 1;
|
||||||
|
- result = xmalloc (len + 1);
|
||||||
|
- endp = mempcpy (result, path, len) - 1;
|
||||||
|
+ /* This is a user path. */
|
||||||
|
+ result = xasprintf ("%s/", path);
|
||||||
|
|
||||||
|
/* If the user specified an output path we cannot add the output
|
||||||
|
to the archive. */
|
||||||
|
@@ -536,25 +525,41 @@ construct_output_path (char *path)
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
if (no_archive && euidaccess (result, W_OK) == -1)
|
||||||
|
- /* Perhaps the directory does not exist now. Try to create it. */
|
||||||
|
- if (errno == ENOENT)
|
||||||
|
- {
|
||||||
|
- errno = 0;
|
||||||
|
- if (mkdir (result, 0777) < 0)
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- *endp++ = '/';
|
||||||
|
- *endp = '\0';
|
||||||
|
+ {
|
||||||
|
+ /* Perhaps the directory does not exist now. Try to create it. */
|
||||||
|
+ if (errno == ENOENT)
|
||||||
|
+ {
|
||||||
|
+ errno = 0;
|
||||||
|
+ if (mkdir (result, 0777) < 0)
|
||||||
|
+ {
|
||||||
|
+ record_verbose (stderr,
|
||||||
|
+ _("cannot create output path \'%s\': %s"),
|
||||||
|
+ result, strerror (errno));
|
||||||
|
+ free (result);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ record_verbose (stderr,
|
||||||
|
+ _("no write permission to output path \'%s\': %s"),
|
||||||
|
+ result, strerror (errno));
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-/* Normalize codeset name. There is no standard for the codeset
|
||||||
|
- names. Normalization allows the user to use any of the common
|
||||||
|
- names. */
|
||||||
|
-static const char *
|
||||||
|
+/* Normalize codeset name. There is no standard for the codeset names.
|
||||||
|
+ Normalization allows the user to use any of the common names e.g. UTF-8,
|
||||||
|
+ utf-8, utf8, UTF8 etc.
|
||||||
|
+
|
||||||
|
+ We normalize using the following rules:
|
||||||
|
+ - Remove all non-alpha-numeric characters
|
||||||
|
+ - Lowercase all characters.
|
||||||
|
+ - If there are only digits assume it's an ISO standard and prefix with 'iso'
|
||||||
|
+
|
||||||
|
+ We return the normalized string which needs to be freed by free. */
|
||||||
|
+static char *
|
||||||
|
normalize_codeset (const char *codeset, size_t name_len)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
@@ -563,6 +568,7 @@ normalize_codeset (const char *codeset, size_t name_len)
|
||||||
|
char *wp;
|
||||||
|
size_t cnt;
|
||||||
|
|
||||||
|
+ /* Compute the length of only the alpha-numeric characters. */
|
||||||
|
for (cnt = 0; cnt < name_len; ++cnt)
|
||||||
|
if (isalnum (codeset[cnt]))
|
||||||
|
{
|
||||||
|
@@ -572,25 +578,24 @@ normalize_codeset (const char *codeset, size_t name_len)
|
||||||
|
only_digit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
|
||||||
|
+ /* If there were only digits we assume it's an ISO standard and we will
|
||||||
|
+ prefix with 'iso' so include space for that. We fill in the required
|
||||||
|
+ space from codeset up to the converted length. */
|
||||||
|
+ wp = retval = xasprintf ("%s%.*s", only_digit ? "iso" : "", len, codeset);
|
||||||
|
|
||||||
|
- if (retval != NULL)
|
||||||
|
- {
|
||||||
|
- if (only_digit)
|
||||||
|
- wp = stpcpy (retval, "iso");
|
||||||
|
- else
|
||||||
|
- wp = retval;
|
||||||
|
-
|
||||||
|
- for (cnt = 0; cnt < name_len; ++cnt)
|
||||||
|
- if (isalpha (codeset[cnt]))
|
||||||
|
- *wp++ = tolower (codeset[cnt]);
|
||||||
|
- else if (isdigit (codeset[cnt]))
|
||||||
|
- *wp++ = codeset[cnt];
|
||||||
|
+ /* Skip "iso". */
|
||||||
|
+ if (only_digit)
|
||||||
|
+ wp += 3;
|
||||||
|
|
||||||
|
- *wp = '\0';
|
||||||
|
- }
|
||||||
|
+ /* Lowercase all characters. */
|
||||||
|
+ for (cnt = 0; cnt < name_len; ++cnt)
|
||||||
|
+ if (isalpha (codeset[cnt]))
|
||||||
|
+ *wp++ = tolower (codeset[cnt]);
|
||||||
|
+ else if (isdigit (codeset[cnt]))
|
||||||
|
+ *wp++ = codeset[cnt];
|
||||||
|
|
||||||
|
- return (const char *) retval;
|
||||||
|
+ /* Return allocated and converted name for caller to free. */
|
||||||
|
+ return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/locale/programs/localedef.h b/locale/programs/localedef.h
|
||||||
|
index 0083faceabbf3dd9..c528dbb97854dbd1 100644
|
||||||
|
--- a/locale/programs/localedef.h
|
||||||
|
+++ b/locale/programs/localedef.h
|
||||||
|
@@ -122,6 +122,7 @@ extern const char *alias_file;
|
||||||
|
|
||||||
|
/* Prototypes for a few program-wide used functions. */
|
||||||
|
#include <programs/xmalloc.h>
|
||||||
|
+#include <programs/xasprintf.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Mark given locale as to be read. */
|
||||||
|
diff --git a/locale/programs/xasprintf.c b/locale/programs/xasprintf.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..efc91a9c34074736
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/locale/programs/xasprintf.c
|
||||||
|
@@ -0,0 +1,34 @@
|
||||||
|
+/* asprintf with out of memory checking
|
||||||
|
+ Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
+ This file is part of the GNU C Library.
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published
|
||||||
|
+ by the Free Software Foundation; version 2 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program 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 a copy of the GNU General Public License
|
||||||
|
+ along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+#include <libintl.h>
|
||||||
|
+#include <error.h>
|
||||||
|
+
|
||||||
|
+char *
|
||||||
|
+xasprintf (const char *format, ...)
|
||||||
|
+{
|
||||||
|
+ va_list ap;
|
||||||
|
+ va_start (ap, format);
|
||||||
|
+ char *result;
|
||||||
|
+ if (vasprintf (&result, format, ap) < 0)
|
||||||
|
+ error (EXIT_FAILURE, 0, _("memory exhausted"));
|
||||||
|
+ va_end (ap);
|
||||||
|
+ return result;
|
||||||
|
+}
|
||||||
|
diff --git a/locale/tst-localedef-path-norm.c b/locale/tst-localedef-path-norm.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..2ef1d26f07084c68
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/locale/tst-localedef-path-norm.c
|
||||||
|
@@ -0,0 +1,242 @@
|
||||||
|
+/* Test for localedef path name handling and normalization.
|
||||||
|
+ Copyright (C) 2019 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/>. */
|
||||||
|
+
|
||||||
|
+/* The test runs localedef with various named paths to test for expected
|
||||||
|
+ behaviours dealing with codeset name normalization. That is to say that use
|
||||||
|
+ of UTF-8, and it's variations, are normalized to utf8. Likewise that values
|
||||||
|
+ after the @ are not normalized and left as-is. The test needs to run
|
||||||
|
+ localedef with known input values and then check that the generated path
|
||||||
|
+ matches the expected value after normalization. */
|
||||||
|
+
|
||||||
|
+/* Note: In some cases adding -v (verbose) to localedef changes the exit
|
||||||
|
+ status to a non-zero value because some warnings are only enabled in verbose
|
||||||
|
+ mode. This should probably be changed so warnings are either present or not
|
||||||
|
+ present, regardless of verbosity. POSIX requires that any warnings cause the
|
||||||
|
+ exit status to be non-zero. */
|
||||||
|
+
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+
|
||||||
|
+#include <support/capture_subprocess.h>
|
||||||
|
+#include <support/check.h>
|
||||||
|
+#include <support/support.h>
|
||||||
|
+#include <support/xunistd.h>
|
||||||
|
+
|
||||||
|
+/* Full path to localedef. */
|
||||||
|
+char *prog;
|
||||||
|
+
|
||||||
|
+/* Execute localedef in a subprocess. */
|
||||||
|
+static void
|
||||||
|
+execv_wrapper (void *args)
|
||||||
|
+{
|
||||||
|
+ char **argv = args;
|
||||||
|
+
|
||||||
|
+ execv (prog, argv);
|
||||||
|
+ FAIL_EXIT1 ("execv: %m");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct test_closure
|
||||||
|
+{
|
||||||
|
+ /* Arguments for running localedef. */
|
||||||
|
+ const char *const argv[16];
|
||||||
|
+ /* Expected directory name for compiled locale. */
|
||||||
|
+ const char *exp;
|
||||||
|
+ /* Expected path to compiled locale. */
|
||||||
|
+ const char *complocaledir;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Run localedef with DATA.ARGV arguments (NULL terminated), and expect path to
|
||||||
|
+ the compiled locale is "DATA.COMPLOCALEDIR/DATA.EXP". */
|
||||||
|
+static void
|
||||||
|
+run_test (struct test_closure data)
|
||||||
|
+{
|
||||||
|
+ const char * const *args = data.argv;
|
||||||
|
+ const char *exp = data.exp;
|
||||||
|
+ const char *complocaledir = data.complocaledir;
|
||||||
|
+ struct stat64 fs;
|
||||||
|
+
|
||||||
|
+ /* Expected output path. */
|
||||||
|
+ const char *path = xasprintf ("%s/%s", complocaledir, exp);
|
||||||
|
+
|
||||||
|
+ /* Run test. */
|
||||||
|
+ struct support_capture_subprocess result;
|
||||||
|
+ result = support_capture_subprocess (execv_wrapper, (void *)args);
|
||||||
|
+ support_capture_subprocess_check (&result, "execv", 0, sc_allow_none);
|
||||||
|
+ support_capture_subprocess_free (&result);
|
||||||
|
+
|
||||||
|
+ /* Verify path is present and is a directory. */
|
||||||
|
+ xstat (path, &fs);
|
||||||
|
+ TEST_VERIFY_EXIT (S_ISDIR (fs.st_mode));
|
||||||
|
+ printf ("info: Directory '%s' exists.\n", path);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_test (void)
|
||||||
|
+{
|
||||||
|
+ /* We are running as root inside the container. */
|
||||||
|
+ prog = xasprintf ("%s/localedef", support_bindir_prefix);
|
||||||
|
+
|
||||||
|
+ /* Create the needed directories:
|
||||||
|
+ - We need the default compiled locale dir for default output.
|
||||||
|
+ - We need an arbitrary absolute path for localedef output.
|
||||||
|
+
|
||||||
|
+ Note: Writing to a non-default absolute path disables any kind
|
||||||
|
+ of path normalization since we expect the user wants the path
|
||||||
|
+ exactly as they specified it. */
|
||||||
|
+ xmkdirp (support_complocaledir_prefix, 0777);
|
||||||
|
+ xmkdirp ("/output", 0777);
|
||||||
|
+
|
||||||
|
+ /* It takes ~10 seconds to serially execute 9 localedef test. We
|
||||||
|
+ could run the compilations in parallel if we want to reduce test
|
||||||
|
+ time. We don't want to split this out into distinct tests because
|
||||||
|
+ it would require multiple chroots. Batching the same localedef
|
||||||
|
+ tests saves disk space during testing. */
|
||||||
|
+
|
||||||
|
+ /* Test 1: Expected normalization.
|
||||||
|
+ Run localedef and expect output in /usr/lib/locale/en_US1.utf8,
|
||||||
|
+ with normalization changing UTF-8 to utf8. */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "en_US1.UTF-8", NULL },
|
||||||
|
+ .exp = "en_US1.utf8",
|
||||||
|
+ .complocaledir = support_complocaledir_prefix
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ /* Test 2: No normalization past '@'.
|
||||||
|
+ Run localedef and expect output in /usr/lib/locale/en_US2.utf8@tEsT,
|
||||||
|
+ with normalization changing UTF-8@tEsT to utf8@tEsT (everything after
|
||||||
|
+ @ is untouched). */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "en_US2.UTF-8@tEsT", NULL },
|
||||||
|
+ .exp = "en_US2.utf8@tEsT",
|
||||||
|
+ .complocaledir = support_complocaledir_prefix
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ /* Test 3: No normalization past '@' despite period.
|
||||||
|
+ Run localedef and expect output in /usr/lib/locale/en_US3@tEsT.UTF-8,
|
||||||
|
+ with normalization changing nothing (everything after @ is untouched)
|
||||||
|
+ despite there being a period near the end. */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "en_US3@tEsT.UTF-8", NULL },
|
||||||
|
+ .exp = "en_US3@tEsT.UTF-8",
|
||||||
|
+ .complocaledir = support_complocaledir_prefix
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ /* Test 4: Normalize numeric codeset by adding 'iso' prefix.
|
||||||
|
+ Run localedef and expect output in /usr/lib/locale/en_US4.88591,
|
||||||
|
+ with normalization changing 88591 to iso88591. */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "en_US4.88591", NULL },
|
||||||
|
+ .exp = "en_US4.iso88591",
|
||||||
|
+ .complocaledir = support_complocaledir_prefix
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ /* Test 5: Don't add 'iso' prefix if first char is alpha.
|
||||||
|
+ Run localedef and expect output in /usr/lib/locale/en_US5.a88591,
|
||||||
|
+ with normalization changing nothing. */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "en_US5.a88591", NULL },
|
||||||
|
+ .exp = "en_US5.a88591",
|
||||||
|
+ .complocaledir = support_complocaledir_prefix
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ /* Test 6: Don't add 'iso' prefix if last char is alpha.
|
||||||
|
+ Run localedef and expect output in /usr/lib/locale/en_US6.88591a,
|
||||||
|
+ with normalization changing nothing. */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "en_US6.88591a", NULL },
|
||||||
|
+ .exp = "en_US6.88591a",
|
||||||
|
+ .complocaledir = support_complocaledir_prefix
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ /* Test 7: Don't normalize anything with an absolute path.
|
||||||
|
+ Run localedef and expect output in /output/en_US7.UTF-8,
|
||||||
|
+ with normalization changing nothing. */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "/output/en_US7.UTF-8", NULL },
|
||||||
|
+ .exp = "en_US7.UTF-8",
|
||||||
|
+ .complocaledir = "/output"
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ /* Test 8: Don't normalize anything with an absolute path.
|
||||||
|
+ Run localedef and expect output in /output/en_US8.UTF-8@tEsT,
|
||||||
|
+ with normalization changing nothing. */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "/output/en_US8.UTF-8@tEsT", NULL },
|
||||||
|
+ .exp = "en_US8.UTF-8@tEsT",
|
||||||
|
+ .complocaledir = "/output"
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ /* Test 9: Don't normalize anything with an absolute path.
|
||||||
|
+ Run localedef and expect output in /output/en_US9@tEsT.UTF-8,
|
||||||
|
+ with normalization changing nothing. */
|
||||||
|
+ run_test ((struct test_closure)
|
||||||
|
+ {
|
||||||
|
+ .argv = { prog,
|
||||||
|
+ "--no-archive",
|
||||||
|
+ "-i", "en_US",
|
||||||
|
+ "-f", "UTF-8",
|
||||||
|
+ "/output/en_US9@tEsT.UTF-8", NULL },
|
||||||
|
+ .exp = "en_US9@tEsT.UTF-8",
|
||||||
|
+ .complocaledir = "/output"
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#include <support/test-driver.c>
|
||||||
|
diff --git a/locale/tst-localedef-path-norm.root/postclean.req b/locale/tst-localedef-path-norm.root/postclean.req
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..e69de29bb2d1d643
|
||||||
|
diff --git a/locale/tst-localedef-path-norm.root/tst-localedef-path-norm.script b/locale/tst-localedef-path-norm.root/tst-localedef-path-norm.script
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000..b0f016256a47f762
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/locale/tst-localedef-path-norm.root/tst-localedef-path-norm.script
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+# Must run localedef as root to write into default paths.
|
||||||
|
+su
|
||||||
|
diff --git a/support/Makefile b/support/Makefile
|
||||||
|
index 117cfdd4f22fc405..5808a42dce87151f 100644
|
||||||
|
--- a/support/Makefile
|
||||||
|
+++ b/support/Makefile
|
||||||
|
@@ -182,7 +182,8 @@ CFLAGS-support_paths.c = \
|
||||||
|
-DLIBDIR_PATH=\"$(libdir)\" \
|
||||||
|
-DBINDIR_PATH=\"$(bindir)\" \
|
||||||
|
-DSBINDIR_PATH=\"$(sbindir)\" \
|
||||||
|
- -DROOTSBINDIR_PATH=\"$(rootsbindir)\"
|
||||||
|
+ -DROOTSBINDIR_PATH=\"$(rootsbindir)\" \
|
||||||
|
+ -DCOMPLOCALEDIR_PATH=\"$(complocaledir)\"
|
||||||
|
|
||||||
|
ifeq (,$(CXX))
|
||||||
|
LINKS_DSO_PROGRAM = links-dso-program-c
|
||||||
|
diff --git a/support/support.h b/support/support.h
|
||||||
|
index 121cc9e9b7c98ca6..3af87f85fe1b762d 100644
|
||||||
|
--- a/support/support.h
|
||||||
|
+++ b/support/support.h
|
||||||
|
@@ -112,6 +112,8 @@ extern const char support_bindir_prefix[];
|
||||||
|
extern const char support_sbindir_prefix[];
|
||||||
|
/* Corresponds to the install's sbin/ directory (without prefix). */
|
||||||
|
extern const char support_install_rootsbindir[];
|
||||||
|
+/* Corresponds to the install's compiled locale directory. */
|
||||||
|
+extern const char support_complocaledir_prefix[];
|
||||||
|
|
||||||
|
extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *,
|
||||||
|
size_t, unsigned int);
|
||||||
|
diff --git a/support/support_paths.c b/support/support_paths.c
|
||||||
|
index eb2390227433aa70..6b15fae0f0173b1e 100644
|
||||||
|
--- a/support/support_paths.c
|
||||||
|
+++ b/support/support_paths.c
|
||||||
|
@@ -78,3 +78,10 @@ const char support_install_rootsbindir[] = ROOTSBINDIR_PATH;
|
||||||
|
#else
|
||||||
|
# error please -DROOTSBINDIR_PATH=something in the Makefile
|
||||||
|
#endif
|
||||||
|
+
|
||||||
|
+#ifdef COMPLOCALEDIR_PATH
|
||||||
|
+/* Corresponds to the install's compiled locale directory. */
|
||||||
|
+const char support_complocaledir_prefix[] = COMPLOCALEDIR_PATH;
|
||||||
|
+#else
|
||||||
|
+# error please -DCOMPLOCALEDIR_PATH=something in the Makefile
|
||||||
|
+#endif
|
141
SOURCES/glibc-rh1817513-52.patch
Normal file
141
SOURCES/glibc-rh1817513-52.patch
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
commit 03e187a41d91069543cfcf33469a05912e555447
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed Apr 29 15:44:03 2020 +0200
|
||||||
|
|
||||||
|
elf: Add initial flag argument to __libc_early_init
|
||||||
|
|
||||||
|
The rseq initialization should happen only for the libc in the base
|
||||||
|
namespace (in the dynamic case) or the statically linked libc. The
|
||||||
|
__libc_multiple_libcs flag does not quite cover this case at present,
|
||||||
|
so this commit introduces a flag argument to __libc_early_init,
|
||||||
|
indicating whether the libc being libc is the primary one (of the main
|
||||||
|
program).
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/csu/libc-start.c b/csu/libc-start.c
|
||||||
|
index d9c3248219d8f84f..fd0f8640eaeae34c 100644
|
||||||
|
--- a/csu/libc-start.c
|
||||||
|
+++ b/csu/libc-start.c
|
||||||
|
@@ -23,6 +23,7 @@
|
||||||
|
#include <exit-thread.h>
|
||||||
|
#include <libc-internal.h>
|
||||||
|
#include <elf/libc-early-init.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <elf/dl-tunables.h>
|
||||||
|
|
||||||
|
@@ -241,7 +242,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||||
|
#ifndef SHARED
|
||||||
|
/* Perform early initialization. In the shared case, this function
|
||||||
|
is called from the dynamic loader as early as possible. */
|
||||||
|
- __libc_early_init ();
|
||||||
|
+ __libc_early_init (true);
|
||||||
|
|
||||||
|
/* Call the initializer of the libc. This is only needed here if we
|
||||||
|
are compiling for the static library in which case we haven't
|
||||||
|
diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c
|
||||||
|
index 41e9ad9aad8b5b46..9a84680a1ceafba2 100644
|
||||||
|
--- a/elf/dl-call-libc-early-init.c
|
||||||
|
+++ b/elf/dl-call-libc-early-init.c
|
||||||
|
@@ -23,7 +23,7 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
-_dl_call_libc_early_init (struct link_map *libc_map)
|
||||||
|
+_dl_call_libc_early_init (struct link_map *libc_map, _Bool initial)
|
||||||
|
{
|
||||||
|
/* There is nothing to do if we did not actually load libc.so. */
|
||||||
|
if (libc_map == NULL)
|
||||||
|
@@ -37,5 +37,5 @@ _dl_call_libc_early_init (struct link_map *libc_map)
|
||||||
|
assert (sym != NULL);
|
||||||
|
__typeof (__libc_early_init) *early_init
|
||||||
|
= DL_SYMBOL_ADDRESS (libc_map, sym);
|
||||||
|
- early_init ();
|
||||||
|
+ early_init (initial);
|
||||||
|
}
|
||||||
|
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||||
|
index 1a77ec833cad6c55..3d49a84596e99bf6 100644
|
||||||
|
--- a/elf/dl-open.c
|
||||||
|
+++ b/elf/dl-open.c
|
||||||
|
@@ -748,9 +748,22 @@ dl_open_worker (void *a)
|
||||||
|
LIBC_PROBE (reloc_complete, 3, args->nsid, r, new);
|
||||||
|
|
||||||
|
/* If libc.so was not there before, attempt to call its early
|
||||||
|
- initialization routine. */
|
||||||
|
+ initialization routine. Indicate to the initialization routine
|
||||||
|
+ whether the libc being initialized is the one in the base
|
||||||
|
+ namespace. */
|
||||||
|
if (!args->libc_already_loaded)
|
||||||
|
- _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map);
|
||||||
|
+ {
|
||||||
|
+ struct link_map *libc_map = GL(dl_ns)[args->nsid].libc_map;
|
||||||
|
+#ifdef SHARED
|
||||||
|
+ bool initial = libc_map->l_ns == LM_ID_BASE;
|
||||||
|
+#else
|
||||||
|
+ /* In the static case, there is only one namespace, but it
|
||||||
|
+ contains a secondary libc (the primary libc is statically
|
||||||
|
+ linked). */
|
||||||
|
+ bool initial = false;
|
||||||
|
+#endif
|
||||||
|
+ _dl_call_libc_early_init (libc_map, initial);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
#ifndef SHARED
|
||||||
|
DL_STATIC_INIT (new);
|
||||||
|
diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h
|
||||||
|
index 5185fa8895c0e11a..8f7836dceaeecd5a 100644
|
||||||
|
--- a/elf/libc-early-init.h
|
||||||
|
+++ b/elf/libc-early-init.h
|
||||||
|
@@ -22,14 +22,17 @@
|
||||||
|
struct link_map;
|
||||||
|
|
||||||
|
/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it
|
||||||
|
- and call this function. */
|
||||||
|
-void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden;
|
||||||
|
+ and call this function, with INITIAL as the argument. */
|
||||||
|
+void _dl_call_libc_early_init (struct link_map *libc_map, _Bool initial)
|
||||||
|
+ attribute_hidden;
|
||||||
|
|
||||||
|
/* In the shared case, this function is defined in libc.so and invoked
|
||||||
|
from ld.so (or on the fist static dlopen) after complete relocation
|
||||||
|
of a new loaded libc.so, but before user-defined ELF constructors
|
||||||
|
run. In the static case, this function is called directly from the
|
||||||
|
- startup code. */
|
||||||
|
-void __libc_early_init (void);
|
||||||
|
+ startup code. If INITIAL is true, the libc being initialized is
|
||||||
|
+ the libc for the main program. INITIAL is false for libcs loaded
|
||||||
|
+ for audit modules, dlmopen, and static dlopen. */
|
||||||
|
+void __libc_early_init (_Bool initial);
|
||||||
|
|
||||||
|
#endif /* _LIBC_EARLY_INIT_H */
|
||||||
|
diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c
|
||||||
|
index 7f4ca332b805a22c..e6c64fb526600fae 100644
|
||||||
|
--- a/elf/libc_early_init.c
|
||||||
|
+++ b/elf/libc_early_init.c
|
||||||
|
@@ -20,7 +20,7 @@
|
||||||
|
#include <libc-early-init.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
-__libc_early_init (void)
|
||||||
|
+__libc_early_init (_Bool initial)
|
||||||
|
{
|
||||||
|
/* Initialize ctype data. */
|
||||||
|
__ctype_init ();
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index a40d5f17db0dac8b..772aff5160359b7b 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -2366,8 +2366,10 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
|
||||||
|
rtld_timer_accum (&relocate_time, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* Relocation is complete. Perform early libc initialization. */
|
||||||
|
- _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map);
|
||||||
|
+ /* Relocation is complete. Perform early libc initialization. This
|
||||||
|
+ is the initial libc, even if audit modules have been loaded with
|
||||||
|
+ other libcs. */
|
||||||
|
+ _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map, true);
|
||||||
|
|
||||||
|
/* Do any necessary cleanups for the startup OS interface code.
|
||||||
|
We do these now so that no calls are made after rtld re-relocation
|
86
SOURCES/glibc-rh1817513-53.patch
Normal file
86
SOURCES/glibc-rh1817513-53.patch
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
commit 32ac0b988466785d6e3cc1dffc364bb26fc63193
|
||||||
|
Author: mayshao <mayshao-oc@zhaoxin.com>
|
||||||
|
Date: Fri Apr 24 12:55:38 2020 +0800
|
||||||
|
|
||||||
|
x86: Add CPU Vendor ID detection support for Zhaoxin processors
|
||||||
|
|
||||||
|
To recognize Zhaoxin CPU Vendor ID, add a new architecture type
|
||||||
|
arch_kind_zhaoxin for Vendor Zhaoxin detection.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index ade37a9bb3de86cc..c432d646ce6806a6 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -464,6 +464,60 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ /* This spells out "CentaurHauls" or " Shanghai ". */
|
||||||
|
+ else if ((ebx == 0x746e6543 && ecx == 0x736c7561 && edx == 0x48727561)
|
||||||
|
+ || (ebx == 0x68532020 && ecx == 0x20206961 && edx == 0x68676e61))
|
||||||
|
+ {
|
||||||
|
+ unsigned int extended_model, stepping;
|
||||||
|
+
|
||||||
|
+ kind = arch_kind_zhaoxin;
|
||||||
|
+
|
||||||
|
+ get_common_indices (cpu_features, &family, &model, &extended_model,
|
||||||
|
+ &stepping);
|
||||||
|
+
|
||||||
|
+ get_extended_indices (cpu_features);
|
||||||
|
+
|
||||||
|
+ model += extended_model;
|
||||||
|
+ if (family == 0x6)
|
||||||
|
+ {
|
||||||
|
+ if (model == 0xf || model == 0x19)
|
||||||
|
+ {
|
||||||
|
+ cpu_features->feature[index_arch_AVX_Usable]
|
||||||
|
+ &= (~bit_arch_AVX_Usable
|
||||||
|
+ & ~bit_arch_AVX2_Usable);
|
||||||
|
+
|
||||||
|
+ cpu_features->feature[index_arch_Slow_SSE4_2]
|
||||||
|
+ |= (bit_arch_Slow_SSE4_2);
|
||||||
|
+
|
||||||
|
+ cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
|
||||||
|
+ &= ~bit_arch_AVX_Fast_Unaligned_Load;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (family == 0x7)
|
||||||
|
+ {
|
||||||
|
+ if (model == 0x1b)
|
||||||
|
+ {
|
||||||
|
+ cpu_features->feature[index_arch_AVX_Usable]
|
||||||
|
+ &= (~bit_arch_AVX_Usable
|
||||||
|
+ & ~bit_arch_AVX2_Usable);
|
||||||
|
+
|
||||||
|
+ cpu_features->feature[index_arch_Slow_SSE4_2]
|
||||||
|
+ |= bit_arch_Slow_SSE4_2;
|
||||||
|
+
|
||||||
|
+ cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
|
||||||
|
+ &= ~bit_arch_AVX_Fast_Unaligned_Load;
|
||||||
|
+ }
|
||||||
|
+ else if (model == 0x3b)
|
||||||
|
+ {
|
||||||
|
+ cpu_features->feature[index_arch_AVX_Usable]
|
||||||
|
+ &= (~bit_arch_AVX_Usable
|
||||||
|
+ & ~bit_arch_AVX2_Usable);
|
||||||
|
+
|
||||||
|
+ cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load]
|
||||||
|
+ &= ~bit_arch_AVX_Fast_Unaligned_Load;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kind = arch_kind_other;
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
|
||||||
|
index 4917182e99a8ee90..388172a1c07bf979 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.h
|
||||||
|
+++ b/sysdeps/x86/cpu-features.h
|
||||||
|
@@ -53,6 +53,7 @@ enum cpu_features_kind
|
||||||
|
arch_kind_unknown = 0,
|
||||||
|
arch_kind_intel,
|
||||||
|
arch_kind_amd,
|
||||||
|
+ arch_kind_zhaoxin,
|
||||||
|
arch_kind_other
|
||||||
|
};
|
||||||
|
|
534
SOURCES/glibc-rh1817513-54.patch
Normal file
534
SOURCES/glibc-rh1817513-54.patch
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
commit a98dc92dd1e278df4c501deb07985018bc2b06de
|
||||||
|
Author: mayshao-oc <mayshao-oc@zhaoxin.com>
|
||||||
|
Date: Sun Apr 26 13:48:27 2020 +0800
|
||||||
|
|
||||||
|
x86: Add cache information support for Zhaoxin processors
|
||||||
|
|
||||||
|
To obtain Zhaoxin CPU cache information, add a new function
|
||||||
|
handle_zhaoxin().
|
||||||
|
|
||||||
|
Add a new function get_common_cache_info() that extracts the code
|
||||||
|
in init_cacheinfo() to get the value of the variable shared, threads.
|
||||||
|
|
||||||
|
Add Zhaoxin branch in init_cacheinfo() for initializing variables,
|
||||||
|
such as __x86_shared_cache_size.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c
|
||||||
|
index f1125f30223f5ca3..aa7cb705d546bcd0 100644
|
||||||
|
--- a/sysdeps/x86/cacheinfo.c
|
||||||
|
+++ b/sysdeps/x86/cacheinfo.c
|
||||||
|
@@ -436,6 +436,57 @@ handle_amd (int name)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+static long int __attribute__ ((noinline))
|
||||||
|
+handle_zhaoxin (int name)
|
||||||
|
+{
|
||||||
|
+ unsigned int eax;
|
||||||
|
+ unsigned int ebx;
|
||||||
|
+ unsigned int ecx;
|
||||||
|
+ unsigned int edx;
|
||||||
|
+
|
||||||
|
+ int folded_rel_name = (M(name) / 3) * 3;
|
||||||
|
+
|
||||||
|
+ unsigned int round = 0;
|
||||||
|
+ while (1)
|
||||||
|
+ {
|
||||||
|
+ __cpuid_count (4, round, eax, ebx, ecx, edx);
|
||||||
|
+
|
||||||
|
+ enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f;
|
||||||
|
+ if (type == null)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ unsigned int level = (eax >> 5) & 0x7;
|
||||||
|
+
|
||||||
|
+ if ((level == 1 && type == data
|
||||||
|
+ && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE))
|
||||||
|
+ || (level == 1 && type == inst
|
||||||
|
+ && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE))
|
||||||
|
+ || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE))
|
||||||
|
+ || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)))
|
||||||
|
+ {
|
||||||
|
+ unsigned int offset = M(name) - folded_rel_name;
|
||||||
|
+
|
||||||
|
+ if (offset == 0)
|
||||||
|
+ /* Cache size. */
|
||||||
|
+ return (((ebx >> 22) + 1)
|
||||||
|
+ * (((ebx >> 12) & 0x3ff) + 1)
|
||||||
|
+ * ((ebx & 0xfff) + 1)
|
||||||
|
+ * (ecx + 1));
|
||||||
|
+ if (offset == 1)
|
||||||
|
+ return (ebx >> 22) + 1;
|
||||||
|
+
|
||||||
|
+ assert (offset == 2);
|
||||||
|
+ return (ebx & 0xfff) + 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ++round;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Nothing found. */
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
/* Get the value of the system variable NAME. */
|
||||||
|
long int
|
||||||
|
attribute_hidden
|
||||||
|
@@ -449,6 +500,9 @@ __cache_sysconf (int name)
|
||||||
|
if (cpu_features->basic.kind == arch_kind_amd)
|
||||||
|
return handle_amd (name);
|
||||||
|
|
||||||
|
+ if (cpu_features->basic.kind == arch_kind_zhaoxin)
|
||||||
|
+ return handle_zhaoxin (name);
|
||||||
|
+
|
||||||
|
// XXX Fill in more vendors.
|
||||||
|
|
||||||
|
/* CPU not known, we have no information. */
|
||||||
|
@@ -482,6 +536,224 @@ int __x86_prefetchw attribute_hidden;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr,
|
||||||
|
+ long int core)
|
||||||
|
+{
|
||||||
|
+ unsigned int eax;
|
||||||
|
+ unsigned int ebx;
|
||||||
|
+ unsigned int ecx;
|
||||||
|
+ unsigned int edx;
|
||||||
|
+
|
||||||
|
+ /* Number of logical processors sharing L2 cache. */
|
||||||
|
+ int threads_l2;
|
||||||
|
+
|
||||||
|
+ /* Number of logical processors sharing L3 cache. */
|
||||||
|
+ int threads_l3;
|
||||||
|
+
|
||||||
|
+ const struct cpu_features *cpu_features = __get_cpu_features ();
|
||||||
|
+ int max_cpuid = cpu_features->basic.max_cpuid;
|
||||||
|
+ unsigned int family = cpu_features->basic.family;
|
||||||
|
+ unsigned int model = cpu_features->basic.model;
|
||||||
|
+ long int shared = *shared_ptr;
|
||||||
|
+ unsigned int threads = *threads_ptr;
|
||||||
|
+ bool inclusive_cache = true;
|
||||||
|
+ bool support_count_mask = true;
|
||||||
|
+
|
||||||
|
+ /* Try L3 first. */
|
||||||
|
+ unsigned int level = 3;
|
||||||
|
+
|
||||||
|
+ if (cpu_features->basic.kind == arch_kind_zhaoxin && family == 6)
|
||||||
|
+ support_count_mask = false;
|
||||||
|
+
|
||||||
|
+ if (shared <= 0)
|
||||||
|
+ {
|
||||||
|
+ /* Try L2 otherwise. */
|
||||||
|
+ level = 2;
|
||||||
|
+ shared = core;
|
||||||
|
+ threads_l2 = 0;
|
||||||
|
+ threads_l3 = -1;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ threads_l2 = 0;
|
||||||
|
+ threads_l3 = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* A value of 0 for the HTT bit indicates there is only a single
|
||||||
|
+ logical processor. */
|
||||||
|
+ if (HAS_CPU_FEATURE (HTT))
|
||||||
|
+ {
|
||||||
|
+ /* Figure out the number of logical threads that share the
|
||||||
|
+ highest cache level. */
|
||||||
|
+ if (max_cpuid >= 4)
|
||||||
|
+ {
|
||||||
|
+ int i = 0;
|
||||||
|
+
|
||||||
|
+ /* Query until cache level 2 and 3 are enumerated. */
|
||||||
|
+ int check = 0x1 | (threads_l3 == 0) << 1;
|
||||||
|
+ do
|
||||||
|
+ {
|
||||||
|
+ __cpuid_count (4, i++, eax, ebx, ecx, edx);
|
||||||
|
+
|
||||||
|
+ /* There seems to be a bug in at least some Pentium Ds
|
||||||
|
+ which sometimes fail to iterate all cache parameters.
|
||||||
|
+ Do not loop indefinitely here, stop in this case and
|
||||||
|
+ assume there is no such information. */
|
||||||
|
+ if (cpu_features->basic.kind == arch_kind_intel
|
||||||
|
+ && (eax & 0x1f) == 0 )
|
||||||
|
+ goto intel_bug_no_cache_info;
|
||||||
|
+
|
||||||
|
+ switch ((eax >> 5) & 0x7)
|
||||||
|
+ {
|
||||||
|
+ default:
|
||||||
|
+ break;
|
||||||
|
+ case 2:
|
||||||
|
+ if ((check & 0x1))
|
||||||
|
+ {
|
||||||
|
+ /* Get maximum number of logical processors
|
||||||
|
+ sharing L2 cache. */
|
||||||
|
+ threads_l2 = (eax >> 14) & 0x3ff;
|
||||||
|
+ check &= ~0x1;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ case 3:
|
||||||
|
+ if ((check & (0x1 << 1)))
|
||||||
|
+ {
|
||||||
|
+ /* Get maximum number of logical processors
|
||||||
|
+ sharing L3 cache. */
|
||||||
|
+ threads_l3 = (eax >> 14) & 0x3ff;
|
||||||
|
+
|
||||||
|
+ /* Check if L2 and L3 caches are inclusive. */
|
||||||
|
+ inclusive_cache = (edx & 0x2) != 0;
|
||||||
|
+ check &= ~(0x1 << 1);
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ while (check);
|
||||||
|
+
|
||||||
|
+ /* If max_cpuid >= 11, THREADS_L2/THREADS_L3 are the maximum
|
||||||
|
+ numbers of addressable IDs for logical processors sharing
|
||||||
|
+ the cache, instead of the maximum number of threads
|
||||||
|
+ sharing the cache. */
|
||||||
|
+ if (max_cpuid >= 11 && support_count_mask)
|
||||||
|
+ {
|
||||||
|
+ /* Find the number of logical processors shipped in
|
||||||
|
+ one core and apply count mask. */
|
||||||
|
+ i = 0;
|
||||||
|
+
|
||||||
|
+ /* Count SMT only if there is L3 cache. Always count
|
||||||
|
+ core if there is no L3 cache. */
|
||||||
|
+ int count = ((threads_l2 > 0 && level == 3)
|
||||||
|
+ | ((threads_l3 > 0
|
||||||
|
+ || (threads_l2 > 0 && level == 2)) << 1));
|
||||||
|
+
|
||||||
|
+ while (count)
|
||||||
|
+ {
|
||||||
|
+ __cpuid_count (11, i++, eax, ebx, ecx, edx);
|
||||||
|
+
|
||||||
|
+ int shipped = ebx & 0xff;
|
||||||
|
+ int type = ecx & 0xff00;
|
||||||
|
+ if (shipped == 0 || type == 0)
|
||||||
|
+ break;
|
||||||
|
+ else if (type == 0x100)
|
||||||
|
+ {
|
||||||
|
+ /* Count SMT. */
|
||||||
|
+ if ((count & 0x1))
|
||||||
|
+ {
|
||||||
|
+ int count_mask;
|
||||||
|
+
|
||||||
|
+ /* Compute count mask. */
|
||||||
|
+ asm ("bsr %1, %0"
|
||||||
|
+ : "=r" (count_mask) : "g" (threads_l2));
|
||||||
|
+ count_mask = ~(-1 << (count_mask + 1));
|
||||||
|
+ threads_l2 = (shipped - 1) & count_mask;
|
||||||
|
+ count &= ~0x1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (type == 0x200)
|
||||||
|
+ {
|
||||||
|
+ /* Count core. */
|
||||||
|
+ if ((count & (0x1 << 1)))
|
||||||
|
+ {
|
||||||
|
+ int count_mask;
|
||||||
|
+ int threads_core
|
||||||
|
+ = (level == 2 ? threads_l2 : threads_l3);
|
||||||
|
+
|
||||||
|
+ /* Compute count mask. */
|
||||||
|
+ asm ("bsr %1, %0"
|
||||||
|
+ : "=r" (count_mask) : "g" (threads_core));
|
||||||
|
+ count_mask = ~(-1 << (count_mask + 1));
|
||||||
|
+ threads_core = (shipped - 1) & count_mask;
|
||||||
|
+ if (level == 2)
|
||||||
|
+ threads_l2 = threads_core;
|
||||||
|
+ else
|
||||||
|
+ threads_l3 = threads_core;
|
||||||
|
+ count &= ~(0x1 << 1);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (threads_l2 > 0)
|
||||||
|
+ threads_l2 += 1;
|
||||||
|
+ if (threads_l3 > 0)
|
||||||
|
+ threads_l3 += 1;
|
||||||
|
+ if (level == 2)
|
||||||
|
+ {
|
||||||
|
+ if (threads_l2)
|
||||||
|
+ {
|
||||||
|
+ threads = threads_l2;
|
||||||
|
+ if (cpu_features->basic.kind == arch_kind_intel
|
||||||
|
+ && threads > 2
|
||||||
|
+ && family == 6)
|
||||||
|
+ switch (model)
|
||||||
|
+ {
|
||||||
|
+ case 0x37:
|
||||||
|
+ case 0x4a:
|
||||||
|
+ case 0x4d:
|
||||||
|
+ case 0x5a:
|
||||||
|
+ case 0x5d:
|
||||||
|
+ /* Silvermont has L2 cache shared by 2 cores. */
|
||||||
|
+ threads = 2;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (threads_l3)
|
||||||
|
+ threads = threads_l3;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+intel_bug_no_cache_info:
|
||||||
|
+ /* Assume that all logical threads share the highest cache
|
||||||
|
+ level. */
|
||||||
|
+ threads
|
||||||
|
+ = ((cpu_features->cpuid[COMMON_CPUID_INDEX_1].ebx
|
||||||
|
+ >> 16) & 0xff);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Cap usage of highest cache level to the number of supported
|
||||||
|
+ threads. */
|
||||||
|
+ if (shared > 0 && threads > 0)
|
||||||
|
+ shared /= threads;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Account for non-inclusive L2 and L3 caches. */
|
||||||
|
+ if (!inclusive_cache)
|
||||||
|
+ {
|
||||||
|
+ if (threads_l2 > 0)
|
||||||
|
+ core /= threads_l2;
|
||||||
|
+ shared += core;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *shared_ptr = shared;
|
||||||
|
+ *threads_ptr = threads;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
__attribute__((constructor))
|
||||||
|
init_cacheinfo (void)
|
||||||
|
@@ -494,211 +766,25 @@ init_cacheinfo (void)
|
||||||
|
int max_cpuid_ex;
|
||||||
|
long int data = -1;
|
||||||
|
long int shared = -1;
|
||||||
|
- unsigned int level;
|
||||||
|
+ long int core;
|
||||||
|
unsigned int threads = 0;
|
||||||
|
const struct cpu_features *cpu_features = __get_cpu_features ();
|
||||||
|
- int max_cpuid = cpu_features->basic.max_cpuid;
|
||||||
|
|
||||||
|
if (cpu_features->basic.kind == arch_kind_intel)
|
||||||
|
{
|
||||||
|
data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
|
||||||
|
-
|
||||||
|
- long int core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
|
||||||
|
- bool inclusive_cache = true;
|
||||||
|
-
|
||||||
|
- /* Try L3 first. */
|
||||||
|
- level = 3;
|
||||||
|
+ core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
|
||||||
|
shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features);
|
||||||
|
|
||||||
|
- /* Number of logical processors sharing L2 cache. */
|
||||||
|
- int threads_l2;
|
||||||
|
-
|
||||||
|
- /* Number of logical processors sharing L3 cache. */
|
||||||
|
- int threads_l3;
|
||||||
|
-
|
||||||
|
- if (shared <= 0)
|
||||||
|
- {
|
||||||
|
- /* Try L2 otherwise. */
|
||||||
|
- level = 2;
|
||||||
|
- shared = core;
|
||||||
|
- threads_l2 = 0;
|
||||||
|
- threads_l3 = -1;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- threads_l2 = 0;
|
||||||
|
- threads_l3 = 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* A value of 0 for the HTT bit indicates there is only a single
|
||||||
|
- logical processor. */
|
||||||
|
- if (HAS_CPU_FEATURE (HTT))
|
||||||
|
- {
|
||||||
|
- /* Figure out the number of logical threads that share the
|
||||||
|
- highest cache level. */
|
||||||
|
- if (max_cpuid >= 4)
|
||||||
|
- {
|
||||||
|
- unsigned int family = cpu_features->basic.family;
|
||||||
|
- unsigned int model = cpu_features->basic.model;
|
||||||
|
-
|
||||||
|
- int i = 0;
|
||||||
|
-
|
||||||
|
- /* Query until cache level 2 and 3 are enumerated. */
|
||||||
|
- int check = 0x1 | (threads_l3 == 0) << 1;
|
||||||
|
- do
|
||||||
|
- {
|
||||||
|
- __cpuid_count (4, i++, eax, ebx, ecx, edx);
|
||||||
|
-
|
||||||
|
- /* There seems to be a bug in at least some Pentium Ds
|
||||||
|
- which sometimes fail to iterate all cache parameters.
|
||||||
|
- Do not loop indefinitely here, stop in this case and
|
||||||
|
- assume there is no such information. */
|
||||||
|
- if ((eax & 0x1f) == 0)
|
||||||
|
- goto intel_bug_no_cache_info;
|
||||||
|
-
|
||||||
|
- switch ((eax >> 5) & 0x7)
|
||||||
|
- {
|
||||||
|
- default:
|
||||||
|
- break;
|
||||||
|
- case 2:
|
||||||
|
- if ((check & 0x1))
|
||||||
|
- {
|
||||||
|
- /* Get maximum number of logical processors
|
||||||
|
- sharing L2 cache. */
|
||||||
|
- threads_l2 = (eax >> 14) & 0x3ff;
|
||||||
|
- check &= ~0x1;
|
||||||
|
- }
|
||||||
|
- break;
|
||||||
|
- case 3:
|
||||||
|
- if ((check & (0x1 << 1)))
|
||||||
|
- {
|
||||||
|
- /* Get maximum number of logical processors
|
||||||
|
- sharing L3 cache. */
|
||||||
|
- threads_l3 = (eax >> 14) & 0x3ff;
|
||||||
|
-
|
||||||
|
- /* Check if L2 and L3 caches are inclusive. */
|
||||||
|
- inclusive_cache = (edx & 0x2) != 0;
|
||||||
|
- check &= ~(0x1 << 1);
|
||||||
|
- }
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- while (check);
|
||||||
|
-
|
||||||
|
- /* If max_cpuid >= 11, THREADS_L2/THREADS_L3 are the maximum
|
||||||
|
- numbers of addressable IDs for logical processors sharing
|
||||||
|
- the cache, instead of the maximum number of threads
|
||||||
|
- sharing the cache. */
|
||||||
|
- if (max_cpuid >= 11)
|
||||||
|
- {
|
||||||
|
- /* Find the number of logical processors shipped in
|
||||||
|
- one core and apply count mask. */
|
||||||
|
- i = 0;
|
||||||
|
-
|
||||||
|
- /* Count SMT only if there is L3 cache. Always count
|
||||||
|
- core if there is no L3 cache. */
|
||||||
|
- int count = ((threads_l2 > 0 && level == 3)
|
||||||
|
- | ((threads_l3 > 0
|
||||||
|
- || (threads_l2 > 0 && level == 2)) << 1));
|
||||||
|
-
|
||||||
|
- while (count)
|
||||||
|
- {
|
||||||
|
- __cpuid_count (11, i++, eax, ebx, ecx, edx);
|
||||||
|
-
|
||||||
|
- int shipped = ebx & 0xff;
|
||||||
|
- int type = ecx & 0xff00;
|
||||||
|
- if (shipped == 0 || type == 0)
|
||||||
|
- break;
|
||||||
|
- else if (type == 0x100)
|
||||||
|
- {
|
||||||
|
- /* Count SMT. */
|
||||||
|
- if ((count & 0x1))
|
||||||
|
- {
|
||||||
|
- int count_mask;
|
||||||
|
-
|
||||||
|
- /* Compute count mask. */
|
||||||
|
- asm ("bsr %1, %0"
|
||||||
|
- : "=r" (count_mask) : "g" (threads_l2));
|
||||||
|
- count_mask = ~(-1 << (count_mask + 1));
|
||||||
|
- threads_l2 = (shipped - 1) & count_mask;
|
||||||
|
- count &= ~0x1;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- else if (type == 0x200)
|
||||||
|
- {
|
||||||
|
- /* Count core. */
|
||||||
|
- if ((count & (0x1 << 1)))
|
||||||
|
- {
|
||||||
|
- int count_mask;
|
||||||
|
- int threads_core
|
||||||
|
- = (level == 2 ? threads_l2 : threads_l3);
|
||||||
|
-
|
||||||
|
- /* Compute count mask. */
|
||||||
|
- asm ("bsr %1, %0"
|
||||||
|
- : "=r" (count_mask) : "g" (threads_core));
|
||||||
|
- count_mask = ~(-1 << (count_mask + 1));
|
||||||
|
- threads_core = (shipped - 1) & count_mask;
|
||||||
|
- if (level == 2)
|
||||||
|
- threads_l2 = threads_core;
|
||||||
|
- else
|
||||||
|
- threads_l3 = threads_core;
|
||||||
|
- count &= ~(0x1 << 1);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- if (threads_l2 > 0)
|
||||||
|
- threads_l2 += 1;
|
||||||
|
- if (threads_l3 > 0)
|
||||||
|
- threads_l3 += 1;
|
||||||
|
- if (level == 2)
|
||||||
|
- {
|
||||||
|
- if (threads_l2)
|
||||||
|
- {
|
||||||
|
- threads = threads_l2;
|
||||||
|
- if (threads > 2 && family == 6)
|
||||||
|
- switch (model)
|
||||||
|
- {
|
||||||
|
- case 0x37:
|
||||||
|
- case 0x4a:
|
||||||
|
- case 0x4d:
|
||||||
|
- case 0x5a:
|
||||||
|
- case 0x5d:
|
||||||
|
- /* Silvermont has L2 cache shared by 2 cores. */
|
||||||
|
- threads = 2;
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- else if (threads_l3)
|
||||||
|
- threads = threads_l3;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
-intel_bug_no_cache_info:
|
||||||
|
- /* Assume that all logical threads share the highest cache
|
||||||
|
- level. */
|
||||||
|
-
|
||||||
|
- threads
|
||||||
|
- = ((cpu_features->cpuid[COMMON_CPUID_INDEX_1].ebx
|
||||||
|
- >> 16) & 0xff);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* Cap usage of highest cache level to the number of supported
|
||||||
|
- threads. */
|
||||||
|
- if (shared > 0 && threads > 0)
|
||||||
|
- shared /= threads;
|
||||||
|
- }
|
||||||
|
+ get_common_cache_info (&shared, &threads, core);
|
||||||
|
+ }
|
||||||
|
+ else if (cpu_features->basic.kind == arch_kind_zhaoxin)
|
||||||
|
+ {
|
||||||
|
+ data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE);
|
||||||
|
+ core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
|
||||||
|
+ shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
|
||||||
|
|
||||||
|
- /* Account for non-inclusive L2 and L3 caches. */
|
||||||
|
- if (!inclusive_cache)
|
||||||
|
- {
|
||||||
|
- if (threads_l2 > 0)
|
||||||
|
- core /= threads_l2;
|
||||||
|
- shared += core;
|
||||||
|
- }
|
||||||
|
+ get_common_cache_info (&shared, &threads, core);
|
||||||
|
}
|
||||||
|
else if (cpu_features->basic.kind == arch_kind_amd)
|
||||||
|
{
|
136
SOURCES/glibc-rh1817513-55.patch
Normal file
136
SOURCES/glibc-rh1817513-55.patch
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
commit 033362cfd7e0e1dccd6c9a2642710d6e3a7e7007
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Thu Jan 23 09:45:00 2020 -0500
|
||||||
|
|
||||||
|
test-container: Support $(complocaledir) and mkdirp.
|
||||||
|
|
||||||
|
Expand the support infrastructure:
|
||||||
|
- Create $(complocaledir) in the testroot.pristine to support localedef.
|
||||||
|
- Add the variable $complocaledir to script support.
|
||||||
|
- Add the script command 'mkdirp'.
|
||||||
|
|
||||||
|
All localedef tests which run with default paths need to have the
|
||||||
|
$(complocaledir) created in testroot.pristine. The localedef binary
|
||||||
|
will not by itself create the default path, but it will write into
|
||||||
|
the path. By adding this we can simplify the localedef tests.
|
||||||
|
|
||||||
|
The variable $complocaledir is the value of the configured
|
||||||
|
$(complocaledir) which is the location of the compiled locales that
|
||||||
|
will be searched by the runtime by default.
|
||||||
|
|
||||||
|
The command mkdirp will be available in script setup and will
|
||||||
|
be equivalent to running `mkdir -p`.
|
||||||
|
|
||||||
|
The variable and command can be used to write more complex tests.
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index ae44b9cdd29fb0e3..3748d6f7cfb6223b 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -371,6 +371,9 @@ $(objpfx)testroot.pristine/install.stamp :
|
||||||
|
# We need a working /bin/sh for some of the tests.
|
||||||
|
test -d $(objpfx)testroot.pristine/bin || \
|
||||||
|
mkdir $(objpfx)testroot.pristine/bin
|
||||||
|
+ # We need the compiled locale dir for localedef tests.
|
||||||
|
+ test -d $(objpfx)testroot.pristine/$(complocaledir) || \
|
||||||
|
+ mkdir -p $(objpfx)testroot.pristine/$(complocaledir)
|
||||||
|
cp $(objpfx)support/shell-container $(objpfx)testroot.pristine/bin/sh
|
||||||
|
cp $(objpfx)support/echo-container $(objpfx)testroot.pristine/bin/echo
|
||||||
|
cp $(objpfx)support/true-container $(objpfx)testroot.pristine/bin/true
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index 9eff8baeef0e9d8a..9fcc91e478038232 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -72,6 +72,10 @@ int verbose = 0;
|
||||||
|
|
||||||
|
* mkdir $buildroot/testroot.pristine/
|
||||||
|
* install into it
|
||||||
|
+ * default glibc install
|
||||||
|
+ * create /bin for /bin/sh
|
||||||
|
+ * create $(complocaledir) so localedef tests work with default paths.
|
||||||
|
+ * install /bin/sh, /bin/echo, and /bin/true.
|
||||||
|
* rsync to $buildroot/testroot.root/
|
||||||
|
|
||||||
|
"Per-test" actions:
|
||||||
|
@@ -97,9 +101,23 @@ int verbose = 0;
|
||||||
|
rm FILE
|
||||||
|
cwd PATH
|
||||||
|
exec FILE
|
||||||
|
- FILE must start with $B/, $S/, $I/, $L/, or /
|
||||||
|
- (expands to build dir, source dir, install dir, library dir
|
||||||
|
- (in container), or container's root)
|
||||||
|
+ mkdirp MODE DIR
|
||||||
|
+
|
||||||
|
+ variables:
|
||||||
|
+ $B/ build dir, equivalent to $(common-objpfx)
|
||||||
|
+ $S/ source dir, equivalent to $(srcdir)
|
||||||
|
+ $I/ install dir, equivalent to $(prefix)
|
||||||
|
+ $L/ library dir (in container), equivalent to $(libdir)
|
||||||
|
+ $complocaledir/ compiled locale dir, equivalent to $(complocaledir)
|
||||||
|
+ / container's root
|
||||||
|
+
|
||||||
|
+ If FILE begins with any of these variables then they will be
|
||||||
|
+ substituted for the described value.
|
||||||
|
+
|
||||||
|
+ The goal is to expose as many of the runtime's configured paths
|
||||||
|
+ via variables so they can be used to setup the container environment
|
||||||
|
+ before execution reaches the test.
|
||||||
|
+
|
||||||
|
details:
|
||||||
|
- '#': A comment.
|
||||||
|
- 'su': Enables running test as root in the container.
|
||||||
|
@@ -108,6 +126,8 @@ int verbose = 0;
|
||||||
|
- 'rm': A minimal remove files command.
|
||||||
|
- 'cwd': set test working directory
|
||||||
|
- 'exec': change test binary location (may end in /)
|
||||||
|
+ - 'mkdirp': A minimal "mkdir -p FILE" command.
|
||||||
|
+
|
||||||
|
* mytest.root/postclean.req causes fresh rsync (with delete) after
|
||||||
|
test if present
|
||||||
|
|
||||||
|
@@ -859,6 +879,7 @@ main (int argc, char **argv)
|
||||||
|
int nt = tokenize (the_line, the_words, 3);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
+ /* Expand variables. */
|
||||||
|
for (i = 1; i < nt; ++i)
|
||||||
|
{
|
||||||
|
if (memcmp (the_words[i], "$B/", 3) == 0)
|
||||||
|
@@ -875,6 +896,10 @@ main (int argc, char **argv)
|
||||||
|
the_words[i] = concat (new_root_path,
|
||||||
|
support_libdir_prefix,
|
||||||
|
the_words[i] + 2, NULL);
|
||||||
|
+ else if (memcmp (the_words[i], "$complocaledir/", 15) == 0)
|
||||||
|
+ the_words[i] = concat (new_root_path,
|
||||||
|
+ support_complocaledir_prefix,
|
||||||
|
+ the_words[i] + 14, NULL);
|
||||||
|
/* "exec" and "cwd" use inside-root paths. */
|
||||||
|
else if (strcmp (the_words[0], "exec") != 0
|
||||||
|
&& strcmp (the_words[0], "cwd") != 0
|
||||||
|
@@ -892,6 +917,9 @@ main (int argc, char **argv)
|
||||||
|
the_words[2] = concat (the_words[2], the_words[1], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Run the following commands in the_words[0] with NT number of
|
||||||
|
+ arguments (including the command). */
|
||||||
|
+
|
||||||
|
if (nt == 2 && strcmp (the_words[0], "so") == 0)
|
||||||
|
{
|
||||||
|
the_words[2] = concat (new_root_path, support_libdir_prefix,
|
||||||
|
@@ -961,6 +989,14 @@ main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
be_su = 1;
|
||||||
|
}
|
||||||
|
+ else if (nt == 3 && strcmp (the_words[0], "mkdirp") == 0)
|
||||||
|
+ {
|
||||||
|
+ long int m;
|
||||||
|
+ errno = 0;
|
||||||
|
+ m = strtol (the_words[1], NULL, 0);
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
+ xmkdirp (the_words[2], m);
|
||||||
|
+ }
|
||||||
|
else if (nt > 0 && the_words[0][0] != '#')
|
||||||
|
{
|
||||||
|
fprintf (stderr, "\033[31minvalid [%s]\033[0m\n", the_words[0]);
|
45
SOURCES/glibc-rh1817513-56.patch
Normal file
45
SOURCES/glibc-rh1817513-56.patch
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
commit 183083c35972611e7786c7ee0c96d7da571631ed
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Wed Apr 29 16:31:29 2020 -0400
|
||||||
|
|
||||||
|
support: Set errno before testing it.
|
||||||
|
|
||||||
|
In test-conainer we should set errno to 0 before calling strtol,
|
||||||
|
and check after with TEST_COMPARE.
|
||||||
|
|
||||||
|
In tst-support_capture_subprocess we should set errno to 0 before
|
||||||
|
checking it after the call to strtol.
|
||||||
|
|
||||||
|
Tested on x86_64.
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index 9fcc91e478038232..d7ed073812305f71 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -940,7 +940,9 @@ main (int argc, char **argv)
|
||||||
|
else if (nt == 3 && strcmp (the_words[0], "chmod") == 0)
|
||||||
|
{
|
||||||
|
long int m;
|
||||||
|
+ errno = 0;
|
||||||
|
m = strtol (the_words[1], NULL, 0);
|
||||||
|
+ TEST_COMPARE (errno, 0);
|
||||||
|
if (chmod (the_words[2], m) < 0)
|
||||||
|
FAIL_EXIT1 ("chmod %s: %s\n",
|
||||||
|
the_words[2], strerror (errno));
|
||||||
|
diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
|
||||||
|
index 99570879eedd65b1..fe6649dda6032de2 100644
|
||||||
|
--- a/support/tst-support_capture_subprocess.c
|
||||||
|
+++ b/support/tst-support_capture_subprocess.c
|
||||||
|
@@ -133,7 +133,9 @@ static int
|
||||||
|
parse_int (const char *str)
|
||||||
|
{
|
||||||
|
char *endptr;
|
||||||
|
- long int ret = strtol (str, &endptr, 10);
|
||||||
|
+ long int ret;
|
||||||
|
+ errno = 0;
|
||||||
|
+ ret = strtol (str, &endptr, 10);
|
||||||
|
TEST_COMPARE (errno, 0);
|
||||||
|
TEST_VERIFY (ret >= 0 && ret <= INT_MAX);
|
||||||
|
return ret;
|
30
SOURCES/glibc-rh1817513-57.patch
Normal file
30
SOURCES/glibc-rh1817513-57.patch
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
commit cad64f778aced84efdaa04ae64f8737b86f063ab
|
||||||
|
Author: Josh Triplett <josh@joshtriplett.org>
|
||||||
|
Date: Tue May 19 14:41:48 2020 +0200
|
||||||
|
|
||||||
|
ldconfig: Default to the new format for ld.so.cache
|
||||||
|
|
||||||
|
glibc has supported this format for close to 20 years.
|
||||||
|
|
||||||
|
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||||
|
index 5e6516688a1c192a..f31e10817dd5d665 100644
|
||||||
|
--- a/elf/ldconfig.c
|
||||||
|
+++ b/elf/ldconfig.c
|
||||||
|
@@ -97,7 +97,7 @@ int opt_verbose;
|
||||||
|
|
||||||
|
/* Format to support. */
|
||||||
|
/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */
|
||||||
|
-int opt_format = 1;
|
||||||
|
+int opt_format = 2;
|
||||||
|
|
||||||
|
/* Build cache. */
|
||||||
|
static int opt_build_cache = 1;
|
||||||
|
@@ -150,7 +150,7 @@ static const struct argp_option options[] =
|
||||||
|
{ NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
|
||||||
|
{ NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0},
|
||||||
|
{ NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
|
||||||
|
- { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new, old or compat (default)"), 0},
|
||||||
|
+ { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new (default), old, or compat"), 0},
|
||||||
|
{ "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0},
|
||||||
|
{ NULL, 0, NULL, 0, NULL, 0 }
|
||||||
|
};
|
59
SOURCES/glibc-rh1817513-58.patch
Normal file
59
SOURCES/glibc-rh1817513-58.patch
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
commit 76d5b2f002a1243ddba06bd646249553353f4322
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Thu May 21 13:36:54 2020 -0700
|
||||||
|
|
||||||
|
x86: Update Intel Atom processor family optimization
|
||||||
|
|
||||||
|
Enable Intel Silvermont optimization for Intel Goldmont Plus. Detect more
|
||||||
|
Intel Airmont processors. Optimize Intel Tremont like Intel Silvermont
|
||||||
|
with rep string instructions.
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||||
|
index c432d646ce6806a6..2a801e1856cfe1b3 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.c
|
||||||
|
+++ b/sysdeps/x86/cpu-features.c
|
||||||
|
@@ -347,18 +347,23 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
case 0x57:
|
||||||
|
/* Knights Landing. Enable Silvermont optimizations. */
|
||||||
|
|
||||||
|
+ case 0x7a:
|
||||||
|
+ /* Unaligned load versions are faster than SSSE3
|
||||||
|
+ on Goldmont Plus. */
|
||||||
|
+
|
||||||
|
case 0x5c:
|
||||||
|
case 0x5f:
|
||||||
|
/* Unaligned load versions are faster than SSSE3
|
||||||
|
on Goldmont. */
|
||||||
|
|
||||||
|
case 0x4c:
|
||||||
|
+ case 0x5a:
|
||||||
|
+ case 0x75:
|
||||||
|
/* Airmont is a die shrink of Silvermont. */
|
||||||
|
|
||||||
|
case 0x37:
|
||||||
|
case 0x4a:
|
||||||
|
case 0x4d:
|
||||||
|
- case 0x5a:
|
||||||
|
case 0x5d:
|
||||||
|
/* Unaligned load versions are faster than SSSE3
|
||||||
|
on Silvermont. */
|
||||||
|
@@ -369,6 +374,19 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||||
|
| bit_arch_Slow_SSE4_2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case 0x86:
|
||||||
|
+ case 0x96:
|
||||||
|
+ case 0x9c:
|
||||||
|
+ /* Enable rep string instructions, unaligned load, unaligned
|
||||||
|
+ copy, pminub and avoid SSE 4.2 on Tremont. */
|
||||||
|
+ cpu_features->feature[index_arch_Fast_Rep_String]
|
||||||
|
+ |= (bit_arch_Fast_Rep_String
|
||||||
|
+ | bit_arch_Fast_Unaligned_Load
|
||||||
|
+ | bit_arch_Fast_Unaligned_Copy
|
||||||
|
+ | bit_arch_Prefer_PMINUB_for_stringop
|
||||||
|
+ | bit_arch_Slow_SSE4_2);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
default:
|
||||||
|
/* Unknown family 0x06 processors. Assuming this is one
|
||||||
|
of Core i3/i5/i7 processors if AVX is available. */
|
148
SOURCES/glibc-rh1817513-59.patch
Normal file
148
SOURCES/glibc-rh1817513-59.patch
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
commit dcbc6b83eff5b9238170bdfed834ba934150895f
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu May 28 10:20:56 2020 +0200
|
||||||
|
|
||||||
|
elf: Do not read hwcaps from the vDSO in ld.so
|
||||||
|
|
||||||
|
This was only ever used for the "nosegneg" flag. This approach for
|
||||||
|
passing hardware capability information creates a subtle dependency
|
||||||
|
between the kernel and userspace, and ld.so.cache contents. It seems
|
||||||
|
inappropriate for toady, where people expect to be able to run
|
||||||
|
system images which very different kernel versions.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
||||||
|
index ecf00b457760e517..ae2e4ca7fe91d407 100644
|
||||||
|
--- a/elf/dl-hwcaps.c
|
||||||
|
+++ b/elf/dl-hwcaps.c
|
||||||
|
@@ -26,12 +26,6 @@
|
||||||
|
#include <dl-procinfo.h>
|
||||||
|
#include <dl-hwcaps.h>
|
||||||
|
|
||||||
|
-#ifdef _DL_FIRST_PLATFORM
|
||||||
|
-# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
|
||||||
|
-#else
|
||||||
|
-# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
/* Return an array of useful/necessary hardware capability names. */
|
||||||
|
const struct r_strlenpair *
|
||||||
|
_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||||
|
@@ -52,116 +46,12 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
|
||||||
|
if ((masked & (1ULL << n)) != 0)
|
||||||
|
++cnt;
|
||||||
|
|
||||||
|
-#ifdef NEED_DL_SYSINFO_DSO
|
||||||
|
- /* The system-supplied DSO can contain a note of type 2, vendor "GNU".
|
||||||
|
- This gives us a list of names to treat as fake hwcap bits. */
|
||||||
|
-
|
||||||
|
- const char *dsocaps = NULL;
|
||||||
|
- size_t dsocapslen = 0;
|
||||||
|
- if (GLRO(dl_sysinfo_map) != NULL)
|
||||||
|
- {
|
||||||
|
- const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr;
|
||||||
|
- const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum;
|
||||||
|
- for (uint_fast16_t i = 0; i < phnum; ++i)
|
||||||
|
- if (phdr[i].p_type == PT_NOTE)
|
||||||
|
- {
|
||||||
|
- const ElfW(Addr) start = (phdr[i].p_vaddr
|
||||||
|
- + GLRO(dl_sysinfo_map)->l_addr);
|
||||||
|
- /* NB: Some PT_NOTE segment may have alignment value of 0
|
||||||
|
- or 1. gABI specifies that PT_NOTE segments should be
|
||||||
|
- aligned to 4 bytes in 32-bit objects and to 8 bytes in
|
||||||
|
- 64-bit objects. As a Linux extension, we also support
|
||||||
|
- 4 byte alignment in 64-bit objects. If p_align is less
|
||||||
|
- than 4, we treate alignment as 4 bytes since some note
|
||||||
|
- segments have 0 or 1 byte alignment. */
|
||||||
|
- ElfW(Addr) align = phdr[i].p_align;
|
||||||
|
- if (align < 4)
|
||||||
|
- align = 4;
|
||||||
|
- else if (align != 4 && align != 8)
|
||||||
|
- continue;
|
||||||
|
- /* The standard ELF note layout is exactly as the anonymous struct.
|
||||||
|
- The next element is a variable length vendor name of length
|
||||||
|
- VENDORLEN (with a real length rounded to ElfW(Word)), followed
|
||||||
|
- by the data of length DATALEN (with a real length rounded to
|
||||||
|
- ElfW(Word)). */
|
||||||
|
- const struct
|
||||||
|
- {
|
||||||
|
- ElfW(Word) vendorlen;
|
||||||
|
- ElfW(Word) datalen;
|
||||||
|
- ElfW(Word) type;
|
||||||
|
- } *note = (const void *) start;
|
||||||
|
- while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
|
||||||
|
- {
|
||||||
|
- /* The layout of the type 2, vendor "GNU" note is as follows:
|
||||||
|
- .long <Number of capabilities enabled by this note>
|
||||||
|
- .long <Capabilities mask> (as mask >> _DL_FIRST_EXTRA).
|
||||||
|
- .byte <The bit number for the next capability>
|
||||||
|
- .asciz <The name of the capability>. */
|
||||||
|
- if (note->type == NT_GNU_HWCAP
|
||||||
|
- && note->vendorlen == sizeof "GNU"
|
||||||
|
- && !memcmp ((note + 1), "GNU", sizeof "GNU")
|
||||||
|
- && note->datalen > 2 * sizeof (ElfW(Word)) + 2)
|
||||||
|
- {
|
||||||
|
- const ElfW(Word) *p
|
||||||
|
- = ((const void *) note
|
||||||
|
- + ELF_NOTE_DESC_OFFSET (sizeof "GNU", align));
|
||||||
|
- cnt += *p++;
|
||||||
|
- ++p; /* Skip mask word. */
|
||||||
|
- dsocaps = (const char *) p; /* Pseudo-string "<b>name" */
|
||||||
|
- dsocapslen = note->datalen - sizeof *p * 2;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- note = ((const void *) note
|
||||||
|
- + ELF_NOTE_NEXT_OFFSET (note->vendorlen,
|
||||||
|
- note->datalen, align));
|
||||||
|
- }
|
||||||
|
- if (dsocaps != NULL)
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
/* For TLS enabled builds always add 'tls'. */
|
||||||
|
++cnt;
|
||||||
|
|
||||||
|
/* Create temporary data structure to generate result table. */
|
||||||
|
struct r_strlenpair temp[cnt];
|
||||||
|
m = 0;
|
||||||
|
-#ifdef NEED_DL_SYSINFO_DSO
|
||||||
|
- if (dsocaps != NULL)
|
||||||
|
- {
|
||||||
|
- /* dsocaps points to the .asciz string, and -1 points to the mask
|
||||||
|
- .long just before the string. */
|
||||||
|
- const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1];
|
||||||
|
- GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA;
|
||||||
|
- /* Note that we add the dsocaps to the set already chosen by the
|
||||||
|
- 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. */
|
||||||
|
- hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA;
|
||||||
|
-#if HAVE_TUNABLES
|
||||||
|
- TUNABLE_SET (glibc, cpu, 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)
|
||||||
|
- {
|
||||||
|
- uint_fast8_t bit = *p++;
|
||||||
|
- len = strlen (p);
|
||||||
|
-
|
||||||
|
- /* Skip entries that are not enabled in the mask word. */
|
||||||
|
- if (__glibc_likely (mask & ((ElfW(Word)) 1 << bit)))
|
||||||
|
- {
|
||||||
|
- temp[m].str = p;
|
||||||
|
- temp[m].len = len;
|
||||||
|
- ++m;
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- --cnt;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
for (n = 0; masked != 0; ++n)
|
||||||
|
if ((masked & (1ULL << n)) != 0)
|
||||||
|
{
|
53
SOURCES/glibc-rh1817513-6.patch
Normal file
53
SOURCES/glibc-rh1817513-6.patch
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
commit d330f31af68f96dde82840d1e9343b479a8c179e
|
||||||
|
Author: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
Date: Thu Aug 30 11:01:33 2018 -0400
|
||||||
|
|
||||||
|
Fix test failure with -DNDEBUG.
|
||||||
|
|
||||||
|
The elf/tst-dlopen-aout.c test uses asserts to verify properties of the
|
||||||
|
test execution. Instead of using assert it should use xpthread_create
|
||||||
|
and xpthread_join to catch errors starting the threads and fail the
|
||||||
|
test. This shows up in Fedora 28 when building for i686-pc-linux-gnu
|
||||||
|
and using gcc 8.1.1.
|
||||||
|
|
||||||
|
Tested on i686, and fixes a check failure with -DNDEBUG.
|
||||||
|
|
||||||
|
Signed-off-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/elf/tst-dlopen-aout.c b/elf/tst-dlopen-aout.c
|
||||||
|
index 9038e2096add8798..b0264515cfe62276 100644
|
||||||
|
--- a/elf/tst-dlopen-aout.c
|
||||||
|
+++ b/elf/tst-dlopen-aout.c
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
+#include <support/xthread.h>
|
||||||
|
|
||||||
|
__thread int x;
|
||||||
|
|
||||||
|
@@ -45,7 +46,6 @@ do_test (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
pthread_t thr;
|
||||||
|
void *p;
|
||||||
|
- int rc;
|
||||||
|
|
||||||
|
p = dlopen (argv[0], RTLD_LAZY);
|
||||||
|
if (p != NULL)
|
||||||
|
@@ -53,11 +53,11 @@ do_test (int argc, char *argv[])
|
||||||
|
fprintf (stderr, "dlopen unexpectedly succeeded\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
- rc = pthread_create (&thr, NULL, fn, NULL);
|
||||||
|
- assert (rc == 0);
|
||||||
|
-
|
||||||
|
- rc = pthread_join (thr, NULL);
|
||||||
|
- assert (rc == 0);
|
||||||
|
+ /* We create threads to force TLS allocation, which triggers
|
||||||
|
+ the original bug i.e. running out of surplus slotinfo entries
|
||||||
|
+ for TLS. */
|
||||||
|
+ thr = xpthread_create (NULL, fn, NULL);
|
||||||
|
+ xpthread_join (thr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
151
SOURCES/glibc-rh1817513-60.patch
Normal file
151
SOURCES/glibc-rh1817513-60.patch
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
commit 31563b68410ff8e9490c5aafca31ec71b38f87a5
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu May 28 10:21:17 2020 +0200
|
||||||
|
|
||||||
|
elf: Remove extra hwcap mechanism from ldconfig
|
||||||
|
|
||||||
|
Historically, this mechanism was used to process "nosegneg"
|
||||||
|
subdirectories, and it is still used to include the "tls"
|
||||||
|
subdirectories. With nosegneg support gone from ld.so, this is part
|
||||||
|
no longer useful.
|
||||||
|
|
||||||
|
The entire mechanism is not well-designed because it causes the
|
||||||
|
meaning of hwcap bits in ld.so.cache to depend on the kernel version
|
||||||
|
that was used to generate the cache, which makes it difficult to use
|
||||||
|
this mechanism for anything else in the future.
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||||
|
index f31e10817dd5d665..7c8fd29387463a8a 100644
|
||||||
|
--- a/elf/ldconfig.c
|
||||||
|
+++ b/elf/ldconfig.c
|
||||||
|
@@ -44,11 +44,15 @@
|
||||||
|
|
||||||
|
#include <dl-procinfo.h>
|
||||||
|
|
||||||
|
-#ifdef _DL_FIRST_PLATFORM
|
||||||
|
-# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
|
||||||
|
-#else
|
||||||
|
-# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
|
||||||
|
-#endif
|
||||||
|
+/* This subpath in search path entries is always supported and
|
||||||
|
+ included in the cache for backwards compatibility. */
|
||||||
|
+#define TLS_SUBPATH "tls"
|
||||||
|
+
|
||||||
|
+/* The MSB of the hwcap field is set for objects in TLS_SUBPATH
|
||||||
|
+ directories. There is always TLS support in glibc, so the dynamic
|
||||||
|
+ loader does not check the bit directly. But more hwcap bits make a
|
||||||
|
+ an object more preferred, so the bit still has meaning. */
|
||||||
|
+#define TLS_HWCAP_BIT 63
|
||||||
|
|
||||||
|
#ifndef LD_SO_CONF
|
||||||
|
# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
|
||||||
|
@@ -127,9 +131,6 @@ static const char *config_file;
|
||||||
|
/* Mask to use for important hardware capabilities. */
|
||||||
|
static unsigned long int hwcap_mask = HWCAP_IMPORTANT;
|
||||||
|
|
||||||
|
-/* Configuration-defined capabilities defined in kernel vDSOs. */
|
||||||
|
-static const char *hwcap_extra[64 - _DL_FIRST_EXTRA];
|
||||||
|
-
|
||||||
|
/* Name and version of program. */
|
||||||
|
static void print_version (FILE *stream, struct argp_state *state);
|
||||||
|
void (*argp_program_version_hook) (FILE *, struct argp_state *)
|
||||||
|
@@ -186,12 +187,9 @@ is_hwcap_platform (const char *name)
|
||||||
|
if (hwcap_idx != -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- /* Is this one of the extra pseudo-hwcaps that we map beyond
|
||||||
|
- _DL_FIRST_EXTRA like "tls", or "nosegneg?" */
|
||||||
|
- for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx)
|
||||||
|
- if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL
|
||||||
|
- && !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA]))
|
||||||
|
- return 1;
|
||||||
|
+ /* Backwards-compatibility for the "tls" subdirectory. */
|
||||||
|
+ if (strcmp (name, TLS_SUBPATH) == 0)
|
||||||
|
+ return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -226,11 +224,9 @@ path_hwcap (const char *path)
|
||||||
|
h = _dl_string_platform (ptr + 1);
|
||||||
|
if (h == (uint64_t) -1)
|
||||||
|
{
|
||||||
|
- for (h = _DL_FIRST_EXTRA; h < 64; ++h)
|
||||||
|
- if (hwcap_extra[h - _DL_FIRST_EXTRA] != NULL
|
||||||
|
- && !strcmp (ptr + 1, hwcap_extra[h - _DL_FIRST_EXTRA]))
|
||||||
|
- break;
|
||||||
|
- if (h == 64)
|
||||||
|
+ if (strcmp (ptr + 1, TLS_SUBPATH) == 0)
|
||||||
|
+ h = TLS_HWCAP_BIT;
|
||||||
|
+ else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1145,52 +1141,7 @@ Warning: ignoring configuration file that cannot be opened: %s"),
|
||||||
|
parse_conf_include (filename, lineno, do_chroot, dir);
|
||||||
|
}
|
||||||
|
else if (!strncasecmp (cp, "hwcap", 5) && isblank (cp[5]))
|
||||||
|
- {
|
||||||
|
- cp += 6;
|
||||||
|
- char *p, *name = NULL;
|
||||||
|
- unsigned long int n = strtoul (cp, &cp, 0);
|
||||||
|
- if (cp != NULL && isblank (*cp))
|
||||||
|
- while ((p = strsep (&cp, " \t")) != NULL)
|
||||||
|
- if (p[0] != '\0')
|
||||||
|
- {
|
||||||
|
- if (name == NULL)
|
||||||
|
- name = p;
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- name = NULL;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- if (name == NULL)
|
||||||
|
- {
|
||||||
|
- error (EXIT_FAILURE, 0, _("%s:%u: bad syntax in hwcap line"),
|
||||||
|
- filename, lineno);
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- if (n >= (64 - _DL_FIRST_EXTRA))
|
||||||
|
- error (EXIT_FAILURE, 0,
|
||||||
|
- _("%s:%u: hwcap index %lu above maximum %u"),
|
||||||
|
- filename, lineno, n, 64 - _DL_FIRST_EXTRA - 1);
|
||||||
|
- if (hwcap_extra[n] == NULL)
|
||||||
|
- {
|
||||||
|
- for (unsigned long int h = 0; h < (64 - _DL_FIRST_EXTRA); ++h)
|
||||||
|
- if (hwcap_extra[h] != NULL && !strcmp (name, hwcap_extra[h]))
|
||||||
|
- error (EXIT_FAILURE, 0,
|
||||||
|
- _("%s:%u: hwcap index %lu already defined as %s"),
|
||||||
|
- filename, lineno, h, name);
|
||||||
|
- hwcap_extra[n] = xstrdup (name);
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- if (strcmp (name, hwcap_extra[n]))
|
||||||
|
- error (EXIT_FAILURE, 0,
|
||||||
|
- _("%s:%u: hwcap index %lu already defined as %s"),
|
||||||
|
- filename, lineno, n, hwcap_extra[n]);
|
||||||
|
- if (opt_verbose)
|
||||||
|
- error (0, 0, _("%s:%u: duplicate hwcap %lu %s"),
|
||||||
|
- filename, lineno, n, name);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ error (0, 0, _("%s:%u: hwcap directive ignored"), filename, lineno);
|
||||||
|
else
|
||||||
|
add_dir_1 (cp, filename, lineno);
|
||||||
|
}
|
||||||
|
@@ -1303,12 +1254,6 @@ main (int argc, char **argv)
|
||||||
|
add_dir_1 (argv[i], "<cmdline>", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* The last entry in hwcap_extra is reserved for the "tls" pseudo-hwcap which
|
||||||
|
- indicates support for TLS. This pseudo-hwcap is only used by old versions
|
||||||
|
- under which TLS support was optional. The entry is no longer needed, but
|
||||||
|
- must remain for compatibility. */
|
||||||
|
- hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls";
|
||||||
|
-
|
||||||
|
set_hwcap ();
|
||||||
|
|
||||||
|
if (opt_chroot)
|
21
SOURCES/glibc-rh1817513-61.patch
Normal file
21
SOURCES/glibc-rh1817513-61.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
commit 9e2dc874e62b0950891b319c000b009ea12ac8c2
|
||||||
|
Author: Girish Joshi <girish946@gmail.com>
|
||||||
|
Date: Fri May 29 10:11:24 2020 -0300
|
||||||
|
|
||||||
|
build: Use FAIL_EXIT1 () on failure to exec child [BZ #23990]
|
||||||
|
|
||||||
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
|
diff --git a/support/test-container.c b/support/test-container.c
|
||||||
|
index d7ed073812305f71..9975c8cb7bc9a955 100644
|
||||||
|
--- a/support/test-container.c
|
||||||
|
+++ b/support/test-container.c
|
||||||
|
@@ -392,7 +392,7 @@ recursive_remove (char *path)
|
||||||
|
/* "rm" would have already printed a suitable error message. */
|
||||||
|
if (! WIFEXITED (status)
|
||||||
|
|| WEXITSTATUS (status) != 0)
|
||||||
|
- exit (1);
|
||||||
|
+ FAIL_EXIT1 ("exec child returned status: %d", status);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
67
SOURCES/glibc-rh1817513-62.patch
Normal file
67
SOURCES/glibc-rh1817513-62.patch
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
commit 533dd2acf7eefa969fb770fa782b20519bd4bc0f
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Tue Jun 9 12:15:01 2020 -0700
|
||||||
|
|
||||||
|
Add "%d" support to _dl_debug_vdprintf
|
||||||
|
|
||||||
|
"%d" will be used to print out signed value.
|
||||||
|
|
||||||
|
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
|
||||||
|
index 2eb81eeb0231368d..3f28de3ee9d68368 100644
|
||||||
|
--- a/elf/dl-misc.c
|
||||||
|
+++ b/elf/dl-misc.c
|
||||||
|
@@ -167,6 +167,7 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
|
||||||
|
switch (*fmt)
|
||||||
|
{
|
||||||
|
/* Integer formatting. */
|
||||||
|
+ case 'd':
|
||||||
|
case 'u':
|
||||||
|
case 'x':
|
||||||
|
{
|
||||||
|
@@ -179,11 +180,34 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
|
||||||
|
#else
|
||||||
|
unsigned long int num = va_arg (arg, unsigned int);
|
||||||
|
#endif
|
||||||
|
+ bool negative = false;
|
||||||
|
+ if (*fmt == 'd')
|
||||||
|
+ {
|
||||||
|
+#if LONG_MAX != INT_MAX
|
||||||
|
+ if (long_mod)
|
||||||
|
+ {
|
||||||
|
+ if ((long int) num < 0)
|
||||||
|
+ negative = true;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ if ((int) num < 0)
|
||||||
|
+ {
|
||||||
|
+ num = (unsigned int) num;
|
||||||
|
+ negative = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#else
|
||||||
|
+ if ((int) num < 0)
|
||||||
|
+ negative = true;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* We use alloca() to allocate the buffer with the most
|
||||||
|
pessimistic guess for the size. Using alloca() allows
|
||||||
|
having more than one integer formatting in a call. */
|
||||||
|
- char *buf = (char *) alloca (3 * sizeof (unsigned long int));
|
||||||
|
- char *endp = &buf[3 * sizeof (unsigned long int)];
|
||||||
|
+ char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int));
|
||||||
|
+ char *endp = &buf[1 + 3 * sizeof (unsigned long int)];
|
||||||
|
char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
|
||||||
|
|
||||||
|
/* Pad to the width the user specified. */
|
||||||
|
@@ -191,6 +215,9 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
|
||||||
|
while (endp - cp < width)
|
||||||
|
*--cp = fill;
|
||||||
|
|
||||||
|
+ if (negative)
|
||||||
|
+ *--cp = '-';
|
||||||
|
+
|
||||||
|
iov[niov].iov_base = cp;
|
||||||
|
iov[niov].iov_len = endp - cp;
|
||||||
|
++niov;
|
62
SOURCES/glibc-rh1817513-63.patch
Normal file
62
SOURCES/glibc-rh1817513-63.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
commit e221c512c74ec42fd47b71de2981a475b38110a4
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Mon Jun 15 09:50:14 2020 +0200
|
||||||
|
|
||||||
|
ld.so: Check for new cache format first and enhance corruption check
|
||||||
|
|
||||||
|
Now that ldconfig defaults to the new format (only), check for it
|
||||||
|
first. Also apply the corruption check added in commit 2954daf00bb4d
|
||||||
|
("Add more checks for valid ld.so.cache file (bug 18093)") to the
|
||||||
|
new-format-only case.
|
||||||
|
|
||||||
|
Suggested-by: Josh Triplett <josh@joshtriplett.org>
|
||||||
|
|
||||||
|
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
|
||||||
|
index 6dd99a35b9f97cfb..ef37ca18fa9fb6e0 100644
|
||||||
|
--- a/elf/dl-cache.c
|
||||||
|
+++ b/elf/dl-cache.c
|
||||||
|
@@ -199,15 +199,25 @@ _dl_load_cache_lookup (const char *name)
|
||||||
|
PROT_READ);
|
||||||
|
|
||||||
|
/* We can handle three different cache file formats here:
|
||||||
|
+ - only the new format
|
||||||
|
- the old libc5/glibc2.0/2.1 format
|
||||||
|
- the old format with the new format in it
|
||||||
|
- - only the new format
|
||||||
|
The following checks if the cache contains any of these formats. */
|
||||||
|
- if (file != MAP_FAILED && cachesize > sizeof *cache
|
||||||
|
- && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
|
||||||
|
+ if (file != MAP_FAILED && cachesize > sizeof *cache_new
|
||||||
|
+ && memcmp (file, CACHEMAGIC_VERSION_NEW,
|
||||||
|
+ sizeof CACHEMAGIC_VERSION_NEW - 1) == 0
|
||||||
|
/* Check for corruption, avoiding overflow. */
|
||||||
|
- && ((cachesize - sizeof *cache) / sizeof (struct file_entry)
|
||||||
|
- >= ((struct cache_file *) file)->nlibs))
|
||||||
|
+ && ((cachesize - sizeof *cache_new) / sizeof (struct file_entry_new)
|
||||||
|
+ >= ((struct cache_file_new *) file)->nlibs))
|
||||||
|
+ {
|
||||||
|
+ cache_new = file;
|
||||||
|
+ cache = file;
|
||||||
|
+ }
|
||||||
|
+ else if (file != MAP_FAILED && cachesize > sizeof *cache
|
||||||
|
+ && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
|
||||||
|
+ /* Check for corruption, avoiding overflow. */
|
||||||
|
+ && ((cachesize - sizeof *cache) / sizeof (struct file_entry)
|
||||||
|
+ >= ((struct cache_file *) file)->nlibs))
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
/* Looks ok. */
|
||||||
|
@@ -223,13 +233,6 @@ _dl_load_cache_lookup (const char *name)
|
||||||
|
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
|
||||||
|
cache_new = (void *) -1;
|
||||||
|
}
|
||||||
|
- else if (file != MAP_FAILED && cachesize > sizeof *cache_new
|
||||||
|
- && memcmp (file, CACHEMAGIC_VERSION_NEW,
|
||||||
|
- sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
|
||||||
|
- {
|
||||||
|
- cache_new = file;
|
||||||
|
- cache = file;
|
||||||
|
- }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (file != MAP_FAILED)
|
21
SOURCES/glibc-rh1817513-64.patch
Normal file
21
SOURCES/glibc-rh1817513-64.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
commit b7c9bb183b799b10c09ec32e98d1843546ea4324
|
||||||
|
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||||
|
Date: Wed Jun 17 05:32:37 2020 -0700
|
||||||
|
|
||||||
|
x86: Correct bit_cpu_CLFLUSHOPT [BZ #26128]
|
||||||
|
|
||||||
|
bit_cpu_CLFLUSHOPT should be (1u << 23), not (1u << 22).
|
||||||
|
|
||||||
|
diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h
|
||||||
|
index 388172a1c07bf979..7abfa046c4b8f6ac 100644
|
||||||
|
--- a/sysdeps/x86/cpu-features.h
|
||||||
|
+++ b/sysdeps/x86/cpu-features.h
|
||||||
|
@@ -465,7 +465,7 @@ extern const struct cpu_features *__get_cpu_features (void)
|
||||||
|
#define bit_cpu_ADX (1u << 19)
|
||||||
|
#define bit_cpu_SMAP (1u << 20)
|
||||||
|
#define bit_cpu_AVX512_IFMA (1u << 21)
|
||||||
|
-#define bit_cpu_CLFLUSHOPT (1u << 22)
|
||||||
|
+#define bit_cpu_CLFLUSHOPT (1u << 23)
|
||||||
|
#define bit_cpu_CLWB (1u << 24)
|
||||||
|
#define bit_cpu_TRACE (1u << 25)
|
||||||
|
#define bit_cpu_AVX512PF (1u << 26)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user