mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
Compare commits
No commits in common. "master" and "glibc-2.41" have entirely different histories.
master
...
glibc-2.41
406 changed files with 4117 additions and 25066 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 misc
|
||||
rpath-dirs = math elf dlfcn nss nis rt resolv mathvec support
|
||||
rpath-link = \
|
||||
$(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
|
||||
else # build-static
|
||||
|
|
27
NEWS
27
NEWS
|
@ -5,33 +5,6 @@ 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,31 +334,3 @@ 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,20 +21,5 @@ 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,7 +39,6 @@ tests := \
|
|||
test-assert-perr \
|
||||
tst-assert-c++ \
|
||||
tst-assert-g++ \
|
||||
tst-assert-sa-2025-0001 \
|
||||
# tests
|
||||
|
||||
ifeq ($(have-cxx-thread_local),yes)
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
/* 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,20 +28,16 @@ bench-math := \
|
|||
acosf \
|
||||
acosh \
|
||||
acoshf \
|
||||
acospif \
|
||||
asin \
|
||||
asinf \
|
||||
asinh \
|
||||
asinhf \
|
||||
asinpif \
|
||||
atan \
|
||||
atan2 \
|
||||
atan2f \
|
||||
atan2pif \
|
||||
atanf \
|
||||
atanh \
|
||||
atanhf \
|
||||
atanpif \
|
||||
cbrt \
|
||||
cbrtf \
|
||||
ceil \
|
||||
|
@ -50,7 +46,6 @@ bench-math := \
|
|||
cosf \
|
||||
cosh \
|
||||
coshf \
|
||||
cospif \
|
||||
erf \
|
||||
erfc \
|
||||
erfcf \
|
||||
|
@ -115,13 +110,11 @@ bench-math := \
|
|||
sinf \
|
||||
sinh \
|
||||
sinhf \
|
||||
sinpif \
|
||||
sqrt \
|
||||
tan \
|
||||
tanf \
|
||||
tanh \
|
||||
tanhf \
|
||||
tanpif \
|
||||
tgamma \
|
||||
tgammaf \
|
||||
trunc \
|
||||
|
@ -201,7 +194,6 @@ string-benchset := \
|
|||
strcpy_chk \
|
||||
strcspn \
|
||||
strlen \
|
||||
strlen-random \
|
||||
strncasecmp \
|
||||
strncat \
|
||||
strncmp \
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -22,8 +22,9 @@
|
|||
#else
|
||||
# define TEST_NAME "bzero"
|
||||
#endif
|
||||
#define START_SIZE (64 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
|
||||
#define START_SIZE (128 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 64 * 1024 * 1024)
|
||||
#define TIMEOUT (20 * 60)
|
||||
#include "bench-string.h"
|
||||
|
||||
#include "json-lib.h"
|
||||
|
@ -51,7 +52,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 = (MIN_PAGE_SIZE * 64) / n;
|
||||
size_t i, iters = 16;
|
||||
timing_t start, stop, cur;
|
||||
|
||||
TIMING_NOW (start);
|
||||
|
@ -73,13 +74,20 @@ 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,9 +19,10 @@
|
|||
#ifndef MEMCPY_RESULT
|
||||
# define MEMCPY_RESULT(dst, len) dst
|
||||
# define START_SIZE (64 * 1024)
|
||||
# define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
|
||||
# define MIN_PAGE_SIZE (getpagesize () + 32 * 1024 * 1024)
|
||||
# define TEST_MAIN
|
||||
# define TEST_NAME "memcpy"
|
||||
# define TIMEOUT (20 * 60)
|
||||
# include "bench-string.h"
|
||||
|
||||
IMPL (memcpy, 1)
|
||||
|
@ -35,7 +36,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 = (MIN_PAGE_SIZE * 8) / len;
|
||||
size_t i, iters = 16;
|
||||
timing_t start, stop, cur;
|
||||
|
||||
TIMING_NOW (start);
|
||||
|
@ -58,7 +59,12 @@ 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,10 +16,12 @@
|
|||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#define START_SIZE (64 * 1024)
|
||||
#define BASE_PAGE_SIZE (1024 * 1024)
|
||||
#define START_SIZE (4 * 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"
|
||||
|
||||
|
@ -31,7 +33,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 = (MIN_PAGE_SIZE * 8) / len;
|
||||
size_t i, iters = 16;
|
||||
timing_t start, stop, cur;
|
||||
|
||||
TIMING_NOW (start);
|
||||
|
@ -52,8 +54,13 @@ do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len)
|
|||
size_t i, j;
|
||||
char *s1, *s2;
|
||||
|
||||
align1 &= 4095;
|
||||
align2 &= 4095;
|
||||
align1 &= 127;
|
||||
if (align1 + len >= page_size)
|
||||
return;
|
||||
|
||||
align2 &= 127;
|
||||
if (align2 + len >= page_size)
|
||||
return;
|
||||
|
||||
s1 = (char *) (buf2 + align1);
|
||||
s2 = (char *) (buf2 + align2);
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
|
||||
#define TEST_MAIN
|
||||
#define TEST_NAME "memset"
|
||||
#define START_SIZE (64 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 16 * 1024 * 1024)
|
||||
#define START_SIZE (128 * 1024)
|
||||
#define MIN_PAGE_SIZE (getpagesize () + 64 * 1024 * 1024)
|
||||
#define TIMEOUT (20 * 60)
|
||||
#include "bench-string.h"
|
||||
|
||||
#include "json-lib.h"
|
||||
|
@ -34,7 +35,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 = (MIN_PAGE_SIZE * 64) / n;
|
||||
size_t i, iters = 16;
|
||||
timing_t start, stop, cur;
|
||||
|
||||
TIMING_NOW (start);
|
||||
|
@ -52,6 +53,10 @@ 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);
|
||||
|
@ -59,7 +64,10 @@ 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);
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
/* 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>
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -53,7 +53,6 @@ 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,7 +659,6 @@ 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
|
||||
|
@ -7115,40 +7114,6 @@ 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
|
||||
|
@ -8943,105 +8908,6 @@ 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,10 +1318,6 @@ 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)
|
||||
|
@ -1996,23 +1992,6 @@ 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,7 +30,6 @@
|
|||
#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,6 +34,7 @@ routines = \
|
|||
dl-addr \
|
||||
dl-addr-obj \
|
||||
dl-early_allocate \
|
||||
dl-find_object \
|
||||
dl-iteratephdr \
|
||||
dl-libc \
|
||||
dl-origin \
|
||||
|
@ -60,7 +61,6 @@ dl-routines = \
|
|||
dl-deps \
|
||||
dl-exception \
|
||||
dl-execstack \
|
||||
dl-find_object \
|
||||
dl-fini \
|
||||
dl-init \
|
||||
dl-load \
|
||||
|
@ -379,7 +379,6 @@ tests += \
|
|||
tst-align3 \
|
||||
tst-audit-tlsdesc \
|
||||
tst-audit-tlsdesc-dlopen \
|
||||
tst-audit-tlsdesc-dlopen2 \
|
||||
tst-audit1 \
|
||||
tst-audit2 \
|
||||
tst-audit8 \
|
||||
|
@ -864,7 +863,6 @@ modules-names += \
|
|||
tst-auditmanymod8 \
|
||||
tst-auditmanymod9 \
|
||||
tst-auditmod-tlsdesc \
|
||||
tst-auditmod-tlsdesc2 \
|
||||
tst-auditmod1 \
|
||||
tst-auditmod11 \
|
||||
tst-auditmod12 \
|
||||
|
@ -1137,14 +1135,12 @@ 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
|
||||
|
@ -1159,11 +1155,9 @@ 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)
|
||||
|
@ -1994,9 +1988,6 @@ $(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
|
||||
|
@ -2006,9 +1997,6 @@ 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))
|
||||
|
@ -2086,7 +2074,6 @@ $(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)
|
||||
|
@ -3202,9 +3189,6 @@ $(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,6 +21,7 @@
|
|||
#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,6 +24,7 @@
|
|||
#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,7 +463,8 @@ _dl_find_object (void *pc1, struct dl_find_object *result)
|
|||
return -1;
|
||||
} /* Transaction retry loop. */
|
||||
}
|
||||
rtld_hidden_def (_dl_find_object)
|
||||
hidden_def (__dl_find_object)
|
||||
weak_alias (__dl_find_object, _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,6 +23,7 @@
|
|||
#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,3 +226,110 @@ __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,109 +19,8 @@
|
|||
#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,8 +1421,10 @@ 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_soname (l) != NULL)
|
||||
add_name_to_object (l, l_soname (l));
|
||||
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));
|
||||
#else
|
||||
/* Audit modules only exist when linking is dynamic so ORIGNAME
|
||||
cannot be non-NULL. */
|
||||
|
@ -1432,7 +1434,9 @@ 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_soname (l) != NULL && strcmp (l_soname(l), LIBC_SO) == 0)
|
||||
&& l->l_info[DT_SONAME] != NULL
|
||||
&& strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||
+ l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0)
|
||||
GL(dl_ns)[nsid].libc_map = l;
|
||||
|
||||
/* _dl_close can only eventually undo the module ID assignment (via
|
||||
|
@ -1883,42 +1887,10 @@ open_path (const char *name, size_t namelen, int mode,
|
|||
return -1;
|
||||
}
|
||||
|
||||
struct link_map *
|
||||
_dl_lookup_map (Lmid_t nsid, const char *name)
|
||||
{
|
||||
assert (nsid >= 0);
|
||||
assert (nsid < GL(dl_nns));
|
||||
|
||||
/* Look for this name among those already loaded. */
|
||||
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
|
||||
yet been opened. */
|
||||
if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0))
|
||||
continue;
|
||||
if (!_dl_name_match_p (name, l))
|
||||
{
|
||||
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, l_soname (l));
|
||||
l->l_soname_added = 1;
|
||||
}
|
||||
|
||||
/* We have a match. */
|
||||
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,
|
||||
_dl_map_object (struct link_map *loader, const char *name,
|
||||
int type, int trace_mode, int mode, Lmid_t nsid)
|
||||
{
|
||||
int fd;
|
||||
|
@ -1928,6 +1900,39 @@ _dl_map_new_object (struct link_map *loader, const char *name,
|
|||
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)
|
||||
{
|
||||
/* If the requested name matches the soname of a loaded object,
|
||||
use that object. Elide this check for names that have not
|
||||
yet been opened. */
|
||||
if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0))
|
||||
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)
|
||||
continue;
|
||||
|
||||
/* We have a match on a new name -- cache it. */
|
||||
add_name_to_object (l, soname);
|
||||
l->l_soname_added = 1;
|
||||
}
|
||||
|
||||
/* We have a match. */
|
||||
return l;
|
||||
}
|
||||
|
||||
/* Display information if we are debugging. */
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)
|
||||
&& loader != NULL)
|
||||
|
@ -2178,17 +2183,6 @@ _dl_map_new_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,7 +18,6 @@
|
|||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <dl-load.h>
|
||||
#include <setvmaname.h>
|
||||
|
||||
/* Map a segment and align it properly. */
|
||||
|
||||
|
@ -183,41 +182,12 @@ _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,7 +49,8 @@ struct dl_open_args
|
|||
{
|
||||
const char *file;
|
||||
int mode;
|
||||
struct link_map *caller_map; /* Derived from the caller address. */
|
||||
/* This is the caller of the dlopen() function. */
|
||||
const void *caller_dlopen;
|
||||
struct link_map *map;
|
||||
/* Namespace ID. */
|
||||
Lmid_t nsid;
|
||||
|
@ -492,29 +493,36 @@ 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
|
||||
|
@ -530,9 +538,8 @@ dl_open_worker_begin (void *a)
|
|||
_dl_debug_initialize (0, args->nsid);
|
||||
|
||||
/* Load the named object. */
|
||||
struct link_map *new = args->map;
|
||||
if (new == NULL)
|
||||
args->map = new = _dl_map_new_object (args->caller_map, file, lt_loaded, 0,
|
||||
struct link_map *new;
|
||||
args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
|
||||
mode | __RTLD_CALLMAP, args->nsid);
|
||||
|
||||
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
|
||||
|
@ -550,7 +557,7 @@ dl_open_worker_begin (void *a)
|
|||
/* This object is directly loaded. */
|
||||
++new->l_direct_opencount;
|
||||
|
||||
/* It was already open. See is_already_fully_open above. */
|
||||
/* It was already open. */
|
||||
if (__glibc_unlikely (new->l_searchlist.r_list != NULL))
|
||||
{
|
||||
/* Let the user know about the opencount. */
|
||||
|
@ -610,7 +617,9 @@ 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 (l_soname (map) != NULL && strcmp (l_soname (map), LD_SO) == 0)
|
||||
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)
|
||||
__rtld_static_init (map);
|
||||
#endif
|
||||
}
|
||||
|
@ -852,6 +861,8 @@ 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). */
|
||||
|
@ -859,34 +870,6 @@ 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,8 +51,7 @@ _dl_relocate_static_pie (void)
|
|||
switch (ph->p_type)
|
||||
{
|
||||
case PT_LOAD:
|
||||
/* Skip the empty PT_LOAD segment at offset 0. */
|
||||
if (ph->p_filesz != 0 && ph->p_offset == 0)
|
||||
if (ph->p_offset == 0)
|
||||
file_p_vaddr = ph->p_vaddr;
|
||||
break;
|
||||
case PT_DYNAMIC:
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#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,12 +39,6 @@
|
|||
|
||||
#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
|
||||
|
@ -566,13 +560,6 @@ _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,6 +22,7 @@
|
|||
#include <unistd.h>
|
||||
#include "version.h"
|
||||
|
||||
#include <dl-procinfo.h>
|
||||
#include <dl-hwcaps.h>
|
||||
|
||||
void
|
||||
|
|
13
elf/elf.h
13
elf/elf.h
|
@ -2906,6 +2906,19 @@ 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,6 +45,7 @@
|
|||
#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,6 +35,7 @@
|
|||
#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>
|
||||
|
@ -1054,9 +1055,13 @@ static void
|
|||
rtld_chain_load (struct link_map *main_map, char *argv0)
|
||||
{
|
||||
/* The dynamic loader run against itself. */
|
||||
const char *rtld_soname = l_soname (&_dl_rtld_map);
|
||||
if (l_soname (main_map) != NULL
|
||||
&& strcmp (rtld_soname, l_soname (main_map)) == 0)
|
||||
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)
|
||||
_dl_fatal_printf ("%s: loader cannot load itself\n", rtld_soname);
|
||||
|
||||
/* With DT_NEEDED dependencies, the executable is dynamically
|
||||
|
@ -1627,20 +1632,20 @@ dl_main (const ElfW(Phdr) *phdr,
|
|||
|
||||
/* If the current libname is different from the SONAME, add the
|
||||
latter as well. */
|
||||
{
|
||||
const char *soname = l_soname (&_dl_rtld_map);
|
||||
if (soname != NULL
|
||||
&& strcmp (_dl_rtld_map.l_libname->name, soname) != 0)
|
||||
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)
|
||||
{
|
||||
static struct libname_list newname;
|
||||
newname.name = soname;
|
||||
newname.name = ((char *) D_PTR (&_dl_rtld_map, l_info[DT_STRTAB])
|
||||
+ _dl_rtld_map.l_info[DT_SONAME]->d_un.d_ptr);
|
||||
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);
|
||||
|
@ -1653,8 +1658,10 @@ 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 (l_soname (main_map) != NULL
|
||||
&& strcmp (l_soname (main_map), LIBC_SO) == 0)
|
||||
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))
|
||||
GL(dl_ns)[LM_ID_BASE].libc_map = main_map;
|
||||
|
||||
/* Set up our cache of pointers into the hash table. */
|
||||
|
|
|
@ -76,13 +76,12 @@ 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)
|
||||
{
|
||||
const char *dsoname = l_soname (l);
|
||||
if (dsoname != NULL)
|
||||
{
|
||||
char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
|
||||
+ l->l_info[DT_SONAME]->d_un.d_val);
|
||||
l->l_libname->name = dsoname;
|
||||
l->l_name = (char *) dsoname;
|
||||
}
|
||||
l->l_name = dsoname;
|
||||
}
|
||||
|
||||
/* Add the vDSO to the object list. */
|
||||
|
|
|
@ -530,7 +530,10 @@ load_shobj (const char *name)
|
|||
printf ("string table: %p\n", result->dynstrtab);
|
||||
|
||||
/* Determine the soname. */
|
||||
result->soname = l_soname (map);
|
||||
if (map->l_info[DT_SONAME] == NULL)
|
||||
result->soname = NULL;
|
||||
else
|
||||
result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
|
||||
if (do_test && result->soname != NULL)
|
||||
printf ("soname: %s\n", result->soname);
|
||||
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/* 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>
|
|
@ -1,59 +0,0 @@
|
|||
/* 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;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/* 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"
|
68
htl/Makefile
68
htl/Makefile
|
@ -25,12 +25,21 @@ 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 \
|
||||
|
@ -41,9 +50,34 @@ 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 \
|
||||
|
@ -138,14 +172,6 @@ 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 \
|
||||
|
@ -163,15 +189,6 @@ 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 \
|
||||
|
@ -185,25 +202,8 @@ 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,13 +26,6 @@ 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;
|
||||
|
@ -45,14 +38,6 @@ 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;
|
||||
|
@ -63,22 +48,6 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -96,7 +65,7 @@ libc {
|
|||
pthread_equal;
|
||||
pthread_exit; pthread_getschedparam; pthread_setschedparam;
|
||||
pthread_mutex_destroy; pthread_mutex_init;
|
||||
pthread_mutex_lock; pthread_mutex_unlock;
|
||||
pthread_mutex_lock; pthread_mutex_trylock; pthread_mutex_unlock;
|
||||
pthread_self; pthread_setcancelstate; pthread_setcanceltype;
|
||||
__pthread_get_cleanup_stack;
|
||||
}
|
||||
|
@ -110,14 +79,8 @@ 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 {
|
||||
|
@ -146,35 +109,6 @@ 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;
|
||||
|
@ -193,7 +127,6 @@ libc {
|
|||
__pthread_attr_setstacksize;
|
||||
__pthread_attr_setstackaddr;
|
||||
__pthread_attr_setstack;
|
||||
__pthread_setcancelstate;
|
||||
__pthread_cond_broadcast;
|
||||
__pthread_cond_destroy;
|
||||
__pthread_cond_init;
|
||||
|
@ -204,16 +137,9 @@ 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;
|
||||
|
@ -248,6 +174,10 @@ 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;
|
||||
|
@ -265,8 +195,22 @@ libpthread {
|
|||
pthread_kill;
|
||||
__pthread_kill;
|
||||
|
||||
pthread_mutex_transfer_np;
|
||||
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_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;
|
||||
|
||||
|
@ -295,6 +239,11 @@ 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;
|
||||
|
@ -318,7 +267,14 @@ 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,5 +58,21 @@ 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,7 +203,10 @@ __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. */
|
||||
err = __pthread_sigmask (0, 0, &pthread->init_sigset);
|
||||
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);
|
||||
assert_perror (err);
|
||||
|
||||
if (start_routine)
|
||||
|
|
|
@ -28,8 +28,18 @@
|
|||
#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,9 +42,5 @@ __pthread_setcancelstate (int state, int *oldstate)
|
|||
|
||||
return 0;
|
||||
}
|
||||
libc_hidden_def (__pthread_setcancelstate)
|
||||
versioned_symbol (libc, __pthread_setcancelstate, pthread_setcancelstate, GLIBC_2_21);
|
||||
|
||||
#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_12, GLIBC_2_21)
|
||||
compat_symbol (libc, __pthread_setcancelstate, pthread_setcancelstate, GLIBC_2_12);
|
||||
#endif
|
||||
weak_alias (__pthread_setcancelstate, pthread_setcancelstate);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <shlib-compat.h>
|
||||
|
||||
#include <pt-internal.h>
|
||||
|
||||
int
|
||||
|
@ -42,9 +42,5 @@ __pthread_setcanceltype (int type, int *oldtype)
|
|||
|
||||
return 0;
|
||||
}
|
||||
libc_hidden_def (__pthread_setcanceltype)
|
||||
versioned_symbol (libc, __pthread_setcanceltype, pthread_setcanceltype, GLIBC_2_21);
|
||||
|
||||
#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_12, GLIBC_2_21)
|
||||
compat_symbol (libc, __pthread_setcanceltype, pthread_setcanceltype, GLIBC_2_12);
|
||||
#endif
|
||||
weak_alias (__pthread_setcanceltype, pthread_setcanceltype);
|
||||
|
|
|
@ -19,14 +19,15 @@
|
|||
#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 __sigthreadmask (_hurd_self_sigstate (), how, set, oset, 0);
|
||||
return __pthread_sigstate (self, how, set, oset, 0);
|
||||
}
|
||||
libc_hidden_def (__pthread_sigmask)
|
||||
versioned_symbol (libc, __pthread_sigmask, pthread_sigmask, GLIBC_2_41);
|
||||
|
|
|
@ -131,7 +131,6 @@ 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,
|
||||
string_t retryname,
|
||||
char retryname[1024],
|
||||
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,
|
||||
string_t retryname,
|
||||
char retryname[1024],
|
||||
int flags, mode_t mode,
|
||||
file_t *result);
|
||||
|
||||
|
|
|
@ -99,7 +99,6 @@ __lll_abstimed_lock (void *ptr,
|
|||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__lll_abstimed_lock)
|
||||
|
||||
/* Robust locks. */
|
||||
|
||||
|
@ -158,7 +157,6 @@ __lll_robust_lock (void *ptr, int flags)
|
|||
}
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__lll_robust_lock)
|
||||
|
||||
int
|
||||
__lll_robust_abstimed_lock (void *ptr,
|
||||
|
@ -208,7 +206,6 @@ __lll_robust_abstimed_lock (void *ptr,
|
|||
}
|
||||
}
|
||||
}
|
||||
libc_hidden_def (__lll_robust_abstimed_lock)
|
||||
|
||||
int
|
||||
__lll_robust_trylock (void *ptr)
|
||||
|
@ -228,7 +225,6 @@ __lll_robust_trylock (void *ptr)
|
|||
|
||||
return EBUSY;
|
||||
}
|
||||
libc_hidden_def (__lll_robust_trylock)
|
||||
|
||||
void
|
||||
__lll_robust_unlock (void *ptr, int flags)
|
||||
|
@ -245,5 +241,3 @@ __lll_robust_unlock (void *ptr, int flags)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
libc_hidden_def (__lll_robust_unlock)
|
||||
|
|
|
@ -68,27 +68,23 @@ 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. */
|
||||
|
@ -100,7 +96,6 @@ libc_hidden_proto (__lll_robust_trylock)
|
|||
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;
|
||||
string_t retryname;
|
||||
char retryname[1024]; /* XXX string_t LOSES! */
|
||||
int startport;
|
||||
|
||||
error_t lookup_op (mach_port_t startdir)
|
||||
|
|
|
@ -1611,31 +1611,18 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
|
|||
static void
|
||||
reauth_proc (mach_port_t new)
|
||||
{
|
||||
error_t err;
|
||||
mach_port_t ref, newproc;
|
||||
mach_port_t ref, ignore;
|
||||
|
||||
ref = __mach_reply_port ();
|
||||
err = HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
|
||||
if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
|
||||
__proc_reauthenticate (port, ref,
|
||||
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)
|
||||
|| __auth_user_authenticate (new, ref,
|
||||
MACH_MSG_TYPE_MAKE_SEND,
|
||||
&newproc);
|
||||
&ignore))
|
||||
&& ignore != MACH_PORT_NULL)
|
||||
__mach_port_deallocate (__mach_task_self (), ignore);
|
||||
__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);
|
||||
|
@ -1647,18 +1634,6 @@ 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;
|
||||
string_t retryname;
|
||||
char retryname[1024]; /* XXX string_t LOSES! */
|
||||
|
||||
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,
|
||||
string_t retryname,
|
||||
char retryname[1024],
|
||||
int flags, mode_t mode,
|
||||
file_t *result)
|
||||
{
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
#include <link.h> /* For ElfW. */
|
||||
#include <stdbool.h>
|
||||
|
||||
rtld_hidden_proto (_dl_find_object)
|
||||
extern __typeof (_dl_find_object) __dl_find_object;
|
||||
hidden_proto (__dl_find_object)
|
||||
|
||||
/* Internally used flag. */
|
||||
#define __RTLD_DLOPEN 0x80000000
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
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,8 +69,6 @@ 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,7 +32,6 @@
|
|||
#endif
|
||||
|
||||
#include <bits/types.h>
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
struct _IO_FILE;
|
||||
struct _IO_marker;
|
||||
|
@ -98,15 +97,8 @@ 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[12 * sizeof (int) - 5 * sizeof (void *)];
|
||||
char _unused2[15 * sizeof (int) - 5 * sizeof (void *)];
|
||||
};
|
||||
|
||||
/* These macros are used by bits/stdio.h and internal headers. */
|
||||
|
|
|
@ -127,48 +127,15 @@ _IO_new_file_init (struct _IO_FILE_plus *fp)
|
|||
int
|
||||
_IO_new_file_close_it (FILE *fp)
|
||||
{
|
||||
int flush_status = 0;
|
||||
int write_status;
|
||||
if (!_IO_file_is_open (fp))
|
||||
return EOF;
|
||||
|
||||
if ((fp->_flags & _IO_NO_WRITES) == 0
|
||||
&& (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
|
||||
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;
|
||||
}
|
||||
write_status = _IO_do_flush (fp);
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
write_status = 0;
|
||||
|
||||
_IO_unsave_markers (fp);
|
||||
|
||||
|
@ -193,7 +160,7 @@ _IO_new_file_close_it (FILE *fp)
|
|||
fp->_fileno = -1;
|
||||
fp->_offset = _IO_pos_BAD;
|
||||
|
||||
return close_status ? close_status : flush_status;
|
||||
return close_status ? close_status : write_status;
|
||||
}
|
||||
libc_hidden_ver (_IO_new_file_close_it, _IO_file_close_it)
|
||||
|
||||
|
@ -832,11 +799,6 @@ _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);
|
||||
|
@ -858,21 +820,17 @@ 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 (_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)
|
||||
if (__lseek64 (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base,
|
||||
SEEK_SET)
|
||||
!= fp->_IO_read_ptr - fp->_IO_buf_base)
|
||||
{
|
||||
fp->_flags |= _IO_ERR_SEEN;
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
fp->_offset = o;
|
||||
fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base;
|
||||
fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1110,18 +1068,11 @@ _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->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
|
||||
offset += fp->_IO_read_ptr - fp->_IO_read_base;
|
||||
break;
|
||||
case _IO_seek_set:
|
||||
break;
|
||||
|
@ -1234,7 +1185,6 @@ _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,7 +611,6 @@ _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
|
||||
|
@ -731,13 +730,6 @@ _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,42 +36,13 @@ _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. */
|
||||
if (written == request)
|
||||
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)
|
||||
return count;
|
||||
else
|
||||
return written / size;
|
||||
|
|
|
@ -604,6 +604,9 @@ 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,14 +6,6 @@
|
|||
vm_size_t
|
||||
__mig_strncpy (char *dst, const char *src, vm_size_t len)
|
||||
{
|
||||
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;
|
||||
return __stpncpy (dst, src, len) - dst;
|
||||
}
|
||||
weak_alias (__mig_strncpy, mig_strncpy)
|
||||
|
|
|
@ -4005,9 +4005,6 @@ _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
|
||||
|
@ -4244,9 +4241,6 @@ _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,6 +28,7 @@
|
|||
# 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
|
||||
|
@ -135,6 +136,7 @@ __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,25 +966,13 @@ 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,6 +46,71 @@ by @theglibc{}.
|
|||
@end deftypefun
|
||||
|
||||
@subsection POSIX Semaphores
|
||||
@Theglibc{} provides POSIX semaphores as well. These functions' names begin
|
||||
with @code{sem_} and they are declared in @file{semaphore.h}. @xref{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
|
||||
|
|
|
@ -282,22 +282,14 @@ 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,,\func\(\sec\)}
|
||||
@xref{Linux Kernel}
|
||||
@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html}
|
||||
@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,31 +929,18 @@ 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.
|
||||
|
||||
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
|
||||
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
|
||||
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. 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.
|
||||
tasks.
|
||||
|
||||
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.
|
||||
If there are no other tasks that share the calling task's absolute
|
||||
priority, this function doesn't have any effect.
|
||||
|
||||
To the extent that the containing program is oblivious to what other
|
||||
processes in the system are doing and how fast it executes, this
|
||||
|
@ -979,6 +966,7 @@ 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.
|
||||
|
@ -1012,7 +1000,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}.
|
||||
@manpageurl{sched_setattr,2}. @xref{Linux Kernel}.
|
||||
@end deftp
|
||||
|
||||
@deftypefun int sched_setaddr (pid_t @var{tid}, struct sched_attr *@var{attr}, unsigned int flags)
|
||||
|
|
|
@ -427,18 +427,9 @@ failure to properly emulate them.
|
|||
|
||||
@deftypevr Macro int SIGSYS
|
||||
@standards{Unix, signal.h}
|
||||
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.
|
||||
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.
|
||||
@end deftypevr
|
||||
|
||||
@node Termination Signals
|
||||
|
@ -761,11 +752,12 @@ that isn't connected. @xref{Sending Data}.
|
|||
@deftypevr Macro int SIGLOST
|
||||
@standards{GNU, signal.h}
|
||||
@cindex lost resource signal
|
||||
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.
|
||||
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.
|
||||
@end deftypevr
|
||||
|
||||
@deftypevr Macro int SIGXCPU
|
||||
|
@ -825,17 +817,6 @@ 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,18 +4346,6 @@ 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
|
||||
|
@ -4850,6 +4838,12 @@ 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,7 +498,10 @@ The symbols referred to in this section are declared in the file
|
|||
|
||||
@deftypefun int setlogmask (int @var{mask})
|
||||
@standards{BSD, syslog.h}
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{}}}
|
||||
@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.
|
||||
|
||||
@code{setlogmask} sets a mask (the ``logmask'') that determines which
|
||||
future @code{syslog} calls shall be ignored. If a program has not
|
||||
|
|
|
@ -554,8 +554,6 @@ 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
|
||||
|
@ -617,107 +615,6 @@ 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
|
||||
|
||||
|
@ -855,6 +752,16 @@ 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})
|
||||
|
@ -928,9 +835,6 @@ 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,7 +595,6 @@ 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}.
|
||||
|
||||
|
@ -604,7 +603,6 @@ 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,13 +366,8 @@ 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,7 +936,6 @@ 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
|
||||
|
@ -7292,8 +7291,6 @@ 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
|
||||
|
@ -8301,7 +8298,6 @@ 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
|
||||
|
@ -8665,7 +8661,6 @@ 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,31 +1061,6 @@ 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,31 +1789,6 @@ 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,31 +2115,6 @@ 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,31 +2532,6 @@ 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,10 +173,6 @@ 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,7 +289,6 @@ tests = \
|
|||
tst-dlsym1 \
|
||||
tst-exec4 \
|
||||
tst-exec5 \
|
||||
tst-guard1 \
|
||||
tst-initializers1 \
|
||||
tst-initializers1-c11 \
|
||||
tst-initializers1-c89 \
|
||||
|
@ -702,9 +701,6 @@ $(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,3 +1,7 @@
|
|||
pthread_attr_setguardsize
|
||||
|
||||
test effectiveness
|
||||
|
||||
pthread_attr_[sg]etschedparam
|
||||
|
||||
what to test?
|
||||
|
|
|
@ -146,37 +146,10 @@ 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, const struct pthread *pd,
|
||||
guard_position (void *mem, size_t size, size_t guardsize, struct pthread *pd,
|
||||
size_t pagesize_m1)
|
||||
{
|
||||
#if _STACK_GROWS_DOWN
|
||||
|
@ -186,131 +159,27 @@ guard_position (void *mem, size_t size, size_t guardsize, const struct pthread *
|
|||
#endif
|
||||
}
|
||||
|
||||
/* 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)
|
||||
/* 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)
|
||||
{
|
||||
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 false;
|
||||
return errno;
|
||||
#else
|
||||
size_t mprots1 = (uintptr_t) guard - (uintptr_t) mem;
|
||||
if (__mprotect (mem, mprots1, prot) != 0)
|
||||
return false;
|
||||
return errno;
|
||||
size_t mprots2 = ((uintptr_t) mem + size) - (uintptr_t) guardend;
|
||||
if (__mprotect (guardend, mprots2, prot) != 0)
|
||||
return false;
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Mark the memory of the stack as usable to the kernel. It frees everything
|
||||
|
@ -422,7 +291,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->stack_mode = ALLOCATE_GUARD_USER;
|
||||
pd->user_stack = true;
|
||||
|
||||
/* This is at least the second thread. */
|
||||
pd->header.multiple_threads = 1;
|
||||
|
@ -456,7 +325,10 @@ 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;
|
||||
|
@ -486,10 +358,16 @@ 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)
|
||||
{
|
||||
mem = allocate_thread_stack (size, guardsize);
|
||||
/* 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);
|
||||
|
||||
if (__glibc_unlikely (mem == MAP_FAILED))
|
||||
return errno;
|
||||
|
||||
|
@ -516,11 +394,16 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
#endif
|
||||
|
||||
/* Now mprotect the required region excluding the guard area. */
|
||||
if (!setup_stack_prot (mem, size, pd, guardsize, pagesize_m1))
|
||||
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)
|
||||
{
|
||||
__munmap (mem, size);
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remember the stack-related values. */
|
||||
pd->stackblock = mem;
|
||||
|
@ -573,10 +456,14 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
|||
which will be read next. */
|
||||
}
|
||||
|
||||
/* Create or resize the guard area if necessary on an already
|
||||
allocated stack. */
|
||||
if (!adjust_stack_prot (mem, size, pd, guardsize, pagesize_m1))
|
||||
/* Create or resize the guard area if necessary. */
|
||||
if (__glibc_unlikely (guardsize > pd->guardsize))
|
||||
{
|
||||
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. */
|
||||
|
@ -598,6 +485,30 @@ 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. */
|
||||
|
@ -638,6 +549,10 @@ 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) + \
|
||||
|
@ -653,21 +568,19 @@ 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 + adjust;
|
||||
void *stack = pd->stackblock + pd->guardsize;
|
||||
#else
|
||||
void *stack = pd->stackblock;
|
||||
#endif
|
||||
size_t stacksize = pd->stackblock_size - adjust;
|
||||
size_t stacksize = pd->stackblock_size - pd->guardsize;
|
||||
|
||||
if (!set)
|
||||
__set_vma_name (stack, stacksize, " glibc: unused stack");
|
||||
__set_vma_name (stack, stacksize, NULL);
|
||||
else
|
||||
{
|
||||
unsigned int tid = pd->tid;
|
||||
if (pd->stack_mode == ALLOCATE_GUARD_USER)
|
||||
if (pd->user_stack)
|
||||
SET_STACK_NAME (" glibc: pthread user stack: ", stack, stacksize, tid);
|
||||
else
|
||||
SET_STACK_NAME (" glibc: pthread stack: ", stack, stacksize, tid);
|
||||
|
|
|
@ -125,12 +125,6 @@ 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
|
||||
|
@ -330,7 +324,7 @@ struct pthread
|
|||
bool report_events;
|
||||
|
||||
/* True if the user provided the stack. */
|
||||
enum allocate_stack_mode_t stack_mode;
|
||||
bool user_stack;
|
||||
|
||||
/* 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->stack_mode != ALLOCATE_GUARD_USER))
|
||||
if (__glibc_likely (! pd->user_stack))
|
||||
(void) queue_stack (pd);
|
||||
else
|
||||
/* Free the memory associated with the ELF TLS. */
|
||||
|
|
|
@ -273,6 +273,11 @@ __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->stack_mode != ALLOCATE_GUARD_USER)
|
||||
if (!pd->user_stack)
|
||||
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 low. */
|
||||
/* The limit might be too high. */
|
||||
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. */
|
||||
|
|
|
@ -1,369 +0,0 @@
|
|||
/* 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,7 +367,6 @@ 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,8 +42,7 @@ LINE_PARSER
|
|||
|
||||
STRING_FIELD (addr, isspace, 1);
|
||||
/* 'inet_network' does not add zeroes at the end if the network number
|
||||
does not contain four byte values. We shift result ourselves if
|
||||
necessary. */
|
||||
does not four byte values. We add them ourselves if necessary. */
|
||||
cp = strchr (addr, '.');
|
||||
if (cp != NULL)
|
||||
{
|
||||
|
@ -57,11 +56,20 @@ LINE_PARSER
|
|||
++n;
|
||||
}
|
||||
}
|
||||
result->n_net = __inet_network (addr);
|
||||
if (result->n_net == INADDR_NONE)
|
||||
return 0;
|
||||
if (n < 4)
|
||||
result->n_net <<= 8 * (4 - n);
|
||||
{
|
||||
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);
|
||||
result->n_addrtype = AF_INET;
|
||||
|
||||
})
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
/* Test long entries and truncated numbers in /etc/networks (bug 32573/32575).
|
||||
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 <netdb.h>
|
||||
#include <gnu/lib-names.h>
|
||||
#include <nss.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <support/check.h>
|
||||
#include <support/check_nss.h>
|
||||
#include <support/namespace.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <support/xdlfcn.h>
|
||||
#include <support/xunistd.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#define STACK_LIM 1048576
|
||||
#define STRING_SIZE (2 * STACK_LIM)
|
||||
|
||||
struct support_chroot *chroot_env;
|
||||
|
||||
static void
|
||||
prepare (int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
char *content;
|
||||
char *entry = malloc (STRING_SIZE);
|
||||
struct rlimit lim;
|
||||
getrlimit (RLIMIT_STACK, &lim);
|
||||
lim.rlim_cur = STACK_LIM;
|
||||
setrlimit (RLIMIT_STACK, &lim);
|
||||
if (entry == NULL)
|
||||
{
|
||||
puts ("malloc failed, cannot test");
|
||||
exit (1);
|
||||
}
|
||||
memset (entry, 'A', STRING_SIZE);
|
||||
entry[STRING_SIZE - 1] = 0;
|
||||
ret = asprintf (&content, "%s\n%s\nnet3 %s\n",
|
||||
"net1 x0000000000Ff.077", /* legal 255.63.0.0 */
|
||||
"net2 xFF00000000.0.0.0", /* illegal */
|
||||
entry /* illegal */);
|
||||
if (ret == -1)
|
||||
{
|
||||
puts ("asprintf failed, cannot test");
|
||||
exit (1);
|
||||
}
|
||||
free (entry);
|
||||
chroot_env = support_chroot_create
|
||||
((struct support_chroot_configuration)
|
||||
{
|
||||
.networks = content
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
support_become_root ();
|
||||
if (!support_can_chroot ())
|
||||
return EXIT_UNSUPPORTED;
|
||||
|
||||
__nss_configure_lookup ("networks", "files");
|
||||
xdlopen (LIBNSS_FILES_SO, RTLD_NOW);
|
||||
|
||||
xchroot (chroot_env->path_chroot);
|
||||
|
||||
check_netent ("net1", getnetbyname ("net1"),
|
||||
"name: net1\n"
|
||||
"net: 0xff3f0000\n");
|
||||
check_netent ("net2", getnetbyname ("net2"), "error: HOST_NOT_FOUND\n");
|
||||
|
||||
support_chroot_free (chroot_env);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PREPARE prepare
|
||||
#include <support/test-driver.c>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue