mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 05:59:27 +08:00
Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59c0f6ff86 | ||
|
|
94dc51ad84 | ||
|
|
50d2d4bb0e | ||
|
|
3a6219d3ec | ||
|
|
f5eb5f9c91 | ||
|
|
3b7f56026c | ||
|
|
daf161ce63 | ||
|
|
87efefb037 | ||
|
|
65c7020d26 | ||
|
|
9f95ec0adb | ||
|
|
1885fe873e | ||
|
|
16d0a0ce76 | ||
|
|
014eaa2207 | ||
|
|
965630aefa | ||
|
|
51e762570e | ||
|
|
163437ec37 | ||
|
|
f676ce661c | ||
|
|
907cc11c57 | ||
|
|
dbcaca73cb | ||
|
|
26f36461f6 | ||
|
|
e04da210f7 | ||
|
|
e871e19b5f | ||
|
|
f2cdbadd8a | ||
|
|
978908245b | ||
|
|
8a4e5cc657 | ||
|
|
fe7b1136e5 | ||
|
|
d679497db2 | ||
|
|
01b07c70ad | ||
|
|
75adf430d2 | ||
|
|
c66e8b9e58 | ||
|
|
004c993bdd |
@@ -1,3 +1,225 @@
|
||||
2016-05-09 Yvan Roux <yvan.roux@linaro.org>
|
||||
|
||||
* stdlib/setenv.c (unsetenv): Fix ambiguous 'else'.
|
||||
* nis/nis_call.c (nis_server_cache_add): Likewise.
|
||||
|
||||
2016-04-28 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
[BZ #18508]
|
||||
* stdlib/Makefile ($(objpfx)tst-makecontext3):
|
||||
Depend on $(libdl).
|
||||
* stdlib/tst-makecontext.c (cf): Test if _Unwind_Backtrace
|
||||
is not called infinitely times.
|
||||
(backtrace_helper): New function.
|
||||
(trace_arg): New struct.
|
||||
(st1): Enlarge stack size.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S:
|
||||
(__makecontext_ret): Omit cfi_startproc and cfi_endproc.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S:
|
||||
Likewise.
|
||||
|
||||
2016-04-28 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
[BZ #18080]
|
||||
* sysdeps/unix/sysv/linux/s390/s390-32/setcontext.S
|
||||
(__setcontext): Use SIG_SETMASK instead of SIG_BLOCK.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/setcontext.S
|
||||
(__setcontext): Likewise.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-32/swapcontext.S
|
||||
(__swapcontext): Use SIG_SETMASK instead of SIG_BLOCK.
|
||||
Call rt_sigprocmask syscall one time to set new signal mask
|
||||
and retrieve the current signal mask instead of two calls.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/swapcontext.S
|
||||
(__swapcontext): Likewise.
|
||||
* stdlib/Makefile (tests): Add new testcase tst-setcontext2.
|
||||
* stdlib/tst-setcontext2.c: New file.
|
||||
|
||||
2016-04-09 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* sysdeps/x86_64/configure.ac: Change == to = when calling test.
|
||||
* sysdeps/x86_64/configure: Likewise.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/s390/bits/link.h: (La_s390_vr) New typedef.
|
||||
(La_s390_32_regs): Append vector register lr_v24-lr_v31.
|
||||
(La_s390_64_regs): Likewise.
|
||||
(La_s390_32_retval): Append vector register lrv_v24.
|
||||
(La_s390_64_retval): Likeweise.
|
||||
* sysdeps/s390/s390-32/dl-trampoline.h (_dl_runtime_profile):
|
||||
Handle extended structs La_s390_32_regs and La_s390_32_retval.
|
||||
* sysdeps/s390/s390-64/dl-trampoline.h (_dl_runtime_profile):
|
||||
Handle extended structs La_s390_64_regs and La_s390_64_retval.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/s390/s390-32/dl-trampoline.S: Include dl-trampoline.h twice
|
||||
to create a non-vector/vector version for _dl_runtime_resolve and
|
||||
_dl_runtime_profile. Move implementation to ...
|
||||
* sysdeps/s390/s390-32/dl-trampoline.h: ... here.
|
||||
(_dl_runtime_resolve) Save and restore fpr/vrs.
|
||||
(_dl_runtime_profile) Save and restore vrs and fix some issues
|
||||
if _dl_call_pltexit is called.
|
||||
* sysdeps/s390/s390-32/dl-machine.h (elf_machine_runtime_setup):
|
||||
Choose the correct resolver function if running on a machine with vx.
|
||||
* sysdeps/s390/s390-64/dl-trampoline.S: Include dl-trampoline.h twice
|
||||
to create a non-vector/vector version for _dl_runtime_resolve and
|
||||
_dl_runtime_profile. Move implementation to ...
|
||||
* sysdeps/s390/s390-64/dl-trampoline.h: ... here.
|
||||
(_dl_runtime_resolve) Save and restore fpr/vrs.
|
||||
(_dl_runtime_profile) Save and restore vrs and fix some issues
|
||||
* sysdeps/s390/s390-64/dl-machine.h: (elf_machine_runtime_setup):
|
||||
Choose the correct resolver function if running on a machine with vx.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* config.h.in (HAVE_S390_VX_ASM_SUPPORT): New macro undefine.
|
||||
* sysdeps/s390/configure.ac: Add test for S390 vector instruction
|
||||
assembler support.
|
||||
* sysdeps/s390/configure: Regenerated.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/s390/dl-procinfo.c (_dl_s390_cap_flags): Add z13.
|
||||
* sysdeps/s390/dl-procinfo.h (_DL_PLATFORMS_COUNT): Increased.
|
||||
|
||||
2016-04-04 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
* sysdeps/s390/dl-procinfo.c (_dl_s390_platforms): Add vector flag.
|
||||
* sysdeps/s390/dl-procinfo.h: Add vector capability.
|
||||
* sysdeps/unix/sysv/linux/s390/bits/hwcap.h (HWCAP_S390_VX): Define.
|
||||
|
||||
2016-03-07 Hongjiu Zhang <noctuorare@gmail.com>
|
||||
|
||||
* elf/sln.c (makesymlink): Change struct stat to stat64, and lstat
|
||||
to lstat64.
|
||||
|
||||
2016-03-02 Stefan Liebler <stli@linux.vnet.ibm.com>
|
||||
|
||||
[BZ #19682]
|
||||
* sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list:
|
||||
Remove socketcall syscalls.
|
||||
|
||||
2016-02-15 Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
[BZ #18665]
|
||||
* resolv/nss_dns/dns-host.c (gaih_getanswer_slice): Always set
|
||||
*herrno_p.
|
||||
(gaih_getanswer): Document functional behviour. Return tryagain
|
||||
if any result is tryagain.
|
||||
* resolv/res_query.c (__libc_res_nsearch): Set buffer size to zero
|
||||
when freed.
|
||||
* resolv/res_send.c: Add copyright text.
|
||||
(__libc_res_nsend): Document that MAXPACKET is expected.
|
||||
(send_vc): Document. Remove buffer reuse.
|
||||
(send_dg): Document. Remove buffer reuse. Set *thisanssizp to set the
|
||||
size of the buffer. Add Dprint for truncated UDP buffer.
|
||||
|
||||
2016-02-12 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* misc/bug18240.c (do_test): Set RLIMIT_AS.
|
||||
|
||||
2016-01-27 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
[BZ #18240]
|
||||
* misc/hsearch_r.c (isprime, __hcreate_r): Protect against
|
||||
unsigned int wraparound.
|
||||
|
||||
2016-01-27 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #18240]
|
||||
* misc/bug18240.c: New test.
|
||||
* misc/Makefile (tests): Add it.
|
||||
|
||||
2015-08-25 Ondřej Bílka <neleai@seznam.cz>
|
||||
|
||||
[BZ #18240]
|
||||
* misc/hsearch_r.c (__hcreate_r): Handle overflow.
|
||||
|
||||
2015-09-26 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
[BZ #18985]
|
||||
* time/strftime_l.c (a_wkday, f_wkday, a_month, f_month): Range check.
|
||||
(__strftime_internal): Likewise.
|
||||
* time/tst-strftime.c (do_bz18985): New test.
|
||||
(do_test): Call it.
|
||||
|
||||
2015-08-08 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
[BZ #17905]
|
||||
* catgets/Makefile (tst-catgets-mem): New test.
|
||||
* catgets/catgets.c (catopen): Don't use unbounded alloca.
|
||||
* catgets/open_catalog.c (__open_catalog): Likewise.
|
||||
* catgets/tst-catgets.c (do_bz17905): Test unbounded alloca.
|
||||
|
||||
2015-05-01 Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
|
||||
* config.h.in (HAVE_AARCH64_BE): Add.
|
||||
|
||||
2015-07-08 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* nscd/selinux.c: Delete selinux/flask.h include.
|
||||
|
||||
2015-03-02 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
* elf/Makefile ($(elf-objpfx)runtime-linker.st): Fix typo in
|
||||
variable name.
|
||||
|
||||
2015-04-29 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #18007]
|
||||
* nss/nss_files/files-XXX.c (CONCAT): Always enable stayopen.
|
||||
(CVE-2014-8121)
|
||||
* nss/tst-nss-getpwent.c: New file.
|
||||
* nss/Makefile (tests): Add new test.
|
||||
|
||||
2015-08-28 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
[BZ #18887]
|
||||
* misc/Makefile (tests): Add tst-mntent-blank-corrupt and
|
||||
tst-mntent-blank-passno.
|
||||
* misc/mntent_r.c (__getmntent_r): Do not read past buffer[0].
|
||||
* misc/tst-mntent-blank-corrupt.c: New test.
|
||||
* misc/tst-mntent-blank-passno.c: New test ripped from ...
|
||||
* misc/tst-mntent.c (do_test): ... here.
|
||||
|
||||
2015-07-27 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* sysdeps/ia64/bits/atomic.h (atomic_exchange_and_add): Define
|
||||
directly in terms of __sync_fetch_and_add and delete (int) cast.
|
||||
|
||||
2015-02-22 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
|
||||
[BZ #17269]
|
||||
* libio/wstrops.c (_IO_wstr_overflow): Guard against integer overflow
|
||||
(enlarge_userbuf): Likewise.
|
||||
|
||||
2015-02-26 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
[BZ #18032]
|
||||
* posix/fnmatch_loop.c (FCT): Remove extra increment when skipping
|
||||
over collating symbol inside a bracket expression. Minor cleanup.
|
||||
* posix/tst-fnmatch3.c (do_test): Add test case.
|
||||
|
||||
2015-07-21 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
[BZ #18694]
|
||||
* sysdeps/unix/sysv/linux/sparc/bits/sigaction.h: Include
|
||||
bits/wordsize.h.
|
||||
(sigaction): Declare __glibc_reserved0 only when __WORDSIZE is 64.
|
||||
|
||||
2015-04-21 Arjun Shankar <arjun.is@lostca.se>
|
||||
|
||||
[BZ #18287]
|
||||
* resolv/nss_dns/dns-host.c (getanswer_r): Adjust buffer length
|
||||
based on padding. (CVE-2015-1781)
|
||||
|
||||
2015-02-10 Evangelos Foutras <evangelos@foutrelis.com>
|
||||
|
||||
[BZ #17949]
|
||||
* sysdeps/i386/i686/multiarch/mempcpy_chk.S: Fix position of
|
||||
jump label.
|
||||
|
||||
2015-02-06 Carlos O'Donell <carlos@systemhalted.org>
|
||||
|
||||
* version.h (RELEASE): Set to "stable".
|
||||
@@ -7,6 +229,7 @@
|
||||
* sysdeps/unix/sysv/linux/hppa/pthread.h: Sync with pthread.h.
|
||||
|
||||
2015-02-05 Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
[BZ #16618]
|
||||
* stdio-common/tst-sscanf.c (main): Test for buffer overflow.
|
||||
|
||||
@@ -5,6 +5,43 @@ See the end for copying conditions.
|
||||
Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
|
||||
using `glibc' in the "product" field.
|
||||
|
||||
Version 2.21.1
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
|
||||
17269, 17905, 17949, 18007, 18032, 18080, 18240, 18287, 18508, 18694,
|
||||
18887, 18985, 19682.
|
||||
|
||||
* A stack-based buffer overflow was found in libresolv when invoked from
|
||||
libnss_dns, allowing specially crafted DNS responses to seize control
|
||||
of execution flow in the DNS client. The buffer overflow occurs in
|
||||
the functions send_dg (send datagram) and send_vc (send TCP) for the
|
||||
NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC
|
||||
family. The use of AF_UNSPEC triggers the low-level resolver code to
|
||||
send out two parallel queries for A and AAAA. A mismanagement of the
|
||||
buffers used for those queries could result in the response of a query
|
||||
writing beyond the alloca allocated buffer created by
|
||||
_nss_dns_gethostbyname4_r. Buffer management is simplified to remove
|
||||
the overflow. Thanks to the Google Security Team and Red Hat for
|
||||
reporting the security impact of this issue, and Robert Holiday of
|
||||
Ciena for reporting the related bug 18665. (CVE-2015-7547)
|
||||
|
||||
* A buffer overflow in gethostbyname_r and related functions performing DNS
|
||||
requests has been fixed. If the NSS functions were called with a
|
||||
misaligned buffer, the buffer length change due to pointer alignment was
|
||||
not taken into account. This could result in application crashes or,
|
||||
potentially arbitrary code execution, using crafted, but syntactically
|
||||
valid DNS responses. (CVE-2015-1781)
|
||||
|
||||
* The 32-bit sparc sigaction ABI was inadvertently broken in the 2.20 and 2.21
|
||||
releases. It has been fixed to match 2.19 and older, but binaries built
|
||||
against 2.20 and 2.21 might need to be recompiled. See BZ#18694.
|
||||
|
||||
* CVE-2014-8121 The NSS files backend would reset the file pointer used by
|
||||
the get*ent functions if any of the query functions for the same database
|
||||
are used during the iteration, causing a denial-of-service condition in
|
||||
some applications.
|
||||
|
||||
Version 2.21
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
@@ -21,10 +58,11 @@ Version 2.21
|
||||
17801, 17803, 17806, 17834, 17844, 17848, 17868, 17869, 17870, 17885,
|
||||
17892.
|
||||
|
||||
* CVE-2015-1472 Under certain conditions wscanf can allocate too little
|
||||
memory for the to-be-scanned arguments and overflow the allocated
|
||||
buffer. The implementation now correctly computes the required buffer
|
||||
size when using malloc.
|
||||
* CVE-2015-1472 CVE-2015-1473 Under certain conditions wscanf can allocate
|
||||
too little memory for the to-be-scanned arguments and overflow the
|
||||
allocated buffer. The implementation now correctly computes the required
|
||||
buffer size when using malloc, and switches to malloc from alloca as
|
||||
intended.
|
||||
|
||||
* A new semaphore algorithm has been implemented in generic C code for all
|
||||
machines. Previous custom assembly implementations of semaphore were
|
||||
|
||||
+8
-1
@@ -34,6 +34,7 @@ test-srcs = test-gencat
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)de/libc.cat $(objpfx)test1.cat $(objpfx)test2.cat \
|
||||
$(objpfx)sample.SJIS.cat $(objpfx)test-gencat.out
|
||||
tests-special += $(objpfx)tst-catgets-mem.out
|
||||
endif
|
||||
|
||||
gencat-modules = xmalloc
|
||||
@@ -50,9 +51,11 @@ catgets-CPPFLAGS := -DNLSPATH='"$(msgcatdir)/%L/%N:$(msgcatdir)/%L/LC_MESSAGES/%
|
||||
|
||||
generated += de.msg test1.cat test1.h test2.cat test2.h sample.SJIS.cat \
|
||||
test-gencat.h
|
||||
generated += tst-catgets.mtrace tst-catgets-mem.out
|
||||
|
||||
generated-dirs += de
|
||||
|
||||
tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de
|
||||
tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de MALLOC_TRACE=$(objpfx)tst-catgets.mtrace
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
# This test just checks whether the program produces any error or not.
|
||||
@@ -86,4 +89,8 @@ $(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat \
|
||||
$(objpfx)sample.SJIS.cat: sample.SJIS $(objpfx)gencat
|
||||
$(built-program-cmd) -H $(objpfx)test-gencat.h < $(word 1,$^) > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-catgets-mem.out: $(objpfx)tst-catgets.out
|
||||
$(common-objpfx)malloc/mtrace $(objpfx)tst-catgets.mtrace > $@; \
|
||||
$(evaluate-test)
|
||||
endif
|
||||
|
||||
+12
-7
@@ -16,7 +16,6 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <nl_types.h>
|
||||
@@ -35,6 +34,7 @@ catopen (const char *cat_name, int flag)
|
||||
__nl_catd result;
|
||||
const char *env_var = NULL;
|
||||
const char *nlspath = NULL;
|
||||
char *tmp = NULL;
|
||||
|
||||
if (strchr (cat_name, '/') == NULL)
|
||||
{
|
||||
@@ -54,7 +54,10 @@ catopen (const char *cat_name, int flag)
|
||||
{
|
||||
/* Append the system dependent directory. */
|
||||
size_t len = strlen (nlspath) + 1 + sizeof NLSPATH;
|
||||
char *tmp = alloca (len);
|
||||
tmp = malloc (len);
|
||||
|
||||
if (__glibc_unlikely (tmp == NULL))
|
||||
return (nl_catd) -1;
|
||||
|
||||
__stpcpy (__stpcpy (__stpcpy (tmp, nlspath), ":"), NLSPATH);
|
||||
nlspath = tmp;
|
||||
@@ -65,16 +68,18 @@ catopen (const char *cat_name, int flag)
|
||||
|
||||
result = (__nl_catd) malloc (sizeof (*result));
|
||||
if (result == NULL)
|
||||
/* We cannot get enough memory. */
|
||||
return (nl_catd) -1;
|
||||
|
||||
if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
|
||||
{
|
||||
/* We cannot get enough memory. */
|
||||
result = (nl_catd) -1;
|
||||
}
|
||||
else if (__open_catalog (cat_name, nlspath, env_var, result) != 0)
|
||||
{
|
||||
/* Couldn't open the file. */
|
||||
free ((void *) result);
|
||||
return (nl_catd) -1;
|
||||
result = (nl_catd) -1;
|
||||
}
|
||||
|
||||
free (tmp);
|
||||
return (nl_catd) result;
|
||||
}
|
||||
|
||||
|
||||
+14
-9
@@ -47,6 +47,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
|
||||
size_t tab_size;
|
||||
const char *lastp;
|
||||
int result = -1;
|
||||
char *buf = NULL;
|
||||
|
||||
if (strchr (cat_name, '/') != NULL || nlspath == NULL)
|
||||
fd = open_not_cancel_2 (cat_name, O_RDONLY);
|
||||
@@ -57,23 +58,23 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
|
||||
if (__glibc_unlikely (bufact + (n) >= bufmax)) \
|
||||
{ \
|
||||
char *old_buf = buf; \
|
||||
bufmax += 256 + (n); \
|
||||
buf = (char *) alloca (bufmax); \
|
||||
memcpy (buf, old_buf, bufact); \
|
||||
bufmax += (bufmax < 256 + (n)) ? 256 + (n) : bufmax; \
|
||||
buf = realloc (buf, bufmax); \
|
||||
if (__glibc_unlikely (buf == NULL)) \
|
||||
{ \
|
||||
free (old_buf); \
|
||||
return -1; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* The RUN_NLSPATH variable contains a colon separated list of
|
||||
descriptions where we expect to find catalogs. We have to
|
||||
recognize certain % substitutions and stop when we found the
|
||||
first existing file. */
|
||||
char *buf;
|
||||
size_t bufact;
|
||||
size_t bufmax;
|
||||
size_t bufmax = 0;
|
||||
size_t len;
|
||||
|
||||
buf = NULL;
|
||||
bufmax = 0;
|
||||
|
||||
fd = -1;
|
||||
while (*run_nlspath != '\0')
|
||||
{
|
||||
@@ -188,7 +189,10 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
|
||||
|
||||
/* Avoid dealing with directories and block devices */
|
||||
if (__builtin_expect (fd, 0) < 0)
|
||||
return -1;
|
||||
{
|
||||
free (buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
|
||||
goto close_unlock_return;
|
||||
@@ -325,6 +329,7 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var,
|
||||
/* Release the lock again. */
|
||||
close_unlock_return:
|
||||
close_not_cancel_no_status (fd);
|
||||
free (buf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include <assert.h>
|
||||
#include <mcheck.h>
|
||||
#include <nl_types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
|
||||
static const char *msgs[] =
|
||||
@@ -12,6 +15,33 @@ static const char *msgs[] =
|
||||
};
|
||||
#define nmsgs (sizeof (msgs) / sizeof (msgs[0]))
|
||||
|
||||
|
||||
/* Test for unbounded alloca. */
|
||||
static int
|
||||
do_bz17905 (void)
|
||||
{
|
||||
char *buf;
|
||||
struct rlimit rl;
|
||||
nl_catd result;
|
||||
|
||||
const int sz = 1024 * 1024;
|
||||
|
||||
getrlimit (RLIMIT_STACK, &rl);
|
||||
rl.rlim_cur = sz;
|
||||
setrlimit (RLIMIT_STACK, &rl);
|
||||
|
||||
buf = malloc (sz + 1);
|
||||
memset (buf, 'A', sz);
|
||||
buf[sz] = '\0';
|
||||
setenv ("NLSPATH", buf, 1);
|
||||
|
||||
result = catopen (buf, NL_CAT_LOCALE);
|
||||
assert (result == (nl_catd) -1);
|
||||
|
||||
free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ROUNDS 5
|
||||
|
||||
static int
|
||||
@@ -62,6 +92,7 @@ do_test (void)
|
||||
}
|
||||
}
|
||||
|
||||
result += do_bz17905 ();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,9 @@
|
||||
/* Define if assembler supports AVX512. */
|
||||
#undef HAVE_AVX512_ASM_SUPPORT
|
||||
|
||||
/* Define if assembler supports vector instructions on S390. */
|
||||
#undef HAVE_S390_VX_ASM_SUPPORT
|
||||
|
||||
/* Define if assembler supports Intel MPX. */
|
||||
#undef HAVE_MPX_SUPPORT
|
||||
|
||||
@@ -114,6 +117,9 @@
|
||||
include/libc-symbols.h that avoid PLT slots in the shared objects. */
|
||||
#undef NO_HIDDEN
|
||||
|
||||
/* AArch64 big endian ABI */
|
||||
#undef HAVE_AARCH64_BE
|
||||
|
||||
|
||||
/* Defined to some form of __attribute__ ((...)) if the compiler supports
|
||||
a different, more efficient calling convention. */
|
||||
|
||||
+1
-1
@@ -358,7 +358,7 @@ $(objpfx)interp.os: $(elf-objpfx)runtime-linker.h
|
||||
|
||||
$(elf-objpfx)runtime-linker.h: $(elf-objpfx)runtime-linker.st; @:
|
||||
$(elf-objpfx)runtime-linker.st: $(common-objpfx)config.make
|
||||
$(name-target-directory)
|
||||
$(make-target-directory)
|
||||
echo '#define RUNTIME_LINKER "$(rtlddir)/$(rtld-installed-name)"' \
|
||||
> ${@:st=T}
|
||||
$(move-if-change) ${@:st=T} ${@:st=h}
|
||||
|
||||
@@ -167,11 +167,11 @@ makesymlink (src, dest)
|
||||
const char *src;
|
||||
const char *dest;
|
||||
{
|
||||
struct stat stats;
|
||||
struct stat64 stats;
|
||||
const char *error;
|
||||
|
||||
/* Destination must not be a directory. */
|
||||
if (lstat (dest, &stats) == 0)
|
||||
if (lstat64 (dest, &stats) == 0)
|
||||
{
|
||||
if (S_ISDIR (stats.st_mode))
|
||||
{
|
||||
|
||||
+7
-1
@@ -95,8 +95,11 @@ _IO_wstr_overflow (fp, c)
|
||||
wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
|
||||
size_t old_wblen = _IO_wblen (fp);
|
||||
_IO_size_t new_size = 2 * old_wblen + 100;
|
||||
if (new_size < old_wblen)
|
||||
|
||||
if (__glibc_unlikely (new_size < old_wblen)
|
||||
|| __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t)))
|
||||
return EOF;
|
||||
|
||||
new_buf
|
||||
= (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
|
||||
* sizeof (wchar_t));
|
||||
@@ -186,6 +189,9 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
|
||||
return 1;
|
||||
|
||||
_IO_size_t newsize = offset + 100;
|
||||
if (__glibc_unlikely (newsize > SIZE_MAX / sizeof (wchar_t)))
|
||||
return 1;
|
||||
|
||||
wchar_t *oldbuf = wd->_IO_buf_base;
|
||||
wchar_t *newbuf
|
||||
= (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize
|
||||
|
||||
+2
-1
@@ -76,7 +76,8 @@ install-lib := libg.a
|
||||
gpl2lgpl := error.c error.h
|
||||
|
||||
tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \
|
||||
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1
|
||||
tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \
|
||||
tst-mntent-blank-corrupt tst-mntent-blank-passno bug18240
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += $(objpfx)tst-error1-mem.out
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/* Test integer wraparound in hcreate.
|
||||
Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <search.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
static void
|
||||
test_size (size_t size)
|
||||
{
|
||||
int res = hcreate (size);
|
||||
if (res == 0)
|
||||
{
|
||||
if (errno == ENOMEM)
|
||||
return;
|
||||
printf ("error: hcreate (%zu): %m\n", size);
|
||||
exit (1);
|
||||
}
|
||||
char *keys[100];
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
if (asprintf (keys + i, "%d", i) < 0)
|
||||
{
|
||||
printf ("error: asprintf: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
ENTRY e = { keys[i], (char *) "value" };
|
||||
if (hsearch (e, ENTER) == NULL)
|
||||
{
|
||||
printf ("error: hsearch (\"%s\"): %m\n", keys[i]);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
hdestroy ();
|
||||
|
||||
for (int i = 0; i < 100; ++i)
|
||||
free (keys[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* Limit the size of the process, so that memory allocation will
|
||||
fail without impacting the entire system. */
|
||||
{
|
||||
struct rlimit limit;
|
||||
if (getrlimit (RLIMIT_AS, &limit) != 0)
|
||||
{
|
||||
printf ("getrlimit (RLIMIT_AS) failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
long target = 100 * 1024 * 1024;
|
||||
if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
|
||||
{
|
||||
limit.rlim_cur = target;
|
||||
if (setrlimit (RLIMIT_AS, &limit) != 0)
|
||||
{
|
||||
printf ("setrlimit (RLIMIT_AS) failed: %m\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test_size (500);
|
||||
test_size (-1);
|
||||
test_size (-3);
|
||||
test_size (INT_MAX - 2);
|
||||
test_size (INT_MAX - 1);
|
||||
test_size (INT_MAX);
|
||||
test_size (((unsigned) INT_MAX) + 1);
|
||||
test_size (UINT_MAX - 2);
|
||||
test_size (UINT_MAX - 1);
|
||||
test_size (UINT_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
+18
-12
@@ -19,7 +19,7 @@
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <search.h>
|
||||
|
||||
/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
|
||||
@@ -46,15 +46,12 @@ static int
|
||||
isprime (unsigned int number)
|
||||
{
|
||||
/* no even number will be passed */
|
||||
unsigned int div = 3;
|
||||
|
||||
while (div * div < number && number % div != 0)
|
||||
div += 2;
|
||||
|
||||
return number % div != 0;
|
||||
for (unsigned int div = 3; div <= number / div; div += 2)
|
||||
if (number % div == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Before using the hash table we must allocate memory for it.
|
||||
Test for an existing table are done. We allocate one element
|
||||
more as the found prime number says. This is done for more effective
|
||||
@@ -81,10 +78,19 @@ hcreate_r (nel, htab)
|
||||
use will not work. */
|
||||
if (nel < 3)
|
||||
nel = 3;
|
||||
/* Change nel to the first prime number not smaller as nel. */
|
||||
nel |= 1; /* make odd */
|
||||
while (!isprime (nel))
|
||||
nel += 2;
|
||||
|
||||
/* Change nel to the first prime number in the range [nel, UINT_MAX - 2],
|
||||
The '- 2' means 'nel += 2' cannot overflow. */
|
||||
for (nel |= 1; ; nel += 2)
|
||||
{
|
||||
if (UINT_MAX - 2 < nel)
|
||||
{
|
||||
__set_errno (ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
if (isprime (nel))
|
||||
break;
|
||||
}
|
||||
|
||||
htab->size = nel;
|
||||
htab->filled = 0;
|
||||
|
||||
+3
-1
@@ -136,7 +136,9 @@ __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
|
||||
end_ptr = strchr (buffer, '\n');
|
||||
if (end_ptr != NULL) /* chop newline */
|
||||
{
|
||||
while (end_ptr[-1] == ' ' || end_ptr[-1] == '\t')
|
||||
/* Do not walk past the start of buffer if it's all whitespace. */
|
||||
while (end_ptr != buffer
|
||||
&& (end_ptr[-1] == ' ' || end_ptr[-1] == '\t'))
|
||||
end_ptr--;
|
||||
*end_ptr = '\0';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/* Make sure blank lines does not cause memory corruption BZ #18887.
|
||||
|
||||
Copyright (C) 2009-2015 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 <mntent.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Make sure blank lines don't trigger memory corruption. This doesn't happen
|
||||
for all targets though, so it's a best effort test BZ #18887. */
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = tmpfile ();
|
||||
fputs ("\n \n/foo\\040dir /bar\\040dir auto bind \t \n", fp);
|
||||
rewind (fp);
|
||||
|
||||
/* The corruption happens here ... */
|
||||
getmntent (fp);
|
||||
/* ... but trigers here. */
|
||||
endmntent (fp);
|
||||
|
||||
/* If the test failed, we would crash, and not hit this point. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Make sure trailing whitespace is handled properly BZ #17273.
|
||||
|
||||
Copyright (C) 2009-2015 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 <mntent.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Check entries to make sure trailing whitespace is ignored and we return the
|
||||
correct passno value BZ #17273. */
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int result = 0;
|
||||
FILE *fp;
|
||||
struct mntent *mnt;
|
||||
|
||||
fp = tmpfile ();
|
||||
fputs ("/foo\\040dir /bar\\040dir auto bind \t \n", fp);
|
||||
rewind (fp);
|
||||
|
||||
mnt = getmntent (fp);
|
||||
if (strcmp (mnt->mnt_fsname, "/foo dir") != 0
|
||||
|| strcmp (mnt->mnt_dir, "/bar dir") != 0
|
||||
|| strcmp (mnt->mnt_type, "auto") != 0
|
||||
|| strcmp (mnt->mnt_opts, "bind") != 0
|
||||
|| mnt->mnt_freq != 0
|
||||
|| mnt->mnt_passno != 0)
|
||||
{
|
||||
puts ("Error while reading entry with trailing whitespaces");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -73,26 +73,6 @@ main (int argc, char *argv[])
|
||||
puts ("Error while reading written entry back in");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
/* Part III: Entry with whitespaces at the end of a line. */
|
||||
rewind (fp);
|
||||
|
||||
fputs ("/foo\\040dir /bar\\040dir auto bind \t \n", fp);
|
||||
|
||||
rewind (fp);
|
||||
|
||||
mnt = getmntent (fp);
|
||||
|
||||
if (strcmp (mnt->mnt_fsname, "/foo dir") != 0
|
||||
|| strcmp (mnt->mnt_dir, "/bar dir") != 0
|
||||
|| strcmp (mnt->mnt_type, "auto") != 0
|
||||
|| strcmp (mnt->mnt_opts, "bind") != 0
|
||||
|| mnt->mnt_freq != 0
|
||||
|| mnt->mnt_passno != 0)
|
||||
{
|
||||
puts ("Error while reading entry with trailing whitespaces");
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
+11
-9
@@ -680,16 +680,18 @@ nis_server_cache_add (const_nis_name name, int search_parent,
|
||||
/* Choose which entry should be evicted from the cache. */
|
||||
loc = &nis_server_cache[0];
|
||||
if (*loc != NULL)
|
||||
for (i = 1; i < 16; ++i)
|
||||
if (nis_server_cache[i] == NULL)
|
||||
{
|
||||
{
|
||||
for (i = 1; i < 16; ++i)
|
||||
if (nis_server_cache[i] == NULL)
|
||||
{
|
||||
loc = &nis_server_cache[i];
|
||||
break;
|
||||
}
|
||||
else if ((*loc)->uses > nis_server_cache[i]->uses
|
||||
|| ((*loc)->uses == nis_server_cache[i]->uses
|
||||
&& (*loc)->expires > nis_server_cache[i]->expires))
|
||||
loc = &nis_server_cache[i];
|
||||
break;
|
||||
}
|
||||
else if ((*loc)->uses > nis_server_cache[i]->uses
|
||||
|| ((*loc)->uses == nis_server_cache[i]->uses
|
||||
&& (*loc)->expires > nis_server_cache[i]->expires))
|
||||
loc = &nis_server_cache[i];
|
||||
}
|
||||
old = *loc;
|
||||
*loc = new;
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <selinux/avc.h>
|
||||
#include <selinux/flask.h>
|
||||
#include <selinux/selinux.h>
|
||||
#ifdef HAVE_LIBAUDIT
|
||||
# include <libaudit.h>
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ install-bin := getent makedb
|
||||
makedb-modules = xmalloc hash-string
|
||||
extra-objs += $(makedb-modules:=.o)
|
||||
|
||||
tests = test-netdb tst-nss-test1 test-digits-dots
|
||||
tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent
|
||||
xtests = bug-erange
|
||||
|
||||
# Specify rules for the nss_* modules. We have some services.
|
||||
|
||||
@@ -134,7 +134,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stayopen)
|
||||
|
||||
__libc_lock_lock (lock);
|
||||
|
||||
status = internal_setent (stayopen);
|
||||
status = internal_setent (1);
|
||||
|
||||
if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/* Copyright (C) 2015 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 <pwd.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
/* Count the number of entries in the password database, and fetch
|
||||
data from the first and last entries. */
|
||||
size_t count = 0;
|
||||
struct passwd * pw;
|
||||
char *first_name = NULL;
|
||||
uid_t first_uid = 0;
|
||||
char *last_name = NULL;
|
||||
uid_t last_uid = 0;
|
||||
setpwent ();
|
||||
while ((pw = getpwent ()) != NULL)
|
||||
{
|
||||
if (first_name == NULL)
|
||||
{
|
||||
first_name = strdup (pw->pw_name);
|
||||
if (first_name == NULL)
|
||||
{
|
||||
printf ("strdup: %m\n");
|
||||
return 1;
|
||||
}
|
||||
first_uid = pw->pw_uid;
|
||||
}
|
||||
|
||||
free (last_name);
|
||||
last_name = strdup (pw->pw_name);
|
||||
if (last_name == NULL)
|
||||
{
|
||||
printf ("strdup: %m\n");
|
||||
return 1;
|
||||
}
|
||||
last_uid = pw->pw_uid;
|
||||
++count;
|
||||
}
|
||||
endpwent ();
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
printf ("No entries in the password database.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try again, this time interleaving with name-based and UID-based
|
||||
lookup operations. The counts do not match if the interleaved
|
||||
lookups affected the enumeration. */
|
||||
size_t new_count = 0;
|
||||
setpwent ();
|
||||
while ((pw = getpwent ()) != NULL)
|
||||
{
|
||||
if (new_count == count)
|
||||
{
|
||||
printf ("Additional entry in the password database.\n");
|
||||
return 1;
|
||||
}
|
||||
++new_count;
|
||||
struct passwd *pw2 = getpwnam (first_name);
|
||||
if (pw2 == NULL)
|
||||
{
|
||||
printf ("getpwnam (%s) failed: %m\n", first_name);
|
||||
return 1;
|
||||
}
|
||||
pw2 = getpwnam (last_name);
|
||||
if (pw2 == NULL)
|
||||
{
|
||||
printf ("getpwnam (%s) failed: %m\n", last_name);
|
||||
return 1;
|
||||
}
|
||||
pw2 = getpwuid (first_uid);
|
||||
if (pw2 == NULL)
|
||||
{
|
||||
printf ("getpwuid (%llu) failed: %m\n",
|
||||
(unsigned long long) first_uid);
|
||||
return 1;
|
||||
}
|
||||
pw2 = getpwuid (last_uid);
|
||||
if (pw2 == NULL)
|
||||
{
|
||||
printf ("getpwuid (%llu) failed: %m\n",
|
||||
(unsigned long long) last_uid);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
endpwent ();
|
||||
if (new_count < count)
|
||||
{
|
||||
printf ("Missing entry in the password database.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -945,14 +945,13 @@ FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
|
||||
}
|
||||
else if (c == L('[') && *p == L('.'))
|
||||
{
|
||||
++p;
|
||||
while (1)
|
||||
{
|
||||
c = *++p;
|
||||
if (c == '\0')
|
||||
if (c == L('\0'))
|
||||
return FNM_NOMATCH;
|
||||
|
||||
if (*p == L('.') && p[1] == L(']'))
|
||||
if (c == L('.') && p[1] == L(']'))
|
||||
break;
|
||||
}
|
||||
p += 2;
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
const char *pattern = "[[:alpha:]'[:alpha:]\0]";
|
||||
|
||||
return fnmatch (pattern, "a", 0) != FNM_NOMATCH;
|
||||
if (fnmatch ("[[:alpha:]'[:alpha:]\0]", "a", 0) != FNM_NOMATCH)
|
||||
return 1;
|
||||
if (fnmatch ("[a[.\0.]]", "a", 0) != FNM_NOMATCH)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
|
||||
+111
-3
@@ -615,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
int have_to_map = 0;
|
||||
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
buffer += pad;
|
||||
if (__glibc_unlikely (buflen < sizeof (struct host_data) + pad))
|
||||
buflen = buflen > pad ? buflen - pad : 0;
|
||||
if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
{
|
||||
/* The buffer is too small. */
|
||||
too_small:
|
||||
@@ -1031,7 +1032,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
int h_namelen = 0;
|
||||
|
||||
if (ancount == 0)
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
{
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
{
|
||||
@@ -1208,7 +1212,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
/* Special case here: if the resolver sent a result but it only
|
||||
contains a CNAME while we are looking for a T_A or T_AAAA record,
|
||||
we fail with NOTFOUND instead of TRYAGAIN. */
|
||||
return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
|
||||
if (canon != NULL)
|
||||
{
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
*h_errnop = NETDB_INTERNAL;
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
|
||||
@@ -1222,11 +1233,101 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
|
||||
enum nss_status status = NSS_STATUS_NOTFOUND;
|
||||
|
||||
/* Combining the NSS status of two distinct queries requires some
|
||||
compromise and attention to symmetry (A or AAAA queries can be
|
||||
returned in any order). What follows is a breakdown of how this
|
||||
code is expected to work and why. We discuss only SUCCESS,
|
||||
TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
|
||||
that apply (though RETURN and MERGE exist). We make a distinction
|
||||
between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
|
||||
A recoverable TRYAGAIN is almost always due to buffer size issues
|
||||
and returns ERANGE in errno and the caller is expected to retry
|
||||
with a larger buffer.
|
||||
|
||||
Lastly, you may be tempted to make significant changes to the
|
||||
conditions in this code to bring about symmetry between responses.
|
||||
Please don't change anything without due consideration for
|
||||
expected application behaviour. Some of the synthesized responses
|
||||
aren't very well thought out and sometimes appear to imply that
|
||||
IPv4 responses are always answer 1, and IPv6 responses are always
|
||||
answer 2, but that's not true (see the implementation of send_dg
|
||||
and send_vc to see response can arrive in any order, particularly
|
||||
for UDP). However, we expect it holds roughly enough of the time
|
||||
that this code works, but certainly needs to be fixed to make this
|
||||
a more robust implementation.
|
||||
|
||||
----------------------------------------------
|
||||
| Answer 1 Status / | Synthesized | Reason |
|
||||
| Answer 2 Status | Status | |
|
||||
|--------------------------------------------|
|
||||
| SUCCESS/SUCCESS | SUCCESS | [1] |
|
||||
| SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
|
||||
| SUCCESS/TRYAGAIN' | SUCCESS | [1] |
|
||||
| SUCCESS/NOTFOUND | SUCCESS | [1] |
|
||||
| SUCCESS/UNAVAIL | SUCCESS | [1] |
|
||||
| TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
|
||||
| TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
|
||||
| TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
|
||||
| TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
|
||||
| TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
|
||||
| TRYAGAIN'/SUCCESS | SUCCESS | [3] |
|
||||
| TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
|
||||
| TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
|
||||
| TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
|
||||
| TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
|
||||
| NOTFOUND/SUCCESS | SUCCESS | [3] |
|
||||
| NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
|
||||
| NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
|
||||
| NOTFOUND/NOTFOUND | NOTFOUND | [3] |
|
||||
| NOTFOUND/UNAVAIL | UNAVAIL | [3] |
|
||||
| UNAVAIL/SUCCESS | UNAVAIL | [4] |
|
||||
| UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
|
||||
| UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
|
||||
| UNAVAIL/NOTFOUND | UNAVAIL | [4] |
|
||||
| UNAVAIL/UNAVAIL | UNAVAIL | [4] |
|
||||
----------------------------------------------
|
||||
|
||||
[1] If the first response is a success we return success.
|
||||
This ignores the state of the second answer and in fact
|
||||
incorrectly sets errno and h_errno to that of the second
|
||||
answer. However because the response is a success we ignore
|
||||
*errnop and *h_errnop (though that means you touched errno on
|
||||
success). We are being conservative here and returning the
|
||||
likely IPv4 response in the first answer as a success.
|
||||
|
||||
[2] If the first response is a recoverable TRYAGAIN we return
|
||||
that instead of looking at the second response. The
|
||||
expectation here is that we have failed to get an IPv4 response
|
||||
and should retry both queries.
|
||||
|
||||
[3] If the first response was not a SUCCESS and the second
|
||||
response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
|
||||
or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
|
||||
result from the second response, otherwise the first responses
|
||||
status is used. Again we have some odd side-effects when the
|
||||
second response is NOTFOUND because we overwrite *errnop and
|
||||
*h_errnop that means that a first answer of NOTFOUND might see
|
||||
its *errnop and *h_errnop values altered. Whether it matters
|
||||
in practice that a first response NOTFOUND has the wrong
|
||||
*errnop and *h_errnop is undecided.
|
||||
|
||||
[4] If the first response is UNAVAIL we return that instead of
|
||||
looking at the second response. The expectation here is that
|
||||
it will have failed similarly e.g. configuration failure.
|
||||
|
||||
[5] Testing this code is complicated by the fact that truncated
|
||||
second response buffers might be returned as SUCCESS if the
|
||||
first answer is a SUCCESS. To fix this we add symmetry to
|
||||
TRYAGAIN with the second response. If the second response
|
||||
is a recoverable error we now return TRYAGIN even if the first
|
||||
response was SUCCESS. */
|
||||
|
||||
if (anslen1 > 0)
|
||||
status = gaih_getanswer_slice(answer1, anslen1, qname,
|
||||
&pat, &buffer, &buflen,
|
||||
errnop, h_errnop, ttlp,
|
||||
&first);
|
||||
|
||||
if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
|
||||
|| (status == NSS_STATUS_TRYAGAIN
|
||||
/* We want to look at the second answer in case of an
|
||||
@@ -1242,8 +1343,15 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
&pat, &buffer, &buflen,
|
||||
errnop, h_errnop, ttlp,
|
||||
&first);
|
||||
/* Use the second response status in some cases. */
|
||||
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
|
||||
status = status2;
|
||||
/* Do not return a truncated second response (unless it was
|
||||
unavoidable e.g. unrecoverable TRYAGAIN). */
|
||||
if (status == NSS_STATUS_SUCCESS
|
||||
&& (status2 == NSS_STATUS_TRYAGAIN
|
||||
&& *errnop == ERANGE && *h_errnop != NO_RECOVERY))
|
||||
status = NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
}
|
||||
@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
|
||||
@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
*nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
if (saved_herrno != -1)
|
||||
|
||||
+197
-67
@@ -1,3 +1,20 @@
|
||||
/* Copyright (C) 2016 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/>. */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
@@ -361,6 +378,8 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||||
#ifdef USE_HOOKS
|
||||
if (__glibc_unlikely (statp->qhook || statp->rhook)) {
|
||||
if (anssiz < MAXPACKET && ansp) {
|
||||
/* Always allocate MAXPACKET, callers expect
|
||||
this specific size. */
|
||||
u_char *buf = malloc (MAXPACKET);
|
||||
if (buf == NULL)
|
||||
return (-1);
|
||||
@@ -660,6 +679,77 @@ libresolv_hidden_def (res_nsend)
|
||||
|
||||
/* Private */
|
||||
|
||||
/* The send_vc function is responsible for sending a DNS query over TCP
|
||||
to the nameserver numbered NS from the res_state STATP i.e.
|
||||
EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
|
||||
IPv6 queries at the same serially on the same socket.
|
||||
|
||||
Please note that for TCP there is no way to disable sending both
|
||||
queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
|
||||
and sends the queries serially and waits for the result after each
|
||||
sent query. This implemetnation should be corrected to honour these
|
||||
options.
|
||||
|
||||
Please also note that for TCP we send both queries over the same
|
||||
socket one after another. This technically violates best practice
|
||||
since the server is allowed to read the first query, respond, and
|
||||
then close the socket (to service another client). If the server
|
||||
does this, then the remaining second query in the socket data buffer
|
||||
will cause the server to send the client an RST which will arrive
|
||||
asynchronously and the client's OS will likely tear down the socket
|
||||
receive buffer resulting in a potentially short read and lost
|
||||
response data. This will force the client to retry the query again,
|
||||
and this process may repeat until all servers and connection resets
|
||||
are exhausted and then the query will fail. It's not known if this
|
||||
happens with any frequency in real DNS server implementations. This
|
||||
implementation should be corrected to use two sockets by default for
|
||||
parallel queries.
|
||||
|
||||
The query stored in BUF of BUFLEN length is sent first followed by
|
||||
the query stored in BUF2 of BUFLEN2 length. Queries are sent
|
||||
serially on the same socket.
|
||||
|
||||
Answers to the query are stored firstly in *ANSP up to a max of
|
||||
*ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
|
||||
is non-NULL (to indicate that modifying the answer buffer is allowed)
|
||||
then malloc is used to allocate a new response buffer and ANSCP and
|
||||
ANSP will both point to the new buffer. If more than *ANSSIZP bytes
|
||||
are needed but ANSCP is NULL, then as much of the response as
|
||||
possible is read into the buffer, but the results will be truncated.
|
||||
When truncation happens because of a small answer buffer the DNS
|
||||
packets header field TC will bet set to 1, indicating a truncated
|
||||
message and the rest of the socket data will be read and discarded.
|
||||
|
||||
Answers to the query are stored secondly in *ANSP2 up to a max of
|
||||
*ANSSIZP2 bytes, with the actual response length stored in
|
||||
*RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
|
||||
is non-NULL (required for a second query) then malloc is used to
|
||||
allocate a new response buffer, *ANSSIZP2 is set to the new buffer
|
||||
size and *ANSP2_MALLOCED is set to 1.
|
||||
|
||||
The ANSP2_MALLOCED argument will eventually be removed as the
|
||||
change in buffer pointer can be used to detect the buffer has
|
||||
changed and that the caller should use free on the new buffer.
|
||||
|
||||
Note that the answers may arrive in any order from the server and
|
||||
therefore the first and second answer buffers may not correspond to
|
||||
the first and second queries.
|
||||
|
||||
It is not supported to call this function with a non-NULL ANSP2
|
||||
but a NULL ANSCP. Put another way, you can call send_vc with a
|
||||
single unmodifiable buffer or two modifiable buffers, but no other
|
||||
combination is supported.
|
||||
|
||||
It is the caller's responsibility to free the malloc allocated
|
||||
buffers by detecting that the pointers have changed from their
|
||||
original values i.e. *ANSCP or *ANSP2 has changed.
|
||||
|
||||
If errors are encountered then *TERRNO is set to an appropriate
|
||||
errno value and a zero result is returned for a recoverable error,
|
||||
and a less-than zero result is returned for a non-recoverable error.
|
||||
|
||||
If no errors are encountered then *TERRNO is left unmodified and
|
||||
a the length of the first response in bytes is returned. */
|
||||
static int
|
||||
send_vc(res_state statp,
|
||||
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
||||
@@ -669,11 +759,7 @@ send_vc(res_state statp,
|
||||
{
|
||||
const HEADER *hp = (HEADER *) buf;
|
||||
const HEADER *hp2 = (HEADER *) buf2;
|
||||
u_char *ans = *ansp;
|
||||
int orig_anssizp = *anssizp;
|
||||
// XXX REMOVE
|
||||
// int anssiz = *anssizp;
|
||||
HEADER *anhp = (HEADER *) ans;
|
||||
HEADER *anhp = (HEADER *) *ansp;
|
||||
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
||||
int truncating, connreset, n;
|
||||
/* On some architectures compiler might emit a warning indicating
|
||||
@@ -766,6 +852,8 @@ send_vc(res_state statp,
|
||||
* Receive length & response
|
||||
*/
|
||||
int recvresp1 = 0;
|
||||
/* Skip the second response if there is no second query.
|
||||
To do that we mark the second response as received. */
|
||||
int recvresp2 = buf2 == NULL;
|
||||
uint16_t rlen16;
|
||||
read_len:
|
||||
@@ -802,40 +890,14 @@ send_vc(res_state statp,
|
||||
u_char **thisansp;
|
||||
int *thisresplenp;
|
||||
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
|
||||
/* We have not received any responses
|
||||
yet or we only have one response to
|
||||
receive. */
|
||||
thisanssizp = anssizp;
|
||||
thisansp = anscp ?: ansp;
|
||||
assert (anscp != NULL || ansp2 == NULL);
|
||||
thisresplenp = &resplen;
|
||||
} else {
|
||||
if (*anssizp != MAXPACKET) {
|
||||
/* No buffer allocated for the first
|
||||
reply. We can try to use the rest
|
||||
of the user-provided buffer. */
|
||||
#if __GNUC_PREREQ (4, 7)
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
|
||||
#endif
|
||||
#if _STRING_ARCH_unaligned
|
||||
*anssizp2 = orig_anssizp - resplen;
|
||||
*ansp2 = *ansp + resplen;
|
||||
#else
|
||||
int aligned_resplen
|
||||
= ((resplen + __alignof__ (HEADER) - 1)
|
||||
& ~(__alignof__ (HEADER) - 1));
|
||||
*anssizp2 = orig_anssizp - aligned_resplen;
|
||||
*ansp2 = *ansp + aligned_resplen;
|
||||
#endif
|
||||
#if __GNUC_PREREQ (4, 7)
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
#endif
|
||||
} else {
|
||||
/* The first reply did not fit into the
|
||||
user-provided buffer. Maybe the second
|
||||
answer will. */
|
||||
*anssizp2 = orig_anssizp;
|
||||
*ansp2 = *ansp;
|
||||
}
|
||||
|
||||
thisanssizp = anssizp2;
|
||||
thisansp = ansp2;
|
||||
thisresplenp = resplen2;
|
||||
@@ -843,10 +905,14 @@ send_vc(res_state statp,
|
||||
anhp = (HEADER *) *thisansp;
|
||||
|
||||
*thisresplenp = rlen;
|
||||
if (rlen > *thisanssizp) {
|
||||
/* Yes, we test ANSCP here. If we have two buffers
|
||||
both will be allocatable. */
|
||||
if (__glibc_likely (anscp != NULL)) {
|
||||
/* Is the answer buffer too small? */
|
||||
if (*thisanssizp < rlen) {
|
||||
/* If the current buffer is not the the static
|
||||
user-supplied buffer then we can reallocate
|
||||
it. */
|
||||
if (thisansp != NULL && thisansp != ansp) {
|
||||
/* Always allocate MAXPACKET, callers expect
|
||||
this specific size. */
|
||||
u_char *newp = malloc (MAXPACKET);
|
||||
if (newp == NULL) {
|
||||
*terrno = ENOMEM;
|
||||
@@ -858,6 +924,9 @@ send_vc(res_state statp,
|
||||
if (thisansp == ansp2)
|
||||
*ansp2_malloced = 1;
|
||||
anhp = (HEADER *) newp;
|
||||
/* A uint16_t can't be larger than MAXPACKET
|
||||
thus it's safe to allocate MAXPACKET but
|
||||
read RLEN bytes instead. */
|
||||
len = rlen;
|
||||
} else {
|
||||
Dprint(statp->options & RES_DEBUG,
|
||||
@@ -1021,6 +1090,66 @@ reopen (res_state statp, int *terrno, int ns)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The send_dg function is responsible for sending a DNS query over UDP
|
||||
to the nameserver numbered NS from the res_state STATP i.e.
|
||||
EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries
|
||||
along with the ability to send the query in parallel for both stacks
|
||||
(default) or serially (RES_SINGLKUP). It also supports serial lookup
|
||||
with a close and reopen of the socket used to talk to the server
|
||||
(RES_SNGLKUPREOP) to work around broken name servers.
|
||||
|
||||
The query stored in BUF of BUFLEN length is sent first followed by
|
||||
the query stored in BUF2 of BUFLEN2 length. Queries are sent
|
||||
in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
|
||||
|
||||
Answers to the query are stored firstly in *ANSP up to a max of
|
||||
*ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
|
||||
is non-NULL (to indicate that modifying the answer buffer is allowed)
|
||||
then malloc is used to allocate a new response buffer and ANSCP and
|
||||
ANSP will both point to the new buffer. If more than *ANSSIZP bytes
|
||||
are needed but ANSCP is NULL, then as much of the response as
|
||||
possible is read into the buffer, but the results will be truncated.
|
||||
When truncation happens because of a small answer buffer the DNS
|
||||
packets header field TC will bet set to 1, indicating a truncated
|
||||
message, while the rest of the UDP packet is discarded.
|
||||
|
||||
Answers to the query are stored secondly in *ANSP2 up to a max of
|
||||
*ANSSIZP2 bytes, with the actual response length stored in
|
||||
*RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
|
||||
is non-NULL (required for a second query) then malloc is used to
|
||||
allocate a new response buffer, *ANSSIZP2 is set to the new buffer
|
||||
size and *ANSP2_MALLOCED is set to 1.
|
||||
|
||||
The ANSP2_MALLOCED argument will eventually be removed as the
|
||||
change in buffer pointer can be used to detect the buffer has
|
||||
changed and that the caller should use free on the new buffer.
|
||||
|
||||
Note that the answers may arrive in any order from the server and
|
||||
therefore the first and second answer buffers may not correspond to
|
||||
the first and second queries.
|
||||
|
||||
It is not supported to call this function with a non-NULL ANSP2
|
||||
but a NULL ANSCP. Put another way, you can call send_vc with a
|
||||
single unmodifiable buffer or two modifiable buffers, but no other
|
||||
combination is supported.
|
||||
|
||||
It is the caller's responsibility to free the malloc allocated
|
||||
buffers by detecting that the pointers have changed from their
|
||||
original values i.e. *ANSCP or *ANSP2 has changed.
|
||||
|
||||
If an answer is truncated because of UDP datagram DNS limits then
|
||||
*V_CIRCUIT is set to 1 and the return value non-zero to indicate to
|
||||
the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1
|
||||
if any progress was made reading a response from the nameserver and
|
||||
is used by the caller to distinguish between ECONNREFUSED and
|
||||
ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
|
||||
|
||||
If errors are encountered then *TERRNO is set to an appropriate
|
||||
errno value and a zero result is returned for a recoverable error,
|
||||
and a less-than zero result is returned for a non-recoverable error.
|
||||
|
||||
If no errors are encountered then *TERRNO is left unmodified and
|
||||
a the length of the first response in bytes is returned. */
|
||||
static int
|
||||
send_dg(res_state statp,
|
||||
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
||||
@@ -1030,8 +1159,6 @@ send_dg(res_state statp,
|
||||
{
|
||||
const HEADER *hp = (HEADER *) buf;
|
||||
const HEADER *hp2 = (HEADER *) buf2;
|
||||
u_char *ans = *ansp;
|
||||
int orig_anssizp = *anssizp;
|
||||
struct timespec now, timeout, finish;
|
||||
struct pollfd pfd[1];
|
||||
int ptimeout;
|
||||
@@ -1064,6 +1191,8 @@ send_dg(res_state statp,
|
||||
int need_recompute = 0;
|
||||
int nwritten = 0;
|
||||
int recvresp1 = 0;
|
||||
/* Skip the second response if there is no second query.
|
||||
To do that we mark the second response as received. */
|
||||
int recvresp2 = buf2 == NULL;
|
||||
pfd[0].fd = EXT(statp).nssocks[ns];
|
||||
pfd[0].events = POLLOUT;
|
||||
@@ -1227,55 +1356,56 @@ send_dg(res_state statp,
|
||||
int *thisresplenp;
|
||||
|
||||
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
|
||||
/* We have not received any responses
|
||||
yet or we only have one response to
|
||||
receive. */
|
||||
thisanssizp = anssizp;
|
||||
thisansp = anscp ?: ansp;
|
||||
assert (anscp != NULL || ansp2 == NULL);
|
||||
thisresplenp = &resplen;
|
||||
} else {
|
||||
if (*anssizp != MAXPACKET) {
|
||||
/* No buffer allocated for the first
|
||||
reply. We can try to use the rest
|
||||
of the user-provided buffer. */
|
||||
#if _STRING_ARCH_unaligned
|
||||
*anssizp2 = orig_anssizp - resplen;
|
||||
*ansp2 = *ansp + resplen;
|
||||
#else
|
||||
int aligned_resplen
|
||||
= ((resplen + __alignof__ (HEADER) - 1)
|
||||
& ~(__alignof__ (HEADER) - 1));
|
||||
*anssizp2 = orig_anssizp - aligned_resplen;
|
||||
*ansp2 = *ansp + aligned_resplen;
|
||||
#endif
|
||||
} else {
|
||||
/* The first reply did not fit into the
|
||||
user-provided buffer. Maybe the second
|
||||
answer will. */
|
||||
*anssizp2 = orig_anssizp;
|
||||
*ansp2 = *ansp;
|
||||
}
|
||||
|
||||
thisanssizp = anssizp2;
|
||||
thisansp = ansp2;
|
||||
thisresplenp = resplen2;
|
||||
}
|
||||
|
||||
if (*thisanssizp < MAXPACKET
|
||||
/* Yes, we test ANSCP here. If we have two buffers
|
||||
both will be allocatable. */
|
||||
&& anscp
|
||||
/* If the current buffer is not the the static
|
||||
user-supplied buffer then we can reallocate
|
||||
it. */
|
||||
&& (thisansp != NULL && thisansp != ansp)
|
||||
#ifdef FIONREAD
|
||||
/* Is the size too small? */
|
||||
&& (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
|
||||
|| *thisanssizp < *thisresplenp)
|
||||
#endif
|
||||
) {
|
||||
/* Always allocate MAXPACKET, callers expect
|
||||
this specific size. */
|
||||
u_char *newp = malloc (MAXPACKET);
|
||||
if (newp != NULL) {
|
||||
*anssizp = MAXPACKET;
|
||||
*thisansp = ans = newp;
|
||||
*thisanssizp = MAXPACKET;
|
||||
*thisansp = newp;
|
||||
if (thisansp == ansp2)
|
||||
*ansp2_malloced = 1;
|
||||
}
|
||||
}
|
||||
/* We could end up with truncation if anscp was NULL
|
||||
(not allowed to change caller's buffer) and the
|
||||
response buffer size is too small. This isn't a
|
||||
reliable way to detect truncation because the ioctl
|
||||
may be an inaccurate report of the UDP message size.
|
||||
Therefore we use this only to issue debug output.
|
||||
To do truncation accurately with UDP we need
|
||||
MSG_TRUNC which is only available on Linux. We
|
||||
can abstract out the Linux-specific feature in the
|
||||
future to detect truncation. */
|
||||
if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
|
||||
Dprint(statp->options & RES_DEBUG,
|
||||
(stdout, ";; response may be truncated (UDP)\n")
|
||||
);
|
||||
}
|
||||
|
||||
HEADER *anhp = (HEADER *) *thisansp;
|
||||
socklen_t fromlen = sizeof(struct sockaddr_in6);
|
||||
assert (sizeof(from) <= fromlen);
|
||||
|
||||
+7
-5
@@ -66,11 +66,11 @@ test-srcs := tst-fmtmsg
|
||||
tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
|
||||
test-canon test-canon2 tst-strtoll tst-environ \
|
||||
tst-xpg-basename tst-random tst-random2 tst-bsearch \
|
||||
tst-limits tst-rand48 bug-strtod tst-setcontext \
|
||||
test-a64l tst-qsort tst-system testmb2 bug-strtod2 \
|
||||
tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 tst-rand48-2 \
|
||||
tst-makecontext tst-strtod4 tst-strtod5 tst-qsort2 \
|
||||
tst-makecontext2 tst-strtod6 tst-unsetenv1 \
|
||||
tst-limits tst-rand48 bug-strtod tst-setcontext \
|
||||
tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \
|
||||
bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 tst-strtod3 \
|
||||
tst-rand48-2 tst-makecontext tst-strtod4 tst-strtod5 \
|
||||
tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \
|
||||
tst-makecontext3 bug-getcontext bug-fmtmsg1 \
|
||||
tst-secure-getenv tst-strtod-overflow tst-strtod-round \
|
||||
tst-tininess tst-strtod-underflow tst-tls-atexit
|
||||
@@ -157,3 +157,5 @@ tst-tls-atexit-lib.so-no-z-defs = yes
|
||||
|
||||
$(objpfx)tst-tls-atexit: $(shared-thread-library) $(libdl)
|
||||
$(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so
|
||||
|
||||
$(objpfx)tst-makecontext: $(libdl)
|
||||
|
||||
+13
-11
@@ -269,18 +269,20 @@ unsetenv (name)
|
||||
ep = __environ;
|
||||
if (ep != NULL)
|
||||
while (*ep != NULL)
|
||||
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
|
||||
{
|
||||
/* Found it. Remove this pointer by moving later ones back. */
|
||||
char **dp = ep;
|
||||
{
|
||||
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
|
||||
{
|
||||
/* Found it. Remove this pointer by moving later ones back. */
|
||||
char **dp = ep;
|
||||
|
||||
do
|
||||
dp[0] = dp[1];
|
||||
while (*dp++);
|
||||
/* Continue the loop in case NAME appears again. */
|
||||
}
|
||||
else
|
||||
++ep;
|
||||
do
|
||||
dp[0] = dp[1];
|
||||
while (*dp++);
|
||||
/* Continue the loop in case NAME appears again. */
|
||||
}
|
||||
else
|
||||
++ep;
|
||||
}
|
||||
|
||||
UNLOCK;
|
||||
|
||||
|
||||
@@ -19,23 +19,62 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ucontext.h>
|
||||
#include <assert.h>
|
||||
#include <unwind.h>
|
||||
#include <dlfcn.h>
|
||||
#include <gnu/lib-names.h>
|
||||
|
||||
ucontext_t ucp;
|
||||
char st1[8192];
|
||||
char st1[16384];
|
||||
__thread int thr;
|
||||
|
||||
int somevar = -76;
|
||||
long othervar = -78L;
|
||||
|
||||
struct trace_arg
|
||||
{
|
||||
int cnt, size;
|
||||
};
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
backtrace_helper (struct _Unwind_Context *ctx, void *a)
|
||||
{
|
||||
struct trace_arg *arg = a;
|
||||
if (++arg->cnt == arg->size)
|
||||
return _URC_END_OF_STACK;
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
void
|
||||
cf (int i)
|
||||
{
|
||||
struct trace_arg arg = { .size = 100, .cnt = -1 };
|
||||
void *handle;
|
||||
_Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
|
||||
|
||||
if (i != othervar || thr != 94)
|
||||
{
|
||||
printf ("i %d thr %d\n", i, thr);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Test if callback function of _Unwind_Backtrace is not called infinitely
|
||||
times. See Bug 18508 or gcc bug "Bug 66303 - runtime.Caller() returns
|
||||
infinitely deep stack frames on s390x.".
|
||||
The go runtime calls backtrace_full() in
|
||||
<gcc-src>/libbacktrace/backtrace.c, which uses _Unwind_Backtrace(). */
|
||||
handle = dlopen (LIBGCC_S_SO, RTLD_LAZY);
|
||||
if (handle != NULL)
|
||||
{
|
||||
unwind_backtrace = dlsym (handle, "_Unwind_Backtrace");
|
||||
if (unwind_backtrace != NULL)
|
||||
{
|
||||
unwind_backtrace (backtrace_helper, &arg);
|
||||
assert (arg.cnt != -1 && arg.cnt < 100);
|
||||
}
|
||||
dlclose (handle);
|
||||
}
|
||||
|
||||
/* Since uc_link below has been set to NULL, setcontext is supposed to
|
||||
terminate the process normally after this function returns. */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/* Testcase checks, if setcontext(), swapcontext() restores signal-mask
|
||||
and if pending signals are delivered after those calls.
|
||||
Copyright (C) 2015 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
|
||||
volatile int global;
|
||||
volatile sig_atomic_t handlerCalled;
|
||||
|
||||
static void
|
||||
check (const char *funcName)
|
||||
{
|
||||
sigset_t set;
|
||||
|
||||
/* check if SIGUSR2 is unblocked after setcontext-call. */
|
||||
sigprocmask (SIG_BLOCK, NULL, &set);
|
||||
|
||||
if (sigismember (&set, SIGUSR2) != 0)
|
||||
{
|
||||
printf ("FAIL: SIGUSR2 is blocked after %s.\n", funcName);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (sigismember (&set, SIGUSR1) != 1)
|
||||
{
|
||||
printf ("FAIL: SIGUSR1 is not blocked after %s.\n", funcName);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
signalmask (int how, int signum)
|
||||
{
|
||||
sigset_t set;
|
||||
sigemptyset (&set);
|
||||
sigaddset (&set, signum);
|
||||
if (sigprocmask (how, &set, NULL) != 0)
|
||||
{
|
||||
printf ("FAIL: sigprocmaks (%d, %d, NULL): %m\n", how, signum);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
signalpending (int signum, const char *msg)
|
||||
{
|
||||
sigset_t set;
|
||||
sigemptyset (&set);
|
||||
if (sigpending (&set) != 0)
|
||||
{
|
||||
printf ("FAIL: sigpending: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
if (sigismember (&set, SIGUSR2) != 1)
|
||||
{
|
||||
printf ("FAIL: Signal %d is not pending %s\n", signum, msg);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handler (int __attribute__ ((unused)) signum)
|
||||
{
|
||||
handlerCalled ++;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
ucontext_t ctx, oldctx;
|
||||
struct sigaction action;
|
||||
pid_t pid;
|
||||
|
||||
pid = getpid ();
|
||||
|
||||
/* unblock SIGUSR2 */
|
||||
signalmask (SIG_UNBLOCK, SIGUSR2);
|
||||
|
||||
/* block SIGUSR1 */
|
||||
signalmask (SIG_BLOCK, SIGUSR1);
|
||||
|
||||
/* register handler for SIGUSR2 */
|
||||
action.sa_flags = 0;
|
||||
action.sa_handler = handler;
|
||||
sigemptyset (&action.sa_mask);
|
||||
sigaction (SIGUSR2, &action, NULL);
|
||||
|
||||
if (getcontext (&ctx) != 0)
|
||||
{
|
||||
printf ("FAIL: getcontext: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
global++;
|
||||
|
||||
if (global == 1)
|
||||
{
|
||||
puts ("after getcontext");
|
||||
|
||||
/* block SIGUSR2 */
|
||||
signalmask (SIG_BLOCK, SIGUSR2);
|
||||
|
||||
/* send SIGUSR2 to me */
|
||||
handlerCalled = 0;
|
||||
kill (pid, SIGUSR2);
|
||||
|
||||
/* was SIGUSR2 handler called? */
|
||||
if (handlerCalled != 0)
|
||||
{
|
||||
puts ("FAIL: signal handler was called, but signal was blocked.");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* is SIGUSR2 pending? */
|
||||
signalpending (SIGUSR2, "before setcontext");
|
||||
|
||||
/* SIGUSR2 will be unblocked by setcontext-call. */
|
||||
if (setcontext (&ctx) != 0)
|
||||
{
|
||||
printf ("FAIL: setcontext: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
else if (global == 2)
|
||||
{
|
||||
puts ("after setcontext");
|
||||
|
||||
/* check SIGUSR1/2 */
|
||||
check ("setcontext");
|
||||
|
||||
/* was SIGUSR2 handler called? */
|
||||
if (handlerCalled != 1)
|
||||
{
|
||||
puts ("FAIL: signal handler was not called after setcontext.");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* block SIGUSR2 */
|
||||
signalmask (SIG_BLOCK, SIGUSR2);
|
||||
|
||||
/* send SIGUSR2 to me */
|
||||
handlerCalled = 0;
|
||||
kill (pid, SIGUSR2);
|
||||
|
||||
/* was SIGUSR2 handler called? */
|
||||
if (handlerCalled != 0)
|
||||
{
|
||||
puts ("FAIL: signal handler was called, but signal was blocked.");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* is SIGUSR2 pending? */
|
||||
signalpending (SIGUSR2, "before swapcontext");
|
||||
|
||||
if (swapcontext (&oldctx, &ctx) != 0)
|
||||
{
|
||||
printf ("FAIL: swapcontext: %m\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("after returned from swapcontext");
|
||||
|
||||
if (global != 3)
|
||||
{
|
||||
puts ("FAIL: returned from swapcontext without ctx-context called.");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("test succeeded");
|
||||
return 0;
|
||||
}
|
||||
else if ( global != 3 )
|
||||
{
|
||||
puts ("FAIL: 'global' not incremented three times");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
puts ("after swapcontext");
|
||||
/* check SIGUSR1/2 */
|
||||
check ("swapcontext");
|
||||
|
||||
/* was SIGUSR2 handler called? */
|
||||
if (handlerCalled != 1)
|
||||
{
|
||||
puts ("FAIL: signal handler was not called after swapcontext.");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* check sigmask in old context of swapcontext-call */
|
||||
if (sigismember (&oldctx.uc_sigmask, SIGUSR2) != 1)
|
||||
{
|
||||
puts ("FAIL: SIGUSR2 is not blocked in oldctx.uc_sigmask.");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (sigismember (&oldctx.uc_sigmask, SIGUSR1) != 1)
|
||||
{
|
||||
puts ("FAIL: SIGUSR1 is not blocked in oldctx.uc_sigmaks.");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* change to old context, which was gathered by swapcontext() call. */
|
||||
setcontext (&oldctx);
|
||||
|
||||
puts ("FAIL: returned from setcontext (&oldctx)");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -36,8 +36,8 @@ ENTRY(__mempcpy_chk)
|
||||
cmpl $0, KIND_OFFSET+__cpu_features@GOTOFF(%ebx)
|
||||
jne 1f
|
||||
call __init_cpu_features
|
||||
leal __mempcpy_chk_ia32@GOTOFF(%ebx), %eax
|
||||
1: testl $bit_SSE2, CPUID_OFFSET+index_SSE2+__cpu_features@GOTOFF(%ebx)
|
||||
1: leal __mempcpy_chk_ia32@GOTOFF(%ebx), %eax
|
||||
testl $bit_SSE2, CPUID_OFFSET+index_SSE2+__cpu_features@GOTOFF(%ebx)
|
||||
jz 2f
|
||||
leal __mempcpy_chk_sse2_unaligned@GOTOFF(%ebx), %eax
|
||||
testl $bit_Fast_Unaligned_Load, FEATURE_OFFSET+index_Fast_Unaligned_Load+__cpu_features@GOTOFF(%ebx)
|
||||
|
||||
@@ -82,9 +82,7 @@ typedef uintmax_t uatomic_max_t;
|
||||
(__sync_synchronize (), __sync_lock_test_and_set (mem, value))
|
||||
|
||||
#define atomic_exchange_and_add(mem, value) \
|
||||
({ __typeof (*mem) __result; \
|
||||
__result = __sync_fetch_and_add ((mem), (int) (value)); \
|
||||
__result; })
|
||||
__sync_fetch_and_add ((mem), (value))
|
||||
|
||||
#define atomic_decrement_if_positive(mem) \
|
||||
({ __typeof (*mem) __oldval, __val; \
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
# error "Never include <bits/link.h> directly; use <link.h> instead."
|
||||
#endif
|
||||
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
typedef char La_s390_vr[16];
|
||||
#endif
|
||||
|
||||
#if __ELF_NATIVE_CLASS == 32
|
||||
|
||||
@@ -32,6 +35,16 @@ typedef struct La_s390_32_regs
|
||||
uint32_t lr_r6;
|
||||
double lr_fp0;
|
||||
double lr_fp2;
|
||||
# if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
La_s390_vr lr_v24;
|
||||
La_s390_vr lr_v25;
|
||||
La_s390_vr lr_v26;
|
||||
La_s390_vr lr_v27;
|
||||
La_s390_vr lr_v28;
|
||||
La_s390_vr lr_v29;
|
||||
La_s390_vr lr_v30;
|
||||
La_s390_vr lr_v31;
|
||||
# endif
|
||||
} La_s390_32_regs;
|
||||
|
||||
/* Return values for calls from PLT on s390-32. */
|
||||
@@ -40,6 +53,9 @@ typedef struct La_s390_32_retval
|
||||
uint32_t lrv_r2;
|
||||
uint32_t lrv_r3;
|
||||
double lrv_fp0;
|
||||
# if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
La_s390_vr lrv_v24;
|
||||
# endif
|
||||
} La_s390_32_retval;
|
||||
|
||||
|
||||
@@ -77,6 +93,16 @@ typedef struct La_s390_64_regs
|
||||
double lr_fp2;
|
||||
double lr_fp4;
|
||||
double lr_fp6;
|
||||
# if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
La_s390_vr lr_v24;
|
||||
La_s390_vr lr_v25;
|
||||
La_s390_vr lr_v26;
|
||||
La_s390_vr lr_v27;
|
||||
La_s390_vr lr_v28;
|
||||
La_s390_vr lr_v29;
|
||||
La_s390_vr lr_v30;
|
||||
La_s390_vr lr_v31;
|
||||
# endif
|
||||
} La_s390_64_regs;
|
||||
|
||||
/* Return values for calls from PLT on s390-64. */
|
||||
@@ -84,6 +110,9 @@ typedef struct La_s390_64_retval
|
||||
{
|
||||
uint64_t lrv_r2;
|
||||
double lrv_fp0;
|
||||
# if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
La_s390_vr lrv_v24;
|
||||
# endif
|
||||
} La_s390_64_retval;
|
||||
|
||||
|
||||
|
||||
Vendored
+41
@@ -104,5 +104,46 @@ if test "$enable_lock_elision" = yes && test "$libc_cv_gcc_builtin_tbegin" = no
|
||||
critic_missing="$critic_missing The used GCC has no support for __builtin_tbegin, which is needed for lock-elision on target S390."
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 vector instruction support" >&5
|
||||
$as_echo_n "checking for S390 vector instruction support... " >&6; }
|
||||
if ${libc_cv_asm_s390_vx+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat > conftest.c <<\EOF
|
||||
void testvecinsn ()
|
||||
{
|
||||
__asm__ (".machine \"z13\" \n\t"
|
||||
".machinemode \"zarch_nohighgprs\" \n\t"
|
||||
"vistrbs %%v16,%%v17 \n\t"
|
||||
"locghie %%r1,0" : :);
|
||||
}
|
||||
EOF
|
||||
if { ac_try='${CC-cc} --shared conftest.c -o conftest.o &> /dev/null'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; } ;
|
||||
then
|
||||
libc_cv_asm_s390_vx=yes
|
||||
else
|
||||
libc_cv_asm_s390_vx=no
|
||||
fi
|
||||
rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_vx" >&5
|
||||
$as_echo "$libc_cv_asm_s390_vx" >&6; }
|
||||
|
||||
if test "$libc_cv_asm_s390_vx" = yes ;
|
||||
then
|
||||
$as_echo "#define HAVE_S390_VX_ASM_SUPPORT 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Use binutils with vector-support in order to use optimized implementations." >&5
|
||||
$as_echo "$as_me: WARNING: Use binutils with vector-support in order to use optimized implementations." >&2;}
|
||||
fi
|
||||
|
||||
|
||||
test -n "$critic_missing" && as_fn_error $? "
|
||||
*** $critic_missing" "$LINENO" 5
|
||||
|
||||
@@ -36,5 +36,34 @@ if test "$enable_lock_elision" = yes && test "$libc_cv_gcc_builtin_tbegin" = no
|
||||
critic_missing="$critic_missing The used GCC has no support for __builtin_tbegin, which is needed for lock-elision on target S390."
|
||||
fi
|
||||
|
||||
|
||||
AC_CACHE_CHECK(for S390 vector instruction support, libc_cv_asm_s390_vx, [dnl
|
||||
cat > conftest.c <<\EOF
|
||||
void testvecinsn ()
|
||||
{
|
||||
__asm__ (".machine \"z13\" \n\t"
|
||||
".machinemode \"zarch_nohighgprs\" \n\t"
|
||||
"vistrbs %%v16,%%v17 \n\t"
|
||||
"locghie %%r1,0" : :);
|
||||
}
|
||||
EOF
|
||||
dnl
|
||||
dnl test, if assembler supports S390 vector instructions
|
||||
if AC_TRY_COMMAND([${CC-cc} --shared conftest.c -o conftest.o &> /dev/null]) ;
|
||||
then
|
||||
libc_cv_asm_s390_vx=yes
|
||||
else
|
||||
libc_cv_asm_s390_vx=no
|
||||
fi
|
||||
rm -f conftest* ])
|
||||
|
||||
if test "$libc_cv_asm_s390_vx" = yes ;
|
||||
then
|
||||
AC_DEFINE(HAVE_S390_VX_ASM_SUPPORT)
|
||||
else
|
||||
AC_MSG_WARN([Use binutils with vector-support in order to use optimized implementations.])
|
||||
fi
|
||||
|
||||
|
||||
test -n "$critic_missing" && AC_MSG_ERROR([
|
||||
*** $critic_missing])
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
#if !defined PROCINFO_DECL && defined SHARED
|
||||
._dl_s390_cap_flags
|
||||
#else
|
||||
PROCINFO_CLASS const char _dl_s390_cap_flags[11][9]
|
||||
PROCINFO_CLASS const char _dl_s390_cap_flags[12][9]
|
||||
#endif
|
||||
#ifndef PROCINFO_DECL
|
||||
= {
|
||||
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", "highgprs", "te"
|
||||
"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", "highgprs", "te", "vx"
|
||||
}
|
||||
#endif
|
||||
#if !defined SHARED || defined PROCINFO_DECL
|
||||
@@ -62,11 +62,11 @@ PROCINFO_CLASS const char _dl_s390_cap_flags[11][9]
|
||||
#if !defined PROCINFO_DECL && defined SHARED
|
||||
._dl_s390_platforms
|
||||
#else
|
||||
PROCINFO_CLASS const char _dl_s390_platforms[7][7]
|
||||
PROCINFO_CLASS const char _dl_s390_platforms[8][7]
|
||||
#endif
|
||||
#ifndef PROCINFO_DECL
|
||||
= {
|
||||
"g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12"
|
||||
"g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13"
|
||||
}
|
||||
#endif
|
||||
#if !defined SHARED || defined PROCINFO_DECL
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
#define _DL_PROCINFO_H 1
|
||||
#include <ldsodefs.h>
|
||||
|
||||
#define _DL_HWCAP_COUNT 10
|
||||
#define _DL_HWCAP_COUNT 12
|
||||
|
||||
#define _DL_PLATFORMS_COUNT 5
|
||||
#define _DL_PLATFORMS_COUNT 8
|
||||
|
||||
/* The kernel provides up to 32 capability bits with elf_hwcap. */
|
||||
#define _DL_FIRST_PLATFORM 32
|
||||
@@ -50,6 +50,7 @@ enum
|
||||
HWCAP_S390_ETF3EH = 1 << 8,
|
||||
HWCAP_S390_HIGH_GPRS = 1 << 9,
|
||||
HWCAP_S390_TE = 1 << 10,
|
||||
HWCAP_S390_VX = 1 << 11,
|
||||
};
|
||||
|
||||
#define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \
|
||||
|
||||
@@ -89,6 +89,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
{
|
||||
extern void _dl_runtime_resolve (Elf32_Word);
|
||||
extern void _dl_runtime_profile (Elf32_Word);
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
extern void _dl_runtime_resolve_vx (Elf32_Word);
|
||||
extern void _dl_runtime_profile_vx (Elf32_Word);
|
||||
#endif
|
||||
|
||||
|
||||
if (l->l_info[DT_JMPREL] && lazy)
|
||||
{
|
||||
@@ -116,7 +121,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
end in this function. */
|
||||
if (__glibc_unlikely (profile))
|
||||
{
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
if (GLRO(dl_hwcap) & HWCAP_S390_VX)
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_profile_vx;
|
||||
else
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_profile;
|
||||
#else
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_profile;
|
||||
#endif
|
||||
|
||||
if (GLRO(dl_profile) != NULL
|
||||
&& _dl_name_match_p (GLRO(dl_profile), l))
|
||||
@@ -125,9 +137,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
GL(dl_profile_map) = l;
|
||||
}
|
||||
else
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
{
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
if (GLRO(dl_hwcap) & HWCAP_S390_VX)
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_resolve_vx;
|
||||
else
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
#else
|
||||
got[2] = (Elf32_Addr) &_dl_runtime_resolve;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return lazy;
|
||||
|
||||
@@ -16,130 +16,18 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* This code is used in dl-runtime.c to call the `fixup' function
|
||||
and then redirect to the address it returns. */
|
||||
|
||||
/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
|
||||
* with the following linkage:
|
||||
* r2 - r6 : parameter registers
|
||||
* f0, f2 : floating point parameter registers
|
||||
* 24(r15), 28(r15) : PLT arguments PLT1, PLT2
|
||||
* 96(r15) : additional stack parameters
|
||||
* The normal clobber rules for function calls apply:
|
||||
* r0 - r5 : call clobbered
|
||||
* r6 - r13 : call saved
|
||||
* r14 : return address (call clobbered)
|
||||
* r15 : stack pointer (call saved)
|
||||
* f4, f6 : call saved
|
||||
* f0 - f3, f5, f7 - f15 : call clobbered
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
.text
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_resolve:
|
||||
stm %r2,%r5,32(%r15) # save registers
|
||||
st %r14,8(%r15)
|
||||
cfi_offset (r14, -88)
|
||||
lr %r0,%r15 # create stack frame
|
||||
ahi %r15,-96
|
||||
cfi_adjust_cfa_offset (96)
|
||||
st 0,0(%r15)
|
||||
lm %r2,%r3,120(%r15) # load args saved by PLT
|
||||
basr %r1,0
|
||||
0: l %r14,1f-0b(%r1)
|
||||
bas %r14,0(%r14,%r1) # call resolver
|
||||
lr %r1,%r2 # function addr returned in r2
|
||||
ahi %r15,96 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-96)
|
||||
l %r14,8(15) # restore registers
|
||||
lm %r2,%r5,32(%r15)
|
||||
br %r1
|
||||
1: .long _dl_fixup - 0b
|
||||
cfi_endproc
|
||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||||
/* Create variant of _dl_runtime_resolve/profile for machines before z13.
|
||||
No vector registers are saved/restored. */
|
||||
#include <dl-trampoline.h>
|
||||
|
||||
|
||||
#ifndef PROF
|
||||
.globl _dl_runtime_profile
|
||||
.type _dl_runtime_profile, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_profile:
|
||||
stm %r2,%r6,32(%r15) # save registers
|
||||
std %f0,56(%r15)
|
||||
std %f2,64(%r15)
|
||||
st %r6,8(%r15)
|
||||
st %r12,12(%r15)
|
||||
st %r14,16(%r15)
|
||||
cfi_offset (r6, -64)
|
||||
cfi_offset (f0, -40)
|
||||
cfi_offset (f2, -32)
|
||||
cfi_offset (r12, -84)
|
||||
cfi_offset (r14, -80)
|
||||
lr %r12,%r15 # create stack frame
|
||||
cfi_def_cfa_register (12)
|
||||
ahi %r15,-96
|
||||
st %r12,0(%r15)
|
||||
lm %r2,%r3,24(%r12) # load arguments saved by PLT
|
||||
lr %r4,%r14 # return address as third parameter
|
||||
basr %r1,0
|
||||
0: l %r14,6f-0b(%r1)
|
||||
la %r5,32(%r12) # pointer to struct La_s390_32_regs
|
||||
la %r6,20(%r12) # long int * framesize
|
||||
bas %r14,0(%r14,%r1) # call resolver
|
||||
lr %r1,%r2 # function addr returned in r2
|
||||
icm %r0,15,20(%r12) # load & test framesize
|
||||
jnm 2f
|
||||
|
||||
lm %r2,%r6,32(%r12)
|
||||
ld %f0,56(%r12)
|
||||
ld %f2,64(%r12)
|
||||
lr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
l %r14,16(%r15) # restore registers
|
||||
l %r12,12(%r15)
|
||||
br %r1 # tail-call to the resolved function
|
||||
|
||||
cfi_def_cfa_register (12)
|
||||
2: jz 4f # framesize == 0 ?
|
||||
ahi %r0,7 # align framesize to 8
|
||||
lhi %r2,-8
|
||||
nr %r0,%r2
|
||||
slr %r15,%r0 # make room for framesize bytes
|
||||
st %r12,0(%r15)
|
||||
la %r2,96(%r15)
|
||||
la %r3,96(%r12)
|
||||
srl %r0,3
|
||||
3: mvc 0(8,%r2),0(%r3) # copy additional parameters
|
||||
la %r2,8(%r2)
|
||||
la %r3,8(%r3)
|
||||
brct %r0,3b
|
||||
4: lm %r2,%r6,32(%r12) # load register parameters
|
||||
ld %f0,56(%r12)
|
||||
ld %f2,64(%r12)
|
||||
basr %r14,%r1 # call resolved function
|
||||
stm %r2,%r3,72(%r12)
|
||||
std %f0,80(%r12)
|
||||
lm %r2,%r3,24(%r12) # load arguments saved by PLT
|
||||
basr %r1,0
|
||||
5: l %r14,7f-5b(%r1)
|
||||
la %r4,32(%r12) # pointer to struct La_s390_32_regs
|
||||
la %r5,72(%r12) # pointer to struct La_s390_32_retval
|
||||
basr %r14,%r1 # call _dl_call_pltexit
|
||||
|
||||
lr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
l %r14,16(%r15) # restore registers
|
||||
l %r12,12(%r15)
|
||||
br %r14
|
||||
|
||||
6: .long _dl_profile_fixup - 0b
|
||||
7: .long _dl_call_pltexit - 5b
|
||||
cfi_endproc
|
||||
.size _dl_runtime_profile, .-_dl_runtime_profile
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
/* Create variant of _dl_runtime_resolve/profile for z13 and newer.
|
||||
The vector registers are saved/restored, too.*/
|
||||
# define _dl_runtime_resolve _dl_runtime_resolve_vx
|
||||
# define _dl_runtime_profile _dl_runtime_profile_vx
|
||||
# define RESTORE_VRS
|
||||
# include <dl-trampoline.h>
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/* PLT trampolines. s390 version.
|
||||
Copyright (C) 2016 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/>. */
|
||||
|
||||
/* This code is used in dl-runtime.c to call the `fixup' function
|
||||
and then redirect to the address it returns. */
|
||||
|
||||
/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
|
||||
* with the following linkage:
|
||||
* r2 - r6 : parameter registers
|
||||
* f0, f2 : floating point parameter registers
|
||||
* v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers
|
||||
* 24(r15), 28(r15) : PLT arguments PLT1, PLT2
|
||||
* 96(r15) : additional stack parameters
|
||||
* The normal clobber rules for function calls apply:
|
||||
* r0 - r5 : call clobbered
|
||||
* r6 - r13 : call saved
|
||||
* r14 : return address (call clobbered)
|
||||
* r15 : stack pointer (call saved)
|
||||
* f4, f6 : call saved
|
||||
* f0 - f3, f5, f7 - f15 : call clobbered
|
||||
* v0 - v3, v5, v7 - v15 : bytes 0-7 overlap with fprs: call clobbered
|
||||
bytes 8-15: call clobbered
|
||||
* v4, v6 : bytes 0-7 overlap with f4, f6: call saved
|
||||
bytes 8-15: call clobbered
|
||||
* v16 - v31 : call clobbered
|
||||
*/
|
||||
|
||||
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_resolve:
|
||||
stm %r2,%r5,32(%r15) # save registers
|
||||
cfi_offset (r2, -64)
|
||||
cfi_offset (r3, -60)
|
||||
cfi_offset (r4, -56)
|
||||
cfi_offset (r5, -52)
|
||||
std %f0,56(%r15)
|
||||
cfi_offset (f0, -40)
|
||||
std %f2,64(%r15)
|
||||
cfi_offset (f2, -32)
|
||||
st %r14,8(%r15)
|
||||
cfi_offset (r14, -88)
|
||||
lr %r0,%r15
|
||||
lm %r2,%r3,24(%r15) # load args saved by PLT
|
||||
#ifdef RESTORE_VRS
|
||||
ahi %r15,-224 # create stack frame
|
||||
cfi_adjust_cfa_offset (224)
|
||||
.machine push
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
vstm %v24,%v31,96(%r15) # store call-clobbered vr arguments
|
||||
cfi_offset (v24, -224)
|
||||
cfi_offset (v25, -208)
|
||||
cfi_offset (v26, -192)
|
||||
cfi_offset (v27, -176)
|
||||
cfi_offset (v28, -160)
|
||||
cfi_offset (v29, -144)
|
||||
cfi_offset (v30, -128)
|
||||
cfi_offset (v31, -112)
|
||||
.machine pop
|
||||
#else
|
||||
ahi %r15,-96 # create stack frame
|
||||
cfi_adjust_cfa_offset (96)
|
||||
#endif
|
||||
st %r0,0(%r15) # write backchain
|
||||
basr %r1,0
|
||||
0: l %r14,1f-0b(%r1)
|
||||
bas %r14,0(%r14,%r1) # call _dl_fixup
|
||||
lr %r1,%r2 # function addr returned in r2
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
vlm %v24,%v31,96(%r15) # restore vector registers
|
||||
.machine pop
|
||||
ahi %r15,224 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-224)
|
||||
#else
|
||||
ahi %r15,96 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-96)
|
||||
#endif
|
||||
l %r14,8(15) # restore registers
|
||||
ld %f0,56(%r15)
|
||||
ld %f2,64(%r15)
|
||||
lm %r2,%r5,32(%r15)
|
||||
br %r1
|
||||
1: .long _dl_fixup - 0b
|
||||
cfi_endproc
|
||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||||
|
||||
|
||||
#ifndef PROF
|
||||
.globl _dl_runtime_profile
|
||||
.type _dl_runtime_profile, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_profile:
|
||||
st %r12,12(%r15) # r12 is used as backup of r15
|
||||
cfi_offset (r12, -84)
|
||||
st %r14,16(%r15)
|
||||
cfi_offset (r14, -80)
|
||||
lr %r12,%r15 # backup stack pointer
|
||||
cfi_def_cfa_register (12)
|
||||
ahi %r15,-264 # create stack frame:
|
||||
# 96 + sizeof(La_s390_32_regs)
|
||||
st %r12,0(%r15) # save backchain
|
||||
|
||||
stm %r2,%r6,96(%r15) # save registers
|
||||
cfi_offset (r2, -264) # + r6 needed as arg for
|
||||
cfi_offset (r3, -260) # _dl_profile_fixup
|
||||
cfi_offset (r4, -256)
|
||||
cfi_offset (r5, -252)
|
||||
cfi_offset (r6, -248)
|
||||
std %f0,120(%r15)
|
||||
cfi_offset (f0, -240)
|
||||
std %f2,128(%r15)
|
||||
cfi_offset (f2, -232)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
vstm %v24,%v31,136(%r15) # store call-clobbered vr arguments
|
||||
cfi_offset (v24, -224)
|
||||
cfi_offset (v25, -208)
|
||||
cfi_offset (v26, -192)
|
||||
cfi_offset (v27, -176)
|
||||
cfi_offset (v28, -160)
|
||||
cfi_offset (v29, -144)
|
||||
cfi_offset (v30, -128)
|
||||
cfi_offset (v31, -112)
|
||||
.machine pop
|
||||
#endif
|
||||
|
||||
lm %r2,%r3,24(%r12) # load arguments saved by PLT
|
||||
lr %r4,%r14 # return address as third parameter
|
||||
basr %r1,0
|
||||
0: l %r14,6f-0b(%r1)
|
||||
la %r5,96(%r15) # pointer to struct La_s390_32_regs
|
||||
la %r6,20(%r12) # long int * framesize
|
||||
bas %r14,0(%r14,%r1) # call resolver
|
||||
lr %r1,%r2 # function addr returned in r2
|
||||
ld %f0,120(%r15) # restore call-clobbered arg fprs
|
||||
ld %f2,128(%r15)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
.machinemode "zarch_nohighgprs"
|
||||
vlm %v24,%v31,136(%r15) # restore call-clobbered arg vrs
|
||||
.machine pop
|
||||
#endif
|
||||
icm %r0,15,20(%r12) # load & test framesize
|
||||
jnm 2f
|
||||
|
||||
lm %r2,%r6,96(%r15) # framesize < 0 means no pltexit call
|
||||
# so we can do a tail call without
|
||||
# copying the arg overflow area
|
||||
lr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
l %r14,16(%r15) # restore registers
|
||||
l %r12,12(%r15)
|
||||
br %r1 # tail-call to the resolved function
|
||||
|
||||
cfi_def_cfa_register (12)
|
||||
2: la %r4,96(%r15) # pointer to struct La_s390_32_regs
|
||||
st %r4,32(%r12)
|
||||
jz 4f # framesize == 0 ?
|
||||
ahi %r0,7 # align framesize to 8
|
||||
lhi %r2,-8
|
||||
nr %r0,%r2
|
||||
slr %r15,%r0 # make room for framesize bytes
|
||||
st %r12,0(%r15) # save backchain
|
||||
la %r2,96(%r15)
|
||||
la %r3,96(%r12)
|
||||
srl %r0,3
|
||||
3: mvc 0(8,%r2),0(%r3) # copy additional parameters
|
||||
la %r2,8(%r2)
|
||||
la %r3,8(%r3)
|
||||
brct %r0,3b
|
||||
4: lm %r2,%r6,0(%r4) # load register parameters
|
||||
basr %r14,%r1 # call resolved function
|
||||
stm %r2,%r3,40(%r12) # store return values r2, r3, f0
|
||||
std %f0,48(%r12) # to struct La_s390_32_retval
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vst %v24,56(%r12) # store return value v24
|
||||
.machine pop
|
||||
#endif
|
||||
lm %r2,%r4,24(%r12) # r2, r3: load arguments saved by PLT
|
||||
# r4: pointer to struct La_s390_32_regs
|
||||
basr %r1,0
|
||||
5: l %r14,7f-5b(%r1)
|
||||
la %r5,40(%r12) # pointer to struct La_s390_32_retval
|
||||
bas %r14,0(%r14,%r1) # call _dl_call_pltexit
|
||||
|
||||
lr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
l %r14,16(%r15) # restore registers
|
||||
l %r12,12(%r15)
|
||||
lm %r2,%r3,40(%r15) # restore return values
|
||||
ld %f0,48(%r15)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vl %v24,56(%r15) # restore return value v24
|
||||
.machine pop
|
||||
#endif
|
||||
br %r14
|
||||
|
||||
6: .long _dl_profile_fixup - 0b
|
||||
7: .long _dl_call_pltexit - 5b
|
||||
cfi_endproc
|
||||
.size _dl_runtime_profile, .-_dl_runtime_profile
|
||||
#endif
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
#include <link.h>
|
||||
#include <sysdeps/s390/dl-procinfo.h>
|
||||
#include <dl-irel.h>
|
||||
|
||||
#define ELF_MACHINE_IRELATIVE R_390_IRELATIVE
|
||||
@@ -78,6 +79,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
{
|
||||
extern void _dl_runtime_resolve (Elf64_Word);
|
||||
extern void _dl_runtime_profile (Elf64_Word);
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
extern void _dl_runtime_resolve_vx (Elf64_Word);
|
||||
extern void _dl_runtime_profile_vx (Elf64_Word);
|
||||
#endif
|
||||
|
||||
if (l->l_info[DT_JMPREL] && lazy)
|
||||
{
|
||||
@@ -105,7 +110,14 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
end in this function. */
|
||||
if (__glibc_unlikely (profile))
|
||||
{
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
if (GLRO(dl_hwcap) & HWCAP_S390_VX)
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_profile_vx;
|
||||
else
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_profile;
|
||||
#else
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_profile;
|
||||
#endif
|
||||
|
||||
if (GLRO(dl_profile) != NULL
|
||||
&& _dl_name_match_p (GLRO(dl_profile), l))
|
||||
@@ -114,9 +126,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
GL(dl_profile_map) = l;
|
||||
}
|
||||
else
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_resolve;
|
||||
{
|
||||
/* This function will get called to fix up the GOT entry indicated by
|
||||
the offset on the stack, and then jump to the resolved address. */
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
if (GLRO(dl_hwcap) & HWCAP_S390_VX)
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_resolve_vx;
|
||||
else
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_resolve;
|
||||
#else
|
||||
got[2] = (Elf64_Addr) &_dl_runtime_resolve;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return lazy;
|
||||
|
||||
@@ -16,126 +16,18 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
|
||||
* with the following linkage:
|
||||
* r2 - r6 : parameter registers
|
||||
* f0, f2, f4, f6 : floating point parameter registers
|
||||
* 48(r15), 56(r15) : PLT arguments PLT1, PLT2
|
||||
* 160(r15) : additional stack parameters
|
||||
* The normal clobber rules for function calls apply:
|
||||
* r0 - r5 : call clobbered
|
||||
* r6 - r13 : call saved
|
||||
* r14 : return address (call clobbered)
|
||||
* r15 : stack pointer (call saved)
|
||||
* f1, f3, f5, f7 : call saved
|
||||
* f0 - f3, f5, f7 - f15 : call clobbered
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
.text
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_resolve:
|
||||
stmg %r2,%r5,64(15) # save call-clobbered argument registers
|
||||
stg %r14,96(15)
|
||||
cfi_offset (r14, -64)
|
||||
lgr %r0,%r15
|
||||
aghi %r15,-160 # create stack frame
|
||||
cfi_adjust_cfa_offset (160)
|
||||
stg %r0,0(%r15) # write backchain
|
||||
lmg %r2,%r3,208(%r15)# load args saved by PLT
|
||||
brasl %r14,_dl_fixup # call fixup
|
||||
lgr %r1,%r2 # function addr returned in r2
|
||||
aghi %r15,160 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-160)
|
||||
lg %r14,96(15) # restore registers
|
||||
lmg %r2,%r5,64(15)
|
||||
br %r1
|
||||
cfi_endproc
|
||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||||
/* Create variant of _dl_runtime_resolve/profile for machines before z13.
|
||||
No vector registers are saved/restored. */
|
||||
#include <dl-trampoline.h>
|
||||
|
||||
|
||||
#ifndef PROF
|
||||
.globl _dl_runtime_profile
|
||||
.type _dl_runtime_profile, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_profile:
|
||||
stmg %r2,%r6,64(%r15) # save call-clobbered arg regs
|
||||
std %f0,104(%r15) # + r6 needed as arg for
|
||||
std %f2,112(%r15) # _dl_profile_fixup
|
||||
std %f4,120(%r15)
|
||||
std %f6,128(%r15)
|
||||
stg %r12,24(%r15) # r12 is used as backup of r15
|
||||
stg %r14,32(%r15)
|
||||
cfi_offset (r6, -96)
|
||||
cfi_offset (f0, -56)
|
||||
cfi_offset (f2, -48)
|
||||
cfi_offset (f4, -40)
|
||||
cfi_offset (f6, -32)
|
||||
cfi_offset (r12, -136)
|
||||
cfi_offset (r14, -128)
|
||||
lgr %r12,%r15 # backup stack pointer
|
||||
cfi_def_cfa_register (12)
|
||||
aghi %r15,-160 # create stack frame
|
||||
stg %r12,0(%r15) # save backchain
|
||||
lmg %r2,%r3,48(%r12) # load arguments saved by PLT
|
||||
lgr %r4,%r14 # return address as third parameter
|
||||
la %r5,64(%r12) # pointer to struct La_s390_32_regs
|
||||
la %r6,40(%r12) # long int * framesize
|
||||
brasl %r14,_dl_profile_fixup # call resolver
|
||||
lgr %r1,%r2 # function addr returned in r2
|
||||
lg %r0,40(%r12) # load framesize
|
||||
ltgr %r0,%r0
|
||||
jnm 1f
|
||||
|
||||
lmg %r2,%r6,64(%r12) # framesize < 0 means no pltexit call
|
||||
ld %f0,104(%r12) # so we can do a tail call without
|
||||
ld %f2,112(%r12) # copying the arg overflow area
|
||||
ld %f4,120(%r12)
|
||||
ld %f6,128(%r12)
|
||||
|
||||
lgr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
lg %r14,32(%r15) # restore registers
|
||||
lg %r12,24(%r15)
|
||||
br %r1 # tail-call to resolved function
|
||||
|
||||
cfi_def_cfa_register (12)
|
||||
1: jz 4f # framesize == 0 ?
|
||||
aghi %r0,7 # align framesize to 8
|
||||
nill %r0,0xfff8
|
||||
slgr %r15,%r0 # make room for framesize bytes
|
||||
stg %r12,0(%r15)
|
||||
la %r2,160(%r15)
|
||||
la %r3,160(%r12)
|
||||
srlg %r0,%r0,3
|
||||
3: mvc 0(8,%r2),0(%r3) # copy additional parameters
|
||||
la %r2,8(%r2)
|
||||
la %r3,8(%r3)
|
||||
brctg %r0,3b
|
||||
4: lmg %r2,%r6,64(%r12) # load register parameters
|
||||
ld %f0,104(%r12) # restore call-clobbered arg regs
|
||||
ld %f2,112(%r12)
|
||||
ld %f4,120(%r12)
|
||||
ld %f6,128(%r12)
|
||||
basr %r14,%r1 # call resolved function
|
||||
stg %r2,136(%r12)
|
||||
std %f0,144(%r12)
|
||||
lmg %r2,%r3,48(%r12) # load arguments saved by PLT
|
||||
la %r4,32(%r12) # pointer to struct La_s390_32_regs
|
||||
la %r5,72(%r12) # pointer to struct La_s390_32_retval
|
||||
brasl %r14,_dl_call_pltexit
|
||||
|
||||
lgr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
lg %r14,32(%r15) # restore registers
|
||||
lg %r12,24(%r15)
|
||||
br %r14
|
||||
|
||||
cfi_endproc
|
||||
.size _dl_runtime_profile, .-_dl_runtime_profile
|
||||
#if defined HAVE_S390_VX_ASM_SUPPORT
|
||||
/* Create variant of _dl_runtime_resolve/profile for z13 and newer.
|
||||
The vector registers are saved/restored, too.*/
|
||||
# define _dl_runtime_resolve _dl_runtime_resolve_vx
|
||||
# define _dl_runtime_profile _dl_runtime_profile_vx
|
||||
# define RESTORE_VRS
|
||||
# include <dl-trampoline.h>
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
/* PLT trampolines. s390x version.
|
||||
Copyright (C) 2016 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 PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
|
||||
* with the following linkage:
|
||||
* r2 - r6 : parameter registers
|
||||
* f0, f2, f4, f6 : floating point parameter registers
|
||||
* v24, v26, v28, v30, v25, v27, v29, v31 : vector parameter registers
|
||||
* 48(r15), 56(r15) : PLT arguments PLT1, PLT2
|
||||
* 160(r15) : additional stack parameters
|
||||
* The normal clobber rules for function calls apply:
|
||||
* r0 - r5 : call clobbered
|
||||
* r6 - r13 : call saved
|
||||
* r14 : return address (call clobbered)
|
||||
* r15 : stack pointer (call saved)
|
||||
* f0 - f7 : call clobbered
|
||||
* f8 - f15 : call saved
|
||||
* v0 - v7 : bytes 0-7 overlap with f0-f7: call clobbered
|
||||
bytes 8-15: call clobbered
|
||||
* v8 - v15 : bytes 0-7 overlap with f8-f15: call saved
|
||||
bytes 8-15: call clobbered
|
||||
* v16 - v31 : call clobbered
|
||||
*/
|
||||
|
||||
.globl _dl_runtime_resolve
|
||||
.type _dl_runtime_resolve, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_resolve:
|
||||
stmg %r2,%r5,64(%r15) # save call-clobbered argument registers
|
||||
cfi_offset (r2, -96)
|
||||
cfi_offset (r3, -88)
|
||||
cfi_offset (r4, -80)
|
||||
cfi_offset (r5, -72)
|
||||
std %f0,104(%r15)
|
||||
cfi_offset (f0, -56)
|
||||
std %f2,112(%r15)
|
||||
cfi_offset (f2, -48)
|
||||
std %f4,120(%r15)
|
||||
cfi_offset (f4, -40)
|
||||
std %f6,128(%r15)
|
||||
cfi_offset (f6, -32)
|
||||
stg %r14,96(15)
|
||||
cfi_offset (r14, -64)
|
||||
lmg %r2,%r3,48(%r15) # load args for fixup saved by PLT
|
||||
lgr %r0,%r15
|
||||
#ifdef RESTORE_VRS
|
||||
aghi %r15,-288 # create stack frame
|
||||
cfi_adjust_cfa_offset (288)
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vstm %v24,%v31,160(%r15)# store call-clobbered vector argument registers
|
||||
cfi_offset (v24, -288)
|
||||
cfi_offset (v25, -272)
|
||||
cfi_offset (v26, -256)
|
||||
cfi_offset (v27, -240)
|
||||
cfi_offset (v28, -224)
|
||||
cfi_offset (v29, -208)
|
||||
cfi_offset (v30, -192)
|
||||
cfi_offset (v31, -176)
|
||||
.machine pop
|
||||
#else
|
||||
aghi %r15,-160 # create stack frame
|
||||
cfi_adjust_cfa_offset (160)
|
||||
#endif
|
||||
stg %r0,0(%r15) # write backchain
|
||||
brasl %r14,_dl_fixup # call _dl_fixup
|
||||
lgr %r1,%r2 # function addr returned in r2
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vlm %v24,%v31,160(%r15)# restore vector registers
|
||||
.machine pop
|
||||
aghi %r15,288 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-288)
|
||||
#else
|
||||
aghi %r15,160 # remove stack frame
|
||||
cfi_adjust_cfa_offset (-160)
|
||||
#endif
|
||||
lg %r14,96(%r15) # restore registers
|
||||
ld %f0,104(%r15)
|
||||
ld %f2,112(%r15)
|
||||
ld %f4,120(%r15)
|
||||
ld %f6,128(%r15)
|
||||
lmg %r2,%r5,64(%r15)
|
||||
br %r1
|
||||
cfi_endproc
|
||||
.size _dl_runtime_resolve, .-_dl_runtime_resolve
|
||||
|
||||
|
||||
#ifndef PROF
|
||||
.globl _dl_runtime_profile
|
||||
.type _dl_runtime_profile, @function
|
||||
cfi_startproc
|
||||
.align 16
|
||||
_dl_runtime_profile:
|
||||
stg %r12,24(%r15) # r12 is used as backup of r15
|
||||
cfi_offset (r12, -136)
|
||||
stg %r14,32(%r15)
|
||||
cfi_offset (r14, -128)
|
||||
lgr %r12,%r15 # backup stack pointer
|
||||
cfi_def_cfa_register (12)
|
||||
aghi %r15,-360 # create stack frame:
|
||||
# 160 + sizeof(La_s390_64_regs)
|
||||
stg %r12,0(%r15) # save backchain
|
||||
|
||||
stmg %r2,%r6,160(%r15) # save call-clobbered arg regs
|
||||
cfi_offset (r2, -360) # + r6 needed as arg for
|
||||
cfi_offset (r3, -352) # _dl_profile_fixup
|
||||
cfi_offset (r4, -344)
|
||||
cfi_offset (r5, -336)
|
||||
cfi_offset (r6, -328)
|
||||
std %f0,200(%r15)
|
||||
cfi_offset (f0, -320)
|
||||
std %f2,208(%r15)
|
||||
cfi_offset (f2, -312)
|
||||
std %f4,216(%r15)
|
||||
cfi_offset (f4, -304)
|
||||
std %f6,224(%r15)
|
||||
cfi_offset (f6, -296)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vstm %v24,%v31,232(%r15) # store call-clobbered vector arguments
|
||||
cfi_offset (v24, -288)
|
||||
cfi_offset (v25, -272)
|
||||
cfi_offset (v26, -256)
|
||||
cfi_offset (v27, -240)
|
||||
cfi_offset (v28, -224)
|
||||
cfi_offset (v29, -208)
|
||||
cfi_offset (v30, -192)
|
||||
cfi_offset (v31, -176)
|
||||
.machine pop
|
||||
#endif
|
||||
lmg %r2,%r3,48(%r12) # load arguments saved by PLT
|
||||
lgr %r4,%r14 # return address as third parameter
|
||||
la %r5,160(%r15) # pointer to struct La_s390_64_regs
|
||||
la %r6,40(%r12) # long int * framesize
|
||||
brasl %r14,_dl_profile_fixup # call resolver
|
||||
lgr %r1,%r2 # function addr returned in r2
|
||||
ld %f0,200(%r15) # restore call-clobbered arg fprs
|
||||
ld %f2,208(%r15)
|
||||
ld %f4,216(%r15)
|
||||
ld %f6,224(%r15)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vlm %v24,%v31,232(%r15) # restore call-clobbered arg vrs
|
||||
.machine pop
|
||||
#endif
|
||||
lg %r0,40(%r12) # load framesize
|
||||
ltgr %r0,%r0
|
||||
jnm 1f
|
||||
|
||||
lmg %r2,%r6,160(%r15) # framesize < 0 means no pltexit call
|
||||
# so we can do a tail call without
|
||||
# copying the arg overflow area
|
||||
lgr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
lg %r14,32(%r15) # restore registers
|
||||
lg %r12,24(%r15)
|
||||
br %r1 # tail-call to resolved function
|
||||
|
||||
cfi_def_cfa_register (12)
|
||||
1: la %r4,160(%r15) # pointer to struct La_s390_64_regs
|
||||
stg %r4,64(%r12)
|
||||
jz 4f # framesize == 0 ?
|
||||
aghi %r0,7 # align framesize to 8
|
||||
nill %r0,0xfff8
|
||||
slgr %r15,%r0 # make room for framesize bytes
|
||||
stg %r12,0(%r15) # save backchain
|
||||
la %r2,160(%r15)
|
||||
la %r3,160(%r12)
|
||||
srlg %r0,%r0,3
|
||||
3: mvc 0(8,%r2),0(%r3) # copy additional parameters
|
||||
la %r2,8(%r2) # depending on framesize
|
||||
la %r3,8(%r3)
|
||||
brctg %r0,3b
|
||||
4: lmg %r2,%r6,0(%r4) # restore call-clobbered arg gprs
|
||||
basr %r14,%r1 # call resolved function
|
||||
stg %r2,72(%r12) # store return values r2, f0
|
||||
std %f0,80(%r12) # to struct La_s390_64_retval
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vst %v24,88(%r12) # store return value v24
|
||||
.machine pop
|
||||
#endif
|
||||
lmg %r2,%r4,48(%r12) # r2, r3: load arguments saved by PLT
|
||||
# r4: pointer to struct La_s390_64_regs
|
||||
la %r5,72(%r12) # pointer to struct La_s390_64_retval
|
||||
brasl %r14,_dl_call_pltexit
|
||||
|
||||
lgr %r15,%r12 # remove stack frame
|
||||
cfi_def_cfa_register (15)
|
||||
lg %r14,32(%r15) # restore registers
|
||||
lg %r12,24(%r15)
|
||||
lg %r2,72(%r15) # restore return values
|
||||
ld %f0,80(%r15)
|
||||
#ifdef RESTORE_VRS
|
||||
.machine push
|
||||
.machine "z13"
|
||||
vl %v24,88(%r15) # restore return value v24
|
||||
.machine pop
|
||||
#endif
|
||||
br %r14 # Jump back to caller
|
||||
|
||||
cfi_endproc
|
||||
.size _dl_runtime_profile, .-_dl_runtime_profile
|
||||
#endif
|
||||
@@ -35,3 +35,4 @@
|
||||
#define HWCAP_S390_ETF3EH 256
|
||||
#define HWCAP_S390_HIGH_GPRS 512
|
||||
#define HWCAP_S390_TE 1024
|
||||
#define HWCAP_S390_VX 2048
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
/* We do not want .eh_frame info so that __makecontext_ret stops unwinding
|
||||
if backtrace was called within a context created by makecontext. (There
|
||||
is also no .eh_frame info for _start or thread_start.) */
|
||||
#undef cfi_startproc
|
||||
#define cfi_startproc
|
||||
#undef cfi_endproc
|
||||
#define cfi_endproc
|
||||
|
||||
ENTRY(__makecontext_ret)
|
||||
basr %r14,%r7
|
||||
ltr %r8,%r8 /* Check whether uc_link is 0. */
|
||||
|
||||
@@ -34,7 +34,7 @@ ENTRY(__setcontext)
|
||||
lr %r1,%r2
|
||||
|
||||
/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize). */
|
||||
la %r2,SIG_BLOCK
|
||||
la %r2,SIG_SETMASK
|
||||
la %r3,SC_MASK(%r1)
|
||||
slr %r4,%r4
|
||||
lhi %r5,_NSIG8
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/* __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
|
||||
|
||||
Saves the machine context in oucp such that when it is activated,
|
||||
it appears as if __swapcontextt() returned again, restores the
|
||||
it appears as if __swapcontext() returned again, restores the
|
||||
machine context in ucp and thereby resumes execution in that
|
||||
context.
|
||||
|
||||
@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
|
||||
lr %r1,%r2
|
||||
lr %r0,%r3
|
||||
|
||||
/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask). */
|
||||
la %r2,SIG_BLOCK
|
||||
slr %r3,%r3
|
||||
la %r4,SC_MASK(%r1)
|
||||
lhi %r5,_NSIG8
|
||||
svc SYS_ify(rt_sigprocmask)
|
||||
|
||||
/* Store fpu context. */
|
||||
stfpc SC_FPC(%r1)
|
||||
std %f0,SC_FPRS(%r1)
|
||||
@@ -74,11 +67,12 @@ ENTRY(__swapcontext)
|
||||
/* Store general purpose registers. */
|
||||
stm %r0,%r15,SC_GPRS(%r1)
|
||||
|
||||
/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL). */
|
||||
la %r2,SIG_BLOCK
|
||||
/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
|
||||
sigsetsize). */
|
||||
la %r2,SIG_SETMASK
|
||||
lr %r5,%r0
|
||||
la %r3,SC_MASK(%r5)
|
||||
slr %r4,%r4
|
||||
la %r4,SC_MASK(%r1)
|
||||
lhi %r5,_NSIG8
|
||||
svc SYS_ify(rt_sigprocmask)
|
||||
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
/* We do not want .eh_frame info so that __makecontext_ret stops unwinding
|
||||
if backtrace was called within a context created by makecontext. (There
|
||||
is also no .eh_frame info for _start or thread_start.) */
|
||||
#undef cfi_startproc
|
||||
#define cfi_startproc
|
||||
#undef cfi_endproc
|
||||
#define cfi_endproc
|
||||
|
||||
ENTRY(__makecontext_ret)
|
||||
basr %r14,%r7
|
||||
ltgr %r8,%r8 /* Check whether uc_link is 0. */
|
||||
|
||||
@@ -34,7 +34,7 @@ ENTRY(__setcontext)
|
||||
lgr %r1,%r2
|
||||
|
||||
/* sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL). */
|
||||
la %r2,SIG_BLOCK
|
||||
la %r2,SIG_SETMASK
|
||||
la %r3,SC_MASK(%r1)
|
||||
slgr %r4,%r4
|
||||
lghi %r5,_NSIG8
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/* __swapcontext (ucontext_t *oucp, const ucontext_t *ucp)
|
||||
|
||||
Saves the machine context in oucp such that when it is activated,
|
||||
it appears as if __swapcontextt() returned again, restores the
|
||||
it appears as if __swapcontext() returned again, restores the
|
||||
machine context in ucp and thereby resumes execution in that
|
||||
context.
|
||||
|
||||
@@ -39,13 +39,6 @@ ENTRY(__swapcontext)
|
||||
lgr %r1,%r2
|
||||
lgr %r0,%r3
|
||||
|
||||
/* sigprocmask (SIG_BLOCK, NULL, &sc->sc_mask). */
|
||||
la %r2,SIG_BLOCK
|
||||
slgr %r3,%r3
|
||||
la %r4,SC_MASK(%r1)
|
||||
lghi %r5,_NSIG8
|
||||
svc SYS_ify(rt_sigprocmask)
|
||||
|
||||
/* Store fpu context. */
|
||||
stfpc SC_FPC(%r1)
|
||||
std %f0,SC_FPRS(%r1)
|
||||
@@ -74,12 +67,13 @@ ENTRY(__swapcontext)
|
||||
/* Store general purpose registers. */
|
||||
stmg %r0,%r15,SC_GPRS(%r1)
|
||||
|
||||
/* rt_sigprocmask (SIG_SETMASK, &sc->sc_mask, NULL, sigsetsize). */
|
||||
la %r2,SIG_BLOCK
|
||||
/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask,
|
||||
sigsetsize). */
|
||||
la %r2,SIG_SETMASK
|
||||
lgr %r5,%r0
|
||||
la %r3,SC_MASK(%r5)
|
||||
la %r4,SC_MASK(%r1)
|
||||
lghi %r5,_NSIG8
|
||||
slgr %r4,%r4
|
||||
svc SYS_ify(rt_sigprocmask)
|
||||
|
||||
/* Load fpu context. */
|
||||
|
||||
@@ -12,22 +12,3 @@ shmget - shmget i:iii __shmget shmget
|
||||
semop - semop i:ipi __semop semop
|
||||
semget - semget i:iii __semget semget
|
||||
semctl - semctl i:iiii __semctl semctl
|
||||
|
||||
# proper socket implementations:
|
||||
accept - accept Ci:iBN __libc_accept __accept accept
|
||||
bind - bind i:ipi __bind bind
|
||||
connect - connect Ci:ipi __libc_connect __connect connect
|
||||
getpeername - getpeername i:ipp __getpeername getpeername
|
||||
getsockname - getsockname i:ipp __getsockname getsockname
|
||||
getsockopt - getsockopt i:iiiBN __getsockopt getsockopt
|
||||
listen - listen i:ii __listen listen
|
||||
recv - recv Ci:ibni __libc_recv __recv recv
|
||||
recvfrom - recvfrom Ci:ibniBN __libc_recvfrom __recvfrom recvfrom
|
||||
recvmsg - recvmsg Ci:ipi __libc_recvmsg __recvmsg recvmsg
|
||||
send - send Ci:ibni __libc_send __send send
|
||||
sendmsg - sendmsg Ci:ipi __libc_sendmsg __sendmsg sendmsg
|
||||
sendto - sendto Ci:ibnibn __libc_sendto __sendto sendto
|
||||
setsockopt - setsockopt i:iiibn __setsockopt setsockopt
|
||||
shutdown - shutdown i:ii __shutdown shutdown
|
||||
socket - socket i:iii __socket socket
|
||||
socketpair - socketpair i:iiif __socketpair socketpair
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
# error "Never include <bits/sigaction.h> directly; use <signal.h> instead."
|
||||
#endif
|
||||
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
/* Structure describing the action to be taken when a signal arrives. */
|
||||
struct sigaction
|
||||
{
|
||||
@@ -43,7 +45,9 @@ struct sigaction
|
||||
__sigset_t sa_mask;
|
||||
|
||||
/* Special flags. */
|
||||
#if __WORDSIZE == 64
|
||||
int __glibc_reserved0;
|
||||
#endif
|
||||
int sa_flags;
|
||||
|
||||
/* Not used by Linux/Sparc yet. */
|
||||
|
||||
Vendored
+2
-2
@@ -117,7 +117,7 @@ rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_avx512" >&5
|
||||
$as_echo "$libc_cv_asm_avx512" >&6; }
|
||||
if test $libc_cv_asm_avx512 == yes; then
|
||||
if test $libc_cv_asm_avx512 = yes; then
|
||||
$as_echo "#define HAVE_AVX512_ASM_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
@@ -244,7 +244,7 @@ rm -f conftest*
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_mpx" >&5
|
||||
$as_echo "$libc_cv_asm_mpx" >&6; }
|
||||
if test $libc_cv_asm_mpx == yes; then
|
||||
if test $libc_cv_asm_mpx = yes; then
|
||||
$as_echo "#define HAVE_MPX_SUPPORT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
@@ -34,7 +34,7 @@ else
|
||||
libc_cv_asm_avx512=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
if test $libc_cv_asm_avx512 == yes; then
|
||||
if test $libc_cv_asm_avx512 = yes; then
|
||||
AC_DEFINE(HAVE_AVX512_ASM_SUPPORT)
|
||||
fi
|
||||
|
||||
@@ -86,7 +86,7 @@ else
|
||||
libc_cv_asm_mpx=no
|
||||
fi
|
||||
rm -f conftest*])
|
||||
if test $libc_cv_asm_mpx == yes; then
|
||||
if test $libc_cv_asm_mpx = yes; then
|
||||
AC_DEFINE(HAVE_MPX_SUPPORT)
|
||||
fi
|
||||
|
||||
|
||||
+13
-7
@@ -510,13 +510,17 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
|
||||
only a few elements. Dereference the pointers only if the format
|
||||
requires this. Then it is ok to fail if the pointers are invalid. */
|
||||
# define a_wkday \
|
||||
((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday))
|
||||
((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
|
||||
? "?" : _NL_CURRENT (LC_TIME, NLW(ABDAY_1) + tp->tm_wday)))
|
||||
# define f_wkday \
|
||||
((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday))
|
||||
((const CHAR_T *) (tp->tm_wday < 0 || tp->tm_wday > 6 \
|
||||
? "?" : _NL_CURRENT (LC_TIME, NLW(DAY_1) + tp->tm_wday)))
|
||||
# define a_month \
|
||||
((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon))
|
||||
((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
|
||||
? "?" : _NL_CURRENT (LC_TIME, NLW(ABMON_1) + tp->tm_mon)))
|
||||
# define f_month \
|
||||
((const CHAR_T *) _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon))
|
||||
((const CHAR_T *) (tp->tm_mon < 0 || tp->tm_mon > 11 \
|
||||
? "?" : _NL_CURRENT (LC_TIME, NLW(MON_1) + tp->tm_mon)))
|
||||
# define ampm \
|
||||
((const CHAR_T *) _NL_CURRENT (LC_TIME, tp->tm_hour > 11 \
|
||||
? NLW(PM_STR) : NLW(AM_STR)))
|
||||
@@ -526,8 +530,10 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
|
||||
# define ap_len STRLEN (ampm)
|
||||
#else
|
||||
# if !HAVE_STRFTIME
|
||||
# define f_wkday (weekday_name[tp->tm_wday])
|
||||
# define f_month (month_name[tp->tm_mon])
|
||||
# define f_wkday (tp->tm_wday < 0 || tp->tm_wday > 6 \
|
||||
? "?" : weekday_name[tp->tm_wday])
|
||||
# define f_month (tp->tm_mon < 0 || tp->tm_mon > 11 \
|
||||
? "?" : month_name[tp->tm_mon])
|
||||
# define a_wkday f_wkday
|
||||
# define a_month f_month
|
||||
# define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11))
|
||||
@@ -1321,7 +1327,7 @@ __strftime_internal (s, maxsize, format, tp, tzset_called ut_argument
|
||||
*tzset_called = true;
|
||||
}
|
||||
# endif
|
||||
zone = tzname[tp->tm_isdst];
|
||||
zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?";
|
||||
}
|
||||
#endif
|
||||
if (! zone)
|
||||
|
||||
+51
-1
@@ -4,6 +4,56 @@
|
||||
#include <time.h>
|
||||
|
||||
|
||||
static int
|
||||
do_bz18985 (void)
|
||||
{
|
||||
char buf[1000];
|
||||
struct tm ttm;
|
||||
int rc, ret = 0;
|
||||
|
||||
memset (&ttm, 1, sizeof (ttm));
|
||||
ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */
|
||||
rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
|
||||
|
||||
if (rc == 66)
|
||||
{
|
||||
const char expected[]
|
||||
= "? ? ? ? ? ? 16843009 16843009:16843009:16843009 16844909 +467836 ?";
|
||||
if (0 != strcmp (buf, expected))
|
||||
{
|
||||
printf ("expected:\n %s\ngot:\n %s\n", expected, buf);
|
||||
ret += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("expected 66, got %d\n", rc);
|
||||
ret += 1;
|
||||
}
|
||||
|
||||
/* Check negative values as well. */
|
||||
memset (&ttm, 0xFF, sizeof (ttm));
|
||||
ttm.tm_zone = NULL; /* Dereferenced directly if non-NULL. */
|
||||
rc = strftime (buf, sizeof (buf), "%a %A %b %B %c %z %Z", &ttm);
|
||||
|
||||
if (rc == 30)
|
||||
{
|
||||
const char expected[] = "? ? ? ? ? ? -1 -1:-1:-1 1899 ";
|
||||
if (0 != strcmp (buf, expected))
|
||||
{
|
||||
printf ("expected:\n %s\ngot:\n %s\n", expected, buf);
|
||||
ret += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("expected 30, got %d\n", rc);
|
||||
ret += 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
const char *fmt;
|
||||
@@ -104,7 +154,7 @@ do_test (void)
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result + do_bz18985 ();
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
|
||||
Reference in New Issue
Block a user