mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-10 23:58:28 +08:00
Compare commits
56
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
402fa33cf0 | ||
|
|
2f012b713a | ||
|
|
2a709bcc0f | ||
|
|
a3195f733d | ||
|
|
ee91916b21 | ||
|
|
59a8bb61d7 | ||
|
|
1199943f07 | ||
|
|
b286c83dcb | ||
|
|
066bfd4625 | ||
|
|
3ffe1a9e55 | ||
|
|
209606141f | ||
|
|
3f749c2e7b | ||
|
|
1fd66a522e | ||
|
|
78b80a2276 | ||
|
|
e012eafca4 | ||
|
|
258e9043d8 | ||
|
|
306df6aa95 | ||
|
|
24772ea8cd | ||
|
|
29c2af3215 | ||
|
|
21ccef1540 | ||
|
|
afd269312e | ||
|
|
5b4ed59d74 | ||
|
|
23f12d0a81 | ||
|
|
b84ee767b4 | ||
|
|
65402b410d | ||
|
|
fb3642bf3c | ||
|
|
b4f19537f9 | ||
|
|
0f74aed2de | ||
|
|
d717c3fd0e | ||
|
|
68baefe5b8 | ||
|
|
bf6a73fb38 | ||
|
|
5c4ac50148 | ||
|
|
cdb1aad567 | ||
|
|
6ff3aac23c | ||
|
|
adf228f91c | ||
|
|
ca6a9ce615 | ||
|
|
0acbb93ebb | ||
|
|
9ab172e7f8 | ||
|
|
969fb008f4 | ||
|
|
6f9b62ae84 | ||
|
|
078cee5a65 | ||
|
|
077b6d91d3 | ||
|
|
0a1a932b01 | ||
|
|
7bc2cafecb | ||
|
|
ebe01981ad | ||
|
|
8175e9150a | ||
|
|
6fef29c020 | ||
|
|
98b9c13e1a | ||
|
|
ca167a22d2 | ||
|
|
016376847a | ||
|
|
e973063f44 | ||
|
|
57dbdc6499 | ||
|
|
e6a8de48ec | ||
|
|
de1e604b49 | ||
|
|
9eef0eeeff | ||
|
|
b49a9c12c0 |
@@ -1,3 +1,14 @@
|
||||
2016-03-07 Hongjiu Zhang <noctuorare@gmail.com>
|
||||
|
||||
* elf/sln.c (makesymlink): Change struct stat to stat64, and lstat
|
||||
to lstat64.
|
||||
|
||||
2015-08-05 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* nptl/allocatestack.c (allocate_stack): Move stacktop decl down to
|
||||
bottom and under _STACK_GROWS_DOWN. Move the stacktop assignment
|
||||
in there too.
|
||||
|
||||
2015-08-05 Carlos O'Donell <carlos@systemhalted.org>
|
||||
|
||||
* version.h (RELEASE): Set to "stable".
|
||||
|
||||
+2
-2
@@ -648,7 +648,7 @@ comma = ,
|
||||
sysdep-library-path = \
|
||||
$(subst $(empty) ,:,$(strip $(patsubst -Wl$(comma)-rpath-link=%, %,\
|
||||
$(filter -Wl$(comma)-rpath-link=%,\
|
||||
$(sysdep-LDFLAGS)))))
|
||||
$(sysdep-LDFLAGS)))) $(common-objpfx)/dlfcn)
|
||||
# $(run-via-rtld-prefix) is a command that, when prepended to the name
|
||||
# of a program built with the newly built library, produces a command
|
||||
# that, executed on the host for which the library is built, runs that
|
||||
@@ -1096,7 +1096,7 @@ all-subdirs = csu assert ctype locale intl catgets math setjmp signal \
|
||||
stdlib stdio-common libio malloc string wcsmbs time dirent \
|
||||
grp pwd posix io termios resource misc socket sysvipc gmon \
|
||||
gnulib iconv iconvdata wctype manual shadow gshadow po argp \
|
||||
crypt localedata timezone rt conform debug mathvec \
|
||||
crypt localedata rt conform debug mathvec \
|
||||
$(add-on-subdirs) dlfcn elf
|
||||
|
||||
ifndef avoid-generated
|
||||
|
||||
@@ -105,6 +105,7 @@ install-symbolic-link: subdir_install
|
||||
rm -f $(symbolic-link-list)
|
||||
|
||||
install:
|
||||
dont-bother-with-destdir:
|
||||
-test ! -x $(elf-objpfx)ldconfig || LC_ALL=C \
|
||||
$(elf-objpfx)ldconfig $(addprefix -r ,$(install_root)) \
|
||||
$(slibdir) $(libdir)
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,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
|
||||
|
||||
|
||||
@@ -7309,7 +7309,7 @@ cat > conftest.c <<EOF
|
||||
# error PIC is default.
|
||||
#endif
|
||||
EOF
|
||||
if eval "${CC-cc} -S conftest.c 2>&5 1>&5"; then
|
||||
if eval "${CC-cc} -fno-PIE -S conftest.c 2>&5 1>&5"; then
|
||||
libc_cv_pic_default=no
|
||||
fi
|
||||
rm -f conftest.*
|
||||
|
||||
+1
-1
@@ -2069,7 +2069,7 @@ cat > conftest.c <<EOF
|
||||
# error PIC is default.
|
||||
#endif
|
||||
EOF
|
||||
if eval "${CC-cc} -S conftest.c 2>&AS_MESSAGE_LOG_FD 1>&AS_MESSAGE_LOG_FD"; then
|
||||
if eval "${CC-cc} -fno-PIE -S conftest.c 2>&AS_MESSAGE_LOG_FD 1>&AS_MESSAGE_LOG_FD"; then
|
||||
libc_cv_pic_default=no
|
||||
fi
|
||||
rm -f conftest.*])
|
||||
|
||||
+10
-3
@@ -148,7 +148,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \
|
||||
tst-nodelete) \
|
||||
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
|
||||
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened
|
||||
tst-ptrguard1 tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
|
||||
tst-nodelete2
|
||||
# reldep9
|
||||
ifeq ($(build-hardcoded-path-in-tests),yes)
|
||||
tests += tst-dlopen-aout
|
||||
@@ -218,7 +219,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
tst-initorder2d \
|
||||
tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
|
||||
tst-array5dep tst-null-argv-lib \
|
||||
tst-tlsalign-lib tst-nodelete-opened-lib
|
||||
tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod
|
||||
ifeq (yes,$(have-protected-data))
|
||||
modules-names += tst-protected1moda tst-protected1modb
|
||||
tests += tst-protected1a tst-protected1b
|
||||
@@ -449,7 +450,7 @@ CFLAGS-ldconfig.c = $(SYSCONF-FLAGS) -D'LIBDIR="$(libdir)"' \
|
||||
libof-ldconfig = ldconfig
|
||||
CFLAGS-dl-cache.c = $(SYSCONF-FLAGS)
|
||||
CFLAGS-cache.c = $(SYSCONF-FLAGS)
|
||||
CFLAGS-rtld.c = $(SYSCONF-FLAGS)
|
||||
CFLAGS-rtld.c += $(SYSCONF-FLAGS)
|
||||
|
||||
cpp-srcs-left := $(all-rtld-routines:=.os)
|
||||
lib := rtld
|
||||
@@ -594,6 +595,7 @@ tst-auditmod9b.so-no-z-defs = yes
|
||||
tst-nodelete-uniquemod.so-no-z-defs = yes
|
||||
tst-nodelete-rtldmod.so-no-z-defs = yes
|
||||
tst-nodelete-zmod.so-no-z-defs = yes
|
||||
tst-nodelete2mod.so-no-z-defs = yes
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
# Build all the modules even when not actually running test programs.
|
||||
@@ -1164,6 +1166,11 @@ $(objpfx)tst-nodelete.out: $(objpfx)tst-nodelete-uniquemod.so \
|
||||
LDFLAGS-tst-nodelete = -rdynamic
|
||||
LDFLAGS-tst-nodelete-zmod.so = -Wl,--enable-new-dtags,-z,nodelete
|
||||
|
||||
$(objpfx)tst-nodelete2: $(libdl)
|
||||
$(objpfx)tst-nodelete2.out: $(objpfx)tst-nodelete2mod.so
|
||||
|
||||
LDFLAGS-tst-nodelete2 = -rdynamic
|
||||
|
||||
$(objpfx)tst-initorder-cmp.out: tst-initorder.exp $(objpfx)tst-initorder.out
|
||||
cmp $^ > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
+8
-7
@@ -144,6 +144,14 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
char done[nloaded];
|
||||
struct link_map *maps[nloaded];
|
||||
|
||||
/* Clear DF_1_NODELETE to force object deletion. We don't need to touch
|
||||
l_tls_dtor_count because forced object deletion only happens when an
|
||||
error occurs during object load. Destructor registration for TLS
|
||||
non-POD objects should not have happened till then for this
|
||||
object. */
|
||||
if (force)
|
||||
map->l_flags_1 &= ~DF_1_NODELETE;
|
||||
|
||||
/* Run over the list and assign indexes to the link maps and enter
|
||||
them into the MAPS array. */
|
||||
int idx = 0;
|
||||
@@ -153,13 +161,6 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
maps[idx] = l;
|
||||
++idx;
|
||||
|
||||
/* Clear DF_1_NODELETE to force object deletion. We don't need to touch
|
||||
l_tls_dtor_count because forced object deletion only happens when an
|
||||
error occurs during object load. Destructor registration for TLS
|
||||
non-POD objects should not have happened till then for this
|
||||
object. */
|
||||
if (force)
|
||||
l->l_flags_1 &= ~DF_1_NODELETE;
|
||||
}
|
||||
assert (idx == nloaded);
|
||||
|
||||
|
||||
+19
-2
@@ -1016,6 +1016,18 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||
#ifdef SHARED
|
||||
if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK)
|
||||
{
|
||||
/* ELF_RTYPE_CLASS_XXX must match RTYPE_CLASS_XXX used by prelink with
|
||||
LD_TRACE_PRELINKING. */
|
||||
#define RTYPE_CLASS_VALID 8
|
||||
#define RTYPE_CLASS_PLT (8|1)
|
||||
#define RTYPE_CLASS_COPY (8|2)
|
||||
#define RTYPE_CLASS_TLS (8|4)
|
||||
#if ELF_RTYPE_CLASS_PLT != 0 && ELF_RTYPE_CLASS_PLT != 1
|
||||
# error ELF_RTYPE_CLASS_PLT must be 0 or 1!
|
||||
#endif
|
||||
#if ELF_RTYPE_CLASS_COPY != 0 && ELF_RTYPE_CLASS_COPY != 2
|
||||
# error ELF_RTYPE_CLASS_COPY must be 0 or 2!
|
||||
#endif
|
||||
int conflict = 0;
|
||||
struct sym_val val = { NULL, NULL };
|
||||
|
||||
@@ -1071,12 +1083,17 @@ _dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
|
||||
|
||||
if (value->s)
|
||||
{
|
||||
/* Keep only ELF_RTYPE_CLASS_PLT and ELF_RTYPE_CLASS_COPY
|
||||
bits since since prelink only uses them. */
|
||||
type_class &= ELF_RTYPE_CLASS_PLT | ELF_RTYPE_CLASS_COPY;
|
||||
if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
|
||||
== STT_TLS))
|
||||
type_class = 4;
|
||||
/* Clear the RTYPE_CLASS_VALID bit in RTYPE_CLASS_TLS. */
|
||||
type_class = RTYPE_CLASS_TLS & ~RTYPE_CLASS_VALID;
|
||||
else if (__glibc_unlikely (ELFW(ST_TYPE) (value->s->st_info)
|
||||
== STT_GNU_IFUNC))
|
||||
type_class |= 8;
|
||||
/* Set the RTYPE_CLASS_VALID bit. */
|
||||
type_class |= RTYPE_CLASS_VALID;
|
||||
}
|
||||
|
||||
if (conflict
|
||||
|
||||
@@ -91,7 +91,6 @@ static struct link_map _dl_main_map =
|
||||
.l_scope = _dl_main_map.l_scope_mem,
|
||||
.l_local_scope = { &_dl_main_map.l_searchlist },
|
||||
.l_used = 1,
|
||||
.l_flags_1 = DF_1_NODEFLIB,
|
||||
.l_tls_offset = NO_TLS_OFFSET,
|
||||
.l_serial = 1,
|
||||
};
|
||||
|
||||
+4
-11
@@ -162,7 +162,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
|
||||
._dl_hwcap_mask = HWCAP_IMPORTANT,
|
||||
._dl_lazy = 1,
|
||||
._dl_fpu_control = _FPU_DEFAULT,
|
||||
._dl_pointer_guard = 1,
|
||||
._dl_pagesize = EXEC_PAGESIZE,
|
||||
._dl_inhibit_cache = 0,
|
||||
|
||||
@@ -709,15 +708,12 @@ security_init (void)
|
||||
#endif
|
||||
|
||||
/* Set up the pointer guard as well, if necessary. */
|
||||
if (GLRO(dl_pointer_guard))
|
||||
{
|
||||
uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
|
||||
stack_chk_guard);
|
||||
uintptr_t pointer_chk_guard
|
||||
= _dl_setup_pointer_guard (_dl_random, stack_chk_guard);
|
||||
#ifdef THREAD_SET_POINTER_GUARD
|
||||
THREAD_SET_POINTER_GUARD (pointer_chk_guard);
|
||||
THREAD_SET_POINTER_GUARD (pointer_chk_guard);
|
||||
#endif
|
||||
__pointer_chk_guard_local = pointer_chk_guard;
|
||||
}
|
||||
__pointer_chk_guard_local = pointer_chk_guard;
|
||||
|
||||
/* We do not need the _dl_random value anymore. The less
|
||||
information we leave behind, the better, so clear the
|
||||
@@ -2471,9 +2467,6 @@ process_envvars (enum mode *modep)
|
||||
GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (memcmp (envline, "POINTER_GUARD", 13) == 0)
|
||||
GLRO(dl_pointer_guard) = envline[14] != '0';
|
||||
break;
|
||||
|
||||
case 14:
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#include "../dlfcn/dlfcn.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gnu/lib-names.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
printf ("\nOpening pthread library.\n");
|
||||
void *pthread = dlopen (LIBPTHREAD_SO, RTLD_LAZY);
|
||||
|
||||
/* This is a test for correct DF_1_NODELETE clearing when dlopen failure
|
||||
happens. We should clear DF_1_NODELETE for failed library only, because
|
||||
doing this for others (e.g. libpthread) might cause them to be unloaded,
|
||||
that may lead to some global references (e.g. __rtld_lock_unlock) to be
|
||||
broken. The dlopen should fail because of undefined symbols in shared
|
||||
library, that cause DF_1_NODELETE to be cleared. For libpthread, this
|
||||
flag should be set, because if not, SIGSEGV will happen in dlclose. */
|
||||
if (dlopen ("tst-nodelete2mod.so", RTLD_NOW) != NULL)
|
||||
{
|
||||
printf ("Unique symbols test failed\n");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
if (pthread)
|
||||
dlclose (pthread);
|
||||
|
||||
if (result == 0)
|
||||
printf ("SUCCESS\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
@@ -1,6 +1,7 @@
|
||||
/* Undefined symbol. */
|
||||
extern int not_exist (void);
|
||||
|
||||
int foo (void)
|
||||
{
|
||||
return not_exist ();
|
||||
return not_exist ();
|
||||
}
|
||||
@@ -31,7 +31,7 @@ temp2=$codir/iconvdata/iconv-test.yyy
|
||||
trap "rm -f $temp1 $temp2" 1 2 3 15
|
||||
|
||||
# We have to have some directories in the library path.
|
||||
LIBPATH=$codir:$codir/iconvdata
|
||||
LIBPATH=$codir:$codir/iconvdata:$codir/dlfcn
|
||||
|
||||
# How the start the iconv(1) program.
|
||||
ICONV='$codir/elf/ld.so --library-path $LIBPATH --inhibit-rpath ${from}.so \
|
||||
|
||||
+20
-1
@@ -144,7 +144,7 @@ test_ftello (void)
|
||||
int
|
||||
do_test (int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
int ret, fd2;
|
||||
struct stat64 statbuf;
|
||||
|
||||
ret = lseek64 (fd, TWO_GB+100, SEEK_SET);
|
||||
@@ -195,6 +195,25 @@ do_test (int argc, char *argv[])
|
||||
error (EXIT_FAILURE, 0, "stat reported size %lld instead of %lld.",
|
||||
(long long int) statbuf.st_size, (TWO_GB + 100 + 5));
|
||||
|
||||
fd2 = openat64 (AT_FDCWD, name, O_RDWR);
|
||||
if (fd2 == -1)
|
||||
{
|
||||
if (errno == ENOSYS)
|
||||
{
|
||||
/* Silently ignore this test. */
|
||||
error (0, 0, "openat64 is not supported");
|
||||
}
|
||||
else
|
||||
error (EXIT_FAILURE, errno, "openat64 failed to open big file");
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = close (fd2);
|
||||
|
||||
if (ret == -1)
|
||||
error (EXIT_FAILURE, errno, "error closing file");
|
||||
}
|
||||
|
||||
test_ftello ();
|
||||
|
||||
return 0;
|
||||
|
||||
+1
-3
@@ -144,8 +144,6 @@ const struct __locale_data _nl_C_LC_COLLATE attribute_hidden =
|
||||
/* _NL_COLLATE_COLLSEQWC */
|
||||
{ .string = (const char *) collseqwc },
|
||||
/* _NL_COLLATE_CODESET */
|
||||
{ .string = _nl_C_codeset },
|
||||
/* _NL_COLLATE_ENCODING_TYPE */
|
||||
{ .word = __cet_8bit }
|
||||
{ .string = _nl_C_codeset }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,7 +58,6 @@ DEFINE_CATEGORY
|
||||
DEFINE_ELEMENT (_NL_COLLATE_COLLSEQMB, "collate-collseqmb", std, wstring)
|
||||
DEFINE_ELEMENT (_NL_COLLATE_COLLSEQWC, "collate-collseqwc", std, wstring)
|
||||
DEFINE_ELEMENT (_NL_COLLATE_CODESET, "collate-codeset", std, string)
|
||||
DEFINE_ELEMENT (_NL_COLLATE_ENCODING_TYPE, "collate-encoding-type", std, word)
|
||||
), NO_POSTLOAD)
|
||||
|
||||
|
||||
|
||||
@@ -255,7 +255,6 @@ enum
|
||||
_NL_COLLATE_COLLSEQMB,
|
||||
_NL_COLLATE_COLLSEQWC,
|
||||
_NL_COLLATE_CODESET,
|
||||
_NL_COLLATE_ENCODING_TYPE,
|
||||
_NL_NUM_LC_COLLATE,
|
||||
|
||||
/* LC_CTYPE category: character classification.
|
||||
|
||||
+4
-3
@@ -121,9 +121,10 @@ _nl_intern_locale_data (int category, const void *data, size_t datasize)
|
||||
switch (category)
|
||||
{
|
||||
#define CATTEST(cat) \
|
||||
case LC_##cat: \
|
||||
assert (cnt < (sizeof (_nl_value_type_LC_##cat) \
|
||||
/ sizeof (_nl_value_type_LC_##cat[0]))); \
|
||||
case LC_##cat: \
|
||||
if (cnt >= (sizeof (_nl_value_type_LC_##cat) \
|
||||
/ sizeof (_nl_value_type_LC_##cat[0]))) \
|
||||
goto puntdata; \
|
||||
break
|
||||
CATTEST (NUMERIC);
|
||||
CATTEST (TIME);
|
||||
|
||||
@@ -110,14 +110,6 @@ enum coll_sort_rule
|
||||
sort_mask
|
||||
};
|
||||
|
||||
/* Collation encoding type. */
|
||||
enum collation_encoding_type
|
||||
{
|
||||
__cet_other,
|
||||
__cet_8bit,
|
||||
__cet_utf8
|
||||
};
|
||||
|
||||
/* We can map the types of the entries into a few categories. */
|
||||
enum value_type
|
||||
{
|
||||
|
||||
@@ -204,6 +204,42 @@ CONCAT(TABLE,_iterate) (struct TABLE *t,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* GCC ATM seems to do a poor job with pointers to nested functions passed
|
||||
to inlined functions. Help it a little bit with this hack. */
|
||||
#define wchead_table_iterate(tp, fn) \
|
||||
do \
|
||||
{ \
|
||||
struct wchead_table *t = (tp); \
|
||||
uint32_t index1; \
|
||||
for (index1 = 0; index1 < t->level1_size; index1++) \
|
||||
{ \
|
||||
uint32_t lookup1 = t->level1[index1]; \
|
||||
if (lookup1 != ((uint32_t) ~0)) \
|
||||
{ \
|
||||
uint32_t lookup1_shifted = lookup1 << t->q; \
|
||||
uint32_t index2; \
|
||||
for (index2 = 0; index2 < (1 << t->q); index2++) \
|
||||
{ \
|
||||
uint32_t lookup2 = t->level2[index2 + lookup1_shifted]; \
|
||||
if (lookup2 != ((uint32_t) ~0)) \
|
||||
{ \
|
||||
uint32_t lookup2_shifted = lookup2 << t->p; \
|
||||
uint32_t index3; \
|
||||
for (index3 = 0; index3 < (1 << t->p); index3++) \
|
||||
{ \
|
||||
struct element_t *lookup3 \
|
||||
= t->level3[index3 + lookup2_shifted]; \
|
||||
if (lookup3 != NULL) \
|
||||
fn ((((index1 << t->q) + index2) << t->p) + index3, \
|
||||
lookup3); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NO_ADD_LOCALE
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "linereader.h"
|
||||
#include "locfile.h"
|
||||
#include "elem-hash.h"
|
||||
#include "../localeinfo.h"
|
||||
|
||||
/* Uncomment the following line in the production version. */
|
||||
/* #define NDEBUG 1 */
|
||||
@@ -2131,8 +2130,6 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
/* The words have to be handled specially. */
|
||||
if (idx == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB))
|
||||
add_locale_uint32 (&file, 0);
|
||||
else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE))
|
||||
add_locale_uint32 (&file, __cet_other);
|
||||
else
|
||||
add_locale_empty (&file);
|
||||
}
|
||||
@@ -2496,12 +2493,6 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
|
||||
add_locale_raw_data (&file, collate->mbseqorder, 256);
|
||||
add_locale_collseq_table (&file, &collate->wcseqorder);
|
||||
add_locale_string (&file, charmap->code_set_name);
|
||||
if (strcmp (charmap->code_set_name, "UTF-8") == 0)
|
||||
add_locale_uint32 (&file, __cet_utf8);
|
||||
else if (charmap->mb_cur_max == 1)
|
||||
add_locale_uint32 (&file, __cet_8bit);
|
||||
else
|
||||
add_locale_uint32 (&file, __cet_other);
|
||||
write_locale_data (output_path, LC_COLLATE, "LC_COLLATE", &file);
|
||||
|
||||
obstack_free (&weightpool, NULL);
|
||||
|
||||
@@ -172,6 +172,8 @@ include ../Rules
|
||||
|
||||
.PHONY: install subdir_install install-data
|
||||
install-data subdir_install: install
|
||||
# libm-err.texi generation requires perl.
|
||||
ifneq ($(PERL),no)
|
||||
ifneq ($(strip $(MAKEINFO)),:)
|
||||
install: $(inst_infodir)/libc.info
|
||||
@if $(SHELL) -c '$(INSTALL_INFO) --version' >/dev/null 2>&1; then \
|
||||
@@ -179,6 +181,7 @@ install: $(inst_infodir)/libc.info
|
||||
$(INSTALL_INFO) --info-dir=$(inst_infodir) $(inst_infodir)/libc.info;\
|
||||
else : ; fi
|
||||
endif
|
||||
endif
|
||||
# Catchall implicit rule for other installation targets from the parent.
|
||||
install-%: ;
|
||||
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ $(inst_libdir)/libm.so: $(common-objpfx)format.lds \
|
||||
(echo '/* GNU ld script'; echo '*/';\
|
||||
cat $<; \
|
||||
echo 'GROUP ( $(slibdir)/libm.so$(libm.so-version) ' \
|
||||
'AS_NEEDED ( $(slibdir)/libmvec.so$(libmvec.so-version) ) )' \
|
||||
'AS_NEEDED ( $(libdir)/libmvec_nonshared.a $(slibdir)/libmvec.so$(libmvec.so-version) ) )' \
|
||||
) > $@
|
||||
endif
|
||||
|
||||
|
||||
+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,75 @@
|
||||
/* 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>
|
||||
|
||||
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)
|
||||
{
|
||||
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';
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
#if !defined NOFILE && defined OPEN_MAX
|
||||
# define NOFILE OPEN_MAX
|
||||
#endif
|
||||
#if !defined MAXHOSTNAMELEN && defined HOST_NAME_MAX
|
||||
# define MAXHOSTNAMELEN HOST_NAME_MAX
|
||||
#endif
|
||||
#ifndef NCARGS
|
||||
# ifdef ARG_MAX
|
||||
# define NCARGS ARG_MAX
|
||||
|
||||
@@ -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;
|
||||
|
||||
+23
-14
@@ -353,7 +353,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
struct pthread *pd;
|
||||
size_t size;
|
||||
size_t pagesize_m1 = __getpagesize () - 1;
|
||||
void *stacktop;
|
||||
|
||||
assert (powerof2 (pagesize_m1 + 1));
|
||||
assert (TCB_ALIGNMENT >= STACK_ALIGN);
|
||||
@@ -373,6 +372,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
|
||||
{
|
||||
uintptr_t adj;
|
||||
char *stackaddr = (char *) attr->stackaddr;
|
||||
|
||||
/* Assume the same layout as the _STACK_GROWS_DOWN case, with struct
|
||||
pthread at the top of the stack block. Later we adjust the guard
|
||||
location and stack address to match the _STACK_GROWS_UP case. */
|
||||
if (_STACK_GROWS_UP)
|
||||
stackaddr += attr->stacksize;
|
||||
|
||||
/* If the user also specified the size of the stack make sure it
|
||||
is large enough. */
|
||||
@@ -382,11 +388,11 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
|
||||
/* Adjust stack size for alignment of the TLS block. */
|
||||
#if TLS_TCB_AT_TP
|
||||
adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
|
||||
adj = ((uintptr_t) stackaddr - TLS_TCB_SIZE)
|
||||
& __static_tls_align_m1;
|
||||
assert (size > adj + TLS_TCB_SIZE);
|
||||
#elif TLS_DTV_AT_TP
|
||||
adj = ((uintptr_t) attr->stackaddr - __static_tls_size)
|
||||
adj = ((uintptr_t) stackaddr - __static_tls_size)
|
||||
& __static_tls_align_m1;
|
||||
assert (size > adj);
|
||||
#endif
|
||||
@@ -396,10 +402,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
the stack. It is the user's responsibility to do this if it
|
||||
is wanted. */
|
||||
#if TLS_TCB_AT_TP
|
||||
pd = (struct pthread *) ((uintptr_t) attr->stackaddr
|
||||
pd = (struct pthread *) ((uintptr_t) stackaddr
|
||||
- TLS_TCB_SIZE - adj);
|
||||
#elif TLS_DTV_AT_TP
|
||||
pd = (struct pthread *) (((uintptr_t) attr->stackaddr
|
||||
pd = (struct pthread *) (((uintptr_t) stackaddr
|
||||
- __static_tls_size - adj)
|
||||
- TLS_PRE_TCB_SIZE);
|
||||
#endif
|
||||
@@ -411,7 +417,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
pd->specific[0] = pd->specific_1stblock;
|
||||
|
||||
/* Remember the stack-related values. */
|
||||
pd->stackblock = (char *) attr->stackaddr - size;
|
||||
pd->stackblock = (char *) stackaddr - size;
|
||||
pd->stackblock_size = size;
|
||||
|
||||
/* This is a user-provided stack. It will not be queued in the
|
||||
@@ -635,7 +641,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
|
||||
#elif _STACK_GROWS_DOWN
|
||||
char *guard = mem;
|
||||
# elif _STACK_GROWS_UP
|
||||
#elif _STACK_GROWS_UP
|
||||
char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1);
|
||||
#endif
|
||||
if (mprotect (guard, guardsize, PROT_NONE) != 0)
|
||||
@@ -717,21 +723,24 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
|
||||
/* We place the thread descriptor at the end of the stack. */
|
||||
*pdp = pd;
|
||||
|
||||
#if TLS_TCB_AT_TP
|
||||
#if _STACK_GROWS_DOWN
|
||||
void *stacktop;
|
||||
|
||||
# if TLS_TCB_AT_TP
|
||||
/* The stack begins before the TCB and the static TLS block. */
|
||||
stacktop = ((char *) (pd + 1) - __static_tls_size);
|
||||
#elif TLS_DTV_AT_TP
|
||||
# elif TLS_DTV_AT_TP
|
||||
stacktop = (char *) (pd - 1);
|
||||
#endif
|
||||
# endif
|
||||
|
||||
#ifdef NEED_SEPARATE_REGISTER_STACK
|
||||
# ifdef NEED_SEPARATE_REGISTER_STACK
|
||||
*stack = pd->stackblock;
|
||||
*stacksize = stacktop - *stack;
|
||||
#elif _STACK_GROWS_DOWN
|
||||
# else
|
||||
*stack = stacktop;
|
||||
#elif _STACK_GROWS_UP
|
||||
# endif
|
||||
#else
|
||||
*stack = pd->stackblock;
|
||||
assert (*stack > 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
+16
-3
@@ -428,12 +428,25 @@ START_THREAD_DEFN
|
||||
#ifdef _STACK_GROWS_DOWN
|
||||
char *sp = CURRENT_STACK_FRAME;
|
||||
size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1;
|
||||
#else
|
||||
# error "to do"
|
||||
#endif
|
||||
assert (freesize < pd->stackblock_size);
|
||||
if (freesize > PTHREAD_STACK_MIN)
|
||||
__madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
|
||||
#else
|
||||
/* Page aligned start of memory to free (higher than or equal
|
||||
to current sp plus the minimum stack size). */
|
||||
void *freeblock = (void*)((size_t)(CURRENT_STACK_FRAME
|
||||
+ PTHREAD_STACK_MIN
|
||||
+ pagesize_m1)
|
||||
& ~pagesize_m1);
|
||||
char *free_end = (char *) (((uintptr_t) pd - pd->guardsize) & ~pagesize_m1);
|
||||
/* Is there any space to free? */
|
||||
if (free_end > (char *)freeblock)
|
||||
{
|
||||
size_t freesize = (size_t)(free_end - (char *)freeblock);
|
||||
assert (freesize < pd->stackblock_size);
|
||||
__madvise (freeblock, freesize, MADV_DONTNEED);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the thread is detached free the TCB. */
|
||||
if (IS_DETACHED (pd))
|
||||
|
||||
@@ -60,7 +60,11 @@ pthread_getattr_np (thread_id, attr)
|
||||
if (__glibc_likely (thread->stackblock != NULL))
|
||||
{
|
||||
iattr->stacksize = thread->stackblock_size;
|
||||
#if _STACK_GROWS_DOWN
|
||||
iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
|
||||
#else
|
||||
iattr->stackaddr = (char *) thread->stackblock;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -105,7 +109,9 @@ pthread_getattr_np (thread_id, attr)
|
||||
|
||||
char *line = NULL;
|
||||
size_t linelen = 0;
|
||||
#if _STACK_GROWS_DOWN
|
||||
uintptr_t last_to = 0;
|
||||
#endif
|
||||
|
||||
while (! feof_unlocked (fp))
|
||||
{
|
||||
@@ -129,17 +135,24 @@ pthread_getattr_np (thread_id, attr)
|
||||
stack extension request. */
|
||||
iattr->stacksize = (iattr->stacksize
|
||||
& -(intptr_t) GLRO(dl_pagesize));
|
||||
|
||||
#if _STACK_GROWS_DOWN
|
||||
/* The limit might be too high. */
|
||||
if ((size_t) iattr->stacksize
|
||||
> (size_t) iattr->stackaddr - last_to)
|
||||
iattr->stacksize = (size_t) iattr->stackaddr - last_to;
|
||||
|
||||
#else
|
||||
/* The limit might be too high. */
|
||||
if ((size_t) iattr->stacksize
|
||||
> to - (size_t) iattr->stackaddr)
|
||||
iattr->stacksize = to - (size_t) iattr->stackaddr;
|
||||
#endif
|
||||
/* We succeed and no need to look further. */
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
#if _STACK_GROWS_DOWN
|
||||
last_to = to;
|
||||
#endif
|
||||
}
|
||||
|
||||
free (line);
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ run_program_env=$1; shift
|
||||
logfile=$common_objpfx/nptl/tst-tls6.out
|
||||
|
||||
# We have to find libc and nptl
|
||||
library_path=${common_objpfx}:${common_objpfx}nptl
|
||||
library_path=${common_objpfx}:${common_objpfx}nptl:${common_objpfx}/dlfcn
|
||||
tst_tls5="${test_via_rtld_prefix} ${common_objpfx}/nptl/tst-tls5"
|
||||
|
||||
> $logfile
|
||||
|
||||
+109
-2
@@ -1031,7 +1031,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 +1211,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 +1232,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 +1342,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;
|
||||
|
||||
@@ -118,17 +118,14 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
|
||||
} net_buffer;
|
||||
querybuf *orig_net_buffer;
|
||||
int anslen;
|
||||
char *qbuf;
|
||||
enum nss_status status;
|
||||
|
||||
if (__res_maybe_init (&_res, 0) == -1)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
|
||||
qbuf = strdupa (name);
|
||||
|
||||
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
|
||||
|
||||
anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
|
||||
anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf,
|
||||
1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
|
||||
if (anslen < 0)
|
||||
{
|
||||
|
||||
+1
-1
@@ -593,7 +593,7 @@ __res_iclose(res_state statp, bool free_addr) {
|
||||
statp->_vcsock = -1;
|
||||
statp->_flags &= ~(RES_F_VC | RES_F_CONN);
|
||||
}
|
||||
for (ns = 0; ns < statp->_u._ext.nscount; ns++)
|
||||
for (ns = 0; ns < statp->nscount; ns++)
|
||||
if (statp->_u._ext.nsaddrs[ns]) {
|
||||
if (statp->_u._ext.nssocks[ns] != -1) {
|
||||
close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
#include <bits/libc-lock.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
/* The following bit is copied from res_data.c (where it is #ifdef'ed
|
||||
@@ -95,6 +96,20 @@ int
|
||||
__res_maybe_init (res_state resp, int preinit)
|
||||
{
|
||||
if (resp->options & RES_INIT) {
|
||||
static time_t last_mtime, last_check;
|
||||
time_t now;
|
||||
struct stat statbuf;
|
||||
|
||||
time (&now);
|
||||
if (now != last_check) {
|
||||
last_check = now;
|
||||
if (stat (_PATH_RESCONF, &statbuf) == 0 && last_mtime != statbuf.st_mtime) {
|
||||
last_mtime = statbuf.st_mtime;
|
||||
atomicinclock (lock);
|
||||
atomicinc (__res_initstamp);
|
||||
atomicincunlock (lock);
|
||||
}
|
||||
}
|
||||
if (__res_initstamp != resp->_u._ext.initstamp) {
|
||||
if (resp->nscount > 0)
|
||||
__res_iclose (resp, true);
|
||||
|
||||
@@ -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)
|
||||
|
||||
+237
-90
@@ -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.
|
||||
@@ -363,6 +380,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);
|
||||
@@ -638,6 +657,89 @@ get_nsaddr (res_state statp, int n)
|
||||
return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
|
||||
}
|
||||
|
||||
/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
|
||||
is not NULL, and return zero. */
|
||||
static int
|
||||
__attribute__ ((warn_unused_result))
|
||||
close_and_return_error (res_state statp, int *resplen2)
|
||||
{
|
||||
__res_iclose(statp, false);
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
@@ -647,11 +749,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 *nsap = get_nsaddr (statp, ns);
|
||||
int truncating, connreset, n;
|
||||
/* On some architectures compiler might emit a warning indicating
|
||||
@@ -743,6 +841,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:
|
||||
@@ -779,40 +879,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;
|
||||
@@ -820,10 +894,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;
|
||||
@@ -835,6 +913,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,
|
||||
@@ -997,6 +1078,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,
|
||||
@@ -1006,8 +1147,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;
|
||||
@@ -1032,7 +1171,11 @@ send_dg(res_state statp,
|
||||
retry_reopen:
|
||||
retval = reopen (statp, terrno, ns);
|
||||
if (retval <= 0)
|
||||
return retval;
|
||||
{
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return retval;
|
||||
}
|
||||
retry:
|
||||
evNowTime(&now);
|
||||
evConsTime(&timeout, seconds, 0);
|
||||
@@ -1040,11 +1183,11 @@ 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;
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
wait:
|
||||
if (need_recompute) {
|
||||
recompute_resend:
|
||||
@@ -1052,9 +1195,7 @@ send_dg(res_state statp,
|
||||
if (evCmpTime(finish, now) <= 0) {
|
||||
poll_err_out:
|
||||
Perror(statp, stderr, "poll", errno);
|
||||
err_out:
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
evSubTime(&timeout, &finish, &now);
|
||||
need_recompute = 0;
|
||||
@@ -1101,7 +1242,9 @@ send_dg(res_state statp,
|
||||
}
|
||||
|
||||
*gotsomewhere = 1;
|
||||
return (0);
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return 0;
|
||||
}
|
||||
if (n < 0) {
|
||||
if (errno == EINTR)
|
||||
@@ -1169,7 +1312,7 @@ send_dg(res_state statp,
|
||||
|
||||
fail_sendmmsg:
|
||||
Perror(statp, stderr, "sendmmsg", errno);
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1187,7 +1330,7 @@ send_dg(res_state statp,
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
goto recompute_resend;
|
||||
Perror(statp, stderr, "send", errno);
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
just_one:
|
||||
if (nwritten != 0 || buf2 == NULL || single_request)
|
||||
@@ -1203,55 +1346,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);
|
||||
@@ -1264,7 +1408,7 @@ send_dg(res_state statp,
|
||||
goto wait;
|
||||
}
|
||||
Perror(statp, stderr, "recvfrom", errno);
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
*gotsomewhere = 1;
|
||||
if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
|
||||
@@ -1275,7 +1419,7 @@ send_dg(res_state statp,
|
||||
(stdout, ";; undersized: %d\n",
|
||||
*thisresplenp));
|
||||
*terrno = EMSGSIZE;
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
if ((recvresp1 || hp->id != anhp->id)
|
||||
&& (recvresp2 || hp2->id != anhp->id)) {
|
||||
@@ -1324,7 +1468,7 @@ send_dg(res_state statp,
|
||||
? *thisanssizp : *thisresplenp);
|
||||
/* record the error */
|
||||
statp->_flags |= RES_F_EDNS0ERR;
|
||||
goto err_out;
|
||||
return close_and_return_error (statp, resplen2);
|
||||
}
|
||||
#endif
|
||||
if (!(statp->options & RES_INSECURE2)
|
||||
@@ -1376,10 +1520,10 @@ send_dg(res_state statp,
|
||||
goto wait;
|
||||
}
|
||||
|
||||
__res_iclose(statp, false);
|
||||
/* don't retry if called from dig */
|
||||
if (!statp->pfcode)
|
||||
return (0);
|
||||
return close_and_return_error (statp, resplen2);
|
||||
__res_iclose(statp, false);
|
||||
}
|
||||
if (anhp->rcode == NOERROR && anhp->ancount == 0
|
||||
&& anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
|
||||
@@ -1401,6 +1545,8 @@ send_dg(res_state statp,
|
||||
__res_iclose(statp, false);
|
||||
// XXX if we have received one reply we could
|
||||
// XXX use it and not repeat it over TCP...
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return (1);
|
||||
}
|
||||
/* Mark which reply we received. */
|
||||
@@ -1416,21 +1562,22 @@ send_dg(res_state statp,
|
||||
__res_iclose (statp, false);
|
||||
retval = reopen (statp, terrno, ns);
|
||||
if (retval <= 0)
|
||||
return retval;
|
||||
{
|
||||
if (resplen2 != NULL)
|
||||
*resplen2 = 0;
|
||||
return retval;
|
||||
}
|
||||
pfd[0].fd = EXT(statp).nssocks[ns];
|
||||
}
|
||||
}
|
||||
goto wait;
|
||||
}
|
||||
/*
|
||||
* All is well, or the error is fatal. Signal that the
|
||||
* next nameserver ought not be tried.
|
||||
*/
|
||||
/* All is well. We have received both responses (if
|
||||
two responses were requested). */
|
||||
return (resplen);
|
||||
} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
|
||||
/* Something went wrong. We can stop trying. */
|
||||
goto err_out;
|
||||
}
|
||||
} else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
|
||||
/* Something went wrong. We can stop trying. */
|
||||
return close_and_return_error (statp, resplen2);
|
||||
else {
|
||||
/* poll should not have returned > 0 in this case. */
|
||||
abort ();
|
||||
|
||||
@@ -80,16 +80,25 @@ arglist: while (@ARGV) {
|
||||
# We expect none or one argument.
|
||||
if ($#ARGV == -1) {
|
||||
$soversions="soversions.mk";
|
||||
$config="config.make";
|
||||
} elsif ($#ARGV == 0) {
|
||||
if (-d $ARGV[0]) {
|
||||
$soversions = "$ARGV[0]/soversions.mk";
|
||||
$config = "$ARGV[0]/config.make";
|
||||
} else {
|
||||
$soversions = $ARGV[0];
|
||||
$soversions = $dir = $ARGV[0];
|
||||
$dir =~ s!/?[^/]*/*$!!;
|
||||
$config = $dir . "/config.make";
|
||||
}
|
||||
} else {
|
||||
die "Wrong number of arguments.";
|
||||
}
|
||||
|
||||
if (system ("grep -q \"build-mathvec = yes\" $config") == 0) {
|
||||
$build_mathvec = 1;
|
||||
} else {
|
||||
$build_mathvec = 0;
|
||||
}
|
||||
|
||||
# Read names and versions of all shared libraries that are part of
|
||||
# glibc
|
||||
@@ -111,6 +120,8 @@ while (<SOVERSIONS>) {
|
||||
# - libthread_db since it contains unresolved references
|
||||
# - it's just a test NSS module
|
||||
# - We don't provide the libgcc so we don't test it
|
||||
# - libmvec if it wasn't built
|
||||
next if ($build_mathvec == 0 && $name eq "mvec");
|
||||
if ($name ne "nss_ldap" && $name ne "db1"
|
||||
&& !($name =~/^nss1_/) && $name ne "thread_db"
|
||||
&& $name ne "nss_test1" && $name ne "libgcc_s") {
|
||||
|
||||
@@ -98,6 +98,10 @@ static __thread struct link_map *lm_cache;
|
||||
int
|
||||
__cxa_thread_atexit_impl (dtor_func func, void *obj, void *dso_symbol)
|
||||
{
|
||||
#ifdef PTR_MANGLE
|
||||
PTR_MANGLE (func);
|
||||
#endif
|
||||
|
||||
/* Prepend. */
|
||||
struct dtor_list *new = calloc (1, sizeof (struct dtor_list));
|
||||
new->func = func;
|
||||
@@ -142,9 +146,13 @@ __call_tls_dtors (void)
|
||||
while (tls_dtor_list)
|
||||
{
|
||||
struct dtor_list *cur = tls_dtor_list;
|
||||
dtor_func func = cur->func;
|
||||
#ifdef PTR_DEMANGLE
|
||||
PTR_DEMANGLE (func);
|
||||
#endif
|
||||
|
||||
tls_dtor_list = tls_dtor_list->next;
|
||||
cur->func (cur->obj);
|
||||
func (cur->obj);
|
||||
|
||||
/* Ensure that the MAP dereference happens before
|
||||
l_tls_dtor_count decrement. That way, we protect this access from a
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/* Bug 18589: sort-test.sh fails at random.
|
||||
Copyright (C) 1998-2015 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||
|
||||
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 <string.h>
|
||||
#include <locale.h>
|
||||
|
||||
/* An incorrect strcoll optimization resulted in incorrect
|
||||
results from strcoll for cs_CZ and da_DK. */
|
||||
|
||||
int
|
||||
test_cs_CZ (void)
|
||||
{
|
||||
const char t1[] = "config";
|
||||
const char t2[] = "choose";
|
||||
if (setlocale (LC_ALL, "cs_CZ.UTF-8") == NULL)
|
||||
{
|
||||
perror ("setlocale");
|
||||
return 1;
|
||||
}
|
||||
/* In Czech the digraph ch sorts after c, therefore we expect
|
||||
config to sort before choose. */
|
||||
int a = strcoll (t1, t2);
|
||||
int b = strcoll (t2, t1);
|
||||
printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, a);
|
||||
printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, b);
|
||||
if (a < 0 && b > 0)
|
||||
{
|
||||
puts ("PASS: config < choose");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
puts ("FAIL: Wrong sorting in cz_CZ.UTF-8.");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
test_da_DK (void)
|
||||
{
|
||||
const char t1[] = "AS";
|
||||
const char t2[] = "AA";
|
||||
if (setlocale (LC_ALL, "da_DK.ISO-8859-1") == NULL)
|
||||
{
|
||||
perror ("setlocale");
|
||||
return 1;
|
||||
}
|
||||
/* AA should be treated as the last letter of the Danish alphabet,
|
||||
hence sorting after AS. */
|
||||
int a = strcoll (t1, t2);
|
||||
int b = strcoll (t2, t1);
|
||||
printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, a);
|
||||
printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, b);
|
||||
if (a < 0 && b > 0)
|
||||
{
|
||||
puts ("PASS: AS < AA");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
puts ("FAIL: Wrong sorting in da_DK.ISO-8859-1");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int err = 0;
|
||||
err |= test_cs_CZ ();
|
||||
err |= test_da_DK ();
|
||||
return err;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
||||
+1
-37
@@ -29,7 +29,6 @@
|
||||
# define STRING_TYPE char
|
||||
# define USTRING_TYPE unsigned char
|
||||
# define STRCOLL __strcoll_l
|
||||
# define STRDIFF __strdiff
|
||||
# define STRCMP strcmp
|
||||
# define WEIGHT_H "../locale/weight.h"
|
||||
# define SUFFIX MB
|
||||
@@ -42,20 +41,6 @@
|
||||
#include "../locale/localeinfo.h"
|
||||
#include WEIGHT_H
|
||||
|
||||
#define MASK_UTF8_7BIT (1 << 7)
|
||||
#define MASK_UTF8_START (3 << 6)
|
||||
|
||||
size_t
|
||||
STRDIFF (const STRING_TYPE *s, const STRING_TYPE *t)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
for (n = 0; *s != '\0' && *s++ == *t++; ++n)
|
||||
continue;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Track status while looking for sequences in a string. */
|
||||
typedef struct
|
||||
{
|
||||
@@ -269,29 +254,9 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
|
||||
const USTRING_TYPE *extra;
|
||||
const int32_t *indirect;
|
||||
|
||||
/* In case there is no locale specific sort order (C / POSIX). */
|
||||
if (nrules == 0)
|
||||
return STRCMP (s1, s2);
|
||||
|
||||
/* Fast forward to the position of the first difference. Needs to be
|
||||
encoding aware as the byte-by-byte comparison can stop in the middle
|
||||
of a char sequence for multibyte encodings like UTF-8. */
|
||||
uint_fast32_t encoding =
|
||||
current->values[_NL_ITEM_INDEX (_NL_COLLATE_ENCODING_TYPE)].word;
|
||||
if (encoding != __cet_other)
|
||||
{
|
||||
size_t diff = STRDIFF (s1, s2);
|
||||
if (diff > 0)
|
||||
{
|
||||
if (encoding == __cet_utf8 && (*(s1 + diff) & MASK_UTF8_7BIT) != 0)
|
||||
do
|
||||
diff--;
|
||||
while (diff > 0 && (*(s1 + diff) & MASK_UTF8_START) != MASK_UTF8_START);
|
||||
s1 += diff;
|
||||
s2 += diff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Catch empty strings. */
|
||||
if (__glibc_unlikely (*s1 == '\0') || __glibc_unlikely (*s2 == '\0'))
|
||||
return (*s1 != '\0') - (*s2 != '\0');
|
||||
@@ -358,8 +323,7 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
|
||||
byte-level comparison to ensure that we don't waste time
|
||||
going through multiple passes for totally equal strings
|
||||
before proceeding to subsequent passes. */
|
||||
if (pass == 0 && encoding == __cet_other &&
|
||||
STRCMP (s1, s2) == 0)
|
||||
if (pass == 0 && STRCMP (s1, s2) == 0)
|
||||
return result;
|
||||
else
|
||||
break;
|
||||
|
||||
@@ -81,7 +81,7 @@ ENTRY (__longjmp)
|
||||
C_SYMBOL_NAME(_rtld_local_ro) \
|
||||
+ RTLD_GLOBAL_RO_DL_HWCAP_OFFSET)
|
||||
# else
|
||||
# ifdef PIC
|
||||
# ifdef SHARED
|
||||
LDR_GLOBAL (a4, a3, C_SYMBOL_NAME(_rtld_global_ro), \
|
||||
RTLD_GLOBAL_RO_DL_HWCAP_OFFSET)
|
||||
# else
|
||||
|
||||
@@ -62,7 +62,7 @@ ENTRY (__sigsetjmp)
|
||||
C_SYMBOL_NAME(_rtld_local_ro) \
|
||||
+ RTLD_GLOBAL_RO_DL_HWCAP_OFFSET)
|
||||
# else
|
||||
# ifdef PIC
|
||||
# ifdef SHARED
|
||||
LDR_GLOBAL (a3, a4, C_SYMBOL_NAME(_rtld_global_ro), \
|
||||
RTLD_GLOBAL_RO_DL_HWCAP_OFFSET)
|
||||
# else
|
||||
|
||||
@@ -592,9 +592,6 @@ struct rtld_global_ro
|
||||
/* List of auditing interfaces. */
|
||||
struct audit_ifaces *_dl_audit;
|
||||
unsigned int _dl_naudit;
|
||||
|
||||
/* 0 if internal pointer values should not be guarded, 1 if they should. */
|
||||
EXTERN int _dl_pointer_guard;
|
||||
};
|
||||
# define __rtld_global_attribute__
|
||||
# if IS_IN (rtld)
|
||||
|
||||
@@ -33,3 +33,4 @@ _dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref)
|
||||
else
|
||||
return (void *) value;
|
||||
}
|
||||
rtld_hidden_def (_dl_symbol_address)
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
int
|
||||
pthread_spin_init (pthread_spinlock_t *lock, int pshared)
|
||||
{
|
||||
int tmp = 0;
|
||||
/* This should be a memory barrier to newer compilers */
|
||||
__asm__ __volatile__ ("stw,ma %1,0(%0)"
|
||||
: : "r" (lock), "r" (tmp) : "memory");
|
||||
/* The LWS-CAS operation on hppa is a synthetic atomic operation
|
||||
that doesn't provide the type of coherency that we need. Therefore
|
||||
we force that coherency by using LWS-CAS again. */
|
||||
atomic_exchange_rel (lock, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
int
|
||||
pthread_spin_unlock (pthread_spinlock_t *lock)
|
||||
{
|
||||
int tmp = 0;
|
||||
/* This should be a memory barrier to newer compilers */
|
||||
__asm__ __volatile__ ("stw,ma %1,0(%0)"
|
||||
: : "r" (lock), "r" (tmp) : "memory");
|
||||
/* The LWS-CAS operation on hppa is a synthetic atomic operation
|
||||
that doesn't provide the type of coherency that we need. Therefore
|
||||
we force that coherency by using LWS-CAS again. */
|
||||
atomic_exchange_rel (lock, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+14
-2
@@ -42,7 +42,11 @@
|
||||
/* Have the linker create plabel words so we get PLABEL32
|
||||
relocs and not 21/14. The use of 21/14 relocs is only
|
||||
supported in the latest dynamic linker. */
|
||||
.section .rodata
|
||||
#ifdef SHARED
|
||||
.section .data.rel.ro,"aw",@progbits
|
||||
#else
|
||||
.section .rodata,"a",@progbits
|
||||
#endif
|
||||
.align 4
|
||||
.Lpmain:
|
||||
.word P%main
|
||||
@@ -52,6 +56,10 @@
|
||||
.word P%__libc_csu_fini
|
||||
.Lp__libc_csu_init:
|
||||
.word P%__libc_csu_init
|
||||
#ifdef SHARED
|
||||
.Lp__global:
|
||||
.word $global$
|
||||
#endif
|
||||
|
||||
.text
|
||||
.align 4
|
||||
@@ -122,10 +130,14 @@ _start:
|
||||
/* void *stack_end (7th argument) */
|
||||
stw %sp, -60(%sp)
|
||||
|
||||
#ifdef SHARED
|
||||
addil LT'.Lp__global, %r19
|
||||
ldw RT'.Lp__global(%r1), %dp
|
||||
#else
|
||||
/* load global */
|
||||
ldil L%$global$, %dp
|
||||
ldo R%$global$(%dp), %dp
|
||||
|
||||
#endif
|
||||
bl __libc_start_main,%r2
|
||||
nop
|
||||
/* die horribly if it returned (it shouldn't) */
|
||||
|
||||
Vendored
+1
-1
@@ -262,7 +262,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
|
||||
|
||||
@@ -99,7 +99,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
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ need_isdir_precheck (void)
|
||||
tryopen_o_directory ();
|
||||
|
||||
/* We can skip the expensive `stat' call if O_DIRECTORY works. */
|
||||
return o_directory_works > 0;
|
||||
return o_directory_works < 0;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,67 +23,78 @@
|
||||
# include <htm.h>
|
||||
# include <elision-conf.h>
|
||||
|
||||
/* Returns true if the lock defined by is_lock_free as elided.
|
||||
ADAPT_COUNT is a pointer to per-lock state variable. */
|
||||
|
||||
/* Get the new value of adapt_count according to the elision
|
||||
configurations. Returns true if the system should retry again or false
|
||||
otherwise. */
|
||||
static inline bool
|
||||
__elide_lock (uint8_t *adapt_count, int is_lock_free)
|
||||
__get_new_count (uint8_t *adapt_count, int attempt)
|
||||
{
|
||||
if (*adapt_count > 0)
|
||||
/* A persistent failure indicates that a retry will probably
|
||||
result in another failure. Use normal locking now and
|
||||
for the next couple of calls. */
|
||||
if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
|
||||
{
|
||||
(*adapt_count)--;
|
||||
if (__elision_aconf.skip_lock_internal_abort > 0)
|
||||
*adapt_count = __elision_aconf.skip_lock_internal_abort;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = __elision_aconf.try_tbegin; i > 0; i--)
|
||||
{
|
||||
if (__builtin_tbegin (0))
|
||||
{
|
||||
if (is_lock_free)
|
||||
return true;
|
||||
/* Lock was busy. */
|
||||
__builtin_tabort (_ABORT_LOCK_BUSY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A persistent failure indicates that a retry will probably
|
||||
result in another failure. Use normal locking now and
|
||||
for the next couple of calls. */
|
||||
if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
|
||||
{
|
||||
if (__elision_aconf.skip_lock_internal_abort > 0)
|
||||
*adapt_count = __elision_aconf.skip_lock_internal_abort;
|
||||
break;
|
||||
}
|
||||
/* Same logic as above, but for a number of temporary failures in a
|
||||
a row. */
|
||||
else if (__elision_aconf.skip_lock_out_of_tbegin_retries > 0
|
||||
&& __elision_aconf.try_tbegin > 0)
|
||||
*adapt_count = __elision_aconf.skip_lock_out_of_tbegin_retries;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
/* Same logic as above, but for a number of temporary failures in a
|
||||
a row. */
|
||||
else if (attempt <= 1 && __elision_aconf.skip_lock_out_of_tbegin_retries > 0
|
||||
&& __elision_aconf.try_tbegin > 0)
|
||||
*adapt_count = __elision_aconf.skip_lock_out_of_tbegin_retries;
|
||||
return true;
|
||||
}
|
||||
|
||||
# define ELIDE_LOCK(adapt_count, is_lock_free) \
|
||||
__elide_lock (&(adapt_count), is_lock_free)
|
||||
/* CONCURRENCY NOTES:
|
||||
|
||||
The evaluation of the macro expression is_lock_free encompasses one or
|
||||
more loads from memory locations that are concurrently modified by other
|
||||
threads. For lock elision to work, this evaluation and the rest of the
|
||||
critical section protected by the lock must be atomic because an
|
||||
execution with lock elision must be equivalent to an execution in which
|
||||
the lock would have been actually acquired and released. Therefore, we
|
||||
evaluate is_lock_free inside of the transaction that represents the
|
||||
critical section for which we want to use lock elision, which ensures
|
||||
the atomicity that we require. */
|
||||
|
||||
static inline bool
|
||||
__elide_trylock (uint8_t *adapt_count, int is_lock_free, int write)
|
||||
{
|
||||
if (__elision_aconf.try_tbegin > 0)
|
||||
{
|
||||
if (write)
|
||||
__builtin_tabort (_ABORT_NESTED_TRYLOCK);
|
||||
return __elide_lock (adapt_count, is_lock_free);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* Returns 0 if the lock defined by is_lock_free was elided.
|
||||
ADAPT_COUNT is a per-lock state variable. */
|
||||
# define ELIDE_LOCK(adapt_count, is_lock_free) \
|
||||
({ \
|
||||
int ret = 0; \
|
||||
if (adapt_count > 0) \
|
||||
(adapt_count)--; \
|
||||
else \
|
||||
for (int i = __elision_aconf.try_tbegin; i > 0; i--) \
|
||||
{ \
|
||||
if (__libc_tbegin (0)) \
|
||||
{ \
|
||||
if (is_lock_free) \
|
||||
{ \
|
||||
ret = 1; \
|
||||
break; \
|
||||
} \
|
||||
__libc_tabort (_ABORT_LOCK_BUSY); \
|
||||
} \
|
||||
else \
|
||||
if (!__get_new_count (&adapt_count,i)) \
|
||||
break; \
|
||||
} \
|
||||
ret; \
|
||||
})
|
||||
|
||||
# define ELIDE_TRYLOCK(adapt_count, is_lock_free, write) \
|
||||
__elide_trylock (&(adapt_count), is_lock_free, write)
|
||||
({ \
|
||||
int ret = 0; \
|
||||
if (__elision_aconf.try_tbegin > 0) \
|
||||
{ \
|
||||
if (write) \
|
||||
__libc_tabort (_ABORT_NESTED_TRYLOCK); \
|
||||
ret = ELIDE_LOCK (adapt_count, is_lock_free); \
|
||||
} \
|
||||
ret; \
|
||||
})
|
||||
|
||||
|
||||
static inline bool
|
||||
@@ -91,7 +102,7 @@ __elide_unlock (int is_lock_free)
|
||||
{
|
||||
if (is_lock_free)
|
||||
{
|
||||
__builtin_tend (0);
|
||||
__libc_tend (0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
# define ABORT_TRANSACTION \
|
||||
({ \
|
||||
if (THREAD_GET_TM_CAPABLE ()) \
|
||||
__builtin_tabort (_ABORT_SYSCALL); \
|
||||
__libc_tabort (_ABORT_SYSCALL); \
|
||||
})
|
||||
#else
|
||||
# define ABORT_TRANSACTION
|
||||
|
||||
@@ -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
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include "semaphoreP.h"
|
||||
#include <futex-internal.h>
|
||||
#include <shm-directory.h>
|
||||
|
||||
|
||||
|
||||
@@ -1822,9 +1822,6 @@ GLIBC_2.17
|
||||
GLIBC_2.18
|
||||
GLIBC_2.18 A
|
||||
__cxa_thread_atexit_impl F
|
||||
GLIBC_2.22
|
||||
GLIBC_2.22 A
|
||||
fmemopen F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_IO_adjust_wcolumn F
|
||||
@@ -2015,6 +2012,9 @@ GLIBC_2.2.4
|
||||
GLIBC_2.2.6
|
||||
GLIBC_2.2.6 A
|
||||
__nanosleep F
|
||||
GLIBC_2.22
|
||||
GLIBC_2.22 A
|
||||
fmemopen F
|
||||
GLIBC_2.3
|
||||
GLIBC_2.3 A
|
||||
__ctype_b_loc F
|
||||
|
||||
@@ -64,35 +64,39 @@ typedef uintmax_t uatomic_max_t;
|
||||
|
||||
#if __ASSUME_LWS_CAS
|
||||
/* The only basic operation needed is compare and exchange. */
|
||||
static int __attribute__((noinline, unused))
|
||||
__atomic_compare_and_exchange_val_acq (int mem, int newval, int oldval)
|
||||
{
|
||||
volatile int lws_errno;
|
||||
volatile int lws_ret;
|
||||
asm volatile(
|
||||
"0: \n\t"
|
||||
"copy %2, %%r26 \n\t"
|
||||
"copy %3, %%r25 \n\t"
|
||||
"copy %4, %%r24 \n\t"
|
||||
"ble " _LWS "(%%sr2, %%r0) \n\t"
|
||||
"ldi " _LWS_CAS ", %%r20 \n\t"
|
||||
"ldi " _ASM_EAGAIN ", %%r24 \n\t"
|
||||
"cmpb,=,n %%r24, %%r21, 0b \n\t"
|
||||
"nop \n\t"
|
||||
"ldi " _ASM_EDEADLOCK ", %%r25 \n\t"
|
||||
"cmpb,=,n %%r25, %%r21, 0b \n\t"
|
||||
"nop \n\t"
|
||||
"stw %%r28, %0 \n\t"
|
||||
"stw %%r21, %1 \n\t"
|
||||
: "=m" (lws_ret), "=m" (lws_errno)
|
||||
: "r" (mem), "r" (oldval), "r" (newval)
|
||||
: _LWS_CLOBBER
|
||||
);
|
||||
|
||||
if (lws_errno == -EFAULT || lws_errno == -ENOSYS)
|
||||
ABORT_INSTRUCTION;
|
||||
|
||||
return lws_ret;
|
||||
}
|
||||
# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
|
||||
({ \
|
||||
volatile int lws_errno; \
|
||||
__typeof__ (*mem) lws_ret; \
|
||||
asm volatile( \
|
||||
"0: \n\t" \
|
||||
"copy %2, %%r26 \n\t" \
|
||||
"copy %3, %%r25 \n\t" \
|
||||
"copy %4, %%r24 \n\t" \
|
||||
"ble " _LWS "(%%sr2, %%r0) \n\t" \
|
||||
"ldi " _LWS_CAS ", %%r20 \n\t" \
|
||||
"ldi " _ASM_EAGAIN ", %%r24 \n\t" \
|
||||
"cmpb,=,n %%r24, %%r21, 0b \n\t" \
|
||||
"nop \n\t" \
|
||||
"ldi " _ASM_EDEADLOCK ", %%r25 \n\t" \
|
||||
"cmpb,=,n %%r25, %%r21, 0b \n\t" \
|
||||
"nop \n\t" \
|
||||
"stw %%r28, %0 \n\t" \
|
||||
"stw %%r21, %1 \n\t" \
|
||||
: "=m" (lws_ret), "=m" (lws_errno) \
|
||||
: "r" (mem), "r" (oldval), "r" (newval) \
|
||||
: _LWS_CLOBBER \
|
||||
); \
|
||||
\
|
||||
if(lws_errno == -EFAULT || lws_errno == -ENOSYS) \
|
||||
ABORT_INSTRUCTION; \
|
||||
\
|
||||
lws_ret; \
|
||||
})
|
||||
((__typeof__(oldval)) \
|
||||
__atomic_compare_and_exchange_val_acq ((int)mem, (int)newval, (int)oldval))
|
||||
|
||||
# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
|
||||
({ \
|
||||
|
||||
@@ -95,9 +95,6 @@ GLIBC_2.18
|
||||
GLIBC_2.19
|
||||
GLIBC_2.19 A
|
||||
fanotify_mark F
|
||||
GLIBC_2.22
|
||||
GLIBC_2.22 A
|
||||
fmemopen F
|
||||
GLIBC_2.2
|
||||
GLIBC_2.2 A
|
||||
_Exit F
|
||||
@@ -1863,6 +1860,9 @@ GLIBC_2.2.4
|
||||
GLIBC_2.2.6
|
||||
GLIBC_2.2.6 A
|
||||
__nanosleep F
|
||||
GLIBC_2.22
|
||||
GLIBC_2.22 A
|
||||
fmemopen F
|
||||
GLIBC_2.3
|
||||
GLIBC_2.3 A
|
||||
__ctype_b_loc F
|
||||
|
||||
@@ -43,9 +43,10 @@ syscall (long int __sysno, ...)
|
||||
va_end (args);
|
||||
|
||||
{
|
||||
LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
register unsigned long int __res asm("r28");
|
||||
PIC_REG_DEF
|
||||
LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5)
|
||||
LOAD_REGS_6
|
||||
asm volatile (SAVE_ASM_PIC
|
||||
" ble 0x100(%%sr2, %%r0) \n"
|
||||
" copy %1, %%r20 \n"
|
||||
|
||||
@@ -400,9 +400,10 @@ L(pre_end): ASM_LINE_SEP \
|
||||
({ \
|
||||
long __sys_res; \
|
||||
{ \
|
||||
LOAD_ARGS_##nr(args) \
|
||||
register unsigned long __res asm("r28"); \
|
||||
PIC_REG_DEF \
|
||||
LOAD_ARGS_##nr(args) \
|
||||
LOAD_REGS_##nr \
|
||||
/* FIXME: HACK save/load r19 around syscall */ \
|
||||
asm volatile( \
|
||||
SAVE_ASM_PIC \
|
||||
@@ -425,9 +426,10 @@ L(pre_end): ASM_LINE_SEP \
|
||||
({ \
|
||||
long __sys_res; \
|
||||
{ \
|
||||
LOAD_ARGS_##nr(args) \
|
||||
register unsigned long __res asm("r28"); \
|
||||
PIC_REG_DEF \
|
||||
LOAD_ARGS_##nr(args) \
|
||||
LOAD_REGS_##nr \
|
||||
/* FIXME: HACK save/load r19 around syscall */ \
|
||||
asm volatile( \
|
||||
SAVE_ASM_PIC \
|
||||
@@ -443,27 +445,44 @@ L(pre_end): ASM_LINE_SEP \
|
||||
__sys_res; \
|
||||
})
|
||||
|
||||
|
||||
|
||||
#define LOAD_ARGS_0()
|
||||
#define LOAD_ARGS_1(r26) \
|
||||
register unsigned long __r26 __asm__("r26") = (unsigned long)(r26); \
|
||||
#define LOAD_REGS_0
|
||||
#define LOAD_ARGS_1(a1) \
|
||||
register unsigned long __x26 = (unsigned long)(a1); \
|
||||
LOAD_ARGS_0()
|
||||
#define LOAD_ARGS_2(r26,r25) \
|
||||
register unsigned long __r25 __asm__("r25") = (unsigned long)(r25); \
|
||||
LOAD_ARGS_1(r26)
|
||||
#define LOAD_ARGS_3(r26,r25,r24) \
|
||||
register unsigned long __r24 __asm__("r24") = (unsigned long)(r24); \
|
||||
LOAD_ARGS_2(r26,r25)
|
||||
#define LOAD_ARGS_4(r26,r25,r24,r23) \
|
||||
register unsigned long __r23 __asm__("r23") = (unsigned long)(r23); \
|
||||
LOAD_ARGS_3(r26,r25,r24)
|
||||
#define LOAD_ARGS_5(r26,r25,r24,r23,r22) \
|
||||
register unsigned long __r22 __asm__("r22") = (unsigned long)(r22); \
|
||||
LOAD_ARGS_4(r26,r25,r24,r23)
|
||||
#define LOAD_ARGS_6(r26,r25,r24,r23,r22,r21) \
|
||||
register unsigned long __r21 __asm__("r21") = (unsigned long)(r21); \
|
||||
LOAD_ARGS_5(r26,r25,r24,r23,r22)
|
||||
#define LOAD_REGS_1 \
|
||||
register unsigned long __r26 __asm__("r26") = __x26; \
|
||||
LOAD_REGS_0
|
||||
#define LOAD_ARGS_2(a1,a2) \
|
||||
register unsigned long __x25 = (unsigned long)(a2); \
|
||||
LOAD_ARGS_1(a1)
|
||||
#define LOAD_REGS_2 \
|
||||
register unsigned long __r25 __asm__("r25") = __x25; \
|
||||
LOAD_REGS_1
|
||||
#define LOAD_ARGS_3(a1,a2,a3) \
|
||||
register unsigned long __x24 = (unsigned long)(a3); \
|
||||
LOAD_ARGS_2(a1,a2)
|
||||
#define LOAD_REGS_3 \
|
||||
register unsigned long __r24 __asm__("r24") = __x24; \
|
||||
LOAD_REGS_2
|
||||
#define LOAD_ARGS_4(a1,a2,a3,a4) \
|
||||
register unsigned long __x23 = (unsigned long)(a4); \
|
||||
LOAD_ARGS_3(a1,a2,a3)
|
||||
#define LOAD_REGS_4 \
|
||||
register unsigned long __r23 __asm__("r23") = __x23; \
|
||||
LOAD_REGS_3
|
||||
#define LOAD_ARGS_5(a1,a2,a3,a4,a5) \
|
||||
register unsigned long __x22 = (unsigned long)(a5); \
|
||||
LOAD_ARGS_4(a1,a2,a3,a4)
|
||||
#define LOAD_REGS_5 \
|
||||
register unsigned long __r22 __asm__("r22") = __x22; \
|
||||
LOAD_REGS_4
|
||||
#define LOAD_ARGS_6(a1,a2,a3,a4,a5,a6) \
|
||||
register unsigned long __x21 = (unsigned long)(a6); \
|
||||
LOAD_ARGS_5(a1,a2,a3,a4,a5)
|
||||
#define LOAD_REGS_6 \
|
||||
register unsigned long __r21 __asm__("r21") = __x21; \
|
||||
LOAD_REGS_5
|
||||
|
||||
/* Even with zero args we use r20 for the syscall number */
|
||||
#define ASM_ARGS_0
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _LINUX_MICROBLAZE_SYSDEP_H
|
||||
#define _LINUX_MICROBLAZE_SYSDEP_H 1
|
||||
|
||||
#include <sysdeps/unix/sysdep.h>
|
||||
#include <sysdeps/microblaze/sysdep.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
/* Defines RTLD_PRIVATE_ERRNO. */
|
||||
#include <dl-sysdep.h>
|
||||
@@ -305,3 +308,5 @@ SYSCALL_ERROR_LABEL_DCL: \
|
||||
# define PTR_DEMANGLE(var) (void) (var)
|
||||
|
||||
#endif /* not __ASSEMBLER__ */
|
||||
|
||||
#endif /* _LINUX_MICROBLAZE_SYSDEP_H */
|
||||
|
||||
@@ -68,6 +68,11 @@ __OPENAT (int fd, const char *file, int oflag, ...)
|
||||
va_end (arg);
|
||||
}
|
||||
|
||||
/* We have to add the O_LARGEFILE flag for openat64. */
|
||||
#ifdef MORE_OFLAGS
|
||||
oflag |= MORE_OFLAGS;
|
||||
#endif
|
||||
|
||||
return SYSCALL_CANCEL (openat, fd, file, oflag, mode);
|
||||
}
|
||||
libc_hidden_def (__OPENAT)
|
||||
|
||||
@@ -72,36 +72,33 @@ __lll_lock_elision (int *lock, short *adapt_count, EXTRAARG int pshared)
|
||||
goto use_lock;
|
||||
}
|
||||
|
||||
int try_begin = aconf.try_tbegin;
|
||||
while (1)
|
||||
for (int i = aconf.try_tbegin; i > 0; i--)
|
||||
{
|
||||
if (__builtin_tbegin (0))
|
||||
if (__libc_tbegin (0))
|
||||
{
|
||||
if (*lock == 0)
|
||||
return 0;
|
||||
/* Lock was busy. Fall back to normal locking. */
|
||||
__builtin_tabort (_ABORT_LOCK_BUSY);
|
||||
__libc_tabort (_ABORT_LOCK_BUSY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A persistent failure indicates that a retry will probably
|
||||
result in another failure. Use normal locking now and
|
||||
for the next couple of calls. */
|
||||
if (try_begin-- <= 0
|
||||
|| _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
|
||||
if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
|
||||
{
|
||||
if (aconf.skip_lock_internal_abort > 0)
|
||||
*adapt_count = aconf.skip_lock_internal_abort;
|
||||
goto use_lock;
|
||||
}
|
||||
/* Same logic as above, but for for a number of temporary failures
|
||||
in a row. */
|
||||
else if (aconf.skip_lock_out_of_tbegin_retries > 0
|
||||
&& aconf.try_tbegin > 0)
|
||||
*adapt_count = aconf.skip_lock_out_of_tbegin_retries;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fall back to locks for a bit if retries have been exhausted */
|
||||
if (aconf.try_tbegin > 0 && aconf.skip_lock_out_of_tbegin_retries > 0)
|
||||
*adapt_count = aconf.skip_lock_out_of_tbegin_retries;
|
||||
|
||||
use_lock:
|
||||
return LLL_LOCK ((*lock), pshared);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ int
|
||||
__lll_trylock_elision (int *futex, short *adapt_count)
|
||||
{
|
||||
/* Implement POSIX semantics by forbiding nesting elided trylocks. */
|
||||
__builtin_tabort (_ABORT_NESTED_TRYLOCK);
|
||||
__libc_tabort (_ABORT_NESTED_TRYLOCK);
|
||||
|
||||
/* Only try a transaction if it's worth it. */
|
||||
if (*adapt_count > 0)
|
||||
@@ -40,13 +40,13 @@ __lll_trylock_elision (int *futex, short *adapt_count)
|
||||
goto use_lock;
|
||||
}
|
||||
|
||||
if (__builtin_tbegin (0))
|
||||
if (__libc_tbegin (0))
|
||||
{
|
||||
if (*futex == 0)
|
||||
return 0;
|
||||
|
||||
/* Lock was busy. Fall back to normal locking. */
|
||||
__builtin_tabort (_ABORT_LOCK_BUSY);
|
||||
__libc_tabort (_ABORT_LOCK_BUSY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ __lll_unlock_elision(int *lock, int pshared)
|
||||
{
|
||||
/* When the lock was free we're in a transaction. */
|
||||
if (*lock == 0)
|
||||
__builtin_tend (0);
|
||||
__libc_tend (0);
|
||||
else
|
||||
lll_unlock ((*lock), pshared);
|
||||
return 0;
|
||||
|
||||
@@ -118,13 +118,44 @@
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define __builtin_tbegin(tdb) _tbegin ()
|
||||
#define __builtin_tend(nested) _tend ()
|
||||
#define __builtin_tabort(abortcode) _tabort (abortcode)
|
||||
#define __builtin_get_texasru() _texasru ()
|
||||
#define __libc_tbegin(tdb) _tbegin ()
|
||||
#define __libc_tend(nested) _tend ()
|
||||
#define __libc_tabort(abortcode) _tabort (abortcode)
|
||||
#define __builtin_get_texasru() _texasru ()
|
||||
|
||||
#else
|
||||
# include <htmintrin.h>
|
||||
|
||||
# ifdef __TM_FENCE__
|
||||
/* New GCC behavior. */
|
||||
# define __libc_tbegin(R) __builtin_tbegin (R)
|
||||
# define __libc_tend(R) __builtin_tend (R)
|
||||
# define __libc_tabort(R) __builtin_tabort (R)
|
||||
# else
|
||||
/* Workaround an old GCC behavior. Earlier releases of GCC 4.9 and 5.0,
|
||||
didn't use to treat __builtin_tbegin, __builtin_tend and
|
||||
__builtin_tabort as compiler barriers, moving instructions into and
|
||||
out the transaction.
|
||||
Remove this when glibc drops support for GCC 5.0. */
|
||||
# define __libc_tbegin(R) \
|
||||
({ __asm__ volatile("" ::: "memory"); \
|
||||
unsigned int __ret = __builtin_tbegin (R); \
|
||||
__asm__ volatile("" ::: "memory"); \
|
||||
__ret; \
|
||||
})
|
||||
# define __libc_tabort(R) \
|
||||
({ __asm__ volatile("" ::: "memory"); \
|
||||
unsigned int __ret = __builtin_tabort (R); \
|
||||
__asm__ volatile("" ::: "memory"); \
|
||||
__ret; \
|
||||
})
|
||||
# define __libc_tend(R) \
|
||||
({ __asm__ volatile("" ::: "memory"); \
|
||||
unsigned int __ret = __builtin_tend (R); \
|
||||
__asm__ volatile("" ::: "memory"); \
|
||||
__ret; \
|
||||
})
|
||||
# endif /* __TM_FENCE__ */
|
||||
#endif /* __HTM__ */
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
/* Using the hidden attribute here does not change the code but it
|
||||
helps to avoid warnings. */
|
||||
extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
|
||||
extern void restore_rt (void) asm ("__restore_rt") __attribute__((__visibility__("hidden")));
|
||||
|
||||
|
||||
/* If ACT is not NULL, change the action for SIG to *ACT.
|
||||
|
||||
@@ -53,34 +53,5 @@
|
||||
# undef __DECL_SIMD_powf
|
||||
# define __DECL_SIMD_powf __DECL_SIMD_x86_64
|
||||
|
||||
/* Workaround to exclude unnecessary symbol aliases in libmvec
|
||||
while GCC creates the vector names based on scalar asm name.
|
||||
Corresponding discussion started at
|
||||
<https://gcc.gnu.org/ml/gcc/2015-06/msg00173.html>. */
|
||||
__asm__ ("_ZGVbN2v___log_finite = _ZGVbN2v_log");
|
||||
__asm__ ("_ZGVcN4v___log_finite = _ZGVcN4v_log");
|
||||
__asm__ ("_ZGVdN4v___log_finite = _ZGVdN4v_log");
|
||||
__asm__ ("_ZGVeN8v___log_finite = _ZGVeN8v_log");
|
||||
__asm__ ("_ZGVbN4v___logf_finite = _ZGVbN4v_logf");
|
||||
__asm__ ("_ZGVcN8v___logf_finite = _ZGVcN8v_logf");
|
||||
__asm__ ("_ZGVdN8v___logf_finite = _ZGVdN8v_logf");
|
||||
__asm__ ("_ZGVeN16v___logf_finite = _ZGVeN16v_logf");
|
||||
__asm__ ("_ZGVbN2v___exp_finite = _ZGVbN2v_exp");
|
||||
__asm__ ("_ZGVcN4v___exp_finite = _ZGVcN4v_exp");
|
||||
__asm__ ("_ZGVdN4v___exp_finite = _ZGVdN4v_exp");
|
||||
__asm__ ("_ZGVeN8v___exp_finite = _ZGVeN8v_exp");
|
||||
__asm__ ("_ZGVbN4v___expf_finite = _ZGVbN4v_expf");
|
||||
__asm__ ("_ZGVcN8v___expf_finite = _ZGVcN8v_expf");
|
||||
__asm__ ("_ZGVdN8v___expf_finite = _ZGVdN8v_expf");
|
||||
__asm__ ("_ZGVeN16v___expf_finite = _ZGVeN16v_expf");
|
||||
__asm__ ("_ZGVbN2vv___pow_finite = _ZGVbN2vv_pow");
|
||||
__asm__ ("_ZGVcN4vv___pow_finite = _ZGVcN4vv_pow");
|
||||
__asm__ ("_ZGVdN4vv___pow_finite = _ZGVdN4vv_pow");
|
||||
__asm__ ("_ZGVeN8vv___pow_finite = _ZGVeN8vv_pow");
|
||||
__asm__ ("_ZGVbN4vv___powf_finite = _ZGVbN4vv_powf");
|
||||
__asm__ ("_ZGVcN8vv___powf_finite = _ZGVcN8vv_powf");
|
||||
__asm__ ("_ZGVdN8vv___powf_finite = _ZGVdN8vv_powf");
|
||||
__asm__ ("_ZGVeN16vv___powf_finite = _ZGVeN16vv_powf");
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
Vendored
+2
-2
@@ -118,7 +118,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
|
||||
@@ -245,7 +245,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
|
||||
|
||||
@@ -35,7 +35,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
|
||||
|
||||
@@ -87,7 +87,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
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ libmvec-support += svml_d_cos2_core svml_d_cos4_core_avx \
|
||||
svml_d_pow_data svml_s_powf4_core svml_s_powf8_core_avx \
|
||||
svml_s_powf8_core svml_s_powf16_core svml_s_powf_data \
|
||||
svml_s_sincosf4_core svml_s_sincosf8_core_avx \
|
||||
svml_s_sincosf8_core svml_s_sincosf16_core init-arch
|
||||
svml_s_sincosf8_core svml_s_sincosf16_core init-arch \
|
||||
svml_finite_alias
|
||||
|
||||
libmvec-static-only-routines = svml_finite_alias
|
||||
endif
|
||||
|
||||
# Variables for libmvec tests.
|
||||
|
||||
@@ -16,7 +16,7 @@ CFLAGS-e_asin-fma4.c = -mfma4
|
||||
CFLAGS-e_atan2-fma4.c = -mfma4
|
||||
CFLAGS-e_exp-fma4.c = -mfma4
|
||||
CFLAGS-e_log-fma4.c = -mfma4
|
||||
CFLAGS-e_pow-fma4.c = -mfma4
|
||||
CFLAGS-e_pow-fma4.c = -mfma4 $(config-cflags-nofma)
|
||||
CFLAGS-halfulp-fma4.c = -mfma4
|
||||
CFLAGS-mpa-fma4.c = -mfma4
|
||||
CFLAGS-mpatan-fma4.c = -mfma4
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/* These aliases added as workaround to exclude unnecessary symbol
|
||||
aliases in libmvec.so while compiler creates the vector names
|
||||
based on scalar asm name. Corresponding discussion is at
|
||||
<https://gcc.gnu.org/ml/gcc/2015-06/msg00173.html>.
|
||||
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 <sysdep.h>
|
||||
|
||||
#define ALIAS_IMPL(alias, target) \
|
||||
ENTRY (alias); \
|
||||
jmp *target@GOTPCREL(%rip); \
|
||||
END (alias)
|
||||
|
||||
.text
|
||||
ALIAS_IMPL (_ZGVbN2v___log_finite, _ZGVbN2v_log)
|
||||
ALIAS_IMPL (_ZGVcN4v___log_finite, _ZGVcN4v_log)
|
||||
ALIAS_IMPL (_ZGVdN4v___log_finite, _ZGVdN4v_log)
|
||||
ALIAS_IMPL (_ZGVeN8v___log_finite, _ZGVeN8v_log)
|
||||
|
||||
ALIAS_IMPL (_ZGVbN4v___logf_finite, _ZGVbN4v_logf)
|
||||
ALIAS_IMPL (_ZGVcN8v___logf_finite, _ZGVcN8v_logf)
|
||||
ALIAS_IMPL (_ZGVdN8v___logf_finite, _ZGVdN8v_logf)
|
||||
ALIAS_IMPL (_ZGVeN16v___logf_finite, _ZGVeN16v_logf)
|
||||
|
||||
ALIAS_IMPL (_ZGVbN2v___exp_finite, _ZGVbN2v_exp)
|
||||
ALIAS_IMPL (_ZGVcN4v___exp_finite, _ZGVcN4v_exp)
|
||||
ALIAS_IMPL (_ZGVdN4v___exp_finite, _ZGVdN4v_exp)
|
||||
ALIAS_IMPL (_ZGVeN8v___exp_finite, _ZGVeN8v_exp)
|
||||
|
||||
ALIAS_IMPL (_ZGVbN4v___expf_finite, _ZGVbN4v_expf)
|
||||
ALIAS_IMPL (_ZGVcN8v___expf_finite, _ZGVcN8v_expf)
|
||||
ALIAS_IMPL (_ZGVdN8v___expf_finite, _ZGVdN8v_expf)
|
||||
ALIAS_IMPL (_ZGVeN16v___expf_finite, _ZGVeN16v_expf)
|
||||
|
||||
ALIAS_IMPL (_ZGVbN2vv___pow_finite, _ZGVbN2vv_pow)
|
||||
ALIAS_IMPL (_ZGVcN4vv___pow_finite, _ZGVcN4vv_pow)
|
||||
ALIAS_IMPL (_ZGVdN4vv___pow_finite, _ZGVdN4vv_pow)
|
||||
ALIAS_IMPL (_ZGVeN8vv___pow_finite, _ZGVeN8vv_pow)
|
||||
|
||||
ALIAS_IMPL (_ZGVbN4vv___powf_finite, _ZGVbN4vv_powf)
|
||||
ALIAS_IMPL (_ZGVcN8vv___powf_finite, _ZGVcN8vv_powf)
|
||||
ALIAS_IMPL (_ZGVdN8vv___powf_finite, _ZGVdN8vv_powf)
|
||||
ALIAS_IMPL (_ZGVeN16vv___powf_finite, _ZGVeN16vv_powf)
|
||||
+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 ()
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#define STRING_TYPE wchar_t
|
||||
#define USTRING_TYPE wint_t
|
||||
#define STRCOLL __wcscoll_l
|
||||
#define STRDIFF __wcsdiff
|
||||
#define STRCMP __wcscmp
|
||||
#define WEIGHT_H "../locale/weightwc.h"
|
||||
#define SUFFIX WC
|
||||
|
||||
Reference in New Issue
Block a user