mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
Compare commits
144 commits
glibc-2.41
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
4e68a5ca5d | ||
|
81c4ec1ca8 | ||
|
7a185eb9e9 | ||
|
596130591a | ||
|
50351e0570 | ||
|
6cb703b81d | ||
|
1d60b9dfda | ||
|
2fd580ea46 | ||
|
a768993c10 | ||
|
8a995670a8 | ||
|
3a9fb97caf | ||
|
dac7ea4a6f | ||
|
226476e322 | ||
|
a2bd5008a9 | ||
|
4cf2d86936 | ||
|
8c6fee9f7f | ||
|
ccdb68e829 | ||
|
e5893e6349 | ||
|
c0f380c465 | ||
|
efd13567f7 | ||
|
ee4ee1cb02 | ||
|
0195552e15 | ||
|
0f044be1da | ||
|
9e51ae3cd0 | ||
|
2fe5e2af09 | ||
|
3fd2ff7685 | ||
|
935563754b | ||
|
4c11379106 | ||
|
0a021727bc | ||
|
eb7ac024d9 | ||
|
19860fd42e | ||
|
ce2f26a22e | ||
|
be0cfd848d | ||
|
4734d0f8ad | ||
|
8a46bf41e5 | ||
|
fa53723cdb | ||
|
29803ed3ce | ||
|
689a62a421 | ||
|
41f6684557 | ||
|
15afd01e80 | ||
|
57ee1deb1f | ||
|
82decb59bc | ||
|
c05086d904 | ||
|
6d24313e4a | ||
|
163b1bbb76 | ||
|
5a4573be6f | ||
|
ad9c4c5361 | ||
|
0242c9f9e6 | ||
|
1faccf388a | ||
|
246e52574d | ||
|
4afbc1aa2e | ||
|
6f6732c1c4 | ||
|
d3ef1b56aa | ||
|
25650ef6b9 | ||
|
119798a7b1 | ||
|
18accc19b9 | ||
|
4b25413df5 | ||
|
cd2d31ed58 | ||
|
e618b671cd | ||
|
8f842ce13e | ||
|
60f2d6be65 | ||
|
1b6f868625 | ||
|
aa3d7bd529 | ||
|
88f7ef881d | ||
|
d10176c0ff | ||
|
6a3cb6b1bd | ||
|
991febc2f4 | ||
|
a30374e4ce | ||
|
95e807209b | ||
|
0b195651db | ||
|
f5ff34cb3c | ||
|
c0ff447edf | ||
|
8f0e7fe61e | ||
|
5afaf99edb | ||
|
cdb9ba8419 | ||
|
b81252c4b9 | ||
|
994007ff29 | ||
|
8f170dc819 | ||
|
de2fca9fe2 | ||
|
be85208b9f | ||
|
95a01ea955 | ||
|
1cd9ccd8c0 | ||
|
ae679a0aca | ||
|
edb2a8f0ae | ||
|
57d1fc9971 | ||
|
10370a4d00 | ||
|
180e97bee6 | ||
|
1700d306d4 | ||
|
ec9d2f3066 | ||
|
082ffa4ddc | ||
|
3e0e782b29 | ||
|
392261a2b6 | ||
|
659fa18dde | ||
|
da49165ea6 | ||
|
6bcd7bf100 | ||
|
710bbc9659 | ||
|
2789003489 | ||
|
735c9b73d6 | ||
|
ccf19a68ab | ||
|
ca2a95ee67 | ||
|
40cbd3c361 | ||
|
7d799d85e8 | ||
|
bb6496b964 | ||
|
cdb0800022 | ||
|
3755ffb665 | ||
|
68c9ef4419 | ||
|
37a0933e1b | ||
|
09e7f4d594 | ||
|
fc058b46c7 | ||
|
b05e78d473 | ||
|
edc6842bbc | ||
|
d12cb8e452 | ||
|
749310c61b | ||
|
aa1bf89039 | ||
|
a7aad6e2b7 | ||
|
96429bcc91 | ||
|
cf51d18b9d | ||
|
04588633cf | ||
|
c79277a167 | ||
|
1b29cb7b78 | ||
|
22a11aa1c3 | ||
|
47c4f4045c | ||
|
a3a5634d9b | ||
|
4c43173eba | ||
|
a6fbe36b7f | ||
|
8e86549d14 | ||
|
32ac9f8049 | ||
|
9a31eb64db | ||
|
265c5991af | ||
|
8bfabe7a92 | ||
|
be9f0e7681 | ||
|
2ebc2d8e24 | ||
|
e892a93073 | ||
|
56b25bfd60 | ||
|
203452a460 | ||
|
3ff3b9997c | ||
|
0dcc0b2f63 | ||
|
94251ae99e | ||
|
be6818be31 | ||
|
377e9733b5 | ||
|
1515f74fd8 | ||
|
596a61cf6b | ||
|
45c42b65c2 | ||
|
42aba91895 |
407 changed files with 25076 additions and 4127 deletions
|
@ -633,7 +633,7 @@ link-libc-printers-tests = $(link-libc-rpath) \
|
|||
$(link-libc-tests-after-rpath-link)
|
||||
|
||||
# This is how to find at build-time things that will be installed there.
|
||||
rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support
|
||||
rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support misc
|
||||
rpath-link = \
|
||||
$(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
|
||||
else # build-static
|
||||
|
|
27
NEWS
27
NEWS
|
@ -5,6 +5,33 @@ See the end for copying conditions.
|
|||
Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
|
||||
using `glibc' in the "product" field.
|
||||
|
||||
Version 2.42
|
||||
|
||||
Major new features:
|
||||
|
||||
[Add new features here]
|
||||
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
|
||||
[Add deprecations, removals and changes affecting compatibility here]
|
||||
|
||||
Changes to build and runtime requirements:
|
||||
|
||||
[Add changes to build and runtime requirements here]
|
||||
|
||||
Security related changes:
|
||||
|
||||
The following CVEs were fixed in this release, details of which can be
|
||||
found in the advisories directory of the release tarball:
|
||||
|
||||
[The release manager will add the list generated by
|
||||
scripts/process-advisories.sh just before the release.]
|
||||
|
||||
The following bugs were resolved with this release:
|
||||
|
||||
[The release manager will add the list generated by
|
||||
scripts/list-fixed-bugs.py just before the release.]
|
||||
|
||||
Version 2.41
|
||||
|
||||
Major new features:
|
||||
|
|
28
SHARED-FILES
28
SHARED-FILES
|
@ -334,3 +334,31 @@ sysdeps/ieee754/flt-32/s_tanhf.c:
|
|||
(src/binary32/tanh/tanhf.c in CORE-MATH)
|
||||
- the code was adapted to use glibc code style and internal
|
||||
functions to handle errno, overflow, and underflow.
|
||||
sysdeps/ieee754/flt-32/s_acospif.c:
|
||||
(src/binary32/acospi/acospif.c in CORE-MATH)
|
||||
- the code was adapted to use glibc code style and internal
|
||||
functions to handle errno, overflow, and underflow.
|
||||
sysdeps/ieee754/flt-32/s_asinpif.c:
|
||||
(src/binary32/asinpi/asinpif.c in CORE-MATH)
|
||||
- the code was adapted to use glibc code style and internal
|
||||
functions to handle errno, overflow, and underflow.
|
||||
sysdeps/ieee754/flt-32/s_atan2pif.c:
|
||||
(src/binary32/atan2pi/atan2pif.c in CORE-MATH)
|
||||
- the code was adapted to use glibc code style and internal
|
||||
functions to handle errno, overflow, and underflow.
|
||||
sysdeps/ieee754/flt-32/s_atanpif.c:
|
||||
(src/binary32/atanpi/atanpif.c in CORE-MATH)
|
||||
- the code was adapted to use glibc code style and internal
|
||||
functions to handle errno, overflow, and underflow.
|
||||
sysdeps/ieee754/flt-32/s_cospif.c:
|
||||
(src/binary32/cospi/cospif.c in CORE-MATH)
|
||||
- the code was adapted to use glibc code style and internal
|
||||
functions to handle errno, overflow, and underflow.
|
||||
sysdeps/ieee754/flt-32/s_sinpif.c:
|
||||
(src/binary32/sinpi/sinpif.c in CORE-MATH)
|
||||
- the code was adapted to use glibc code style and internal
|
||||
functions to handle errno, overflow, and underflow.
|
||||
sysdeps/ieee754/flt-32/s_tanpif.c:
|
||||
(src/binary32/tanpi/tanpif.c in CORE-MATH)
|
||||
- the code was adapted to use glibc code style and internal
|
||||
functions to handle errno, overflow, and underflow.
|
||||
|
|
|
@ -21,5 +21,20 @@ CVE-Id: CVE-2025-0395
|
|||
Public-Date: 2025-01-22
|
||||
Vulnerable-Commit: f8a3b5bf8fa1d0c43d2458e03cc109a04fdef194 (2.13-175)
|
||||
Fix-Commit: 68ee0f704cb81e9ad0a78c644a83e1e9cd2ee578 (2.41)
|
||||
Fix-Commit: cdb9ba84191ce72e86346fb8b1d906e7cd930ea2 (2.42)
|
||||
Fix-Commit: 69fda28279b497bd405fdd442a6d8e4d3d5f681b (2.41-7)
|
||||
Fix-Commit: 7d4b6bcae91f29d7b4daf15bab06b66cf1d2217c (2.40-66)
|
||||
Fix-Commit: d6c156c326999f144cb5b73d29982108d549ad8a (2.40-71)
|
||||
Fix-Commit: 808a84a8b81468b517a4d721fdc62069cb8c211f (2.39-146)
|
||||
Fix-Commit: f6d48470aef9264d2d56f4c4533eb76db7f9c2e4 (2.39-150)
|
||||
Fix-Commit: c32fd59314c343db88c3ea4a203870481d33c3d2 (2.38-122)
|
||||
Fix-Commit: f984e2d7e8299726891a1a497a3c36cd5542a0bf (2.38-124)
|
||||
Fix-Commit: a3d7865b098a3a67c44f7812208d9ce4718873ba (2.37-143)
|
||||
Fix-Commit: b989519fe1683c204ac24ec92830e3fe3bfaccad (2.37-146)
|
||||
Fix-Commit: 7971add7ee4171fdd8dfd17e7c04c4ed77a18845 (2.36-216)
|
||||
Fix-Commit: 0487893d5c5bc6710d83d7c3152d888a0339559e (2.36-219)
|
||||
Fix-Commit: 8b5d4be762419c4f6176261c6fea40ac559b88dc (2.35-370)
|
||||
Fix-Commit: 8b3d09dc0d350191985f9d291cc30ce96f034b49 (2.35-373)
|
||||
Fix-Commit: df4e1f4a5096b385c9bcc94424cf2eaa227b3761 (2.34-500)
|
||||
Fix-Commit: 31eb872cb21449832ab47ad5db83281d240e1d03 (2.34-503)
|
||||
Reported-By: Qualys Security Advisory
|
||||
|
|
|
@ -39,6 +39,7 @@ tests := \
|
|||
test-assert-perr \
|
||||
tst-assert-c++ \
|
||||
tst-assert-g++ \
|
||||
tst-assert-sa-2025-0001 \
|
||||
# tests
|
||||
|
||||
ifeq ($(have-cxx-thread_local),yes)
|
||||
|
|
92
assert/tst-assert-sa-2025-0001.c
Normal file
92
assert/tst-assert-sa-2025-0001.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* Test for CVE-2025-0395.
|
||||
Copyright The GNU Toolchain Authors.
|
||||
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/>. */
|
||||
|
||||
/* Test that a large enough __progname does not result in a buffer overflow
|
||||
when printing an assertion failure. This was CVE-2025-0395. */
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
#include <support/xstdio.h>
|
||||
#include <support/xunistd.h>
|
||||
|
||||
extern const char *__progname;
|
||||
|
||||
int
|
||||
do_test (int argc, char **argv)
|
||||
{
|
||||
|
||||
support_need_proc ("Reads /proc/self/maps to add guards to writable maps.");
|
||||
ignore_stderr ();
|
||||
|
||||
/* XXX assumes that the assert is on a 2 digit line number. */
|
||||
const char *prompt = ": %s:99: do_test: Assertion `argc < 1' failed.\n";
|
||||
|
||||
int ret = fprintf (stderr, prompt, __FILE__);
|
||||
if (ret < 0)
|
||||
FAIL_EXIT1 ("fprintf failed: %m\n");
|
||||
|
||||
size_t pagesize = getpagesize ();
|
||||
size_t namesize = pagesize - 1 - ret;
|
||||
|
||||
/* Alter the progname so that the assert message fills the entire page. */
|
||||
char progname[namesize];
|
||||
memset (progname, 'A', namesize - 1);
|
||||
progname[namesize - 1] = '\0';
|
||||
__progname = progname;
|
||||
|
||||
FILE *f = xfopen ("/proc/self/maps", "r");
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
uintptr_t prev_to = 0;
|
||||
|
||||
/* Pad the beginning of every writable mapping with a PROT_NONE map. This
|
||||
ensures that the mmap in the assert_fail path never ends up below a
|
||||
writable map and will terminate immediately in case of a buffer
|
||||
overflow. */
|
||||
while (xgetline (&line, &len, f))
|
||||
{
|
||||
uintptr_t from, to;
|
||||
char perm[4];
|
||||
|
||||
sscanf (line, "%" SCNxPTR "-%" SCNxPTR " %c%c%c%c ",
|
||||
&from, &to,
|
||||
&perm[0], &perm[1], &perm[2], &perm[3]);
|
||||
|
||||
bool writable = (memchr (perm, 'w', 4) != NULL);
|
||||
|
||||
if (prev_to != 0 && from - prev_to > pagesize && writable)
|
||||
xmmap ((void *) from - pagesize, pagesize, PROT_NONE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, 0);
|
||||
|
||||
prev_to = to;
|
||||
}
|
||||
|
||||
xfclose (f);
|
||||
|
||||
assert (argc < 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define EXPECTED_SIGNAL SIGABRT
|
||||
#define TEST_FUNCTION_ARGV do_test
|
||||
#include <support/test-driver.c>
|
|
@ -28,16 +28,20 @@ bench-math := \
|
|||
acosf \
|
||||
acosh \
|
||||
acoshf \
|
||||
acospif \
|
||||
asin \
|
||||
asinf \
|
||||
asinh \
|
||||
asinhf \
|
||||
asinpif \
|
||||
atan \
|
||||
atan2 \
|
||||
atan2f \
|
||||
atan2pif \
|
||||
atanf \
|
||||
atanh \
|
||||
atanhf \
|
||||
atanpif \
|
||||
cbrt \
|
||||
cbrtf \
|
||||
ceil \
|
||||
|
@ -46,6 +50,7 @@ bench-math := \
|
|||
cosf \
|
||||
cosh \
|
||||
coshf \
|
||||
cospif \
|
||||
erf \
|
||||
erfc \
|
||||
erfcf \
|
||||
|
@ -110,11 +115,13 @@ bench-math := \
|
|||
sinf \
|
||||
sinh \
|
||||
sinhf \
|
||||
sinpif \
|
||||
sqrt \
|
||||
tan \
|
||||
tanf \
|
||||
tanh \
|
||||
tanhf \
|
||||
tanpif \
|
||||
tgamma \
|
||||
tgammaf \
|
||||
trunc \
|
||||
|
@ -194,6 +201,7 @@ string-benchset := \
|
|||
strcpy_chk \
|
||||
strcspn \
|
||||
strlen \
|
||||
strlen-random \
|
||||
strncasecmp \
|
||||
strncat \
|
||||
strncmp \
|
||||
|
|
2710
benchtests/acospif-inputs
Normal file
2710
benchtests/acospif-inputs
Normal file
File diff suppressed because it is too large
Load diff
2710
benchtests/asinpif-inputs
Normal file
2710
benchtests/asinpif-inputs
Normal file
File diff suppressed because it is too large
Load diff
2005
benchtests/atan2pif-inputs
Normal file
2005
benchtests/atan2pif-inputs
Normal file
File diff suppressed because it is too large
Load diff
2005
benchtests/atanpif-inputs
Normal file
2005
benchtests/atanpif-inputs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -22,9 +22,8 @@
|
|||
#else
|
||||
# define TEST_NAME "bzero"
|
||||
#endif
|
||||
#define START_SIZE (128 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 64 * 1024 * 1024)
|
||||
#define TIMEOUT (20 * 60)
|
||||
#define START_SIZE (64 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
|
||||
#include "bench-string.h"
|
||||
|
||||
#include "json-lib.h"
|
||||
|
@ -52,7 +51,7 @@ IMPL (memset_zero, 0)
|
|||
static void
|
||||
do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *s, size_t n)
|
||||
{
|
||||
size_t i, iters = 16;
|
||||
size_t i, iters = (MIN_PAGE_SIZE * 64) / n;
|
||||
timing_t start, stop, cur;
|
||||
|
||||
TIMING_NOW (start);
|
||||
|
@ -74,20 +73,13 @@ do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *s, size_t n)
|
|||
static void
|
||||
do_test (json_ctx_t *json_ctx, size_t align, size_t len)
|
||||
{
|
||||
align &= 63;
|
||||
if ((align + len) * sizeof (CHAR) > page_size)
|
||||
return;
|
||||
|
||||
json_element_object_begin (json_ctx);
|
||||
json_attr_uint (json_ctx, "length", len);
|
||||
json_attr_uint (json_ctx, "alignment", align);
|
||||
json_array_begin (json_ctx, "timings");
|
||||
|
||||
FOR_EACH_IMPL (impl, 0)
|
||||
{
|
||||
do_one_test (json_ctx, impl, (CHAR *) (buf1) + align, len);
|
||||
alloc_bufs ();
|
||||
}
|
||||
|
||||
json_array_end (json_ctx);
|
||||
json_element_object_end (json_ctx);
|
||||
|
|
|
@ -19,10 +19,9 @@
|
|||
#ifndef MEMCPY_RESULT
|
||||
# define MEMCPY_RESULT(dst, len) dst
|
||||
# define START_SIZE (64 * 1024)
|
||||
# define MIN_PAGE_SIZE (getpagesize () + 32 * 1024 * 1024)
|
||||
# define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
|
||||
# define TEST_MAIN
|
||||
# define TEST_NAME "memcpy"
|
||||
# define TIMEOUT (20 * 60)
|
||||
# include "bench-string.h"
|
||||
|
||||
IMPL (memcpy, 1)
|
||||
|
@ -36,7 +35,7 @@ static void
|
|||
do_one_test (json_ctx_t *json_ctx, impl_t *impl, char *dst, const char *src,
|
||||
size_t len)
|
||||
{
|
||||
size_t i, iters = 16;
|
||||
size_t i, iters = (MIN_PAGE_SIZE * 8) / len;
|
||||
timing_t start, stop, cur;
|
||||
|
||||
TIMING_NOW (start);
|
||||
|
@ -59,12 +58,7 @@ do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len,
|
|||
char *s1, *s2;
|
||||
size_t repeats;
|
||||
align1 &= 4095;
|
||||
if (align1 + len >= page_size)
|
||||
return;
|
||||
|
||||
align2 &= 4095;
|
||||
if (align2 + len >= page_size)
|
||||
return;
|
||||
|
||||
s1 = (char *) (buf1 + align1);
|
||||
s2 = (char *) (buf2 + align2);
|
||||
|
|
|
@ -16,12 +16,10 @@
|
|||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#define BASE_PAGE_SIZE (1024 * 1024)
|
||||
#define START_SIZE (4 * 1024)
|
||||
#define START_SIZE (64 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
|
||||
#define TEST_MAIN
|
||||
#define TEST_NAME "memmove"
|
||||
#define TIMEOUT (20 * 60)
|
||||
#include "bench-string.h"
|
||||
#include "json-lib.h"
|
||||
|
||||
|
@ -33,7 +31,7 @@ static void
|
|||
do_one_test (json_ctx_t *json_ctx, impl_t *impl, char *dst, char *src,
|
||||
size_t len)
|
||||
{
|
||||
size_t i, iters = 16;
|
||||
size_t i, iters = (MIN_PAGE_SIZE * 8) / len;
|
||||
timing_t start, stop, cur;
|
||||
|
||||
TIMING_NOW (start);
|
||||
|
@ -54,13 +52,8 @@ do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len)
|
|||
size_t i, j;
|
||||
char *s1, *s2;
|
||||
|
||||
align1 &= 127;
|
||||
if (align1 + len >= page_size)
|
||||
return;
|
||||
|
||||
align2 &= 127;
|
||||
if (align2 + len >= page_size)
|
||||
return;
|
||||
align1 &= 4095;
|
||||
align2 &= 4095;
|
||||
|
||||
s1 = (char *) (buf2 + align1);
|
||||
s2 = (char *) (buf2 + align2);
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
|
||||
#define TEST_MAIN
|
||||
#define TEST_NAME "memset"
|
||||
#define START_SIZE (128 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 64 * 1024 * 1024)
|
||||
#define TIMEOUT (20 * 60)
|
||||
#define START_SIZE (64 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
|
||||
#include "bench-string.h"
|
||||
|
||||
#include "json-lib.h"
|
||||
|
@ -35,7 +34,7 @@ static void
|
|||
do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *s,
|
||||
int c __attribute ((unused)), size_t n)
|
||||
{
|
||||
size_t i, iters = 16;
|
||||
size_t i, iters = (MIN_PAGE_SIZE * 64) / n;
|
||||
timing_t start, stop, cur;
|
||||
|
||||
TIMING_NOW (start);
|
||||
|
@ -53,10 +52,6 @@ do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *s,
|
|||
static void
|
||||
do_test (json_ctx_t *json_ctx, size_t align, int c, size_t len)
|
||||
{
|
||||
align &= 63;
|
||||
if ((align + len) * sizeof (CHAR) > page_size)
|
||||
return;
|
||||
|
||||
json_element_object_begin (json_ctx);
|
||||
json_attr_uint (json_ctx, "length", len);
|
||||
json_attr_uint (json_ctx, "alignment", align);
|
||||
|
@ -64,10 +59,7 @@ do_test (json_ctx_t *json_ctx, size_t align, int c, size_t len)
|
|||
json_array_begin (json_ctx, "timings");
|
||||
|
||||
FOR_EACH_IMPL (impl, 0)
|
||||
{
|
||||
do_one_test (json_ctx, impl, (CHAR *) (buf1) + align, c, len);
|
||||
alloc_bufs ();
|
||||
}
|
||||
|
||||
json_array_end (json_ctx);
|
||||
json_element_object_end (json_ctx);
|
||||
|
|
194
benchtests/bench-strlen-random.c
Normal file
194
benchtests/bench-strlen-random.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
/* Measure strlen performance.
|
||||
Copyright (C) 2024 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 TEST_MAIN
|
||||
#define TEST_NAME "strlen"
|
||||
|
||||
#define NUM_TESTS 65536
|
||||
#define MAX_ALIGN 32
|
||||
#define MAX_STRLEN 128
|
||||
#define MIN_PAGE_SIZE (2 * getpagesize())
|
||||
|
||||
#include "bench-string.h"
|
||||
#include <assert.h>
|
||||
#include "json-lib.h"
|
||||
|
||||
typedef size_t (*proto_t) (const CHAR *);
|
||||
|
||||
size_t memchr_strlen (const CHAR *);
|
||||
|
||||
IMPL (memchr_strlen, 0)
|
||||
|
||||
size_t
|
||||
memchr_strlen (const CHAR *p)
|
||||
{
|
||||
return (const CHAR *)MEMCHR (p, 0, PTRDIFF_MAX) - p;
|
||||
}
|
||||
|
||||
IMPL (STRLEN, 1)
|
||||
|
||||
static uint32_t strlen_tests[NUM_TESTS];
|
||||
|
||||
typedef struct { uint16_t size; uint16_t freq; } freq_data_t;
|
||||
typedef struct { uint16_t align; uint16_t freq; } align_data_t;
|
||||
|
||||
#define SIZE_NUM 65536
|
||||
#define SIZE_MASK (SIZE_NUM-1)
|
||||
static uint8_t strlen_len_arr[SIZE_NUM];
|
||||
|
||||
/* Frequency data for strlen sizes up to 256 based on SPEC2017. */
|
||||
static freq_data_t strlen_len_freq[] =
|
||||
{
|
||||
{ 12,22671}, { 18,12834}, { 13, 9555}, { 6, 6348}, { 17, 6095}, { 11, 2115},
|
||||
{ 10, 1335}, { 7, 814}, { 2, 646}, { 9, 483}, { 8, 471}, { 16, 418},
|
||||
{ 4, 390}, { 1, 388}, { 5, 233}, { 3, 204}, { 0, 79}, { 14, 79},
|
||||
{ 15, 69}, { 26, 36}, { 22, 35}, { 31, 24}, { 32, 24}, { 19, 21},
|
||||
{ 25, 17}, { 28, 15}, { 21, 14}, { 33, 14}, { 20, 13}, { 24, 9},
|
||||
{ 29, 9}, { 30, 9}, { 23, 7}, { 34, 7}, { 27, 6}, { 44, 5},
|
||||
{ 42, 4}, { 45, 3}, { 47, 3}, { 40, 2}, { 41, 2}, { 43, 2},
|
||||
{ 58, 2}, { 78, 2}, { 36, 2}, { 48, 1}, { 52, 1}, { 60, 1},
|
||||
{ 64, 1}, { 56, 1}, { 76, 1}, { 68, 1}, { 80, 1}, { 84, 1},
|
||||
{ 72, 1}, { 86, 1}, { 35, 1}, { 39, 1}, { 50, 1}, { 38, 1},
|
||||
{ 37, 1}, { 46, 1}, { 98, 1}, {102, 1}, {128, 1}, { 51, 1},
|
||||
{107, 1}, { 0, 0}
|
||||
};
|
||||
|
||||
#define ALIGN_NUM 1024
|
||||
#define ALIGN_MASK (ALIGN_NUM-1)
|
||||
static uint8_t strlen_align_arr[ALIGN_NUM];
|
||||
|
||||
/* Alignment data for strlen based on SPEC2017. */
|
||||
static align_data_t string_align_freq[] =
|
||||
{
|
||||
{8, 470}, {32, 427}, {16, 99}, {1, 19}, {2, 6}, {4, 3}, {0, 0}
|
||||
};
|
||||
|
||||
static void
|
||||
init_strlen_distribution (void)
|
||||
{
|
||||
int i, j, freq, size, n;
|
||||
|
||||
for (n = i = 0; (freq = strlen_len_freq[i].freq) != 0; i++)
|
||||
for (j = 0, size = strlen_len_freq[i].size; j < freq; j++)
|
||||
strlen_len_arr[n++] = size;
|
||||
assert (n == SIZE_NUM);
|
||||
|
||||
for (n = i = 0; (freq = string_align_freq[i].freq) != 0; i++)
|
||||
for (j = 0, size = string_align_freq[i].align; j < freq; j++)
|
||||
strlen_align_arr[n++] = size;
|
||||
assert (n == ALIGN_NUM);
|
||||
}
|
||||
|
||||
static volatile size_t maskv = 0;
|
||||
|
||||
static void
|
||||
do_one_test (json_ctx_t *json_ctx, impl_t *impl, size_t iters,
|
||||
uint32_t *input, size_t n)
|
||||
{
|
||||
timing_t start, stop, cur;
|
||||
size_t res = 0;
|
||||
size_t mask = maskv;
|
||||
|
||||
/* Avoid 'cold start' performance penalty. */
|
||||
for (int i = 0; i < 10; i++)
|
||||
for (int j = 0; j < n; j++)
|
||||
CALL (impl, (const char*)buf1 + input[j]);
|
||||
|
||||
TIMING_NOW (start);
|
||||
for (int i = 0; i < iters; ++i)
|
||||
for (int j = 0; j < n; j++)
|
||||
res = CALL (impl, (const char*)buf1 + input[j] + (res & mask));
|
||||
TIMING_NOW (stop);
|
||||
TIMING_DIFF (cur, start, stop);
|
||||
json_element_double (json_ctx, (double) cur / (double) iters);
|
||||
}
|
||||
|
||||
static void
|
||||
do_test (json_ctx_t *json_ctx)
|
||||
{
|
||||
size_t n;
|
||||
uint8_t *a = buf1;
|
||||
uint16_t index[MAX_ALIGN];
|
||||
|
||||
memset (a, 'x', MIN_PAGE_SIZE);
|
||||
|
||||
/* Create indices for strings at all alignments. */
|
||||
for (int i = 0; i < MAX_ALIGN; i++)
|
||||
{
|
||||
index[i] = i * (MAX_STRLEN + 1);
|
||||
a[index[i] + MAX_STRLEN] = 0;
|
||||
}
|
||||
|
||||
/* Create a random set of strlen input strings using the string length
|
||||
and alignment distributions. */
|
||||
for (n = 0; n < NUM_TESTS; n++)
|
||||
{
|
||||
int align = strlen_align_arr[rand () & ALIGN_MASK];
|
||||
int exp_len = strlen_len_arr[rand () & SIZE_MASK];
|
||||
|
||||
strlen_tests[n] =
|
||||
index[(align + exp_len) & (MAX_ALIGN - 1)] + MAX_STRLEN - exp_len;
|
||||
assert ((strlen_tests[n] & (align - 1)) == 0);
|
||||
assert (strlen ((char*) a + strlen_tests[n]) == exp_len);
|
||||
}
|
||||
|
||||
json_element_object_begin (json_ctx);
|
||||
json_array_begin (json_ctx, "timings");
|
||||
|
||||
FOR_EACH_IMPL (impl, 0)
|
||||
do_one_test (json_ctx, impl, INNER_LOOP_ITERS_MEDIUM, strlen_tests, n);
|
||||
|
||||
json_array_end (json_ctx);
|
||||
json_element_object_end (json_ctx);
|
||||
}
|
||||
|
||||
int
|
||||
test_main (void)
|
||||
{
|
||||
|
||||
json_ctx_t json_ctx;
|
||||
|
||||
test_init ();
|
||||
init_strlen_distribution ();
|
||||
|
||||
json_init (&json_ctx, 0, stdout);
|
||||
|
||||
json_document_begin (&json_ctx);
|
||||
json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
|
||||
|
||||
json_attr_object_begin (&json_ctx, "functions");
|
||||
json_attr_object_begin (&json_ctx, TEST_NAME);
|
||||
json_attr_string (&json_ctx, "bench-variant", "random");
|
||||
|
||||
json_array_begin (&json_ctx, "ifuncs");
|
||||
FOR_EACH_IMPL (impl, 0)
|
||||
json_element_string (&json_ctx, impl->name);
|
||||
json_array_end (&json_ctx);
|
||||
|
||||
json_array_begin (&json_ctx, "results");
|
||||
do_test (&json_ctx);
|
||||
|
||||
json_array_end (&json_ctx);
|
||||
json_attr_object_end (&json_ctx);
|
||||
json_attr_object_end (&json_ctx);
|
||||
json_document_end (&json_ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
2409
benchtests/cospif-inputs
Normal file
2409
benchtests/cospif-inputs
Normal file
File diff suppressed because it is too large
Load diff
2409
benchtests/sinpif-inputs
Normal file
2409
benchtests/sinpif-inputs
Normal file
File diff suppressed because it is too large
Load diff
2409
benchtests/tanpif-inputs
Normal file
2409
benchtests/tanpif-inputs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -53,6 +53,7 @@ c++-bits-std_abs-h = @CXX_BITS_STD_ABS_H@
|
|||
enable-werror = @enable_werror@
|
||||
|
||||
have-z-execstack = @libc_cv_z_execstack@
|
||||
have-no-error-execstack = @libc_cv_no_error_execstack@
|
||||
have-protected-data = @libc_cv_protected_data@
|
||||
have-insert = @libc_cv_insert@
|
||||
have-glob-dat-reloc = @libc_cv_has_glob_dat@
|
||||
|
|
134
configure
vendored
134
configure
vendored
|
@ -659,6 +659,7 @@ libc_cv_has_glob_dat
|
|||
libc_cv_fpie
|
||||
libc_cv_test_static_pie
|
||||
libc_cv_z_execstack
|
||||
libc_cv_no_error_execstack
|
||||
ASFLAGS_config
|
||||
libc_cv_cc_with_libunwind
|
||||
libc_cv_insert
|
||||
|
@ -7114,6 +7115,40 @@ if test $libc_cv_as_noexecstack = yes; then
|
|||
fi
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-error-execstack" >&5
|
||||
printf %s "checking for linker that supports --no-error-execstack... " >&6; }
|
||||
libc_linker_feature=no
|
||||
cat > conftest.c <<EOF
|
||||
int _start (void) { return 42; }
|
||||
EOF
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
|
||||
-Wl,-no-error-execstack -nostdlib -nostartfiles
|
||||
-fPIC -shared -o conftest.so conftest.c
|
||||
1>&5'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then
|
||||
if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-no-error-execstack -nostdlib \
|
||||
-nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
|
||||
| grep "warning: --no-error-execstack ignored" > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
libc_linker_feature=yes
|
||||
fi
|
||||
fi
|
||||
rm -f conftest*
|
||||
if test $libc_linker_feature = yes; then
|
||||
libc_cv_no_error_execstack=yes
|
||||
else
|
||||
libc_cv_no_error_execstack=no
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
|
||||
printf "%s\n" "$libc_linker_feature" >&6; }
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z execstack" >&5
|
||||
printf %s "checking for linker that supports -z execstack... " >&6; }
|
||||
libc_linker_feature=no
|
||||
|
@ -8908,6 +8943,105 @@ printf "%s\n" "$libc_linker_feature" >&6; }
|
|||
config_vars="$config_vars
|
||||
load-address-ldflag = $libc_cv_load_address_ldflag"
|
||||
|
||||
# Check if compilers support GCS in branch protection:
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs" >&5
|
||||
printf %s "checking if compiler supports -mbranch-protection=gcs... " >&6; }
|
||||
if test ${libc_cv_cc_gcs+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else case e in #(
|
||||
e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then :
|
||||
libc_cv_cc_gcs=yes
|
||||
else case e in #(
|
||||
e) libc_cv_cc_gcs=no ;;
|
||||
esac
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_gcs" >&5
|
||||
printf "%s\n" "$libc_cv_cc_gcs" >&6; }
|
||||
if test "$TEST_CC" = "$CC"; then
|
||||
libc_cv_test_cc_gcs=$libc_cv_cc_gcs
|
||||
else
|
||||
|
||||
saved_CC="$CC"
|
||||
CC="$TEST_CC"
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports -mbranch-protection=gcs in testing" >&5
|
||||
printf %s "checking if compiler supports -mbranch-protection=gcs in testing... " >&6; }
|
||||
if test ${libc_cv_test_cc_gcs+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else case e in #(
|
||||
e) if { ac_try='${CC-cc} -Werror -mbranch-protection=gcs -xc /dev/null -S -o /dev/null'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then :
|
||||
libc_cv_test_cc_gcs=yes
|
||||
else case e in #(
|
||||
e) libc_cv_test_cc_gcs=no ;;
|
||||
esac
|
||||
fi ;;
|
||||
esac
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_cc_gcs" >&5
|
||||
printf "%s\n" "$libc_cv_test_cc_gcs" >&6; }
|
||||
|
||||
CC="$saved_CC"
|
||||
|
||||
fi
|
||||
|
||||
config_vars="$config_vars
|
||||
have-cc-gcs = $libc_cv_cc_gcs"
|
||||
config_vars="$config_vars
|
||||
have-test-cc-gcs = $libc_cv_test_cc_gcs"
|
||||
|
||||
# Check if linker supports GCS marking
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z gcs=always" >&5
|
||||
printf %s "checking for linker that supports -z gcs=always... " >&6; }
|
||||
libc_linker_feature=no
|
||||
cat > conftest.c <<EOF
|
||||
int _start (void) { return 42; }
|
||||
EOF
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
|
||||
-Wl,-z,gcs=always -nostdlib -nostartfiles
|
||||
-fPIC -shared -o conftest.so conftest.c
|
||||
1>&5'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then
|
||||
if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-z,gcs=always -nostdlib \
|
||||
-nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
|
||||
| grep "warning: -z gcs=always ignored" > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
libc_linker_feature=yes
|
||||
fi
|
||||
fi
|
||||
rm -f conftest*
|
||||
if test $libc_linker_feature = yes; then
|
||||
libc_cv_ld_gcs=yes
|
||||
else
|
||||
libc_cv_ld_gcs=no
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
|
||||
printf "%s\n" "$libc_linker_feature" >&6; }
|
||||
config_vars="$config_vars
|
||||
have-ld-gcs = $libc_cv_ld_gcs"
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
|
||||
printf %s "checking if we can build programs as PIE... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
|
|
21
configure.ac
21
configure.ac
|
@ -1318,6 +1318,10 @@ if test $libc_cv_as_noexecstack = yes; then
|
|||
fi
|
||||
AC_SUBST(ASFLAGS_config)
|
||||
|
||||
LIBC_LINKER_FEATURE([--no-error-execstack], [-Wl,-no-error-execstack],
|
||||
[libc_cv_no_error_execstack=yes], [libc_cv_no_error_execstack=no])
|
||||
AC_SUBST(libc_cv_no_error_execstack)
|
||||
|
||||
LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack],
|
||||
[libc_cv_z_execstack=yes], [libc_cv_z_execstack=no])
|
||||
AC_SUBST(libc_cv_z_execstack)
|
||||
|
@ -1992,6 +1996,23 @@ LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
|
|||
[libc_cv_load_address_ldflag=])
|
||||
LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address_ldflag])
|
||||
|
||||
# Check if compilers support GCS in branch protection:
|
||||
LIBC_TRY_CC_AND_TEST_CC_OPTION([if compiler supports -mbranch-protection=gcs],
|
||||
[-Werror -mbranch-protection=gcs],
|
||||
libc_cv_cc_gcs,
|
||||
[libc_cv_cc_gcs=yes],
|
||||
[libc_cv_cc_gcs=no],
|
||||
libc_cv_test_cc_gcs,
|
||||
[libc_cv_test_cc_gcs=yes],
|
||||
[libc_cv_test_cc_gcs=no])
|
||||
LIBC_CONFIG_VAR([have-cc-gcs], [$libc_cv_cc_gcs])
|
||||
LIBC_CONFIG_VAR([have-test-cc-gcs], [$libc_cv_test_cc_gcs])
|
||||
|
||||
# Check if linker supports GCS marking
|
||||
LIBC_LINKER_FEATURE([-z gcs=always], [-Wl,-z,gcs=always],
|
||||
[libc_cv_ld_gcs=yes], [libc_cv_ld_gcs=no])
|
||||
LIBC_CONFIG_VAR([have-ld-gcs], [$libc_cv_ld_gcs])
|
||||
|
||||
AC_MSG_CHECKING(if we can build programs as PIE)
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
|
||||
# error PIE is not supported
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <dl-extra_tls.h>
|
||||
#include <array_length.h>
|
||||
#include <elf/dl-tls_block_align.h>
|
||||
#include <dl-symbol-redir-ifunc.h>
|
||||
|
||||
#ifdef SHARED
|
||||
#error makefile bug, this file is for static only
|
||||
|
|
18
elf/Makefile
18
elf/Makefile
|
@ -34,7 +34,6 @@ routines = \
|
|||
dl-addr \
|
||||
dl-addr-obj \
|
||||
dl-early_allocate \
|
||||
dl-find_object \
|
||||
dl-iteratephdr \
|
||||
dl-libc \
|
||||
dl-origin \
|
||||
|
@ -61,6 +60,7 @@ dl-routines = \
|
|||
dl-deps \
|
||||
dl-exception \
|
||||
dl-execstack \
|
||||
dl-find_object \
|
||||
dl-fini \
|
||||
dl-init \
|
||||
dl-load \
|
||||
|
@ -379,6 +379,7 @@ tests += \
|
|||
tst-align3 \
|
||||
tst-audit-tlsdesc \
|
||||
tst-audit-tlsdesc-dlopen \
|
||||
tst-audit-tlsdesc-dlopen2 \
|
||||
tst-audit1 \
|
||||
tst-audit2 \
|
||||
tst-audit8 \
|
||||
|
@ -863,6 +864,7 @@ modules-names += \
|
|||
tst-auditmanymod8 \
|
||||
tst-auditmanymod9 \
|
||||
tst-auditmod-tlsdesc \
|
||||
tst-auditmod-tlsdesc2 \
|
||||
tst-auditmod1 \
|
||||
tst-auditmod11 \
|
||||
tst-auditmod12 \
|
||||
|
@ -1135,12 +1137,14 @@ tests += \
|
|||
tst-dlopen-pie \
|
||||
tst-dlopen-self-pie \
|
||||
tst-dlopen-tlsmodid-pie \
|
||||
tst-pie-bss \
|
||||
tst-pie1 \
|
||||
tst-pie2 \
|
||||
# tests
|
||||
tests-pie += \
|
||||
tst-dlopen-self-pie \
|
||||
tst-dlopen-tlsmodid-pie \
|
||||
tst-pie-bss \
|
||||
tst-pie1 \
|
||||
tst-pie2 \
|
||||
# tests-pie
|
||||
|
@ -1155,9 +1159,11 @@ LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
|
|||
ifeq (yes,$(enable-static-pie))
|
||||
tests += \
|
||||
tst-pie-address-static \
|
||||
tst-pie-bss-static \
|
||||
# tests
|
||||
tests-static += \
|
||||
tst-pie-address-static \
|
||||
tst-pie-bss-static \
|
||||
# tests-static
|
||||
LDFLAGS-tst-pie-address-static += \
|
||||
$(load-address-ldflag)=$(pde-load-address)
|
||||
|
@ -1988,6 +1994,9 @@ $(objpfx)tst-execstack.out: $(objpfx)tst-execstack-mod.so
|
|||
CPPFLAGS-tst-execstack.c += -DUSE_PTHREADS=0
|
||||
LDFLAGS-tst-execstack = -Wl,-z,noexecstack
|
||||
LDFLAGS-tst-execstack-mod.so = -Wl,-z,execstack
|
||||
ifeq ($(have-no-error-execstack),yes)
|
||||
LDFLAGS-tst-execstack-mod.so += -Wl,--no-error-execstack
|
||||
endif
|
||||
|
||||
$(objpfx)tst-execstack-needed: $(objpfx)tst-execstack-mod.so
|
||||
LDFLAGS-tst-execstack-needed = -Wl,-z,noexecstack
|
||||
|
@ -1997,6 +2006,9 @@ CFLAGS-tst-execstack-prog.c += -Wno-trampolines
|
|||
CFLAGS-tst-execstack-mod.c += -Wno-trampolines
|
||||
|
||||
LDFLAGS-tst-execstack-prog-static = -Wl,-z,execstack
|
||||
ifeq ($(have-no-error-execstack),yes)
|
||||
LDFLAGS-tst-execstack-prog-static += -Wl,--no-error-execstack
|
||||
endif
|
||||
CFLAGS-tst-execstack-prog-static.c += -Wno-trampolines
|
||||
|
||||
ifeq (yes,$(build-hardcoded-path-in-tests))
|
||||
|
@ -2074,6 +2086,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
|
|||
|
||||
CFLAGS-tst-pie1.c += $(pie-ccflag)
|
||||
CFLAGS-tst-pie2.c += $(pie-ccflag)
|
||||
CFLAGS-tst-pie-bss.c += $(pie-ccflag)
|
||||
CFLAGS-tst-pie-address.c += $(pie-ccflag)
|
||||
|
||||
$(objpfx)tst-piemod1.so: $(libsupport)
|
||||
|
@ -3189,6 +3202,9 @@ $(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
|
|||
tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
$(objpfx)tst-audit-tlsdesc-dlopen2.out: $(objpfx)tst-auditmod-tlsdesc2.so \
|
||||
$(patsubst %, $(objpfx)%.so, $(tlsmod17a-modules))
|
||||
tst-audit-tlsdesc-dlopen2-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc2.so
|
||||
|
||||
$(objpfx)tst-dlmopen-twice.out: \
|
||||
$(objpfx)tst-dlmopen-twice-mod1.so \
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <ldsodefs.h>
|
||||
#include <sys/mman.h>
|
||||
#include <dl-cache.h>
|
||||
#include <dl-procinfo.h>
|
||||
#include <stdint.h>
|
||||
#include <_itoa.h>
|
||||
#include <dl-hwcaps.h>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <dl-diagnostics.h>
|
||||
#include <dl-hwcaps.h>
|
||||
#include <dl-main.h>
|
||||
#include <dl-procinfo.h>
|
||||
#include <dl-sysdep.h>
|
||||
#include <ldsodefs.h>
|
||||
#include "trusted-dirs.h"
|
||||
|
|
|
@ -356,7 +356,7 @@ _dlfo_lookup (uintptr_t pc, struct dl_find_object_internal *first1, size_t size)
|
|||
}
|
||||
|
||||
int
|
||||
__dl_find_object (void *pc1, struct dl_find_object *result)
|
||||
_dl_find_object (void *pc1, struct dl_find_object *result)
|
||||
{
|
||||
uintptr_t pc = (uintptr_t) pc1;
|
||||
|
||||
|
@ -463,8 +463,7 @@ __dl_find_object (void *pc1, struct dl_find_object *result)
|
|||
return -1;
|
||||
} /* Transaction retry loop. */
|
||||
}
|
||||
hidden_def (__dl_find_object)
|
||||
weak_alias (__dl_find_object, _dl_find_object)
|
||||
rtld_hidden_def (_dl_find_object)
|
||||
|
||||
/* _dlfo_process_initial is called twice. First to compute the array
|
||||
sizes from the initial loaded mappings. Second to fill in the
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
|
||||
#include <dl-procinfo.h>
|
||||
#include <dl-hwcaps.h>
|
||||
|
||||
/* This is the result of counting the substrings in a colon-separated
|
||||
|
|
107
elf/dl-libc.c
107
elf/dl-libc.c
|
@ -226,110 +226,3 @@ __libc_dlclose (void *map)
|
|||
#endif
|
||||
return dlerror_run (do_dlclose, map);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
free_slotinfo (struct dtv_slotinfo_list **elemp)
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
if (*elemp == NULL)
|
||||
/* Nothing here, all is removed (or there never was anything). */
|
||||
return true;
|
||||
|
||||
if (!free_slotinfo (&(*elemp)->next))
|
||||
/* We cannot free the entry. */
|
||||
return false;
|
||||
|
||||
/* That cleared our next pointer for us. */
|
||||
|
||||
for (cnt = 0; cnt < (*elemp)->len; ++cnt)
|
||||
if ((*elemp)->slotinfo[cnt].map != NULL)
|
||||
/* Still used. */
|
||||
return false;
|
||||
|
||||
/* We can remove the list element. */
|
||||
free (*elemp);
|
||||
*elemp = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__dl_libc_freemem (void)
|
||||
{
|
||||
struct link_map *l;
|
||||
struct r_search_path_elem *d;
|
||||
|
||||
/* Remove all search directories. */
|
||||
d = GL(dl_all_dirs);
|
||||
while (d != GLRO(dl_init_all_dirs))
|
||||
{
|
||||
struct r_search_path_elem *old = d;
|
||||
d = d->next;
|
||||
free (old);
|
||||
}
|
||||
|
||||
for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
|
||||
{
|
||||
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
|
||||
{
|
||||
struct libname_list *lnp = l->l_libname->next;
|
||||
|
||||
l->l_libname->next = NULL;
|
||||
|
||||
/* Remove all additional names added to the objects. */
|
||||
while (lnp != NULL)
|
||||
{
|
||||
struct libname_list *old = lnp;
|
||||
lnp = lnp->next;
|
||||
if (! old->dont_free)
|
||||
free (old);
|
||||
}
|
||||
|
||||
/* Free the initfini dependency list. */
|
||||
if (l->l_free_initfini)
|
||||
free (l->l_initfini);
|
||||
l->l_initfini = NULL;
|
||||
}
|
||||
|
||||
if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0
|
||||
&& (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist
|
||||
// XXX Check whether we need NS-specific initial_searchlist
|
||||
== GLRO(dl_initial_searchlist).r_nlist))
|
||||
{
|
||||
/* All object dynamically loaded by the program are unloaded. Free
|
||||
the memory allocated for the global scope variable. */
|
||||
struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list;
|
||||
|
||||
/* Put the old map in. */
|
||||
GL(dl_ns)[ns]._ns_main_searchlist->r_list
|
||||
// XXX Check whether we need NS-specific initial_searchlist
|
||||
= GLRO(dl_initial_searchlist).r_list;
|
||||
/* Signal that the original map is used. */
|
||||
GL(dl_ns)[ns]._ns_global_scope_alloc = 0;
|
||||
|
||||
/* Now free the old map. */
|
||||
free (old);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory allocated for the dtv slotinfo array. We can do
|
||||
this only if all modules which used this memory are unloaded. */
|
||||
#ifdef SHARED
|
||||
if (GL(dl_initial_dtv) == NULL)
|
||||
/* There was no initial TLS setup, it was set up later when
|
||||
it used the normal malloc. */
|
||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
|
||||
else
|
||||
#endif
|
||||
/* The first element of the list does not have to be deallocated.
|
||||
It was allocated in the dynamic linker (i.e., with a different
|
||||
malloc), and in the static library it's in .bss space. */
|
||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
|
||||
|
||||
void *scope_free_list = GL(dl_scope_free_list);
|
||||
GL(dl_scope_free_list) = NULL;
|
||||
free (scope_free_list);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,109 @@
|
|||
#include <ldsodefs.h>
|
||||
#include <dl-find_object.h>
|
||||
|
||||
static bool
|
||||
free_slotinfo (struct dtv_slotinfo_list **elemp)
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
if (*elemp == NULL)
|
||||
/* Nothing here, all is removed (or there never was anything). */
|
||||
return true;
|
||||
|
||||
if (!free_slotinfo (&(*elemp)->next))
|
||||
/* We cannot free the entry. */
|
||||
return false;
|
||||
|
||||
/* That cleared our next pointer for us. */
|
||||
|
||||
for (cnt = 0; cnt < (*elemp)->len; ++cnt)
|
||||
if ((*elemp)->slotinfo[cnt].map != NULL)
|
||||
/* Still used. */
|
||||
return false;
|
||||
|
||||
/* We can remove the list element. */
|
||||
free (*elemp);
|
||||
*elemp = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
__rtld_libc_freeres (void)
|
||||
{
|
||||
struct link_map *l;
|
||||
struct r_search_path_elem *d;
|
||||
|
||||
/* Remove all search directories. */
|
||||
d = GL(dl_all_dirs);
|
||||
while (d != GLRO(dl_init_all_dirs))
|
||||
{
|
||||
struct r_search_path_elem *old = d;
|
||||
d = d->next;
|
||||
free (old);
|
||||
}
|
||||
|
||||
for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
|
||||
{
|
||||
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
|
||||
{
|
||||
struct libname_list *lnp = l->l_libname->next;
|
||||
|
||||
l->l_libname->next = NULL;
|
||||
|
||||
/* Remove all additional names added to the objects. */
|
||||
while (lnp != NULL)
|
||||
{
|
||||
struct libname_list *old = lnp;
|
||||
lnp = lnp->next;
|
||||
if (! old->dont_free)
|
||||
free (old);
|
||||
}
|
||||
|
||||
/* Free the initfini dependency list. */
|
||||
if (l->l_free_initfini)
|
||||
free (l->l_initfini);
|
||||
l->l_initfini = NULL;
|
||||
}
|
||||
|
||||
if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0
|
||||
&& (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist
|
||||
// XXX Check whether we need NS-specific initial_searchlist
|
||||
== GLRO(dl_initial_searchlist).r_nlist))
|
||||
{
|
||||
/* All object dynamically loaded by the program are unloaded. Free
|
||||
the memory allocated for the global scope variable. */
|
||||
struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list;
|
||||
|
||||
/* Put the old map in. */
|
||||
GL(dl_ns)[ns]._ns_main_searchlist->r_list
|
||||
// XXX Check whether we need NS-specific initial_searchlist
|
||||
= GLRO(dl_initial_searchlist).r_list;
|
||||
/* Signal that the original map is used. */
|
||||
GL(dl_ns)[ns]._ns_global_scope_alloc = 0;
|
||||
|
||||
/* Now free the old map. */
|
||||
free (old);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory allocated for the dtv slotinfo array. We can do
|
||||
this only if all modules which used this memory are unloaded. */
|
||||
#ifdef SHARED
|
||||
if (GL(dl_initial_dtv) == NULL)
|
||||
/* There was no initial TLS setup, it was set up later when
|
||||
it used the normal malloc. */
|
||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
|
||||
else
|
||||
#endif
|
||||
/* The first element of the list does not have to be deallocated.
|
||||
It was allocated in the dynamic linker (i.e., with a different
|
||||
malloc), and in the static library it's in .bss space. */
|
||||
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
|
||||
|
||||
void *scope_free_list = GL(dl_scope_free_list);
|
||||
GL(dl_scope_free_list) = NULL;
|
||||
free (scope_free_list);
|
||||
|
||||
_dl_find_object_freeres ();
|
||||
}
|
||||
|
|
|
@ -1421,10 +1421,8 @@ cannot enable executable stack as shared object requires");
|
|||
|
||||
/* When we profile the SONAME might be needed for something else but
|
||||
loading. Add it right away. */
|
||||
if (__glibc_unlikely (GLRO(dl_profile) != NULL)
|
||||
&& l->l_info[DT_SONAME] != NULL)
|
||||
add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||
+ l->l_info[DT_SONAME]->d_un.d_val));
|
||||
if (__glibc_unlikely (GLRO(dl_profile) != NULL) && l_soname (l) != NULL)
|
||||
add_name_to_object (l, l_soname (l));
|
||||
#else
|
||||
/* Audit modules only exist when linking is dynamic so ORIGNAME
|
||||
cannot be non-NULL. */
|
||||
|
@ -1434,9 +1432,7 @@ cannot enable executable stack as shared object requires");
|
|||
/* 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)
|
||||
&& l_soname (l) != NULL && strcmp (l_soname(l), LIBC_SO) == 0)
|
||||
GL(dl_ns)[nsid].libc_map = l;
|
||||
|
||||
/* _dl_close can only eventually undo the module ID assignment (via
|
||||
|
@ -1887,24 +1883,14 @@ open_path (const char *name, size_t namelen, int mode,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Map in the shared object file NAME. */
|
||||
|
||||
struct link_map *
|
||||
_dl_map_object (struct link_map *loader, const char *name,
|
||||
int type, int trace_mode, int mode, Lmid_t nsid)
|
||||
_dl_lookup_map (Lmid_t nsid, const char *name)
|
||||
{
|
||||
int fd;
|
||||
const char *origname = NULL;
|
||||
char *realname;
|
||||
char *name_copy;
|
||||
struct link_map *l;
|
||||
struct filebuf fb;
|
||||
|
||||
assert (nsid >= 0);
|
||||
assert (nsid < GL(dl_nns));
|
||||
|
||||
/* Look for this name among those already loaded. */
|
||||
for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
|
||||
for (struct link_map *l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
|
||||
{
|
||||
/* If the requested name matches the soname of a loaded object,
|
||||
use that object. Elide this check for names that have not
|
||||
|
@ -1913,19 +1899,12 @@ _dl_map_object (struct link_map *loader, const char *name,
|
|||
continue;
|
||||
if (!_dl_name_match_p (name, l))
|
||||
{
|
||||
const char *soname;
|
||||
|
||||
if (__glibc_likely (l->l_soname_added)
|
||||
|| l->l_info[DT_SONAME] == NULL)
|
||||
continue;
|
||||
|
||||
soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||
+ l->l_info[DT_SONAME]->d_un.d_val);
|
||||
if (strcmp (name, soname) != 0)
|
||||
if (__glibc_likely (l->l_soname_added) || l_soname (l) == NULL
|
||||
|| strcmp (name, l_soname (l)) != 0)
|
||||
continue;
|
||||
|
||||
/* We have a match on a new name -- cache it. */
|
||||
add_name_to_object (l, soname);
|
||||
add_name_to_object (l, l_soname (l));
|
||||
l->l_soname_added = 1;
|
||||
}
|
||||
|
||||
|
@ -1933,6 +1912,22 @@ _dl_map_object (struct link_map *loader, const char *name,
|
|||
return l;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Map in the shared object file NAME. */
|
||||
|
||||
struct link_map *
|
||||
_dl_map_new_object (struct link_map *loader, const char *name,
|
||||
int type, int trace_mode, int mode, Lmid_t nsid)
|
||||
{
|
||||
int fd;
|
||||
const char *origname = NULL;
|
||||
char *realname;
|
||||
char *name_copy;
|
||||
struct link_map *l;
|
||||
struct filebuf fb;
|
||||
|
||||
/* Display information if we are debugging. */
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)
|
||||
&& loader != NULL)
|
||||
|
@ -2183,6 +2178,17 @@ _dl_map_object (struct link_map *loader, const char *name,
|
|||
type, mode, &stack_end, nsid);
|
||||
}
|
||||
|
||||
struct link_map *
|
||||
_dl_map_object (struct link_map *loader, const char *name,
|
||||
int type, int trace_mode, int mode, Lmid_t nsid)
|
||||
{
|
||||
struct link_map *l = _dl_lookup_map (nsid, name);
|
||||
if (l != NULL)
|
||||
return l;
|
||||
return _dl_map_new_object (loader, name, type, trace_mode, mode, nsid);
|
||||
}
|
||||
|
||||
|
||||
struct add_path_state
|
||||
{
|
||||
bool counting;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <dl-load.h>
|
||||
#include <setvmaname.h>
|
||||
|
||||
/* Map a segment and align it properly. */
|
||||
|
||||
|
@ -182,12 +183,41 @@ _dl_map_segments (struct link_map *l, int fd,
|
|||
if (zeroend > zeropage)
|
||||
{
|
||||
/* Map the remaining zero pages in from the zero fill FD. */
|
||||
char bssname[ANON_VMA_NAME_MAX_LEN] = " glibc: .bss";
|
||||
|
||||
caddr_t mapat;
|
||||
mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
|
||||
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
|
||||
-1, 0);
|
||||
if (__glibc_unlikely (mapat == MAP_FAILED))
|
||||
return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
|
||||
if (__is_decorate_maps_enabled ())
|
||||
{
|
||||
if (l->l_name != NULL && *l->l_name != '\0')
|
||||
{
|
||||
int i = strlen (bssname), j = 0;
|
||||
int namelen = strlen (l->l_name);
|
||||
|
||||
bssname[i++] = ' ';
|
||||
if (namelen > sizeof (bssname) - i - 1)
|
||||
for (j = namelen - 1; j > 0; j--)
|
||||
if (l->l_name[j - 1] == '/')
|
||||
break;
|
||||
|
||||
for (; l->l_name[j] != '\0' && i < sizeof (bssname) - 1;
|
||||
i++, j++)
|
||||
{
|
||||
char ch = l->l_name[j];
|
||||
/* Replace non-printable characters and
|
||||
\, `, $, [ and ]. */
|
||||
if (ch <= 0x1f || ch >= 0x7f || strchr("\\`$[]", ch))
|
||||
ch = '!';
|
||||
bssname[i] = ch;
|
||||
}
|
||||
bssname[i] = 0;
|
||||
}
|
||||
__set_vma_name ((void*)zeropage, zeroend - zeropage, bssname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,7 @@ struct dl_open_args
|
|||
{
|
||||
const char *file;
|
||||
int mode;
|
||||
/* This is the caller of the dlopen() function. */
|
||||
const void *caller_dlopen;
|
||||
struct link_map *caller_map; /* Derived from the caller address. */
|
||||
struct link_map *map;
|
||||
/* Namespace ID. */
|
||||
Lmid_t nsid;
|
||||
|
@ -493,36 +492,29 @@ call_dl_init (void *closure)
|
|||
_dl_init (args->map, args->argc, args->argv, args->env);
|
||||
}
|
||||
|
||||
/* Return true if the object does not need any processing beyond the
|
||||
l_direct_opencount update. Needs to be kept in sync with the logic
|
||||
in dl_open_worker_begin after the l->l_searchlist.r_list != NULL check.
|
||||
MODE is the dlopen mode argument. */
|
||||
static bool
|
||||
is_already_fully_open (struct link_map *map, int mode)
|
||||
{
|
||||
return (map != NULL /* An existing map was found. */
|
||||
/* dlopen completed initialization of this map. Maps with
|
||||
l_type == lt_library start out as partially initialized. */
|
||||
&& map->l_searchlist.r_list != NULL
|
||||
/* The object is already in the global scope if requested. */
|
||||
&& (!(mode & RTLD_GLOBAL) || map->l_global)
|
||||
/* The object is already NODELETE if requested. */
|
||||
&& (!(mode & RTLD_NODELETE) || map->l_nodelete_active));
|
||||
}
|
||||
|
||||
static void
|
||||
dl_open_worker_begin (void *a)
|
||||
{
|
||||
struct dl_open_args *args = a;
|
||||
const char *file = args->file;
|
||||
int mode = args->mode;
|
||||
struct link_map *call_map = NULL;
|
||||
|
||||
/* Determine the caller's map if necessary. This is needed in case
|
||||
we have a DST, when we don't know the namespace ID we have to put
|
||||
the new object in, or when the file name has no path in which
|
||||
case we need to look along the RUNPATH/RPATH of the caller. */
|
||||
const char *dst = strchr (file, '$');
|
||||
if (dst != NULL || args->nsid == __LM_ID_CALLER
|
||||
|| strchr (file, '/') == NULL)
|
||||
{
|
||||
const void *caller_dlopen = args->caller_dlopen;
|
||||
|
||||
/* We have to find out from which object the caller is calling.
|
||||
By default we assume this is the main application. */
|
||||
call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
|
||||
struct link_map *l = _dl_find_dso_for_object ((ElfW(Addr)) caller_dlopen);
|
||||
|
||||
if (l)
|
||||
call_map = l;
|
||||
|
||||
if (args->nsid == __LM_ID_CALLER)
|
||||
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
|
||||
|
@ -538,8 +530,9 @@ dl_open_worker_begin (void *a)
|
|||
_dl_debug_initialize (0, args->nsid);
|
||||
|
||||
/* Load the named object. */
|
||||
struct link_map *new;
|
||||
args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
|
||||
struct link_map *new = args->map;
|
||||
if (new == NULL)
|
||||
args->map = new = _dl_map_new_object (args->caller_map, file, lt_loaded, 0,
|
||||
mode | __RTLD_CALLMAP, args->nsid);
|
||||
|
||||
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
|
||||
|
@ -557,7 +550,7 @@ dl_open_worker_begin (void *a)
|
|||
/* This object is directly loaded. */
|
||||
++new->l_direct_opencount;
|
||||
|
||||
/* It was already open. */
|
||||
/* It was already open. See is_already_fully_open above. */
|
||||
if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
|
||||
{
|
||||
/* Let the user know about the opencount. */
|
||||
|
@ -617,9 +610,7 @@ dl_open_worker_begin (void *a)
|
|||
Perform partial initialization in this case. This must
|
||||
come after the symbol versioning initialization in
|
||||
_dl_check_map_versions. */
|
||||
if (map->l_info[DT_SONAME] != NULL
|
||||
&& strcmp (((const char *) D_PTR (map, l_info[DT_STRTAB])
|
||||
+ map->l_info[DT_SONAME]->d_un.d_val), LD_SO) == 0)
|
||||
if (l_soname (map) != NULL && strcmp (l_soname (map), LD_SO) == 0)
|
||||
__rtld_static_init (map);
|
||||
#endif
|
||||
}
|
||||
|
@ -861,8 +852,6 @@ no more namespaces available for dlmopen()"));
|
|||
struct dl_open_args args;
|
||||
args.file = file;
|
||||
args.mode = mode;
|
||||
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). */
|
||||
|
@ -870,6 +859,34 @@ no more namespaces available for dlmopen()"));
|
|||
args.argv = argv;
|
||||
args.env = env;
|
||||
|
||||
/* Determine the caller's map if necessary. This is needed when we
|
||||
don't know the namespace ID in which we have to put the new object,
|
||||
in case we have a DST, or when the file name has no path in
|
||||
which case we need to look along the RUNPATH/RPATH of the caller. */
|
||||
if (nsid == __LM_ID_CALLER || strchr (file, '$') != NULL
|
||||
|| strchr (file, '/') == NULL)
|
||||
{
|
||||
struct dl_find_object dlfo;
|
||||
if (_dl_find_object ((void *) caller_dlopen, &dlfo) == 0)
|
||||
args.caller_map = dlfo.dlfo_link_map;
|
||||
else
|
||||
/* By default we assume this is the main application. */
|
||||
args.caller_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
if (args.nsid == __LM_ID_CALLER)
|
||||
args.nsid = args.caller_map->l_ns;
|
||||
}
|
||||
else
|
||||
args.caller_map = NULL;
|
||||
|
||||
args.map = _dl_lookup_map (args.nsid, file);
|
||||
if (is_already_fully_open (args.map, mode))
|
||||
{
|
||||
/* We can use the fast path. */
|
||||
++args.map->l_direct_opencount;
|
||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
||||
return args.map;
|
||||
}
|
||||
|
||||
struct dl_exception exception;
|
||||
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ _dl_relocate_static_pie (void)
|
|||
switch (ph->p_type)
|
||||
{
|
||||
case PT_LOAD:
|
||||
if (ph->p_offset == 0)
|
||||
/* Skip the empty PT_LOAD segment at offset 0. */
|
||||
if (ph->p_filesz != 0 && ph->p_offset == 0)
|
||||
file_p_vaddr = ph->p_vaddr;
|
||||
break;
|
||||
case PT_DYNAMIC:
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <dl-machine.h>
|
||||
#include <libc-lock.h>
|
||||
#include <dl-cache.h>
|
||||
#include <dl-procinfo.h>
|
||||
#include <unsecvars.h>
|
||||
#include <hp-timing.h>
|
||||
#include <stackinfo.h>
|
||||
|
|
13
elf/dl-tls.c
13
elf/dl-tls.c
|
@ -39,6 +39,12 @@
|
|||
|
||||
#include <dl-extra_tls.h>
|
||||
|
||||
/* This code is used during early startup when statically linked,
|
||||
via __libc_setup_tls in csu/libc-tls.c. */
|
||||
#ifndef SHARED
|
||||
# include <dl-symbol-redir-ifunc.h>
|
||||
#endif
|
||||
|
||||
/* Surplus static TLS, GLRO(dl_tls_static_surplus), is used for
|
||||
|
||||
- IE TLS in libc.so for all dlmopen namespaces except in the initial
|
||||
|
@ -560,6 +566,13 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
|
|||
if (newp == NULL)
|
||||
oom ();
|
||||
memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
|
||||
#ifdef SHARED
|
||||
/* Auditors can trigger a DTV resize event while the full malloc
|
||||
is not yet in use. Mark the new DTV allocation as the
|
||||
initial allocation. */
|
||||
if (!__rtld_malloc_is_complete ())
|
||||
GL(dl_initial_dtv) = &newp[1];
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <unistd.h>
|
||||
#include "version.h"
|
||||
|
||||
#include <dl-procinfo.h>
|
||||
#include <dl-hwcaps.h>
|
||||
|
||||
void
|
||||
|
|
13
elf/elf.h
13
elf/elf.h
|
@ -2906,19 +2906,6 @@ enum
|
|||
|
||||
#define R_AARCH64_NONE 0 /* No relocation. */
|
||||
|
||||
/* ILP32 AArch64 relocs. */
|
||||
#define R_AARCH64_P32_ABS32 1 /* Direct 32 bit. */
|
||||
#define R_AARCH64_P32_COPY 180 /* Copy symbol at runtime. */
|
||||
#define R_AARCH64_P32_GLOB_DAT 181 /* Create GOT entry. */
|
||||
#define R_AARCH64_P32_JUMP_SLOT 182 /* Create PLT entry. */
|
||||
#define R_AARCH64_P32_RELATIVE 183 /* Adjust by program base. */
|
||||
#define R_AARCH64_P32_TLS_DTPMOD 184 /* Module number, 32 bit. */
|
||||
#define R_AARCH64_P32_TLS_DTPREL 185 /* Module-relative offset, 32 bit. */
|
||||
#define R_AARCH64_P32_TLS_TPREL 186 /* TP-relative offset, 32 bit. */
|
||||
#define R_AARCH64_P32_TLSDESC 187 /* TLS Descriptor. */
|
||||
#define R_AARCH64_P32_IRELATIVE 188 /* STT_GNU_IFUNC relocation. */
|
||||
|
||||
/* LP64 AArch64 relocs. */
|
||||
#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
|
||||
#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
|
||||
#define R_AARCH64_ABS16 259 /* Direct 16-bit. */
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include <dl-hwcaps.h>
|
||||
#include <dl-is_dso.h>
|
||||
|
||||
#include <dl-procinfo.h>
|
||||
|
||||
#ifndef LD_SO_CONF
|
||||
# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
|
||||
|
|
29
elf/rtld.c
29
elf/rtld.c
|
@ -35,7 +35,6 @@
|
|||
#include <unsecvars.h>
|
||||
#include <dl-cache.h>
|
||||
#include <dl-osinfo.h>
|
||||
#include <dl-procinfo.h>
|
||||
#include <dl-prop.h>
|
||||
#include <dl-vdso.h>
|
||||
#include <dl-vdso-setup.h>
|
||||
|
@ -1055,13 +1054,9 @@ static void
|
|||
rtld_chain_load (struct link_map *main_map, char *argv0)
|
||||
{
|
||||
/* The dynamic loader run against itself. */
|
||||
const char *rtld_soname
|
||||
= ((const char *) D_PTR (&_dl_rtld_map, l_info[DT_STRTAB])
|
||||
+ _dl_rtld_map.l_info[DT_SONAME]->d_un.d_val);
|
||||
if (main_map->l_info[DT_SONAME] != NULL
|
||||
&& strcmp (rtld_soname,
|
||||
((const char *) D_PTR (main_map, l_info[DT_STRTAB])
|
||||
+ main_map->l_info[DT_SONAME]->d_un.d_val)) == 0)
|
||||
const char *rtld_soname = l_soname (&_dl_rtld_map);
|
||||
if (l_soname (main_map) != NULL
|
||||
&& strcmp (rtld_soname, l_soname (main_map)) == 0)
|
||||
_dl_fatal_printf ("%s: loader cannot load itself\n", rtld_soname);
|
||||
|
||||
/* With DT_NEEDED dependencies, the executable is dynamically
|
||||
|
@ -1632,20 +1627,20 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||
|
||||
/* If the current libname is different from the SONAME, add the
|
||||
latter as well. */
|
||||
if (_dl_rtld_map.l_info[DT_SONAME] != NULL
|
||||
&& strcmp (_dl_rtld_map.l_libname->name,
|
||||
(const char *) D_PTR (&_dl_rtld_map, l_info[DT_STRTAB])
|
||||
+ _dl_rtld_map.l_info[DT_SONAME]->d_un.d_val) != 0)
|
||||
{
|
||||
const char *soname = l_soname (&_dl_rtld_map);
|
||||
if (soname != NULL
|
||||
&& strcmp (_dl_rtld_map.l_libname->name, soname) != 0)
|
||||
{
|
||||
static struct libname_list newname;
|
||||
newname.name = ((char *) D_PTR (&_dl_rtld_map, l_info[DT_STRTAB])
|
||||
+ _dl_rtld_map.l_info[DT_SONAME]->d_un.d_ptr);
|
||||
newname.name = soname;
|
||||
newname.next = NULL;
|
||||
newname.dont_free = 1;
|
||||
|
||||
assert (_dl_rtld_map.l_libname->next == NULL);
|
||||
_dl_rtld_map.l_libname->next = &newname;
|
||||
}
|
||||
}
|
||||
/* The ld.so must be relocated since otherwise loading audit modules
|
||||
will fail since they reuse the very same ld.so. */
|
||||
assert (_dl_rtld_map.l_relocated);
|
||||
|
@ -1658,10 +1653,8 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||
/* If the main map is libc.so, update the base namespace to
|
||||
refer to this map. If libc.so is loaded later, this happens
|
||||
in _dl_map_object_from_fd. */
|
||||
if (main_map->l_info[DT_SONAME] != NULL
|
||||
&& (strcmp (((const char *) D_PTR (main_map, l_info[DT_STRTAB])
|
||||
+ main_map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO)
|
||||
== 0))
|
||||
if (l_soname (main_map) != NULL
|
||||
&& strcmp (l_soname (main_map), LIBC_SO) == 0)
|
||||
GL(dl_ns)[LM_ID_BASE].libc_map = main_map;
|
||||
|
||||
/* Set up our cache of pointers into the hash table. */
|
||||
|
|
|
@ -76,12 +76,13 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
|
|||
|
||||
/* Now that we have the info handy, use the DSO image's soname
|
||||
so this object can be looked up by name. */
|
||||
if (l->l_info[DT_SONAME] != NULL)
|
||||
{
|
||||
char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
|
||||
+ l->l_info[DT_SONAME]->d_un.d_val);
|
||||
const char *dsoname = l_soname (l);
|
||||
if (dsoname != NULL)
|
||||
{
|
||||
l->l_libname->name = dsoname;
|
||||
l->l_name = dsoname;
|
||||
l->l_name = (char *) dsoname;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the vDSO to the object list. */
|
||||
|
|
|
@ -530,10 +530,7 @@ load_shobj (const char *name)
|
|||
printf ("string table: %p\n", result->dynstrtab);
|
||||
|
||||
/* Determine the soname. */
|
||||
if (map->l_info[DT_SONAME] == NULL)
|
||||
result->soname = NULL;
|
||||
else
|
||||
result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
|
||||
result->soname = l_soname (map);
|
||||
if (do_test && result->soname != NULL)
|
||||
printf ("soname: %s\n", result->soname);
|
||||
|
||||
|
|
46
elf/tst-audit-tlsdesc-dlopen2.c
Normal file
46
elf/tst-audit-tlsdesc-dlopen2.c
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* Loading TLS-using modules from auditors (bug 32412). Main program.
|
||||
Copyright (C) 2021-2025 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/xdlfcn.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
puts ("info: start of main program");
|
||||
|
||||
/* Load TLS-using modules, to trigger DTV resizing. The dynamic
|
||||
linker will load them again (requiring their own TLS) because the
|
||||
dlopen calls from the auditor were in the auditing namespace. */
|
||||
for (int i = 1; i <= 19; ++i)
|
||||
{
|
||||
char dso[30];
|
||||
snprintf (dso, sizeof (dso), "tst-tlsmod17a%d.so", i);
|
||||
char sym[30];
|
||||
snprintf (sym, sizeof(sym), "tlsmod17a%d", i);
|
||||
|
||||
void *handle = xdlopen (dso, RTLD_LAZY);
|
||||
int (*func) (void) = xdlsym (handle, sym);
|
||||
/* Trigger TLS allocation. */
|
||||
func ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
59
elf/tst-auditmod-tlsdesc2.c
Normal file
59
elf/tst-auditmod-tlsdesc2.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Loading TLS-using modules from auditors (bug 32412). Audit module.
|
||||
Copyright (C) 2021-2025 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 <link.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int version)
|
||||
{
|
||||
/* Open some modules, to trigger DTV resizing before the switch to
|
||||
the main malloc. */
|
||||
for (int i = 1; i <= 19; ++i)
|
||||
{
|
||||
char dso[30];
|
||||
snprintf (dso, sizeof (dso), "tst-tlsmod17a%d.so", i);
|
||||
char sym[30];
|
||||
snprintf (sym, sizeof(sym), "tlsmod17a%d", i);
|
||||
|
||||
void *handle = dlopen (dso, RTLD_LAZY);
|
||||
if (handle == NULL)
|
||||
{
|
||||
printf ("error: dlmopen from auditor: %s\n", dlerror ());
|
||||
fflush (stdout);
|
||||
_exit (1);
|
||||
}
|
||||
int (*func) (void) = dlsym (handle, sym);
|
||||
if (func == NULL)
|
||||
{
|
||||
printf ("error: dlsym from auditor: %s\n", dlerror ());
|
||||
fflush (stdout);
|
||||
_exit (1);
|
||||
}
|
||||
/* Trigger TLS allocation. */
|
||||
func ();
|
||||
}
|
||||
|
||||
puts ("info: TLS-using modules loaded from auditor");
|
||||
fflush (stdout);
|
||||
|
||||
return LAV_CURRENT;
|
||||
}
|
19
elf/tst-pie-bss-static.c
Normal file
19
elf/tst-pie-bss-static.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* Test static PIE with an empty PT_LOAD segment at offset 0.
|
||||
Copyright (C) 2025 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 "tst-pie-bss.c"
|
|
@ -1,5 +1,5 @@
|
|||
/* x86 version of processor capability information handling macros.
|
||||
Copyright (C) 2017-2025 Free Software Foundation, Inc.
|
||||
/* Test PIE with an empty PT_LOAD segment at offset 0.
|
||||
Copyright (C) 2025 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
|
||||
|
@ -16,11 +16,15 @@
|
|||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _DL_PROCINFO_H
|
||||
#define _DL_PROCINFO_H 1
|
||||
#include <ldsodefs.h>
|
||||
#include <dl-hwcap.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define _DL_HWCAP_COUNT HWCAP_COUNT
|
||||
char bss[0xb5dce8] __attribute__ ((aligned (65536)));
|
||||
|
||||
#endif /* dl-procinfo.h */
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
printf ("Hello\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
68
htl/Makefile
68
htl/Makefile
|
@ -25,21 +25,12 @@ SYSDEPS := lockfile
|
|||
LCLHDRS :=
|
||||
|
||||
libpthread-routines := \
|
||||
pt-barrier-destroy \
|
||||
pt-barrier-init \
|
||||
pt-barrier-wait \
|
||||
pt-barrier \
|
||||
pt-barrierattr-destroy \
|
||||
pt-barrierattr-init \
|
||||
pt-barrierattr-getpshared \
|
||||
pt-barrierattr-setpshared \
|
||||
pt-destroy-specific \
|
||||
pt-init-specific \
|
||||
pt-key-create \
|
||||
pt-key-delete \
|
||||
pt-getspecific \
|
||||
pt-setspecific \
|
||||
pt-once \
|
||||
pt-alloc \
|
||||
pt-create \
|
||||
pt-getattr \
|
||||
|
@ -50,34 +41,9 @@ libpthread-routines := \
|
|||
pt-join \
|
||||
pt-spin-inlines \
|
||||
pt-cleanup \
|
||||
pt-setcancelstate \
|
||||
pt-setcanceltype \
|
||||
pt-testcancel \
|
||||
pt-cancel \
|
||||
pt-mutex-init \
|
||||
pt-mutex-destroy \
|
||||
pt-mutex-lock \
|
||||
pt-mutex-trylock \
|
||||
pt-mutex-timedlock \
|
||||
pt-mutex-unlock \
|
||||
pt-mutex-transfer-np \
|
||||
pt-mutex-getprioceiling \
|
||||
pt-mutex-setprioceiling \
|
||||
pt-mutex-consistent \
|
||||
pt-rwlock-attr \
|
||||
pt-rwlockattr-init \
|
||||
pt-rwlockattr-destroy \
|
||||
pt-rwlockattr-getpshared \
|
||||
pt-rwlockattr-setpshared \
|
||||
pt-rwlock-init \
|
||||
pt-rwlock-destroy \
|
||||
pt-rwlock-rdlock \
|
||||
pt-rwlock-tryrdlock \
|
||||
pt-rwlock-trywrlock \
|
||||
pt-rwlock-wrlock \
|
||||
pt-rwlock-timedrdlock \
|
||||
pt-rwlock-timedwrlock \
|
||||
pt-rwlock-unlock \
|
||||
pt-hurd-cond-wait \
|
||||
pt-hurd-cond-timedwait \
|
||||
pt-stack-alloc \
|
||||
|
@ -172,6 +138,14 @@ routines := \
|
|||
pt-attr-setstack \
|
||||
pt-attr-setstackaddr \
|
||||
pt-attr-setstacksize \
|
||||
pt-barrier \
|
||||
pt-barrier-destroy \
|
||||
pt-barrier-init \
|
||||
pt-barrier-wait \
|
||||
pt-barrierattr-destroy \
|
||||
pt-barrierattr-getpshared \
|
||||
pt-barrierattr-init \
|
||||
pt-barrierattr-setpshared \
|
||||
pt-block \
|
||||
pt-block-intr \
|
||||
pt-cond \
|
||||
|
@ -189,6 +163,15 @@ routines := \
|
|||
pt-condattr-setpshared \
|
||||
pt-getschedparam \
|
||||
pt-mutex-checklocked \
|
||||
pt-mutex-consistent \
|
||||
pt-mutex-destroy \
|
||||
pt-mutex-getprioceiling \
|
||||
pt-mutex-init \
|
||||
pt-mutex-lock \
|
||||
pt-mutex-setprioceiling \
|
||||
pt-mutex-timedlock \
|
||||
pt-mutex-trylock \
|
||||
pt-mutex-unlock \
|
||||
pt-mutexattr-destroy \
|
||||
pt-mutexattr-getprioceiling \
|
||||
pt-mutexattr-getprotocol \
|
||||
|
@ -202,8 +185,25 @@ routines := \
|
|||
pt-mutexattr-setrobust \
|
||||
pt-mutexattr-settype \
|
||||
pt-nthreads \
|
||||
pt-once \
|
||||
pt-pthread_self \
|
||||
pt-rwlock-attr \
|
||||
pt-rwlock-destroy \
|
||||
pt-rwlock-init \
|
||||
pt-rwlock-rdlock \
|
||||
pt-rwlock-timedrdlock \
|
||||
pt-rwlock-timedwrlock \
|
||||
pt-rwlock-tryrdlock \
|
||||
pt-rwlock-trywrlock \
|
||||
pt-rwlock-unlock \
|
||||
pt-rwlock-wrlock \
|
||||
pt-rwlockattr-destroy \
|
||||
pt-rwlockattr-getpshared \
|
||||
pt-rwlockattr-init \
|
||||
pt-rwlockattr-setpshared \
|
||||
pt-self pt-equal \
|
||||
pt-setcancelstate \
|
||||
pt-setcanceltype \
|
||||
pt-setschedparam \
|
||||
pt-sigmask \
|
||||
pt-sigstate \
|
||||
|
|
108
htl/Versions
108
htl/Versions
|
@ -26,6 +26,13 @@ libc {
|
|||
pthread_attr_setscope;
|
||||
pthread_attr_setschedparam;
|
||||
pthread_attr_init;
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
pthread_cond_init;
|
||||
|
@ -38,6 +45,14 @@ libc {
|
|||
pthread_condattr_getpshared;
|
||||
pthread_condattr_setclock;
|
||||
pthread_condattr_setpshared;
|
||||
pthread_mutex_destroy;
|
||||
pthread_mutex_getprioceiling;
|
||||
pthread_mutex_init;
|
||||
pthread_mutex_lock;
|
||||
pthread_mutex_setprioceiling;
|
||||
pthread_mutex_timedlock;
|
||||
pthread_mutex_trylock;
|
||||
pthread_mutex_unlock;
|
||||
pthread_mutexattr_destroy;
|
||||
pthread_mutexattr_getprioceiling;
|
||||
pthread_mutexattr_getprotocol;
|
||||
|
@ -48,6 +63,22 @@ libc {
|
|||
pthread_mutexattr_setprotocol;
|
||||
pthread_mutexattr_setpshared;
|
||||
pthread_mutexattr_settype;
|
||||
pthread_once;
|
||||
pthread_rwlock_destroy;
|
||||
pthread_rwlock_init;
|
||||
pthread_rwlock_rdlock;
|
||||
pthread_rwlock_timedrdlock;
|
||||
pthread_rwlock_timedwrlock;
|
||||
pthread_rwlock_tryrdlock;
|
||||
pthread_rwlock_trywrlock;
|
||||
pthread_rwlock_unlock;
|
||||
pthread_rwlock_wrlock;
|
||||
pthread_rwlockattr_destroy;
|
||||
pthread_rwlockattr_getpshared;
|
||||
pthread_rwlockattr_init;
|
||||
pthread_rwlockattr_setpshared;
|
||||
pthread_setcancelstate;
|
||||
pthread_setcanceltype;
|
||||
pthread_sigmask;
|
||||
}
|
||||
|
||||
|
@ -65,7 +96,7 @@ libc {
|
|||
pthread_equal;
|
||||
pthread_exit; pthread_getschedparam; pthread_setschedparam;
|
||||
pthread_mutex_destroy; pthread_mutex_init;
|
||||
pthread_mutex_lock; pthread_mutex_trylock; pthread_mutex_unlock;
|
||||
pthread_mutex_lock; pthread_mutex_unlock;
|
||||
pthread_self; pthread_setcancelstate; pthread_setcanceltype;
|
||||
__pthread_get_cleanup_stack;
|
||||
}
|
||||
|
@ -79,8 +110,14 @@ libc {
|
|||
|
||||
pthread_cond_clockwait;
|
||||
|
||||
pthread_mutex_clocklock;
|
||||
|
||||
pthread_mutex_consistent; pthread_mutex_consistent_np;
|
||||
|
||||
pthread_mutexattr_getrobust; pthread_mutexattr_getrobust_np;
|
||||
pthread_mutexattr_setrobust; pthread_mutexattr_setrobust_np;
|
||||
|
||||
pthread_rwlock_clockrdlock; pthread_rwlock_clockwrlock;
|
||||
}
|
||||
|
||||
GLIBC_2.41 {
|
||||
|
@ -109,6 +146,35 @@ libc {
|
|||
pthread_sigmask;
|
||||
}
|
||||
|
||||
GLIBC_2.42 {
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_mutex_consistent; pthread_mutex_consistent_np;
|
||||
pthread_mutex_getprioceiling;
|
||||
pthread_mutex_setprioceiling;
|
||||
pthread_rwlock_destroy;
|
||||
pthread_mutex_trylock;
|
||||
pthread_once;
|
||||
pthread_rwlock_clockrdlock;
|
||||
pthread_rwlock_clockwrlock;
|
||||
pthread_rwlock_init;
|
||||
pthread_rwlock_rdlock;
|
||||
pthread_rwlock_timedrdlock;
|
||||
pthread_rwlock_timedwrlock;
|
||||
pthread_rwlock_wrlock;
|
||||
pthread_rwlock_tryrdlock;
|
||||
pthread_rwlock_trywrlock;
|
||||
pthread_rwlock_unlock;
|
||||
pthread_rwlockattr_destroy;
|
||||
pthread_rwlockattr_getpshared;
|
||||
pthread_rwlockattr_init;
|
||||
pthread_rwlockattr_setpshared;
|
||||
}
|
||||
|
||||
GLIBC_PRIVATE {
|
||||
__libc_alloca_cutoff;
|
||||
|
@ -127,6 +193,7 @@ libc {
|
|||
__pthread_attr_setstacksize;
|
||||
__pthread_attr_setstackaddr;
|
||||
__pthread_attr_setstack;
|
||||
__pthread_setcancelstate;
|
||||
__pthread_cond_broadcast;
|
||||
__pthread_cond_destroy;
|
||||
__pthread_cond_init;
|
||||
|
@ -137,9 +204,16 @@ libc {
|
|||
__pthread_condattr_init;
|
||||
__pthread_default_condattr;
|
||||
__pthread_mutex_checklocked;
|
||||
__pthread_mutex_destroy;
|
||||
__pthread_mutex_init;
|
||||
__pthread_mutex_lock;
|
||||
__pthread_mutex_timedlock;
|
||||
__pthread_mutex_trylock;
|
||||
__pthread_mutex_unlock;
|
||||
__pthread_mutexattr_destroy;
|
||||
__pthread_mutexattr_init;
|
||||
__pthread_mutexattr_settype;
|
||||
__pthread_once;
|
||||
__pthread_sigstate;
|
||||
__pthread_sigstate_destroy;
|
||||
__pthread_sigmask;
|
||||
|
@ -174,10 +248,6 @@ libpthread {
|
|||
|
||||
pthread_atfork;
|
||||
|
||||
pthread_barrier_destroy; pthread_barrier_init; pthread_barrier_wait;
|
||||
pthread_barrierattr_destroy; pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init; pthread_barrierattr_setpshared;
|
||||
|
||||
pthread_cancel;
|
||||
|
||||
pthread_create; pthread_detach; pthread_exit;
|
||||
|
@ -195,22 +265,8 @@ libpthread {
|
|||
pthread_kill;
|
||||
__pthread_kill;
|
||||
|
||||
pthread_mutex_destroy; pthread_mutex_getprioceiling;
|
||||
pthread_mutex_init; pthread_mutex_lock; pthread_mutex_setprioceiling;
|
||||
pthread_mutex_timedlock; pthread_mutex_transfer_np;
|
||||
pthread_mutex_trylock; pthread_mutex_unlock;
|
||||
pthread_mutex_transfer_np;
|
||||
|
||||
pthread_once;
|
||||
|
||||
pthread_rwlock_destroy; pthread_rwlock_init; pthread_rwlock_rdlock;
|
||||
pthread_rwlock_timedrdlock; pthread_rwlock_timedwrlock;
|
||||
pthread_rwlock_tryrdlock; pthread_rwlock_trywrlock;
|
||||
pthread_rwlock_unlock; pthread_rwlock_wrlock;
|
||||
|
||||
pthread_rwlockattr_destroy; pthread_rwlockattr_getpshared;
|
||||
pthread_rwlockattr_init; pthread_rwlockattr_setpshared;
|
||||
|
||||
pthread_setcancelstate; pthread_setcanceltype;
|
||||
pthread_setconcurrency;
|
||||
pthread_setschedprio; pthread_setspecific;
|
||||
|
||||
|
@ -239,11 +295,6 @@ libpthread {
|
|||
cnd_broadcast; cnd_destroy; cnd_init; cnd_signal; cnd_timedwait; cnd_wait;
|
||||
tss_create; tss_delete; tss_get; tss_set;
|
||||
|
||||
pthread_mutex_consistent; pthread_mutex_consistent_np;
|
||||
pthread_mutex_clocklock;
|
||||
|
||||
pthread_rwlock_clockrdlock; pthread_rwlock_clockwrlock;
|
||||
|
||||
pthread_tryjoin_np; pthread_timedjoin_np; pthread_clockjoin_np;
|
||||
|
||||
sem_clockwait;
|
||||
|
@ -267,14 +318,7 @@ libpthread {
|
|||
__pthread_getspecific;
|
||||
__pthread_setspecific;
|
||||
__pthread_getattr_np;
|
||||
__pthread_mutex_init;
|
||||
__pthread_mutex_destroy;
|
||||
__pthread_mutex_timedlock;
|
||||
__pthread_enable_asynccancel;
|
||||
__pthread_disable_asynccancel;
|
||||
|
||||
__pthread_mutex_lock; __pthread_mutex_trylock; __pthread_mutex_unlock;
|
||||
_pthread_mutex_lock; _pthread_mutex_trylock; _pthread_mutex_unlock;
|
||||
_pthread_rwlock_destroy; _pthread_rwlock_init;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,21 +58,5 @@ FORWARD_NORETURN (__pthread_exit, void, (void *retval), (retval),
|
|||
exit (EXIT_SUCCESS))
|
||||
strong_alias (__pthread_exit, pthread_exit);
|
||||
|
||||
FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0)
|
||||
|
||||
FORWARD (pthread_mutex_init,
|
||||
(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr),
|
||||
(mutex, mutexattr), 0)
|
||||
|
||||
FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0)
|
||||
|
||||
FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0)
|
||||
|
||||
FORWARD (__pthread_setcancelstate, (int state, int *oldstate),
|
||||
(state, oldstate), 0)
|
||||
strong_alias (__pthread_setcancelstate, pthread_setcancelstate);
|
||||
|
||||
FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0)
|
||||
|
||||
FORWARD2 (__pthread_get_cleanup_stack, struct __pthread_cancelation_handler **,
|
||||
(void), (), return &__pthread_cleanup_stack);
|
||||
|
|
|
@ -203,10 +203,7 @@ __pthread_create_internal (struct __pthread **thread,
|
|||
creating thread. The set of signals pending for the new thread
|
||||
shall be empty." If the current thread is not a pthread then we
|
||||
just inherit the process' sigmask. */
|
||||
if (GL (dl_pthread_num_threads) == 1)
|
||||
err = __sigprocmask (0, 0, &pthread->init_sigset);
|
||||
else
|
||||
err = __pthread_sigstate (_pthread_self (), 0, 0, &pthread->init_sigset, 0);
|
||||
err = __pthread_sigmask (0, 0, &pthread->init_sigset);
|
||||
assert_perror (err);
|
||||
|
||||
if (start_routine)
|
||||
|
|
|
@ -28,18 +28,8 @@
|
|||
#if IS_IN (libpthread)
|
||||
static const struct pthread_functions pthread_functions = {
|
||||
.ptr___pthread_exit = __pthread_exit,
|
||||
.ptr_pthread_mutex_destroy = __pthread_mutex_destroy,
|
||||
.ptr_pthread_mutex_init = __pthread_mutex_init,
|
||||
.ptr_pthread_mutex_lock = __pthread_mutex_lock,
|
||||
.ptr_pthread_mutex_trylock = __pthread_mutex_trylock,
|
||||
.ptr_pthread_mutex_unlock = __pthread_mutex_unlock,
|
||||
.ptr___pthread_setcancelstate = __pthread_setcancelstate,
|
||||
.ptr_pthread_setcanceltype = __pthread_setcanceltype,
|
||||
.ptr___pthread_get_cleanup_stack = __pthread_get_cleanup_stack,
|
||||
.ptr_pthread_once = __pthread_once,
|
||||
.ptr_pthread_rwlock_rdlock = __pthread_rwlock_rdlock,
|
||||
.ptr_pthread_rwlock_wrlock = __pthread_rwlock_wrlock,
|
||||
.ptr_pthread_rwlock_unlock = __pthread_rwlock_unlock,
|
||||
.ptr___pthread_key_create = __pthread_key_create,
|
||||
.ptr___pthread_getspecific = __pthread_getspecific,
|
||||
.ptr___pthread_setspecific = __pthread_setspecific,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
#include <pt-internal.h>
|
||||
|
||||
int
|
||||
|
@ -42,5 +42,9 @@ __pthread_setcancelstate (int state, int *oldstate)
|
|||
|
||||
return 0;
|
||||
}
|
||||
libc_hidden_def (__pthread_setcancelstate)
|
||||
versioned_symbol (libc, __pthread_setcancelstate, pthread_setcancelstate, GLIBC_2_21);
|
||||
|
||||
weak_alias (__pthread_setcancelstate, pthread_setcancelstate);
|
||||
#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_12, GLIBC_2_21)
|
||||
compat_symbol (libc, __pthread_setcancelstate, pthread_setcancelstate, GLIBC_2_12);
|
||||
#endif
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <shlib-compat.h>
|
||||
#include <pt-internal.h>
|
||||
|
||||
int
|
||||
|
@ -42,5 +42,9 @@ __pthread_setcanceltype (int type, int *oldtype)
|
|||
|
||||
return 0;
|
||||
}
|
||||
libc_hidden_def (__pthread_setcanceltype)
|
||||
versioned_symbol (libc, __pthread_setcanceltype, pthread_setcanceltype, GLIBC_2_21);
|
||||
|
||||
weak_alias (__pthread_setcanceltype, pthread_setcanceltype);
|
||||
#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_12, GLIBC_2_21)
|
||||
compat_symbol (libc, __pthread_setcanceltype, pthread_setcanceltype, GLIBC_2_12);
|
||||
#endif
|
||||
|
|
|
@ -19,15 +19,14 @@
|
|||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <shlib-compat.h>
|
||||
#include <hurd/signal.h>
|
||||
#include <pt-internal.h>
|
||||
|
||||
int
|
||||
__pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
|
||||
{
|
||||
struct __pthread *self = _pthread_self ();
|
||||
|
||||
/* Do not clear SELF's pending signals. */
|
||||
return __pthread_sigstate (self, how, set, oset, 0);
|
||||
return __sigthreadmask (_hurd_self_sigstate (), how, set, oset, 0);
|
||||
}
|
||||
libc_hidden_def (__pthread_sigmask)
|
||||
versioned_symbol (libc, __pthread_sigmask, pthread_sigmask, GLIBC_2_41);
|
||||
|
|
|
@ -131,6 +131,7 @@ sig = \
|
|||
longjmp-ts \
|
||||
preempt-sig \
|
||||
siginfo \
|
||||
sigthreadmask \
|
||||
sigunwind \
|
||||
thread-cancel \
|
||||
thread-self \
|
||||
|
|
|
@ -138,7 +138,7 @@ error_t __hurd_file_name_lookup_retry (error_t (*use_init_port)
|
|||
string_t retry_name,
|
||||
mach_port_t *result),
|
||||
enum retry_type doretry,
|
||||
char retryname[1024],
|
||||
string_t retryname,
|
||||
int flags, mode_t mode,
|
||||
file_t *result);
|
||||
error_t hurd_file_name_lookup_retry (error_t (*use_init_port)
|
||||
|
@ -152,7 +152,7 @@ error_t hurd_file_name_lookup_retry (error_t (*use_init_port)
|
|||
string_t retry_name,
|
||||
mach_port_t *result),
|
||||
enum retry_type doretry,
|
||||
char retryname[1024],
|
||||
string_t retryname,
|
||||
int flags, mode_t mode,
|
||||
file_t *result);
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ __lll_abstimed_lock (void *ptr,
|
|||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__lll_abstimed_lock)
|
||||
|
||||
/* Robust locks. */
|
||||
|
||||
|
@ -157,6 +158,7 @@ __lll_robust_lock (void *ptr, int flags)
|
|||
}
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__lll_robust_lock)
|
||||
|
||||
int
|
||||
__lll_robust_abstimed_lock (void *ptr,
|
||||
|
@ -206,6 +208,7 @@ __lll_robust_abstimed_lock (void *ptr,
|
|||
}
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__lll_robust_abstimed_lock)
|
||||
|
||||
int
|
||||
__lll_robust_trylock (void *ptr)
|
||||
|
@ -225,6 +228,7 @@ __lll_robust_trylock (void *ptr)
|
|||
|
||||
return EBUSY;
|
||||
}
|
||||
libc_hidden_def (__lll_robust_trylock)
|
||||
|
||||
void
|
||||
__lll_robust_unlock (void *ptr, int flags)
|
||||
|
@ -241,3 +245,5 @@ __lll_robust_unlock (void *ptr, int flags)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
libc_hidden_def (__lll_robust_unlock)
|
||||
|
|
|
@ -68,23 +68,27 @@ extern int __lll_abstimed_xwait (void *__ptr, int __lo, int __hi,
|
|||
using clock CLK. */
|
||||
extern int __lll_abstimed_lock (void *__ptr,
|
||||
const struct timespec *__tsp, int __flags, int __clk);
|
||||
libc_hidden_proto (__lll_abstimed_lock)
|
||||
|
||||
/* Acquire the lock at PTR, but return with an error if
|
||||
the process containing the owner thread dies. */
|
||||
extern int __lll_robust_lock (void *__ptr, int __flags);
|
||||
#define lll_robust_lock(var, flags) \
|
||||
__lll_robust_lock (&(var), flags)
|
||||
libc_hidden_proto (__lll_robust_lock)
|
||||
|
||||
/* Same as '__lll_robust_lock', but only block until TSP
|
||||
elapses, using clock CLK. */
|
||||
extern int __lll_robust_abstimed_lock (void *__ptr,
|
||||
const struct timespec *__tsp, int __flags, int __clk);
|
||||
libc_hidden_proto (__lll_robust_abstimed_lock)
|
||||
|
||||
/* Same as '__lll_robust_lock', but return with an error
|
||||
if the lock cannot be acquired without blocking. */
|
||||
extern int __lll_robust_trylock (void *__ptr);
|
||||
#define lll_robust_trylock(var) \
|
||||
__lll_robust_trylock (&(var))
|
||||
libc_hidden_proto (__lll_robust_trylock)
|
||||
|
||||
/* Wake one or more threads waiting on address PTR,
|
||||
setting its value to VAL before doing so. */
|
||||
|
@ -96,6 +100,7 @@ extern int __lll_robust_trylock (void *__ptr);
|
|||
extern void __lll_robust_unlock (void *__ptr, int __flags);
|
||||
#define lll_robust_unlock(var, flags) \
|
||||
__lll_robust_unlock (&(var), flags)
|
||||
libc_hidden_proto (__lll_robust_unlock)
|
||||
|
||||
/* Rearrange threads waiting on address SRC to instead wait on
|
||||
DST, waking one of them if WAIT_ONE is non-zero. */
|
||||
|
|
|
@ -51,7 +51,7 @@ __hurd_file_name_lookup (error_t (*use_init_port)
|
|||
{
|
||||
error_t err;
|
||||
enum retry_type doretry;
|
||||
char retryname[1024]; /* XXX string_t LOSES! */
|
||||
string_t retryname;
|
||||
int startport;
|
||||
|
||||
error_t lookup_op (mach_port_t startdir)
|
||||
|
|
|
@ -1611,18 +1611,31 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
|
|||
static void
|
||||
reauth_proc (mach_port_t new)
|
||||
{
|
||||
mach_port_t ref, ignore;
|
||||
error_t err;
|
||||
mach_port_t ref, newproc;
|
||||
|
||||
ref = __mach_reply_port ();
|
||||
if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
|
||||
err = HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
|
||||
__proc_reauthenticate (port, ref,
|
||||
MACH_MSG_TYPE_MAKE_SEND)
|
||||
|| __auth_user_authenticate (new, ref,
|
||||
MACH_MSG_TYPE_MAKE_SEND,
|
||||
&ignore))
|
||||
&& ignore != MACH_PORT_NULL)
|
||||
__mach_port_deallocate (__mach_task_self (), ignore);
|
||||
MACH_MSG_TYPE_MAKE_SEND));
|
||||
if (err)
|
||||
{
|
||||
__mach_port_destroy (__mach_task_self (), ref);
|
||||
return;
|
||||
}
|
||||
|
||||
err = __auth_user_authenticate (new, ref,
|
||||
MACH_MSG_TYPE_MAKE_SEND,
|
||||
&newproc);
|
||||
__mach_port_destroy (__mach_task_self (), ref);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
if (newproc == MACH_PORT_NULL)
|
||||
{
|
||||
/* Old versions of the proc server did not recreate the process
|
||||
port when reauthenticating, and passed MACH_PORT_NULL through
|
||||
the auth server. That must be what we're dealing with. */
|
||||
|
||||
/* Set the owner of the process here too. */
|
||||
__mutex_lock (&_hurd_id.lock);
|
||||
|
@ -1634,6 +1647,18 @@ reauth_proc (mach_port_t new)
|
|||
!_hurd_id.gen.nuids));
|
||||
__mutex_unlock (&_hurd_id.lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
err = __proc_reauthenticate_complete (newproc);
|
||||
if (err)
|
||||
{
|
||||
__mach_port_deallocate (__mach_task_self (), newproc);
|
||||
return;
|
||||
}
|
||||
|
||||
_hurd_port_set (&_hurd_ports[INIT_PORT_PROC], newproc);
|
||||
|
||||
(void) &reauth_proc; /* Silence compiler warning. */
|
||||
}
|
||||
text_set_element (_hurd_reauth_hook, reauth_proc);
|
||||
|
|
|
@ -40,7 +40,7 @@ __file_name_lookup_at (int fd, int at_flags,
|
|||
if (empty != 0 && file_name[0] == '\0')
|
||||
{
|
||||
enum retry_type doretry;
|
||||
char retryname[1024]; /* XXX string_t LOSES! */
|
||||
string_t retryname;
|
||||
|
||||
err = HURD_DPORT_USE (fd, __dir_lookup (port, "", flags, mode,
|
||||
&doretry, retryname,
|
||||
|
|
|
@ -53,7 +53,7 @@ __hurd_file_name_lookup_retry (error_t (*use_init_port)
|
|||
retry_type *do_retry, string_t retry_name,
|
||||
mach_port_t *result),
|
||||
enum retry_type doretry,
|
||||
char retryname[1024],
|
||||
string_t retryname,
|
||||
int flags, mode_t mode,
|
||||
file_t *result)
|
||||
{
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include <link.h> /* For ElfW. */
|
||||
#include <stdbool.h>
|
||||
|
||||
extern __typeof (_dl_find_object) __dl_find_object;
|
||||
hidden_proto (__dl_find_object)
|
||||
rtld_hidden_proto (_dl_find_object)
|
||||
|
||||
/* Internally used flag. */
|
||||
#define __RTLD_DLOPEN 0x80000000
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
Each free routines must be explicit listed below. */
|
||||
|
||||
/* From libc.so. */
|
||||
extern void __dl_libc_freemem (void) attribute_hidden;
|
||||
extern void __hdestroy (void) attribute_hidden;
|
||||
extern void __gconv_cache_freemem (void) attribute_hidden;
|
||||
extern void __gconv_conf_freemem (void) attribute_hidden;
|
||||
|
|
|
@ -69,6 +69,8 @@ again:
|
|||
if (*cp == 'x' || *cp == 'X')
|
||||
digit = 0, base = 16, cp++;
|
||||
while ((c = *cp) != 0) {
|
||||
if (val > 0xff)
|
||||
return (INADDR_NONE);
|
||||
if (isdigit(c)) {
|
||||
if (base == 8 && (c == '8' || c == '9'))
|
||||
return (INADDR_NONE);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#endif
|
||||
|
||||
#include <bits/types.h>
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
struct _IO_FILE;
|
||||
struct _IO_marker;
|
||||
|
@ -97,8 +98,15 @@ struct _IO_FILE_complete
|
|||
void *_freeres_buf;
|
||||
struct _IO_FILE **_prevchain;
|
||||
int _mode;
|
||||
#if __WORDSIZE == 64
|
||||
int _unused3;
|
||||
#endif
|
||||
__uint64_t _total_written;
|
||||
#if __WORDSIZE == 32
|
||||
int _unused3;
|
||||
#endif
|
||||
/* Make sure we don't get into trouble again. */
|
||||
char _unused2[15 * sizeof (int) - 5 * sizeof (void *)];
|
||||
char _unused2[12 * sizeof (int) - 5 * sizeof (void *)];
|
||||
};
|
||||
|
||||
/* These macros are used by bits/stdio.h and internal headers. */
|
||||
|
|
|
@ -127,15 +127,48 @@ _IO_new_file_init (struct _IO_FILE_plus *fp)
|
|||
int
|
||||
_IO_new_file_close_it (FILE *fp)
|
||||
{
|
||||
int write_status;
|
||||
int flush_status = 0;
|
||||
if (!_IO_file_is_open (fp))
|
||||
return EOF;
|
||||
|
||||
if ((fp->_flags & _IO_NO_WRITES) == 0
|
||||
&& (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
|
||||
write_status = _IO_do_flush (fp);
|
||||
flush_status = _IO_do_flush (fp);
|
||||
else if (fp->_fileno >= 0
|
||||
/* If this is the active handle, we must seek the
|
||||
underlying open file description (possibly shared with
|
||||
other file descriptors that remain open) to the correct
|
||||
offset. But if this stream is in a state such that some
|
||||
other handle might have become the active handle, then
|
||||
(a) at the time it entered that state, the underlying
|
||||
open file description had the correct offset, and (b)
|
||||
seeking the underlying open file description, even to
|
||||
its newly determined current offset, is not safe because
|
||||
it can race with operations on a different active
|
||||
handle. So check here for cases where it is necessary
|
||||
to seek, while avoiding seeking in cases where it is
|
||||
unsafe to do so. */
|
||||
&& (_IO_in_backup (fp)
|
||||
|| (fp->_mode <= 0 && fp->_IO_read_ptr < fp->_IO_read_end)
|
||||
|| (_IO_vtable_offset (fp) == 0
|
||||
&& fp->_mode > 0 && (fp->_wide_data->_IO_read_ptr
|
||||
< fp->_wide_data->_IO_read_end))))
|
||||
{
|
||||
off64_t o = _IO_SEEKOFF (fp, 0, _IO_seek_cur, 0);
|
||||
if (o == EOF)
|
||||
{
|
||||
if (errno != ESPIPE)
|
||||
flush_status = EOF;
|
||||
}
|
||||
else
|
||||
write_status = 0;
|
||||
{
|
||||
if (_IO_in_backup (fp))
|
||||
o -= fp->_IO_save_end - fp->_IO_save_base;
|
||||
flush_status = (_IO_SYSSEEK (fp, o, SEEK_SET) < 0 && errno != ESPIPE
|
||||
? EOF
|
||||
: 0);
|
||||
}
|
||||
}
|
||||
|
||||
_IO_unsave_markers (fp);
|
||||
|
||||
|
@ -160,7 +193,7 @@ _IO_new_file_close_it (FILE *fp)
|
|||
fp->_fileno = -1;
|
||||
fp->_offset = _IO_pos_BAD;
|
||||
|
||||
return close_status ? close_status : write_status;
|
||||
return close_status ? close_status : flush_status;
|
||||
}
|
||||
libc_hidden_ver (_IO_new_file_close_it, _IO_file_close_it)
|
||||
|
||||
|
@ -799,6 +832,11 @@ _IO_new_file_sync (FILE *fp)
|
|||
if (fp->_IO_write_ptr > fp->_IO_write_base)
|
||||
if (_IO_do_flush(fp)) return EOF;
|
||||
delta = fp->_IO_read_ptr - fp->_IO_read_end;
|
||||
if (_IO_in_backup (fp))
|
||||
{
|
||||
_IO_switch_to_main_get_area (fp);
|
||||
delta += fp->_IO_read_ptr - fp->_IO_read_end;
|
||||
}
|
||||
if (delta != 0)
|
||||
{
|
||||
off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
|
||||
|
@ -820,17 +858,21 @@ libc_hidden_ver (_IO_new_file_sync, _IO_file_sync)
|
|||
int
|
||||
_IO_file_sync_mmap (FILE *fp)
|
||||
{
|
||||
off64_t o = fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
|
||||
if (fp->_IO_read_ptr != fp->_IO_read_end)
|
||||
{
|
||||
if (__lseek64 (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base,
|
||||
SEEK_SET)
|
||||
!= fp->_IO_read_ptr - fp->_IO_buf_base)
|
||||
if (_IO_in_backup (fp))
|
||||
{
|
||||
_IO_switch_to_main_get_area (fp);
|
||||
o -= fp->_IO_read_end - fp->_IO_read_base;
|
||||
}
|
||||
if (__lseek64 (fp->_fileno, o, SEEK_SET) != o)
|
||||
{
|
||||
fp->_flags |= _IO_ERR_SEEN;
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base;
|
||||
fp->_offset = o;
|
||||
fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1068,11 +1110,18 @@ _IO_file_seekoff_mmap (FILE *fp, off64_t offset, int dir, int mode)
|
|||
if (mode == 0)
|
||||
return fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
|
||||
|
||||
if (_IO_in_backup (fp))
|
||||
{
|
||||
if (dir == _IO_seek_cur)
|
||||
offset += fp->_IO_read_ptr - fp->_IO_read_end;
|
||||
_IO_switch_to_main_get_area (fp);
|
||||
}
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case _IO_seek_cur:
|
||||
/* Adjust for read-ahead (bytes is buffer). */
|
||||
offset += fp->_IO_read_ptr - fp->_IO_read_base;
|
||||
offset += fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
|
||||
break;
|
||||
case _IO_seek_set:
|
||||
break;
|
||||
|
@ -1185,6 +1234,7 @@ _IO_new_file_write (FILE *f, const void *data, ssize_t n)
|
|||
f->_flags |= _IO_ERR_SEEN;
|
||||
break;
|
||||
}
|
||||
f->_total_written += count;
|
||||
to_do -= count;
|
||||
data = (void *) ((char *) data + count);
|
||||
}
|
||||
|
|
|
@ -611,6 +611,7 @@ _IO_no_init (FILE *fp, int flags, int orientation,
|
|||
stream. */
|
||||
fp->_wide_data = (struct _IO_wide_data *) -1L;
|
||||
fp->_freeres_list = NULL;
|
||||
fp->_total_written = 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -730,6 +731,13 @@ _IO_flush_all (void)
|
|||
)
|
||||
&& _IO_OVERFLOW (fp, EOF) == EOF)
|
||||
result = EOF;
|
||||
if (_IO_fileno (fp) >= 0
|
||||
&& ((fp->_mode <= 0 && fp->_IO_read_ptr < fp->_IO_read_end)
|
||||
|| (_IO_vtable_offset (fp) == 0
|
||||
&& fp->_mode > 0 && (fp->_wide_data->_IO_read_ptr
|
||||
< fp->_wide_data->_IO_read_end)))
|
||||
&& _IO_SYNC (fp) != 0)
|
||||
result = EOF;
|
||||
|
||||
_IO_funlockfile (fp);
|
||||
run_fp = NULL;
|
||||
|
|
|
@ -36,13 +36,42 @@ _IO_fwrite (const void *buf, size_t size, size_t count, FILE *fp)
|
|||
return 0;
|
||||
_IO_acquire_lock (fp);
|
||||
if (_IO_vtable_offset (fp) != 0 || _IO_fwide (fp, -1) == -1)
|
||||
{
|
||||
/* Compute actually written bytes plus pending buffer
|
||||
contents. */
|
||||
uint64_t original_total_written
|
||||
= fp->_total_written + (fp->_IO_write_ptr - fp->_IO_write_base);
|
||||
written = _IO_sputn (fp, (const char *) buf, request);
|
||||
if (written == EOF)
|
||||
{
|
||||
/* An error happened and we need to find the appropriate return
|
||||
value. There 3 possible scenarios:
|
||||
1. If the number of bytes written is between 0..[buffer content],
|
||||
we need to return 0 because none of the bytes from this
|
||||
request have been written;
|
||||
2. If the number of bytes written is between
|
||||
[buffer content]+1..request-1, that means we managed to write
|
||||
data requested in this fwrite call;
|
||||
3. We might have written all the requested data and got an error
|
||||
anyway. We can't return success, which means we still have to
|
||||
return less than request. */
|
||||
if (fp->_total_written > original_total_written)
|
||||
{
|
||||
written = fp->_total_written - original_total_written;
|
||||
/* If everything was reported as written and somehow an
|
||||
error occurred afterwards, avoid reporting success. */
|
||||
if (written == request)
|
||||
--written;
|
||||
}
|
||||
else
|
||||
/* Only already-pending buffer contents was written. */
|
||||
written = 0;
|
||||
}
|
||||
}
|
||||
_IO_release_lock (fp);
|
||||
/* We have written all of the input in case the return value indicates
|
||||
this or EOF is returned. The latter is a special case where we
|
||||
simply did not manage to flush the buffer. But the data is in the
|
||||
buffer and therefore written as far as fwrite is concerned. */
|
||||
if (written == request || written == EOF)
|
||||
this. */
|
||||
if (written == request)
|
||||
return count;
|
||||
else
|
||||
return written / size;
|
||||
|
|
|
@ -604,9 +604,6 @@ extern int fgetc_unlocked (FILE *__stream) __nonnull ((1));
|
|||
/* Write a character to STREAM.
|
||||
|
||||
These functions are possible cancellation points and therefore not
|
||||
marked with __THROW.
|
||||
|
||||
These functions is a possible cancellation point and therefore not
|
||||
marked with __THROW. */
|
||||
extern int fputc (int __c, FILE *__stream) __nonnull ((2));
|
||||
extern int putc (int __c, FILE *__stream) __nonnull ((2));
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
vm_size_t
|
||||
__mig_strncpy (char *dst, const char *src, vm_size_t len)
|
||||
{
|
||||
return __stpncpy (dst, src, len) - dst;
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
char *end = __stpncpy (dst, src, len - 1);
|
||||
vm_size_t ret = end - dst;
|
||||
/* Null terminate the string. */
|
||||
if (ret == len - 1)
|
||||
*end = '\0';
|
||||
return ret;
|
||||
}
|
||||
weak_alias (__mig_strncpy, mig_strncpy)
|
||||
|
|
|
@ -4005,6 +4005,9 @@ _int_malloc (mstate av, size_t bytes)
|
|||
{
|
||||
if (__glibc_unlikely (misaligned_chunk (tc_victim)))
|
||||
malloc_printerr ("malloc(): unaligned fastbin chunk detected 3");
|
||||
size_t victim_tc_idx = csize2tidx (chunksize (tc_victim));
|
||||
if (__glibc_unlikely (tc_idx != victim_tc_idx))
|
||||
malloc_printerr ("malloc(): chunk size mismatch in fastbin");
|
||||
if (SINGLE_THREAD_P)
|
||||
*fb = REVEAL_PTR (tc_victim->fd);
|
||||
else
|
||||
|
@ -4241,6 +4244,9 @@ _int_malloc (mstate av, size_t bytes)
|
|||
fwd = bck;
|
||||
bck = bck->bk;
|
||||
|
||||
if (__glibc_unlikely (fwd->fd->bk_nextsize->fd_nextsize != fwd->fd))
|
||||
malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
|
||||
|
||||
victim->fd_nextsize = fwd->fd;
|
||||
victim->bk_nextsize = fwd->fd->bk_nextsize;
|
||||
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
# pragma weak __nss_module_freeres
|
||||
# pragma weak __nss_action_freeres
|
||||
# pragma weak __nss_database_freeres
|
||||
# pragma weak __dl_libc_freemem
|
||||
# pragma weak __hdestroy
|
||||
# pragma weak __gconv_cache_freemem
|
||||
# pragma weak __gconv_conf_freemem
|
||||
|
@ -136,7 +135,6 @@ __libc_freeres (void)
|
|||
_IO_cleanup ();
|
||||
|
||||
/* We run the resource freeing after IO cleanup. */
|
||||
call_function_static_weak (__dl_libc_freemem);
|
||||
call_function_static_weak (__hdestroy);
|
||||
call_function_static_weak (__gconv_cache_freemem);
|
||||
call_function_static_weak (__gconv_conf_freemem);
|
||||
|
|
|
@ -966,13 +966,25 @@ functionality is available on commercial systems.
|
|||
|
||||
@Theglibc{} includes by reference the Linux man-pages
|
||||
@value{man_pages_version} documentation to document the listed
|
||||
syscalls for the Linux kernel. For reference purposes only the latest
|
||||
syscalls for the Linux kernel. For reference purposes only, the latest
|
||||
@uref{https://www.kernel.org/doc/man-pages/,Linux man-pages Project}
|
||||
documentation can be accessed from the
|
||||
@uref{https://www.kernel.org,Linux kernel} website. Where the syscall
|
||||
has more specific documentation in this manual that more specific
|
||||
documentation is considered authoritative.
|
||||
|
||||
Throughout this manual, when we refer to a man page, for example:
|
||||
@quotation
|
||||
@manpageurl{sendmsg,2}
|
||||
@end quotation
|
||||
@noindent
|
||||
we are referring primarily to the specific version noted above (the
|
||||
``normative'' version), typically accessed by running (for example)
|
||||
@code{man 2 sendmsg} on a system with that version installed. For
|
||||
convenience, we will also link to the online latest copy of the man
|
||||
pages, but keep in mind that version will almost always be newer than,
|
||||
and thus different than, the normative version noted above.
|
||||
|
||||
Additional details on the Linux system call interface can be found in
|
||||
@xref{System Calls}.
|
||||
|
||||
|
|
|
@ -46,71 +46,6 @@ by @theglibc{}.
|
|||
@end deftypefun
|
||||
|
||||
@subsection POSIX Semaphores
|
||||
|
||||
@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value})
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
|
||||
@c Does not atomically update sem_t therefore AC-unsafe
|
||||
@c because it can leave sem_t partially initialized.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_destroy (sem_t *@var{sem})
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
@c Function does nothing and is therefore always safe.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {sem_t *} sem_open (const char *@var{name}, int @var{oflag}, ...)
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acuinit{}}}
|
||||
@c pthread_once asuinit
|
||||
@c
|
||||
@c We are AC-Unsafe because we use pthread_once to initialize
|
||||
@c a global variable that holds the location of the mounted
|
||||
@c shmfs on Linux.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_close (sem_t *@var{sem})
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
|
||||
@c lll_lock asulock aculock
|
||||
@c twalk mtsrace{:root}
|
||||
@c
|
||||
@c We are AS-unsafe because we take a non-recursive lock.
|
||||
@c We are AC-unsafe because several internal data structures
|
||||
@c are not updated atomically.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_unlink (const char *@var{name})
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acucorrupt{}}}
|
||||
@c pthread_once asuinit acucorrupt aculock
|
||||
@c mempcpy acucorrupt
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_wait (sem_t *@var{sem})
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
|
||||
@c atomic_fetch_add_relaxed (nwaiters) acucorrupt
|
||||
@c
|
||||
@c Given the use atomic operations this function seems
|
||||
@c to be AS-safe. It is AC-unsafe because there is still
|
||||
@c a window between atomic_fetch_add_relaxed and the pthread_push
|
||||
@c of the handler that undoes that operation. A cancellation
|
||||
@c at that point would fail to remove the process from the
|
||||
@c waiters count.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_timedwait (sem_t *@var{sem}, const struct timespec *@var{abstime})
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
|
||||
@c Same safety issues as sem_wait.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_trywait (sem_t *@var{sem})
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
@c All atomic operations are safe in all contexts.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_post (sem_t *@var{sem})
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
@c Same safety as sem_trywait.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_getvalue (sem_t *@var{sem}, int *@var{sval})
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
@c Atomic write of a value is safe in all contexts.
|
||||
@end deftypefun
|
||||
@Theglibc{} provides POSIX semaphores as well. These functions' names begin
|
||||
with @code{sem_} and they are declared in @file{semaphore.h}. @xref{POSIX
|
||||
Semaphores}.
|
||||
|
|
|
@ -282,14 +282,22 @@ cwd\comments\
|
|||
@macro standardsx {element, standard, header}
|
||||
@end macro
|
||||
|
||||
@ifhtml
|
||||
@macro manpageurl {func, sec}
|
||||
@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html}
|
||||
@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html,,\func\(\sec\)}
|
||||
@xref{Linux Kernel}
|
||||
@end macro
|
||||
@end ifhtml
|
||||
@ifnothtml
|
||||
@macro manpageurl {func, sec}
|
||||
\func\(\sec\) (Latest, online: @url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html})
|
||||
@xref{Linux Kernel}
|
||||
@end macro
|
||||
@end ifnothtml
|
||||
|
||||
@macro manpagefunctionstub {func,sec}
|
||||
This documentation is a stub. For additional information on this
|
||||
function, consult the manual page @manpageurl{\func\,\sec\}.
|
||||
@xref{Linux Kernel}.
|
||||
@end macro
|
||||
|
||||
@end ifclear
|
||||
|
|
|
@ -929,18 +929,31 @@ function, so there are no specific @code{errno} values.
|
|||
@c Direct syscall on Linux; alias to swtch on HURD.
|
||||
|
||||
This function voluntarily gives up the task's claim on the CPU.
|
||||
Depending on the scheduling policy in effect and the tasks ready to run
|
||||
on the system, another task may be scheduled to run instead.
|
||||
|
||||
Technically, @code{sched_yield} causes the calling task to be made
|
||||
immediately ready to run (as opposed to running, which is what it was
|
||||
before). This means that if it has absolute priority higher than 0, it
|
||||
gets pushed onto the tail of the queue of tasks that share its
|
||||
A call to @code{sched_yield} does not guarantee that a different task
|
||||
from the calling task is scheduled as a result; it depends on the
|
||||
scheduling policy used on the target system. It is possible that the
|
||||
call may not result in any visible effect, i.e., the same task gets
|
||||
scheduled again.
|
||||
|
||||
For example on Linux systems, when a simple priority-based FIFO
|
||||
scheduling policy (@code{SCHED_FIFO}) is in effect, the calling task is
|
||||
made immediately ready to run (as opposed to running, which is what it
|
||||
was before). This means that if it has absolute priority higher than 0,
|
||||
it gets pushed onto the tail of the queue of tasks that share its
|
||||
absolute priority and are ready to run, and it will run again when its
|
||||
turn next arrives. If its absolute priority is 0, it is more
|
||||
complicated, but still has the effect of yielding the CPU to other
|
||||
tasks.
|
||||
tasks. If there are no other tasks that share the calling task's
|
||||
absolute priority, it will be scheduled again as if @code{sched_yield}
|
||||
was never called.
|
||||
|
||||
If there are no other tasks that share the calling task's absolute
|
||||
priority, this function doesn't have any effect.
|
||||
Another example could be a time slice based preemptive round-robin
|
||||
policy, such as the @code{SCHED_RR} policy on Linux. It is possible
|
||||
with this policy that the calling task is scheduled again because it
|
||||
still has time left in its slice.
|
||||
|
||||
To the extent that the containing program is oblivious to what other
|
||||
processes in the system are doing and how fast it executes, this
|
||||
|
@ -966,7 +979,6 @@ scheduling policies.
|
|||
|
||||
For additional information about scheduling policies, consult consult
|
||||
the manual pages @manpageurl{sched,7} and @manpageurl{sched_setattr,2}.
|
||||
@xref{Linux Kernel}.
|
||||
|
||||
@strong{Note:} Calling the @code{sched_setattr} function is incompatible
|
||||
with support for @code{PTHREAD_PRIO_PROTECT} mutexes.
|
||||
|
@ -1000,7 +1012,7 @@ Scheduling flags associated with the scheduling policy.
|
|||
|
||||
In addition to the generic fields, policy-specific fields are available.
|
||||
For additional information, consult the manual page
|
||||
@manpageurl{sched_setattr,2}. @xref{Linux Kernel}.
|
||||
@manpageurl{sched_setattr,2}.
|
||||
@end deftp
|
||||
|
||||
@deftypefun int sched_setaddr (pid_t @var{tid}, struct sched_attr *@var{attr}, unsigned int flags)
|
||||
|
|
|
@ -427,9 +427,18 @@ failure to properly emulate them.
|
|||
|
||||
@deftypevr Macro int SIGSYS
|
||||
@standards{Unix, signal.h}
|
||||
Bad system call; that is to say, the instruction to trap to the
|
||||
operating system was executed, but the code number for the system call
|
||||
to perform was invalid.
|
||||
System call event. This signal may be generated by a valid system
|
||||
call which requested an invalid sub-function, and also by the SECCOMP
|
||||
filter when it filters or traps a system call.
|
||||
|
||||
If the system call itself is invalid or unsupported by the kernel, the
|
||||
call will not raise this signal, but will return @code{ENOSYS}.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr Macro int SIGSTKFLT
|
||||
Coprocessor stack fault. Obsolete, no longer generated. This signal
|
||||
may be used by applications in much the way @code{SIGUSR1} and
|
||||
@code{SIGUSR2} are.
|
||||
@end deftypevr
|
||||
|
||||
@node Termination Signals
|
||||
|
@ -752,12 +761,11 @@ that isn't connected. @xref{Sending Data}.
|
|||
@deftypevr Macro int SIGLOST
|
||||
@standards{GNU, signal.h}
|
||||
@cindex lost resource signal
|
||||
Resource lost. This signal is generated when you have an advisory lock
|
||||
on an NFS file, and the NFS server reboots and forgets about your lock.
|
||||
|
||||
On @gnuhurdsystems{}, @code{SIGLOST} is generated when any server program
|
||||
dies unexpectedly. It is usually fine to ignore the signal; whatever
|
||||
call was made to the server that died just returns an error.
|
||||
Resource lost. On @gnuhurdsystems{}, @code{SIGLOST} is generated when
|
||||
any server program dies unexpectedly. It is usually fine to ignore
|
||||
the signal; whatever call was made to the server that died just
|
||||
returns an error. This signal's original purpose of signalling a lost
|
||||
NFS lock is obsolete.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr Macro int SIGXCPU
|
||||
|
@ -817,6 +825,17 @@ to print some status information about the system and what the process
|
|||
is doing. Otherwise the default is to do nothing.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr Macro int SIGPWR
|
||||
@cindex power event signal
|
||||
Power lost or restored. On s390x Linux systems, this signal is
|
||||
generated when a machine check warning is issued, and is sent to the
|
||||
process designated to receive ctrl-alt-del notifications. Otherwise,
|
||||
it is up to userspace applications to generate this signal and manage
|
||||
notifications as to the type of power event that happened.
|
||||
|
||||
The default action is to terminate the process.
|
||||
@end deftypevr
|
||||
|
||||
@node Signal Messages
|
||||
@subsection Signal Messages
|
||||
@cindex signal messages
|
||||
|
|
|
@ -4346,6 +4346,18 @@ fail to handle lines more than 254 characters long (including the
|
|||
terminating newline character).
|
||||
@cindex lines (in a text file)
|
||||
|
||||
@item
|
||||
If the system does not use POSIX-style in-band signalling to indicate
|
||||
line termination, it can be impossibe to write anything to a text stream
|
||||
without adding a line terminator. As a result, flushing a text stream
|
||||
(by calling @code{fflush}, for example) may produce a logical line
|
||||
terminator even if no @code{'\n'} character was written by the program.
|
||||
|
||||
@item
|
||||
Text files may contain lines that embed @code{'\n'} characters that are
|
||||
not treated as line terminators by the system. C programs cannot read
|
||||
such text files reliably using the @file{stdio.h} facilities.
|
||||
|
||||
@item
|
||||
On some systems, text files can contain only printing characters,
|
||||
horizontal tab characters, and newlines, and so text streams may not
|
||||
|
@ -4838,12 +4850,6 @@ currently opened.
|
|||
This function is declared in the @file{stdio_ext.h} header.
|
||||
@end deftypefun
|
||||
|
||||
@strong{Compatibility Note:} Some brain-damaged operating systems have
|
||||
been known to be so thoroughly fixated on line-oriented input and output
|
||||
that flushing a line buffered stream causes a newline to be written!
|
||||
Fortunately, this ``feature'' seems to be becoming less common. You do
|
||||
not need to worry about this with @theglibc{}.
|
||||
|
||||
In some situations it might be useful to not flush the output pending
|
||||
for a stream but instead simply forget it. If transmission is costly
|
||||
and the output is not needed anymore this is valid reasoning. In this
|
||||
|
|
|
@ -498,10 +498,7 @@ The symbols referred to in this section are declared in the file
|
|||
|
||||
@deftypefun int setlogmask (int @var{mask})
|
||||
@standards{BSD, syslog.h}
|
||||
@safety{@prelim{}@mtunsafe{@mtasurace{:LogMask}}@asunsafe{}@acsafe{}}
|
||||
@c Read and modify are not guarded by syslog_lock, so concurrent changes
|
||||
@c or even uses are undefined. This should use an atomic swap instead,
|
||||
@c at least for modifications.
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
|
||||
|
||||
@code{setlogmask} sets a mask (the ``logmask'') that determines which
|
||||
future @code{syslog} calls shall be ignored. If a program has not
|
||||
|
|
|
@ -554,6 +554,8 @@ This section describes the @glibcadj{} POSIX Threads implementation.
|
|||
@menu
|
||||
* Thread-specific Data:: Support for creating and
|
||||
managing thread-specific data
|
||||
* POSIX Semaphores:: Support for process and thread
|
||||
synchronization using semaphores
|
||||
* Non-POSIX Extensions:: Additional functions to extend
|
||||
POSIX Thread functionality
|
||||
@end menu
|
||||
|
@ -615,6 +617,107 @@ Associate the thread-specific @var{value} with @var{key} in the calling thread.
|
|||
@end deftypefun
|
||||
|
||||
|
||||
@node POSIX Semaphores
|
||||
@subsection POSIX Semaphores
|
||||
|
||||
@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
|
||||
@manpagefunctionstub{sem_init,3}
|
||||
@c Does not atomically update sem_t therefore AC-unsafe
|
||||
@c because it can leave sem_t partially initialized.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_destroy (sem_t *@var{sem})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
@manpagefunctionstub{sem_destroy,3}
|
||||
@c Function does nothing and is therefore always safe.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {sem_t *} sem_open (const char *@var{name}, int @var{oflag}, ...)
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acuinit{}}}
|
||||
@manpagefunctionstub{sem_open,3}
|
||||
@c pthread_once asuinit
|
||||
@c
|
||||
@c We are AC-Unsafe because we use pthread_once to initialize
|
||||
@c a global variable that holds the location of the mounted
|
||||
@c shmfs on Linux.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_close (sem_t *@var{sem})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
|
||||
@manpagefunctionstub{sem_close,3}
|
||||
@c lll_lock asulock aculock
|
||||
@c twalk mtsrace{:root}
|
||||
@c
|
||||
@c We are AS-unsafe because we take a non-recursive lock.
|
||||
@c We are AC-unsafe because several internal data structures
|
||||
@c are not updated atomically.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_unlink (const char *@var{name})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asuinit{}}@acunsafe{@acucorrupt{}}}
|
||||
@manpagefunctionstub{sem_unlink,3}
|
||||
@c pthread_once asuinit acucorrupt aculock
|
||||
@c mempcpy acucorrupt
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_wait (sem_t *@var{sem})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
|
||||
@manpagefunctionstub{sem_wait,3}
|
||||
@c atomic_fetch_add_relaxed (nwaiters) acucorrupt
|
||||
@c
|
||||
@c Given the use atomic operations this function seems
|
||||
@c to be AS-safe. It is AC-unsafe because there is still
|
||||
@c a window between atomic_fetch_add_relaxed and the pthread_push
|
||||
@c of the handler that undoes that operation. A cancellation
|
||||
@c at that point would fail to remove the process from the
|
||||
@c waiters count.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_timedwait (sem_t *@var{sem}, const struct timespec *@var{abstime})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
|
||||
@manpagefunctionstub{sem_timedwait,3}
|
||||
@c Same safety issues as sem_wait.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_clockwait (sem_t *@var{sem}, clockid_t @var{clockid}, const struct timespec *@var{abstime})
|
||||
@standards{POSIX.1-2024, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
|
||||
Behaves like @code{sem_timedwait} except the time @var{abstime} is measured
|
||||
against the clock specified by @var{clockid} rather than
|
||||
@code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
|
||||
@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_trywait (sem_t *@var{sem})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
@manpagefunctionstub{sem_trywait,3}
|
||||
@c All atomic operations are safe in all contexts.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_post (sem_t *@var{sem})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
@manpagefunctionstub{sem_post,3}
|
||||
@c Same safety as sem_trywait.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun int sem_getvalue (sem_t *@var{sem}, int *@var{sval})
|
||||
@standards{POSIX.1-2008, semaphore.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
@manpagefunctionstub{sem_getvalue,3}
|
||||
@c Atomic write of a value is safe in all contexts.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Non-POSIX Extensions
|
||||
@subsection Non-POSIX Extensions
|
||||
|
||||
|
@ -752,16 +855,6 @@ freed.
|
|||
@Theglibc{} provides several waiting functions that expect an explicit
|
||||
@code{clockid_t} argument.
|
||||
|
||||
@comment semaphore.h
|
||||
@comment POSIX-proposed
|
||||
@deftypefun int sem_clockwait (sem_t *@var{sem}, clockid_t @var{clockid}, const struct timespec *@var{abstime})
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
|
||||
Behaves like @code{sem_timedwait} except the time @var{abstime} is measured
|
||||
against the clock specified by @var{clockid} rather than
|
||||
@code{CLOCK_REALTIME}. Currently, @var{clockid} must be either
|
||||
@code{CLOCK_MONOTONIC} or @code{CLOCK_REALTIME}.
|
||||
@end deftypefun
|
||||
|
||||
@comment pthread.h
|
||||
@comment POSIX-proposed
|
||||
@deftypefun int pthread_cond_clockwait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}, clockid_t @var{clockid}, const struct timespec *@var{abstime})
|
||||
|
@ -835,6 +928,9 @@ Currently, @var{clockid} must be either @code{CLOCK_MONOTONIC} or
|
|||
@code{CLOCK_REALTIME}.
|
||||
@end deftypefun
|
||||
|
||||
The @code{sem_clockwait} function also works using a @code{clockid_t}
|
||||
argument. @xref{POSIX Semaphores}.
|
||||
|
||||
@node Single-Threaded
|
||||
@subsubsection Detecting Single-Threaded Execution
|
||||
|
||||
|
|
|
@ -595,6 +595,7 @@ Systems may support more than just this @w{ISO C} clock.
|
|||
|
||||
@deftypefun int timespec_get (struct timespec *@var{ts}, int @var{base})
|
||||
@standards{ISO, time.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
Store into @code{*@var{ts}} the current time according to the @w{ISO
|
||||
C} time @var{base}.
|
||||
|
||||
|
@ -603,6 +604,7 @@ The return value is @var{base} on success and @code{0} on failure.
|
|||
|
||||
@deftypefun int timespec_getres (struct timespec *@var{res}, int @var{base})
|
||||
@standards{ISO, time.h}
|
||||
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
|
||||
If @var{ts} is non-null, store into @code{*@var{ts}} the resolution of
|
||||
the time provided by @code{timespec_get} function for the @w{ISO C}
|
||||
time @var{base}.
|
||||
|
|
|
@ -366,8 +366,13 @@ type-float-routines := \
|
|||
e_log2f_data \
|
||||
e_logf_data \
|
||||
e_powf_log2_data \
|
||||
e_sincoshf_data \
|
||||
math_errf \
|
||||
s_asincosf_data \
|
||||
s_asincoshf_data \
|
||||
s_asincospif_data \
|
||||
s_sincosf_data \
|
||||
s_sincospif_data \
|
||||
# type-float-routines
|
||||
|
||||
# _Float128 support
|
||||
|
|
|
@ -936,6 +936,7 @@ atanpi -0x3.eb8e18p+0
|
|||
atanpi 0x3.53c188p+0
|
||||
atanpi -0x1.58c83p+0
|
||||
atanpi 0x1.626772p-1
|
||||
atanpi 0x1p-126
|
||||
atanpi min
|
||||
atanpi -min
|
||||
atanpi min_subnorm
|
||||
|
@ -7291,6 +7292,8 @@ log10p1 -0x1p-125
|
|||
log10p1 -0x1p-1021
|
||||
log10p1 -0x1p-16381
|
||||
|
||||
log10p1 0x1.27f7dap-17
|
||||
|
||||
log10p1 0x7.2a4368p-4
|
||||
log10p1 0x6.d3a118p-4
|
||||
log10p1 0x5.03f228p+0
|
||||
|
@ -8298,6 +8301,7 @@ sinh -0x1.3dda8ap+0
|
|||
sinh -0x5.ee9218p-4
|
||||
sinh -0x1.bcfc98p+0
|
||||
sinh -0x6.9bbb6df7c5d08p-4
|
||||
sinh 0x1.250bfep-11
|
||||
# the next value generates larger error bounds on x86_64 (ldbl-96)
|
||||
sinh 0x2.c5d376167f4052f4p+12
|
||||
sinh max
|
||||
|
@ -8661,6 +8665,7 @@ tan 0x1.1ad374p+0
|
|||
tan -0x1.0d55b8p+0
|
||||
tan 1.57079697
|
||||
tan -1.57079697
|
||||
tan 0x1.ada6aap+27
|
||||
tan 0x1p-5
|
||||
tan 0x1p-10
|
||||
tan 0x1p-15
|
||||
|
|
|
@ -1061,6 +1061,31 @@ atanpi 0x1.626772p-1
|
|||
= atanpi tonearest ibm128 0xb.133b9p-4 : 0x3.156898f544dca52f89f818e127p-4 : inexact-ok
|
||||
= atanpi towardzero ibm128 0xb.133b9p-4 : 0x3.156898f544dca52f89f818e127p-4 : inexact-ok
|
||||
= atanpi upward ibm128 0xb.133b9p-4 : 0x3.156898f544dca52f89f818e128p-4 : inexact-ok
|
||||
atanpi 0x1p-126
|
||||
= atanpi downward binary32 0x4p-128 : 0x1.45f3p-128 : inexact-ok underflow errno-erange-ok
|
||||
= atanpi tonearest binary32 0x4p-128 : 0x1.45f308p-128 : inexact-ok underflow errno-erange-ok
|
||||
= atanpi towardzero binary32 0x4p-128 : 0x1.45f3p-128 : inexact-ok underflow errno-erange-ok
|
||||
= atanpi upward binary32 0x4p-128 : 0x1.45f308p-128 : inexact-ok underflow errno-erange-ok
|
||||
= atanpi downward binary64 0x4p-128 : 0x1.45f306dc9c882p-128 : inexact-ok
|
||||
= atanpi tonearest binary64 0x4p-128 : 0x1.45f306dc9c883p-128 : inexact-ok
|
||||
= atanpi towardzero binary64 0x4p-128 : 0x1.45f306dc9c882p-128 : inexact-ok
|
||||
= atanpi upward binary64 0x4p-128 : 0x1.45f306dc9c883p-128 : inexact-ok
|
||||
= atanpi downward intel96 0x4p-128 : 0x1.45f306dc9c882a52p-128 : inexact-ok
|
||||
= atanpi tonearest intel96 0x4p-128 : 0x1.45f306dc9c882a54p-128 : inexact-ok
|
||||
= atanpi towardzero intel96 0x4p-128 : 0x1.45f306dc9c882a52p-128 : inexact-ok
|
||||
= atanpi upward intel96 0x4p-128 : 0x1.45f306dc9c882a54p-128 : inexact-ok
|
||||
= atanpi downward m68k96 0x4p-128 : 0x1.45f306dc9c882a52p-128 : inexact-ok
|
||||
= atanpi tonearest m68k96 0x4p-128 : 0x1.45f306dc9c882a54p-128 : inexact-ok
|
||||
= atanpi towardzero m68k96 0x4p-128 : 0x1.45f306dc9c882a52p-128 : inexact-ok
|
||||
= atanpi upward m68k96 0x4p-128 : 0x1.45f306dc9c882a54p-128 : inexact-ok
|
||||
= atanpi downward binary128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea69p-128 : inexact-ok
|
||||
= atanpi tonearest binary128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea6ap-128 : inexact-ok
|
||||
= atanpi towardzero binary128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea69p-128 : inexact-ok
|
||||
= atanpi upward binary128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea6ap-128 : inexact-ok
|
||||
= atanpi downward ibm128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3eap-128 : inexact-ok
|
||||
= atanpi tonearest ibm128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea8p-128 : inexact-ok
|
||||
= atanpi towardzero ibm128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3eap-128 : inexact-ok
|
||||
= atanpi upward ibm128 0x4p-128 : 0x1.45f306dc9c882a53f84eafa3ea8p-128 : inexact-ok
|
||||
atanpi min
|
||||
= atanpi downward binary32 0x4p-128 : 0x1.45f3p-128 : inexact-ok underflow errno-erange-ok
|
||||
= atanpi tonearest binary32 0x4p-128 : 0x1.45f308p-128 : inexact-ok underflow errno-erange-ok
|
||||
|
|
|
@ -1789,6 +1789,31 @@ log10p1 -0x1p-16381
|
|||
= log10p1 tonearest binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4dp-16384 : inexact-ok underflow errno-erange-ok
|
||||
= log10p1 towardzero binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4ccp-16384 : inexact-ok underflow errno-erange-ok
|
||||
= log10p1 upward binary128 -0x8p-16384 : -0x3.796f62a4dca1c654d56eaabeb4ccp-16384 : inexact-ok underflow errno-erange-ok
|
||||
log10p1 0x1.27f7dap-17
|
||||
= log10p1 downward binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
|
||||
= log10p1 tonearest binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
|
||||
= log10p1 towardzero binary32 0x9.3fbedp-20 : 0x4.044b5p-20 : inexact-ok
|
||||
= log10p1 upward binary32 0x9.3fbedp-20 : 0x4.044b58p-20 : inexact-ok
|
||||
= log10p1 downward binary64 0x9.3fbedp-20 : 0x4.044b5157872ep-20 : inexact-ok
|
||||
= log10p1 tonearest binary64 0x9.3fbedp-20 : 0x4.044b5157872e4p-20 : inexact-ok
|
||||
= log10p1 towardzero binary64 0x9.3fbedp-20 : 0x4.044b5157872ep-20 : inexact-ok
|
||||
= log10p1 upward binary64 0x9.3fbedp-20 : 0x4.044b5157872e4p-20 : inexact-ok
|
||||
= log10p1 downward intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
|
||||
= log10p1 tonearest intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
|
||||
= log10p1 towardzero intel96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
|
||||
= log10p1 upward intel96 0x9.3fbedp-20 : 0x4.044b5157872e287p-20 : inexact-ok
|
||||
= log10p1 downward m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
|
||||
= log10p1 tonearest m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
|
||||
= log10p1 towardzero m68k96 0x9.3fbedp-20 : 0x4.044b5157872e2868p-20 : inexact-ok
|
||||
= log10p1 upward m68k96 0x9.3fbedp-20 : 0x4.044b5157872e287p-20 : inexact-ok
|
||||
= log10p1 downward binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d808p-20 : inexact-ok
|
||||
= log10p1 tonearest binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d80cp-20 : inexact-ok
|
||||
= log10p1 towardzero binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d808p-20 : inexact-ok
|
||||
= log10p1 upward binary128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d80cp-20 : inexact-ok
|
||||
= log10p1 downward ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
|
||||
= log10p1 tonearest ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
|
||||
= log10p1 towardzero ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287d8p-20 : inexact-ok
|
||||
= log10p1 upward ibm128 0x9.3fbedp-20 : 0x4.044b5157872e2868f5c04287dap-20 : inexact-ok
|
||||
log10p1 0x7.2a4368p-4
|
||||
= log10p1 downward binary32 0x7.2a4368p-4 : 0x2.9248dcp-4 : inexact-ok
|
||||
= log10p1 tonearest binary32 0x7.2a4368p-4 : 0x2.9248ep-4 : inexact-ok
|
||||
|
|
|
@ -2115,6 +2115,31 @@ sinh -0x6.9bbb6df7c5d08p-4
|
|||
= sinh tonearest ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
|
||||
= sinh towardzero ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
|
||||
= sinh upward ibm128 -0x6.9bbb6df7c5d08p-4 : -0x6.cc3ddf003dcda77f8f9e892e36p-4 : inexact-ok
|
||||
sinh 0x1.250bfep-11
|
||||
= sinh downward binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
|
||||
= sinh tonearest binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
|
||||
= sinh towardzero binary32 0x2.4a17fcp-12 : 0x2.4a17fcp-12 : inexact-ok
|
||||
= sinh upward binary32 0x2.4a17fcp-12 : 0x2.4a18p-12 : inexact-ok
|
||||
= sinh downward binary64 0x2.4a17fcp-12 : 0x2.4a17fdffffffep-12 : inexact-ok
|
||||
= sinh tonearest binary64 0x2.4a17fcp-12 : 0x2.4a17fep-12 : inexact-ok
|
||||
= sinh towardzero binary64 0x2.4a17fcp-12 : 0x2.4a17fdffffffep-12 : inexact-ok
|
||||
= sinh upward binary64 0x2.4a17fcp-12 : 0x2.4a17fep-12 : inexact-ok
|
||||
= sinh downward intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
|
||||
= sinh tonearest intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
|
||||
= sinh towardzero intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
|
||||
= sinh upward intel96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
|
||||
= sinh downward m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
|
||||
= sinh tonearest m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
|
||||
= sinh towardzero m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87cp-12 : inexact-ok
|
||||
= sinh upward m68k96 0x2.4a17fcp-12 : 0x2.4a17fdfffffff88p-12 : inexact-ok
|
||||
= sinh downward binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec88p-12 : inexact-ok
|
||||
= sinh tonearest binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec8ap-12 : inexact-ok
|
||||
= sinh towardzero binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec88p-12 : inexact-ok
|
||||
= sinh upward binary128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ec8ap-12 : inexact-ok
|
||||
= sinh downward ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ecp-12 : inexact-ok
|
||||
= sinh tonearest ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786edp-12 : inexact-ok
|
||||
= sinh towardzero ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786ecp-12 : inexact-ok
|
||||
= sinh upward ibm128 0x2.4a17fcp-12 : 0x2.4a17fdfffffff87e8d322786edp-12 : inexact-ok
|
||||
sinh 0x2.c5d376167f4052f4p+12
|
||||
= sinh downward binary32 0x2.c5d378p+12 : 0xf.fffffp+124 : inexact-ok overflow errno-erange-ok
|
||||
= sinh tonearest binary32 0x2.c5d378p+12 : plus_infty : inexact-ok overflow errno-erange
|
||||
|
|
|
@ -2532,6 +2532,31 @@ tan -1.57079697
|
|||
= tan tonearest ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5c8p+20 : inexact-ok
|
||||
= tan towardzero ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5cp+20 : inexact-ok
|
||||
= tan upward ibm128 -0x1.921fc00ece4f02f278ade6ad9fp+0 : 0x1.7b91a0851bbbafa14cf21c2b5c8p+20 : inexact-ok
|
||||
tan 0x1.ada6aap+27
|
||||
= tan downward binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
|
||||
= tan tonearest binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
|
||||
= tan towardzero binary32 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
|
||||
= tan upward binary32 0xd.6d355p+24 : 0x3.d0060cp-4 : inexact-ok
|
||||
= tan downward binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
|
||||
= tan tonearest binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
|
||||
= tan towardzero binary64 0xd.6d355p+24 : 0x3.d00608p-4 : inexact-ok
|
||||
= tan upward binary64 0xd.6d355p+24 : 0x3.d006080000002p-4 : inexact-ok
|
||||
= tan downward intel96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
|
||||
= tan tonearest intel96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
|
||||
= tan towardzero intel96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
|
||||
= tan upward intel96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
|
||||
= tan downward m68k96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
|
||||
= tan tonearest m68k96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
|
||||
= tan towardzero m68k96 0xd.6d355p+24 : 0x3.d006080000000504p-4 : inexact-ok
|
||||
= tan upward m68k96 0xd.6d355p+24 : 0x3.d006080000000508p-4 : inexact-ok
|
||||
= tan downward binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
|
||||
= tan tonearest binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
|
||||
= tan towardzero binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15ap-4 : inexact-ok
|
||||
= tan upward binary128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c15cp-4 : inexact-ok
|
||||
= tan downward ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
|
||||
= tan tonearest ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
|
||||
= tan towardzero ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c1p-4 : inexact-ok
|
||||
= tan upward ibm128 0xd.6d355p+24 : 0x3.d0060800000005067d16c1c9c2p-4 : inexact-ok
|
||||
tan 0x1p-5
|
||||
= tan downward binary32 0x8p-8 : 0x8.00aabp-8 : inexact-ok
|
||||
= tan tonearest binary32 0x8p-8 : 0x8.00aacp-8 : inexact-ok
|
||||
|
|
|
@ -173,6 +173,10 @@ static const struct test_ff_f_data remainder_test_data[] =
|
|||
TEST_ff_f (remainder, 2, -1, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_ff_f (remainder, -2, 1, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_ff_f (remainder, -2, -1, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
|
||||
TEST_ff_f (remainder, 0x1.08001cp-2, 0x1p-24, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
TEST_ff_f (remainder, -0x1.003ffep-126, -0x1.8p-148, minus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
TEST_ff_f (remainder, 0x1.2c3224p+17, 0x1p-5, plus_zero, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC),
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
@ -289,6 +289,7 @@ tests = \
|
|||
tst-dlsym1 \
|
||||
tst-exec4 \
|
||||
tst-exec5 \
|
||||
tst-guard1 \
|
||||
tst-initializers1 \
|
||||
tst-initializers1-c11 \
|
||||
tst-initializers1-c89 \
|
||||
|
@ -701,6 +702,9 @@ $(objpfx)tst-execstack-threads.out: $(objpfx)tst-execstack-threads-mod.so
|
|||
LDFLAGS-tst-execstack-threads = -Wl,-z,noexecstack
|
||||
LDFLAGS-tst-execstack-threads-mod.so = -Wl,-z,execstack
|
||||
CFLAGS-tst-execstack-threads-mod.c += -Wno-trampolines
|
||||
ifeq ($(have-no-error-execstack),yes)
|
||||
LDFLAGS-tst-execstack-threads-mod.so += -Wl,--no-error-execstack
|
||||
endif
|
||||
|
||||
tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child"
|
||||
tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
pthread_attr_setguardsize
|
||||
|
||||
test effectiveness
|
||||
|
||||
pthread_attr_[sg]etschedparam
|
||||
|
||||
what to test?
|
||||
|
|
|
@ -146,10 +146,37 @@ get_cached_stack (size_t *sizep, void **memp)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Assume support for MADV_ADVISE_GUARD, setup_stack_prot will disable it
|
||||
and fallback to ALLOCATE_GUARD_PROT_NONE if the madvise call fails. */
|
||||
static int allocate_stack_mode = ALLOCATE_GUARD_MADV_GUARD;
|
||||
|
||||
static inline int stack_prot (void)
|
||||
{
|
||||
return (PROT_READ | PROT_WRITE
|
||||
| ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
|
||||
}
|
||||
|
||||
static void *
|
||||
allocate_thread_stack (size_t size, size_t guardsize)
|
||||
{
|
||||
/* MADV_ADVISE_GUARD does not require an additional PROT_NONE mapping. */
|
||||
int prot = stack_prot ();
|
||||
|
||||
if (atomic_load_relaxed (&allocate_stack_mode) == ALLOCATE_GUARD_PROT_NONE)
|
||||
/* If a guard page is required, avoid committing memory by first allocate
|
||||
with PROT_NONE and then reserve with required permission excluding the
|
||||
guard page. */
|
||||
prot = guardsize == 0 ? prot : PROT_NONE;
|
||||
|
||||
return __mmap (NULL, size, prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
/* Return the guard page position on allocated stack. */
|
||||
static inline char *
|
||||
__attribute ((always_inline))
|
||||
guard_position (void *mem, size_t size, size_t guardsize, struct pthread *pd,
|
||||
guard_position (void *mem, size_t size, size_t guardsize, const struct pthread *pd,
|
||||
size_t pagesize_m1)
|
||||
{
|
||||
#if _STACK_GROWS_DOWN
|
||||
|
@ -159,27 +186,131 @@ guard_position (void *mem, size_t size, size_t guardsize, struct pthread *pd,
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Based on stack allocated with PROT_NONE, setup the required portions with
|
||||
'prot' flags based on the guard page position. */
|
||||
static inline int
|
||||
setup_stack_prot (char *mem, size_t size, char *guard, size_t guardsize,
|
||||
const int prot)
|
||||
/* Setup the MEM thread stack of SIZE bytes with the required protection flags
|
||||
along with a guard area of GUARDSIZE size. It first tries with
|
||||
MADV_GUARD_INSTALL, and then fallback to setup the guard area using the
|
||||
extra PROT_NONE mapping. Update PD with the type of guard area setup. */
|
||||
static inline bool
|
||||
setup_stack_prot (char *mem, size_t size, struct pthread *pd,
|
||||
size_t guardsize, size_t pagesize_m1)
|
||||
{
|
||||
if (__glibc_unlikely (guardsize == 0))
|
||||
return true;
|
||||
|
||||
char *guard = guard_position (mem, size, guardsize, pd, pagesize_m1);
|
||||
if (atomic_load_relaxed (&allocate_stack_mode) == ALLOCATE_GUARD_MADV_GUARD)
|
||||
{
|
||||
if (__madvise (guard, guardsize, MADV_GUARD_INSTALL) == 0)
|
||||
{
|
||||
pd->stack_mode = ALLOCATE_GUARD_MADV_GUARD;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If madvise fails it means the kernel does not support the guard
|
||||
advise (we assume that the syscall is available, guard is page-aligned
|
||||
and length is non negative). The stack has already the expected
|
||||
protection flags, so it just need to PROT_NONE the guard area. */
|
||||
atomic_store_relaxed (&allocate_stack_mode, ALLOCATE_GUARD_PROT_NONE);
|
||||
if (__mprotect (guard, guardsize, PROT_NONE) != 0)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int prot = stack_prot ();
|
||||
char *guardend = guard + guardsize;
|
||||
#if _STACK_GROWS_DOWN
|
||||
/* As defined at guard_position, for architectures with downward stack
|
||||
the guard page is always at start of the allocated area. */
|
||||
if (__mprotect (guardend, size - guardsize, prot) != 0)
|
||||
return errno;
|
||||
return false;
|
||||
#else
|
||||
size_t mprots1 = (uintptr_t) guard - (uintptr_t) mem;
|
||||
if (__mprotect (mem, mprots1, prot) != 0)
|
||||
return errno;
|
||||
return false;
|
||||
size_t mprots2 = ((uintptr_t) mem + size) - (uintptr_t) guardend;
|
||||
if (__mprotect (guardend, mprots2, prot) != 0)
|
||||
return errno;
|
||||
return false;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
pd->stack_mode = ALLOCATE_GUARD_PROT_NONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Update the guard area of the thread stack MEM of size SIZE with the new
|
||||
GUARDISZE. It uses the method defined by PD stack_mode. */
|
||||
static inline bool
|
||||
adjust_stack_prot (char *mem, size_t size, const struct pthread *pd,
|
||||
size_t guardsize, size_t pagesize_m1)
|
||||
{
|
||||
/* The required guard area is larger than the current one. For
|
||||
_STACK_GROWS_DOWN it means the guard should increase as:
|
||||
|
||||
|guard|---------------------------------stack|
|
||||
|new guard--|---------------------------stack|
|
||||
|
||||
while for _STACK_GROWS_UP:
|
||||
|
||||
|stack---------------------------|guard|-----|
|
||||
|stack--------------------|new guard---|-----|
|
||||
|
||||
Both madvise and mprotect allows overlap the required region,
|
||||
so use the new guard placement with the new size. */
|
||||
if (guardsize > pd->guardsize)
|
||||
{
|
||||
char *guard = guard_position (mem, size, guardsize, pd, pagesize_m1);
|
||||
if (pd->stack_mode == ALLOCATE_GUARD_MADV_GUARD)
|
||||
return __madvise (guard, guardsize, MADV_GUARD_INSTALL) == 0;
|
||||
else if (pd->stack_mode == ALLOCATE_GUARD_PROT_NONE)
|
||||
return __mprotect (guard, guardsize, PROT_NONE) == 0;
|
||||
}
|
||||
/* The current guard area is larger than the required one. For
|
||||
_STACK_GROWS_DOWN is means change the guard as:
|
||||
|
||||
|guard-------|-------------------------stack|
|
||||
|new guard|----------------------------stack|
|
||||
|
||||
And for _STACK_GROWS_UP:
|
||||
|
||||
|stack---------------------|guard-------|---|
|
||||
|stack------------------------|new guard|---|
|
||||
|
||||
For ALLOCATE_GUARD_MADV_GUARD it means remove the slack area
|
||||
(disjointed region of guard and new guard), while for
|
||||
ALLOCATE_GUARD_PROT_NONE it requires to mprotect it with the stack
|
||||
protection flags. */
|
||||
else if (pd->guardsize > guardsize)
|
||||
{
|
||||
size_t slacksize = pd->guardsize - guardsize;
|
||||
if (pd->stack_mode == ALLOCATE_GUARD_MADV_GUARD)
|
||||
{
|
||||
void *slack =
|
||||
#if _STACK_GROWS_DOWN
|
||||
mem + guardsize;
|
||||
#else
|
||||
guard_position (mem, size, pd->guardsize, pd, pagesize_m1);
|
||||
#endif
|
||||
return __madvise (slack, slacksize, MADV_GUARD_REMOVE) == 0;
|
||||
}
|
||||
else if (pd->stack_mode == ALLOCATE_GUARD_PROT_NONE)
|
||||
{
|
||||
const int prot = stack_prot ();
|
||||
#if _STACK_GROWS_DOWN
|
||||
return __mprotect (mem + guardsize, slacksize, prot) == 0;
|
||||
#else
|
||||
char *new_guard = (char *)(((uintptr_t) pd - guardsize)
|
||||
& ~pagesize_m1);
|
||||
char *old_guard = (char *)(((uintptr_t) pd - pd->guardsize)
|
||||
& ~pagesize_m1);
|
||||
/* The guard size difference might be > 0, but once rounded
|
||||
to the nearest page the size difference might be zero. */
|
||||
if (new_guard > old_guard
|
||||
&& __mprotect (old_guard, new_guard - old_guard, prot) != 0)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Mark the memory of the stack as usable to the kernel. It frees everything
|
||||
|
@ -291,7 +422,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
|
||||
/* This is a user-provided stack. It will not be queued in the
|
||||
stack cache nor will the memory (except the TLS memory) be freed. */
|
||||
pd->user_stack = true;
|
||||
pd->stack_mode = ALLOCATE_GUARD_USER;
|
||||
|
||||
/* This is at least the second thread. */
|
||||
pd->header.multiple_threads = 1;
|
||||
|
@ -325,10 +456,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
/* Allocate some anonymous memory. If possible use the cache. */
|
||||
size_t guardsize;
|
||||
size_t reported_guardsize;
|
||||
size_t reqsize;
|
||||
void *mem;
|
||||
const int prot = (PROT_READ | PROT_WRITE
|
||||
| ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
|
||||
|
||||
/* Adjust the stack size for alignment. */
|
||||
size &= ~tls_static_align_m1;
|
||||
|
@ -358,16 +486,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
return EINVAL;
|
||||
|
||||
/* Try to get a stack from the cache. */
|
||||
reqsize = size;
|
||||
pd = get_cached_stack (&size, &mem);
|
||||
if (pd == NULL)
|
||||
{
|
||||
/* If a guard page is required, avoid committing memory by first
|
||||
allocate with PROT_NONE and then reserve with required permission
|
||||
excluding the guard page. */
|
||||
mem = __mmap (NULL, size, (guardsize == 0) ? prot : PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||
|
||||
mem = allocate_thread_stack (size, guardsize);
|
||||
if (__glibc_unlikely (mem == MAP_FAILED))
|
||||
return errno;
|
||||
|
||||
|
@ -394,16 +516,11 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
#endif
|
||||
|
||||
/* Now mprotect the required region excluding the guard area. */
|
||||
if (__glibc_likely (guardsize > 0))
|
||||
{
|
||||
char *guard = guard_position (mem, size, guardsize, pd,
|
||||
pagesize_m1);
|
||||
if (setup_stack_prot (mem, size, guard, guardsize, prot) != 0)
|
||||
if (!setup_stack_prot (mem, size, pd, guardsize, pagesize_m1))
|
||||
{
|
||||
__munmap (mem, size);
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the stack-related values. */
|
||||
pd->stackblock = mem;
|
||||
|
@ -456,14 +573,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
which will be read next. */
|
||||
}
|
||||
|
||||
/* Create or resize the guard area if necessary. */
|
||||
if (__glibc_unlikely (guardsize > pd->guardsize))
|
||||
/* Create or resize the guard area if necessary on an already
|
||||
allocated stack. */
|
||||
if (!adjust_stack_prot (mem, size, pd, guardsize, pagesize_m1))
|
||||
{
|
||||
char *guard = guard_position (mem, size, guardsize, pd,
|
||||
pagesize_m1);
|
||||
if (__mprotect (guard, guardsize, PROT_NONE) != 0)
|
||||
{
|
||||
mprot_error:
|
||||
lll_lock (GL (dl_stack_cache_lock), LLL_PRIVATE);
|
||||
|
||||
/* Remove the thread from the list. */
|
||||
|
@ -485,30 +598,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
}
|
||||
|
||||
pd->guardsize = guardsize;
|
||||
}
|
||||
else if (__builtin_expect (pd->guardsize - guardsize > size - reqsize,
|
||||
0))
|
||||
{
|
||||
/* The old guard area is too large. */
|
||||
|
||||
#if _STACK_GROWS_DOWN
|
||||
if (__mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
|
||||
prot) != 0)
|
||||
goto mprot_error;
|
||||
#elif _STACK_GROWS_UP
|
||||
char *new_guard = (char *)(((uintptr_t) pd - guardsize)
|
||||
& ~pagesize_m1);
|
||||
char *old_guard = (char *)(((uintptr_t) pd - pd->guardsize)
|
||||
& ~pagesize_m1);
|
||||
/* The guard size difference might be > 0, but once rounded
|
||||
to the nearest page the size difference might be zero. */
|
||||
if (new_guard > old_guard
|
||||
&& __mprotect (old_guard, new_guard - old_guard, prot) != 0)
|
||||
goto mprot_error;
|
||||
#endif
|
||||
|
||||
pd->guardsize = guardsize;
|
||||
}
|
||||
/* The pthread_getattr_np() calls need to get passed the size
|
||||
requested in the attribute, regardless of how large the
|
||||
actually used guardsize is. */
|
||||
|
@ -549,10 +638,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Maximum supported name from initial kernel support, not exported
|
||||
by user API. */
|
||||
#define ANON_VMA_NAME_MAX_LEN 80
|
||||
|
||||
#define SET_STACK_NAME(__prefix, __stack, __stacksize, __tid) \
|
||||
({ \
|
||||
char __stack_name[sizeof (__prefix) + \
|
||||
|
@ -568,19 +653,21 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
static void
|
||||
name_stack_maps (struct pthread *pd, bool set)
|
||||
{
|
||||
size_t adjust = pd->stack_mode == ALLOCATE_GUARD_PROT_NONE ?
|
||||
pd->guardsize : 0;
|
||||
#if _STACK_GROWS_DOWN
|
||||
void *stack = pd->stackblock + pd->guardsize;
|
||||
void *stack = pd->stackblock + adjust;
|
||||
#else
|
||||
void *stack = pd->stackblock;
|
||||
#endif
|
||||
size_t stacksize = pd->stackblock_size - pd->guardsize;
|
||||
size_t stacksize = pd->stackblock_size - adjust;
|
||||
|
||||
if (!set)
|
||||
__set_vma_name (stack, stacksize, NULL);
|
||||
__set_vma_name (stack, stacksize, " glibc: unused stack");
|
||||
else
|
||||
{
|
||||
unsigned int tid = pd->tid;
|
||||
if (pd->user_stack)
|
||||
if (pd->stack_mode == ALLOCATE_GUARD_USER)
|
||||
SET_STACK_NAME (" glibc: pthread user stack: ", stack, stacksize, tid);
|
||||
else
|
||||
SET_STACK_NAME (" glibc: pthread stack: ", stack, stacksize, tid);
|
||||
|
|
|
@ -125,6 +125,12 @@ struct priority_protection_data
|
|||
unsigned int priomap[];
|
||||
};
|
||||
|
||||
enum allocate_stack_mode_t
|
||||
{
|
||||
ALLOCATE_GUARD_MADV_GUARD = 0,
|
||||
ALLOCATE_GUARD_PROT_NONE = 1,
|
||||
ALLOCATE_GUARD_USER = 2,
|
||||
};
|
||||
|
||||
/* Thread descriptor data structure. */
|
||||
struct pthread
|
||||
|
@ -324,7 +330,7 @@ struct pthread
|
|||
bool report_events;
|
||||
|
||||
/* True if the user provided the stack. */
|
||||
bool user_stack;
|
||||
enum allocate_stack_mode_t stack_mode;
|
||||
|
||||
/* True if thread must stop at startup time. */
|
||||
bool stopped_start;
|
||||
|
|
|
@ -120,7 +120,7 @@ __nptl_deallocate_stack (struct pthread *pd)
|
|||
not reset the 'used' flag in the 'tid' field. This is done by
|
||||
the kernel. If no thread has been created yet this field is
|
||||
still zero. */
|
||||
if (__glibc_likely (! pd->user_stack))
|
||||
if (__glibc_likely (pd->stack_mode != ALLOCATE_GUARD_USER))
|
||||
(void) queue_stack (pd);
|
||||
else
|
||||
/* Free the memory associated with the ELF TLS. */
|
||||
|
|
|
@ -273,11 +273,6 @@ __condvar_cleanup_waiting (void *arg)
|
|||
(If the format of __wrefs is changed, update nptl_lock_constants.pysym
|
||||
and the pretty printers.)
|
||||
For each of the two groups, we have:
|
||||
__g_refs: Futex waiter reference count.
|
||||
* LSB is true if waiters should run futex_wake when they remove the
|
||||
last reference.
|
||||
* Reference count used by waiters concurrently with signalers that have
|
||||
acquired the condvar-internal lock.
|
||||
__g_signals: The number of signals that can still be consumed, relative to
|
||||
the current g1_start. (i.e. g1_start with the signal count added)
|
||||
* Used as a futex word by waiters. Used concurrently by waiters and
|
||||
|
|
|
@ -554,7 +554,7 @@ start_thread (void *arg)
|
|||
to avoid creating a new free-state block during thread release. */
|
||||
__getrandom_vdso_release (pd);
|
||||
|
||||
if (!pd->user_stack)
|
||||
if (pd->stack_mode != ALLOCATE_GUARD_USER)
|
||||
advise_stack_range (pd->stackblock, pd->stackblock_size, (uintptr_t) pd,
|
||||
pd->guardsize);
|
||||
|
||||
|
|
|
@ -145,9 +145,9 @@ __pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
|
|||
> (size_t) iattr->stackaddr - last_to)
|
||||
iattr->stacksize = (size_t) iattr->stackaddr - last_to;
|
||||
#else
|
||||
/* The limit might be too high. */
|
||||
/* The limit might be too low. */
|
||||
if ((size_t) iattr->stacksize
|
||||
> to - (size_t) iattr->stackaddr)
|
||||
< to - (size_t) iattr->stackaddr)
|
||||
iattr->stacksize = to - (size_t) iattr->stackaddr;
|
||||
#endif
|
||||
/* We succeed and no need to look further. */
|
||||
|
|
369
nptl/tst-guard1.c
Normal file
369
nptl/tst-guard1.c
Normal file
|
@ -0,0 +1,369 @@
|
|||
/* Basic tests for pthread guard area.
|
||||
Copyright (C) 2025 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 <array_length.h>
|
||||
#include <pthreaddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <stackinfo.h>
|
||||
#include <stdio.h>
|
||||
#include <support/check.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <support/xsignal.h>
|
||||
#include <support/xthread.h>
|
||||
#include <support/xunistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static long int pagesz;
|
||||
|
||||
/* To check if the guard region is inaccessible, the thread tries read/writes
|
||||
on it and checks if a SIGSEGV is generated. */
|
||||
|
||||
static volatile sig_atomic_t signal_jump_set;
|
||||
static sigjmp_buf signal_jmp_buf;
|
||||
|
||||
static void
|
||||
sigsegv_handler (int sig)
|
||||
{
|
||||
if (signal_jump_set == 0)
|
||||
return;
|
||||
|
||||
siglongjmp (signal_jmp_buf, sig);
|
||||
}
|
||||
|
||||
static bool
|
||||
try_access_buf (char *ptr, bool write)
|
||||
{
|
||||
signal_jump_set = true;
|
||||
|
||||
bool failed = sigsetjmp (signal_jmp_buf, 0) != 0;
|
||||
if (!failed)
|
||||
{
|
||||
if (write)
|
||||
*(volatile char *)(ptr) = 'x';
|
||||
else
|
||||
*(volatile char *)(ptr);
|
||||
}
|
||||
|
||||
signal_jump_set = false;
|
||||
return !failed;
|
||||
}
|
||||
|
||||
static bool
|
||||
try_read_buf (char *ptr)
|
||||
{
|
||||
return try_access_buf (ptr, false);
|
||||
}
|
||||
|
||||
static bool
|
||||
try_write_buf (char *ptr)
|
||||
{
|
||||
return try_access_buf (ptr, true);
|
||||
}
|
||||
|
||||
static bool
|
||||
try_read_write_buf (char *ptr)
|
||||
{
|
||||
return try_read_buf (ptr) && try_write_buf(ptr);
|
||||
}
|
||||
|
||||
|
||||
/* Return the guard region of the current thread (it only makes sense on
|
||||
a thread created by pthread_created). */
|
||||
|
||||
struct stack_t
|
||||
{
|
||||
char *stack;
|
||||
size_t stacksize;
|
||||
char *guard;
|
||||
size_t guardsize;
|
||||
};
|
||||
|
||||
static inline size_t
|
||||
adjust_stacksize (size_t stacksize)
|
||||
{
|
||||
/* For some ABIs, The guard page depends of the thread descriptor, which in
|
||||
turn rely on the require static TLS. The only supported _STACK_GROWS_UP
|
||||
ABI, hppa, defines TLS_DTV_AT_TP and it is not straightforward to
|
||||
calculate the guard region with current pthread APIs. So to get a
|
||||
correct stack size assumes an extra page after the guard area. */
|
||||
#if _STACK_GROWS_DOWN
|
||||
return stacksize;
|
||||
#elif _STACK_GROWS_UP
|
||||
return stacksize - pagesz;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct stack_t
|
||||
get_current_stack_info (void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
TEST_VERIFY_EXIT (pthread_getattr_np (pthread_self (), &attr) == 0);
|
||||
void *stack;
|
||||
size_t stacksize;
|
||||
TEST_VERIFY_EXIT (pthread_attr_getstack (&attr, &stack, &stacksize) == 0);
|
||||
size_t guardsize;
|
||||
TEST_VERIFY_EXIT (pthread_attr_getguardsize (&attr, &guardsize) == 0);
|
||||
/* The guardsize is reported as the current page size, although it might
|
||||
be adjusted to a larger value (aarch64 for instance). */
|
||||
if (guardsize != 0 && guardsize < ARCH_MIN_GUARD_SIZE)
|
||||
guardsize = ARCH_MIN_GUARD_SIZE;
|
||||
|
||||
#if _STACK_GROWS_DOWN
|
||||
void *guard = guardsize ? stack - guardsize : 0;
|
||||
#elif _STACK_GROWS_UP
|
||||
stacksize = adjust_stacksize (stacksize);
|
||||
void *guard = guardsize ? stack + stacksize : 0;
|
||||
#endif
|
||||
|
||||
pthread_attr_destroy (&attr);
|
||||
|
||||
return (struct stack_t) { stack, stacksize, guard, guardsize };
|
||||
}
|
||||
|
||||
struct thread_args_t
|
||||
{
|
||||
size_t stacksize;
|
||||
size_t guardsize;
|
||||
};
|
||||
|
||||
struct thread_args_t
|
||||
get_thread_args (const pthread_attr_t *attr)
|
||||
{
|
||||
size_t stacksize;
|
||||
size_t guardsize;
|
||||
|
||||
TEST_COMPARE (pthread_attr_getstacksize (attr, &stacksize), 0);
|
||||
TEST_COMPARE (pthread_attr_getguardsize (attr, &guardsize), 0);
|
||||
if (guardsize < ARCH_MIN_GUARD_SIZE)
|
||||
guardsize = ARCH_MIN_GUARD_SIZE;
|
||||
|
||||
return (struct thread_args_t) { stacksize, guardsize };
|
||||
}
|
||||
|
||||
static void
|
||||
set_thread_args (pthread_attr_t *attr, const struct thread_args_t *args)
|
||||
{
|
||||
xpthread_attr_setstacksize (attr, args->stacksize);
|
||||
xpthread_attr_setguardsize (attr, args->guardsize);
|
||||
}
|
||||
|
||||
static void *
|
||||
tf (void *closure)
|
||||
{
|
||||
struct thread_args_t *args = closure;
|
||||
|
||||
struct stack_t s = get_current_stack_info ();
|
||||
if (test_verbose)
|
||||
printf ("debug: [tid=%jd] stack = { .stack=%p, stacksize=%#zx, guard=%p, "
|
||||
"guardsize=%#zx }\n",
|
||||
(intmax_t) gettid (),
|
||||
s.stack,
|
||||
s.stacksize,
|
||||
s.guard,
|
||||
s.guardsize);
|
||||
|
||||
if (args != NULL)
|
||||
{
|
||||
TEST_COMPARE (adjust_stacksize (args->stacksize), s.stacksize);
|
||||
TEST_COMPARE (args->guardsize, s.guardsize);
|
||||
}
|
||||
|
||||
/* Ensure we can access the stack area. */
|
||||
TEST_COMPARE (try_read_buf (s.stack), true);
|
||||
TEST_COMPARE (try_read_buf (&s.stack[s.stacksize / 2]), true);
|
||||
TEST_COMPARE (try_read_buf (&s.stack[s.stacksize - 1]), true);
|
||||
|
||||
/* Check if accessing the guard area results in SIGSEGV. */
|
||||
if (s.guardsize > 0)
|
||||
{
|
||||
TEST_COMPARE (try_read_write_buf (s.guard), false);
|
||||
TEST_COMPARE (try_read_write_buf (&s.guard[s.guardsize / 2]), false);
|
||||
TEST_COMPARE (try_read_write_buf (&s.guard[s.guardsize] - 1), false);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Test 1: caller provided stack without guard. */
|
||||
static void
|
||||
do_test1 (void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
xpthread_attr_init (&attr);
|
||||
|
||||
size_t stacksize = support_small_thread_stack_size ();
|
||||
void *stack = xmmap (0,
|
||||
stacksize,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK,
|
||||
-1);
|
||||
xpthread_attr_setstack (&attr, stack, stacksize);
|
||||
xpthread_attr_setguardsize (&attr, 0);
|
||||
|
||||
struct thread_args_t args = { stacksize, 0 };
|
||||
pthread_t t = xpthread_create (&attr, tf, &args);
|
||||
void *status = xpthread_join (t);
|
||||
TEST_VERIFY (status == 0);
|
||||
|
||||
xpthread_attr_destroy (&attr);
|
||||
xmunmap (stack, stacksize);
|
||||
}
|
||||
|
||||
/* Test 2: same as 1., but with a guard area. */
|
||||
static void
|
||||
do_test2 (void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
xpthread_attr_init (&attr);
|
||||
|
||||
size_t stacksize = support_small_thread_stack_size ();
|
||||
void *stack = xmmap (0,
|
||||
stacksize,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK,
|
||||
-1);
|
||||
xpthread_attr_setstack (&attr, stack, stacksize);
|
||||
xpthread_attr_setguardsize (&attr, pagesz);
|
||||
|
||||
struct thread_args_t args = { stacksize, 0 };
|
||||
pthread_t t = xpthread_create (&attr, tf, &args);
|
||||
void *status = xpthread_join (t);
|
||||
TEST_VERIFY (status == 0);
|
||||
|
||||
xpthread_attr_destroy (&attr);
|
||||
xmunmap (stack, stacksize);
|
||||
}
|
||||
|
||||
/* Test 3: pthread_create with default values. */
|
||||
static void
|
||||
do_test3 (void)
|
||||
{
|
||||
pthread_t t = xpthread_create (NULL, tf, NULL);
|
||||
void *status = xpthread_join (t);
|
||||
TEST_VERIFY (status == 0);
|
||||
}
|
||||
|
||||
/* Test 4: pthread_create without a guard area. */
|
||||
static void
|
||||
do_test4 (void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
xpthread_attr_init (&attr);
|
||||
struct thread_args_t args = get_thread_args (&attr);
|
||||
args.stacksize += args.guardsize;
|
||||
args.guardsize = 0;
|
||||
set_thread_args (&attr, &args);
|
||||
|
||||
pthread_t t = xpthread_create (&attr, tf, &args);
|
||||
void *status = xpthread_join (t);
|
||||
TEST_VERIFY (status == 0);
|
||||
|
||||
xpthread_attr_destroy (&attr);
|
||||
}
|
||||
|
||||
/* Test 5: pthread_create with non default stack and guard size value. */
|
||||
static void
|
||||
do_test5 (void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
xpthread_attr_init (&attr);
|
||||
struct thread_args_t args = get_thread_args (&attr);
|
||||
args.guardsize += pagesz;
|
||||
args.stacksize += pagesz;
|
||||
set_thread_args (&attr, &args);
|
||||
|
||||
pthread_t t = xpthread_create (&attr, tf, &args);
|
||||
void *status = xpthread_join (t);
|
||||
TEST_VERIFY (status == 0);
|
||||
|
||||
xpthread_attr_destroy (&attr);
|
||||
}
|
||||
|
||||
/* Test 6: thread with the required size (stack + guard) that matches the
|
||||
test 3, but with a larger guard area. The pthread_create will need to
|
||||
increase the guard area. */
|
||||
static void
|
||||
do_test6 (void)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
xpthread_attr_init (&attr);
|
||||
struct thread_args_t args = get_thread_args (&attr);
|
||||
args.guardsize += pagesz;
|
||||
args.stacksize -= pagesz;
|
||||
set_thread_args (&attr, &args);
|
||||
|
||||
pthread_t t = xpthread_create (&attr, tf, &args);
|
||||
void *status = xpthread_join (t);
|
||||
TEST_VERIFY (status == 0);
|
||||
|
||||
xpthread_attr_destroy (&attr);
|
||||
}
|
||||
|
||||
/* Test 7: pthread_create with default values, the requires size matches the
|
||||
one from test 3 and 6 (but with a reduced guard ares). The
|
||||
pthread_create should use the cached stack from previous tests, but it
|
||||
would require to reduce the guard area. */
|
||||
static void
|
||||
do_test7 (void)
|
||||
{
|
||||
pthread_t t = xpthread_create (NULL, tf, NULL);
|
||||
void *status = xpthread_join (t);
|
||||
TEST_VERIFY (status == 0);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
pagesz = sysconf (_SC_PAGESIZE);
|
||||
|
||||
{
|
||||
struct sigaction sa = {
|
||||
.sa_handler = sigsegv_handler,
|
||||
.sa_flags = SA_NODEFER,
|
||||
};
|
||||
sigemptyset (&sa.sa_mask);
|
||||
xsigaction (SIGSEGV, &sa, NULL);
|
||||
/* Some system generates SIGBUS accessing the guard area when it is
|
||||
setup with madvise. */
|
||||
xsigaction (SIGBUS, &sa, NULL);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *descr;
|
||||
void (*test)(void);
|
||||
} tests[] = {
|
||||
{ "user provided stack without guard", do_test1 },
|
||||
{ "user provided stack with guard", do_test2 },
|
||||
{ "default attribute", do_test3 },
|
||||
{ "default attribute without guard", do_test4 },
|
||||
{ "non default stack and guard sizes", do_test5 },
|
||||
{ "reused stack with larger guard", do_test6 },
|
||||
{ "reused stack with smaller guard", do_test7 },
|
||||
};
|
||||
|
||||
for (int i = 0; i < array_length (tests); i++)
|
||||
{
|
||||
printf ("debug: test%01d: %s\n", i, tests[i].descr);
|
||||
tests[i].test();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
|
@ -367,6 +367,7 @@ tests += tst-nss-files-hosts-multi
|
|||
tests += tst-nss-files-hosts-getent
|
||||
tests += tst-nss-files-alias-leak
|
||||
tests += tst-nss-files-alias-truncated
|
||||
tests += tst-nss-files-network
|
||||
# tst_fgetgrent currently only works with shared libraries
|
||||
test-srcs := tst_fgetgrent
|
||||
ifeq ($(run-built-tests),yes)
|
||||
|
|
|
@ -42,7 +42,8 @@ LINE_PARSER
|
|||
|
||||
STRING_FIELD (addr, isspace, 1);
|
||||
/* 'inet_network' does not add zeroes at the end if the network number
|
||||
does not four byte values. We add them ourselves if necessary. */
|
||||
does not contain four byte values. We shift result ourselves if
|
||||
necessary. */
|
||||
cp = strchr (addr, '.');
|
||||
if (cp != NULL)
|
||||
{
|
||||
|
@ -56,20 +57,11 @@ LINE_PARSER
|
|||
++n;
|
||||
}
|
||||
}
|
||||
if (n < 4)
|
||||
{
|
||||
char *newp = (char *) alloca (strlen (addr) + (4 - n) * 2 + 1);
|
||||
cp = stpcpy (newp, addr);
|
||||
do
|
||||
{
|
||||
*cp++ = '.';
|
||||
*cp++ = '0';
|
||||
}
|
||||
while (++n < 4);
|
||||
*cp = '\0';
|
||||
addr = newp;
|
||||
}
|
||||
result->n_net = __inet_network (addr);
|
||||
if (result->n_net == INADDR_NONE)
|
||||
return 0;
|
||||
if (n < 4)
|
||||
result->n_net <<= 8 * (4 - n);
|
||||
result->n_addrtype = AF_INET;
|
||||
|
||||
})
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue