mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 11:58:23 +08:00
Compare commits
56
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2431995fd0 | ||
|
|
d3f21e2615 | ||
|
|
583e97d196 | ||
|
|
2b89ce53dc | ||
|
|
c3f0d624e9 | ||
|
|
96ba247eed | ||
|
|
1ba2430890 | ||
|
|
98fa878ff0 | ||
|
|
47421c20fa | ||
|
|
7f08540d90 | ||
|
|
98bd74d428 | ||
|
|
84b5ab235e | ||
|
|
0d8743de85 | ||
|
|
8603348fa3 | ||
|
|
240ea3c09c | ||
|
|
411c5470ad | ||
|
|
e5da52d681 | ||
|
|
60c5087acb | ||
|
|
7220c4d393 | ||
|
|
e57ac229dc | ||
|
|
367c8c0e97 | ||
|
|
e9ba4bf620 | ||
|
|
181e58d747 | ||
|
|
40f3f5c1a5 | ||
|
|
7e3b1df6d4 | ||
|
|
964779a113 | ||
|
|
9e10cf821f | ||
|
|
74b7dd6b5a | ||
|
|
4b957d975d | ||
|
|
73efc556ac | ||
|
|
ace275b80b | ||
|
|
52a7cb28f9 | ||
|
|
1cfcdae979 | ||
|
|
7c44a0bf9c | ||
|
|
868fc27ff4 | ||
|
|
fbf200117d | ||
|
|
53eebacec0 | ||
|
|
f38fa7c980 | ||
|
|
64b3e177bc | ||
|
|
1ba307084e | ||
|
|
268ddcff50 | ||
|
|
54031961bf | ||
|
|
4bbfeb8e5b | ||
|
|
dcd2b97dd1 | ||
|
|
0941350c20 | ||
|
|
e28ad442e7 | ||
|
|
6eb48fe80c | ||
|
|
10dd17da71 | ||
|
|
4d0b1b0f61 | ||
|
|
bc6f839fb4 | ||
|
|
067fc32968 | ||
|
|
c096b008d2 | ||
|
|
44113a8ba2 | ||
|
|
2de15ac957 | ||
|
|
726a78867b | ||
|
|
86013ef5ce |
@@ -1,3 +1,119 @@
|
||||
2019-04-09 Carlos O'Donell <carlos@redhat.com>
|
||||
Kwok Cheung Yeung <kcy@codesourcery.com>
|
||||
|
||||
[BZ #16573]
|
||||
* malloc/mtrace.c: Define prototypes for all hooks.
|
||||
(set_default_hooks): New function.
|
||||
(set_trace_hooks): Likewise.
|
||||
(save_default_hooks): Likewise.
|
||||
(tr_freehook): Use new s*_hooks functions.
|
||||
(tr_mallochook): Likewise.
|
||||
(tr_reallochook): Likewise.
|
||||
(tr_memalignhook): Likewise.
|
||||
(mtrace): Likewise.
|
||||
(muntrace): Likewise.
|
||||
|
||||
2019-04-02 TAMUKI Shoichi <tamuki@linet.gr.jp>
|
||||
|
||||
[BZ #22964]
|
||||
* localedata/locales/ja_JP (LC_TIME): Add entry for the new Japanese
|
||||
era.
|
||||
|
||||
2019-03-02 TAMUKI Shoichi <tamuki@linet.gr.jp>
|
||||
|
||||
[BZ #24162]
|
||||
* localedata/locales/ja_JP (LC_TIME): Change the offset for Taisho
|
||||
gan-nen from 2 to 1. Problem reported by Morimitsu, Junji.
|
||||
|
||||
2019-03-21 Stefan Liebler <stli@linux.ibm.com>
|
||||
|
||||
* sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT):
|
||||
Add HWCAP_S390_VX and HWCAP_S390_VXE.
|
||||
|
||||
2019-01-31 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
CVE-2019-9169
|
||||
regex: fix read overrun [BZ #24114]
|
||||
Problem found by AddressSanitizer, reported by Hongxu Chen in:
|
||||
https://debbugs.gnu.org/34140
|
||||
* posix/regexec.c (proceed_next_node):
|
||||
Do not read past end of input buffer.
|
||||
|
||||
2019-03-13 Stefan Liebler <stli@linux.ibm.com>
|
||||
|
||||
* elf/dl-sysdep.c (_dl_show_auxv): Remove condition and always
|
||||
call _dl_procinfo.
|
||||
* sysdeps/unix/sysv/linux/s390/dl-procinfo.h (_dl_procinfo):
|
||||
Ignore types other than AT_HWCAP.
|
||||
* sysdeps/sparc/dl-procinfo.h (_dl_procinfo): Likewise.
|
||||
* sysdeps/unix/sysv/linux/i386/dl-procinfo.h (_dl_procinfo):
|
||||
Likewise.
|
||||
* sysdeps/powerpc/dl-procinfo.h (_dl_procinfo): Adjust comment
|
||||
in the case of falling back to generic output mechanism.
|
||||
* sysdeps/unix/sysv/linux/arm/dl-procinfo.h (_dl_procinfo):
|
||||
Likewise.
|
||||
|
||||
2019-02-15 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #24211]
|
||||
* nptl/pthread_join_common.c (__pthread_timedjoin_ex): Do not read
|
||||
pd->result after the thread descriptor has been freed.
|
||||
|
||||
2019-02-08 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #24161]
|
||||
* sysdeps/nptl/fork.h (__run_fork_handlers): Add multiple_threads
|
||||
argument.
|
||||
* nptl/register-atfork.c (__run_fork_handlers): Only perform
|
||||
locking if the new do_locking argument is true.
|
||||
* sysdeps/nptl/fork.c (__libc_fork): Pass multiple_threads to
|
||||
__run_fork_handlers.
|
||||
|
||||
2019-02-07 Stefan Liebler <stli@linux.ibm.com>
|
||||
|
||||
[BZ #24180]
|
||||
* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock):
|
||||
Add compiler barriers and comments.
|
||||
|
||||
2019-02-05 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #24164]
|
||||
arm: Use "nr" constraint for Systemtap probes, to avoid the
|
||||
compiler using memory operands for constants, due to the "o"
|
||||
alternative in the default "nor" constraint.
|
||||
* include/stap-probe.h [USE_STAP_PROBE]: Include
|
||||
<stap-probe-machine.h>
|
||||
* sysdeps/generic/stap-probe-machine.h: New file.
|
||||
* sysdeps/arm/stap-probe-machine.h: Likewise.
|
||||
|
||||
2019-02-04 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
[BZ #24155]
|
||||
CVE-2019-7309
|
||||
* NEWS: Updated for CVE-2019-7309.
|
||||
* sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the
|
||||
upper 32 bits of RDX register for x32. Use unsigned Jcc
|
||||
instructions, instead of signed.
|
||||
* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2.
|
||||
* sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test.
|
||||
|
||||
2019-01-31 Carlos O'Donell <carlos@redhat.com>
|
||||
Torvald Riegel <triegel@redhat.com>
|
||||
Rik Prohaska <prohaska7@gmail.com>
|
||||
|
||||
[BZ# 23844]
|
||||
* nptl/Makefile (tests): Add tst-rwlock-tryrdlock-stall, and
|
||||
tst-rwlock-trywrlock-stall.
|
||||
* nptl/pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock):
|
||||
Wake waiters if PTHREAD_RWLOCK_FUTEX_USED is set.
|
||||
* nptl/pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock):
|
||||
Set __wrphase_fute to 1 only if we started the write phase.
|
||||
* nptl/tst-rwlock-tryrdlock-stall.c: New file.
|
||||
* nptl/tst-rwlock-trywrlock-stall.c: New file.
|
||||
* support/Makefile (libsupport-routines): Add xpthread_rwlock_destroy.
|
||||
* support/xpthread_rwlock_destroy.c: New file.
|
||||
* support/xthread.h: Declare xpthread_rwlock_destroy.
|
||||
|
||||
2019-01-31 Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
* version.h (RELEASE): Set to "stable".
|
||||
|
||||
+25
@@ -521,8 +521,13 @@ CFLAGS-printers-tests := -O0 -ggdb3 -DIS_IN_build
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
# These indicate whether to link using the built ld.so or the installed one.
|
||||
ifeq ($(with-lld),no)
|
||||
installed-rtld-LDFLAGS = -Wl,-dynamic-linker=$(rtlddir)/$(rtld-installed-name)
|
||||
built-rtld-LDFLAGS = -Wl,-dynamic-linker=$(elf-objpfx)ld.so
|
||||
else
|
||||
installed-rtld-LDFLAGS = -Wl,-dynamic-linker,$(rtlddir)/$(rtld-installed-name)
|
||||
built-rtld-LDFLAGS = -Wl,-dynamic-linker,$(elf-objpfx)ld.so
|
||||
endif
|
||||
|
||||
ifndef rtld-LDFLAGS
|
||||
rtld-LDFLAGS = $(installed-rtld-LDFLAGS)
|
||||
@@ -829,7 +834,9 @@ endif
|
||||
# We have to assume that glibc functions are called in any rounding
|
||||
# mode and also change the rounding mode in a few functions. So,
|
||||
# disable any optimization that assume default rounding mode.
|
||||
ifeq ($(with-clang),no)
|
||||
+math-flags = -frounding-math
|
||||
endif
|
||||
|
||||
# Logically only "libnldbl", "nonlib" and "testsuite" should be using
|
||||
# -fno-math-errno. However due to GCC bug #88576, only "libm" can use
|
||||
@@ -900,6 +907,24 @@ ifeq "$(strip $(+cflags))" ""
|
||||
+cflags := $(default_cflags)
|
||||
endif # $(+cflags) == ""
|
||||
|
||||
# For now, manually add known-needed clang flags here.
|
||||
ifeq ($(with-clang),yes)
|
||||
+cflags += -fheinous-gnu-extensions
|
||||
# Don't complain about __sigsetjmp.
|
||||
+cflags += -Wno-builtin-requires-header
|
||||
# clang takes gnu89 as requiring a warning about duplicates, gcc does not
|
||||
+cflags += -Wno-duplicate-decl-specifier
|
||||
# Non-string format arguments come from debugging prints in ld.so.
|
||||
+cflags += -Wno-format-security
|
||||
|
||||
ifeq ($(with-lld),yes)
|
||||
LDFLAGS.so += -fuse-ld=lld
|
||||
LDFLAGS-rtld += -fuse-ld=lld
|
||||
LDFLAGS += -fuse-ld=lld
|
||||
endif
|
||||
|
||||
endif # with-clang == yes
|
||||
|
||||
+cflags += $(cflags-cpu) $(+gccwarn) $(+merge-constants) $(+math-flags) \
|
||||
$(+stack-protector)
|
||||
+gcc-nowarn := -w
|
||||
|
||||
@@ -225,6 +225,11 @@ sed-remove-dotdot := -e 's@ *\([^ \/$$][^ \]*\)@ $$(..)\1@g' \
|
||||
-e 's@^\([^ \/$$][^ \]*\)@$$(..)\1@g'
|
||||
endif
|
||||
|
||||
MOARFLAGS =
|
||||
ifeq ($(with-clang),yes)
|
||||
MOARFLAGS = -no-integrated-as
|
||||
endif
|
||||
|
||||
ifdef gen-py-const-headers
|
||||
# We'll use a static pattern rule to match .pysym files with their
|
||||
# corresponding generated .py files.
|
||||
@@ -249,7 +254,7 @@ $(py-const): $(py-const-dir)%.py: %.pysym $(py-const-script) \
|
||||
$(common-before-compile)
|
||||
$(make-target-directory)
|
||||
$(PYTHON) $(py-const-script) --python \
|
||||
--cc="$(CC) $(CFLAGS) $(CPPFLAGS)" $< \
|
||||
--cc="$(CC) $(MOARFLAGS) $(CFLAGS) $(CPPFLAGS)" $< \
|
||||
> $@.tmp
|
||||
mv -f $@.tmp $@
|
||||
|
||||
@@ -268,7 +273,7 @@ ifdef gen-as-const-headers
|
||||
# may lead to build hang on a many-core machine.
|
||||
$(common-objpfx)%.h $(common-objpfx)%.h.d: $(..)scripts/gen-as-const.py \
|
||||
%.sym $(common-before-compile)
|
||||
$(PYTHON) $< --cc="$(CC) $(CFLAGS) $(CPPFLAGS) -DGEN_AS_CONST_HEADERS \
|
||||
$(PYTHON) $< --cc="$(CC) $(MOARFLAGS) $(CFLAGS) $(CPPFLAGS) -DGEN_AS_CONST_HEADERS \
|
||||
-MD -MP -MF $(@:.h=.h.d)T \
|
||||
-MT '$(@:.h=.h.d) $(@:.h.d=.h)'" \
|
||||
$(filter %.sym,$^) > $(@:.h.d=.h)T
|
||||
@@ -587,7 +592,7 @@ $(common-objpfx)shlib.lds: $(common-objpfx)config.make $(..)Makerules
|
||||
common-generated += shlib.lds
|
||||
|
||||
shlib-lds = $(common-objpfx)shlib.lds
|
||||
shlib-lds-flags = -T $(shlib-lds)
|
||||
shlib-lds-flags = -Wl,-T,$(shlib-lds)
|
||||
endif
|
||||
|
||||
define build-shlib
|
||||
@@ -639,7 +644,7 @@ LDFLAGS-c.so = -nostdlib -nostartfiles
|
||||
# But we still want to link libc.so against $(libc.so-gnulib).
|
||||
LDLIBS-c.so += $(libc.so-gnulib)
|
||||
# Give libc.so an entry point and make it directly runnable itself.
|
||||
LDFLAGS-c.so += -e __libc_main
|
||||
LDFLAGS-c.so += -Wl,-e,__libc_main
|
||||
# Pre-link the objects of libc_pic.a so that we can locally resolve
|
||||
# COMMON symbols before we link against ld.so. This is because ld.so
|
||||
# contains some of libc_pic.a already, which will prevent the COMMONs
|
||||
|
||||
@@ -4,6 +4,35 @@ 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.29.1
|
||||
|
||||
Major new features:
|
||||
|
||||
* The entry for the new Japanese era has been added for ja_JP locale.
|
||||
|
||||
The following bugs are resolved with this release:
|
||||
|
||||
[16573] malloc: Set and reset all hooks for tracing
|
||||
[24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309)
|
||||
[24164] Systemtap probes need to use "nr" constraint on 32-bit Arm
|
||||
[24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2
|
||||
[24211] Use-after-free in Systemtap probe in pthread_join
|
||||
|
||||
Security related changes:
|
||||
|
||||
CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check
|
||||
size. For x86-64, memcmp on an object size larger than SSIZE_MAX
|
||||
has undefined behavior. On x32, the size_t argument may be passed
|
||||
in the lower 32 bits of the 64-bit RDX register with non-zero upper
|
||||
32 bits. When it happened with the sign bit of RDX register set,
|
||||
memcmp gave the wrong result since it treated the size argument as
|
||||
zero. Reported by H.J. Lu.
|
||||
|
||||
CVE-2019-9169: Attempted case-insensitive regular-expression match
|
||||
via proceed_next_node in posix/regexec.c leads to heap-based buffer
|
||||
over-read. Reported by Hongxu Chen.
|
||||
|
||||
|
||||
Version 2.29
|
||||
|
||||
|
||||
@@ -183,6 +183,8 @@
|
||||
/* Define if the linker defines __ehdr_start. */
|
||||
#undef HAVE_EHDR_START
|
||||
|
||||
#define WANT_FLOAT128 0
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ use-nscd = @use_nscd@
|
||||
build-hardcoded-path-in-tests= @hardcoded_path_in_tests@
|
||||
build-pt-chown = @build_pt_chown@
|
||||
have-tunables = @have_tunables@
|
||||
enable-float128 = @enable_float128@
|
||||
|
||||
# Build tools.
|
||||
CC = @CC@
|
||||
|
||||
@@ -670,6 +670,7 @@ stack_protector
|
||||
libc_cv_ssp
|
||||
libc_cv_with_fp
|
||||
base_machine
|
||||
enable_float128
|
||||
have_tunables
|
||||
build_pt_chown
|
||||
build_nscd
|
||||
@@ -733,6 +734,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -762,6 +764,8 @@ with_gd_include
|
||||
with_gd_lib
|
||||
with_binutils
|
||||
with_selinux
|
||||
with_clang
|
||||
with_lld
|
||||
with_headers
|
||||
with_default_link
|
||||
with_nonshared_cflags
|
||||
@@ -792,6 +796,7 @@ enable_build_nscd
|
||||
enable_nscd
|
||||
enable_pt_chown
|
||||
enable_tunables
|
||||
enable_float128
|
||||
enable_mathvec
|
||||
enable_cet
|
||||
with_cpu
|
||||
@@ -846,6 +851,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -1098,6 +1104,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1235,7 +1250,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1388,6 +1403,7 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -1467,6 +1483,7 @@ Optional Features:
|
||||
--enable-pt_chown Enable building and installing pt_chown
|
||||
--enable-tunables Enable tunables support. Known values are 'yes',
|
||||
'no' and 'valstring'
|
||||
--disable-float128 disable float128 support
|
||||
--enable-mathvec Enable building and installing mathvec [default
|
||||
depends on architecture]
|
||||
--enable-cet enable Intel Control-flow Enforcement Technology
|
||||
@@ -1482,6 +1499,8 @@ Optional Packages:
|
||||
--with-gd-lib=DIR find libgd library files in DIR
|
||||
--with-binutils=PATH specify location of binutils (as and ld)
|
||||
--with-selinux if building with SELinux support
|
||||
--with-clang if building with clang (temporary)
|
||||
--with-lld if building/linking with lld (temporary)
|
||||
--with-headers=PATH location of system headers to use (for example
|
||||
/usr/src/linux/include) [default=compiler default]
|
||||
--with-default-link do not use explicit linker scripts
|
||||
@@ -3324,6 +3343,26 @@ else
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-clang was given.
|
||||
if test "${with_clang+set}" = set; then :
|
||||
withval=$with_clang; with_clang=$withval
|
||||
else
|
||||
with_clang=no
|
||||
fi
|
||||
|
||||
config_vars="$config_vars
|
||||
with-clang = $with_clang"
|
||||
|
||||
# Check whether --with-lld was given.
|
||||
if test "${with_lld+set}" = set; then :
|
||||
withval=$with_lld; with_lld=$withval
|
||||
else
|
||||
with_lld=no
|
||||
fi
|
||||
|
||||
config_vars="$config_vars
|
||||
with-lld = $with_lld"
|
||||
|
||||
|
||||
# Check whether --with-headers was given.
|
||||
if test "${with_headers+set}" = set; then :
|
||||
@@ -3757,6 +3796,19 @@ if test "$have_tunables" = yes; then
|
||||
|
||||
fi
|
||||
|
||||
# Check whether --enable-float128 was given.
|
||||
if test "${enable_float128+set}" = set; then :
|
||||
enableval=$enable_float128; enable_float128=$enableval
|
||||
else
|
||||
enable_float128=yes
|
||||
fi
|
||||
|
||||
|
||||
if test "$enable_float128" = yes; then
|
||||
$as_echo "#define WANT_FLOAT128 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
# The abi-tags file uses a fairly simplistic model for name recognition that
|
||||
# can't distinguish i486-pc-linux-gnu fully from i486-pc-gnu. So we mutate a
|
||||
# $host_os of `gnu*' here to be `gnu-gnu*' just so that it can tell.
|
||||
@@ -3988,6 +4040,13 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# Workaround for clang assembler problem with ifunc relocs, b/119574415
|
||||
if test "$with_clang" = no; then
|
||||
no_integrated_as=
|
||||
else
|
||||
no_integrated_as=-no-integrated-as
|
||||
fi
|
||||
|
||||
# For the multi-arch option we need support in the assembler & linker.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for assembler and linker STT_GNU_IFUNC support" >&5
|
||||
$as_echo_n "checking for assembler and linker STT_GNU_IFUNC support... " >&6; }
|
||||
@@ -4010,7 +4069,7 @@ __start:
|
||||
EOF
|
||||
libc_cv_ld_gnu_indirect_function=no
|
||||
if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
|
||||
-nostartfiles -nostdlib $no_ssp \
|
||||
-nostartfiles -nostdlib $no_ssp $no_integrated_as \
|
||||
-o conftest conftest.S 1>&5 2>&5; then
|
||||
# Do a link to see if the backend supports IFUNC relocs.
|
||||
$READELF -r conftest 1>&5
|
||||
@@ -4528,6 +4587,7 @@ $as_echo "$libc_cv_prog_ld_gnu" >&6; }
|
||||
gnu_ld=$libc_cv_prog_ld_gnu
|
||||
|
||||
|
||||
if test "$with_clang" = no; then
|
||||
# Accept binutils 2.25 or newer.
|
||||
for ac_prog in $AS
|
||||
do
|
||||
@@ -4592,7 +4652,9 @@ if test $ac_verc_fail = yes; then
|
||||
AS=: critic_missing="$critic_missing as"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if test "$with_lld" = no; then
|
||||
if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
|
||||
# Accept gold 1.14 or higher
|
||||
for ac_prog in $LD
|
||||
@@ -4722,6 +4784,7 @@ if test $ac_verc_fail = yes; then
|
||||
LD=: critic_missing="$critic_missing GNU ld"
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
# These programs are version sensitive.
|
||||
@@ -5120,7 +5183,9 @@ main ()
|
||||
{
|
||||
|
||||
#if !defined __GNUC__ || __GNUC__ < 5
|
||||
#if !defined __clang__
|
||||
#error insufficient compiler
|
||||
#endif
|
||||
#endif
|
||||
;
|
||||
return 0;
|
||||
@@ -6271,7 +6336,7 @@ char *foo (const char *a, const char *b)
|
||||
return __builtin_strstr (a, b);
|
||||
}
|
||||
EOF
|
||||
if { ac_try='${CC-cc} -O3 -S conftest.c -o - | grep -F "my_strstr" > /dev/null'
|
||||
if { ac_try='${CC-cc} -O3 -S conftest.c -o - | grep -F "strstr" > /dev/null'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6352,7 +6417,7 @@ __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))
|
||||
foo (void) {}
|
||||
EOF
|
||||
libc_cv_cc_loop_to_function=no
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -c conftest.c'
|
||||
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -Werror -c conftest.c'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
@@ -6872,7 +6937,10 @@ libc_cv_pie_default=$libc_cv_cc_pie_default
|
||||
|
||||
# Set the `multidir' variable by grabbing the variable from the compiler.
|
||||
# We do it once and save the result in a generated makefile.
|
||||
libc_cv_multidir=.
|
||||
if test "$with_clang" = no; then
|
||||
libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
|
||||
fi
|
||||
|
||||
|
||||
if test "$static_pie" = yes; then
|
||||
|
||||
+43
-3
@@ -137,6 +137,20 @@ AC_ARG_WITH([selinux],
|
||||
[if building with SELinux support]),
|
||||
[with_selinux=$withval],
|
||||
[with_selinux=auto])
|
||||
dnl This is a temporary hack, to help sort out wired-in GCC assumptions.
|
||||
AC_ARG_WITH([clang],
|
||||
AC_HELP_STRING([--with-clang],
|
||||
[if building with clang (temporary)]),
|
||||
[with_clang=$withval],
|
||||
[with_clang=no])
|
||||
LIBC_CONFIG_VAR([with-clang], [$with_clang])
|
||||
dnl This is a temporary hack, to help with BFD LD vs LLD debugging.
|
||||
AC_ARG_WITH([lld],
|
||||
AC_HELP_STRING([--with-lld],
|
||||
[if building/linking with lld (temporary)]),
|
||||
[with_lld=$withval],
|
||||
[with_lld=no])
|
||||
LIBC_CONFIG_VAR([with-lld], [$with_lld])
|
||||
|
||||
AC_ARG_WITH([headers],
|
||||
AC_HELP_STRING([--with-headers=PATH],
|
||||
@@ -454,6 +468,16 @@ if test "$have_tunables" = yes; then
|
||||
AC_DEFINE(HAVE_TUNABLES)
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([float128],
|
||||
AC_HELP_STRING([--disable-float128],
|
||||
[disable float128 support]),
|
||||
[enable_float128=$enableval],
|
||||
[enable_float128=yes])
|
||||
AC_SUBST(enable_float128)
|
||||
if test "$enable_float128" = yes; then
|
||||
AC_DEFINE(WANT_FLOAT128)
|
||||
fi
|
||||
|
||||
# The abi-tags file uses a fairly simplistic model for name recognition that
|
||||
# can't distinguish i486-pc-linux-gnu fully from i486-pc-gnu. So we mutate a
|
||||
# $host_os of `gnu*' here to be `gnu-gnu*' just so that it can tell.
|
||||
@@ -618,6 +642,13 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# Workaround for clang assembler problem with ifunc relocs, b/119574415
|
||||
if test "$with_clang" = no; then
|
||||
no_integrated_as=
|
||||
else
|
||||
no_integrated_as=-no-integrated-as
|
||||
fi
|
||||
|
||||
# For the multi-arch option we need support in the assembler & linker.
|
||||
AC_CACHE_CHECK([for assembler and linker STT_GNU_IFUNC support],
|
||||
libc_cv_ld_gnu_indirect_function, [dnl
|
||||
@@ -637,7 +668,7 @@ __start:
|
||||
EOF
|
||||
libc_cv_ld_gnu_indirect_function=no
|
||||
if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
|
||||
-nostartfiles -nostdlib $no_ssp \
|
||||
-nostartfiles -nostdlib $no_ssp $no_integrated_as \
|
||||
-o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
|
||||
# Do a link to see if the backend supports IFUNC relocs.
|
||||
$READELF -r conftest 1>&AS_MESSAGE_LOG_FD
|
||||
@@ -971,12 +1002,15 @@ AC_PROG_LN_S
|
||||
|
||||
LIBC_PROG_BINUTILS
|
||||
|
||||
if test "$with_clang" = no; then
|
||||
# Accept binutils 2.25 or newer.
|
||||
AC_CHECK_PROG_VER(AS, $AS, --version,
|
||||
[GNU assembler.* \([0-9]*\.[0-9.]*\)],
|
||||
[2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
|
||||
AS=: critic_missing="$critic_missing as")
|
||||
fi
|
||||
|
||||
if test "$with_lld" = no; then
|
||||
if test -n "`$LD --version | sed -n 's/^GNU \(gold\).*$/\1/p'`"; then
|
||||
# Accept gold 1.14 or higher
|
||||
AC_CHECK_PROG_VER(LD, $LD, --version,
|
||||
@@ -989,6 +1023,7 @@ else
|
||||
[2.1[0-9][0-9]*|2.2[5-9]*|2.[3-9][0-9]*|[3-9].*|[1-9][0-9]*],
|
||||
LD=: critic_missing="$critic_missing GNU ld")
|
||||
fi
|
||||
fi
|
||||
|
||||
# These programs are version sensitive.
|
||||
AC_CHECK_TOOL_PREFIX
|
||||
@@ -1018,7 +1053,9 @@ AC_CHECK_PROG_VER(BISON, bison, --version,
|
||||
AC_CACHE_CHECK([if $CC is sufficient to build libc], libc_cv_compiler_ok, [
|
||||
AC_TRY_COMPILE([], [
|
||||
#if !defined __GNUC__ || __GNUC__ < 5
|
||||
#if !defined __clang__
|
||||
#error insufficient compiler
|
||||
#endif
|
||||
#endif],
|
||||
[libc_cv_compiler_ok=yes],
|
||||
[libc_cv_compiler_ok=no])])
|
||||
@@ -1556,7 +1593,7 @@ char *foo (const char *a, const char *b)
|
||||
}
|
||||
EOF
|
||||
dnl
|
||||
if AC_TRY_COMMAND([${CC-cc} -O3 -S conftest.c -o - | grep -F "my_strstr" > /dev/null]);
|
||||
if AC_TRY_COMMAND([${CC-cc} -O3 -S conftest.c -o - | grep -F "strstr" > /dev/null]);
|
||||
then
|
||||
libc_cv_gcc_builtin_redirection=yes
|
||||
else
|
||||
@@ -1599,7 +1636,7 @@ __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))
|
||||
foo (void) {}
|
||||
EOF
|
||||
libc_cv_cc_loop_to_function=no
|
||||
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -c conftest.c])
|
||||
if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -Werror -c conftest.c])
|
||||
then
|
||||
libc_cv_cc_loop_to_function=yes
|
||||
fi
|
||||
@@ -1865,7 +1902,10 @@ AC_SUBST(libc_cv_pie_default)
|
||||
|
||||
# Set the `multidir' variable by grabbing the variable from the compiler.
|
||||
# We do it once and save the result in a generated makefile.
|
||||
libc_cv_multidir=.
|
||||
if test "$with_clang" = no; then
|
||||
libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
|
||||
fi
|
||||
AC_SUBST(libc_cv_multidir)
|
||||
|
||||
if test "$static_pie" = yes; then
|
||||
|
||||
+6
-1
@@ -201,9 +201,11 @@ endif
|
||||
test-srcs = tst-pathopt
|
||||
selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
|
||||
ifneq ($(selinux-enabled),1)
|
||||
ifneq ($(with-clang),yes)
|
||||
tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
tests += $(tests-execstack-$(have-z-execstack))
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-leaks1-mem.out \
|
||||
@@ -312,7 +314,9 @@ tests-pie += vismain
|
||||
CFLAGS-vismain.c += $(PIE-ccflag)
|
||||
endif
|
||||
endif
|
||||
ifneq ($(with-clang),yes)
|
||||
modules-execstack-yes = tst-execstack-mod
|
||||
endif
|
||||
extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
|
||||
|
||||
# filtmod1.so has a special rule
|
||||
@@ -458,9 +462,10 @@ $(objpfx)librtld.map: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a
|
||||
rm -f $@.o
|
||||
mv -f $@T $@
|
||||
|
||||
# For lld, add to regexp below for optional address and size to be at front of line.
|
||||
$(objpfx)librtld.mk: $(objpfx)librtld.map Makefile
|
||||
LC_ALL=C \
|
||||
sed -n 's@^$(common-objpfx)\([^(]*\)(\([^)]*\.os\)) *.*$$@\1 \2@p' \
|
||||
sed -n 's@^[0-9a-f ]*$(common-objpfx)\([^(]*\)(\([^)]*\.os\)) *.*$$@\1 \2@p' \
|
||||
$< | \
|
||||
while read lib file; do \
|
||||
case $$lib in \
|
||||
|
||||
+42
-11
@@ -27,17 +27,8 @@
|
||||
#include <sys/types.h>
|
||||
#include "dynamic-link.h"
|
||||
|
||||
void
|
||||
_dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||
ElfW(Rela) *conflictend)
|
||||
{
|
||||
#if ! ELF_MACHINE_NO_RELA
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
|
||||
_dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name));
|
||||
#ifndef NESTING
|
||||
|
||||
{
|
||||
/* Do the conflict relocation of the object and library GOT and other
|
||||
data. */
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(ref, version, flags) (*ref = NULL, NULL)
|
||||
@@ -51,13 +42,49 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||
(map) = resolve_conflict_map; \
|
||||
} while (0)
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
#endif /* n NESTING */
|
||||
|
||||
void
|
||||
_dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||
ElfW(Rela) *conflictend)
|
||||
{
|
||||
#if ! ELF_MACHINE_NO_RELA
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
|
||||
_dl_debug_printf ("\nconflict processing: %s\n", DSO_FILENAME (l->l_name));
|
||||
|
||||
{
|
||||
/* Do the conflict relocation of the object and library GOT and other
|
||||
data. */
|
||||
|
||||
#ifdef NESTING
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(ref, version, flags) (*ref = NULL, NULL)
|
||||
#define RESOLVE(ref, version, flags) (*ref = NULL, 0)
|
||||
#define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \
|
||||
do { \
|
||||
while ((resolve_conflict_map->l_map_end < (ElfW(Addr)) (r_offset)) \
|
||||
|| (resolve_conflict_map->l_map_start > (ElfW(Addr)) (r_offset))) \
|
||||
resolve_conflict_map = resolve_conflict_map->l_next; \
|
||||
\
|
||||
(map) = resolve_conflict_map; \
|
||||
} while (0)
|
||||
|
||||
#endif /* NESTING */
|
||||
|
||||
/* Prelinking makes no sense for anything but the main namespace. */
|
||||
assert (l->l_ns == LM_ID_BASE);
|
||||
struct link_map *resolve_conflict_map __attribute__ ((__unused__))
|
||||
= GL(dl_ns)[LM_ID_BASE]._ns_loaded;
|
||||
|
||||
#ifdef NESTING
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
#endif /* NESTING */
|
||||
|
||||
/* Override these, defined in dynamic-link.h. */
|
||||
#undef CHECK_STATIC_TLS
|
||||
#define CHECK_STATIC_TLS(ref_map, sym_map) ((void) 0)
|
||||
@@ -68,7 +95,11 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
|
||||
|
||||
for (; conflict < conflictend; ++conflict)
|
||||
elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset,
|
||||
0);
|
||||
0
|
||||
#ifndef NESTING
|
||||
, NULL
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+8
-1
@@ -157,8 +157,11 @@ static uint32_t narcs;
|
||||
currently in the mmaped file. At no point of time this has to be the
|
||||
same as NARCS. If it is equal all entries from the file are in our
|
||||
lists. */
|
||||
#ifdef __clang__
|
||||
static volatile unsigned long *narcsp;
|
||||
#else
|
||||
static volatile uint32_t *narcsp;
|
||||
|
||||
#endif
|
||||
|
||||
struct here_fromstruct
|
||||
{
|
||||
@@ -170,7 +173,11 @@ static volatile uint16_t *tos;
|
||||
|
||||
static struct here_fromstruct *froms;
|
||||
static uint32_t fromlimit;
|
||||
#ifdef __clang__
|
||||
static volatile unsigned long fromidx;
|
||||
#else
|
||||
static volatile uint32_t fromidx;
|
||||
#endif
|
||||
|
||||
static uintptr_t lowpc;
|
||||
static size_t textsize;
|
||||
|
||||
+49
-1
@@ -141,6 +141,40 @@ _dl_nothread_init_static_tls (struct link_map *map)
|
||||
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
|
||||
}
|
||||
|
||||
#ifndef NESTING
|
||||
|
||||
/* String table object symbols. */
|
||||
|
||||
static struct link_map *glob_l;
|
||||
static struct r_scope_elem **glob_scope;
|
||||
static const char *glob_strtab;
|
||||
|
||||
/* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
|
||||
#define RESOLVE_MAP(ref, version, r_type) \
|
||||
((ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
|
||||
&& __glibc_likely (!dl_symbol_visibility_binds_local_p (*ref))) \
|
||||
? ((__builtin_expect ((*ref) == glob_l->l_lookup_cache.sym, 0) \
|
||||
&& elf_machine_type_class (r_type) == glob_l->l_lookup_cache.type_class) \
|
||||
? (bump_num_cache_relocations (), \
|
||||
(*ref) = glob_l->l_lookup_cache.ret, \
|
||||
glob_l->l_lookup_cache.value) \
|
||||
: ({ lookup_t _lr; \
|
||||
int _tc = elf_machine_type_class (r_type); \
|
||||
glob_l->l_lookup_cache.type_class = _tc; \
|
||||
glob_l->l_lookup_cache.sym = (*ref); \
|
||||
const struct r_found_version *v = NULL; \
|
||||
if ((version) != NULL && (version)->hash != 0) \
|
||||
v = (version); \
|
||||
_lr = _dl_lookup_symbol_x (glob_strtab + (*ref)->st_name, glob_l, (ref), \
|
||||
glob_scope, v, _tc, \
|
||||
DL_LOOKUP_ADD_DEPENDENCY, NULL); \
|
||||
glob_l->l_lookup_cache.ret = (*ref); \
|
||||
glob_l->l_lookup_cache.value = _lr; })) \
|
||||
: glob_l)
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
#endif /* n NESTING */
|
||||
|
||||
void
|
||||
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||
@@ -223,6 +257,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||
{
|
||||
/* Do the actual relocation of the object's GOT and other data. */
|
||||
|
||||
#ifdef NESTING
|
||||
|
||||
/* String table object symbols. */
|
||||
const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
|
||||
|
||||
@@ -251,7 +287,19 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||
|
||||
#include "dynamic-link.h"
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
|
||||
#else
|
||||
|
||||
glob_l = l;
|
||||
glob_scope = scope;
|
||||
glob_strtab = (const void *) D_PTR (glob_l, l_info[DT_STRTAB]);
|
||||
|
||||
#endif /* NESTING */
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc
|
||||
#ifndef NESTING
|
||||
, NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifndef PROF
|
||||
if (__glibc_unlikely (consider_profiling)
|
||||
|
||||
+3
-8
@@ -328,14 +328,9 @@ _dl_show_auxv (void)
|
||||
assert (AT_NULL == 0);
|
||||
assert (AT_IGNORE == 1);
|
||||
|
||||
if (av->a_type == AT_HWCAP || av->a_type == AT_HWCAP2
|
||||
|| AT_L1I_CACHEGEOMETRY || AT_L1D_CACHEGEOMETRY
|
||||
|| AT_L2_CACHEGEOMETRY || AT_L3_CACHEGEOMETRY)
|
||||
{
|
||||
/* These are handled in a special way per platform. */
|
||||
if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
|
||||
continue;
|
||||
}
|
||||
/* Some entries are handled in a special way per platform. */
|
||||
if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
|
||||
continue;
|
||||
|
||||
if (idx < sizeof (auxvars) / sizeof (auxvars[0])
|
||||
&& auxvars[idx].form != unknown)
|
||||
|
||||
+25
-5
@@ -41,7 +41,11 @@ auto inline void __attribute__ ((always_inline))
|
||||
elf_dynamic_do_Rel (struct link_map *map,
|
||||
ElfW(Addr) reladdr, ElfW(Addr) relsize,
|
||||
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
|
||||
int lazy, int skip_ifunc)
|
||||
int lazy, int skip_ifunc
|
||||
#ifndef NESTING
|
||||
, struct link_map *boot_map
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const ElfW(Rel) *r = (const void *) reladdr;
|
||||
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
|
||||
@@ -136,7 +140,11 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
|
||||
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
|
||||
&map->l_versions[ndx],
|
||||
(void *) (l_addr + r->r_offset), skip_ifunc);
|
||||
(void *) (l_addr + r->r_offset), skip_ifunc
|
||||
#ifndef NESTING
|
||||
, boot_map
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
|
||||
@@ -150,7 +158,11 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
&symtab[ELFW(R_SYM) (r2->r_info)],
|
||||
&map->l_versions[ndx],
|
||||
(void *) (l_addr + r2->r_offset),
|
||||
skip_ifunc);
|
||||
skip_ifunc
|
||||
#ifndef NESTING
|
||||
, boot_map
|
||||
#endif
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -168,7 +180,11 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
else
|
||||
# endif
|
||||
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
|
||||
(void *) (l_addr + r->r_offset), skip_ifunc);
|
||||
(void *) (l_addr + r->r_offset), skip_ifunc
|
||||
#ifndef NESTING
|
||||
, boot_map
|
||||
#endif
|
||||
);
|
||||
|
||||
# ifdef ELF_MACHINE_IRELATIVE
|
||||
if (r2 != NULL)
|
||||
@@ -176,7 +192,11 @@ elf_dynamic_do_Rel (struct link_map *map,
|
||||
if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
|
||||
elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
|
||||
NULL, (void *) (l_addr + r2->r_offset),
|
||||
skip_ifunc);
|
||||
skip_ifunc
|
||||
#ifndef NESTING
|
||||
, boot_map
|
||||
#endif
|
||||
);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
+93
-1
@@ -16,6 +16,10 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef NESTING
|
||||
#define auto static
|
||||
#endif
|
||||
|
||||
/* This macro is used as a callback from elf_machine_rel{a,} when a
|
||||
static TLS reloc is about to be performed. Since (in dl-load.c) we
|
||||
permit dynamic loading of objects that might use such relocs, we
|
||||
@@ -70,7 +74,11 @@ elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
|
||||
auto inline void __attribute__((always_inline))
|
||||
elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
||||
const ElfW(Sym) *sym, const struct r_found_version *version,
|
||||
void *const reloc_addr, int skip_ifunc);
|
||||
void *const reloc_addr, int skip_ifunc
|
||||
#ifndef NESTING
|
||||
, struct link_map *boot_map
|
||||
#endif
|
||||
);
|
||||
auto inline void __attribute__((always_inline))
|
||||
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
|
||||
void *const reloc_addr);
|
||||
@@ -113,6 +121,60 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
|
||||
are completely separate and there is a gap between them. */
|
||||
|
||||
#ifndef NESTING
|
||||
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel, boot_map) \
|
||||
do { \
|
||||
struct { ElfW(Addr) start, size; \
|
||||
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \
|
||||
ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; \
|
||||
\
|
||||
if ((map)->l_info[DT_##RELOC]) \
|
||||
{ \
|
||||
ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
|
||||
ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
|
||||
if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL) \
|
||||
ranges[0].nrelative \
|
||||
= map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val; \
|
||||
} \
|
||||
if ((map)->l_info[DT_PLTREL] \
|
||||
&& (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
|
||||
{ \
|
||||
ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
|
||||
ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
|
||||
\
|
||||
if (ranges[0].start + ranges[0].size == (start + size)) \
|
||||
ranges[0].size -= size; \
|
||||
if (ELF_DURING_STARTUP \
|
||||
|| (!(do_lazy) \
|
||||
&& (ranges[0].start + ranges[0].size) == start)) \
|
||||
{ \
|
||||
/* Combine processing the sections. */ \
|
||||
ranges[0].size += size; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
ranges[1].start = start; \
|
||||
ranges[1].size = size; \
|
||||
ranges[1].lazy = (do_lazy); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (ELF_DURING_STARTUP) \
|
||||
elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, \
|
||||
ranges[0].nrelative, 0, skip_ifunc, boot_map); \
|
||||
else \
|
||||
{ \
|
||||
int ranges_index; \
|
||||
for (ranges_index = 0; ranges_index < 2; ++ranges_index) \
|
||||
elf_dynamic_do_##reloc ((map), \
|
||||
ranges[ranges_index].start, \
|
||||
ranges[ranges_index].size, \
|
||||
ranges[ranges_index].nrelative, \
|
||||
ranges[ranges_index].lazy, \
|
||||
skip_ifunc, boot_map); \
|
||||
} \
|
||||
} while (0)
|
||||
#else /* NESTING */
|
||||
# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \
|
||||
do { \
|
||||
struct { ElfW(Addr) start, size; \
|
||||
@@ -165,6 +227,7 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
skip_ifunc); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif /* NESTING */
|
||||
|
||||
# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
|
||||
# define _ELF_CHECK_REL 0
|
||||
@@ -172,6 +235,34 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
# define _ELF_CHECK_REL 1
|
||||
# endif
|
||||
|
||||
#ifndef NESTING
|
||||
# if ! ELF_MACHINE_NO_REL
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc, boot_map) \
|
||||
_ELF_DYNAMIC_DO_RELOC (REL, Rel, map, lazy, skip_ifunc, _ELF_CHECK_REL, boot_map)
|
||||
# else
|
||||
# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc, boot_map) /* Nothing to do. */
|
||||
# endif
|
||||
|
||||
# if ! ELF_MACHINE_NO_RELA
|
||||
# define DO_RELA
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc, boot_map) \
|
||||
_ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, lazy, skip_ifunc, _ELF_CHECK_REL, boot_map)
|
||||
# else
|
||||
# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc, boot_map) /* Nothing to do. */
|
||||
# endif
|
||||
|
||||
/* This can't just be an inline function because GCC is too dumb
|
||||
to inline functions containing inlines themselves. */
|
||||
# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc, boot_map) \
|
||||
do { \
|
||||
int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \
|
||||
(consider_profile)); \
|
||||
ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc, boot_map); \
|
||||
ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc, boot_map); \
|
||||
} while (0)
|
||||
#else /* NESTING */
|
||||
# if ! ELF_MACHINE_NO_REL
|
||||
# include "do-rel.h"
|
||||
# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \
|
||||
@@ -198,5 +289,6 @@ elf_machine_lazy_rel (struct link_map *map,
|
||||
ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc); \
|
||||
ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc); \
|
||||
} while (0)
|
||||
#endif /* NESTING */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <assert.h>
|
||||
#include <libc-diag.h>
|
||||
|
||||
#if defined NESTING || !defined SAW_EGDI
|
||||
|
||||
#ifndef RESOLVE_MAP
|
||||
static
|
||||
#else
|
||||
@@ -183,3 +185,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
info[DT_RPATH] = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NESTING
|
||||
#ifndef SAW_EGDI
|
||||
#define SAW_EGDI
|
||||
#endif
|
||||
#endif /* n NESTING */
|
||||
|
||||
+49
-2
@@ -325,7 +325,7 @@ DL_SYSINFO_IMPLEMENTATION
|
||||
is fine, too. The latter is important here. We can avoid setting
|
||||
up a temporary link map for ld.so if we can mark _rtld_global as
|
||||
hidden. */
|
||||
#ifdef PI_STATIC_AND_HIDDEN
|
||||
#if 0 //def PI_STATIC_AND_HIDDEN
|
||||
# define DONT_USE_BOOTSTRAP_MAP 1
|
||||
#endif
|
||||
|
||||
@@ -393,7 +393,13 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
|
||||
#endif
|
||||
_dl_setup_hash (&GL(dl_rtld_map));
|
||||
GL(dl_rtld_map).l_real = &GL(dl_rtld_map);
|
||||
#if defined(__clang__)
|
||||
/* Work around an lld complaint that _begin cannot have a reloc and
|
||||
also be absolute because of _begin=0 on linker line. */
|
||||
GL(dl_rtld_map).l_map_start = (ElfW(Addr)) 0;
|
||||
#else
|
||||
GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin;
|
||||
#endif
|
||||
GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
|
||||
GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
|
||||
/* Copy the TLS related data if necessary. */
|
||||
@@ -440,9 +446,30 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
|
||||
return start_addr;
|
||||
}
|
||||
|
||||
#ifndef NESTING
|
||||
#ifdef DONT_USE_BOOTSTRAP_MAP
|
||||
# define bootstrap_map GL(dl_rtld_map)
|
||||
#else
|
||||
# define bootstrap_map info.l
|
||||
#endif
|
||||
|
||||
/* This #define produces dynamic linking inline functions for
|
||||
bootstrap relocation instead of general-purpose relocation.
|
||||
Since ld.so must not have any undefined symbols the result
|
||||
is trivial: always the map of ld.so itself. */
|
||||
#define RTLD_BOOTSTRAP
|
||||
#define RESOLVE_MAP(sym, version, flags) (&bootstrap_map)
|
||||
#include "dynamic-link.h"
|
||||
#endif /* n NESTING */
|
||||
|
||||
static ElfW(Addr) __attribute_used__
|
||||
_dl_start (void *arg)
|
||||
{
|
||||
#ifndef NESTING
|
||||
#ifndef DONT_USE_BOOTSTRAP_MAP
|
||||
struct dl_start_final_info info;
|
||||
#endif /* DUBM */
|
||||
#else /* NESTING */
|
||||
#ifdef DONT_USE_BOOTSTRAP_MAP
|
||||
# define bootstrap_map GL(dl_rtld_map)
|
||||
#else
|
||||
@@ -458,6 +485,7 @@ _dl_start (void *arg)
|
||||
#define BOOTSTRAP_MAP (&bootstrap_map)
|
||||
#define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
|
||||
#include "dynamic-link.h"
|
||||
#endif /* NESTING */
|
||||
|
||||
if (HP_TIMING_INLINE && HP_SMALL_TIMING_AVAIL)
|
||||
#ifdef DONT_USE_BOOTSTRAP_MAP
|
||||
@@ -503,7 +531,11 @@ _dl_start (void *arg)
|
||||
/* Relocate ourselves so we can do normal function calls and
|
||||
data access using the global offset table. */
|
||||
|
||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0);
|
||||
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0
|
||||
#ifndef NESTING
|
||||
, &bootstrap_map
|
||||
#endif
|
||||
);
|
||||
}
|
||||
bootstrap_map.l_relocated = 1;
|
||||
|
||||
@@ -2794,3 +2826,18 @@ print_statistics (hp_timing_t *rtld_total_timep)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NESTING
|
||||
char *dummy1 = (char *)elf_get_dynamic_info;
|
||||
# if ! ELF_MACHINE_NO_REL
|
||||
char *dummy2 = (char *)elf_machine_rel;
|
||||
char *dummy3 = (char *)elf_machine_rel_relative;
|
||||
#endif
|
||||
# if ! ELF_MACHINE_NO_RELA
|
||||
char *dummy4 = (char *)elf_machine_rela;
|
||||
char *dummy5 = (char *)elf_machine_rela_relative;
|
||||
#endif
|
||||
# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
|
||||
char *dummy6 = (char *)elf_machine_lazy_rel;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/* Macros to support TLS testing in times of missing compiler support. */
|
||||
|
||||
#define COMMON_INT_DEF(x) \
|
||||
asm (".tls_common " #x ",4,4")
|
||||
__thread int x;
|
||||
/* XXX Until we get compiler support we don't need declarations. */
|
||||
#define COMMON_INT_DECL(x)
|
||||
|
||||
|
||||
@@ -114,6 +114,10 @@ enum
|
||||
|
||||
/* Internal function. Terminate the process using __libc_fatal. */
|
||||
void __libc_alloc_buffer_create_failure (void *start, size_t size);
|
||||
/* clang wants a hidden proto ahead of use. */
|
||||
#ifndef _ISOMAC
|
||||
libc_hidden_proto (__libc_alloc_buffer_create_failure)
|
||||
#endif
|
||||
|
||||
/* Create a new allocation buffer. The byte range from START to START
|
||||
+ SIZE - 1 must be valid, and the allocation buffer allocates
|
||||
@@ -132,6 +136,10 @@ alloc_buffer_create (void *start, size_t size)
|
||||
/* Internal function. See alloc_buffer_allocate below. */
|
||||
struct alloc_buffer __libc_alloc_buffer_allocate (size_t size, void **pptr)
|
||||
__attribute__ ((nonnull (2)));
|
||||
/* clang wants a hidden proto ahead of use. */
|
||||
#ifndef _ISOMAC
|
||||
libc_hidden_proto (__libc_alloc_buffer_allocate)
|
||||
#endif
|
||||
|
||||
/* Allocate a buffer of SIZE bytes using malloc. The returned buffer
|
||||
is in a failed state if malloc fails. *PPTR points to the start of
|
||||
@@ -342,6 +350,10 @@ alloc_buffer_copy_bytes (struct alloc_buffer *buf, const void *src, size_t size)
|
||||
struct alloc_buffer __libc_alloc_buffer_copy_string (struct alloc_buffer,
|
||||
const char *)
|
||||
__attribute__ ((nonnull (2)));
|
||||
/* clang wants a hidden proto ahead of use. */
|
||||
#ifndef _ISOMAC
|
||||
libc_hidden_proto (__libc_alloc_buffer_copy_string)
|
||||
#endif
|
||||
|
||||
/* Copy the string at SRC into the buffer, including its null
|
||||
terminator. If there is not enough room in the buffer, the buffer
|
||||
|
||||
@@ -28,6 +28,11 @@ void *__libc_allocate_once_slow (void **__place,
|
||||
void *__ptr),
|
||||
void *__closure);
|
||||
|
||||
#ifdef __clang__
|
||||
/* clang needs the hidden proto to be specified ahead of its use. */
|
||||
libc_hidden_proto (__libc_allocate_once_slow)
|
||||
#endif
|
||||
|
||||
/* Return an a pointer to an allocated and initialized data structure.
|
||||
If this function returns a non-NULL value, the caller can assume
|
||||
that pointed-to data has been initialized according to the ALLOCATE
|
||||
|
||||
+1
-2
@@ -462,11 +462,10 @@
|
||||
/* Decide whether we can define 'extern inline' functions in headers. */
|
||||
#if __GNUC_PREREQ (2, 7) && defined __OPTIMIZE__ \
|
||||
&& !defined __OPTIMIZE_SIZE__ && !defined __NO_INLINE__ \
|
||||
&& defined __extern_inline
|
||||
&& defined __extern_inline && !defined __clang__
|
||||
# define __USE_EXTERN_INLINES 1
|
||||
#endif
|
||||
|
||||
|
||||
/* This is here only because every header file already includes this one.
|
||||
Get the definitions of all the appropriate `__stub_FUNCTION' symbols.
|
||||
<gnu/stubs.h> contains `#define __stub_FUNCTION' when FUNCTION is a stub
|
||||
|
||||
@@ -530,9 +530,19 @@ for linking")
|
||||
__hidden_proto (name, , __GI_##name, ##attrs)
|
||||
# define hidden_tls_proto(name, attrs...) \
|
||||
__hidden_proto (name, __thread, __GI_##name, ##attrs)
|
||||
#ifndef __clang__
|
||||
# define __hidden_proto(name, thread, internal, attrs...) \
|
||||
extern thread __typeof (name) name __asm__ (__hidden_asmname (#internal)) \
|
||||
__hidden_proto_hiddenattr (attrs);
|
||||
#else
|
||||
# define __hidden_proto(name, thread, internal, attrs...) \
|
||||
extern thread __typeof (name) name \
|
||||
__hidden_proto_hiddenattr (attrs); \
|
||||
_Pragma (__redefine(name, internal))
|
||||
/* Note that this macro does not use __hidden_asmname, since it produces a string. */
|
||||
# define __redefine(name, internal) __stringize(redefine_extname name internal)
|
||||
# define __stringize(X) #X
|
||||
#endif
|
||||
# define __hidden_asmname(name) \
|
||||
__hidden_asmname1 (__USER_LABEL_PREFIX__, name)
|
||||
# define __hidden_asmname1(prefix, name) __hidden_asmname2(prefix, name)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#ifdef USE_STAP_PROBE
|
||||
|
||||
# include <stap-probe-machine.h>
|
||||
# include <sys/sdt.h>
|
||||
|
||||
/* Our code uses one macro LIBC_PROBE (name, n, arg1, ..., argn).
|
||||
|
||||
@@ -14946,12 +14946,14 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>"
|
||||
|
||||
t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
|
||||
|
||||
era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
|
||||
era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
|
||||
"+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
|
||||
"+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
|
||||
"+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
|
||||
"+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
|
||||
"+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/
|
||||
"+:2:1913//01//01:1926//12//24:<U5927><U6B63>:%EC%Ey<U5E74>";/
|
||||
"+:2:1912//07//30:1912//12//31:<U5927><U6B63>:%EC<U5143><U5E74>";/
|
||||
"+:1:1912//07//30:1912//12//31:<U5927><U6B63>:%EC<U5143><U5E74>";/
|
||||
"+:6:1873//01//01:1912//07//29:<U660E><U6CBB>:%EC%Ey<U5E74>";/
|
||||
"+:1:0001//01//01:1872//12//31:<U897F><U66A6>:%EC%Ey<U5E74>";/
|
||||
"+:1:-0001//12//31:-*:<U7D00><U5143><U524D>:%EC%Ey<U5E74>"
|
||||
|
||||
@@ -112,7 +112,11 @@ struct entry
|
||||
};
|
||||
|
||||
static struct entry buffer[2 * DEFAULT_BUFFER_SIZE];
|
||||
#ifdef __clang__
|
||||
static long buffer_cnt;
|
||||
#else
|
||||
static uatomic32_t buffer_cnt;
|
||||
#endif
|
||||
static struct entry first;
|
||||
|
||||
|
||||
|
||||
+46
-26
@@ -121,6 +121,41 @@ lock_and_info (const void *caller, Dl_info *mem)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void tr_freehook (void *, const void *);
|
||||
static void * tr_mallochook (size_t, const void *);
|
||||
static void * tr_reallochook (void *, size_t, const void *);
|
||||
static void * tr_memalignhook (size_t, size_t, const void *);
|
||||
|
||||
/* Set all the default non-trace hooks. */
|
||||
static __always_inline void
|
||||
set_default_hooks (void)
|
||||
{
|
||||
__free_hook = tr_old_free_hook;
|
||||
__malloc_hook = tr_old_malloc_hook;
|
||||
__realloc_hook = tr_old_realloc_hook;
|
||||
__memalign_hook = tr_old_memalign_hook;
|
||||
}
|
||||
|
||||
/* Set all of the tracing hooks used for mtrace. */
|
||||
static __always_inline void
|
||||
set_trace_hooks (void)
|
||||
{
|
||||
__free_hook = tr_freehook;
|
||||
__malloc_hook = tr_mallochook;
|
||||
__realloc_hook = tr_reallochook;
|
||||
__memalign_hook = tr_memalignhook;
|
||||
}
|
||||
|
||||
/* Save the current set of hooks as the default hooks. */
|
||||
static __always_inline void
|
||||
save_default_hooks (void)
|
||||
{
|
||||
tr_old_free_hook = __free_hook;
|
||||
tr_old_malloc_hook = __malloc_hook;
|
||||
tr_old_realloc_hook = __realloc_hook;
|
||||
tr_old_memalign_hook = __memalign_hook;
|
||||
}
|
||||
|
||||
static void
|
||||
tr_freehook (void *ptr, const void *caller)
|
||||
{
|
||||
@@ -138,12 +173,12 @@ tr_freehook (void *ptr, const void *caller)
|
||||
tr_break ();
|
||||
__libc_lock_lock (lock);
|
||||
}
|
||||
__free_hook = tr_old_free_hook;
|
||||
set_default_hooks ();
|
||||
if (tr_old_free_hook != NULL)
|
||||
(*tr_old_free_hook)(ptr, caller);
|
||||
else
|
||||
free (ptr);
|
||||
__free_hook = tr_freehook;
|
||||
set_trace_hooks ();
|
||||
__libc_lock_unlock (lock);
|
||||
}
|
||||
|
||||
@@ -155,12 +190,12 @@ tr_mallochook (size_t size, const void *caller)
|
||||
Dl_info mem;
|
||||
Dl_info *info = lock_and_info (caller, &mem);
|
||||
|
||||
__malloc_hook = tr_old_malloc_hook;
|
||||
set_default_hooks ();
|
||||
if (tr_old_malloc_hook != NULL)
|
||||
hdr = (void *) (*tr_old_malloc_hook)(size, caller);
|
||||
else
|
||||
hdr = (void *) malloc (size);
|
||||
__malloc_hook = tr_mallochook;
|
||||
set_trace_hooks ();
|
||||
|
||||
tr_where (caller, info);
|
||||
/* We could be printing a NULL here; that's OK. */
|
||||
@@ -185,16 +220,12 @@ tr_reallochook (void *ptr, size_t size, const void *caller)
|
||||
Dl_info mem;
|
||||
Dl_info *info = lock_and_info (caller, &mem);
|
||||
|
||||
__free_hook = tr_old_free_hook;
|
||||
__malloc_hook = tr_old_malloc_hook;
|
||||
__realloc_hook = tr_old_realloc_hook;
|
||||
set_default_hooks ();
|
||||
if (tr_old_realloc_hook != NULL)
|
||||
hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller);
|
||||
else
|
||||
hdr = (void *) realloc (ptr, size);
|
||||
__free_hook = tr_freehook;
|
||||
__malloc_hook = tr_mallochook;
|
||||
__realloc_hook = tr_reallochook;
|
||||
set_trace_hooks ();
|
||||
|
||||
tr_where (caller, info);
|
||||
if (hdr == NULL)
|
||||
@@ -230,14 +261,12 @@ tr_memalignhook (size_t alignment, size_t size, const void *caller)
|
||||
Dl_info mem;
|
||||
Dl_info *info = lock_and_info (caller, &mem);
|
||||
|
||||
__memalign_hook = tr_old_memalign_hook;
|
||||
__malloc_hook = tr_old_malloc_hook;
|
||||
set_default_hooks ();
|
||||
if (tr_old_memalign_hook != NULL)
|
||||
hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller);
|
||||
else
|
||||
hdr = (void *) memalign (alignment, size);
|
||||
__memalign_hook = tr_memalignhook;
|
||||
__malloc_hook = tr_mallochook;
|
||||
set_trace_hooks ();
|
||||
|
||||
tr_where (caller, info);
|
||||
/* We could be printing a NULL here; that's OK. */
|
||||
@@ -305,14 +334,8 @@ mtrace (void)
|
||||
malloc_trace_buffer = mtb;
|
||||
setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
|
||||
fprintf (mallstream, "= Start\n");
|
||||
tr_old_free_hook = __free_hook;
|
||||
__free_hook = tr_freehook;
|
||||
tr_old_malloc_hook = __malloc_hook;
|
||||
__malloc_hook = tr_mallochook;
|
||||
tr_old_realloc_hook = __realloc_hook;
|
||||
__realloc_hook = tr_reallochook;
|
||||
tr_old_memalign_hook = __memalign_hook;
|
||||
__memalign_hook = tr_memalignhook;
|
||||
save_default_hooks ();
|
||||
set_trace_hooks ();
|
||||
#ifdef _LIBC
|
||||
if (!added_atexit_handler)
|
||||
{
|
||||
@@ -338,10 +361,7 @@ muntrace (void)
|
||||
file. */
|
||||
FILE *f = mallstream;
|
||||
mallstream = NULL;
|
||||
__free_hook = tr_old_free_hook;
|
||||
__malloc_hook = tr_old_malloc_hook;
|
||||
__realloc_hook = tr_old_realloc_hook;
|
||||
__memalign_hook = tr_old_memalign_hook;
|
||||
set_default_hooks ();
|
||||
|
||||
fprintf (f, "= End\n");
|
||||
fclose (f);
|
||||
|
||||
@@ -35,8 +35,8 @@ call_free (void *ptr)
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
void *ptr1 = malloc (SIZE);
|
||||
void *ptr2 = malloc (SIZE);
|
||||
void *volatile ptr1 = malloc (SIZE);
|
||||
void *volatile ptr2 = malloc (SIZE);
|
||||
|
||||
/* Avoid unwanted output to TTY after an expected memory corruption. */
|
||||
ignore_stderr();
|
||||
|
||||
@@ -69,7 +69,7 @@ test_setup (void)
|
||||
static void
|
||||
test_large_allocations (size_t size)
|
||||
{
|
||||
void * ptr_to_realloc;
|
||||
void *volatile ptr_to_realloc;
|
||||
|
||||
test_setup ();
|
||||
TEST_VERIFY (malloc (size) == NULL);
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ merror (const char *msg)
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *p, *q;
|
||||
void *volatile p, *volatile q;
|
||||
int save;
|
||||
|
||||
errno = 0;
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ merror (const char *msg)
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *p, *q;
|
||||
void *volatile p, *volatile q;
|
||||
|
||||
errno = 0;
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ merror (const char *msg)
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *p;
|
||||
void *volatile p;
|
||||
unsigned char *c;
|
||||
int save, i, ok;
|
||||
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ merror (const char *msg)
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *p;
|
||||
void *volatile p;
|
||||
unsigned long pagesize = getpagesize ();
|
||||
unsigned long ptrval;
|
||||
int save;
|
||||
|
||||
+3
-1
@@ -361,9 +361,11 @@ tgmath3-macros = atan2 cbrt ceil copysign erf erfc exp2 expm1 fdim floor \
|
||||
fromfp fromfpx ufromfp ufromfpx totalorder totalordermag \
|
||||
scalb
|
||||
tgmath3-macro-tests = $(addprefix test-tgmath3-,$(tgmath3-macros))
|
||||
# Suppress these tests with clang for now, multiple issues
|
||||
ifneq ($(with-clang),yes)
|
||||
tests += $(tgmath3-macro-tests)
|
||||
generated += $(addsuffix .c,$(tgmath3-macro-tests))
|
||||
|
||||
endif
|
||||
$(tgmath3-macro-tests:%=$(objpfx)%.o): CFLAGS += -fno-builtin
|
||||
|
||||
$(foreach m,$(tgmath3-macros),\
|
||||
|
||||
@@ -52,23 +52,40 @@ __BEGIN_DECLS
|
||||
#undef I
|
||||
#define I _Complex_I
|
||||
|
||||
#if defined __USE_ISOC11 && defined __clang__
|
||||
/* Clang casts types to _Complex instead of using __builtin_complex. */
|
||||
#define __CMPLX(x, y, t) (+(_Complex t){(t)(x), (t)(y)})
|
||||
#define CMPLX(x, y) __CMPLX(x, y, double)
|
||||
#define CMPLXF(x, y) __CMPLX(x, y, float)
|
||||
#define CMPLXL(x, y) __CMPLX(x, y, long double)
|
||||
#else
|
||||
#if defined __USE_ISOC11 && __GNUC_PREREQ (4, 7)
|
||||
/* Macros to expand into expression of specified complex type. */
|
||||
# define CMPLX(x, y) __builtin_complex ((double) (x), (double) (y))
|
||||
# define CMPLXF(x, y) __builtin_complex ((float) (x), (float) (y))
|
||||
# define CMPLXL(x, y) __builtin_complex ((long double) (x), (long double) (y))
|
||||
#endif
|
||||
#endif /* __clang __ */
|
||||
|
||||
#if __HAVE_FLOAT16 && __GLIBC_USE (IEC_60559_TYPES_EXT)
|
||||
# define CMPLXF16(x, y) __builtin_complex ((_Float16) (x), (_Float16) (y))
|
||||
#endif
|
||||
|
||||
#if __HAVE_FLOAT32 && __GLIBC_USE (IEC_60559_TYPES_EXT)
|
||||
#if defined(__clang__)
|
||||
/* The typedef _Float32 does not seem to work here. */
|
||||
# define CMPLXF32(x, y) __CMPLX(x, y, float)
|
||||
#else
|
||||
# define CMPLXF32(x, y) __builtin_complex ((_Float32) (x), (_Float32) (y))
|
||||
#endif /* __clang __ */
|
||||
#endif
|
||||
|
||||
#if __HAVE_FLOAT64 && __GLIBC_USE (IEC_60559_TYPES_EXT)
|
||||
#if defined(__clang__)
|
||||
# define CMPLXF64(x, y) __CMPLX(x, y, double)
|
||||
#else
|
||||
# define CMPLXF64(x, y) __builtin_complex ((_Float64) (x), (_Float64) (y))
|
||||
#endif /* __clang __ */
|
||||
#endif
|
||||
|
||||
#if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
|
||||
@@ -76,11 +93,19 @@ __BEGIN_DECLS
|
||||
#endif
|
||||
|
||||
#if __HAVE_FLOAT32X && __GLIBC_USE (IEC_60559_TYPES_EXT)
|
||||
#if defined(__clang__)
|
||||
# define CMPLXF32X(x, y) __CMPLX(x, y, double)
|
||||
#else
|
||||
# define CMPLXF32X(x, y) __builtin_complex ((_Float32x) (x), (_Float32x) (y))
|
||||
#endif
|
||||
#endif /* __clang __ */
|
||||
|
||||
#if __HAVE_FLOAT64X && __GLIBC_USE (IEC_60559_TYPES_EXT)
|
||||
#if defined(__clang__)
|
||||
# define CMPLXF64X(x, y) __CMPLX(x, y, long double)
|
||||
#else
|
||||
# define CMPLXF64X(x, y) __builtin_complex ((_Float64x) (x), (_Float64x) (y))
|
||||
#endif /* __clang __ */
|
||||
#endif
|
||||
|
||||
#if __HAVE_FLOAT128X && __GLIBC_USE (IEC_60559_TYPES_EXT)
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
|
||||
#ifdef FE_INVALID
|
||||
# ifndef FE_SNANS_ALWAYS_SIGNAL
|
||||
# ifdef __clang__
|
||||
# warning "FE_SNANS_ALWAYS_SIGNAL not defined, fix clang please"
|
||||
# else
|
||||
# error "FE_SNANS_ALWAYS_SIGNAL not defined"
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# ifdef FE_SNANS_ALWAYS_SIGNAL
|
||||
|
||||
@@ -21,8 +21,12 @@
|
||||
#include <atomic.h>
|
||||
|
||||
#ifndef atomic_t
|
||||
#ifdef __clang__
|
||||
# define atomic_t long
|
||||
#else
|
||||
# define atomic_t int
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Test various atomic.h macros. */
|
||||
static int
|
||||
|
||||
+16
-3
@@ -231,6 +231,11 @@ CFLAGS-fsync.c += -fexceptions -fasynchronous-unwind-tables
|
||||
|
||||
CFLAGS-pt-system.c += -fexceptions
|
||||
|
||||
# Workaround for clang assembler problem with ifunc relocs, b/119574415
|
||||
ifeq ($(with-clang),yes)
|
||||
CFLAGS-pt-vfork.c += -no-integrated-as
|
||||
endif
|
||||
|
||||
LDLIBS-tst-once5 = -lstdc++
|
||||
CFLAGS-tst-thread_local1.o = -std=gnu++11
|
||||
LDLIBS-tst-thread_local1 = -lstdc++
|
||||
@@ -319,7 +324,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
|
||||
tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
|
||||
tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
|
||||
tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
|
||||
tst-rwlock-pwn
|
||||
tst-rwlock-pwn \
|
||||
tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall
|
||||
|
||||
tests-internal := tst-rwlock19 tst-rwlock20 \
|
||||
tst-sem11 tst-sem12 tst-sem13 \
|
||||
@@ -388,16 +394,22 @@ tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \
|
||||
tests-internal += tst-tls3 tst-tls3-malloc tst-tls5 tst-stackguard1
|
||||
tests-nolibpthread += tst-fini1
|
||||
ifeq ($(have-z-execstack),yes)
|
||||
# Test depends on a nested function, can't compile without rewrite
|
||||
ifneq ($(with-clang),yes)
|
||||
tests += tst-execstack
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
|
||||
tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
|
||||
tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
|
||||
tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \
|
||||
tst-_res1mod1 tst-_res1mod2 tst-fini1mod \
|
||||
tst-join7mod tst-compat-forwarder-mod tst-audit-threads-mod1 \
|
||||
tst-audit-threads-mod2
|
||||
ifneq ($(with-clang),yes)
|
||||
modules-names += tst-execstack-mod
|
||||
endif
|
||||
extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) \
|
||||
tst-cleanup4aux.o tst-cleanupx4aux.o
|
||||
test-extras += tst-cleanup4aux tst-cleanupx4aux
|
||||
@@ -422,10 +434,11 @@ ifeq ($(build-shared),yes)
|
||||
|
||||
# Set the `multidir' variable by grabbing the variable from the compiler.
|
||||
# We do it once and save the result in a generated makefile.
|
||||
# Suppress not-working clang attempt to include 32 and x32 multidirs.
|
||||
-include $(objpfx)multidir.mk
|
||||
$(objpfx)multidir.mk: $(common-objpfx)config.make
|
||||
$(make-target-directory)
|
||||
dir=`$(CC) $(CFLAGS) $(CPPFLAGS) -print-multi-directory`; \
|
||||
dir="."; \
|
||||
echo "multidir := $$dir" > $@T
|
||||
mv -f $@T $@
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
|
||||
pthread_cleanup_pop (0);
|
||||
}
|
||||
|
||||
void *pd_result = pd->result;
|
||||
if (__glibc_likely (result == 0))
|
||||
{
|
||||
/* We mark the thread as terminated and as joined. */
|
||||
@@ -93,7 +94,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
|
||||
|
||||
/* Store the return value if the caller is interested. */
|
||||
if (thread_return != NULL)
|
||||
*thread_return = pd->result;
|
||||
*thread_return = pd_result;
|
||||
|
||||
/* Free the TCB. */
|
||||
__free_tcb (pd);
|
||||
@@ -101,7 +102,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
|
||||
else
|
||||
pd->joinid = NULL;
|
||||
|
||||
LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd->result);
|
||||
LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd_result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
&mutex->__data.__list.__next);
|
||||
/* We need to set op_pending before starting the operation. Also
|
||||
see comments at ENQUEUE_MUTEX. */
|
||||
__asm ("" ::: "memory");
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
do
|
||||
@@ -119,7 +122,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
/* But it is inconsistent unless marked otherwise. */
|
||||
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
|
||||
|
||||
/* We must not enqueue the mutex before we have acquired it.
|
||||
Also see comments at ENQUEUE_MUTEX. */
|
||||
__asm ("" ::: "memory");
|
||||
ENQUEUE_MUTEX (mutex);
|
||||
/* We need to clear op_pending after we enqueue the mutex. */
|
||||
__asm ("" ::: "memory");
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
/* Note that we deliberately exist here. If we fall
|
||||
@@ -135,6 +143,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
int kind = PTHREAD_MUTEX_TYPE (mutex);
|
||||
if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
|
||||
{
|
||||
/* We do not need to ensure ordering wrt another memory
|
||||
access. Also see comments at ENQUEUE_MUTEX. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
NULL);
|
||||
return EDEADLK;
|
||||
@@ -142,6 +152,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
|
||||
if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
|
||||
{
|
||||
/* We do not need to ensure ordering wrt another memory
|
||||
access. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
NULL);
|
||||
|
||||
@@ -160,6 +172,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
id, 0);
|
||||
if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0)
|
||||
{
|
||||
/* We haven't acquired the lock as it is already acquired by
|
||||
another owner. We do not need to ensure ordering wrt another
|
||||
memory access. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
return EBUSY;
|
||||
@@ -173,13 +188,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
if (oldval == id)
|
||||
lll_unlock (mutex->__data.__lock,
|
||||
PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
|
||||
/* FIXME This violates the mutex destruction requirements. See
|
||||
__pthread_mutex_unlock_full. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
}
|
||||
while ((oldval & FUTEX_OWNER_DIED) != 0);
|
||||
|
||||
/* We must not enqueue the mutex before we have acquired it.
|
||||
Also see comments at ENQUEUE_MUTEX. */
|
||||
__asm ("" ::: "memory");
|
||||
ENQUEUE_MUTEX (mutex);
|
||||
/* We need to clear op_pending after we enqueue the mutex. */
|
||||
__asm ("" ::: "memory");
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
mutex->__data.__owner = id;
|
||||
@@ -211,10 +233,15 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
}
|
||||
|
||||
if (robust)
|
||||
/* Note: robust PI futexes are signaled by setting bit 0. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
(void *) (((uintptr_t) &mutex->__data.__list.__next)
|
||||
| 1));
|
||||
{
|
||||
/* Note: robust PI futexes are signaled by setting bit 0. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
|
||||
(void *) (((uintptr_t) &mutex->__data.__list.__next)
|
||||
| 1));
|
||||
/* We need to set op_pending before starting the operation. Also
|
||||
see comments at ENQUEUE_MUTEX. */
|
||||
__asm ("" ::: "memory");
|
||||
}
|
||||
|
||||
oldval = mutex->__data.__lock;
|
||||
|
||||
@@ -223,12 +250,16 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
{
|
||||
if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
|
||||
{
|
||||
/* We do not need to ensure ordering wrt another memory
|
||||
access. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return EDEADLK;
|
||||
}
|
||||
|
||||
if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
|
||||
{
|
||||
/* We do not need to ensure ordering wrt another memory
|
||||
access. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
/* Just bump the counter. */
|
||||
@@ -250,6 +281,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
{
|
||||
if ((oldval & FUTEX_OWNER_DIED) == 0)
|
||||
{
|
||||
/* We haven't acquired the lock as it is already acquired by
|
||||
another owner. We do not need to ensure ordering wrt another
|
||||
memory access. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
return EBUSY;
|
||||
@@ -270,6 +304,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
if (INTERNAL_SYSCALL_ERROR_P (e, __err)
|
||||
&& INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK)
|
||||
{
|
||||
/* The kernel has not yet finished the mutex owner death.
|
||||
We do not need to ensure ordering wrt another memory
|
||||
access. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
return EBUSY;
|
||||
@@ -287,7 +324,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
/* But it is inconsistent unless marked otherwise. */
|
||||
mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
|
||||
|
||||
/* We must not enqueue the mutex before we have acquired it.
|
||||
Also see comments at ENQUEUE_MUTEX. */
|
||||
__asm ("" ::: "memory");
|
||||
ENQUEUE_MUTEX (mutex);
|
||||
/* We need to clear op_pending after we enqueue the mutex. */
|
||||
__asm ("" ::: "memory");
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
|
||||
/* Note that we deliberately exit here. If we fall
|
||||
@@ -310,13 +352,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
|
||||
0, 0);
|
||||
|
||||
/* To the kernel, this will be visible after the kernel has
|
||||
acquired the mutex in the syscall. */
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
return ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
if (robust)
|
||||
{
|
||||
/* We must not enqueue the mutex before we have acquired it.
|
||||
Also see comments at ENQUEUE_MUTEX. */
|
||||
__asm ("" ::: "memory");
|
||||
ENQUEUE_MUTEX_PI (mutex);
|
||||
/* We need to clear op_pending after we enqueue the mutex. */
|
||||
__asm ("" ::: "memory");
|
||||
THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,15 +94,22 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
|
||||
/* Same as in __pthread_rwlock_rdlock_full:
|
||||
We started the read phase, so we are also responsible for
|
||||
updating the write-phase futex. Relaxed MO is sufficient.
|
||||
Note that there can be no other reader that we have to wake
|
||||
because all other readers will see the read phase started by us
|
||||
(or they will try to start it themselves); if a writer started
|
||||
the read phase, we cannot have started it. Furthermore, we
|
||||
cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will
|
||||
overwrite the value set by the most recent writer (or the readers
|
||||
before it in case of explicit hand-over) and we know that there
|
||||
are no waiting readers. */
|
||||
atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
|
||||
We have to do the same steps as a writer would when handing over the
|
||||
read phase to use because other readers cannot distinguish between
|
||||
us and the writer.
|
||||
Note that __pthread_rwlock_tryrdlock callers will not have to be
|
||||
woken up because they will either see the read phase started by us
|
||||
or they will try to start it themselves; however, callers of
|
||||
__pthread_rwlock_rdlock_full just increase the reader count and then
|
||||
check what state the lock is in, so they cannot distinguish between
|
||||
us and a writer that acquired and released the lock in the
|
||||
meantime. */
|
||||
if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
|
||||
& PTHREAD_RWLOCK_FUTEX_USED) != 0)
|
||||
{
|
||||
int private = __pthread_rwlock_get_private (rwlock);
|
||||
futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -46,8 +46,15 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
|
||||
&rwlock->__data.__readers, &r,
|
||||
r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
|
||||
{
|
||||
/* We have become the primary writer and we cannot have shared
|
||||
the PTHREAD_RWLOCK_FUTEX_USED flag with someone else, so we
|
||||
can simply enable blocking (see full wrlock code). */
|
||||
atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
|
||||
atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
|
||||
/* If we started a write phase, we need to enable readers to
|
||||
wait. If we did not, we must not change it because other threads
|
||||
may have set the PTHREAD_RWLOCK_FUTEX_USED in the meantime. */
|
||||
if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
|
||||
atomic_store_relaxed (&rwlock->__data.__cur_writer,
|
||||
THREAD_GETMEM (THREAD_SELF, tid));
|
||||
return 0;
|
||||
|
||||
@@ -107,13 +107,14 @@ __unregister_atfork (void *dso_handle)
|
||||
}
|
||||
|
||||
void
|
||||
__run_fork_handlers (enum __run_fork_handler_type who)
|
||||
__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking)
|
||||
{
|
||||
struct fork_handler *runp;
|
||||
|
||||
if (who == atfork_run_prepare)
|
||||
{
|
||||
lll_lock (atfork_lock, LLL_PRIVATE);
|
||||
if (do_locking)
|
||||
lll_lock (atfork_lock, LLL_PRIVATE);
|
||||
size_t sl = fork_handler_list_size (&fork_handlers);
|
||||
for (size_t i = sl; i > 0; i--)
|
||||
{
|
||||
@@ -133,7 +134,8 @@ __run_fork_handlers (enum __run_fork_handler_type who)
|
||||
else if (who == atfork_run_parent && runp->parent_handler)
|
||||
runp->parent_handler ();
|
||||
}
|
||||
lll_unlock (atfork_lock, LLL_PRIVATE);
|
||||
if (do_locking)
|
||||
lll_unlock (atfork_lock, LLL_PRIVATE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
/* Bug 23844: Test for pthread_rwlock_tryrdlock stalls.
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* For a full analysis see comment:
|
||||
https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14
|
||||
|
||||
Provided here for reference:
|
||||
|
||||
--- Analysis of pthread_rwlock_tryrdlock() stall ---
|
||||
A read lock begins to execute.
|
||||
|
||||
In __pthread_rwlock_rdlock_full:
|
||||
|
||||
We can attempt a read lock, but find that the lock is
|
||||
in a write phase (PTHREAD_RWLOCK_WRPHASE, or WP-bit
|
||||
is set), and the lock is held by a primary writer
|
||||
(PTHREAD_RWLOCK_WRLOCKED is set). In this case we must
|
||||
wait for explicit hand over from the writer to us or
|
||||
one of the other waiters. The read lock threads are
|
||||
about to execute:
|
||||
|
||||
341 r = (atomic_fetch_add_acquire (&rwlock->__data.__readers,
|
||||
342 (1 << PTHREAD_RWLOCK_READER_SHIFT))
|
||||
343 + (1 << PTHREAD_RWLOCK_READER_SHIFT));
|
||||
|
||||
An unlock beings to execute.
|
||||
|
||||
Then in __pthread_rwlock_wrunlock:
|
||||
|
||||
547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
|
||||
...
|
||||
549 while (!atomic_compare_exchange_weak_release
|
||||
550 (&rwlock->__data.__readers, &r,
|
||||
551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
|
||||
552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
|
||||
553 : PTHREAD_RWLOCK_WRPHASE))))
|
||||
554 {
|
||||
...
|
||||
556 }
|
||||
|
||||
We clear PTHREAD_RWLOCK_WRLOCKED, and if there are
|
||||
no readers so we leave the lock in PTHRAD_RWLOCK_WRPHASE.
|
||||
|
||||
Back in the read lock.
|
||||
|
||||
The read lock adjusts __readres as above.
|
||||
|
||||
383 while ((r & PTHREAD_RWLOCK_WRPHASE) != 0
|
||||
384 && (r & PTHREAD_RWLOCK_WRLOCKED) == 0)
|
||||
385 {
|
||||
...
|
||||
390 if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
|
||||
391 r ^ PTHREAD_RWLOCK_WRPHASE))
|
||||
392 {
|
||||
|
||||
And then attemps to start the read phase.
|
||||
|
||||
Assume there happens to be a tryrdlock at this point, noting
|
||||
that PTHREAD_RWLOCK_WRLOCKED is clear, and PTHREAD_RWLOCK_WRPHASE
|
||||
is 1. So the try lock attemps to start the read phase.
|
||||
|
||||
In __pthread_rwlock_tryrdlock:
|
||||
|
||||
44 if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
|
||||
45 {
|
||||
...
|
||||
49 if (((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
|
||||
50 && (rwlock->__data.__flags
|
||||
51 == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))
|
||||
52 return EBUSY;
|
||||
53 rnew = r + (1 << PTHREAD_RWLOCK_READER_SHIFT);
|
||||
54 }
|
||||
...
|
||||
89 while (!atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
|
||||
90 &r, rnew));
|
||||
|
||||
And succeeds.
|
||||
|
||||
Back in the write unlock:
|
||||
|
||||
557 if ((r >> PTHREAD_RWLOCK_READER_SHIFT) != 0)
|
||||
558 {
|
||||
...
|
||||
563 if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
|
||||
564 & PTHREAD_RWLOCK_FUTEX_USED) != 0)
|
||||
565 futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
|
||||
566 }
|
||||
|
||||
We note that PTHREAD_RWLOCK_FUTEX_USED is non-zero
|
||||
and don't wake anyone. This is OK because we handed
|
||||
over to the trylock. It will be the trylock's responsibility
|
||||
to wake any waiters.
|
||||
|
||||
Back in the read lock:
|
||||
|
||||
The read lock fails to install PTHRAD_REWLOCK_WRPHASE as 0 because
|
||||
the __readers value was adjusted by the trylock, and so it falls through
|
||||
to waiting on the lock for explicit handover from either a new writer
|
||||
or a new reader.
|
||||
|
||||
448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
|
||||
449 1 | PTHREAD_RWLOCK_FUTEX_USED,
|
||||
450 abstime, private);
|
||||
|
||||
We use PTHREAD_RWLOCK_FUTEX_USED to indicate the futex
|
||||
is in use.
|
||||
|
||||
At this point we have readers waiting on the read lock
|
||||
to unlock. The wrlock is done. The trylock is finishing
|
||||
the installation of the read phase.
|
||||
|
||||
92 if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
|
||||
93 {
|
||||
...
|
||||
105 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
|
||||
106 }
|
||||
|
||||
The trylock does note that we were the one that
|
||||
installed the read phase, but the comments are not
|
||||
correct, the execution ordering above shows that
|
||||
readers might indeed be waiting, and they are.
|
||||
|
||||
The atomic_store_relaxed throws away PTHREAD_RWLOCK_FUTEX_USED,
|
||||
and the waiting reader is never worken becuase as noted
|
||||
above it is conditional on the futex being used.
|
||||
|
||||
The solution is for the trylock thread to inspect
|
||||
PTHREAD_RWLOCK_FUTEX_USED and wake the waiting readers.
|
||||
|
||||
--- Analysis of pthread_rwlock_trywrlock() stall ---
|
||||
|
||||
A write lock begins to execute, takes the write lock,
|
||||
and then releases the lock...
|
||||
|
||||
In pthread_rwlock_wrunlock():
|
||||
|
||||
547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
|
||||
...
|
||||
549 while (!atomic_compare_exchange_weak_release
|
||||
550 (&rwlock->__data.__readers, &r,
|
||||
551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
|
||||
552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
|
||||
553 : PTHREAD_RWLOCK_WRPHASE))))
|
||||
554 {
|
||||
...
|
||||
556 }
|
||||
|
||||
... leaving it in the write phase with zero readers
|
||||
(the case where we leave the write phase in place
|
||||
during a write unlock).
|
||||
|
||||
A write trylock begins to execute.
|
||||
|
||||
In __pthread_rwlock_trywrlock:
|
||||
|
||||
40 while (((r & PTHREAD_RWLOCK_WRLOCKED) == 0)
|
||||
41 && (((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)
|
||||
42 || (prefer_writer && ((r & PTHREAD_RWLOCK_WRPHASE) != 0))))
|
||||
43 {
|
||||
|
||||
The lock is not locked.
|
||||
|
||||
There are no readers.
|
||||
|
||||
45 if (atomic_compare_exchange_weak_acquire (
|
||||
46 &rwlock->__data.__readers, &r,
|
||||
47 r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
|
||||
|
||||
We atomically install the write phase and we take the
|
||||
exclusive write lock.
|
||||
|
||||
48 {
|
||||
49 atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
|
||||
|
||||
We get this far.
|
||||
|
||||
A reader lock begins to execute.
|
||||
|
||||
In pthread_rwlock_rdlock:
|
||||
|
||||
437 for (;;)
|
||||
438 {
|
||||
439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
|
||||
440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
441 {
|
||||
442 int private = __pthread_rwlock_get_private (rwlock);
|
||||
443 if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
|
||||
444 && (!atomic_compare_exchange_weak_relaxed
|
||||
445 (&rwlock->__data.__wrphase_futex,
|
||||
446 &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)))
|
||||
447 continue;
|
||||
448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
|
||||
449 1 | PTHREAD_RWLOCK_FUTEX_USED,
|
||||
450 abstime, private);
|
||||
|
||||
We are in a write phase, so the while() on line 439 is true.
|
||||
|
||||
The value of wpf does not have PTHREAD_RWLOCK_FUTEX_USED set
|
||||
since this is the first reader to lock.
|
||||
|
||||
The atomic operation sets wpf with PTHREAD_RELOCK_FUTEX_USED
|
||||
on the expectation that this reader will be woken during
|
||||
the handoff.
|
||||
|
||||
Back in pthread_rwlock_trywrlock:
|
||||
|
||||
50 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
|
||||
51 atomic_store_relaxed (&rwlock->__data.__cur_writer,
|
||||
52 THREAD_GETMEM (THREAD_SELF, tid));
|
||||
53 return 0;
|
||||
54 }
|
||||
...
|
||||
57 }
|
||||
|
||||
We write 1 to __wrphase_futex discarding PTHREAD_RWLOCK_FUTEX_USED,
|
||||
and so in the unlock we will not awaken the waiting reader.
|
||||
|
||||
The solution to this is to realize that if we did not start the write
|
||||
phase we need not write 1 or any other value to __wrphase_futex.
|
||||
This ensures that any readers (which saw __wrphase_futex != 0) can
|
||||
set PTHREAD_RWLOCK_FUTEX_USED and this can be used at unlock to
|
||||
wake them.
|
||||
|
||||
If we installed the write phase then all other readers are looping
|
||||
here:
|
||||
|
||||
In __pthread_rwlock_rdlock_full:
|
||||
|
||||
437 for (;;)
|
||||
438 {
|
||||
439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
|
||||
440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
|
||||
441 {
|
||||
...
|
||||
508 }
|
||||
|
||||
waiting for the write phase to be installed or removed before they
|
||||
can begin waiting on __wrphase_futex (part of the algorithm), or
|
||||
taking a concurrent read lock, and thus we can safely write 1 to
|
||||
__wrphase_futex.
|
||||
|
||||
If we did not install the write phase then the readers may already
|
||||
be waiting on the futex, the original writer wrote 1 to __wrphase_futex
|
||||
as part of starting the write phase, and we cannot also write 1
|
||||
without loosing the PTHREAD_RWLOCK_FUTEX_USED bit.
|
||||
|
||||
---
|
||||
|
||||
Summary for the pthread_rwlock_tryrdlock() stall:
|
||||
|
||||
The stall is caused by pthread_rwlock_tryrdlock failing to check
|
||||
that PTHREAD_RWLOCK_FUTEX_USED is set in the __wrphase_futex futex
|
||||
and then waking the futex.
|
||||
|
||||
The fix for bug 23844 ensures that waiters on __wrphase_futex are
|
||||
correctly woken. Before the fix the test stalls as readers can
|
||||
wait forever on __wrphase_futex. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <support/xthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* We need only one lock to reproduce the issue. We will need multiple
|
||||
threads to get the exact case where we have a read, try, and unlock
|
||||
all interleaving to produce the case where the readers are waiting
|
||||
and the try fails to wake them. */
|
||||
pthread_rwlock_t onelock;
|
||||
|
||||
/* The number of threads is arbitrary but empirically chosen to have
|
||||
enough threads that we see the condition where waiting readers are
|
||||
not woken by a successful tryrdlock. */
|
||||
#define NTHREADS 32
|
||||
|
||||
_Atomic int do_exit;
|
||||
|
||||
void *
|
||||
run_loop (void *arg)
|
||||
{
|
||||
int i = 0, ret;
|
||||
while (!do_exit)
|
||||
{
|
||||
/* Arbitrarily choose if we are the writer or reader. Choose a
|
||||
high enough ratio of readers to writers to make it likely
|
||||
that readers block (and eventually are susceptable to
|
||||
stalling).
|
||||
|
||||
If we are a writer, take the write lock, and then unlock.
|
||||
If we are a reader, try the lock, then lock, then unlock. */
|
||||
if ((i % 8) != 0)
|
||||
xpthread_rwlock_wrlock (&onelock);
|
||||
else
|
||||
{
|
||||
if ((ret = pthread_rwlock_tryrdlock (&onelock)) != 0)
|
||||
{
|
||||
if (ret == EBUSY)
|
||||
xpthread_rwlock_rdlock (&onelock);
|
||||
else
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
/* Thread does some work and then unlocks. */
|
||||
xpthread_rwlock_unlock (&onelock);
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
int i;
|
||||
pthread_t tids[NTHREADS];
|
||||
xpthread_rwlock_init (&onelock, NULL);
|
||||
for (i = 0; i < NTHREADS; i++)
|
||||
tids[i] = xpthread_create (NULL, run_loop, NULL);
|
||||
/* Run for some amount of time. Empirically speaking exercising
|
||||
the stall via pthread_rwlock_tryrdlock is much harder, and on
|
||||
a 3.5GHz 4 core x86_64 VM system it takes somewhere around
|
||||
20-200s to stall, approaching 100% stall past 200s. We can't
|
||||
wait that long for a regression test so we just test for 20s,
|
||||
and expect the stall to happen with a 5-10% chance (enough for
|
||||
developers to see). */
|
||||
sleep (20);
|
||||
/* Then exit. */
|
||||
printf ("INFO: Exiting...\n");
|
||||
do_exit = 1;
|
||||
/* If any readers stalled then we will timeout waiting for them. */
|
||||
for (i = 0; i < NTHREADS; i++)
|
||||
xpthread_join (tids[i]);
|
||||
printf ("INFO: Done.\n");
|
||||
xpthread_rwlock_destroy (&onelock);
|
||||
printf ("PASS: No pthread_rwlock_tryrdlock stalls detected.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TIMEOUT 30
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,108 @@
|
||||
/* Bug 23844: Test for pthread_rwlock_trywrlock stalls.
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* For a full analysis see comments in tst-rwlock-tryrdlock-stall.c.
|
||||
|
||||
Summary for the pthread_rwlock_trywrlock() stall:
|
||||
|
||||
The stall is caused by pthread_rwlock_trywrlock setting
|
||||
__wrphase_futex futex to 1 and loosing the
|
||||
PTHREAD_RWLOCK_FUTEX_USED bit.
|
||||
|
||||
The fix for bug 23844 ensures that waiters on __wrphase_futex are
|
||||
correctly woken. Before the fix the test stalls as readers can
|
||||
wait forever on __wrphase_futex. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <support/xthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* We need only one lock to reproduce the issue. We will need multiple
|
||||
threads to get the exact case where we have a read, try, and unlock
|
||||
all interleaving to produce the case where the readers are waiting
|
||||
and the try clears the PTHREAD_RWLOCK_FUTEX_USED bit and a
|
||||
subsequent unlock fails to wake them. */
|
||||
pthread_rwlock_t onelock;
|
||||
|
||||
/* The number of threads is arbitrary but empirically chosen to have
|
||||
enough threads that we see the condition where waiting readers are
|
||||
not woken by a successful unlock. */
|
||||
#define NTHREADS 32
|
||||
|
||||
_Atomic int do_exit;
|
||||
|
||||
void *
|
||||
run_loop (void *arg)
|
||||
{
|
||||
int i = 0, ret;
|
||||
while (!do_exit)
|
||||
{
|
||||
/* Arbitrarily choose if we are the writer or reader. Choose a
|
||||
high enough ratio of readers to writers to make it likely
|
||||
that readers block (and eventually are susceptable to
|
||||
stalling).
|
||||
|
||||
If we are a writer, take the write lock, and then unlock.
|
||||
If we are a reader, try the lock, then lock, then unlock. */
|
||||
if ((i % 8) != 0)
|
||||
{
|
||||
if ((ret = pthread_rwlock_trywrlock (&onelock)) != 0)
|
||||
{
|
||||
if (ret == EBUSY)
|
||||
xpthread_rwlock_wrlock (&onelock);
|
||||
else
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
xpthread_rwlock_rdlock (&onelock);
|
||||
/* Thread does some work and then unlocks. */
|
||||
xpthread_rwlock_unlock (&onelock);
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
int i;
|
||||
pthread_t tids[NTHREADS];
|
||||
xpthread_rwlock_init (&onelock, NULL);
|
||||
for (i = 0; i < NTHREADS; i++)
|
||||
tids[i] = xpthread_create (NULL, run_loop, NULL);
|
||||
/* Run for some amount of time. The pthread_rwlock_tryrwlock stall
|
||||
is very easy to trigger and happens in seconds under the test
|
||||
conditions. */
|
||||
sleep (10);
|
||||
/* Then exit. */
|
||||
printf ("INFO: Exiting...\n");
|
||||
do_exit = 1;
|
||||
/* If any readers stalled then we will timeout waiting for them. */
|
||||
for (i = 0; i < NTHREADS; i++)
|
||||
xpthread_join (tids[i]);
|
||||
printf ("INFO: Done.\n");
|
||||
xpthread_rwlock_destroy (&onelock);
|
||||
printf ("PASS: No pthread_rwlock_tryrwlock stalls detected.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -618,6 +618,47 @@ next_prime (size_t seed)
|
||||
return seed;
|
||||
}
|
||||
|
||||
#ifndef NESTING
|
||||
static struct database *globdb;
|
||||
static size_t max_chainlength;
|
||||
static char *wp;
|
||||
static size_t nhashentries;
|
||||
static bool copy_string;
|
||||
|
||||
void add_key(const void *nodep, const VISIT which, const int depth)
|
||||
{
|
||||
if (which != leaf && which != postorder)
|
||||
return;
|
||||
|
||||
const struct dbentry *dbe = *(const struct dbentry **) nodep;
|
||||
|
||||
ptrdiff_t stridx;
|
||||
if (copy_string)
|
||||
{
|
||||
stridx = wp - globdb->keystrtab;
|
||||
wp = stpcpy (wp, dbe->str) + 1;
|
||||
}
|
||||
else
|
||||
stridx = 0;
|
||||
|
||||
size_t hidx = dbe->hashval % nhashentries;
|
||||
size_t hval2 = 1 + dbe->hashval % (nhashentries - 2);
|
||||
size_t chainlength = 0;
|
||||
|
||||
while (globdb->hashtable[hidx] != ~((stridx_t) 0))
|
||||
{
|
||||
++chainlength;
|
||||
if ((hidx += hval2) >= nhashentries)
|
||||
hidx -= nhashentries;
|
||||
}
|
||||
|
||||
globdb->hashtable[hidx] = ((globdb->extra_string ? valstrlen : 0)
|
||||
+ dbe->validx);
|
||||
globdb->keyidxtab[hidx] = stridx;
|
||||
|
||||
max_chainlength = MAX (max_chainlength, chainlength);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
compute_tables (void)
|
||||
@@ -649,6 +690,7 @@ compute_tables (void)
|
||||
db->keyidxtab = db->hashtable + nhashentries_max;
|
||||
db->keystrtab = (char *) (db->keyidxtab + nhashentries_max);
|
||||
|
||||
#ifdef NESTING
|
||||
static size_t max_chainlength;
|
||||
static char *wp;
|
||||
static size_t nhashentries;
|
||||
@@ -687,6 +729,9 @@ compute_tables (void)
|
||||
|
||||
max_chainlength = MAX (max_chainlength, chainlength);
|
||||
}
|
||||
#else
|
||||
globdb = db;
|
||||
#endif
|
||||
|
||||
copy_string = false;
|
||||
nhashentries = nhashentries_min;
|
||||
|
||||
@@ -117,6 +117,8 @@ install-others-programs := $(inst_libexecdir)/getconf
|
||||
|
||||
before-compile += $(objpfx)posix-conf-vars-def.h
|
||||
|
||||
CFLAGS-regex.c += -Wno-error
|
||||
|
||||
# So they get cleaned up.
|
||||
generated += $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
|
||||
annexc annexc.out wordexp-tst.out bug-regex2-mem.out \
|
||||
|
||||
+270
-1
@@ -2839,6 +2839,261 @@ build_collating_symbol (bitset_t sbcset, const unsigned char *name)
|
||||
}
|
||||
#endif /* not _LIBC */
|
||||
|
||||
#ifndef NESTING
|
||||
|
||||
/* Local function for parse_bracket_exp used in _LIBC environment.
|
||||
Seek the collating symbol entry corresponding to NAME.
|
||||
Return the index of the symbol in the SYMB_TABLE,
|
||||
or -1 if not found. */
|
||||
|
||||
static int32_t
|
||||
__attribute__ ((always_inline))
|
||||
seek_collating_symbol_entry (const unsigned char *name, size_t name_len,
|
||||
int32_t *symb_table, int32_t table_size,
|
||||
unsigned char *extra)
|
||||
{
|
||||
int32_t elem;
|
||||
|
||||
for (elem = 0; elem < table_size; elem++)
|
||||
if (symb_table[2 * elem] != 0)
|
||||
{
|
||||
int32_t idx = symb_table[2 * elem + 1];
|
||||
/* Skip the name of collating element name. */
|
||||
idx += 1 + extra[idx];
|
||||
if (/* Compare the length of the name. */
|
||||
name_len == extra[idx]
|
||||
/* Compare the name. */
|
||||
&& memcmp (name, &extra[idx + 1], name_len) == 0)
|
||||
/* Yep, this is the entry. */
|
||||
return elem;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Local function for parse_bracket_exp used in _LIBC environment.
|
||||
Look up the collation sequence value of BR_ELEM.
|
||||
Return the value if succeeded, UINT_MAX otherwise. */
|
||||
|
||||
static unsigned int
|
||||
__attribute__ ((always_inline))
|
||||
lookup_collation_sequence_value (bracket_elem_t *br_elem, uint32_t nrules,
|
||||
unsigned char *collseqmb, char *collseqwc,
|
||||
int32_t *symb_table, int32_t table_size,
|
||||
unsigned char *extra)
|
||||
{
|
||||
if (br_elem->type == SB_CHAR)
|
||||
{
|
||||
/*
|
||||
if (MB_CUR_MAX == 1)
|
||||
*/
|
||||
if (nrules == 0)
|
||||
return collseqmb[br_elem->opr.ch];
|
||||
else
|
||||
{
|
||||
wint_t wc = __btowc (br_elem->opr.ch);
|
||||
return __collseq_table_lookup (collseqwc, wc);
|
||||
}
|
||||
}
|
||||
else if (br_elem->type == MB_CHAR)
|
||||
{
|
||||
if (nrules != 0)
|
||||
return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
|
||||
}
|
||||
else if (br_elem->type == COLL_SYM)
|
||||
{
|
||||
size_t sym_name_len = strlen ((char *) br_elem->opr.name);
|
||||
if (nrules != 0)
|
||||
{
|
||||
int32_t elem, idx;
|
||||
elem = seek_collating_symbol_entry (br_elem->opr.name,
|
||||
sym_name_len,
|
||||
symb_table, table_size,
|
||||
extra);
|
||||
if (elem != -1)
|
||||
{
|
||||
/* We found the entry. */
|
||||
idx = symb_table[2 * elem + 1];
|
||||
/* Skip the name of collating element name. */
|
||||
idx += 1 + extra[idx];
|
||||
/* Skip the byte sequence of the collating element. */
|
||||
idx += 1 + extra[idx];
|
||||
/* Adjust for the alignment. */
|
||||
idx = (idx + 3) & ~3;
|
||||
/* Skip the multibyte collation sequence value. */
|
||||
idx += sizeof (unsigned int);
|
||||
/* Skip the wide char sequence of the collating element. */
|
||||
idx += sizeof (unsigned int) *
|
||||
(1 + *(unsigned int *) (extra + idx));
|
||||
/* Return the collation sequence value. */
|
||||
return *(unsigned int *) (extra + idx);
|
||||
}
|
||||
else if (sym_name_len == 1)
|
||||
{
|
||||
/* No valid character. Match it as a single byte
|
||||
character. */
|
||||
return collseqmb[br_elem->opr.name[0]];
|
||||
}
|
||||
}
|
||||
else if (sym_name_len == 1)
|
||||
return collseqmb[br_elem->opr.name[0]];
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
/* Local function for parse_bracket_exp used in _LIBC environment.
|
||||
Build the range expression which starts from START_ELEM, and ends
|
||||
at END_ELEM. The result are written to MBCSET and SBCSET.
|
||||
RANGE_ALLOC is the allocated size of mbcset->range_starts, and
|
||||
mbcset->range_ends, is a pointer argument since we may
|
||||
update it. */
|
||||
|
||||
static reg_errcode_t
|
||||
__attribute__ ((always_inline))
|
||||
build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,
|
||||
bracket_elem_t *start_elem, bracket_elem_t *end_elem,
|
||||
re_dfa_t *dfa, reg_syntax_t syntax, uint32_t nrules,
|
||||
unsigned char *collseqmb, char *collseqwc,
|
||||
int32_t *symb_table, int32_t table_size,
|
||||
unsigned char *extra)
|
||||
{
|
||||
unsigned int ch;
|
||||
uint32_t start_collseq;
|
||||
uint32_t end_collseq;
|
||||
|
||||
/* Equivalence Classes and Character Classes can't be a range
|
||||
start/end. */
|
||||
if (__glibc_unlikely (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
|
||||
|| end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS))
|
||||
return REG_ERANGE;
|
||||
|
||||
start_collseq = lookup_collation_sequence_value (start_elem, nrules, collseqmb, collseqwc,
|
||||
symb_table, table_size, extra);
|
||||
end_collseq = lookup_collation_sequence_value (end_elem, nrules, collseqmb, collseqwc,
|
||||
symb_table, table_size, extra);
|
||||
/* Check start/end collation sequence values. */
|
||||
if (__glibc_unlikely (start_collseq == UINT_MAX || end_collseq == UINT_MAX))
|
||||
return REG_ECOLLATE;
|
||||
if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq))
|
||||
return REG_ERANGE;
|
||||
|
||||
/* Got valid collation sequence values, add them as a new entry.
|
||||
However, if we have no collation elements, and the character set
|
||||
is single byte, the single byte character set that we
|
||||
build below suffices. */
|
||||
if (nrules > 0 || dfa->mb_cur_max > 1)
|
||||
{
|
||||
/* Check the space of the arrays. */
|
||||
if (__glibc_unlikely (*range_alloc == mbcset->nranges))
|
||||
{
|
||||
/* There is not enough space, need realloc. */
|
||||
uint32_t *new_array_start;
|
||||
uint32_t *new_array_end;
|
||||
int new_nranges;
|
||||
|
||||
/* +1 in case of mbcset->nranges is 0. */
|
||||
new_nranges = 2 * mbcset->nranges + 1;
|
||||
new_array_start = re_realloc (mbcset->range_starts, uint32_t,
|
||||
new_nranges);
|
||||
new_array_end = re_realloc (mbcset->range_ends, uint32_t,
|
||||
new_nranges);
|
||||
|
||||
if (__glibc_unlikely (new_array_start == NULL || new_array_end == NULL))
|
||||
return REG_ESPACE;
|
||||
|
||||
mbcset->range_starts = new_array_start;
|
||||
mbcset->range_ends = new_array_end;
|
||||
*range_alloc = new_nranges;
|
||||
}
|
||||
|
||||
mbcset->range_starts[mbcset->nranges] = start_collseq;
|
||||
mbcset->range_ends[mbcset->nranges++] = end_collseq;
|
||||
}
|
||||
|
||||
/* Build the table for single byte characters. */
|
||||
for (ch = 0; ch < SBC_MAX; ch++)
|
||||
{
|
||||
uint32_t ch_collseq;
|
||||
/*
|
||||
if (MB_CUR_MAX == 1)
|
||||
*/
|
||||
if (nrules == 0)
|
||||
ch_collseq = collseqmb[ch];
|
||||
else
|
||||
ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
|
||||
if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
|
||||
bitset_set (sbcset, ch);
|
||||
}
|
||||
return REG_NOERROR;
|
||||
}
|
||||
|
||||
/* Local function for parse_bracket_exp used in _LIBC environment.
|
||||
Build the collating element which is represented by NAME.
|
||||
The result are written to MBCSET and SBCSET.
|
||||
COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
|
||||
pointer argument since we may update it. */
|
||||
|
||||
static reg_errcode_t
|
||||
__attribute__ ((always_inline))
|
||||
build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
|
||||
int *coll_sym_alloc, const unsigned char *name,
|
||||
uint32_t nrules, int32_t *symb_table, int32_t table_size,
|
||||
unsigned char *extra)
|
||||
{
|
||||
int32_t elem, idx;
|
||||
size_t name_len = strlen ((const char *) name);
|
||||
if (nrules != 0)
|
||||
{
|
||||
elem = seek_collating_symbol_entry (name, name_len, symb_table,
|
||||
table_size, extra);
|
||||
if (elem != -1)
|
||||
{
|
||||
/* We found the entry. */
|
||||
idx = symb_table[2 * elem + 1];
|
||||
/* Skip the name of collating element name. */
|
||||
idx += 1 + extra[idx];
|
||||
}
|
||||
else if (name_len == 1)
|
||||
{
|
||||
/* No valid character, treat it as a normal
|
||||
character. */
|
||||
bitset_set (sbcset, name[0]);
|
||||
return REG_NOERROR;
|
||||
}
|
||||
else
|
||||
return REG_ECOLLATE;
|
||||
|
||||
/* Got valid collation sequence, add it as a new entry. */
|
||||
/* Check the space of the arrays. */
|
||||
if (__glibc_unlikely (*coll_sym_alloc == mbcset->ncoll_syms))
|
||||
{
|
||||
/* Not enough, realloc it. */
|
||||
/* +1 in case of mbcset->ncoll_syms is 0. */
|
||||
int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
|
||||
/* Use realloc since mbcset->coll_syms is NULL
|
||||
if *alloc == 0. */
|
||||
int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
|
||||
new_coll_sym_alloc);
|
||||
if (__glibc_unlikely (new_coll_syms == NULL))
|
||||
return REG_ESPACE;
|
||||
mbcset->coll_syms = new_coll_syms;
|
||||
*coll_sym_alloc = new_coll_sym_alloc;
|
||||
}
|
||||
mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
|
||||
return REG_NOERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (__glibc_unlikely (name_len != 1))
|
||||
return REG_ECOLLATE;
|
||||
else
|
||||
{
|
||||
bitset_set (sbcset, name[0]);
|
||||
return REG_NOERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* n NESTING */
|
||||
|
||||
/* This function parse bracket expression like "[abc]", "[a-c]",
|
||||
"[[.a-a.]]" etc. */
|
||||
|
||||
@@ -2854,6 +3109,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
|
||||
const int32_t *symb_table;
|
||||
const unsigned char *extra;
|
||||
|
||||
# ifdef NESTING
|
||||
|
||||
/* Local function for parse_bracket_exp used in _LIBC environment.
|
||||
Seek the collating symbol entry corresponding to NAME.
|
||||
Return the index of the symbol in the SYMB_TABLE,
|
||||
@@ -3095,6 +3352,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif /* NESTING */
|
||||
#endif
|
||||
|
||||
re_token_t br_token;
|
||||
@@ -3237,8 +3495,15 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
|
||||
token_len = peek_token_bracket (token, regexp, syntax);
|
||||
|
||||
#ifdef _LIBC
|
||||
# ifdef NESTING
|
||||
*err = build_range_exp (sbcset, mbcset, &range_alloc,
|
||||
&start_elem, &end_elem);
|
||||
# else /* n NESTING */
|
||||
*err = build_range_exp (sbcset, mbcset, &range_alloc,
|
||||
&start_elem, &end_elem,
|
||||
dfa, syntax, nrules, collseqmb, collseqwc,
|
||||
symb_table, table_size, extra);
|
||||
# endif /* NESTING */
|
||||
#else
|
||||
# ifdef RE_ENABLE_I18N
|
||||
*err = build_range_exp (syntax, sbcset,
|
||||
@@ -3291,7 +3556,11 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
|
||||
#ifdef RE_ENABLE_I18N
|
||||
mbcset, &coll_sym_alloc,
|
||||
#endif /* RE_ENABLE_I18N */
|
||||
start_elem.opr.name);
|
||||
start_elem.opr.name
|
||||
#ifndef NESTING
|
||||
, nrules, symb_table, table_size, extra
|
||||
#endif /* NESTING */
|
||||
);
|
||||
if (__glibc_unlikely (*err != REG_NOERROR))
|
||||
goto parse_bracket_exp_free_return;
|
||||
break;
|
||||
|
||||
+4
-2
@@ -1293,8 +1293,10 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
|
||||
else if (naccepted)
|
||||
{
|
||||
char *buf = (char *) re_string_get_buffer (&mctx->input);
|
||||
if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
|
||||
naccepted) != 0)
|
||||
if (mctx->input.valid_len - *pidx < naccepted
|
||||
|| (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
|
||||
naccepted)
|
||||
!= 0))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,9 +61,9 @@ def gen_test(sym_data):
|
||||
continue
|
||||
name = arg[0]
|
||||
value = arg[1]
|
||||
out_lines.append('_Static_assert (U (asconst_%s) == (c_t) (%s), '
|
||||
'"value of %s");'
|
||||
% (name, value, name))
|
||||
# out_lines.append('_Static_assert (U (asconst_%s) == (c_t) (%s), '
|
||||
# '"value of %s");'
|
||||
# % (name, value, name))
|
||||
return '\n'.join(out_lines)
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
#ifndef __clang__ /* clang never finishes */
|
||||
size_t instances = 16384;
|
||||
#define X0 "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
|
||||
const char *item = "\na\nabbcd55";
|
||||
@@ -44,6 +45,7 @@ do_test (void)
|
||||
return 1;
|
||||
}
|
||||
free (buf);
|
||||
#endif /* __clang__ */
|
||||
return 0;
|
||||
}
|
||||
#define TEST_FUNCTION do_test ()
|
||||
|
||||
+15
-16
@@ -21,27 +21,26 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int failures = 0;
|
||||
|
||||
void
|
||||
try (const char *name, long long int param, int value, int expected)
|
||||
{
|
||||
if (value != expected)
|
||||
{
|
||||
printf ("%s(%#llx) expected %d got %d\n",
|
||||
name, param, expected, value);
|
||||
++failures;
|
||||
}
|
||||
else
|
||||
printf ("%s(%#llx) as expected %d\n", name, param, value);
|
||||
}
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
int failures = 0;
|
||||
int i;
|
||||
|
||||
auto void try (const char *name, long long int param, int value,
|
||||
int expected);
|
||||
|
||||
void try (const char *name, long long int param, int value, int expected)
|
||||
{
|
||||
if (value != expected)
|
||||
{
|
||||
printf ("%s(%#llx) expected %d got %d\n",
|
||||
name, param, expected, value);
|
||||
++failures;
|
||||
}
|
||||
else
|
||||
printf ("%s(%#llx) as expected %d\n", name, param, value);
|
||||
}
|
||||
|
||||
#define TEST(fct, type) \
|
||||
try (#fct, 0, fct ((type) 0), 0); \
|
||||
for (i=0 ; i < 8 * sizeof (type); i++) \
|
||||
|
||||
@@ -129,6 +129,7 @@ libsupport-routines = \
|
||||
xpthread_mutexattr_settype \
|
||||
xpthread_once \
|
||||
xpthread_rwlock_init \
|
||||
xpthread_rwlock_destroy \
|
||||
xpthread_rwlock_rdlock \
|
||||
xpthread_rwlock_unlock \
|
||||
xpthread_rwlock_wrlock \
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/* pthread_rwlock_destroy with error checking.
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <support/xthread.h>
|
||||
|
||||
void
|
||||
xpthread_rwlock_destroy (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
xpthread_check_return ("pthread_rwlock_destroy",
|
||||
pthread_rwlock_destroy (rwlock));
|
||||
}
|
||||
@@ -84,6 +84,7 @@ void xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref);
|
||||
void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
|
||||
void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
|
||||
void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
|
||||
void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/* Macros for customizing Systemtap <sys/sdt.h>. Arm version.
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* The default "nor" constraint produces unparseable memory references
|
||||
for constants. Omit the problematic "o" constraint. See bug 24164
|
||||
and GCC PR 89146. */
|
||||
#define STAP_SDT_ARG_CONSTRAINT nr
|
||||
@@ -719,7 +719,11 @@ _dl_dprintf (int fd, const char *fmt, ...)
|
||||
{
|
||||
/* Use local declaration to avoid includign <stdio.h>. */
|
||||
extern int __dprintf(int fd, const char *format, ...) attribute_hidden;
|
||||
#if defined(__clang__)
|
||||
__dprintf (fd, fmt);
|
||||
#else
|
||||
__dprintf (fd, fmt, __builtin_va_arg_pack ());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/* Macros for customizing Systemtap <sys/sdt.h>. Generic version.
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* By default, there are no customizations. */
|
||||
@@ -1,4 +1,4 @@
|
||||
# Include this earlier so it can be used earlier in Makefiles,
|
||||
# and sysdep/ makefiles.
|
||||
float128-fcts = yes
|
||||
float128-fcts = $(enable-float128)
|
||||
float64x-alias-fcts = yes
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
ifeq ($(enable-float128),yes)
|
||||
ifeq ($(subdir),stdlib)
|
||||
routines += float1282mpn strfromf128
|
||||
routines += strtof128 strtof128_l strtof128_nan mpn2float128
|
||||
@@ -10,3 +11,4 @@ endif
|
||||
ifeq ($(subdir),wcsmbs)
|
||||
routines += wcstof128_l wcstof128 wcstof128_nan
|
||||
endif
|
||||
endif # enable-float128
|
||||
|
||||
@@ -38,7 +38,7 @@ static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $
|
||||
# if 0
|
||||
static const double zero = 0.0; /* used as const */
|
||||
# else
|
||||
static double zero = 0.0; /* used as const */
|
||||
volatile static double zero = 0.0; /* used as const */
|
||||
# endif
|
||||
|
||||
/*
|
||||
|
||||
+3
-3
@@ -55,7 +55,7 @@ __libc_fork (void)
|
||||
but our current fork implementation is not. */
|
||||
bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads);
|
||||
|
||||
__run_fork_handlers (atfork_run_prepare);
|
||||
__run_fork_handlers (atfork_run_prepare, multiple_threads);
|
||||
|
||||
/* If we are not running multiple threads, we do not have to
|
||||
preserve lock state. If fork runs from a signal handler, only
|
||||
@@ -134,7 +134,7 @@ __libc_fork (void)
|
||||
__rtld_lock_initialize (GL(dl_load_lock));
|
||||
|
||||
/* Run the handlers registered for the child. */
|
||||
__run_fork_handlers (atfork_run_child);
|
||||
__run_fork_handlers (atfork_run_child, multiple_threads);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -149,7 +149,7 @@ __libc_fork (void)
|
||||
}
|
||||
|
||||
/* Run the handlers registered for the parent. */
|
||||
__run_fork_handlers (atfork_run_parent);
|
||||
__run_fork_handlers (atfork_run_parent, multiple_threads);
|
||||
}
|
||||
|
||||
return pid;
|
||||
|
||||
+5
-3
@@ -52,9 +52,11 @@ enum __run_fork_handler_type
|
||||
- atfork_run_child: run all the CHILD_HANDLER and unlocks the internal
|
||||
lock.
|
||||
- atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal
|
||||
lock. */
|
||||
extern void __run_fork_handlers (enum __run_fork_handler_type who)
|
||||
attribute_hidden;
|
||||
lock.
|
||||
|
||||
Perform locking only if DO_LOCKING. */
|
||||
extern void __run_fork_handlers (enum __run_fork_handler_type who,
|
||||
_Bool do_locking) attribute_hidden;
|
||||
|
||||
/* C library side function to register new fork handlers. */
|
||||
extern int __register_atfork (void (*__prepare) (void),
|
||||
|
||||
@@ -71,7 +71,11 @@
|
||||
|
||||
|
||||
#define gai_start_notify_thread __gai_start_notify_thread
|
||||
/* For some reason, with clang this define causes a linktime failure
|
||||
building libanl.so. */
|
||||
#ifndef __clang__
|
||||
#define gai_create_helper_thread __gai_create_helper_thread
|
||||
#endif
|
||||
|
||||
extern inline void
|
||||
__gai_start_notify_thread (void)
|
||||
|
||||
@@ -225,7 +225,7 @@ _dl_procinfo (unsigned int type, unsigned long int word)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* This should not happen. */
|
||||
/* Fallback to generic output mechanism. */
|
||||
return -1;
|
||||
}
|
||||
_dl_printf ("\n");
|
||||
|
||||
@@ -684,7 +684,11 @@ elf_machine_rela (struct link_map *map,
|
||||
const Elf64_Sym *sym,
|
||||
const struct r_found_version *version,
|
||||
void *const reloc_addr_arg,
|
||||
int skip_ifunc)
|
||||
int skip_ifunc
|
||||
#ifndef NESTING
|
||||
, struct link_map *boot_map
|
||||
#endif
|
||||
)
|
||||
{
|
||||
Elf64_Addr *const reloc_addr = reloc_addr_arg;
|
||||
const int r_type = ELF64_R_TYPE (reloc->r_info);
|
||||
@@ -707,7 +711,11 @@ elf_machine_rela (struct link_map *map,
|
||||
|
||||
/* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt
|
||||
and STT_GNU_IFUNC. */
|
||||
#if !defined NESTING && defined RTLD_BOOTSTRAP
|
||||
struct link_map *sym_map = boot_map;
|
||||
#else
|
||||
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
|
||||
#endif
|
||||
Elf64_Addr value = SYMBOL_ADDRESS (sym_map, sym, true) + reloc->r_addend;
|
||||
|
||||
if (sym != NULL
|
||||
|
||||
@@ -57,7 +57,8 @@ enum
|
||||
};
|
||||
|
||||
#define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \
|
||||
| HWCAP_S390_EIMM | HWCAP_S390_DFP)
|
||||
| HWCAP_S390_EIMM | HWCAP_S390_DFP \
|
||||
| HWCAP_S390_VX | HWCAP_S390_VXE)
|
||||
|
||||
/* We cannot provide a general printing function. */
|
||||
#define _dl_procinfo(type, word) -1
|
||||
|
||||
@@ -31,8 +31,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Fallback to unknown output mechanism. */
|
||||
if (type == AT_HWCAP2)
|
||||
/* Fallback to generic output mechanism. */
|
||||
if (type != AT_HWCAP)
|
||||
return -1;
|
||||
|
||||
_dl_printf ("AT_HWCAP: ");
|
||||
|
||||
@@ -67,7 +67,7 @@ _dl_procinfo (unsigned int type, unsigned long int word)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* This should not happen. */
|
||||
/* Fallback to generic output mechanism. */
|
||||
return -1;
|
||||
}
|
||||
_dl_printf ("\n");
|
||||
|
||||
@@ -30,8 +30,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
|
||||
in the kernel sources. */
|
||||
int i;
|
||||
|
||||
/* Fallback to unknown output mechanism. */
|
||||
if (type == AT_HWCAP2)
|
||||
/* Fallback to generic output mechanism. */
|
||||
if (type != AT_HWCAP)
|
||||
return -1;
|
||||
|
||||
_dl_printf ("AT_HWCAP: ");
|
||||
|
||||
@@ -49,6 +49,13 @@ __typeof (__write) __write_nocancel;
|
||||
/* Uncancelable close. */
|
||||
__typeof (__close) __close_nocancel;
|
||||
|
||||
#ifdef __clang__
|
||||
/* We need the hidden proto to be ahead of its use. */
|
||||
#if IS_IN (libc) || IS_IN (rtld)
|
||||
hidden_proto (__close_nocancel)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Non cancellable close syscall that does not also set errno in case of
|
||||
failure. */
|
||||
static inline void
|
||||
|
||||
@@ -32,8 +32,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
|
||||
in the kernel sources. */
|
||||
int i;
|
||||
|
||||
/* Fallback to unknown output mechanism. */
|
||||
if (type == AT_HWCAP2)
|
||||
/* Fallback to generic output mechanism. */
|
||||
if (type != AT_HWCAP)
|
||||
return -1;
|
||||
|
||||
_dl_printf ("AT_HWCAP: ");
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef SHARED
|
||||
/* Clang ifunc support works, but differently enough that this code breaks. */
|
||||
#if defined(SHARED) && !defined(__clang__)
|
||||
|
||||
# include <dl-vdso.h>
|
||||
# include <errno.h>
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef SHARED
|
||||
/* Clang ifunc support works, but differently enough that this code breaks. */
|
||||
#if defined(SHARED) && !defined(__clang__)
|
||||
|
||||
#include <dl-vdso.h>
|
||||
#include <errno.h>
|
||||
@@ -57,3 +58,5 @@ time (time_t *t)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
libc_hidden_weak (time)
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
#include <features.h>
|
||||
|
||||
#if 0 /* for macro expansion debugging */
|
||||
#define capture(sym, val) extern int sym[val]
|
||||
#endif
|
||||
|
||||
/* Defined to 1 if the current compiler invocation provides a
|
||||
floating-point type with the IEEE 754 binary128 format, and this
|
||||
glibc includes corresponding *f128 interfaces for it. The required
|
||||
@@ -55,6 +59,11 @@
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#if 0 /* for macro expansion debugging */
|
||||
capture(i_have_float128, __HAVE_FLOAT128);
|
||||
capture(i_have_distinct_float128, __HAVE_DISTINCT_FLOAT128);
|
||||
#endif
|
||||
|
||||
/* Defined to concatenate the literal suffix to be used with _Float128
|
||||
types, if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
@@ -83,9 +92,25 @@ typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
|
||||
|
||||
/* The type _Float128 exists only since GCC 7.0. */
|
||||
# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
/* need a clang 5.0 case here? */
|
||||
typedef __float128 _Float128;
|
||||
# endif
|
||||
|
||||
#if defined __clang__
|
||||
|
||||
#if 0 /* clang 5.0 or less */
|
||||
#define __builtin_huge_valf128() ((_Float128) __builtin_huge_val ())
|
||||
#define __builtin_inff128() ((_Float128) __builtin_inf ())
|
||||
#define __builtin_nanf128(x) ((_Float128) __builtin_nan (x))
|
||||
#define __builtin_nansf128(x) ((_Float128) __builtin_nans (x))
|
||||
|
||||
#define __builtin_copysignf128(x,y) ((_Float128) __builtin_copysign ((double)(x),(double)(y)))
|
||||
#define __builtin_fabsf128(x) ((_Float128) __builtin_fabs ((double)(x)))
|
||||
#endif
|
||||
#define __builtin_signbitf128(x) (__builtin_signbit (x))
|
||||
|
||||
#else /* GCC */
|
||||
|
||||
/* __builtin_huge_valf128 doesn't exist before GCC 7.0. */
|
||||
# if !__GNUC_PREREQ (7, 0)
|
||||
# define __builtin_huge_valf128() ((_Float128) __builtin_huge_val ())
|
||||
@@ -112,8 +137,14 @@ typedef __float128 _Float128;
|
||||
# define __builtin_signbitf128 __signbitf128
|
||||
# endif
|
||||
|
||||
#endif /* clang or GCC */
|
||||
|
||||
# endif
|
||||
|
||||
#if !__HAVE_FLOAT128 && defined __clang__
|
||||
typedef long double _Float128;
|
||||
#endif
|
||||
|
||||
#endif /* !__ASSEMBLER__. */
|
||||
|
||||
#include <bits/floatn-common.h>
|
||||
|
||||
@@ -9,6 +9,9 @@ CFLAGS-test-fenv-sse.c += -msse2 -mfpmath=sse
|
||||
CFLAGS-test-fenv-clear-sse.c += -msse2 -mfpmath=sse
|
||||
CFLAGS-test-fenv-sse-2.c += -msse2 -mfpmath=sse
|
||||
CFLAGS-test-flt-eval-method-387.c += -fexcess-precision=standard -mfpmath=387
|
||||
ifeq ($(with-clang),yes)
|
||||
CFLAGS-test-flt-eval-method-387.c += -mno-sse
|
||||
endif
|
||||
CFLAGS-test-flt-eval-method-sse.c += -fexcess-precision=standard -msse2 \
|
||||
-mfpmath=sse
|
||||
endif
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifndef X86_MATH_BARRIERS_H
|
||||
#define X86_MATH_BARRIERS_H 1
|
||||
|
||||
#ifdef __SSE2_MATH__
|
||||
#if defined(__SSE2_MATH__) && !defined(__clang__)
|
||||
# define math_opt_barrier(x) \
|
||||
({ __typeof(x) __x; \
|
||||
if (sizeof (x) <= sizeof (double) \
|
||||
|
||||
@@ -127,7 +127,10 @@ $(objpfx)tst-sse: $(objpfx)tst-ssemod.so
|
||||
$(objpfx)tst-avx: $(objpfx)tst-avx-aux.o $(objpfx)tst-avxmod.so
|
||||
$(objpfx)tst-avx512: $(objpfx)tst-avx512-aux.o $(objpfx)tst-avx512mod.so
|
||||
|
||||
AVX-CFLAGS=-mavx -mno-vzeroupper
|
||||
AVX-CFLAGS = -mavx
|
||||
ifneq ($(with-clang),yes)
|
||||
AVX-CFLAGS += -mno-vzeroupper
|
||||
endif
|
||||
CFLAGS-tst-audit4-aux.c += $(AVX-CFLAGS)
|
||||
CFLAGS-tst-auditmod4a.c += $(AVX-CFLAGS)
|
||||
CFLAGS-tst-auditmod4b.c += $(AVX-CFLAGS)
|
||||
|
||||
@@ -267,7 +267,11 @@ auto inline void
|
||||
__attribute__ ((always_inline))
|
||||
elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
||||
const ElfW(Sym) *sym, const struct r_found_version *version,
|
||||
void *const reloc_addr_arg, int skip_ifunc)
|
||||
void *const reloc_addr_arg, int skip_ifunc
|
||||
#ifndef NESTING
|
||||
, struct link_map *boot_map
|
||||
#endif
|
||||
)
|
||||
{
|
||||
ElfW(Addr) *const reloc_addr = reloc_addr_arg;
|
||||
const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
|
||||
@@ -305,7 +309,11 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
||||
# ifndef RTLD_BOOTSTRAP
|
||||
const ElfW(Sym) *const refsym = sym;
|
||||
# endif
|
||||
#if !defined NESTING && defined RTLD_BOOTSTRAP
|
||||
struct link_map *sym_map = boot_map;
|
||||
#else
|
||||
struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
|
||||
#endif
|
||||
ElfW(Addr) value = SYMBOL_ADDRESS (sym_map, sym, true);
|
||||
|
||||
if (sym != NULL
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
#ifdef __ILP32__
|
||||
# define PRESERVE_BND_REGS_PREFIX
|
||||
#else
|
||||
# ifdef HAVE_MPX_SUPPORT
|
||||
/* clang integrated assembler does not like "bnd" by itself on a line. */
|
||||
# if defined(HAVE_MPX_SUPPORT) && !defined(__clang__)
|
||||
# define PRESERVE_BND_REGS_PREFIX bnd
|
||||
# else
|
||||
# define PRESERVE_BND_REGS_PREFIX .byte 0xf2
|
||||
|
||||
@@ -17,7 +17,13 @@ RCSID("$NetBSD: s_log1p.S,v 1.7 1995/05/09 00:10:58 jtc Exp $")
|
||||
-1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2
|
||||
0.29 is a safe value.
|
||||
*/
|
||||
#if defined(__clang__)
|
||||
/* Necessary in the absence of a .tfloat directive in the assembler. */
|
||||
limit:
|
||||
.byte 0xe1, 0x7a, 0x14, 0xae, 0x47, 0xe1, 0x7a, 0x94, 0xfd, 0x3f
|
||||
#else
|
||||
limit: .tfloat 0.29
|
||||
#endif
|
||||
/* Please note: we use a double value here. Since 1.0 has
|
||||
an exact representation this does not effect the accuracy
|
||||
but it helps to optimize the code. */
|
||||
|
||||
@@ -29,9 +29,12 @@
|
||||
__svml_dexp_data:
|
||||
|
||||
/* Lookup table of 2^(j/2^K): */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dexp_data != __dbT
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x3ff0000000000000
|
||||
.quad 0x3ff002c605e2e8cf
|
||||
.quad 0x3ff0058c86da1c0a
|
||||
|
||||
@@ -32,18 +32,24 @@
|
||||
#define __iDomainRange 8768
|
||||
|
||||
.macro double_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dexp_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 8
|
||||
.quad \value
|
||||
.endr
|
||||
.endm
|
||||
|
||||
.macro float_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dexp_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 16
|
||||
.long \value
|
||||
.endr
|
||||
|
||||
@@ -30,9 +30,12 @@ __svml_dlog_data:
|
||||
|
||||
/* Lookup table in high+low parts and 9-bit index for
|
||||
-log(mRcp), where mRcp is mantissa of 1/x 9-bit accurate reciprocal: */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dlog_data != _Log_HA_table
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0xc086232bdd7a8300
|
||||
.quad 0xbe1ce91eef3fb100
|
||||
.quad 0xc086232fdc7ad828
|
||||
@@ -1066,9 +1069,12 @@ __svml_dlog_data:
|
||||
/* Lookup table with 9-bit index for
|
||||
-log(mRcp), where mRcp is mantissa of 1/x 9-bit accurate reciprocal:
|
||||
*/
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dlog_data != _Log_LA_table
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x8000000000000000
|
||||
.quad 0xbf5ff802a9ab10e6
|
||||
.quad 0xbf6ff00aa2b10bc0
|
||||
@@ -1630,9 +1636,12 @@ double_vector _L2 0x3fe62e42fefa39ef
|
||||
|
||||
/* General purpose constants:
|
||||
DP infinities, +/- */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dlog_data != _dInfs
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x7ff0000000000000
|
||||
.quad 0xfff0000000000000
|
||||
.rept 48
|
||||
@@ -1640,9 +1649,12 @@ double_vector _L2 0x3fe62e42fefa39ef
|
||||
.endr
|
||||
|
||||
/* DP 1.0, +/- */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dlog_data != _dOnes
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x3ff0000000000000
|
||||
.quad 0xbff0000000000000
|
||||
.rept 48
|
||||
@@ -1650,9 +1662,12 @@ double_vector _L2 0x3fe62e42fefa39ef
|
||||
.endr
|
||||
|
||||
/* DP 0.0, +/- */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dlog_data != _dZeros
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x0000000000000000
|
||||
.quad 0x8000000000000000
|
||||
.rept 48
|
||||
|
||||
@@ -43,9 +43,12 @@
|
||||
#define _dZeros 13568
|
||||
|
||||
.macro double_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dlog_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 8
|
||||
.quad \value
|
||||
.endr
|
||||
|
||||
@@ -30,9 +30,12 @@
|
||||
__svml_dpow_data:
|
||||
|
||||
/* Lookup log(2) table (for HSW): */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dpow_data != _hsw_log2_table
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0xc08ff00000000000
|
||||
.quad 0x0000000000000000
|
||||
.quad 0xc08ff005c3e0ffc2
|
||||
@@ -1064,9 +1067,12 @@ __svml_dpow_data:
|
||||
.endr
|
||||
|
||||
/* Lookup exp(2) table (for HSW): */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dpow_data != _hsw_dTe
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x3ff0000000000000
|
||||
.quad 0x3ff00b1afa5abcbf
|
||||
.quad 0x3ff0163da9fb3335
|
||||
@@ -1395,9 +1401,12 @@ double_vector _hsw_dce2 0x3fcebfbdff82c54d
|
||||
double_vector _hsw_dce1 0x3fe62e42fefa39b9
|
||||
|
||||
/* Reciprocal lookup table for log part (non HSW): */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dpow_data != _rcp_t1
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x3ff7154740000000
|
||||
.quad 0x3ff70f8340000000
|
||||
.quad 0x3ff709c240000000
|
||||
@@ -2429,9 +2438,12 @@ double_vector _hsw_dce1 0x3fe62e42fefa39b9
|
||||
.endr
|
||||
|
||||
/* Log(2) lookup table for log part (non HSW): */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dpow_data != _log2_t1
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 2
|
||||
.quad 0x0000000000000000
|
||||
.endr
|
||||
@@ -4489,9 +4501,12 @@ double_vector _hsw_dce1 0x3fe62e42fefa39b9
|
||||
.endr
|
||||
|
||||
/* Exp(2) lookup table for exp part (non HSW) */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dpow_data != _exp2_tbl
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x3ff0000000000000
|
||||
.quad 0x0000000000000000
|
||||
.quad 0x3ff0163da9fb3335
|
||||
|
||||
@@ -84,18 +84,24 @@
|
||||
#define _jIndexMask 40704
|
||||
|
||||
.macro double_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dpow_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 8
|
||||
.quad \value
|
||||
.endr
|
||||
.endm
|
||||
|
||||
.macro float_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_dpow_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 16
|
||||
.long \value
|
||||
.endr
|
||||
|
||||
@@ -61,9 +61,12 @@
|
||||
#define __dSignMask __lNZero
|
||||
|
||||
.macro double_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_d_trig_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 8
|
||||
.quad \value
|
||||
.endr
|
||||
|
||||
@@ -34,9 +34,12 @@
|
||||
#define __iDomainRange 768
|
||||
|
||||
.macro float_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_sexp_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 16
|
||||
.long \value
|
||||
.endr
|
||||
|
||||
@@ -70,9 +70,12 @@ float_vector _sOne 0x3f800000
|
||||
float_vector _sLn2 0x3f317218
|
||||
|
||||
/* SP infinity, +/- */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_slog_data != _sInfs
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.long 0x7f800000
|
||||
.long 0xff800000
|
||||
.rept 56
|
||||
@@ -80,9 +83,12 @@ float_vector _sLn2 0x3f317218
|
||||
.endr
|
||||
|
||||
/* SP one, +/- */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_slog_data != _sOnes
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.long 0x3f800000
|
||||
.long 0xbf800000
|
||||
.rept 56
|
||||
@@ -90,9 +96,12 @@ float_vector _sLn2 0x3f317218
|
||||
.endr
|
||||
|
||||
/* SP zero +/- */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_slog_data != _sZeros
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.long 0x00000000
|
||||
.long 0x80000000
|
||||
.rept 56
|
||||
|
||||
@@ -37,9 +37,12 @@
|
||||
#define _sZeros 960
|
||||
|
||||
.macro float_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_slog_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 16
|
||||
.long \value
|
||||
.endr
|
||||
|
||||
@@ -46,9 +46,12 @@ float_vector _ABSMASK 0x7fffffff
|
||||
float_vector _DOMAINRANGE 0x42ae9a00
|
||||
|
||||
/* Log(2) lookup High+Low table for logarithmic part */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_spow_data != _Log_HA_table
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0xc086232bdd7a8300
|
||||
.quad 0xbe1ce91eef3fb100
|
||||
.quad 0xc086232fdc7ad828
|
||||
@@ -1080,9 +1083,12 @@ float_vector _DOMAINRANGE 0x42ae9a00
|
||||
.endr
|
||||
|
||||
/* Log(2) lookup table for logarithmic part */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_spow_data != _Log_LA_table
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x8000000000000000
|
||||
.quad 0xbf5ff802a9ab10e6
|
||||
.quad 0xbf6ff00aa2b10bc0
|
||||
@@ -1650,9 +1656,12 @@ double_vector _Bias1 0x408ff00000000000
|
||||
double_vector _L2 0x3fe62e42fefa39ef
|
||||
|
||||
/* dInfs = DP infinity, +/- == */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_spow_data != _dInfs
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x7ff0000000000000
|
||||
.quad 0xfff0000000000000
|
||||
.rept 48
|
||||
@@ -1660,9 +1669,12 @@ double_vector _L2 0x3fe62e42fefa39ef
|
||||
.endr
|
||||
|
||||
/* dOnes = DP one, +/- == */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_spow_data != _dOnes
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x3ff0000000000000
|
||||
.quad 0xbff0000000000000
|
||||
.rept 48
|
||||
@@ -1670,17 +1682,23 @@ double_vector _L2 0x3fe62e42fefa39ef
|
||||
.endr
|
||||
|
||||
/* dZeros = DP zero +/- == */
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_spow_data != _dZeros
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x0000000000000000
|
||||
.quad 0x8000000000000000
|
||||
.rept 48
|
||||
.byte 0
|
||||
.endr
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_spow_data != __dbT
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.quad 0x3feffffffc27dd9e
|
||||
.quad 0x3ff00162f1a4047d
|
||||
.quad 0x3ff002c603f68252
|
||||
|
||||
@@ -56,18 +56,24 @@
|
||||
#define __iDomainRange 30784
|
||||
|
||||
.macro double_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_spow_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 8
|
||||
.quad \value
|
||||
.endr
|
||||
.endm
|
||||
|
||||
.macro float_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_spow_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 16
|
||||
.long \value
|
||||
.endr
|
||||
|
||||
@@ -20,9 +20,12 @@
|
||||
#define S_TRIG_DATA_H
|
||||
|
||||
.macro float_vector offset value
|
||||
/* clang integrated assembler doesn't think subtract yields an absolute, skip. */
|
||||
#if !defined(__clang__)
|
||||
.if .-__svml_s_trig_data != \offset
|
||||
.err
|
||||
.endif
|
||||
#endif
|
||||
.rept 16
|
||||
.long \value
|
||||
.endr
|
||||
|
||||
+12
-8
@@ -21,14 +21,18 @@
|
||||
|
||||
.text
|
||||
ENTRY (memcmp)
|
||||
test %rdx, %rdx
|
||||
#ifdef __ILP32__
|
||||
/* Clear the upper 32 bits. */
|
||||
movl %edx, %edx
|
||||
#endif
|
||||
test %RDX_LP, %RDX_LP
|
||||
jz L(finz)
|
||||
cmpq $1, %rdx
|
||||
jle L(finr1b)
|
||||
jbe L(finr1b)
|
||||
subq %rdi, %rsi
|
||||
movq %rdx, %r10
|
||||
cmpq $32, %r10
|
||||
jge L(gt32)
|
||||
jae L(gt32)
|
||||
/* Handle small chunks and last block of less than 32 bytes. */
|
||||
L(small):
|
||||
testq $1, %r10
|
||||
@@ -156,7 +160,7 @@ L(A32):
|
||||
movq %r11, %r10
|
||||
andq $-32, %r10
|
||||
cmpq %r10, %rdi
|
||||
jge L(mt16)
|
||||
jae L(mt16)
|
||||
/* Pre-unroll to be ready for unrolled 64B loop. */
|
||||
testq $32, %rdi
|
||||
jz L(A64)
|
||||
@@ -178,7 +182,7 @@ L(A64):
|
||||
movq %r11, %r10
|
||||
andq $-64, %r10
|
||||
cmpq %r10, %rdi
|
||||
jge L(mt32)
|
||||
jae L(mt32)
|
||||
|
||||
L(A64main):
|
||||
movdqu (%rdi,%rsi), %xmm0
|
||||
@@ -216,7 +220,7 @@ L(mt32):
|
||||
movq %r11, %r10
|
||||
andq $-32, %r10
|
||||
cmpq %r10, %rdi
|
||||
jge L(mt16)
|
||||
jae L(mt16)
|
||||
|
||||
L(A32main):
|
||||
movdqu (%rdi,%rsi), %xmm0
|
||||
@@ -254,7 +258,7 @@ L(ATR):
|
||||
movq %r11, %r10
|
||||
andq $-32, %r10
|
||||
cmpq %r10, %rdi
|
||||
jge L(mt16)
|
||||
jae L(mt16)
|
||||
testq $16, %rdi
|
||||
jz L(ATR32)
|
||||
|
||||
@@ -325,7 +329,7 @@ L(ATR64main):
|
||||
movq %r11, %r10
|
||||
andq $-32, %r10
|
||||
cmpq %r10, %rdi
|
||||
jge L(mt16)
|
||||
jae L(mt16)
|
||||
|
||||
L(ATR32res):
|
||||
movdqa (%rdi,%rsi), %xmm0
|
||||
|
||||
@@ -2232,8 +2232,9 @@ LABEL(strcmp_exitz):
|
||||
|
||||
.p2align 4
|
||||
LABEL(Byte0):
|
||||
movzx (%rsi), %ecx
|
||||
movzx (%rdi), %eax
|
||||
# Clang assembler objects to movzx here.
|
||||
movzbl (%rsi), %ecx
|
||||
movzbl (%rdi), %eax
|
||||
|
||||
#if defined USE_AS_STRCASECMP_L || defined USE_AS_STRNCASECMP_L
|
||||
leaq _nl_C_LC_CTYPE_tolower+128*4(%rip), %rdx
|
||||
|
||||
@@ -8,7 +8,8 @@ endif
|
||||
ifeq ($(subdir),string)
|
||||
tests += tst-size_t-memchr tst-size_t-memcmp tst-size_t-memcpy \
|
||||
tst-size_t-memrchr tst-size_t-memset tst-size_t-strncasecmp \
|
||||
tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen
|
||||
tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen \
|
||||
tst-size_t-memcmp-2
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),wcsmbs)
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/* Test memcmp with size_t in the lower 32 bits of 64-bit register.
|
||||
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define TEST_MAIN
|
||||
#ifdef WIDE
|
||||
# define TEST_NAME "wmemcmp"
|
||||
#else
|
||||
# define TEST_NAME "memcmp"
|
||||
#endif
|
||||
|
||||
#include "test-size_t.h"
|
||||
|
||||
#ifdef WIDE
|
||||
# include <inttypes.h>
|
||||
# include <wchar.h>
|
||||
|
||||
# define MEMCMP wmemcmp
|
||||
# define CHAR wchar_t
|
||||
#else
|
||||
# define MEMCMP memcmp
|
||||
# define CHAR char
|
||||
#endif
|
||||
|
||||
IMPL (MEMCMP, 1)
|
||||
|
||||
typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
|
||||
|
||||
static int
|
||||
__attribute__ ((noinline, noclone))
|
||||
do_memcmp (parameter_t a, parameter_t b)
|
||||
{
|
||||
return CALL (&b, a.p, b.p, a.len);
|
||||
}
|
||||
|
||||
static int
|
||||
test_main (void)
|
||||
{
|
||||
test_init ();
|
||||
|
||||
parameter_t dest = { { page_size / sizeof (CHAR) }, buf1 };
|
||||
parameter_t src = { { 0 }, buf2 };
|
||||
|
||||
memcpy (buf1, buf2, page_size);
|
||||
|
||||
CHAR *p = (CHAR *) buf1;
|
||||
p[page_size / sizeof (CHAR) - 1] = (CHAR) 1;
|
||||
|
||||
int ret = 0;
|
||||
FOR_EACH_IMPL (impl, 0)
|
||||
{
|
||||
src.fn = impl->fn;
|
||||
int res = do_memcmp (dest, src);
|
||||
if (res >= 0)
|
||||
{
|
||||
error (0, 0, "Wrong result in function %s: %i >= 0",
|
||||
impl->name, res);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
Reference in New Issue
Block a user