Merge branch 'master' of git://sourceware.org/git/glibc
This commit is contained in:
commit
57da2a2395
74
ChangeLog
74
ChangeLog
|
@ -1,8 +1,80 @@
|
|||
2018-10-31 Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
|
||||
* sysdeps/gnu/errlist.c (EIEIO): Document how translators should
|
||||
translate the error message.
|
||||
|
||||
2018-10-30 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* conform/linknamespace.py: New file.
|
||||
* conform/linknamespace.pl: Remove file.
|
||||
* conform/Makefile ($(linknamespace-header-tests)): Use
|
||||
linknamespace.py instead of linknamespace.pl. Do not use --tmpdir
|
||||
option.
|
||||
|
||||
2018-10-30 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* stdlib/test-bz22786.c (do_test): Additional free calls to avoid
|
||||
memory leaks.
|
||||
|
||||
2018-10-30 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* support/blob_repeat.c (allocate_big): Call mkstemp directly.
|
||||
|
||||
2018-10-30 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* stdlib/tst-strtod-overflow.c (do_test): Switch to
|
||||
support_blob_repeat.
|
||||
|
||||
2018-10-30 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
Avoid spurious test failures in stdlib/test-bz22786.
|
||||
* support/Makefile (libsupport-routines): Add blob_repeat.
|
||||
(tests): Add tst-support_blob_repeat.
|
||||
* support/blob_repeat.h: New file.
|
||||
* support/blob_repeat.c: Likewise.
|
||||
* support/tst-support_blob_repeat.c: Likewise.
|
||||
* stdlib/test-bz22786.c (do_test): Replace malloc and memset with
|
||||
support_blob_repeat_allocate.
|
||||
|
||||
2018-10-30 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
[BZ #23125]
|
||||
* sysdeps/riscv/start.S (ENTRY_POINT): Mark ra as undefined.
|
||||
Don't use tail call.
|
||||
* elf/tst-unwind-main.c: New file.
|
||||
* elf/Makefile (tests): Add tst-unwind-main.
|
||||
(CFLAGS-tst-unwind-main.c): Define.
|
||||
|
||||
2018-10-29 Sergi Almacellas Abellana <sergi@koolpi.com>
|
||||
|
||||
[BZ #23791]
|
||||
* localedata/locales/ca_ES (LC_MONETARY): set p_cs_precedes and
|
||||
n_cs_precedes to 0.
|
||||
* localedata/locales/ca_ES (LC_MONETARY): set grouping to 3;3
|
||||
|
||||
2018-10-29 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* conform/glibcconform.py: Do not import shutil.
|
||||
(list_exported_functions): Use tempfile.TemporaryDirectory instead
|
||||
of mkdtemp.
|
||||
|
||||
* configure.ac (PYTHON_PROG): Use AC_CHECK_PROG_VER. Set
|
||||
critic_missing for versions before 3.4.
|
||||
* configure: Regenerated.
|
||||
* manual/install.texi (Tools for Compilation): Document
|
||||
requirement for Python to build glibc.
|
||||
* INSTALL: Regenerated.
|
||||
* Rules [PYTHON]: Make code unconditional.
|
||||
* benchtests/Makefile [PYTHON]: Likewise.
|
||||
* conform/Makefile [PYTHON]: Likewise.
|
||||
* manual/Makefile [PYTHON]: Likewise.
|
||||
* math/Makefile [PYTHON]: Likewise.
|
||||
|
||||
2018-10-28 Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
|
||||
* hurd/hurdsig.c (_hurd_interrupted_rpc_timeout): Set to 60000.
|
||||
* hurd/intr-msg.c (_hurd_intr_rpc_mach_msg): When the server does not
|
||||
answer to interrupt_operation, return EIO instead of EINTR.
|
||||
answer to interrupt_operation, return EIEIO instead of EINTR.
|
||||
* sysdeps/mach/hurd/i386/intr-msg.h (INTR_MSG_TRAP): Make
|
||||
_hurd_intr_rpc_msg_about_to global point to start of controlled
|
||||
assembly snippet. Make it check canceled flag.
|
||||
|
|
8
INSTALL
8
INSTALL
|
@ -531,11 +531,11 @@ build the GNU C Library:
|
|||
work with any version of 'sed'. As of release time, 'sed' version
|
||||
4.5 is the newest verified to work to build the GNU C Library.
|
||||
|
||||
* Python 2.7/3.4 or later
|
||||
* Python 3.4 or later
|
||||
|
||||
Python is required to build the GNU C Library manual and to run
|
||||
some tests. As of release time, Python 3.6 is the newest verified
|
||||
to work for testing the GNU C Library.
|
||||
Python is required to build the GNU C Library. As of release time,
|
||||
Python 3.6 is the newest verified to work for building and testing
|
||||
the GNU C Library.
|
||||
|
||||
* PExpect 4.0
|
||||
|
||||
|
|
2
NEWS
2
NEWS
|
@ -48,7 +48,7 @@ Deprecated and removed features, and other changes affecting compatibility:
|
|||
|
||||
Changes to build and runtime requirements:
|
||||
|
||||
* Python is required to build the GNU C Library manual.
|
||||
* Python 3.4 or later is required to build the GNU C Library.
|
||||
|
||||
Security related changes:
|
||||
|
||||
|
|
7
Rules
7
Rules
|
@ -114,11 +114,6 @@ tests-printers-programs := $(addprefix $(objpfx),$(tests-printers))
|
|||
# .out files with the output of running the pretty printer tests.
|
||||
tests-printers-out := $(patsubst %,$(objpfx)%.out,$(tests-printers))
|
||||
|
||||
ifndef PYTHON
|
||||
# Mark tests-printers tests as unsupported if we don't have PYTHON.
|
||||
tests-unsupported += $(tests-printers)
|
||||
endif
|
||||
|
||||
ifeq ($(build-programs),yes)
|
||||
others: $(addprefix $(objpfx),$(others) $(sysdep-others) $(extra-objs))
|
||||
else
|
||||
|
@ -277,7 +272,6 @@ endif
|
|||
|
||||
endif # tests
|
||||
|
||||
ifdef PYTHON
|
||||
ifneq "$(strip $(tests-printers))" ""
|
||||
|
||||
# Static pattern rule for building the test programs for the pretty printers.
|
||||
|
@ -300,7 +294,6 @@ $(tests-printers-out): $(objpfx)%.out: $(objpfx)% %.py %.c $(pretty-printers) \
|
|||
$(PYTHON) $*.py $*.c $(objpfx)$* $(pretty-printers) > $@; \
|
||||
$(evaluate-test)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
.PHONY: distclean realclean subdir_distclean subdir_realclean \
|
||||
|
|
|
@ -180,14 +180,7 @@ $(error Invalid BENCHSET value)
|
|||
endif
|
||||
endif
|
||||
|
||||
# Define the bench target only if the target has a usable python installation.
|
||||
ifdef PYTHON
|
||||
bench: bench-build bench-set bench-func bench-malloc
|
||||
else
|
||||
bench:
|
||||
@echo "The bench target needs python to run."
|
||||
@exit 1
|
||||
endif
|
||||
|
||||
# Target to only build the benchmark without running it. We generate locales
|
||||
# only if we're building natively.
|
||||
|
|
|
@ -5344,19 +5344,30 @@ fi
|
|||
|
||||
test -n "$PYTHON_PROG" && break
|
||||
done
|
||||
test -n "$PYTHON_PROG" || PYTHON_PROG="no"
|
||||
|
||||
case "x$PYTHON_PROG" in
|
||||
xno|x|x:) PYTHON_PROG=no ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
if test "x$PYTHON_PROG" = xno; then
|
||||
aux_missing="$aux_missing python"
|
||||
if test -z "$PYTHON_PROG"; then
|
||||
ac_verc_fail=yes
|
||||
else
|
||||
PYTHON="$PYTHON_PROG -B"
|
||||
# Found it, now check the version.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking version of $PYTHON_PROG" >&5
|
||||
$as_echo_n "checking version of $PYTHON_PROG... " >&6; }
|
||||
ac_prog_version=`$PYTHON_PROG --version 2>&1 | sed -n 's/^.*Python \([0-9][0-9.]*\).*$/\1/p'`
|
||||
case $ac_prog_version in
|
||||
'') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
|
||||
3.[4-9]*|3.[1-9][0-9]*|[4-9].*|[1-9][0-9]*)
|
||||
ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
|
||||
*) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
|
||||
|
||||
esac
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5
|
||||
$as_echo "$ac_prog_version" >&6; }
|
||||
fi
|
||||
if test $ac_verc_fail = yes; then
|
||||
critic_missing="$critic_missing python"
|
||||
fi
|
||||
|
||||
PYTHON="$PYTHON_PROG -B"
|
||||
|
||||
|
||||
test -n "$critic_missing" && as_fn_error $? "
|
||||
*** These critical programs are missing or too old:$critic_missing
|
||||
|
|
18
configure.ac
18
configure.ac
|
@ -1050,18 +1050,12 @@ else
|
|||
fi
|
||||
|
||||
# Check for python3 if available, or else python.
|
||||
AC_CHECK_PROGS(PYTHON_PROG, python3 python,no)
|
||||
case "x$PYTHON_PROG" in
|
||||
xno|x|x:) PYTHON_PROG=no ;;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
if test "x$PYTHON_PROG" = xno; then
|
||||
aux_missing="$aux_missing python"
|
||||
else
|
||||
PYTHON="$PYTHON_PROG -B"
|
||||
AC_SUBST(PYTHON)
|
||||
fi
|
||||
AC_CHECK_PROG_VER(PYTHON_PROG, python3 python, --version,
|
||||
[Python \([0-9][0-9.]*\)],
|
||||
[3.[4-9]*|3.[1-9][0-9]*|[4-9].*|[1-9][0-9]*],
|
||||
critic_missing="$critic_missing python")
|
||||
PYTHON="$PYTHON_PROG -B"
|
||||
AC_SUBST(PYTHON)
|
||||
|
||||
test -n "$critic_missing" && AC_MSG_ERROR([
|
||||
*** These critical programs are missing or too old:$critic_missing
|
||||
|
|
|
@ -120,9 +120,7 @@ linknamespace-symlists-base := $(foreach std,$(conformtest-standards),\
|
|||
symlist-$(std))
|
||||
linknamespace-symlists-tests := $(addprefix $(objpfx),\
|
||||
$(linknamespace-symlists-base))
|
||||
ifdef PYTHON
|
||||
tests-special += $(linknamespace-symlists-tests)
|
||||
endif
|
||||
|
||||
linknamespace-symlist-stdlibs-base := $(foreach std,$(conformtest-standards),\
|
||||
symlist-stdlibs-$(std))
|
||||
|
@ -130,9 +128,7 @@ linknamespace-symlist-stdlibs-tests := \
|
|||
$(addprefix $(objpfx),\
|
||||
$(linknamespace-symlist-stdlibs-base))
|
||||
|
||||
ifdef PYTHON
|
||||
tests-special += $(linknamespace-symlist-stdlibs-tests)
|
||||
endif
|
||||
|
||||
linknamespace-header-base := $(foreach std,\
|
||||
$(conformtest-standards),\
|
||||
|
@ -141,9 +137,7 @@ linknamespace-header-base := $(foreach std,\
|
|||
$(std)/$(h)/linknamespace.out))
|
||||
linknamespace-header-tests := $(addprefix $(objpfx),\
|
||||
$(linknamespace-header-base))
|
||||
ifdef PYTHON
|
||||
tests-special += $(linknamespace-header-tests)
|
||||
endif
|
||||
|
||||
include ../Rules
|
||||
|
||||
|
@ -224,17 +218,16 @@ $(linknamespace-symlist-stdlibs-tests): $(objpfx)symlist-stdlibs-%: \
|
|||
$(evaluate-test)
|
||||
|
||||
$(linknamespace-header-tests): $(objpfx)%/linknamespace.out: \
|
||||
linknamespace.pl \
|
||||
linknamespace.py \
|
||||
$(linknamespace-symlists-tests) \
|
||||
$(linknamespace-symlist-stdlibs-tests)
|
||||
(set -e; std_hdr=$*; std=$${std_hdr%%/*}; hdr=$${std_hdr#*/}; \
|
||||
mkdir -p $(@D)/scratch; \
|
||||
$(PERL) -I. -w $< --tmpdir=$(@D)/scratch --cc='$(CC)' \
|
||||
--flags='$(conformtest-cc-flags)' --standard=$$std \
|
||||
--stdsyms=$(objpfx)symlist-$$std --header=$$hdr \
|
||||
--libsyms=$(objpfx)symlist-stdlibs-$$std \
|
||||
--readelf='$(READELF)' \
|
||||
> $@ 2>&1); \
|
||||
$(PYTHON) $< --cc='$(CC)' --flags='$(conformtest-cc-flags)' \
|
||||
--standard=$$std --stdsyms=$(objpfx)symlist-$$std \
|
||||
--header=$$hdr --libsyms=$(objpfx)symlist-stdlibs-$$std \
|
||||
--readelf='$(READELF)' \
|
||||
> $@ 2>&1); \
|
||||
$(evaluate-test)
|
||||
|
||||
# Pre-standard C feature no longer supported by GCC (obsoleted in
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
|
@ -43,11 +42,9 @@ def list_exported_functions(cc, standard, header):
|
|||
|
||||
"""
|
||||
cc_all = '%s -D_ISOMAC %s' % (cc, CFLAGS[standard])
|
||||
# tempfile.TemporaryDirectory requires Python 3.2, so use mkdtemp.
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
c_file_name = os.path.join(temp_dir, 'test.c')
|
||||
aux_file_name = os.path.join(temp_dir, 'test.c.aux')
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
c_file_name = os.path.join(temp_dir, 'test.c')
|
||||
aux_file_name = os.path.join(temp_dir, 'test.c.aux')
|
||||
with open(c_file_name, 'w') as c_file:
|
||||
c_file.write('#include <%s>\n' % header)
|
||||
fns = set()
|
||||
|
@ -72,6 +69,4 @@ def list_exported_functions(cc, standard, header):
|
|||
else:
|
||||
raise ValueError("couldn't parse -aux-info output: %s"
|
||||
% line)
|
||||
finally:
|
||||
shutil.rmtree(temp_dir)
|
||||
return fns
|
||||
|
|
|
@ -1,233 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# Check that use of symbols declared in a given header does not result
|
||||
# in any symbols being brought in that are not reserved with external
|
||||
# linkage for the given standard.
|
||||
|
||||
# Copyright (C) 2014-2018 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/>.
|
||||
|
||||
use GlibcConform;
|
||||
use Getopt::Long;
|
||||
|
||||
GetOptions ('header=s' => \$header, 'standard=s' => \$standard,
|
||||
'flags=s' => \$flags, 'cc=s' => \$CC, 'tmpdir=s' => \$tmpdir,
|
||||
'stdsyms=s' => \$stdsyms_file, 'libsyms=s' => \$libsyms_file,
|
||||
'readelf=s' => \$READELF);
|
||||
|
||||
# Load the list of symbols that are OK.
|
||||
%stdsyms = ();
|
||||
open (STDSYMS, "<$stdsyms_file") || die ("open $stdsyms_file: $!\n");
|
||||
while (<STDSYMS>) {
|
||||
chomp;
|
||||
$stdsyms{$_} = 1;
|
||||
}
|
||||
close (STDSYMS) || die ("close $stdsyms_file: $!\n");
|
||||
|
||||
# The following whitelisted symbols are also allowed for now.
|
||||
#
|
||||
# * Bug 17576: stdin, stdout, stderr only reserved with external
|
||||
# linkage when stdio.h included (and possibly not then), not
|
||||
# generally.
|
||||
#
|
||||
# * Bug 18442: re_syntax_options wrongly brought in by regcomp and
|
||||
# used by re_comp.
|
||||
#
|
||||
@whitelist = qw(stdin stdout stderr re_syntax_options);
|
||||
foreach my $sym (@whitelist) {
|
||||
$stdsyms{$sym} = 1;
|
||||
}
|
||||
|
||||
# Return information about GLOBAL and WEAK symbols listed in readelf
|
||||
# -s output.
|
||||
sub list_syms {
|
||||
my ($syms_file) = @_;
|
||||
open (SYMS, "<$syms_file") || die ("open $syms_file: $!\n");
|
||||
my ($file) = $syms_file;
|
||||
my (@ret) = ();
|
||||
while (<SYMS>) {
|
||||
chomp;
|
||||
if (/^File: (.*)/) {
|
||||
$file = $1;
|
||||
$file =~ s|^.*/||;
|
||||
next;
|
||||
}
|
||||
s/^\s*//;
|
||||
# Architecture-specific st_other bits appear inside [] and disrupt
|
||||
# the format of readelf output.
|
||||
s/\[.*?\]//;
|
||||
my (@fields) = split (/\s+/, $_);
|
||||
if (@fields < 8) {
|
||||
next;
|
||||
}
|
||||
my ($bind) = $fields[4];
|
||||
my ($ndx) = $fields[6];
|
||||
my ($sym) = $fields[7];
|
||||
if ($bind ne "GLOBAL" && $bind ne "WEAK") {
|
||||
next;
|
||||
}
|
||||
if ($sym !~ /^\w+$/) {
|
||||
next;
|
||||
}
|
||||
push (@ret, [$file, $sym, $bind, $ndx ne "UND"]);
|
||||
}
|
||||
close (SYMS) || die ("close $syms_file: $!\n");
|
||||
return @ret;
|
||||
}
|
||||
|
||||
# Load information about GLOBAL and WEAK symbols defined or used in
|
||||
# the standard libraries.
|
||||
# Symbols from a given object, except for weak defined symbols.
|
||||
%seen_syms = ();
|
||||
# Strong undefined symbols from a given object.
|
||||
%strong_undef_syms = ();
|
||||
# Objects defining a given symbol (strongly or weakly).
|
||||
%sym_objs = ();
|
||||
@sym_data = list_syms ($libsyms_file);
|
||||
foreach my $sym (@sym_data) {
|
||||
my ($file, $name, $bind, $defined) = @$sym;
|
||||
if ($defined) {
|
||||
if (!defined ($sym_objs{$name})) {
|
||||
$sym_objs{$name} = [];
|
||||
}
|
||||
push (@{$sym_objs{$name}}, $file);
|
||||
}
|
||||
if ($bind eq "GLOBAL" || !$defined) {
|
||||
if (!defined ($seen_syms{$file})) {
|
||||
$seen_syms{$file} = [];
|
||||
}
|
||||
push (@{$seen_syms{$file}}, $name);
|
||||
}
|
||||
if ($bind eq "GLOBAL" && !$defined) {
|
||||
if (!defined ($strong_undef_syms{$file})) {
|
||||
$strong_undef_syms{$file} = [];
|
||||
}
|
||||
push (@{$strong_undef_syms{$file}}, $name);
|
||||
}
|
||||
}
|
||||
|
||||
# Determine what ELF-level symbols are brought in by use of C-level
|
||||
# symbols declared in the given header.
|
||||
#
|
||||
# The rules followed are heuristic and so may produce false positives
|
||||
# and false negatives.
|
||||
#
|
||||
# * All undefined symbols are considered of signficance, but it is
|
||||
# possible that (a) any standard library definition is weak, so can be
|
||||
# overridden by the user's definition, and (b) the symbol is only used
|
||||
# conditionally and not if the program is limited to standard
|
||||
# functionality.
|
||||
#
|
||||
# * If a symbol reference is only brought in by the user using a data
|
||||
# symbol rather than a function from the standard library, this will
|
||||
# not be detected.
|
||||
#
|
||||
# * If a symbol reference is only brought in by crt*.o or libgcc, this
|
||||
# will not be detected.
|
||||
#
|
||||
# * If a symbol reference is only brought in through __builtin_foo in
|
||||
# a standard macro being compiled to call foo, this will not be
|
||||
# detected.
|
||||
#
|
||||
# * Header inclusions should be compiled several times with different
|
||||
# options such as -O2, -D_FORTIFY_SOURCE and -D_FILE_OFFSET_BITS=64 to
|
||||
# find out what symbols are undefined from such a compilation; this is
|
||||
# not yet implemented.
|
||||
#
|
||||
# * This script finds symbols referenced through use of macros on the
|
||||
# basis that if a macro calls an internal function, that function must
|
||||
# also be declared in the header. However, the header might also
|
||||
# declare implementation-namespace functions that are not called by
|
||||
# any standard macro in the header, resulting in false positives for
|
||||
# any symbols brought in only through use of those
|
||||
# implementation-namespace functions.
|
||||
#
|
||||
# * Namespace issues can apply for dynamic linking as well as static
|
||||
# linking, when a call is from one shared library to another or uses a
|
||||
# PLT entry for a call within a shared library; such issues are only
|
||||
# detected by this script if the same namespace issue applies for
|
||||
# static linking.
|
||||
|
||||
@c_syms = list_exported_functions ("$CC $flags", $standard, $header, $tmpdir);
|
||||
$cincfile = "$tmpdir/undef-$$.c";
|
||||
$cincfile_o = "$tmpdir/undef-$$.o";
|
||||
$cincfile_sym = "$tmpdir/undef-$$.sym";
|
||||
open (CINCFILE, ">$cincfile") || die ("open $cincfile: $!\n");
|
||||
print CINCFILE "#include <$header>\n";
|
||||
foreach my $sym (sort @c_syms) {
|
||||
print CINCFILE "void *__glibc_test_$sym = (void *) &$sym;\n";
|
||||
}
|
||||
close CINCFILE || die ("close $cincfile: $!\n");
|
||||
system ("$CC $flags -D_ISOMAC $CFLAGS{$standard} -c $cincfile -o $cincfile_o")
|
||||
&& die ("compiling failed\n");
|
||||
system ("LC_ALL=C $READELF -W -s $cincfile_o > $cincfile_sym")
|
||||
&& die ("readelf failed\n");
|
||||
@elf_syms = list_syms ($cincfile_sym);
|
||||
unlink ($cincfile) || die ("unlink $cincfile: $!\n");
|
||||
unlink ($cincfile_o) || die ("unlink $cincfile_o: $!\n");
|
||||
unlink ($cincfile_sym) || die ("unlink $cincfile_sym: $!\n");
|
||||
|
||||
%seen_where = ();
|
||||
%files_seen = ();
|
||||
%all_undef = ();
|
||||
%current_undef = ();
|
||||
foreach my $sym (@elf_syms) {
|
||||
my ($file, $name, $bind, $defined) = @$sym;
|
||||
if ($bind eq "GLOBAL" && !$defined) {
|
||||
$seen_where{$name} = "[initial] $name";
|
||||
$all_undef{$name} = "[initial] $name";
|
||||
$current_undef{$name} = "[initial] $name";
|
||||
}
|
||||
}
|
||||
|
||||
while (%current_undef) {
|
||||
%new_undef = ();
|
||||
foreach my $sym (sort keys %current_undef) {
|
||||
foreach my $file (@{$sym_objs{$sym}}) {
|
||||
if (defined ($files_seen{$file})) {
|
||||
next;
|
||||
}
|
||||
$files_seen{$file} = 1;
|
||||
foreach my $ssym (@{$seen_syms{$file}}) {
|
||||
if (!defined ($seen_where{$ssym})) {
|
||||
$seen_where{$ssym} = "$current_undef{$sym} -> [$file] $ssym";
|
||||
}
|
||||
}
|
||||
foreach my $usym (@{$strong_undef_syms{$file}}) {
|
||||
if (!defined ($all_undef{$usym})) {
|
||||
$all_undef{$usym} = "$current_undef{$sym} -> [$file] $usym";
|
||||
$new_undef{$usym} = "$current_undef{$sym} -> [$file] $usym";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
%current_undef = %new_undef;
|
||||
}
|
||||
|
||||
$ret = 0;
|
||||
foreach my $sym (sort keys %seen_where) {
|
||||
if ($sym =~ /^_/) {
|
||||
next;
|
||||
}
|
||||
if (defined ($stdsyms{$sym})) {
|
||||
next;
|
||||
}
|
||||
print "$seen_where{$sym}\n";
|
||||
$ret = 1;
|
||||
}
|
||||
|
||||
exit $ret;
|
|
@ -0,0 +1,217 @@
|
|||
#!/usr/bin/python
|
||||
# Check that use of symbols declared in a given header does not result
|
||||
# in any symbols being brought in that are not reserved with external
|
||||
# linkage for the given standard.
|
||||
# Copyright (C) 2014-2018 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/>.
|
||||
|
||||
import argparse
|
||||
from collections import defaultdict
|
||||
import os.path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
import glibcconform
|
||||
|
||||
# The following whitelisted symbols are also allowed for now.
|
||||
#
|
||||
# * Bug 17576: stdin, stdout, stderr only reserved with external
|
||||
# linkage when stdio.h included (and possibly not then), not
|
||||
# generally.
|
||||
#
|
||||
# * Bug 18442: re_syntax_options wrongly brought in by regcomp and
|
||||
# used by re_comp.
|
||||
#
|
||||
WHITELIST = {'stdin', 'stdout', 'stderr', 're_syntax_options'}
|
||||
|
||||
|
||||
def list_syms(filename):
|
||||
"""Return information about GLOBAL and WEAK symbols listed in readelf
|
||||
-s output."""
|
||||
ret = []
|
||||
cur_file = filename
|
||||
with open(filename, 'r') as syms_file:
|
||||
for line in syms_file:
|
||||
line = line.rstrip()
|
||||
if line.startswith('File: '):
|
||||
cur_file = line[len('File: '):]
|
||||
cur_file = cur_file.split('/')[-1]
|
||||
continue
|
||||
# Architecture-specific st_other bits appear inside [] and
|
||||
# disrupt the format of readelf output.
|
||||
line = re.sub(r'\[.*?\]', '', line)
|
||||
fields = line.split()
|
||||
if len(fields) < 8:
|
||||
continue
|
||||
bind = fields[4]
|
||||
ndx = fields[6]
|
||||
sym = fields[7]
|
||||
if bind not in ('GLOBAL', 'WEAK'):
|
||||
continue
|
||||
if not re.fullmatch('[A-Za-z0-9_]+', sym):
|
||||
continue
|
||||
ret.append((cur_file, sym, bind, ndx != 'UND'))
|
||||
return ret
|
||||
|
||||
|
||||
def main():
|
||||
"""The main entry point."""
|
||||
parser = argparse.ArgumentParser(description='Check link-time namespace.')
|
||||
parser.add_argument('--header', metavar='HEADER',
|
||||
help='name of header')
|
||||
parser.add_argument('--standard', metavar='STD',
|
||||
help='standard to use when processing header')
|
||||
parser.add_argument('--cc', metavar='CC',
|
||||
help='C compiler to use')
|
||||
parser.add_argument('--flags', metavar='CFLAGS',
|
||||
help='Compiler flags to use with CC')
|
||||
parser.add_argument('--stdsyms', metavar='FILE',
|
||||
help='File with list of standard symbols')
|
||||
parser.add_argument('--libsyms', metavar='FILE',
|
||||
help='File with symbol information from libraries')
|
||||
parser.add_argument('--readelf', metavar='READELF',
|
||||
help='readelf program to use')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Load the list of symbols that are OK.
|
||||
stdsyms = set()
|
||||
with open(args.stdsyms, 'r') as stdsyms_file:
|
||||
for line in stdsyms_file:
|
||||
stdsyms.add(line.rstrip())
|
||||
stdsyms |= WHITELIST
|
||||
|
||||
# Load information about GLOBAL and WEAK symbols defined or used
|
||||
# in the standard libraries.
|
||||
# Symbols from a given object, except for weak defined symbols.
|
||||
seen_syms = defaultdict(list)
|
||||
# Strong undefined symbols from a given object.
|
||||
strong_undef_syms = defaultdict(list)
|
||||
# Objects defining a given symbol (strongly or weakly).
|
||||
sym_objs = defaultdict(list)
|
||||
for file, name, bind, defined in list_syms(args.libsyms):
|
||||
if defined:
|
||||
sym_objs[name].append(file)
|
||||
if bind == 'GLOBAL' or not defined:
|
||||
seen_syms[file].append(name)
|
||||
if bind == 'GLOBAL' and not defined:
|
||||
strong_undef_syms[file].append(name)
|
||||
|
||||
# Determine what ELF-level symbols are brought in by use of C-level
|
||||
# symbols declared in the given header.
|
||||
#
|
||||
# The rules followed are heuristic and so may produce false
|
||||
# positives and false negatives.
|
||||
#
|
||||
# * All undefined symbols are considered of signficance, but it is
|
||||
# possible that (a) any standard library definition is weak, so
|
||||
# can be overridden by the user's definition, and (b) the symbol
|
||||
# is only used conditionally and not if the program is limited to
|
||||
# standard functionality.
|
||||
#
|
||||
# * If a symbol reference is only brought in by the user using a
|
||||
# data symbol rather than a function from the standard library,
|
||||
# this will not be detected.
|
||||
#
|
||||
# * If a symbol reference is only brought in by crt*.o or libgcc,
|
||||
# this will not be detected.
|
||||
#
|
||||
# * If a symbol reference is only brought in through __builtin_foo
|
||||
# in a standard macro being compiled to call foo, this will not be
|
||||
# detected.
|
||||
#
|
||||
# * Header inclusions should be compiled several times with
|
||||
# different options such as -O2, -D_FORTIFY_SOURCE and
|
||||
# -D_FILE_OFFSET_BITS=64 to find out what symbols are undefined
|
||||
# from such a compilation; this is not yet implemented.
|
||||
#
|
||||
# * This script finds symbols referenced through use of macros on
|
||||
# the basis that if a macro calls an internal function, that
|
||||
# function must also be declared in the header. However, the
|
||||
# header might also declare implementation-namespace functions
|
||||
# that are not called by any standard macro in the header,
|
||||
# resulting in false positives for any symbols brought in only
|
||||
# through use of those implementation-namespace functions.
|
||||
#
|
||||
# * Namespace issues can apply for dynamic linking as well as
|
||||
# static linking, when a call is from one shared library to
|
||||
# another or uses a PLT entry for a call within a shared library;
|
||||
# such issues are only detected by this script if the same
|
||||
# namespace issue applies for static linking.
|
||||
seen_where = {}
|
||||
files_seen = set()
|
||||
all_undef = {}
|
||||
current_undef = {}
|
||||
compiler = '%s %s' % (args.cc, args.flags)
|
||||
c_syms = glibcconform.list_exported_functions(compiler, args.standard,
|
||||
args.header)
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
cincfile_name = os.path.join(temp_dir, 'undef.c')
|
||||
cincfile_o_name = os.path.join(temp_dir, 'undef.o')
|
||||
cincfile_sym_name = os.path.join(temp_dir, 'undef.sym')
|
||||
cincfile_text = ('#include <%s>\n%s\n'
|
||||
% (args.header,
|
||||
'\n'.join('void *__glibc_test_%s = (void *) &%s;'
|
||||
% (sym, sym) for sym in sorted(c_syms))))
|
||||
with open(cincfile_name, 'w') as cincfile:
|
||||
cincfile.write(cincfile_text)
|
||||
cmd = ('%s %s -D_ISOMAC %s -c %s -o %s'
|
||||
% (args.cc, args.flags, glibcconform.CFLAGS[args.standard],
|
||||
cincfile_name, cincfile_o_name))
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
cmd = ('LC_ALL=C %s -W -s %s > %s'
|
||||
% (args.readelf, cincfile_o_name, cincfile_sym_name))
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
for file, name, bind, defined in list_syms(cincfile_sym_name):
|
||||
if bind == 'GLOBAL' and not defined:
|
||||
sym_text = '[initial] %s' % name
|
||||
seen_where[name] = sym_text
|
||||
all_undef[name] = sym_text
|
||||
current_undef[name] = sym_text
|
||||
|
||||
while current_undef:
|
||||
new_undef = {}
|
||||
for sym, cu_sym in sorted(current_undef.items()):
|
||||
for file in sym_objs[sym]:
|
||||
if file in files_seen:
|
||||
continue
|
||||
files_seen.add(file)
|
||||
for ssym in seen_syms[file]:
|
||||
if ssym not in seen_where:
|
||||
seen_where[ssym] = ('%s -> [%s] %s'
|
||||
% (cu_sym, file, ssym))
|
||||
for usym in strong_undef_syms[file]:
|
||||
if usym not in all_undef:
|
||||
usym_text = '%s -> [%s] %s' % (cu_sym, file, usym)
|
||||
all_undef[usym] = usym_text
|
||||
new_undef[usym] = usym_text
|
||||
current_undef = new_undef
|
||||
|
||||
ret = 0
|
||||
for sym in sorted(seen_where):
|
||||
if sym.startswith('_'):
|
||||
continue
|
||||
if sym in stdsyms:
|
||||
continue
|
||||
print(seen_where[sym])
|
||||
ret = 1
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -187,7 +187,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
|||
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
||||
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
||||
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
||||
tst-unwind-ctor
|
||||
tst-unwind-ctor tst-unwind-main
|
||||
# reldep9
|
||||
tests-internal += loadtest unload unload2 circleload1 \
|
||||
neededtest neededtest2 neededtest3 neededtest4 \
|
||||
|
@ -1495,3 +1495,5 @@ $(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so
|
|||
$(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so
|
||||
|
||||
$(objpfx)tst-unwind-ctor: $(objpfx)tst-unwind-ctor-lib.so
|
||||
|
||||
CFLAGS-tst-unwind-main.c += -funwind-tables
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* Test unwinding through main.
|
||||
Copyright (C) 2018 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 <unwind.h>
|
||||
#include <unistd.h>
|
||||
#include <support/test-driver.h>
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
callback (struct _Unwind_Context *ctx, void *arg)
|
||||
{
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
/* Arrange for this test to be killed if _Unwind_Backtrace runs into an
|
||||
endless loop. We cannot use the test driver because the complete
|
||||
call chain needs to be compiled with -funwind-tables so that
|
||||
_Unwind_Backtrace is able to reach _start. */
|
||||
alarm (DEFAULT_TIMEOUT);
|
||||
_Unwind_Backtrace (callback, 0);
|
||||
}
|
|
@ -323,9 +323,9 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
|
|||
/* FALLTHROUGH */
|
||||
|
||||
dead:
|
||||
err = EIO;
|
||||
err = EIEIO;
|
||||
|
||||
/* The EIO return indicates cancellation, so clear the flag. */
|
||||
/* The EIEIO return indicates cancellation, so clear the flag. */
|
||||
ss->cancel = 0;
|
||||
break;
|
||||
|
||||
|
|
|
@ -77,9 +77,9 @@ positive_sign ""
|
|||
negative_sign "-"
|
||||
int_frac_digits 2
|
||||
frac_digits 2
|
||||
p_cs_precedes 1
|
||||
p_cs_precedes 0
|
||||
p_sep_by_space 1
|
||||
n_cs_precedes 1
|
||||
n_cs_precedes 0
|
||||
n_sep_by_space 1
|
||||
p_sign_posn 1
|
||||
n_sign_posn 1
|
||||
|
@ -88,7 +88,7 @@ END LC_MONETARY
|
|||
LC_NUMERIC
|
||||
decimal_point ","
|
||||
thousands_sep "."
|
||||
grouping 0;0
|
||||
grouping 3;3
|
||||
END LC_NUMERIC
|
||||
|
||||
LC_TIME
|
||||
|
|
|
@ -172,7 +172,7 @@ include ../Rules
|
|||
install-data subdir_install: install
|
||||
# Generated files requiring python: libm-err.texi
|
||||
# Generated files requiring perl: summary.texi
|
||||
ifneq ($(if $(PYTHON),$(PERL),no),no)
|
||||
ifneq ($(PERL),no)
|
||||
ifneq ($(strip $(MAKEINFO)),:)
|
||||
install: $(inst_infodir)/libc.info
|
||||
@if $(SHELL) -c '$(INSTALL_INFO) --version' >/dev/null 2>&1; then \
|
||||
|
|
|
@ -575,11 +575,11 @@ with any version of @code{sed}. As of release time, @code{sed} version
|
|||
4.5 is the newest verified to work to build @theglibc{}.
|
||||
|
||||
@item
|
||||
Python 2.7/3.4 or later
|
||||
Python 3.4 or later
|
||||
|
||||
Python is required to build the @glibcadj{} manual and to run some
|
||||
tests. As of release time, Python 3.6 is the newest verified to work
|
||||
for testing @theglibc{}.
|
||||
Python is required to build @theglibc{}. As of release time, Python
|
||||
3.6 is the newest verified to work for building and testing
|
||||
@theglibc{}.
|
||||
|
||||
@item PExpect 4.0
|
||||
|
||||
|
|
|
@ -255,7 +255,6 @@ tests += test-math-isinff test-math-iszero test-math-issignaling \
|
|||
test-math-iscanonical test-math-cxx11 test-math-iseqsig
|
||||
endif
|
||||
|
||||
ifdef PYTHON
|
||||
libm-vec-tests = $(addprefix test-,$(libmvec-tests))
|
||||
libm-test-support = $(foreach t,$(test-types),libm-test-support-$(t))
|
||||
test-extras += $(libm-test-support)
|
||||
|
@ -351,9 +350,7 @@ $(libm-test-c-narrow-obj): $(objpfx)libm-test%.c: libm-test%.inc \
|
|||
auto-libm-test-out%
|
||||
$(make-target-directory)
|
||||
$(PYTHON) gen-libm-test.py -c $< -a auto-libm-test-out$* -C $@
|
||||
endif
|
||||
|
||||
ifdef PYTHON
|
||||
tgmath3-macros = atan2 cbrt ceil copysign erf erfc exp2 expm1 fdim floor \
|
||||
fma fmax fmin fmod frexp hypot ilogb ldexp lgamma llrint \
|
||||
llround log10 log1p log2 logb lrint lround nearbyint \
|
||||
|
@ -380,7 +377,6 @@ tests-special += $(objpfx)test-tgmath3-macro-list.out
|
|||
$(objpfx)test-tgmath3-macro-list.out: gen-tgmath-tests.py
|
||||
$(PYTHON) $< check-list $(tgmath3-macros) > $@; \
|
||||
$(evaluate-test)
|
||||
endif
|
||||
|
||||
libm-test-fast-math-cflags = -fno-builtin -D__FAST_MATH__ -DTEST_FAST_MATH
|
||||
libm-test-vec-cflags = $(libm-test-fast-math-cflags) -fno-inline \
|
||||
|
@ -476,7 +472,6 @@ $(objpfx)gen-libm-templates.stmp: Makefile
|
|||
$(foreach t, $(call type-foreach, $(gen-all-calls)), \
|
||||
$(objpfx)$(t).c): $(objpfx)gen-libm-templates.stmp
|
||||
|
||||
ifdef PYTHON
|
||||
# This must come after the inclusion of sysdeps Makefiles via Rules.
|
||||
|
||||
$(foreach t,$(libm-tests-normal),$(objpfx)$(t).c): $(objpfx)test-%.c:
|
||||
|
@ -637,11 +632,6 @@ regen-ulps: $(addprefix $(objpfx),$(libm-tests))
|
|||
echo "Difference between the current baseline and the new baseline is:";\
|
||||
diff -urN $(ulps-file) $(objpfx)NewUlps; \
|
||||
echo "Copy $(objpfx)NewUlps to $(ulps-file) (relative to source)."
|
||||
else
|
||||
regen-ulps:
|
||||
@echo "Automatic regeneration of ULPs requires python."; \
|
||||
exit 1;
|
||||
endif
|
||||
|
||||
# The generated sysd-rules file defines rules like this for sources
|
||||
# coming from sysdeps/ directories. These rules find the generic sources.
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <support/blob_repeat.h>
|
||||
#include <support/check.h>
|
||||
#include <support/support.h>
|
||||
#include <support/temp_file.h>
|
||||
|
@ -35,21 +36,16 @@
|
|||
static int
|
||||
do_test (void)
|
||||
{
|
||||
const char *dir = support_create_temp_directory ("bz22786.");
|
||||
const char *lnk = xasprintf ("%s/symlink", dir);
|
||||
char *dir = support_create_temp_directory ("bz22786.");
|
||||
char *lnk = xasprintf ("%s/symlink", dir);
|
||||
const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1;
|
||||
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
#if __GNUC_PREREQ (7, 0)
|
||||
/* GCC 7 warns about too-large allocations; here we need such
|
||||
allocation to succeed for the test to work. */
|
||||
DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
|
||||
#endif
|
||||
char *path = malloc (path_len);
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
struct support_blob_repeat repeat
|
||||
= support_blob_repeat_allocate ("a", 1, path_len);
|
||||
char *path = repeat.start;
|
||||
if (path == NULL)
|
||||
{
|
||||
printf ("malloc (%zu): %m\n", path_len);
|
||||
printf ("Repeated allocation (%zu bytes): %m\n", path_len);
|
||||
/* On 31-bit s390 the malloc will always fail as we do not have
|
||||
so much memory, and we want to mark the test unsupported.
|
||||
Likewise on systems with little physical memory the test will
|
||||
|
@ -62,7 +58,6 @@ do_test (void)
|
|||
/* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */
|
||||
char *p = mempcpy (path, lnk, strlen (lnk));
|
||||
*(p++) = '/';
|
||||
memset (p, 'a', path_len - (p - path) - 2);
|
||||
p[path_len - (p - path) - 1] = '\0';
|
||||
|
||||
/* This call crashes before the fix for bz22786 on 32-bit platforms. */
|
||||
|
@ -76,6 +71,9 @@ do_test (void)
|
|||
|
||||
/* Cleanup. */
|
||||
unlink (lnk);
|
||||
support_blob_repeat_free (&repeat);
|
||||
free (lnk);
|
||||
free (dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <support/blob_repeat.h>
|
||||
#include <support/test-driver.h>
|
||||
|
||||
#define EXPONENT "e-2147483649"
|
||||
#define SIZE 214748364
|
||||
|
@ -26,21 +28,23 @@
|
|||
static int
|
||||
do_test (void)
|
||||
{
|
||||
char *p = malloc (1 + SIZE + sizeof (EXPONENT));
|
||||
if (p == NULL)
|
||||
struct support_blob_repeat repeat = support_blob_repeat_allocate
|
||||
("0", 1, 1 + SIZE + sizeof (EXPONENT));
|
||||
if (repeat.size == 0)
|
||||
{
|
||||
puts ("malloc failed, cannot test for overflow");
|
||||
return 0;
|
||||
puts ("warning: memory allocation failed, cannot test for overflow");
|
||||
return EXIT_UNSUPPORTED;
|
||||
}
|
||||
char *p = repeat.start;
|
||||
p[0] = '1';
|
||||
memset (p + 1, '0', SIZE);
|
||||
memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT));
|
||||
double d = strtod (p, NULL);
|
||||
if (d != 0)
|
||||
{
|
||||
printf ("strtod returned wrong value: %a\n", d);
|
||||
printf ("error: strtod returned wrong value: %a\n", d);
|
||||
return 1;
|
||||
}
|
||||
support_blob_repeat_free (&repeat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ extra-libs-others = $(extra-libs)
|
|||
extra-libs-noinstall := $(extra-libs)
|
||||
|
||||
libsupport-routines = \
|
||||
blob_repeat \
|
||||
check \
|
||||
check_addrinfo \
|
||||
check_dns_packet \
|
||||
|
@ -190,6 +191,7 @@ $(objpfx)true-container : $(libsupport)
|
|||
tests = \
|
||||
README-testing \
|
||||
tst-support-namespace \
|
||||
tst-support_blob_repeat \
|
||||
tst-support_capture_subprocess \
|
||||
tst-support_format_dns_packet \
|
||||
tst-support_quote_blob \
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
/* Repeating a memory blob, with alias mapping optimization.
|
||||
Copyright (C) 2018 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 <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <support/blob_repeat.h>
|
||||
#include <support/check.h>
|
||||
#include <support/test-driver.h>
|
||||
#include <support/support.h>
|
||||
#include <support/xunistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
||||
/* Small allocations should use malloc directly instead of the mmap
|
||||
optimization because mappings carry a lot of overhead. */
|
||||
static const size_t maximum_small_size = 4 * 1024 * 1024;
|
||||
|
||||
/* Internal helper for fill. */
|
||||
static void
|
||||
fill0 (char *target, const char *element, size_t element_size,
|
||||
size_t count)
|
||||
{
|
||||
while (count > 0)
|
||||
{
|
||||
memcpy (target, element, element_size);
|
||||
target += element_size;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill the buffer at TARGET with COUNT copies of the ELEMENT_SIZE
|
||||
bytes starting at ELEMENT. */
|
||||
static void
|
||||
fill (char *target, const char *element, size_t element_size,
|
||||
size_t count)
|
||||
{
|
||||
if (element_size == 0 || count == 0)
|
||||
return;
|
||||
else if (element_size == 1)
|
||||
memset (target, element[0], count);
|
||||
else if (element_size == sizeof (wchar_t))
|
||||
{
|
||||
wchar_t wc;
|
||||
memcpy (&wc, element, sizeof (wc));
|
||||
wmemset ((wchar_t *) target, wc, count);
|
||||
}
|
||||
else if (element_size < 1024 && count > 4096)
|
||||
{
|
||||
/* Use larger copies for really small element sizes. */
|
||||
char buffer[8192];
|
||||
size_t buffer_count = sizeof (buffer) / element_size;
|
||||
fill0 (buffer, element, element_size, buffer_count);
|
||||
while (count > 0)
|
||||
{
|
||||
size_t copy_count = buffer_count;
|
||||
if (copy_count > count)
|
||||
copy_count = count;
|
||||
size_t copy_bytes = copy_count * element_size;
|
||||
memcpy (target, buffer, copy_bytes);
|
||||
target += copy_bytes;
|
||||
count -= copy_count;
|
||||
}
|
||||
}
|
||||
else
|
||||
fill0 (target, element, element_size, count);
|
||||
}
|
||||
|
||||
/* Use malloc instead of mmap for small allocations and unusual size
|
||||
combinations. */
|
||||
static struct support_blob_repeat
|
||||
allocate_malloc (size_t total_size, const void *element, size_t element_size,
|
||||
size_t count)
|
||||
{
|
||||
void *buffer = malloc (total_size);
|
||||
if (buffer == NULL)
|
||||
return (struct support_blob_repeat) { 0 };
|
||||
fill (buffer, element, element_size, count);
|
||||
return (struct support_blob_repeat)
|
||||
{
|
||||
.start = buffer,
|
||||
.size = total_size,
|
||||
.use_malloc = true
|
||||
};
|
||||
}
|
||||
|
||||
/* Return the least common multiple of PAGE_SIZE and ELEMENT_SIZE,
|
||||
avoiding overflow. This assumes that PAGE_SIZE is a power of
|
||||
two. */
|
||||
static size_t
|
||||
minimum_stride_size (size_t page_size, size_t element_size)
|
||||
{
|
||||
TEST_VERIFY_EXIT (page_size > 0);
|
||||
TEST_VERIFY_EXIT (element_size > 0);
|
||||
|
||||
/* Compute the number of trailing zeros common to both sizes. */
|
||||
unsigned int common_zeros = __builtin_ctzll (page_size | element_size);
|
||||
|
||||
/* In the product, this power of two appears twice, but in the least
|
||||
common multiple, it appears only once. Therefore, shift one
|
||||
factor. */
|
||||
size_t multiple;
|
||||
if (__builtin_mul_overflow (page_size >> common_zeros, element_size,
|
||||
&multiple))
|
||||
return 0;
|
||||
return multiple;
|
||||
}
|
||||
|
||||
/* Allocations larger than maximum_small_size potentially use mmap
|
||||
with alias mappings. */
|
||||
static struct support_blob_repeat
|
||||
allocate_big (size_t total_size, const void *element, size_t element_size,
|
||||
size_t count)
|
||||
{
|
||||
unsigned long page_size = xsysconf (_SC_PAGESIZE);
|
||||
size_t stride_size = minimum_stride_size (page_size, element_size);
|
||||
if (stride_size == 0)
|
||||
{
|
||||
errno = EOVERFLOW;
|
||||
return (struct support_blob_repeat) { 0 };
|
||||
}
|
||||
|
||||
/* Ensure that the stride size is at least maximum_small_size. This
|
||||
is necessary to reduce the number of distinct mappings. */
|
||||
if (stride_size < maximum_small_size)
|
||||
stride_size
|
||||
= ((maximum_small_size + stride_size - 1) / stride_size) * stride_size;
|
||||
|
||||
if (stride_size > total_size)
|
||||
/* The mmap optimization would not save anything. */
|
||||
return allocate_malloc (total_size, element, element_size, count);
|
||||
|
||||
/* Reserve the memory region. If we cannot create the mapping,
|
||||
there is no reason to set up the backing file. */
|
||||
void *target = mmap (NULL, total_size, PROT_NONE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (target == MAP_FAILED)
|
||||
return (struct support_blob_repeat) { 0 };
|
||||
|
||||
/* Create the backing file for the repeated mapping. Call mkstemp
|
||||
directly to remove the resources backing the temporary file
|
||||
immediately, once support_blob_repeat_free is called. Using
|
||||
create_temp_file would result in a warning during post-test
|
||||
cleanup. */
|
||||
int fd;
|
||||
{
|
||||
char *temppath = xasprintf ("%s/support_blob_repeat-XXXXXX", test_dir);
|
||||
fd = mkstemp (temppath);
|
||||
if (fd < 0)
|
||||
FAIL_EXIT1 ("mkstemp (\"%s\"): %m", temppath);
|
||||
xunlink (temppath);
|
||||
free (temppath);
|
||||
}
|
||||
|
||||
/* Make sure that there is backing storage, so that the fill
|
||||
operation will not fault. */
|
||||
if (posix_fallocate (fd, 0, stride_size) != 0)
|
||||
FAIL_EXIT1 ("posix_fallocate (%zu): %m", stride_size);
|
||||
|
||||
/* The stride size must still be a multiple of the page size and
|
||||
element size. */
|
||||
TEST_VERIFY_EXIT ((stride_size % page_size) == 0);
|
||||
TEST_VERIFY_EXIT ((stride_size % element_size) == 0);
|
||||
|
||||
/* Fill the backing store. */
|
||||
{
|
||||
void *ptr = mmap (target, stride_size, PROT_READ | PROT_WRITE,
|
||||
MAP_FIXED | MAP_FILE | MAP_SHARED, fd, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
xmunmap (target, total_size);
|
||||
xclose (fd);
|
||||
errno = saved_errno;
|
||||
return (struct support_blob_repeat) { 0 };
|
||||
}
|
||||
if (ptr != target)
|
||||
FAIL_EXIT1 ("mapping of %zu bytes moved from %p to %p",
|
||||
stride_size, target, ptr);
|
||||
|
||||
/* Write the repeating data. */
|
||||
fill (target, element, element_size, stride_size / element_size);
|
||||
|
||||
/* Return to a PROT_NONE mapping, just to be on the safe side. */
|
||||
ptr = mmap (target, stride_size, PROT_NONE,
|
||||
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
FAIL_EXIT1 ("Failed to reinstate PROT_NONE mapping: %m");
|
||||
if (ptr != target)
|
||||
FAIL_EXIT1 ("PROT_NONE mapping of %zu bytes moved from %p to %p",
|
||||
stride_size, target, ptr);
|
||||
}
|
||||
|
||||
/* Create the alias mappings. */
|
||||
{
|
||||
size_t remaining_size = total_size;
|
||||
char *current = target;
|
||||
int flags = MAP_FIXED | MAP_FILE | MAP_PRIVATE;
|
||||
#ifdef MAP_NORESERVE
|
||||
flags |= MAP_NORESERVE;
|
||||
#endif
|
||||
while (remaining_size > 0)
|
||||
{
|
||||
size_t to_map = stride_size;
|
||||
if (to_map > remaining_size)
|
||||
to_map = remaining_size;
|
||||
void *ptr = mmap (current, to_map, PROT_READ | PROT_WRITE,
|
||||
flags, fd, 0);
|
||||
if (ptr == MAP_FAILED)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
xmunmap (target, total_size);
|
||||
xclose (fd);
|
||||
errno = saved_errno;
|
||||
return (struct support_blob_repeat) { 0 };
|
||||
}
|
||||
if (ptr != current)
|
||||
FAIL_EXIT1 ("MAP_PRIVATE mapping of %zu bytes moved from %p to %p",
|
||||
to_map, target, ptr);
|
||||
remaining_size -= to_map;
|
||||
current += to_map;
|
||||
}
|
||||
}
|
||||
|
||||
xclose (fd);
|
||||
|
||||
return (struct support_blob_repeat)
|
||||
{
|
||||
.start = target,
|
||||
.size = total_size,
|
||||
.use_malloc = false
|
||||
};
|
||||
}
|
||||
|
||||
struct support_blob_repeat
|
||||
support_blob_repeat_allocate (const void *element, size_t element_size,
|
||||
size_t count)
|
||||
{
|
||||
size_t total_size;
|
||||
if (__builtin_mul_overflow (element_size, count, &total_size))
|
||||
{
|
||||
errno = EOVERFLOW;
|
||||
return (struct support_blob_repeat) { 0 };
|
||||
}
|
||||
if (total_size <= maximum_small_size)
|
||||
return allocate_malloc (total_size, element, element_size, count);
|
||||
else
|
||||
return allocate_big (total_size, element, element_size, count);
|
||||
}
|
||||
|
||||
void
|
||||
support_blob_repeat_free (struct support_blob_repeat *blob)
|
||||
{
|
||||
if (blob->size > 0)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
if (blob->use_malloc)
|
||||
free (blob->start);
|
||||
else
|
||||
xmunmap (blob->start, blob->size);
|
||||
errno = saved_errno;
|
||||
}
|
||||
*blob = (struct support_blob_repeat) { 0 };
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* Repeating a memory blob, with alias mapping optimization.
|
||||
Copyright (C) 2018 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/>. */
|
||||
|
||||
#ifndef SUPPORT_BLOB_REPEAT_H
|
||||
#define SUPPORT_BLOB_REPEAT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct support_blob_repeat
|
||||
{
|
||||
void *start;
|
||||
size_t size;
|
||||
bool use_malloc;
|
||||
};
|
||||
|
||||
/* Return an allocation of COUNT elements, each of ELEMENT_SIZE bytes,
|
||||
initialized with the bytes starting at ELEMENT. The memory is
|
||||
writable (and thus counts towards the commit charge). In case of
|
||||
on error, all members of the return struct are zero-initialized,
|
||||
and errno is set accordingly. */
|
||||
struct support_blob_repeat support_blob_repeat_allocate (const void *element,
|
||||
size_t element_size,
|
||||
size_t count);
|
||||
|
||||
/* Deallocate the blob created by support_blob_repeat_allocate. */
|
||||
void support_blob_repeat_free (struct support_blob_repeat *);
|
||||
|
||||
#endif /* SUPPORT_BLOB_REPEAT_H */
|
|
@ -0,0 +1,85 @@
|
|||
/* Tests for <support/blob_repeat.h>
|
||||
Copyright (C) 2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <support/blob_repeat.h>
|
||||
#include <support/check.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
struct support_blob_repeat repeat
|
||||
= support_blob_repeat_allocate ("5", 1, 5);
|
||||
TEST_COMPARE_BLOB (repeat.start, repeat.size, "55555", 5);
|
||||
support_blob_repeat_free (&repeat);
|
||||
|
||||
repeat = support_blob_repeat_allocate ("ABC", 3, 3);
|
||||
TEST_COMPARE_BLOB (repeat.start, repeat.size, "ABCABCABC", 9);
|
||||
support_blob_repeat_free (&repeat);
|
||||
|
||||
repeat = support_blob_repeat_allocate ("abc", 4, 3);
|
||||
TEST_COMPARE_BLOB (repeat.start, repeat.size, "abc\0abc\0abc", 12);
|
||||
support_blob_repeat_free (&repeat);
|
||||
|
||||
size_t gigabyte = 1U << 30;
|
||||
repeat = support_blob_repeat_allocate ("X", 1, gigabyte + 1);
|
||||
if (repeat.start == NULL)
|
||||
puts ("warning: not enough memory for 1 GiB mapping");
|
||||
else
|
||||
{
|
||||
TEST_COMPARE (repeat.size, gigabyte + 1);
|
||||
{
|
||||
unsigned char *p = repeat.start;
|
||||
for (size_t i = 0; i < gigabyte + 1; ++i)
|
||||
if (p[i] != 'X')
|
||||
FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i);
|
||||
|
||||
/* Check that there is no sharing across the mapping. */
|
||||
p[0] = 'Y';
|
||||
p[1U << 24] = 'Z';
|
||||
for (size_t i = 0; i < gigabyte + 1; ++i)
|
||||
if (i == 0)
|
||||
TEST_COMPARE (p[i], 'Y');
|
||||
else if (i == 1U << 24)
|
||||
TEST_COMPARE (p[i], 'Z');
|
||||
else if (p[i] != 'X')
|
||||
FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i);
|
||||
}
|
||||
}
|
||||
support_blob_repeat_free (&repeat);
|
||||
|
||||
repeat = support_blob_repeat_allocate ("012345678", 9, 10 * 1000 * 1000);
|
||||
if (repeat.start == NULL)
|
||||
puts ("warning: not enough memory for large mapping");
|
||||
else
|
||||
{
|
||||
unsigned char *p = repeat.start;
|
||||
for (int i = 0; i < 10 * 1000 * 1000; ++i)
|
||||
for (int j = 0; j <= 8; ++j)
|
||||
if (p[i * 9 + j] != '0' + j)
|
||||
{
|
||||
printf ("error: element %d index %d\n", i, j);
|
||||
TEST_COMPARE (p[i * 9 + j], '0' + j);
|
||||
}
|
||||
}
|
||||
support_blob_repeat_free (&repeat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
|
@ -974,7 +974,20 @@ TRANS You did @strong{what}? */
|
|||
#endif
|
||||
#ifdef EIEIO
|
||||
/*
|
||||
TRANS Go home and have a glass of warm, dairy-fresh milk. */
|
||||
TRANS Go home and have a glass of warm, dairy-fresh milk.
|
||||
TRANS @c Okay. Since you are dying to know, I'll tell you.
|
||||
TRANS @c This is a joke, obviously. There is a children's song which begins,
|
||||
TRANS @c "Old McDonald had a farm, e-i-e-i-o." Every time I see the (real)
|
||||
TRANS @c errno macro EIO, I think about that song. Probably most of my
|
||||
TRANS @c compatriots who program on Unix do, too. One of them must have stayed
|
||||
TRANS @c up a little too late one night and decided to add it to Hurd or Glibc.
|
||||
TRANS @c Whoever did it should be castigated, but it made me laugh.
|
||||
TRANS @c --jtobey@channel1.com
|
||||
TRANS @c
|
||||
TRANS @c "bought the farm" means "died". -jtobey
|
||||
TRANS @c
|
||||
TRANS @c Translators, please do not translate this litteraly, translate it into
|
||||
TRANS @c an idiomatic funny way of saying that the computer died. */
|
||||
[ERR_REMAP (EIEIO)] = N_("Computer bought the farm"),
|
||||
# if EIEIO > ERR_MAX
|
||||
# undef ERR_MAX
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
__libc_start_main wants this in a5. */
|
||||
|
||||
ENTRY (ENTRY_POINT)
|
||||
/* Terminate call stack by noting ra is undefined. Use a dummy
|
||||
.cfi_label to force starting the FDE. */
|
||||
.cfi_label .Ldummy
|
||||
cfi_undefined (ra)
|
||||
call .Lload_gp
|
||||
mv a5, a0 /* rtld_fini. */
|
||||
/* main may be in a shared library. */
|
||||
|
@ -54,7 +58,8 @@ ENTRY (ENTRY_POINT)
|
|||
lla a4, __libc_csu_fini
|
||||
mv a6, sp /* stack_end. */
|
||||
|
||||
tail __libc_start_main@plt
|
||||
call __libc_start_main@plt
|
||||
ebreak
|
||||
END (ENTRY_POINT)
|
||||
|
||||
/* Dynamic links need the global pointer to be initialized prior to calling
|
||||
|
|
Loading…
Reference in New Issue