mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 05:59:27 +08:00
Compare commits
88
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3a3a9808a | ||
|
|
50245c56a6 | ||
|
|
bc92b40b15 | ||
|
|
5961de5588 | ||
|
|
12726491af | ||
|
|
ffaa52a30e | ||
|
|
015e8ef482 | ||
|
|
0f731d92cd | ||
|
|
e9996c743d | ||
|
|
b9bd146ad1 | ||
|
|
3f3229739e | ||
|
|
a5aa0df24a | ||
|
|
623279d52a | ||
|
|
0d61a81612 | ||
|
|
7ace114369 | ||
|
|
a36971bebe | ||
|
|
b2d4136341 | ||
|
|
a8e580f6a0 | ||
|
|
6b29e74c73 | ||
|
|
249639137e | ||
|
|
a29c483d3c | ||
|
|
5c47592adb | ||
|
|
70685abb80 | ||
|
|
18f97e140d | ||
|
|
49d25edb76 | ||
|
|
2678adc8eb | ||
|
|
82a0bf8d33 | ||
|
|
c82b609596 | ||
|
|
af51ed63d0 | ||
|
|
ea50bcc538 | ||
|
|
e03cefb56b | ||
|
|
81ae821113 | ||
|
|
cdfa80fad3 | ||
|
|
e2cefe16c3 | ||
|
|
2324aa7aa8 | ||
|
|
69b0bacd72 | ||
|
|
a3d4ff18c5 | ||
|
|
202b4f794a | ||
|
|
aafc0024b3 | ||
|
|
b8985facc9 | ||
|
|
1c0531af67 | ||
|
|
098e6c969c | ||
|
|
3a9c4dbe30 | ||
|
|
93d68cfbeb | ||
|
|
f1c94392d9 | ||
|
|
4e971f5558 | ||
|
|
3d3cd10c4e | ||
|
|
5396eb7045 | ||
|
|
980089ebab | ||
|
|
20b13fa08b | ||
|
|
617376a04b | ||
|
|
b5eecf35d9 | ||
|
|
d70dd7d722 | ||
|
|
b416f91801 | ||
|
|
3e3146fd86 | ||
|
|
28c3a25bc2 | ||
|
|
1d95a42ead | ||
|
|
0f61d77aef | ||
|
|
db59f39646 | ||
|
|
59cb960a22 | ||
|
|
df0669d41d | ||
|
|
d692a3444e | ||
|
|
d109f366ce | ||
|
|
c6ce3bed6d | ||
|
|
800ab3e463 | ||
|
|
568e673fa9 | ||
|
|
6f1d069804 | ||
|
|
b4a0ea4a2c | ||
|
|
b9476fa9aa | ||
|
|
5bba5e06e0 | ||
|
|
f2e3dacbff | ||
|
|
2077c0e385 | ||
|
|
70dd422b6f | ||
|
|
1ab0003872 | ||
|
|
2b13da5e0e | ||
|
|
19e158b7f0 | ||
|
|
b6804fb36e | ||
|
|
ef1cb97f69 | ||
|
|
7cac99621e | ||
|
|
e80612e596 | ||
|
|
3c779ab155 | ||
|
|
84c3993f1f | ||
|
|
45267197ff | ||
|
|
fae194043a | ||
|
|
fcea66cd46 | ||
|
|
9a953f9a48 | ||
|
|
b9957a70b8 | ||
|
|
e24269f74b |
File diff suppressed because it is too large
Load Diff
@@ -480,7 +480,7 @@ build the GNU C Library:
|
||||
GCC 12.1 or higher is required. In general it is recommended to
|
||||
use the newest version of the compiler that is known to work for
|
||||
building the GNU C Library, as newer compilers usually produce
|
||||
better code. As of release time, GCC 15.2.1 is the newest compiler
|
||||
better code. As of release time, GCC 16.1.1 is the newest compiler
|
||||
verified to work to build the GNU C Library.
|
||||
|
||||
For multi-arch support it is recommended to use a GCC which has
|
||||
@@ -502,7 +502,7 @@ build the GNU C Library:
|
||||
|
||||
You must use GNU 'binutils' (as and ld) to build the GNU C Library.
|
||||
No other assembler or linker has the necessary functionality at the
|
||||
moment. As of release time, GNU 'binutils' 2.45.1 is the newest
|
||||
moment. As of release time, GNU 'binutils' 2.46.1 is the newest
|
||||
verified to work to build the GNU C Library.
|
||||
|
||||
* GNU 'texinfo' 4.7 or later
|
||||
@@ -511,7 +511,7 @@ build the GNU C Library:
|
||||
need this version of the 'texinfo' package. Earlier versions do
|
||||
not understand all the tags used in the document, and the
|
||||
installation mechanism for the info files is not present or works
|
||||
differently. As of release time, 'texinfo' 7.2 is the newest
|
||||
differently. As of release time, 'texinfo' 7.3 is the newest
|
||||
verified to work to build the GNU C Library.
|
||||
|
||||
* GNU 'awk' 3.1.2, or higher
|
||||
@@ -519,7 +519,7 @@ build the GNU C Library:
|
||||
'awk' is used in several places to generate files. Some 'gawk'
|
||||
extensions are used, including the 'asorti' function, which was
|
||||
introduced in version 3.1.2 of 'gawk'. As of release time, 'gawk'
|
||||
version 5.3.2 is the newest verified to work to build the GNU C
|
||||
version 5.4.1 is the newest verified to work to build the GNU C
|
||||
Library.
|
||||
|
||||
Testing the GNU C Library requires 'gawk' to be compiled with
|
||||
@@ -536,19 +536,19 @@ build the GNU C Library:
|
||||
|
||||
Perl is not required, but if present it is used in some tests and
|
||||
the 'mtrace' program, to build the GNU C Library manual. As of
|
||||
release time 'perl' version 5.42.0 is the newest verified to work
|
||||
release time 'perl' version 5.44.0 is the newest verified to work
|
||||
to build the GNU C Library.
|
||||
|
||||
* GNU 'sed' 3.02 or newer
|
||||
|
||||
'Sed' is used in several places to generate files. Most scripts
|
||||
work with any version of 'sed'. As of release time, 'sed' version
|
||||
4.9 is the newest verified to work to build the GNU C Library.
|
||||
4.10 is the newest verified to work to build the GNU C Library.
|
||||
|
||||
* Python 3.4 or later
|
||||
|
||||
Python is required to build the GNU C Library. As of release time,
|
||||
Python 3.14.0 is the newest verified to work for building and
|
||||
Python 3.14.6 is the newest verified to work for building and
|
||||
testing the GNU C Library.
|
||||
|
||||
* PExpect 4.0
|
||||
@@ -634,7 +634,7 @@ components of the GNU C Library installation to be in '/lib' and some in
|
||||
Library with '--prefix=/usr'. If you set some other prefix or allow it
|
||||
to default to '/usr/local', then all the components are installed there.
|
||||
|
||||
As of release time, Linux version 6.12 is the newest stable version
|
||||
As of release time, Linux version 7.1 is the newest stable version
|
||||
verified to work to build the GNU C Library.
|
||||
|
||||
Reporting Bugs
|
||||
|
||||
+17
@@ -782,6 +782,14 @@ run-built-tests = yes
|
||||
endif
|
||||
endif
|
||||
|
||||
# Whether the timing-sensitive test runs are serialized: each is run with
|
||||
# .NOTPARALLEL and, at the top level, ordered after the rest of the test run.
|
||||
# This is the default; 'make check-parallel' clears it to run every test
|
||||
# concurrently.
|
||||
ifndef serialize-tests
|
||||
serialize-tests = yes
|
||||
endif
|
||||
|
||||
# Whether to build the static math tests
|
||||
ifndef build-math-static-tests
|
||||
build-math-static-tests = no
|
||||
@@ -815,8 +823,15 @@ $(subst $(empty) ,:,$(strip $(patsubst -Wl$(comma)-rpath-link=%, %,\
|
||||
run-via-rtld-prefix = \
|
||||
$(if $(strip $(filter $(notdir $(built-program-file)), \
|
||||
$(tests-static) $(xtests-static))),, $(rtld-prefix))
|
||||
# $(container-via-rtld-prefix) is like $(run-via-rtld-prefix), but for the
|
||||
# support/test-container helper, which is always dynamically linked even
|
||||
# when the test it launches is static. It must therefore always run
|
||||
# through the newly built loader, unlike $(run-via-rtld-prefix) which is
|
||||
# empty for tests listed in tests-static or xtests-static.
|
||||
container-via-rtld-prefix = $(rtld-prefix)
|
||||
else
|
||||
run-via-rtld-prefix =
|
||||
container-via-rtld-prefix =
|
||||
endif
|
||||
# $(run-program-env) is the default environment variable settings to
|
||||
# use when running a program built with the newly built library.
|
||||
@@ -883,6 +898,7 @@ endif
|
||||
|
||||
ifeq (yes,$(build-hardcoded-path-in-tests))
|
||||
test-via-rtld-prefix =
|
||||
test-container-via-rtld-prefix =
|
||||
test-program-prefix-before-env = $(test-wrapper-env)
|
||||
test-program-prefix-after-env =
|
||||
test-program-prefix = $(test-program-prefix-before-env) $(run-program-env) \
|
||||
@@ -894,6 +910,7 @@ test-program-cmd = $(test-program-cmd-before-env) $(run-program-env) \
|
||||
host-test-program-cmd = $(built-program-file)
|
||||
else
|
||||
test-via-rtld-prefix = $(run-via-rtld-prefix)
|
||||
test-container-via-rtld-prefix = $(container-via-rtld-prefix)
|
||||
test-program-prefix-before-env = $(run-program-prefix-before-env)
|
||||
test-program-prefix-after-env = $(run-program-prefix-after-env)
|
||||
test-program-prefix = $(run-program-prefix)
|
||||
|
||||
@@ -54,9 +54,6 @@ configure: configure.ac aclocal.m4; $(autoconf-it)
|
||||
endif # $(AUTOCONF) = no
|
||||
|
||||
|
||||
# We don't want to run anything here in parallel.
|
||||
.NOTPARALLEL:
|
||||
|
||||
# These are the targets that are made by making them in each subdirectory.
|
||||
+subdir_targets := subdir_lib objects objs others subdir_mostlyclean \
|
||||
subdir_clean subdir_distclean subdir_realclean \
|
||||
@@ -129,6 +126,13 @@ lib-noranlib: subdir_lib
|
||||
ifeq (yes,$(build-shared))
|
||||
# Build the shared object from the PIC object library.
|
||||
lib: $(common-objpfx)libc.so $(common-objpfx)linkobj/libc.so
|
||||
ifdef libc.so-version
|
||||
# Every program linked in the others pass lists the versioned name
|
||||
# (through link-libc-between-gnulib) as a prerequisite, and the rule
|
||||
# creating the symbolic link is visible in every sub-make. Build it
|
||||
# here once so the concurrent sub-makes do not race to create it.
|
||||
lib: $(common-objpfx)libc.so$(libc.so-version)
|
||||
endif
|
||||
endif # $(build-shared)
|
||||
|
||||
# Used to build testrun.sh.
|
||||
@@ -490,6 +494,151 @@ subdir=$(@D)$(if $($(@D)-srcdir),\
|
||||
endef
|
||||
|
||||
.PHONY: $(+subdir_targets) $(all-subdirs-targets)
|
||||
|
||||
# Encode the topological ordering computed by scripts/gen-sorted.awk as
|
||||
# explicit dependencies between the per-subdirectory targets, so that
|
||||
# independent subdirectories build concurrently. In summary:
|
||||
#
|
||||
# * Every subdirectory depends on the first sorted one (csu, or mach on
|
||||
# Hurd): its sub-make also materializes the shared generated files in
|
||||
# $(common-objpfx) (abi-versions.h, sysd-syscalls, before-compile
|
||||
# headers, ...) that concurrent sub-makes would otherwise race to
|
||||
# create.
|
||||
#
|
||||
# * The edges requested by the Depend files (emitted by gen-sorted.awk
|
||||
# as subdir-deps-*) are preserved.
|
||||
#
|
||||
# * elf stays last for the object-building classes, as in the sorted
|
||||
# list: its rtld link consumes $(common-objpfx)libc_pic.a, which
|
||||
# aggregates every other subdirectory's objects, and its rtld-Rules
|
||||
# recursion compiles into the other subdirectories' object
|
||||
# directories. The others/tests/xtests classes have no such
|
||||
# dependency (the pass barriers below provide everything they need),
|
||||
# so elf is unordered there.
|
||||
#
|
||||
# * Only target classes without cross-directory file conflicts use this
|
||||
# sparse ordering; everything else (install, clean, abi, stubs) keeps
|
||||
# the previous total order via a serial chain.
|
||||
|
||||
+elf_last_subdir_targets := \
|
||||
subdir_lib objects \
|
||||
objs \
|
||||
subdir_objs \
|
||||
# +elf_last_subdir_targets
|
||||
+parallel_subdir_targets := \
|
||||
$(+elf_last_subdir_targets) \
|
||||
others \
|
||||
tests \
|
||||
xtests \
|
||||
# +parallel_subdir_targets
|
||||
+serial_subdir_targets := $(filter-out $(+parallel_subdir_targets),\
|
||||
$(+subdir_targets))
|
||||
|
||||
# The tests and xtests classes run, rather than build, the per-directory
|
||||
# test programs; once the 'others' pass barrier below has built the tree
|
||||
# they are mutually independent and carry no cross-directory ordering.
|
||||
# Keeping them out of the generated-file and Depend edges below is what
|
||||
# lets 'make subdir/tests' run only that subdirectory's tests.
|
||||
+barrier_only_subdir_targets := tests xtests
|
||||
+ordered_parallel_subdir_targets := \
|
||||
$(filter-out $(+barrier_only_subdir_targets),$(+parallel_subdir_targets))
|
||||
|
||||
# The subdirectories that generate shared files in $(common-objpfx)
|
||||
# consumed by the rest of the build without explicit dependencies: csu
|
||||
# provides the gen-as-const headers, and on Hurd the mach and hurd
|
||||
# directories generate the MiG RPC headers (every other subdirectory
|
||||
# otherwise runs a nested make in hurd/ to create them, racing under
|
||||
# parallel recursion; see sysdeps/mach/hurd/Makefile). Run them serially,
|
||||
# in their sorted order (mach, hurd, csu).
|
||||
+subdir-pregen := $(filter mach hurd csu,$(subdirs))
|
||||
+subdir-rest := $(filter-out $(+subdir-pregen),$(subdirs))
|
||||
|
||||
$(foreach t,$(+ordered_parallel_subdir_targets),$(eval \
|
||||
$(addsuffix /$(t),$(+subdir-rest)): $(addsuffix /$(t),$(+subdir-pregen))))
|
||||
+subdir-pregen-prev :=
|
||||
$(foreach d,$(+subdir-pregen),$(foreach t,$(+ordered_parallel_subdir_targets),$(eval \
|
||||
$(d)/$(t): $(addsuffix /$(t),$(+subdir-pregen-prev))))\
|
||||
$(eval +subdir-pregen-prev := $(d)))
|
||||
# For the classes where elf is forced last, edges pointing to elf are
|
||||
# dropped: the sorted list always overrides such Depend requests today
|
||||
# (e.g. support/Depend), and the elf-last edges below would otherwise
|
||||
# create a cycle. The remaining classes honor them.
|
||||
$(foreach t,$(+elf_last_subdir_targets),$(foreach d,$(+subdir-rest),$(eval \
|
||||
$(d)/$(t): $(addsuffix /$(t),\
|
||||
$(filter-out elf,$(filter $(subdirs),$(subdir-deps-$(d))))))))
|
||||
$(foreach t,$(filter-out $(+elf_last_subdir_targets),\
|
||||
$(+ordered_parallel_subdir_targets)),\
|
||||
$(foreach d,$(+subdir-rest),$(eval \
|
||||
$(d)/$(t): $(addsuffix /$(t),$(filter $(subdirs),$(subdir-deps-$(d)))))))
|
||||
ifneq (,$(filter elf,$(subdirs)))
|
||||
$(foreach t,$(+elf_last_subdir_targets),$(eval \
|
||||
elf/$(t): $(addsuffix /$(t),$(filter-out elf,$(subdirs)))))
|
||||
endif
|
||||
|
||||
# Pass barriers: a subdirectory 'others' build links programs against
|
||||
# the libraries, so the 'lib' pass (including the top-level libc.so
|
||||
# link) must have completed.
|
||||
# 'tests' and 'xtests' additionally require the 'others' pass. The
|
||||
# testroot used by the container tests performs a full installation in
|
||||
# its recipe, which must not run concurrently with the build passes.
|
||||
$(addsuffix /others,$(subdirs)): lib
|
||||
$(addsuffix /tests,$(subdirs)) $(addsuffix /xtests,$(subdirs)): others
|
||||
$(objpfx)testroot.pristine/install.stamp: | others
|
||||
|
||||
# Timing-sensitive test runs: the threading tests (nptl/htl) and the realtime
|
||||
# tests (rt) are perturbed by the machine load, so run them after the rest of
|
||||
# the test run has finished and one group at a time. Those subdirectories
|
||||
# also serialize their own tests (.NOTPARALLEL in their Makefiles).
|
||||
#
|
||||
# This only orders a full-suite run ('make check'/'tests'); a targeted
|
||||
# 'make subdir/tests' is left alone. And it only orders the test run
|
||||
# (run-built-tests=yes); the "build the tests" pass (run-built-tests=no)
|
||||
# is left fully parallel, so every test program still builds concurrently.
|
||||
# serialize-tests=no ('make check-parallel') drops the ordering entirely.
|
||||
ifeq ($(run-built-tests),yes)
|
||||
ifeq (yes,$(serialize-tests))
|
||||
ifneq (,$(filter tests xtests check xcheck,$(MAKECMDGOALS)))
|
||||
+late-test-subdirs := $(filter nptl htl,$(subdirs)) $(filter rt,$(subdirs))
|
||||
+test-run-prev := \
|
||||
$(addsuffix /tests,$(filter-out $(+late-test-subdirs),$(subdirs)))
|
||||
$(foreach d,$(+late-test-subdirs),\
|
||||
$(eval $(d)/tests: $(+test-run-prev))\
|
||||
$(eval +test-run-prev += $(d)/tests))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
# The top-level libc.so and linkobj/libc_pic.a rules list these
|
||||
# subdirectory-built files as prerequisites, but no rule at this level
|
||||
# builds them. The explicit empty recipe (';') is required, a
|
||||
# prerequisite-only rule would send make on an implicitrule search and
|
||||
# have this level compile them itself with the wrong context.
|
||||
ifneq (,$(filter elf,$(subdirs)))
|
||||
$(elf-objpfx)ld.so $(elf-objpfx)sofini.os $(elf-objpfx)interp.os: \
|
||||
| elf/subdir_lib ;
|
||||
endif
|
||||
ifneq (,$(filter sunrpc,$(subdirs)))
|
||||
# Makerules explicit adds librpc_compat_pic.a as a dependency of
|
||||
# libc_pic.a.
|
||||
$(common-objpfx)sunrpc/librpc_compat_pic.a: | sunrpc/subdir_lib ;
|
||||
endif
|
||||
# Hurd sysdedp Makeilfe links libc.so against the lib*user-link.so
|
||||
# objects, built by the %-link.so: %_pic.a pattern rule from archives
|
||||
# that only the mach and hurd sub-makes create.
|
||||
ifneq (,$(filter mach,$(subdirs)))
|
||||
$(common-objpfx)mach/libmachuser_pic.a: | mach/subdir_lib ;
|
||||
endif
|
||||
ifneq (,$(filter hurd,$(subdirs)))
|
||||
$(common-objpfx)hurd/libhurduser_pic.a: | hurd/subdir_lib ;
|
||||
endif
|
||||
endif
|
||||
|
||||
# The remaining target classes keep the old total order.
|
||||
+subdir-chain-prev :=
|
||||
$(foreach d,$(subdirs),$(foreach t,$(+serial_subdir_targets),$(eval \
|
||||
$(d)/$(t): $(addsuffix /$(t),$(+subdir-chain-prev))))\
|
||||
$(eval +subdir-chain-prev := $(d)))
|
||||
|
||||
# Targets to clean things up to various degrees.
|
||||
|
||||
@@ -540,26 +689,41 @@ $(objpfx)check-local-headers.out: scripts/check-local-headers.sh
|
||||
$(evaluate-test)
|
||||
|
||||
ifneq "$(headers)" ""
|
||||
# Special test of all the installed headers in this directory.
|
||||
# Special test of all the installed headers in this directory. See
|
||||
# Rules for the per-header split rationale.
|
||||
tests-special += $(objpfx)check-installed-headers-c.out
|
||||
libof-check-installed-headers-c := testsuite
|
||||
$(objpfx)check-installed-headers-c.out: \
|
||||
+cih-c-iouts := $(patsubst %,$(objpfx)check-installed-headers-c/%.iout,\
|
||||
$(headers))
|
||||
$(+cih-c-iouts): $(objpfx)check-installed-headers-c/%.iout: \
|
||||
scripts/check-installed-headers.sh $(headers)
|
||||
$(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
|
||||
"$(CC) $(test-config-cflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$(headers) > $@; \
|
||||
$(make-target-directory)
|
||||
($(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
|
||||
"$(CC) $(test-config-cflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$*; echo $$? > $@-ret) > $@T; \
|
||||
mv -f $@T $@
|
||||
$(objpfx)check-installed-headers-c.out: $(+cih-c-iouts)
|
||||
cat $^ > $@; \
|
||||
! grep -qv '^0$$' $(+cih-c-iouts:%=%-ret); \
|
||||
$(evaluate-test)
|
||||
|
||||
ifneq "$(CXX)" ""
|
||||
tests-special += $(objpfx)check-installed-headers-cxx.out
|
||||
libof-check-installed-headers-cxx := testsuite
|
||||
$(objpfx)check-installed-headers-cxx.out: \
|
||||
+cih-cxx-iouts := $(patsubst %,$(objpfx)check-installed-headers-cxx/%.iout,\
|
||||
$(headers))
|
||||
$(+cih-cxx-iouts): $(objpfx)check-installed-headers-cxx/%.iout: \
|
||||
scripts/check-installed-headers.sh $(headers)
|
||||
$(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
|
||||
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$(headers) > $@; \
|
||||
$(make-target-directory)
|
||||
($(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
|
||||
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$*; echo $$? > $@-ret) > $@T; \
|
||||
mv -f $@T $@
|
||||
$(objpfx)check-installed-headers-cxx.out: $(+cih-cxx-iouts)
|
||||
cat $^ > $@; \
|
||||
! grep -qv '^0$$' $(+cih-cxx-iouts:%=%-ret); \
|
||||
$(evaluate-test)
|
||||
endif # $(CXX)
|
||||
|
||||
@@ -648,8 +812,13 @@ else
|
||||
LINKS_DSO_PROGRAM = links-dso-program
|
||||
endif
|
||||
|
||||
# The testroot is only used by the container tests, which are not run
|
||||
# when run-built-tests is no; skip the installation entirely in that
|
||||
# case.
|
||||
ifeq ($(run-built-tests),yes)
|
||||
$(tests-container) $(addsuffix /tests,$(subdirs)) : \
|
||||
$(objpfx)testroot.pristine/install.stamp
|
||||
endif
|
||||
$(objpfx)testroot.pristine/install.stamp :
|
||||
test -d $(objpfx)testroot.pristine || \
|
||||
mkdir $(objpfx)testroot.pristine
|
||||
|
||||
@@ -1184,12 +1184,48 @@ ALL_BUILD_CFLAGS = $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -D_GNU_SOURCE \
|
||||
-DIS_IN_build -include $(common-objpfx)config.h
|
||||
|
||||
# Support the GNU standard name for this target.
|
||||
.PHONY: check
|
||||
# Special target xcheck runs tests which cannot be run unconditionally;
|
||||
# maintainers should use this target.
|
||||
.PHONY: check xcheck
|
||||
|
||||
# Building and running a subdirectory's tests are fused in its sub-make,
|
||||
# and run-built-tests is fixed for a make instance, so the only way to
|
||||
# build every test program with the recursion fully parallel while the
|
||||
# run still honors the per-subdirectory .NOTPARALLEL (nptl/htl/rt) and the
|
||||
# run-time ordering is to use two passes. At the top level, 'make check'
|
||||
# therefore builds the test programs (run-built-tests=no, recursion fully
|
||||
# parallel) and then runs them (run-built-tests=yes). 'make tests' and a
|
||||
# subdirectory's own 'check' stay single-pass.
|
||||
check-twopass :=
|
||||
ifndef subdir
|
||||
ifeq (yes,$(run-built-tests))
|
||||
check-twopass := yes
|
||||
endif
|
||||
endif
|
||||
ifeq (yes,$(check-twopass))
|
||||
check:
|
||||
$(MAKE) run-built-tests=no tests
|
||||
$(MAKE) run-built-tests=yes tests
|
||||
xcheck:
|
||||
$(MAKE) run-built-tests=no xtests
|
||||
$(MAKE) run-built-tests=yes xtests
|
||||
else
|
||||
check: tests
|
||||
# Special target to run tests which cannot be run unconditionally.
|
||||
# Maintainers should use this target.
|
||||
.PHONY: xcheck
|
||||
xcheck: xtests
|
||||
endif
|
||||
|
||||
# 'make check-parallel' runs the whole suite with maximum concurrency:
|
||||
# serialize-tests=no drops the per-subdirectory .NOTPARALLEL and the run-time
|
||||
# ordering, so every test builds and runs in parallel. A single pass suffices
|
||||
# (there is no .NOTPARALLEL to work around, so the test programs already build
|
||||
# concurrently).
|
||||
# This is faster on an idle machine, at the cost of possible flakiness in the
|
||||
# timing-sensitive tests under the heavier load.
|
||||
.PHONY: check-parallel xcheck-parallel
|
||||
check-parallel:
|
||||
$(MAKE) serialize-tests=no tests
|
||||
xcheck-parallel:
|
||||
$(MAKE) serialize-tests=no xtests
|
||||
|
||||
# Also handle test inputs in sysdeps.
|
||||
vpath %.input $(sysdirs)
|
||||
|
||||
@@ -9,44 +9,70 @@ Version 2.44
|
||||
|
||||
Major new features:
|
||||
|
||||
* System-wide tunables can be applied using /etc/tunables.conf and
|
||||
running ldconfig. Specific tunable settings and the
|
||||
/etc/tunables.conf file format and path are not part of the stable
|
||||
library interfaces and may change between releases.
|
||||
|
||||
* A new tunable, glibc.elf.thp, is added to map read-only segments with
|
||||
Transparent Huge Pages (THP) if THP isn't disable in kernel. When
|
||||
Transparent Huge Pages (THP) if THP is not disabled in the kernel. When
|
||||
glibc.elf.thp is set to 1, malloc uses the actual kernel THP mode
|
||||
instead of defaulting to madvise mode and madvise_thp will stop issuing
|
||||
MADV_HUGEPAGE if kernel THP mode is always.
|
||||
|
||||
* THP page size in malloc is capped to MAX_THP_PAGESIZE. If THP page
|
||||
size is above MAX_THP_PAGESIZE, THP in malloc is disabled.
|
||||
* The THP page size in malloc is capped to MAX_THP_PAGESIZE. If the THP
|
||||
page size is above MAX_THP_PAGESIZE, THP in malloc is disabled.
|
||||
|
||||
* Additional optimized and correctly rounded mathematical functions have
|
||||
been imported from the CORE-MATH project, in particular cosh, sinh, and
|
||||
tanh.
|
||||
|
||||
* The SVID handling for cosh and sinh were moved to compat symbols, allowing
|
||||
improvements in performance.
|
||||
* Many additional improvements to existing functions have been synchronized
|
||||
from the CORE-MATH project.
|
||||
|
||||
* New locale added: hrx_BR (Hunsrik language spoken in Brazil).
|
||||
* For C++26, the assert macro is now variadic, allowing more complex
|
||||
arguments containing commas (which however still must evaluate to a single
|
||||
value).
|
||||
|
||||
* The SVID error handling for cosh and sinh was moved to compatibility
|
||||
symbols, allowing improvements in performance.
|
||||
|
||||
* Static PIE is now supported for arm-*-linux-gnueabi. It requires toolchain
|
||||
support to correctly set the expected linker options.
|
||||
|
||||
* On AArch64 targets that support Guarded Control Stack extension all GCS
|
||||
* On AArch64 targets that support the Guarded Control Stack extension all GCS
|
||||
operations (including status, write on shadow stack, and push to shadow
|
||||
stack) are locked after enabling GCS with ENFORCED or OVERRIDE GCS policy.
|
||||
When a GCS operation is locked, a program cannot change this operation
|
||||
status via prctl syscall. This prevents disabling or corrupting GCS
|
||||
shadow stack during runtime.
|
||||
status via the prctl syscall. This prevents disabling or corrupting the
|
||||
GCS shadow stack during runtime.
|
||||
|
||||
* On AArch64 targets, log, exp, sin, cas, sinh, cosh, asinh, acosh, atanh
|
||||
single and double precision special cases have been vectorized for SVE and
|
||||
AdvSIMD, and vector variants of powr have been added.
|
||||
|
||||
* On RISC-V targets, vector extension optimized variants of memcmp, memccpy,
|
||||
memchr, memcpy, memmove, stpncpy, strcmp, strchr, strcpy, strncmp, strncpy,
|
||||
strlen, and strrchr have been added.
|
||||
|
||||
* On PowerPC, memchr optimized for Power10 has been re-added.
|
||||
|
||||
* Support for LoongArch32 has been added.
|
||||
|
||||
* Pre-built ld.so.cache files can be installed with ldconfig.
|
||||
|
||||
* A new locale has been added: hrx_BR (Hunsrik language spoken in Brazil).
|
||||
|
||||
Deprecated and removed features, and other changes affecting compatibility:
|
||||
|
||||
* Although malloc and related functions currently return pointers
|
||||
aligned to alignof (max_align_t), the documentation now says future
|
||||
versions of glibc may relax alignment requirements for small allocations.
|
||||
For example, a future malloc (1) might return a pointer with odd
|
||||
For example, a future malloc(1) might return a pointer with odd
|
||||
alignment, because no object of size 1 can have a fundamental
|
||||
alignment greater than 1.
|
||||
|
||||
* The s390-linux-gnu (31bit) configuration is no longer supported.
|
||||
* The s390-linux-gnu (31bit) configuration is no longer supported.
|
||||
|
||||
* The --enable-memory-tagging configure option has been removed.
|
||||
The corresponding AArch64-specific functionality that was previously
|
||||
@@ -57,10 +83,6 @@ Deprecated and removed features, and other changes affecting compatibility:
|
||||
remaining behavior was to suppress the link-time warnings on the NSS
|
||||
interface functions in libc.a, which are now emitted unconditionally.
|
||||
|
||||
Changes to build and runtime requirements:
|
||||
|
||||
[Add changes to build and runtime requirements here]
|
||||
|
||||
Security related changes:
|
||||
|
||||
The following CVEs were fixed in this release, details of which can be
|
||||
@@ -80,8 +102,114 @@ found in the advisories directory of the release tarball:
|
||||
|
||||
The following bugs were resolved with this release:
|
||||
|
||||
[The release manager will add the list generated by
|
||||
scripts/list-fixed-bugs.py just before the release.]
|
||||
[2363] libc: EOPNOTSUPP and ENOTSUP in errno.h must be different,
|
||||
according to SUSv3
|
||||
[3794] manual: iconv: //TRANSLIT and //IGNORE feature not documented
|
||||
[15792] dynamic-link: [arm] ARM dynamic linker should save/restore
|
||||
coprocessor registers
|
||||
[20331] libc: fts ignores errors from readdir()
|
||||
[20680] dynamic-link: ifunc resolver cannot access the thread pointer
|
||||
with static linking
|
||||
[22944] libc: fts cannot traverse paths which have a length longer
|
||||
than USHRT_MAX
|
||||
[25257] libc: sotruss: fix error message for '--f' argument
|
||||
[25770] locale: newlocale memory leak in LOCPATH parsing and on error
|
||||
paths
|
||||
[27582] libc: x86_64: IFUNC in static user programs may crash when
|
||||
built with -fstack-protector-all
|
||||
[28218] dynamic-link: ld.so: ifunc resolver calls a lazy PLT. When
|
||||
does it work?
|
||||
[28817] libc: static-pie ifunc resolver tls failure
|
||||
[28940] nss: __nss_database_get doesn't check for allocation failure
|
||||
[30136] manual: Please document behaviour of iconv(3) when input is
|
||||
untranslatable
|
||||
[30304] nptl: nptl/tst-pthread-gdb-attach test fails with new libc
|
||||
shared library version
|
||||
[30769] malloc: malloc_trim is not working correctly for arenas other
|
||||
than arena 0
|
||||
[30976] dynamic-link: rtld: resolve ifunc relocations after
|
||||
JUMP_SLOT/GLOB_DAT/etc
|
||||
[30992] libc: alpha: setrlimit() with negative values besides
|
||||
RLIM_INFINITY returns EPERM
|
||||
[31901] libc: elf/tst-glibc-hwcaps-prepend-cache fails on i686
|
||||
[33226] math: math-vector-fortran.h vs not ffast-math
|
||||
[33626] libc: execvpe should skip inaccessible $PATH components
|
||||
[33650] build: abilist.awk doesn't handle unversioned defined symbols
|
||||
[33785] stdio: New streams are linked into global list before they are
|
||||
fully initialized
|
||||
[33848] build: Build fails at openat2.h, redefinition of 'struct
|
||||
open_how'
|
||||
[33882] libc: Recursion in nftw() causes stack overflow(CWE-674)
|
||||
[33904] build: error: '__vasprintf_chk' undeclared here
|
||||
[33921] build: Building with Linux-7.0-rc1 errors on OPEN_TREE_CLONE
|
||||
[33935] stdio: _IO_wfile_doallocate not linked correctly when linking
|
||||
glibc statically
|
||||
[33980] locale: iconv: ibm139x trigger assertion error when converting
|
||||
to internal while lack enough room (CVE-2026-4046)
|
||||
[33985] build: ld: cannot find -lgcc_s: No such file or directory
|
||||
[33999] stdio: libio: potential dangling _IO_save_base or memory leak
|
||||
in wgenops.c
|
||||
[34006] stdio: libio: inconsistent fmemopen_write behavior on last \0
|
||||
[34008] stdio: stdio-common: scanf %mc pattern will cause heap
|
||||
overflow when width > 1024
|
||||
[34014] nss: gethostbyaddr and gethostbyaddr_r may incorrectly handle
|
||||
DNS response
|
||||
[34015] nss: gethostbyaddr and gethostbyaddr_r return invalid DNS
|
||||
hostnames
|
||||
[34019] stdio: libio: undefined behavior when setbuf on open_memstream
|
||||
[34033] network: resolv/ns_print.c: ns_sprintrrf TSIG path bypasses
|
||||
buflen and can overflow caller buffer
|
||||
[34064] dynamic-link: The unnecessary PT_NOTE check in when loading a
|
||||
binary
|
||||
[34069] network: Buffer overread in ns_sprintrrf with corrupted RDATA
|
||||
field (CVE-2026-6238)
|
||||
[34070] hurd: Calling open ("/dev/tty/", O_RDONLY) causes the program
|
||||
to segfault
|
||||
[34073] regex: regexec can mistakenly match with backrefs and the $
|
||||
anchor
|
||||
[34079] dynamic-link: THP segment load aligns all PT_LOAD segments to
|
||||
THP page size
|
||||
[34080] dynamic-link: Support THP segment load with THP enabled with
|
||||
madvise
|
||||
[34083] dynamic-link: __get_thp_mode and __get_thp_size are called
|
||||
twice
|
||||
[34090] libc: wordexp WRDE_APPEND rollback restores stale we_wordv,
|
||||
leading to invalid free in wordfree
|
||||
[34098] libc: Missing SUPPORT_STATIC_PIE in arm32
|
||||
[34129] string: x86: Non-temporal memset unreachable on AMD Zen 3/4/5
|
||||
[34144] libc: ld.so clobbers VFP registers during runtime linking
|
||||
[34154] network: Segfault in sock_eq after res_init() returns -1, due
|
||||
to stale _u._ext.nscount in __res_iclose
|
||||
[34156] dynamic-link: dlsym(RTLD_DEFAULT, ...) from a constructor
|
||||
SIGSEGVs when tail-called
|
||||
[34164] dynamic-link: elf: IFUNC resolvers do not see static TLS
|
||||
initialization
|
||||
[34170] dynamic-link: elf: IFUNC resolver reading global-
|
||||
dynamic/TLSDESC __thread variable crashes inside __tls_get_addr
|
||||
[34183] math: fma produces wrong results
|
||||
[34192] nptl: pthread_setname_np opens /proc/<tid>/comm with O_RDWR
|
||||
instead of O_WRONLY|O_CLOEXEC
|
||||
[34196] libc: elf: static dlopen: pointer guard of the loaded
|
||||
ld.so/libc.so is left uninitialized
|
||||
[34197] dynamic-link: elf: Stack canary and pointer guard are
|
||||
recoverable from AT_RANDOM (getauxval)
|
||||
[34205] libc: aarch64: SIGSEGV in tunable_strcmp in static-pie
|
||||
binaries run with a string tunable
|
||||
[34208] stdio: scanf not pushback after matching failure
|
||||
[34210] libc: elf/tst-glibc-hwcaps-prepend-cache fails on
|
||||
armv7a-unknown-linux-gnueabihf
|
||||
[34236] locale: Non-representable transliteration still causes iconv
|
||||
to exit with 1 if //TRANSLIT is specified
|
||||
[34289] network: ns_sprintrrf uses p_class, p_type internally
|
||||
[34311] build: THP tests failed to link
|
||||
[34347] libc: Incorrect trailing bitfield word of struct tcp_info
|
||||
[34348] dynamic-link: FAIL: elf/tst-thp-1 if THP is disabled in kernel
|
||||
[34351] build: Random test failures
|
||||
[34355] build: [2.44 Regression] "make check -j7 subdirs=stdio-common"
|
||||
no longer works
|
||||
[34396] libc: sparc64-unknown-linux-gnu , Gentoo: >200 test failures,
|
||||
SIGILL in many binaries
|
||||
[34398] string: Truncated strncpy on s390x z900 ifunc variant
|
||||
|
||||
Version 2.43
|
||||
|
||||
|
||||
@@ -80,15 +80,24 @@ common-generated += dummy.o dummy.c
|
||||
|
||||
ifneq "$(headers)" ""
|
||||
# Test that all of the headers installed by this directory can be compiled
|
||||
# in isolation.
|
||||
# in isolation. Each header gets its own intermediate target so that the
|
||||
# it can run concurrently under -j; the .out target concatenates the per-header
|
||||
# results in the original $(headers) order.
|
||||
tests-special += $(objpfx)check-installed-headers-c.out
|
||||
libof-check-installed-headers-c := testsuite
|
||||
$(objpfx)check-installed-headers-c.out: \
|
||||
+cih-c-iouts := $(patsubst %,$(objpfx)check-installed-headers-c/%.iout,\
|
||||
$(headers))
|
||||
$(+cih-c-iouts): $(objpfx)check-installed-headers-c/%.iout: \
|
||||
$(..)scripts/check-installed-headers.sh $(headers)
|
||||
$(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
|
||||
"$(CC) $(test-config-cflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$(headers) > $@; \
|
||||
$(make-target-directory)
|
||||
($(SHELL) $(..)scripts/check-installed-headers.sh c $(supported-fortify) \
|
||||
"$(CC) $(test-config-cflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$*; echo $$? > $@-ret) > $@T; \
|
||||
mv -f $@T $@
|
||||
$(objpfx)check-installed-headers-c.out: $(+cih-c-iouts)
|
||||
cat $^ > $@; \
|
||||
! grep -qv '^0$$' $(+cih-c-iouts:%=%-ret); \
|
||||
$(evaluate-test)
|
||||
|
||||
ifneq "$(CXX)" ""
|
||||
@@ -96,12 +105,19 @@ ifneq "$(CXX)" ""
|
||||
# in isolation as C++.
|
||||
tests-special += $(objpfx)check-installed-headers-cxx.out
|
||||
libof-check-installed-headers-cxx := testsuite
|
||||
$(objpfx)check-installed-headers-cxx.out: \
|
||||
+cih-cxx-iouts := $(patsubst %,$(objpfx)check-installed-headers-cxx/%.iout,\
|
||||
$(headers))
|
||||
$(+cih-cxx-iouts): $(objpfx)check-installed-headers-cxx/%.iout: \
|
||||
$(..)scripts/check-installed-headers.sh $(headers)
|
||||
$(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
|
||||
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$(headers) > $@; \
|
||||
$(make-target-directory)
|
||||
($(SHELL) $(..)scripts/check-installed-headers.sh c++ $(supported-fortify) \
|
||||
"$(CXX) $(test-config-cxxflags-finput-charset-ascii) \
|
||||
$(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \
|
||||
$*; echo $$? > $@-ret) > $@T; \
|
||||
mv -f $@T $@
|
||||
$(objpfx)check-installed-headers-cxx.out: $(+cih-cxx-iouts)
|
||||
cat $^ > $@; \
|
||||
! grep -qv '^0$$' $(+cih-cxx-iouts:%=%-ret); \
|
||||
$(evaluate-test)
|
||||
endif # $(CXX)
|
||||
|
||||
@@ -413,7 +429,7 @@ $(objpfx)%.out: /dev/null $(objpfx)% # Make it 2nd arg for canned sequence.
|
||||
# and pid namespaces) in which to run, should be added to
|
||||
# tests-container.
|
||||
$(tests-container:%=$(objpfx)%.out): $(objpfx)%.out : $(if $(wildcard $(objpfx)%.files),$(objpfx)%.files,/dev/null) $(objpfx)%
|
||||
$(test-wrapper-env) $(run-program-env) $(test-via-rtld-prefix) \
|
||||
$(test-wrapper-env) $(run-program-env) $(test-container-via-rtld-prefix) \
|
||||
$(common-objpfx)support/test-container env $(run-program-env) $($*-ENV) $(test-tunables) \
|
||||
$(host-test-program-cmd) $($*-ARGS) > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
+1
-1
@@ -280,7 +280,7 @@ core-math:
|
||||
sysdeps/ieee754/dbl-64/s_erf.c
|
||||
# src/binary64/erfc/erfc.c, revision 55e9869e
|
||||
sysdeps/ieee754/dbl-64/s_erfc.c
|
||||
# src/binary64/tanh/tanh.c, revision 8ea8ea35
|
||||
# src/binary64/tanh/tanh.c, revision cf237fa0
|
||||
sysdeps/ieee754/dbl-64/s_tanh.c
|
||||
# src/binary32/acos/acosf.c, revision 56dd347
|
||||
sysdeps/ieee754/flt-32/e_acosf.c
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
wordexp with WRDE_APPEND may result in an invalid call to free()
|
||||
|
||||
Calling wordexp with WRDE_APPEND in conjunction with an invalid expansion
|
||||
(where an error like WRDE_BADCHAR would be returned) can create a stale
|
||||
address in the wordexp_t that can cause an invalid free from wordfree.
|
||||
This affects the GNU C Library version 2.0 to version 2.43.
|
||||
|
||||
In WRDE_APPEND mode, wordexp saves the caller-visible wordexp_t state
|
||||
before appending the processing input. If the word expansion grows
|
||||
we_wordv via realloc, and realloc requires moving we_wordv to a new memory
|
||||
location (instead of expanding in-place), and the expansion later fails,
|
||||
the rollback fails to properly restore all previous we_wordv values and
|
||||
may add stale pointers into the caller-visible state. A subsequent
|
||||
wordfree may then issue an invalid call to free().
|
||||
|
||||
CVE-Id: CVE-2026-6368
|
||||
Public-Date: 2026-07-14
|
||||
Vulnerable-Commit: 8f2ece695d8822e9ecc63ecd157e90bf17a6fe65 (1.93-260)
|
||||
Reported-by: shinobu
|
||||
+24
-3
@@ -409,9 +409,9 @@ $(addprefix $(objpfx)bench-,calloc-thread): $(libm-benchtests)
|
||||
# Rules to build and execute the benchmarks. Do not put any benchmark
|
||||
# parameters beyond this point.
|
||||
|
||||
# We don't want the benchmark programs to run in parallel since that could
|
||||
# affect their performance.
|
||||
.NOTPARALLEL:
|
||||
# Benchmark programs must not run concurrently, however building them is
|
||||
# safe in parallel. So '.NOTPARALLEL:' is used only when benchmarks run
|
||||
# or when more than one group is going to run.
|
||||
|
||||
bench-extra-objs = json-lib.o
|
||||
|
||||
@@ -627,3 +627,24 @@ $(objpfx)bench-%.c: %-inputs $(bench-deps)
|
||||
fi; \
|
||||
$(PYTHON) scripts/bench.py $(patsubst %-inputs,%,$<); } > $@-tmp
|
||||
mv -f $@-tmp $@
|
||||
|
||||
# Serialize the benchmark runs so their timing is not perturbed by a
|
||||
# concurrent workload, while still building every benchmark program in parallel.
|
||||
# Ordering is only needed when more than one benchmark group run: the combined
|
||||
# 'bench' goal runs all three groups, and the bench* goals can also be combined
|
||||
# on a single command line. A lone group needs no ordering -- make builds its
|
||||
# programs in parallel and then runs its single recipe, which cannot overlap a
|
||||
# compile.
|
||||
ifneq (,$(filter bench,$(MAKECMDGOALS)))
|
||||
bench-run-active := bench-set bench-func bench-malloc
|
||||
else
|
||||
bench-run-active := $(filter bench-set bench-func bench-malloc,$(MAKECMDGOALS))
|
||||
endif
|
||||
|
||||
ifneq (,$(word 2,$(bench-run-active)))
|
||||
# Hold every active run until all benchmark programs have been built.
|
||||
$(bench-run-active): | bench-build
|
||||
# And then run the active groups strictly one at a time.
|
||||
bench-func: | $(filter bench-set,$(bench-run-active))
|
||||
bench-malloc: | $(filter bench-set bench-func,$(bench-run-active))
|
||||
endif
|
||||
|
||||
+3006
-2405
File diff suppressed because it is too large
Load Diff
+3006
-4911
File diff suppressed because it is too large
Load Diff
+2004
-3446
File diff suppressed because it is too large
Load Diff
+11
-3
@@ -60,6 +60,14 @@ vpath %.c ../locale/programs
|
||||
|
||||
include ../Rules
|
||||
|
||||
# The catalog-generation tests below run gencat under specific locales,
|
||||
# and tst-catgets reads the resulting catalog, so the build must wait for
|
||||
# those locales to be generated. Without this dependency a parallel build
|
||||
# races catgets against localedata and gencat can run before the locale
|
||||
# exists (it then falls back to C and the test fails).
|
||||
LOCALES := de_DE.ISO-8859-1 hr_HR.ISO-8859-2 ja_JP.SJIS
|
||||
include ../gen-locales.mk
|
||||
|
||||
$(objpfx)gencat: $(gencat-modules:%=$(objpfx)%.o)
|
||||
|
||||
catgets-CPPFLAGS := -DNLSPATH='"$(localedir)/%L/%N:$(localedir)/%L/LC_MESSAGES/%N:$(localedir)/%l/%N:$(localedir)/%l/LC_MESSAGES/%N:"'
|
||||
@@ -95,7 +103,7 @@ tst-catgets-ENV = NLSPATH="$(objpfx)%l/%N.cat" LANG=de \
|
||||
ifeq ($(run-built-tests),yes)
|
||||
# This test just checks whether the program produces any error or not.
|
||||
# The result is not tested.
|
||||
$(objpfx)test1.cat: test1.msg $(objpfx)gencat
|
||||
$(objpfx)test1.cat: test1.msg $(objpfx)gencat $(gen-locales)
|
||||
$(built-program-cmd-before-env) \
|
||||
$(run-program-env) LC_ALL=hr_HR.ISO-8859-2 \
|
||||
$(built-program-cmd-after-env) -H $(objpfx)test1.h $@ $<; \
|
||||
@@ -103,7 +111,7 @@ $(objpfx)test1.cat: test1.msg $(objpfx)gencat
|
||||
$(objpfx)test2.cat: test2.msg $(objpfx)gencat
|
||||
$(built-program-cmd) -H $(objpfx)test2.h $@ $<; \
|
||||
$(evaluate-test)
|
||||
$(objpfx)de/libc.cat: $(objpfx)de.msg $(objpfx)gencat
|
||||
$(objpfx)de/libc.cat: $(objpfx)de.msg $(objpfx)gencat $(gen-locales)
|
||||
$(make-target-directory)
|
||||
$(built-program-cmd-before-env) \
|
||||
$(run-program-env) LC_ALL=de_DE.ISO-8859-1 \
|
||||
@@ -116,7 +124,7 @@ $(objpfx)de.msg: xopen-msg.awk $(..)po/de.po
|
||||
LC_ALL=C $(AWK) -f $^ $< > $@
|
||||
|
||||
$(objpfx)test-gencat.out: test-gencat.sh $(objpfx)test-gencat \
|
||||
$(objpfx)sample.SJIS.cat
|
||||
$(objpfx)sample.SJIS.cat $(gen-locales)
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-cmd-before-env)' \
|
||||
'$(run-program-env)' '$(test-program-cmd-after-env)'; \
|
||||
$(evaluate-test)
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
|
||||
_dl_aux_init (auxvec);
|
||||
# endif
|
||||
|
||||
__tunables_init (__environ);
|
||||
__tunables_init (__environ, argv);
|
||||
|
||||
ARCH_INIT_CPU_FEATURES ();
|
||||
|
||||
|
||||
@@ -225,6 +225,7 @@ ldconfig-modules := \
|
||||
readlib \
|
||||
static-stubs \
|
||||
stringtable \
|
||||
tunconf \
|
||||
xmalloc \
|
||||
xstrdup \
|
||||
# ldconfig-modules
|
||||
@@ -335,6 +336,7 @@ tests-internal := \
|
||||
$(tests-static-internal) \
|
||||
tst-tls1 \
|
||||
tst-tls_tp_offset \
|
||||
tst-tunconf1 \
|
||||
# tests-internal
|
||||
|
||||
tests-static := $(tests-static-normal) $(tests-static-internal)
|
||||
@@ -345,6 +347,17 @@ tests-static += \
|
||||
tst-tls9-static \
|
||||
# tests-static
|
||||
|
||||
tst-tunconf1-TUNABLES-only = \
|
||||
glibc.malloc.tcache_count=5 \
|
||||
glibc.malloc.perturb=41 \
|
||||
glibc.malloc.mmap_threshold=10002 \
|
||||
glibc.malloc.trim_threshold=10002 \
|
||||
glibc.malloc.arena_max=300
|
||||
tst-tunconf1-ENV = \
|
||||
MALLOC_MMAP_MAX_=200 \
|
||||
MALLOC_TOP_PAD_=200 \
|
||||
MALLOC_ARENA_MAX=400
|
||||
|
||||
static-dlopen-environment = \
|
||||
LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)dlfcn
|
||||
tst-tls9-static-ENV = $(static-dlopen-environment)
|
||||
@@ -577,10 +590,12 @@ endif
|
||||
tests-container += \
|
||||
tst-dlopen-self-container \
|
||||
tst-dlopen-tlsmodid-container \
|
||||
tst-ldconfig-cache \
|
||||
tst-pldd \
|
||||
tst-preload-pthread-libc \
|
||||
tst-ptrguard-static-dlopen \
|
||||
tst-rootdir \
|
||||
tst-tunconf1 \
|
||||
# tests-container
|
||||
|
||||
test-srcs = \
|
||||
@@ -712,6 +727,7 @@ tests-special += $(tests-execstack-special-$(have-z-execstack))
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special += \
|
||||
$(objpfx)tst-ldconfig-X.out \
|
||||
$(objpfx)tst-ldconfig-install.out \
|
||||
$(objpfx)tst-ldconfig-p.out \
|
||||
$(objpfx)tst-ldconfig-soname.out \
|
||||
$(objpfx)tst-rtld-help.out \
|
||||
@@ -734,6 +750,9 @@ one-hundred = $(foreach x,0 1 2 3 4 5 6 7 8 9, \
|
||||
0$x 1$x 2$x 3$x 4$x 5$x 6$x 7$x 8$x 9$x)
|
||||
tst-tls-many-dynamic-modules := \
|
||||
$(foreach n,$(one-hundred),tst-tls-manydynamic$(n)mod)
|
||||
tst-ldconfig-cache-modules := \
|
||||
$(foreach n,01 02 03 04 05,tst-tls-manydynamic$(n)mod)
|
||||
$(objpfx)tst-ldconfig-cache.out: $(tst-ldconfig-cache-modules:%=$(objpfx)%.so)
|
||||
tst-tls-many-dynamic-modules-dep-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 \
|
||||
14 15 16 17 18 19
|
||||
tst-tls-many-dynamic-modules-dep = \
|
||||
@@ -1441,6 +1460,7 @@ ifndef avoid-generated
|
||||
# Makefile fragment to be included.
|
||||
define include_dsosort_tests
|
||||
$(objpfx)$(1).generated-makefile: $(1)
|
||||
$$(make-target-directory)
|
||||
$(PYTHON) $(..)scripts/dso-ordering-test.py \
|
||||
--description-file $$< --objpfx $(objpfx) --output-makefile $$@T
|
||||
mv $$@T $$@
|
||||
@@ -1449,6 +1469,7 @@ endef
|
||||
# Likewise, where the .def file itself is generated.
|
||||
define include_dsosort_tests_objpfx
|
||||
$(objpfx)$(1).generated-makefile: $(objpfx)$(1)
|
||||
$$(make-target-directory)
|
||||
$(PYTHON) $(..)scripts/dso-ordering-test.py \
|
||||
--description-file $$< --objpfx $(objpfx) --output-makefile $$@T
|
||||
mv $$@T $$@
|
||||
@@ -1467,12 +1488,15 @@ $(eval $(call include_dsosort_tests,dso-sort-tests-1.def))
|
||||
$(eval $(call include_dsosort_tests,dso-sort-tests-2.def))
|
||||
|
||||
$(objpfx)dso-sort-tests-all2.def: dso-sort-tests-all.py
|
||||
$(make-target-directory)
|
||||
$(PYTHON) $< 2 > $@
|
||||
|
||||
$(objpfx)dso-sort-tests-all3.def: dso-sort-tests-all.py
|
||||
$(make-target-directory)
|
||||
$(PYTHON) $< 3 > $@
|
||||
|
||||
$(objpfx)dso-sort-tests-all4.def: dso-sort-tests-all.py
|
||||
$(make-target-directory)
|
||||
$(PYTHON) $< 4 > $@
|
||||
|
||||
$(eval $(call include_dsosort_tests_objpfx,dso-sort-tests-all2.def))
|
||||
@@ -2824,6 +2848,11 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
|
||||
'$(run-program-env)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-ldconfig-install.out : tst-ldconfig-install.sh $(objpfx)ldconfig
|
||||
$(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \
|
||||
'$(run-program-env)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
$(objpfx)tst-ldconfig-p.out : tst-ldconfig-p.sh $(objpfx)ldconfig
|
||||
$(SHELL) $< '$(common-objpfx)' '$(sysconfdir)' '$(test-wrapper-env)' \
|
||||
'$(run-program-env)' > $@; \
|
||||
|
||||
+106
-2
@@ -36,6 +36,7 @@
|
||||
#include <dl-cache.h>
|
||||
#include <version.h>
|
||||
#include <stringtable.h>
|
||||
#include <tunconf.h>
|
||||
|
||||
/* Used to store library names, paths, and other strings. */
|
||||
static struct stringtable strings;
|
||||
@@ -275,7 +276,8 @@ check_new_cache (struct cache_file_new *cache)
|
||||
|
||||
/* Print the extension information in *EXT. */
|
||||
static void
|
||||
print_extensions (struct cache_extension_all_loaded *ext)
|
||||
print_extensions (struct cache_extension_all_loaded *ext,
|
||||
const char *cache_data)
|
||||
{
|
||||
if (ext->sections[cache_extension_tag_generator].base != NULL)
|
||||
{
|
||||
@@ -284,6 +286,65 @@ print_extensions (struct cache_extension_all_loaded *ext)
|
||||
ext->sections[cache_extension_tag_generator].size, stdout);
|
||||
putchar ('\n');
|
||||
}
|
||||
if (ext->sections[cache_extension_tag_tunables].base != NULL)
|
||||
{
|
||||
struct tunable_header_cached *thc;
|
||||
struct tunable_entry_cached *tec;
|
||||
int i, count;
|
||||
|
||||
thc = (struct tunable_header_cached *)
|
||||
ext->sections[cache_extension_tag_tunables].base;
|
||||
tec = thc->tunables;
|
||||
count = thc->num_tunables;
|
||||
printf("tunables sig 0x%08x ver 0x%08x count %u\n",
|
||||
thc->signature, thc->version, thc->num_tunables);
|
||||
/* Check that COUNT won't overflow our data block. */
|
||||
assert (ext->sections[cache_extension_tag_tunables].base
|
||||
+ ext->sections[cache_extension_tag_tunables].size
|
||||
== (void *) & tec[count]);
|
||||
for (i = 0; i < count; ++ i)
|
||||
{
|
||||
printf (" [%d] %s = %s [flags 0x%08x (",
|
||||
i,
|
||||
cache_data + tec[i].name_offset,
|
||||
cache_data + tec[i].value_offset,
|
||||
tec[i].flags);
|
||||
if (tec[i].flags & TUNCONF_FLAG_PARSED)
|
||||
printf ("parsed,");
|
||||
if (tec[i].flags & TUNCONF_FLAG_NEGATIVE)
|
||||
printf ("negative,");
|
||||
if ((tec[i].flags & TUNCONF_FLAG_OVERRIDABLE)
|
||||
== TUNCONF_OVERRIDE_ALLOW)
|
||||
printf ("overridable");
|
||||
else
|
||||
printf ("nonoverridable");
|
||||
switch (tec[i].flags & (TUNCONF_EXCLUDE_SECURE
|
||||
| TUNCONF_EXCLUDE_UNSECURE))
|
||||
{
|
||||
case TUNCONF_EXCLUDE_SECURE:
|
||||
printf(",nonsecure");
|
||||
break;
|
||||
case TUNCONF_EXCLUDE_UNSECURE:
|
||||
printf(",onlysecure");
|
||||
break;
|
||||
case TUNCONF_EXCLUDE_SECURE | TUNCONF_EXCLUDE_UNSECURE:
|
||||
printf(",ignore");
|
||||
break;
|
||||
case 0:
|
||||
printf(",anysecure");
|
||||
break;
|
||||
}
|
||||
switch (tec[i].flags & TUNCONF_FLAG_FILTER)
|
||||
{
|
||||
case TUNCONF_FILTER_PERPROC:
|
||||
printf(",[proc]");
|
||||
break;
|
||||
}
|
||||
if (tec[i].flag_offset != 0)
|
||||
printf (",'%s'", cache_data + tec[i].flag_offset);
|
||||
printf (")]\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the whole cache file, if a file contains the new cache format
|
||||
@@ -394,7 +455,7 @@ print_cache (const char *cache_name)
|
||||
cache_new->libs[i].hwcap, hwcaps_string,
|
||||
cache_data + cache_new->libs[i].value);
|
||||
}
|
||||
print_extensions (&ext);
|
||||
print_extensions (&ext, cache_data);
|
||||
}
|
||||
/* Cleanup. */
|
||||
munmap (cache, cache_size);
|
||||
@@ -466,6 +527,18 @@ write_extensions (int fd, uint32_t str_offset,
|
||||
if (p->used)
|
||||
hwcaps_array[p->section_index] = str_offset + p->name->offset;
|
||||
|
||||
struct tunable_header_cached *tunable_data;
|
||||
size_t tunable_size;
|
||||
size_t tunable_aligner = 0;
|
||||
|
||||
tunable_data = get_tunconf_ext (str_offset);
|
||||
|
||||
if (tunable_data == NULL)
|
||||
{
|
||||
/* There is no section for tunables data. */
|
||||
hwcaps_offset -= sizeof (struct cache_extension_section);
|
||||
}
|
||||
|
||||
/* This is the offset of the generator string. */
|
||||
uint32_t generator_offset = hwcaps_offset;
|
||||
if (hwcaps_count == 0)
|
||||
@@ -498,6 +571,23 @@ write_extensions (int fd, uint32_t str_offset,
|
||||
ext->sections[xid].size = hwcaps_size;
|
||||
}
|
||||
|
||||
if (tunable_data != NULL)
|
||||
{
|
||||
uint32_t tunable_offset_ua;
|
||||
uint32_t tunable_offset;
|
||||
|
||||
tunable_size = TUNCONF_SIZE (tunable_data);
|
||||
tunable_offset_ua = generator_offset + strlen (generator);
|
||||
tunable_offset = ALIGN_UP (tunable_offset_ua, 8);
|
||||
tunable_aligner = tunable_offset - tunable_offset_ua;
|
||||
|
||||
++xid;
|
||||
ext->sections[xid].tag = cache_extension_tag_tunables;
|
||||
ext->sections[xid].flags = 0;
|
||||
ext->sections[xid].offset = tunable_offset;
|
||||
ext->sections[xid].size = tunable_size;
|
||||
}
|
||||
|
||||
++xid;
|
||||
ext->count = xid;
|
||||
assert (xid <= cache_extension_count);
|
||||
@@ -509,6 +599,14 @@ write_extensions (int fd, uint32_t str_offset,
|
||||
|| write (fd, generator, strlen (generator)) != strlen (generator))
|
||||
error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
|
||||
|
||||
if (tunable_data)
|
||||
{
|
||||
if (write (fd, " ", tunable_aligner) != tunable_aligner
|
||||
|| write (fd, tunable_data, tunable_size) != tunable_size)
|
||||
error (EXIT_FAILURE, errno, _("Writing of cache tunable data failed"));
|
||||
free (tunable_data);
|
||||
}
|
||||
|
||||
free (hwcaps_array);
|
||||
free (ext);
|
||||
}
|
||||
@@ -1106,3 +1204,9 @@ out_fail:
|
||||
free (temp_name);
|
||||
free (file_entries);
|
||||
}
|
||||
|
||||
struct stringtable_entry *
|
||||
cache_store_string (const char *string)
|
||||
{
|
||||
return stringtable_add (&strings, string);
|
||||
}
|
||||
|
||||
+239
-90
@@ -17,6 +17,7 @@
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <intprops.h>
|
||||
#include <unistd.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -26,11 +27,22 @@
|
||||
#include <_itoa.h>
|
||||
#include <dl-hwcaps.h>
|
||||
#include <dl-isa-level.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include "tunconf.h"
|
||||
|
||||
/* This is the starting address and the size of the mmap()ed file. */
|
||||
static struct cache_file *cache;
|
||||
static struct cache_file_new *cache_new;
|
||||
static size_t cachesize;
|
||||
static struct cache_extension_all_loaded ext;
|
||||
|
||||
static struct {
|
||||
typeof ((*(struct __stat64_t64 *)0).st_mtime) mtime;
|
||||
typeof ((*(struct __stat64_t64 *)0).st_ino) ino;
|
||||
typeof ((*(struct __stat64_t64 *)0).st_size) size;
|
||||
typeof ((*(struct __stat64_t64 *)0).st_dev) dev;
|
||||
} cache_file_time, new_cache_file_time;
|
||||
|
||||
#ifdef SHARED
|
||||
/* This is used to cache the priorities of glibc-hwcaps
|
||||
@@ -53,6 +65,7 @@ glibc_hwcaps_priorities_free (void)
|
||||
free (glibc_hwcaps_priorities);
|
||||
glibc_hwcaps_priorities = NULL;
|
||||
glibc_hwcaps_priorities_allocated = 0;
|
||||
glibc_hwcaps_priorities_length = 0;
|
||||
}
|
||||
|
||||
/* Ordered comparison of a hwcaps string from the cache on the left
|
||||
@@ -84,10 +97,6 @@ glibc_hwcaps_compare (uint32_t left_index, struct dl_hwcaps_priority *right)
|
||||
static void
|
||||
glibc_hwcaps_priorities_init (void)
|
||||
{
|
||||
struct cache_extension_all_loaded ext;
|
||||
if (!cache_extension_load (cache_new, cache, cachesize, &ext))
|
||||
return;
|
||||
|
||||
uint32_t length = (ext.sections[cache_extension_tag_glibc_hwcaps].size
|
||||
/ sizeof (uint32_t));
|
||||
if (length > glibc_hwcaps_priorities_allocated)
|
||||
@@ -374,6 +383,168 @@ _dl_cache_libcmp (const char *p1, const char *p2)
|
||||
return *p1 - *p2;
|
||||
}
|
||||
|
||||
/* Set the cache back to the "no cache" state, which may include
|
||||
cleaning up a loaded cache. */
|
||||
static void
|
||||
_dl_maybe_unload_ldsocache (void)
|
||||
{
|
||||
if (cache != NULL)
|
||||
__munmap (cache, cachesize);
|
||||
|
||||
cache = NULL;
|
||||
cache_new = NULL;
|
||||
cachesize = 0;
|
||||
|
||||
#ifdef SHARED
|
||||
glibc_hwcaps_priorities_free ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns TRUE if for any reason the cache needs to be reloaded
|
||||
(including, the first time, loaded). */
|
||||
static bool
|
||||
_dl_check_ldsocache_needs_loading (void)
|
||||
{
|
||||
int rv;
|
||||
static bool copy_old_time = 0;
|
||||
struct __stat64_t64 new_cache_file_stat;
|
||||
|
||||
/* Save the previous stat every time. We only care when this
|
||||
changes, and we only stat it here, so we can get away with doing
|
||||
the copy now instead of at every single return statement in this
|
||||
function. However, we only need to copy it if the previous stat
|
||||
succeeded. The only way this could be subverted is if the admin
|
||||
moves the file aside, then moves it back, but CACHE would be set
|
||||
to NULL in the interim so that would be detected. */
|
||||
if (copy_old_time)
|
||||
cache_file_time = new_cache_file_time;
|
||||
rv = __fstatat64_time64 (AT_FDCWD, LD_SO_CACHE, &new_cache_file_stat, 0);
|
||||
copy_old_time = (rv >= 0);
|
||||
|
||||
/* No file to load, but there used to be. Assume user intentionally
|
||||
deleted the cache and act accordingly. */
|
||||
if (rv < 0 && cache != NULL)
|
||||
{
|
||||
_dl_maybe_unload_ldsocache ();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* No file to load and no loaded cache, so nothing to do. */
|
||||
if (rv < 0)
|
||||
return false;
|
||||
|
||||
/* Store the fields we check, in order they're likely to differ. We
|
||||
must do this even for the first load (CACHE == NULL below), so that
|
||||
the next call copies an accurate NEW_CACHE_FILE_TIME into
|
||||
CACHE_FILE_TIME and does not spuriously reload the unchanged cache. */
|
||||
new_cache_file_time.mtime = new_cache_file_stat.st_mtime;
|
||||
new_cache_file_time.ino = new_cache_file_stat.st_ino;
|
||||
new_cache_file_time.size = new_cache_file_stat.st_size;
|
||||
new_cache_file_time.dev = new_cache_file_stat.st_dev;
|
||||
|
||||
/* Any file is better than no file (likely the first time
|
||||
through). */
|
||||
if (cache == NULL)
|
||||
return true;
|
||||
|
||||
/* At this point, NEW_CACHE_FILE_TIME is valid as well as
|
||||
CACHE_FILE_TIME, so we compare them. */
|
||||
return (memcmp (&new_cache_file_time, &cache_file_time,
|
||||
sizeof(new_cache_file_time)));
|
||||
}
|
||||
|
||||
/* Attempts to load and validate the cache. On return, CACHE is either
|
||||
unchanged (still loaded or still not loaded) or valid. */
|
||||
static void
|
||||
_dl_maybe_load_ldsocache (void)
|
||||
{
|
||||
struct cache_file *tmp_cache = NULL;
|
||||
struct cache_file_new *tmp_cache_new = NULL;
|
||||
size_t tmp_cachesize = 0;
|
||||
|
||||
/* Read the contents of the file. */
|
||||
void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &tmp_cachesize,
|
||||
PROT_READ);
|
||||
|
||||
/* We can handle three different cache file formats here:
|
||||
- only the new format
|
||||
- the old libc5/glibc2.0/2.1 format
|
||||
- the old format with the new format in it
|
||||
The following checks if the cache contains any of these formats. */
|
||||
if (file != MAP_FAILED && tmp_cachesize > sizeof *cache_new
|
||||
&& memcmp (file, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) == 0
|
||||
/* Check for corruption, avoiding overflow. */
|
||||
&& ((tmp_cachesize - sizeof *cache_new) / sizeof (struct file_entry_new)
|
||||
>= ((struct cache_file_new *) file)->nlibs))
|
||||
{
|
||||
if (! cache_file_new_matches_endian (file))
|
||||
{
|
||||
__munmap (file, tmp_cachesize);
|
||||
return;
|
||||
}
|
||||
|
||||
tmp_cache_new = file;
|
||||
tmp_cache = file;
|
||||
}
|
||||
else if (file != MAP_FAILED && tmp_cachesize > sizeof *cache
|
||||
&& memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
|
||||
/* Check for corruption, avoiding overflow. */
|
||||
&& ((tmp_cachesize - sizeof *cache) / sizeof (struct file_entry)
|
||||
>= ((struct cache_file *) file)->nlibs))
|
||||
{
|
||||
size_t offset;
|
||||
/* Looks ok. */
|
||||
tmp_cache = file;
|
||||
|
||||
/* Check for new version. */
|
||||
offset = ALIGN_CACHE (sizeof (struct cache_file)
|
||||
+ tmp_cache->nlibs * sizeof (struct file_entry));
|
||||
|
||||
tmp_cache_new = (struct cache_file_new *) ((void *) tmp_cache + offset);
|
||||
if (tmp_cachesize < (offset + sizeof (struct cache_file_new))
|
||||
|| memcmp (tmp_cache_new->magic, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
|
||||
tmp_cache_new = NULL;
|
||||
else
|
||||
{
|
||||
if (! cache_file_new_matches_endian (tmp_cache_new))
|
||||
/* The old-format part of the cache is bogus as well
|
||||
if the endianness does not match. (But it is
|
||||
unclear how the new header can be located if the
|
||||
endianness does not match.) */
|
||||
{
|
||||
__munmap (file, tmp_cachesize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file != MAP_FAILED)
|
||||
__munmap (file, tmp_cachesize);
|
||||
return;
|
||||
}
|
||||
|
||||
struct cache_extension_all_loaded tmp_ext;
|
||||
if (!cache_extension_load (tmp_cache_new, tmp_cache, tmp_cachesize, &tmp_ext))
|
||||
{
|
||||
/* The extension is corrupt, so the cache is corrupt. */
|
||||
__munmap (file, tmp_cachesize);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we've gotten here, the loaded cache is good and we need to
|
||||
save it. */
|
||||
_dl_maybe_unload_ldsocache ();
|
||||
cache = tmp_cache;
|
||||
cache_new = tmp_cache_new;
|
||||
cachesize = tmp_cachesize;
|
||||
ext = tmp_ext;
|
||||
|
||||
assert (cache != NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Look up NAME in ld.so.cache and return the file name stored there, or null
|
||||
if none is found. The cache is loaded if it was not already. If loading
|
||||
@@ -389,81 +560,14 @@ _dl_load_cache_lookup (const char *name)
|
||||
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS))
|
||||
_dl_debug_printf (" search cache=%s\n", LD_SO_CACHE);
|
||||
|
||||
if (_dl_check_ldsocache_needs_loading ())
|
||||
_dl_maybe_load_ldsocache ();
|
||||
|
||||
if (cache == NULL)
|
||||
{
|
||||
/* Read the contents of the file. */
|
||||
void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
|
||||
PROT_READ);
|
||||
|
||||
/* We can handle three different cache file formats here:
|
||||
- only the new format
|
||||
- the old libc5/glibc2.0/2.1 format
|
||||
- the old format with the new format in it
|
||||
The following checks if the cache contains any of these formats. */
|
||||
if (file != MAP_FAILED && cachesize > sizeof *cache_new
|
||||
&& memcmp (file, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) == 0
|
||||
/* Check for corruption, avoiding overflow. */
|
||||
&& ((cachesize - sizeof *cache_new) / sizeof (struct file_entry_new)
|
||||
>= ((struct cache_file_new *) file)->nlibs))
|
||||
{
|
||||
if (! cache_file_new_matches_endian (file))
|
||||
{
|
||||
__munmap (file, cachesize);
|
||||
file = (void *) -1;
|
||||
}
|
||||
cache_new = file;
|
||||
cache = file;
|
||||
}
|
||||
else if (file != MAP_FAILED && cachesize > sizeof *cache
|
||||
&& memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0
|
||||
/* Check for corruption, avoiding overflow. */
|
||||
&& ((cachesize - sizeof *cache) / sizeof (struct file_entry)
|
||||
>= ((struct cache_file *) file)->nlibs))
|
||||
{
|
||||
size_t offset;
|
||||
/* Looks ok. */
|
||||
cache = file;
|
||||
|
||||
/* Check for new version. */
|
||||
offset = ALIGN_CACHE (sizeof (struct cache_file)
|
||||
+ cache->nlibs * sizeof (struct file_entry));
|
||||
|
||||
cache_new = (struct cache_file_new *) ((void *) cache + offset);
|
||||
if (cachesize < (offset + sizeof (struct cache_file_new))
|
||||
|| memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
|
||||
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
|
||||
cache_new = (void *) -1;
|
||||
else
|
||||
{
|
||||
if (! cache_file_new_matches_endian (cache_new))
|
||||
{
|
||||
/* The old-format part of the cache is bogus as well
|
||||
if the endianness does not match. (But it is
|
||||
unclear how the new header can be located if the
|
||||
endianness does not match.) */
|
||||
cache = (void *) -1;
|
||||
cache_new = (void *) -1;
|
||||
__munmap (file, cachesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file != MAP_FAILED)
|
||||
__munmap (file, cachesize);
|
||||
cache = (void *) -1;
|
||||
}
|
||||
|
||||
assert (cache != NULL);
|
||||
}
|
||||
|
||||
if (cache == (void *) -1)
|
||||
/* Previously looked for the cache file and didn't find it. */
|
||||
return NULL;
|
||||
|
||||
const char *best;
|
||||
if (cache_new != (void *) -1)
|
||||
if (cache_new != NULL)
|
||||
{
|
||||
const char *string_table = (const char *) cache_new;
|
||||
best = search_cache (string_table, cachesize,
|
||||
@@ -502,22 +606,67 @@ _dl_load_cache_lookup (const char *name)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef MAP_COPY
|
||||
/* If the system does not support MAP_COPY we cannot leave the file open
|
||||
all the time since this would create problems when the file is replaced.
|
||||
Therefore we provide this function to close the file and open it again
|
||||
once needed. */
|
||||
void
|
||||
_dl_unload_cache (void)
|
||||
const struct tunable_header_cached *
|
||||
_dl_load_cache_tunables (const char **data)
|
||||
{
|
||||
if (cache != NULL && cache != (struct cache_file *) -1)
|
||||
struct cache_extension_all_loaded ext;
|
||||
struct tunable_header_cached *thc;
|
||||
struct tunable_entry_cached *tec;
|
||||
int i, count;
|
||||
|
||||
if (_dl_check_ldsocache_needs_loading ())
|
||||
_dl_maybe_load_ldsocache ();
|
||||
|
||||
if (cache_new)
|
||||
*data = (const char *) cache_new;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
if (!cache_extension_load (cache_new, cache, cachesize, &ext))
|
||||
return NULL;
|
||||
|
||||
/* Validate length/contents here. */
|
||||
if (ext.sections[cache_extension_tag_tunables].size
|
||||
< sizeof(struct tunable_header_cached))
|
||||
return NULL;
|
||||
|
||||
thc = (struct tunable_header_cached *)
|
||||
ext.sections[cache_extension_tag_tunables].base;
|
||||
|
||||
/* Reject data produced by a different tunable cache format. */
|
||||
if (thc->signature != TUNCONF_SIGNATURE || thc->version != TUNCONF_VERSION)
|
||||
return NULL;
|
||||
|
||||
tec = thc->tunables;
|
||||
count = thc->num_tunables;
|
||||
|
||||
if (ext.sections[cache_extension_tag_tunables].base
|
||||
+ ext.sections[cache_extension_tag_tunables].size
|
||||
!= (void *) & tec[count])
|
||||
return NULL;
|
||||
|
||||
/* Validate each entry. The string table lies between the file entries
|
||||
and the end of the mapping; clamp its end to CACHESIZE so that a bogus
|
||||
len_strings cannot make an offset point outside the mapped file. */
|
||||
size_t s_start = (const char *) (&cache_new->libs[cache_new->nlibs]) - *data;
|
||||
size_t s_end;
|
||||
if (s_start >= cachesize
|
||||
|| INT_ADD_WRAPV (s_start, cache_new->len_strings, &s_end))
|
||||
return NULL;
|
||||
if (s_end > cachesize)
|
||||
s_end = cachesize;
|
||||
for (i = 0; i < count; i ++)
|
||||
{
|
||||
__munmap (cache, cachesize);
|
||||
cache = NULL;
|
||||
if (thc->tunables[i].name_offset < s_start
|
||||
|| thc->tunables[i].name_offset >= s_end
|
||||
|| thc->tunables[i].value_offset < s_start
|
||||
|| thc->tunables[i].value_offset >= s_end)
|
||||
return NULL;
|
||||
if (thc->tunables[i].flag_offset != 0
|
||||
&& (thc->tunables[i].flag_offset < s_start
|
||||
|| thc->tunables[i].flag_offset >= s_end))
|
||||
return NULL;
|
||||
}
|
||||
#ifdef SHARED
|
||||
/* This marks the glibc_hwcaps_priorities array as out-of-date. */
|
||||
glibc_hwcaps_priorities_length = 0;
|
||||
#endif
|
||||
|
||||
return thc;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -898,11 +898,6 @@ no more namespaces available for dlmopen()"));
|
||||
struct dl_exception exception;
|
||||
int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
|
||||
|
||||
#if defined USE_LDCONFIG && !defined MAP_COPY
|
||||
/* We must unmap the cache file. */
|
||||
_dl_unload_cache ();
|
||||
#endif
|
||||
|
||||
/* Do this for both the error and success cases. The old value has
|
||||
only been determined if the namespace ID was assigned (i.e., it
|
||||
is not __LM_ID_CALLER). In the success case, we actually may
|
||||
|
||||
+2
-14
@@ -42,20 +42,6 @@ typedef struct
|
||||
tunable_num_t max;
|
||||
} tunable_type_t;
|
||||
|
||||
/* Security level for tunables. This decides what to do with individual
|
||||
tunables for AT_SECURE binaries. */
|
||||
typedef enum
|
||||
{
|
||||
/* Erase the tunable for AT_SECURE binaries so that child processes don't
|
||||
read it. */
|
||||
TUNABLE_SECLEVEL_SXID_ERASE = 0,
|
||||
/* Ignore the tunable for AT_SECURE binaries, but don't erase it, so that
|
||||
child processes can read it. */
|
||||
TUNABLE_SECLEVEL_SXID_IGNORE = 1,
|
||||
/* Read the tunable. */
|
||||
TUNABLE_SECLEVEL_NONE = 2,
|
||||
} tunable_seclevel_t;
|
||||
|
||||
/* A tunable. */
|
||||
struct _tunable
|
||||
{
|
||||
@@ -65,6 +51,8 @@ struct _tunable
|
||||
tunable_val_t val; /* The value. */
|
||||
bool initialized; /* Flag to indicate that the tunable is
|
||||
initialized. */
|
||||
bool locked; /* If set, modifications are not
|
||||
allowed. */
|
||||
/* Compatibility elements. */
|
||||
const char env_alias[TUNABLE_ALIAS_MAX]; /* The compatibility environment
|
||||
variable name. */
|
||||
|
||||
+172
-3
@@ -37,6 +37,7 @@
|
||||
|
||||
#define TUNABLES_INTERNAL 1
|
||||
#include "dl-tunables.h"
|
||||
#include "tunconf.h"
|
||||
|
||||
static char **
|
||||
get_next_env (char **envp, char **name, char **val, char ***prev_envp)
|
||||
@@ -71,6 +72,9 @@ do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
|
||||
{
|
||||
tunable_num_t val, min, max;
|
||||
|
||||
if (cur->locked)
|
||||
return;
|
||||
|
||||
switch (cur->type.type_code)
|
||||
{
|
||||
case TUNABLE_TYPE_STRING:
|
||||
@@ -175,6 +179,14 @@ struct tunable_toset_t
|
||||
|
||||
enum { tunables_list_size = array_length (tunable_list) };
|
||||
|
||||
/* Records tunables that were set from GLIBC_TUNABLES during this call, so
|
||||
that a legacy environment-variable alias does not override them (the
|
||||
canonical GLIBC_TUNABLES form takes precedence over the aliases).
|
||||
A tunable that was set only from the system-wide cache is deliberately not
|
||||
recorded here, so an alias may still override an overridable cache default;
|
||||
a nonoverridable one remains protected by tunable_t::locked. */
|
||||
static bool tunable_set_by_env[tunables_list_size];
|
||||
|
||||
/* Parse the tunable string VALSTRING and set TUNABLES with the found tunables
|
||||
and their respective values. The VALSTRING is parsed in place, with the
|
||||
tunable start and size recorded in TUNABLES.
|
||||
@@ -284,6 +296,10 @@ parse_tunables (const char *valstring)
|
||||
if (!tunable_initialize (tunables[i].t, tunables[i].value,
|
||||
tunables[i].len))
|
||||
parse_tunable_print_error (&tunables[i]);
|
||||
else
|
||||
/* GLIBC_TUNABLES set this tunable; a legacy alias must not
|
||||
override it. */
|
||||
tunable_set_by_env[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +307,7 @@ parse_tunables (const char *valstring)
|
||||
ENV_ALIAS to find values. Later we will also use the tunable names to find
|
||||
values. */
|
||||
void
|
||||
__tunables_init (char **envp)
|
||||
__tunables_init (char **envp, char **argv)
|
||||
{
|
||||
char *envname = NULL;
|
||||
char *envval = NULL;
|
||||
@@ -302,6 +318,155 @@ __tunables_init (char **envp)
|
||||
if (MALLOC_DEFAULT_THP_PAGESIZE > 0)
|
||||
TUNABLE_SET (glibc, malloc, hugetlb, 1);
|
||||
|
||||
#if defined(SHARED) && defined (USE_LDCONFIG)
|
||||
const char *prog_name = (argv && argv[0]) ? argv[0] : "";
|
||||
int prog_name_len = -1;
|
||||
const char *base_name = NULL;
|
||||
#ifdef PATH_MAX
|
||||
char exebuf[PATH_MAX];
|
||||
#else
|
||||
char exebuf[256];
|
||||
#endif
|
||||
const struct tunable_header_cached *thc;
|
||||
const char *td;
|
||||
|
||||
thc = _dl_load_cache_tunables (&td);
|
||||
if (thc != NULL)
|
||||
{
|
||||
for (int t = 0; t < thc->num_tunables; ++ t)
|
||||
{
|
||||
const struct tunable_entry_cached *tec = &( thc->tunables[t] );
|
||||
int tid = tec->tunable_id;
|
||||
const char *name = td + tec->name_offset;
|
||||
const char *value = td + tec->value_offset;
|
||||
|
||||
/* Check that we have the correct tunable, and search by
|
||||
name if needed. We rely on order of operations here to
|
||||
avoid mis-indexing tunables[]. */
|
||||
if (tid < 0 || tid >= tunables_list_size
|
||||
|| strcmp (name, tunable_list[tid].name) != 0)
|
||||
{
|
||||
/* It does not, search by name instead. */
|
||||
tid = -1;
|
||||
for (int i = 0; i < tunables_list_size; i++)
|
||||
{
|
||||
if (strcmp (name, tunable_list[i].name) == 0)
|
||||
{
|
||||
tid = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tid == -1)
|
||||
continue;
|
||||
}
|
||||
/* At this point, TID is valid for the tunable we want. */
|
||||
|
||||
if (tec->flags & TUNCONF_EXCLUDE_SECURE && __libc_enable_secure)
|
||||
goto skip_due_to_filter;
|
||||
if (tec->flags & TUNCONF_EXCLUDE_UNSECURE && !__libc_enable_secure)
|
||||
goto skip_due_to_filter;
|
||||
|
||||
/* Apply selected filter, if any. */
|
||||
switch (tec->flags & TUNCONF_FLAG_FILTER) {
|
||||
case TUNCONF_FILTER_NONE:
|
||||
break;
|
||||
case TUNCONF_FILTER_PERPROC:
|
||||
/* Perform one-time calculations that aren't needed if we
|
||||
don't use this filter. */
|
||||
if (prog_name_len == -1)
|
||||
{
|
||||
ssize_t n = readlink ("/proc/self/exe",
|
||||
exebuf, sizeof (exebuf) - 1);
|
||||
if (n > 0 && n < sizeof(exebuf)-1)
|
||||
{
|
||||
/* If /proc/self/exe exists and we can read it,
|
||||
it's more reliable than argv[] so use it. */
|
||||
exebuf[n] = '\0';
|
||||
prog_name = exebuf;
|
||||
}
|
||||
else if (__libc_enable_secure)
|
||||
prog_name = NULL;
|
||||
if (prog_name != NULL)
|
||||
{
|
||||
const char *slash = NULL, *cp;
|
||||
for (cp = prog_name; *cp; ++ cp)
|
||||
if (*cp == '/')
|
||||
slash = cp;
|
||||
if (slash)
|
||||
base_name = slash + 1;
|
||||
else
|
||||
base_name = prog_name;
|
||||
prog_name_len = strlen (prog_name);
|
||||
}
|
||||
}
|
||||
/* prog_name and the cached string are both NUL terminated. */
|
||||
if (prog_name)
|
||||
{
|
||||
if (((const char *)(td + tec->flag_offset))[0] == '/')
|
||||
{
|
||||
if (strcmp (prog_name, td + tec->flag_offset) != 0)
|
||||
goto skip_due_to_filter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp (base_name, td + tec->flag_offset) != 0)
|
||||
goto skip_due_to_filter;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Program is AT_SECURE but the only source of program
|
||||
name is argv[0], which is not secure, so we do not
|
||||
match any name-based filter. */
|
||||
goto skip_due_to_filter;
|
||||
break;
|
||||
default:
|
||||
/* Unknown filter. */
|
||||
goto skip_due_to_filter;
|
||||
}
|
||||
|
||||
/* If the tunable is set here, any previously set
|
||||
overridability flag is discarded. We need to reset the
|
||||
overridability flag here so we can change the tunable,
|
||||
and may set it later if this tunable also locks it. */
|
||||
tunable_list[tid].locked = false;
|
||||
|
||||
/* See if the parsed type matches the desired type. */
|
||||
if (tunable_list[tid].type.type_code == TUNABLE_TYPE_STRING)
|
||||
{
|
||||
/* This is a memory leak but there's no easy way around
|
||||
it, as the mapping will go away if the disk file is
|
||||
updated and the cache is reloaded. */
|
||||
tunable_list[tid].val.strval.str = __strdup (value);
|
||||
tunable_list[tid].val.strval.len = strlen (value);
|
||||
tunable_list[tid].initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tunable_val_t tval;
|
||||
if (tec->flags & TUNCONF_FLAG_PARSED)
|
||||
{
|
||||
tval.numval = tec->parsed_value;
|
||||
do_tunable_update_val (& tunable_list[tid],
|
||||
&tval, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
tunable_initialize (& tunable_list[tid],
|
||||
value, strlen (value));
|
||||
}
|
||||
}
|
||||
|
||||
/* The overriability flag only applies to tunables
|
||||
which aren't filtered out. */
|
||||
if ((tec->flags & TUNCONF_FLAG_OVERRIDABLE)
|
||||
== TUNCONF_OVERRIDE_DENY)
|
||||
tunable_list[tid].locked = true;
|
||||
|
||||
skip_due_to_filter:;
|
||||
}
|
||||
}
|
||||
#endif /* defined(SHARED) && defined (USE_LDCONFIG) */
|
||||
|
||||
/* Ignore tunables for AT_SECURE programs. */
|
||||
if (__libc_enable_secure)
|
||||
return;
|
||||
@@ -345,9 +510,13 @@ __tunables_init (char **envp)
|
||||
|
||||
for (int i = 0; i < tunable_num_env_alias; i++)
|
||||
{
|
||||
/* Skip over tunables that have either been set or already initialized. */
|
||||
/* Skip aliases whose tunable was already set through GLIBC_TUNABLES,
|
||||
which takes precedence over the alias. A value coming only from the
|
||||
system-wide cache does not block the alias here: an overridable cache
|
||||
default may still be overridden, while a nonoverridable one is
|
||||
protected by tunable_t::locked. */
|
||||
if (tunables_env_alias[i].t == NULL
|
||||
|| tunables_env_alias[i].t->initialized)
|
||||
|| tunable_set_by_env[tunable_env_alias_list[i]])
|
||||
continue;
|
||||
|
||||
if (!tunable_initialize (tunables_env_alias[i].t,
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ typedef void (*tunable_callback_t) (tunable_val_t *);
|
||||
|
||||
#include "dl-tunable-list.h"
|
||||
|
||||
extern void __tunables_init (char **);
|
||||
extern void __tunables_init (char **, char **);
|
||||
extern void __tunables_print (void);
|
||||
extern bool __tunable_is_initialized (tunable_id_t);
|
||||
extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
|
||||
|
||||
+7
-1
@@ -45,7 +45,13 @@ elf_dynamic_is_Rel_irelative (const ElfW(Rel) *reloc, const ElfW(Sym) *sym)
|
||||
return ((sym != NULL
|
||||
&& ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC
|
||||
&& sym->st_shndx != SHN_UNDEF)
|
||||
|| r_type == ELF_MACHINE_IRELATIVE);
|
||||
|| r_type == ELF_MACHINE_IRELATIVE
|
||||
# ifdef ELF_MACHINE_IRELATIVE_PLT
|
||||
/* Some ports resolve an IFUNC PLT slot for a local resolver with a
|
||||
dedicated reloc that carries no symboli. */
|
||||
|| r_type == ELF_MACHINE_IRELATIVE_PLT
|
||||
# endif
|
||||
);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
@@ -847,6 +847,7 @@ typedef struct
|
||||
#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */
|
||||
#define NT_RISCV_TAGGED_ADDR_CTRL 0x902 /* RISC-V tagged
|
||||
address control */
|
||||
#define NT_RISCV_USER_CFI 0x903 /* RISC-V shadow stack state */
|
||||
#define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */
|
||||
#define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and
|
||||
status registers. */
|
||||
|
||||
@@ -47,8 +47,10 @@ ldconfig_parse_config_1 (const char *filename, bool do_chroot,
|
||||
|
||||
opt_chroot - If non-NULL, all paths are relative to this.
|
||||
|
||||
callback - for each non-blank line in the file, this function is called
|
||||
with the line and it's location.
|
||||
callback - for each non-blank line in the file, this function is
|
||||
called with the line and it's location. Will also be called
|
||||
with a NULL line at the start and end of each file, for
|
||||
file-scoped config items.
|
||||
*/
|
||||
|
||||
void
|
||||
|
||||
+183
-5
@@ -44,12 +44,17 @@
|
||||
#include <dl-cache.h>
|
||||
#include <dl-hwcaps.h>
|
||||
#include <dl-is_dso.h>
|
||||
#include "tunconf.h"
|
||||
|
||||
|
||||
#ifndef LD_SO_CONF
|
||||
# define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
|
||||
#endif
|
||||
|
||||
#ifndef TUNABLES_CONF
|
||||
# define TUNABLES_CONF SYSCONFDIR "/tunables.conf"
|
||||
#endif
|
||||
|
||||
/* Get libc version number. */
|
||||
#include <version.h>
|
||||
|
||||
@@ -104,12 +109,18 @@ static int opt_manual_link;
|
||||
/* Should we ignore an old auxiliary cache file? */
|
||||
static int opt_ignore_aux_cache;
|
||||
|
||||
/* Install a pre-existing cache file instead of generating a new one. */
|
||||
static int opt_install;
|
||||
|
||||
/* Cache file to use. */
|
||||
static char *cache_file;
|
||||
|
||||
/* Configuration file. */
|
||||
/* Configuration file for libraries. */
|
||||
static const char *config_file;
|
||||
|
||||
/* Configuration file for tunables. */
|
||||
static const char *tunconfig_file;
|
||||
|
||||
/* Name and version of program. */
|
||||
static void print_version (FILE *stream, struct argp_state *state);
|
||||
void (*argp_program_version_hook) (FILE *, struct argp_state *)
|
||||
@@ -127,11 +138,13 @@ static const struct argp_option options[] =
|
||||
{ NULL, 'X', NULL, 0, N_("Don't update symbolic links"), 0},
|
||||
{ NULL, 'r', N_("ROOT"), 0, N_("Change to and use ROOT as root directory"), 0},
|
||||
{ NULL, 'C', N_("CACHE"), 0, N_("Use CACHE as cache file"), 0},
|
||||
{ NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0},
|
||||
{ NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file for libraries"), 0},
|
||||
{ NULL, 't', N_("TUNCONF"), 0, N_("Use TUNCONF as configuration file for tunables"), 0},
|
||||
{ NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0},
|
||||
{ NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0},
|
||||
{ "format", 'c', N_("FORMAT"), 0, N_("Format to use: new (default), old, or compat"), 0},
|
||||
{ "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0},
|
||||
{ "install", 'I', NULL, 0, N_("Install pre-existing cache file"), 0},
|
||||
{ NULL, 0, NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -164,6 +177,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
case 'f':
|
||||
config_file = arg;
|
||||
break;
|
||||
case 't':
|
||||
tunconfig_file = arg;
|
||||
break;
|
||||
case 'i':
|
||||
opt_ignore_aux_cache = 1;
|
||||
break;
|
||||
@@ -197,6 +213,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
else if (strcmp (arg, "new") == 0)
|
||||
opt_format = opt_format_new;
|
||||
break;
|
||||
case 'I':
|
||||
opt_install = 1;
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
@@ -421,8 +440,11 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
|
||||
}
|
||||
|
||||
static void
|
||||
add_dir_callback (const char *line, const char *from_file, int from_line)
|
||||
add_dir_callback (char *line, const char *from_file, int from_line)
|
||||
{
|
||||
/* Denotes file boundaries. Not needed here. */
|
||||
if (line == NULL)
|
||||
return;
|
||||
if (!strncasecmp (line, "hwcap", 5) && isblank (line[5]))
|
||||
error (0, 0, _("%s:%u: hwcap directive ignored"), from_file, from_line);
|
||||
else
|
||||
@@ -1026,6 +1048,155 @@ search_dirs (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
install_cache_file (const char *source_arg)
|
||||
{
|
||||
int e;
|
||||
|
||||
if (source_arg == NULL)
|
||||
error (EXIT_FAILURE, 0, _("Missing source file name"));
|
||||
|
||||
const char *source = (opt_chroot
|
||||
? chroot_canon (opt_chroot, source_arg)
|
||||
: source_arg);
|
||||
if (source == NULL)
|
||||
error (EXIT_FAILURE, errno, _("Can't find %s"), source_arg);
|
||||
|
||||
int src_fd = open (source, O_RDONLY);
|
||||
if (src_fd < 0)
|
||||
error (EXIT_FAILURE, errno, _("Can't open %s"), source);
|
||||
|
||||
char *dest = xmalloc (strlen (cache_file) + 1 + 1);
|
||||
|
||||
/* This matches the temp file created by cache.c, and should be
|
||||
on the same filesystem as the cache file. */
|
||||
sprintf (dest, "%s~", cache_file);
|
||||
int dest_fd;
|
||||
|
||||
struct stat st;
|
||||
if (fstat (src_fd, &st) < 0)
|
||||
error (EXIT_FAILURE, errno, _("Can't stat %s"), source);
|
||||
|
||||
char buf[512];
|
||||
ssize_t r, w = 0, sz = 0;
|
||||
char *bp = buf;
|
||||
|
||||
/* Read the first part of the file and verify it looks
|
||||
reasonable. */
|
||||
while (sz < sizeof (buf)
|
||||
&& (r = read (src_fd, bp, sizeof (buf) - sz)) > 0)
|
||||
{
|
||||
sz += r;
|
||||
bp += r;
|
||||
}
|
||||
if (r < 0)
|
||||
error (EXIT_FAILURE, errno, _("Error reading file %s"), source);
|
||||
|
||||
if (! ((sz >= sizeof (CACHEMAGIC)
|
||||
&& memcmp (buf, CACHEMAGIC,
|
||||
sizeof (CACHEMAGIC) - 1) == 0)
|
||||
|| (sz >= sizeof (CACHEMAGIC_NEW)
|
||||
&& memcmp (buf, CACHEMAGIC_NEW,
|
||||
sizeof (CACHEMAGIC_NEW) - 1) == 0)))
|
||||
{
|
||||
error (EXIT_FAILURE, 0,
|
||||
_("File %s does not look like an ld.so.cache file"),
|
||||
source);
|
||||
}
|
||||
|
||||
/* Now write that first part out. */
|
||||
dest_fd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
|
||||
S_IRUSR|S_IWUSR);
|
||||
if (dest_fd < 0)
|
||||
error (EXIT_FAILURE, errno, _("Can't create %s"), dest);
|
||||
|
||||
r = sz;
|
||||
bp = buf;
|
||||
while (r > 0 && (w = write (dest_fd, bp, r)) > 0)
|
||||
{
|
||||
r -= w;
|
||||
bp += w;
|
||||
}
|
||||
if (w < 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Error writing file %s"), dest);
|
||||
}
|
||||
|
||||
/* At this point, sz contains the number of bytes copied so far.
|
||||
Copy the rest of the file. */
|
||||
while ((r = read (src_fd, buf, sizeof(buf))) > 0)
|
||||
{
|
||||
bp = buf;
|
||||
while (r > 0 && (w = write (dest_fd, bp, r)) > 0)
|
||||
{
|
||||
bp += w;
|
||||
r -= w;
|
||||
sz += w;
|
||||
}
|
||||
if (w <= 0)
|
||||
break;
|
||||
}
|
||||
if (r < 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Error reading file %s"), source);
|
||||
}
|
||||
if (w < 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Error writing file %s"), dest);
|
||||
}
|
||||
|
||||
close (src_fd);
|
||||
|
||||
/* Make sure we copied it all. */
|
||||
if (sz < st.st_size)
|
||||
{
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, 0, _("Unable to copy file %s to %s"),
|
||||
source, dest);
|
||||
}
|
||||
|
||||
/* Make sure user can always read the cache file */
|
||||
if (fchmod (dest_fd, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e,
|
||||
_("Changing access rights of %s to %#o failed"), dest,
|
||||
S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
|
||||
}
|
||||
|
||||
if (fsync (dest_fd) != 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Writing to %s failed"), dest);
|
||||
}
|
||||
|
||||
if (rename (dest, cache_file) < 0)
|
||||
{
|
||||
e = errno;
|
||||
unlink (dest);
|
||||
close (dest_fd);
|
||||
error (EXIT_FAILURE, e, _("Can't rename %s to %s"),
|
||||
dest, cache_file);
|
||||
}
|
||||
|
||||
if (close (dest_fd) != 0)
|
||||
error (EXIT_FAILURE, errno, _("Writing to %s failed"), dest);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
@@ -1045,8 +1216,8 @@ main (int argc, char **argv)
|
||||
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
|
||||
|
||||
/* Remaining arguments are additional directories if opt_manual_link
|
||||
is not set. */
|
||||
if (remaining != argc && !opt_manual_link)
|
||||
and opt_install are not set. */
|
||||
if (remaining != argc && !opt_manual_link && !opt_install)
|
||||
{
|
||||
int i;
|
||||
for (i = remaining; i < argc; ++i)
|
||||
@@ -1089,6 +1260,9 @@ main (int argc, char **argv)
|
||||
if (config_file == NULL)
|
||||
config_file = LD_SO_CONF;
|
||||
|
||||
if (tunconfig_file == NULL)
|
||||
tunconfig_file = TUNABLES_CONF;
|
||||
|
||||
if (opt_print_cache)
|
||||
{
|
||||
if (opt_chroot != NULL)
|
||||
@@ -1139,6 +1313,8 @@ main (int argc, char **argv)
|
||||
exit (0);
|
||||
}
|
||||
|
||||
if (opt_install)
|
||||
install_cache_file (argv[remaining]);
|
||||
|
||||
if (opt_build_cache)
|
||||
init_cache ();
|
||||
@@ -1164,6 +1340,8 @@ main (int argc, char **argv)
|
||||
|
||||
search_dirs ();
|
||||
|
||||
parse_tunconf (tunconfig_file, opt_chroot);
|
||||
|
||||
if (opt_build_cache)
|
||||
{
|
||||
save_cache (cache_file);
|
||||
|
||||
@@ -2371,11 +2371,6 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
/* Auditing checkpoint: we have added all objects. */
|
||||
_dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT);
|
||||
|
||||
#if defined USE_LDCONFIG && !defined MAP_COPY
|
||||
/* We must munmap() the cache file. */
|
||||
_dl_unload_cache ();
|
||||
#endif
|
||||
|
||||
/* Once we return, _dl_sysdep_start will invoke
|
||||
the DT_INIT functions and then *USER_ENTRY. */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/* Test ldconfig cache is correctly used when changed.
|
||||
Copyright (C) 2026 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; see the file COPYING.LIB. If
|
||||
not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* What we're testing for: We initially load ld.so.cache at startup
|
||||
and remember it. If we detect that ld.so.cache has changed, and we
|
||||
can load it successfully, we replace our remember it. If it
|
||||
doesn't change, or if the new version is corrupted, we continue
|
||||
using the old remembered copy. */
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <support/support.h>
|
||||
#include <support/check.h>
|
||||
|
||||
#include <support/xstdio.h>
|
||||
#include <support/xstdlib.h>
|
||||
#include <support/xdlfcn.h>
|
||||
#include <support/xunistd.h>
|
||||
|
||||
|
||||
/* Verify that we can (or can't) load one of our test objects. */
|
||||
static void
|
||||
try (int i, int invert)
|
||||
{
|
||||
char dlname[100];
|
||||
char symname[100];
|
||||
int (*proc)(int);
|
||||
void *dl;
|
||||
|
||||
/* These match the objects copied by tst-ldconfig-cache.script,
|
||||
copied from tst-tls-manydynamic*.so. */
|
||||
sprintf (dlname, "libcache%d.so", i);
|
||||
sprintf (symname, "set_value_%02d", i);
|
||||
|
||||
dl = dlopen (dlname, RTLD_NOW);
|
||||
|
||||
if (invert)
|
||||
{
|
||||
/* This is a negative test; if the object doesn't load the test
|
||||
passes. */
|
||||
TEST_VERIFY (dl == NULL);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a positive test; if the object doesn't load the test
|
||||
fails. */
|
||||
if (dl == NULL)
|
||||
FAIL_EXIT1 ("error: dlopen: %s\n", dlerror ());
|
||||
}
|
||||
|
||||
proc = xdlsym (dl, symname);
|
||||
/* We don't need to call the symbol, just make sure it exists. */
|
||||
TEST_VERIFY (proc != NULL);
|
||||
|
||||
xdlclose (dl);
|
||||
}
|
||||
|
||||
/* Cause corruption in the cache that should prevent loading it. */
|
||||
static void
|
||||
corrupt (void)
|
||||
{
|
||||
int fd = xopen ("/etc/ld.so.cache", O_RDWR, 0);
|
||||
char bytes[] = { 15, 32, 184, 4 };
|
||||
xwrite (fd, bytes, sizeof(bytes));
|
||||
xclose (fd);
|
||||
}
|
||||
|
||||
/* Regenerate the cache from ld.so.conf. */
|
||||
static void
|
||||
ldconfig (void)
|
||||
{
|
||||
xsystem ("/sbin/ldconfig -X");
|
||||
}
|
||||
|
||||
/* Change ld.so.conf to refer to the new directory, and generate a new
|
||||
cache. */
|
||||
static void
|
||||
newpath (const char *p)
|
||||
{
|
||||
FILE *f = xfopen ("/etc/ld.so.conf", "w");
|
||||
fprintf (f, "%s\n", p);
|
||||
xfclose (f);
|
||||
|
||||
ldconfig ();
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
/* Test that the cache we started with can still load objects in
|
||||
/a. */
|
||||
try (1, 0);
|
||||
|
||||
/* Create a new cache that doesn't include /a but corrupt it. Test
|
||||
that we still use the cache with /a in it. */
|
||||
newpath ("/c");
|
||||
corrupt ();
|
||||
try (2, 0);
|
||||
|
||||
/* Regenerate a clean cache with /a in it and verify we can load
|
||||
objects in /a. */
|
||||
newpath ("/a");
|
||||
try (3, 0);
|
||||
|
||||
/* Generate a new cache with /b but not /a and make sure objects
|
||||
in /a can't be loaded. */
|
||||
newpath ("/b");
|
||||
try (3, 1);
|
||||
|
||||
/* But objects in /b can be loaded. */
|
||||
try (4, 0);
|
||||
/* Even multiple times. */
|
||||
try (5, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,3 @@
|
||||
/lib
|
||||
/lib64
|
||||
/a
|
||||
@@ -0,0 +1,7 @@
|
||||
mkdirp 0755 /a
|
||||
cp $B/elf/tst-tls-manydynamic01mod.so /a/libcache1.so
|
||||
cp $B/elf/tst-tls-manydynamic02mod.so /a/libcache2.so
|
||||
cp $B/elf/tst-tls-manydynamic03mod.so /a/libcache3.so
|
||||
mkdirp 0755 /b
|
||||
cp $B/elf/tst-tls-manydynamic04mod.so /b/libcache4.so
|
||||
cp $B/elf/tst-tls-manydynamic05mod.so /b/libcache5.so
|
||||
@@ -0,0 +1,125 @@
|
||||
#!/bin/sh
|
||||
# Test that ldconfig --install installs a pre-built cache file.
|
||||
# Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
|
||||
# The GNU C Library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
# The GNU C Library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with the GNU C Library; if not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
|
||||
set -e
|
||||
|
||||
common_objpfx=$1
|
||||
test_wrapper_env=$2
|
||||
run_program_env=$3
|
||||
|
||||
testroot="${common_objpfx}elf/tst-ldconfig-install-directory"
|
||||
cleanup () {
|
||||
rm -rf "$testroot"
|
||||
}
|
||||
trap cleanup 0
|
||||
|
||||
rm -rf "$testroot"
|
||||
mkdir -p "$testroot/etc"
|
||||
|
||||
ldconfig="${common_objpfx}elf/ldconfig"
|
||||
run_ldconfig () {
|
||||
${test_wrapper_env} ${run_program_env} "$ldconfig" "$@"
|
||||
}
|
||||
|
||||
errors=0
|
||||
fail () {
|
||||
echo "error: $1"
|
||||
errors=1
|
||||
}
|
||||
|
||||
# Build a pre-built cache to install.
|
||||
source="$testroot/prebuilt-ld.so.cache"
|
||||
mkdir -p "$testroot/lib"
|
||||
run_ldconfig -X -f /dev/null -C "$source" "$testroot/lib"
|
||||
test -r "$source" || fail "ldconfig did not create the pre-built cache"
|
||||
|
||||
# Pad the source past the 512-byte internal copy buffer so that the multi-block
|
||||
# copy path is exercised, while leaving the cache magic at the start intact.
|
||||
dd if=/dev/zero bs=1024 count=4 >> "$source" 2>/dev/null
|
||||
|
||||
dest="$testroot/etc/ld.so.cache"
|
||||
temp="$dest~"
|
||||
|
||||
run_ldconfig --install -f /dev/null -C "$dest" "$source"
|
||||
|
||||
# The destination must exist and be byte-identical to the source.
|
||||
if test -r "$dest"; then
|
||||
if cmp -s "$source" "$dest"; then
|
||||
echo "info: installed cache matches the source"
|
||||
else
|
||||
fail "installed cache differs from the source"
|
||||
fi
|
||||
else
|
||||
fail "destination cache file was not created"
|
||||
fi
|
||||
|
||||
# The temporary file used during the atomic rename must not be left behind.
|
||||
if test -e "$temp"; then
|
||||
fail "temporary file $temp was left behind"
|
||||
fi
|
||||
|
||||
# The installed cache must be world-readable (0644).
|
||||
if test -r "$dest"; then
|
||||
mode=$(ls -l "$dest" | cut -c1-10)
|
||||
case "$mode" in
|
||||
(-rw-r--r--) echo "info: installed cache has expected permissions" ;;
|
||||
(*) fail "installed cache has unexpected permissions: $mode" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# A second install over an existing cache must also succeed.
|
||||
run_ldconfig --install -f /dev/null -C "$dest" "$source"
|
||||
if cmp -s "$source" "$dest"; then
|
||||
echo "info: re-install over an existing cache works"
|
||||
else
|
||||
fail "re-install produced a different cache"
|
||||
fi
|
||||
|
||||
# Error case: a source file that is not a cache must be rejected, and no
|
||||
# destination must be produced.
|
||||
rm -f "$dest"
|
||||
notcache="$testroot/not-a-cache"
|
||||
echo "this is not an ld.so.cache file" > "$notcache"
|
||||
if run_ldconfig --install -f /dev/null -C "$dest" "$notcache" 2>"$testroot/err"; then
|
||||
fail "ldconfig accepted a file that is not a cache"
|
||||
else
|
||||
if grep -q "does not look like an ld.so.cache file" "$testroot/err"; then
|
||||
echo "info: non-cache source correctly rejected"
|
||||
else
|
||||
fail "unexpected error message for non-cache source"
|
||||
cat "$testroot/err"
|
||||
fi
|
||||
fi
|
||||
test -e "$dest" && fail "destination created from an invalid source"
|
||||
|
||||
# Error case: a missing source argument must be diagnosed.
|
||||
if run_ldconfig --install -f /dev/null -C "$dest" 2>"$testroot/err"; then
|
||||
fail "ldconfig accepted --install without a source file"
|
||||
else
|
||||
grep -q "Missing source file name" "$testroot/err" \
|
||||
|| fail "unexpected error message for missing source"
|
||||
fi
|
||||
|
||||
# Error case: a nonexistent source must be diagnosed.
|
||||
if run_ldconfig --install -f /dev/null -C "$dest" \
|
||||
"$testroot/does-not-exist" 2>"$testroot/err"; then
|
||||
fail "ldconfig accepted a nonexistent source file"
|
||||
fi
|
||||
|
||||
exit $errors
|
||||
@@ -0,0 +1,81 @@
|
||||
/* Test that the tunables cache can override env vars.
|
||||
Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <support/check.h>
|
||||
|
||||
#include "dl-tunables.h"
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
size_t tcache_count = TUNABLE_GET_FULL (glibc, malloc, tcache_count, size_t, NULL);
|
||||
size_t tcache_max = TUNABLE_GET_FULL (glibc, malloc, tcache_max, size_t, NULL);
|
||||
int32_t perturb = TUNABLE_GET_FULL (glibc, malloc, perturb, int32_t, NULL);
|
||||
size_t mmap_threshold = TUNABLE_GET_FULL (glibc, malloc, mmap_threshold, size_t, NULL);
|
||||
size_t trim_threshold = TUNABLE_GET_FULL (glibc, malloc, trim_threshold, size_t, NULL);
|
||||
|
||||
printf("tcache count is %zu (should be 5, from env)\n", tcache_count);
|
||||
TEST_COMPARE ((long)tcache_count, 5);
|
||||
printf("tcache max is %zu (should be 4, from /etc)\n", tcache_max);
|
||||
TEST_COMPARE ((long)tcache_max, 4);
|
||||
|
||||
/* This is set by the environment but blocked by the config. */
|
||||
printf("perturb is %" PRId32 " (should be 42, from /etc)\n",
|
||||
perturb);
|
||||
TEST_COMPARE (perturb, 42);
|
||||
|
||||
/* This is blocked by the general config, enabled by filter, set in env. */
|
||||
printf("mmap_threshold is %zu (should be 10002, from env)\n",
|
||||
mmap_threshold);
|
||||
TEST_COMPARE ((long)mmap_threshold, 10002);
|
||||
|
||||
/* This is allowed by the general config, blocked by filter, set in env. */
|
||||
printf("trim_threshold is %zu (should be 10001, from filter)\n",
|
||||
trim_threshold);
|
||||
TEST_COMPARE ((long)trim_threshold, 10001);
|
||||
|
||||
/* Interaction with legacy environment-variable aliases (MALLOC_*). */
|
||||
int32_t mmap_max = TUNABLE_GET_FULL (glibc, malloc, mmap_max, int32_t, NULL);
|
||||
size_t top_pad = TUNABLE_GET_FULL (glibc, malloc, top_pad, size_t, NULL);
|
||||
size_t arena_max = TUNABLE_GET_FULL (glibc, malloc, arena_max, size_t, NULL);
|
||||
|
||||
/* Overridable cache default (100); the MALLOC_MMAP_MAX_ alias overrides
|
||||
it, just like GLIBC_TUNABLES would. */
|
||||
printf("mmap_max is %" PRId32 " (should be 200, from MALLOC_MMAP_MAX_ alias)"
|
||||
"\n",
|
||||
mmap_max);
|
||||
TEST_COMPARE (mmap_max, 200);
|
||||
|
||||
/* Nonoverridable cache default (100); the MALLOC_TOP_PAD_ alias must not
|
||||
override it. */
|
||||
printf("top_pad is %zu (should be 100, from /etc nonoverridable)\n",
|
||||
top_pad);
|
||||
TEST_COMPARE ((long)top_pad, 100);
|
||||
|
||||
/* Set both by GLIBC_TUNABLES (300) and by the MALLOC_ARENA_MAX alias
|
||||
(400); the canonical GLIBC_TUNABLES form wins. */
|
||||
printf("arena_max is %zu (should be 300, from GLIBC_TUNABLES)\n", arena_max);
|
||||
TEST_COMPARE ((long)arena_max, 300);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
||||
@@ -0,0 +1,31 @@
|
||||
# These test the parser for both the overridability characters as well as
|
||||
# tunables that either never exist, or only exist on some platforms.
|
||||
-glibc.cpu.cached_memopt=1
|
||||
+glibc.cpu.hwcaps=some,random,string
|
||||
@glibc.test_secure=1
|
||||
$glibc.test_unsecure=1
|
||||
|
||||
# These are checked inside the test case
|
||||
glibc.malloc.tcache_max=6
|
||||
$glibc.malloc.tcache_count=3
|
||||
|
||||
-glibc.malloc.perturb=42
|
||||
-glibc.malloc.mmap_threshold=10000
|
||||
overridable glibc.malloc.trim_threshold=10000
|
||||
|
||||
# Interaction with legacy environment-variable aliases (MALLOC_*), checked
|
||||
# in the test case:
|
||||
# - mmap_max: overridable cache default, must be overridable by the
|
||||
# MALLOC_MMAP_MAX_ alias just like by GLIBC_TUNABLES.
|
||||
# - top_pad: nonoverridable cache default, must NOT be overridable by the
|
||||
# MALLOC_TOP_PAD_ alias.
|
||||
glibc.malloc.mmap_max=100
|
||||
-glibc.malloc.top_pad=100
|
||||
|
||||
[proc:/bin/ls]
|
||||
glibc.malloc.tcache_max=7
|
||||
|
||||
[proc:tst-tunconf1]
|
||||
glibc.malloc.tcache_max=4
|
||||
+glibc.malloc.mmap_threshold=10001
|
||||
nonoverridable glibc.malloc.trim_threshold=10001
|
||||
+440
@@ -0,0 +1,440 @@
|
||||
/* Manage /etc/tunables.*
|
||||
Copyright (C) 1999-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <argp.h>
|
||||
#include <assert.h>
|
||||
#include <error.h>
|
||||
#include <inttypes.h>
|
||||
#include <glob.h>
|
||||
#include <libgen.h>
|
||||
#include <libintl.h>
|
||||
#include <locale.h>
|
||||
#include <programs/xmalloc.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define TUNABLES_INTERNAL
|
||||
#include <elf/dl-tunables.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <ldconfig.h>
|
||||
#include <dl-cache.h>
|
||||
#include <version.h>
|
||||
#include <stringtable.h>
|
||||
#include <array_length.h>
|
||||
|
||||
#include "tunconf.h"
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef TUNABLES_CONF
|
||||
# define TUNABLES_CONF SYSCONFDIR "/tunables.conf"
|
||||
#endif
|
||||
|
||||
#ifndef TUNABLES_CACHE
|
||||
# define TUNABLES_CACHE SYSCONFDIR "/tunables.cache"
|
||||
#endif
|
||||
|
||||
/* Tunable Override Policies. */
|
||||
typedef enum {
|
||||
TOP_ALLOW = 0, /* let the environment variable override */
|
||||
TOP_DENY /* no override allowed */
|
||||
} TOP;
|
||||
|
||||
struct tunable_entry_int {
|
||||
struct stringtable_entry *name;
|
||||
struct stringtable_entry *value;
|
||||
struct stringtable_entry *filter;
|
||||
TOP top;
|
||||
bool exclude_secure:1;
|
||||
bool exclude_nonsecure:1;
|
||||
int tunable_id;
|
||||
int value_is_negative:1;
|
||||
int value_was_parsed:1;
|
||||
unsigned long long value_ull;
|
||||
signed long long value_sll;
|
||||
long filter_flags;
|
||||
|
||||
struct tunable_entry_int *next;
|
||||
};
|
||||
|
||||
struct tunable_entry_int *entry_list;
|
||||
|
||||
static int filter_flags = 0;
|
||||
static char *filter_string = NULL;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
clear_filter (void)
|
||||
{
|
||||
free (filter_string);
|
||||
filter_string = NULL;
|
||||
filter_flags = 0;
|
||||
}
|
||||
|
||||
/* Filters are lines the are bracketed, like
|
||||
[prog:foo]
|
||||
*/
|
||||
static void
|
||||
parse_filter (char *line, const char *filename, int lineno)
|
||||
{
|
||||
const char *colon = NULL;
|
||||
const char *right_bracket = NULL;
|
||||
const char *cp;
|
||||
|
||||
for (cp = line; *cp != 0; ++cp)
|
||||
{
|
||||
if (*cp == ':')
|
||||
colon = cp;
|
||||
if (*cp == ']')
|
||||
{
|
||||
right_bracket = cp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Special case: [] means "no filter" */
|
||||
if (right_bracket != NULL && right_bracket == line + 1)
|
||||
{
|
||||
clear_filter ();
|
||||
return;
|
||||
}
|
||||
if (colon == NULL)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, filter line ignored: `%s' (missing ':')\n",
|
||||
line);
|
||||
return;
|
||||
}
|
||||
if (right_bracket == NULL)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, filter line ignored: `%s' (missing ']')\n",
|
||||
line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter_string != NULL)
|
||||
{
|
||||
clear_filter ();
|
||||
}
|
||||
|
||||
if (colon - line - 1 == 4 && memcmp ("proc", line + 1, 4) == 0)
|
||||
{
|
||||
/* Consider this example: [proc:foo] ..." */
|
||||
/* We allocate 4 bytes, [0] through [3]. */
|
||||
filter_string = (char *) xmalloc (right_bracket - colon);
|
||||
/* We copy "foo" for 3 bytes, [0] through [2]. */
|
||||
memcpy (filter_string, colon + 1, right_bracket - colon - 1);
|
||||
/* [3] = 0 so now "foo\0". */
|
||||
filter_string [right_bracket - colon - 1] = 0;
|
||||
filter_flags = TUNCONF_FILTER_PERPROC;
|
||||
}
|
||||
|
||||
else
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"unrecognized filter `%.*s', ignored\n",
|
||||
(int)(colon - line - 1), line + 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_tunable (char *line, const char *filename, int lineno)
|
||||
{
|
||||
TOP top = TOP_ALLOW;
|
||||
char *name;
|
||||
char *value;
|
||||
char *eq;
|
||||
char *orig_line;
|
||||
struct tunable_entry_int *entry;
|
||||
int i, id;
|
||||
static struct tunable_entry_int **entry_list_next = &entry_list;
|
||||
bool exclude_secure = 1, exclude_nonsecure = 0;
|
||||
|
||||
/* Denotes file boundaries. */
|
||||
if (line == NULL)
|
||||
{
|
||||
clear_filter();
|
||||
return;
|
||||
}
|
||||
|
||||
orig_line = line;
|
||||
|
||||
/* Leading whitespace has already been stripped. */
|
||||
|
||||
/* Canonicalize the line. */
|
||||
for (i=0; line[i]; i++)
|
||||
{
|
||||
if (line[i] == '\t')
|
||||
line[i] = ' ';
|
||||
if (line[i] == '\n' || line[i] == '\r')
|
||||
{
|
||||
line[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse modifiers. */
|
||||
while (*line)
|
||||
{
|
||||
int prefix_len;
|
||||
|
||||
#define TUN_PREFIX(s) \
|
||||
prefix_len = sizeof(s) - 1, \
|
||||
strncmp (line, s " ", prefix_len + 1) == 0
|
||||
|
||||
if (TUN_PREFIX("overridable"))
|
||||
{
|
||||
top = TOP_ALLOW;
|
||||
/* The line++ below skips the space. */
|
||||
line += prefix_len;
|
||||
}
|
||||
else if (TUN_PREFIX ("nonoverridable"))
|
||||
{
|
||||
top = TOP_DENY;
|
||||
line += prefix_len;
|
||||
}
|
||||
else if (TUN_PREFIX ("onlysecure"))
|
||||
{
|
||||
exclude_nonsecure = 1;
|
||||
exclude_secure = 0;
|
||||
line += prefix_len;
|
||||
}
|
||||
else if (TUN_PREFIX ("nonsecure"))
|
||||
{
|
||||
exclude_secure = 1;
|
||||
exclude_nonsecure = 0;
|
||||
line += prefix_len;
|
||||
}
|
||||
else if (TUN_PREFIX ("anysecure"))
|
||||
{
|
||||
exclude_secure = 0;
|
||||
exclude_nonsecure = 0;
|
||||
line += prefix_len;
|
||||
}
|
||||
else switch (*line)
|
||||
{
|
||||
case '+':
|
||||
top = TOP_ALLOW;
|
||||
break;
|
||||
case '-':
|
||||
top = TOP_DENY;
|
||||
break;
|
||||
case '@':
|
||||
exclude_nonsecure = 1;
|
||||
exclude_secure = 0;
|
||||
break;
|
||||
case '$':
|
||||
exclude_nonsecure = 0;
|
||||
exclude_secure = 1;
|
||||
break;
|
||||
case '*':
|
||||
exclude_nonsecure = 0;
|
||||
exclude_secure = 0;
|
||||
break;
|
||||
case '[':
|
||||
parse_filter (line, filename, lineno);
|
||||
return;
|
||||
case ' ':
|
||||
break;
|
||||
|
||||
default:
|
||||
goto done;
|
||||
}
|
||||
line ++;
|
||||
}
|
||||
done:
|
||||
|
||||
/* NAME now points to the start of the tunable name. */
|
||||
name = line;
|
||||
|
||||
/* Look for the '=' separator. */
|
||||
eq = strchr (line, '=');
|
||||
if (eq == NULL)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, line ignored: `%s' (missing '=')",
|
||||
orig_line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (eq == name)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, line ignored: `%s' (missing tunable name)",
|
||||
orig_line);
|
||||
return;
|
||||
}
|
||||
|
||||
/* At this point, EQ actually points to '='. */
|
||||
value = eq + 1;
|
||||
|
||||
while (*value && isspace(*value))
|
||||
value ++;
|
||||
|
||||
if (*value == 0)
|
||||
{
|
||||
error_at_line (0, 0, filename, lineno,
|
||||
"syntax error, line ignored: `%s' (missing value)",
|
||||
orig_line);
|
||||
return;
|
||||
}
|
||||
|
||||
/* VALUE now points to the start of the value. */
|
||||
|
||||
/* Split the string into name and value c-strings. */
|
||||
*eq = 0;
|
||||
/* Trim trailing whitespace off NAME. */
|
||||
while (*name && isspace (name[strlen(name)-1]))
|
||||
name[strlen(name)-1] = 0;
|
||||
/* Trim trailing whitespace off VALUE. */
|
||||
while (*value && isspace (value[strlen(value)-1]))
|
||||
value[strlen(value)-1] = 0;
|
||||
|
||||
id = -1;
|
||||
for (i = 0; i < array_length (tunable_list); i ++)
|
||||
if (strcmp (tunable_list[i].name, name) == 0)
|
||||
{
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
if (id == -1)
|
||||
printf ("%s:%d: Warning: tunable %s not recognized.\n",
|
||||
filename, lineno, name);
|
||||
|
||||
entry = (struct tunable_entry_int *) xcalloc (sizeof (struct tunable_entry_int), 1);
|
||||
entry->name = cache_store_string (name);
|
||||
entry->value = cache_store_string (value);
|
||||
entry->tunable_id = id;
|
||||
entry->top = top;
|
||||
entry->exclude_secure = exclude_secure;
|
||||
entry->exclude_nonsecure = exclude_nonsecure;
|
||||
|
||||
if (filter_flags)
|
||||
{
|
||||
entry->filter_flags = filter_flags;
|
||||
entry->filter = cache_store_string (filter_string);
|
||||
}
|
||||
|
||||
if (value[0] == '-')
|
||||
{
|
||||
entry->value_is_negative = 1;
|
||||
if (sscanf (value, "%lld", &entry->value_sll) == 1)
|
||||
entry->value_was_parsed = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->value_is_negative = 0;
|
||||
if (sscanf (value, "%llu", &entry->value_ull) == 1)
|
||||
entry->value_was_parsed = 1;
|
||||
}
|
||||
|
||||
*entry_list_next = entry;
|
||||
entry_list_next = & (entry->next);
|
||||
}
|
||||
|
||||
void
|
||||
parse_tunconf (const char *filename, char *opt_chroot)
|
||||
{
|
||||
ldconfig_parse_config (filename, opt_chroot, add_tunable);
|
||||
}
|
||||
|
||||
struct tunable_header_cached *
|
||||
get_tunconf_ext (uint32_t string_table_offset)
|
||||
{
|
||||
struct tunable_entry_int *tei;
|
||||
struct tunable_header_cached *thc;
|
||||
size_t count;
|
||||
size_t size;
|
||||
|
||||
/* First, count the number of entries we have. */
|
||||
tei = entry_list;
|
||||
count = 0;
|
||||
while (tei != NULL)
|
||||
{
|
||||
++ count;
|
||||
tei = tei->next;
|
||||
}
|
||||
if (count == 0)
|
||||
return NULL;
|
||||
|
||||
/* Allocate enough space for the whole cached block. */
|
||||
size = sizeof (struct tunable_header_cached)
|
||||
+ sizeof (struct tunable_entry_cached) * count;
|
||||
thc = (struct tunable_header_cached *) xmalloc (size);
|
||||
|
||||
/* Now, fill in the structures. */
|
||||
|
||||
thc->signature = TUNCONF_SIGNATURE;
|
||||
thc->version = TUNCONF_VERSION;
|
||||
thc->num_tunables = count;
|
||||
thc->unused_1 = 0;
|
||||
|
||||
tei = entry_list;
|
||||
count = 0;
|
||||
while (tei != NULL)
|
||||
{
|
||||
struct tunable_entry_cached *tec;
|
||||
|
||||
tec = & ( thc->tunables[count] );
|
||||
|
||||
tec->flags = 0;
|
||||
if (tei->value_was_parsed)
|
||||
tec->flags |= TUNCONF_FLAG_PARSED;
|
||||
if (tei->value_is_negative)
|
||||
tec->flags |= TUNCONF_FLAG_NEGATIVE;
|
||||
switch (tei->top)
|
||||
{
|
||||
case TOP_ALLOW:
|
||||
tec->flags |= TUNCONF_OVERRIDE_ALLOW;
|
||||
break;
|
||||
case TOP_DENY:
|
||||
tec->flags |= TUNCONF_OVERRIDE_DENY;
|
||||
break;
|
||||
}
|
||||
if (tei->exclude_secure)
|
||||
tec->flags |= TUNCONF_EXCLUDE_SECURE;
|
||||
if (tei->exclude_nonsecure)
|
||||
tec->flags |= TUNCONF_EXCLUDE_UNSECURE;
|
||||
|
||||
tec->tunable_id = tei->tunable_id;
|
||||
tec->name_offset = tei->name->offset + string_table_offset;
|
||||
tec->value_offset = tei->value->offset + string_table_offset;
|
||||
|
||||
if (tei->filter_flags != 0)
|
||||
{
|
||||
tec->flag_offset = tei->filter->offset + string_table_offset;
|
||||
tec->flags |= tei->filter_flags;
|
||||
}
|
||||
else
|
||||
tec->flag_offset = 0;
|
||||
|
||||
tec->unused_1 = 0;
|
||||
if (tei->value_is_negative)
|
||||
tec->parsed_value = (uint64_t) tei->value_sll;
|
||||
else
|
||||
tec->parsed_value = (uint64_t) tei->value_ull;
|
||||
|
||||
++ count;
|
||||
tei = tei->next;
|
||||
}
|
||||
|
||||
return thc;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#define TUNCONF_SIGNATURE 0x7c3ba94f
|
||||
#define TUNCONF_VERSION 0x01000000
|
||||
|
||||
#define TUNCONF_FLAG_PARSED 0x00000001
|
||||
#define TUNCONF_FLAG_NEGATIVE 0x00000002
|
||||
|
||||
#define TUNCONF_FLAG_OVERRIDABLE 0x0000000C
|
||||
#define TUNCONF_OVERRIDE_DENY 0x00000004
|
||||
#define TUNCONF_OVERRIDE_ALLOW 0x00000000
|
||||
|
||||
#define TUNCONF_EXCLUDE_SECURE 0x00000010
|
||||
#define TUNCONF_EXCLUDE_UNSECURE 0x00000020
|
||||
|
||||
#define TUNCONF_FLAG_FILTER 0x0000ff00
|
||||
#define TUNCONF_FILTER_NONE 0x00000000
|
||||
#define TUNCONF_FILTER_PERPROC 0x00000100
|
||||
|
||||
/* An array of [num_tunables] of these follows the below. */
|
||||
struct tunable_entry_cached {
|
||||
uint32_t flags;
|
||||
uint32_t tunable_id;
|
||||
uint32_t name_offset;
|
||||
uint32_t value_offset;
|
||||
uint32_t flag_offset;
|
||||
uint32_t unused_1; /* for alignment */
|
||||
uint64_t parsed_value;
|
||||
};
|
||||
|
||||
/* One of these is at the beginning of the tunable data block. */
|
||||
struct tunable_header_cached {
|
||||
uint32_t signature;
|
||||
uint32_t version;
|
||||
uint32_t num_tunables;
|
||||
uint32_t unused_1; /* for alignment */
|
||||
struct tunable_entry_cached tunables[0 /* num_tunables */];
|
||||
};
|
||||
|
||||
void parse_tunconf (const char *filename, char *opt_chroot);
|
||||
|
||||
struct tunable_header_cached * get_tunconf_ext (uint32_t str_offset);
|
||||
#define TUNCONF_SIZE(thc_p) (sizeof(struct tunable_header_cached) \
|
||||
+ thc_p->num_tunables * sizeof (struct tunable_entry_cached))
|
||||
|
||||
extern const struct tunable_header_cached *
|
||||
_dl_load_cache_tunables (const char **data);
|
||||
@@ -257,3 +257,10 @@ $(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(srcdir)/libpthread_sy
|
||||
else
|
||||
$(addprefix $(objpfx),$(tests) $(test-srcs)): $(srcdir)/libpthread_syms.a $(objpfx)libpthread.a
|
||||
endif
|
||||
|
||||
# Like rt, these tests prefer to be run serially.
|
||||
ifeq (yes-yes,$(run-built-tests)-$(serialize-tests))
|
||||
ifneq ($(filter %tests,$(MAKECMDGOALS)),)
|
||||
.NOTPARALLEL:
|
||||
endif
|
||||
endif
|
||||
|
||||
+1
-1
@@ -529,7 +529,7 @@
|
||||
/* Major and minor version number of the GNU C library package. Use
|
||||
these macros to test for features in specific releases. */
|
||||
#define __GLIBC__ 2
|
||||
#define __GLIBC_MINOR__ 43
|
||||
#define __GLIBC_MINOR__ 44
|
||||
|
||||
#define __GLIBC_PREREQ(maj, min) \
|
||||
((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
|
||||
|
||||
@@ -91,6 +91,8 @@ enum
|
||||
#define IPPROTO_MPLS IPPROTO_MPLS
|
||||
IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation. */
|
||||
#define IPPROTO_ETHERNET IPPROTO_ETHERNET
|
||||
IPPROTO_AGGFRAG = 144, /* AGGFRAG in ESP (RFC 9347). */
|
||||
#define IPPROTO_AGGFRAG IPPROTO_AGGFRAG
|
||||
IPPROTO_RAW = 255, /* Raw IP packets. */
|
||||
#define IPPROTO_RAW IPPROTO_RAW
|
||||
IPPROTO_SMC = 256, /* Shared Memory Communications. */
|
||||
|
||||
@@ -24,7 +24,7 @@ test_program_prefix=$2
|
||||
objpfx=$3
|
||||
|
||||
# Create the locale directories.
|
||||
mkdir -p ${objpfx}localedir/existing-locale/LC_MESSAGES
|
||||
mkdir -p ${objpfx}domaindir/existing-locale/LC_MESSAGES
|
||||
|
||||
msgfmt -o ${objpfx}domaindir/existing-locale/LC_MESSAGES/translit.mo \
|
||||
translit.po
|
||||
|
||||
@@ -32,17 +32,25 @@ generate_locale ()
|
||||
out=$3
|
||||
flags=$4
|
||||
ret=0
|
||||
|
||||
# Use a staging area to avoid writing to locales concurrently.
|
||||
# While this process is running, $$ is sufficiently unique.
|
||||
stage="${common_objpfx}localedata/gen-locale.$$.tmp"
|
||||
mkdir "$stage" 2>/dev/null || true
|
||||
|
||||
${localedef_before_env} ${run_program_env} I18NPATH=../localedata \
|
||||
${localedef_after_env} $flags -f $charmap -i $input \
|
||||
${common_objpfx}localedata/$out || ret=$?
|
||||
if [ $ret -eq 0 ]; then
|
||||
# The makefile checks the timestamp of the LC_CTYPE file,
|
||||
# but localedef won't have touched it if it was able to
|
||||
# hard-link it to an existing file.
|
||||
touch ${common_objpfx}localedata/$out/LC_CTYPE
|
||||
$stage/$out || ret=$?
|
||||
if [ $ret -eq 0 ] ; then
|
||||
# Ignore errors in case some other process has created the same locale.
|
||||
# This rename operation should be atomic, and it should fail if the
|
||||
# $out locale already exists (rename fails with ENOTEMPTY).
|
||||
mv $stage/$out ${common_objpfx}localedata/. 2>/dev/null || true
|
||||
rm -rf $stage
|
||||
else
|
||||
rm -rf $stage
|
||||
echo "Charmap: \"${charmap}\" Inputfile: \"${input}\"" \
|
||||
"Outputdir: \"${out}\" failed"
|
||||
"Outputdir: \"${out}\" failed (exit status $ret)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ title "C locale"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language ""
|
||||
|
||||
@@ -13,7 +13,7 @@ title "Aragonese locale for Spain"
|
||||
source "Softaragones"
|
||||
address ""
|
||||
contact "Jordi Mallach Pérez, Juan Pablo Martínez"
|
||||
email "bug-glibc-locales@gnu.org, softaragones@softaragones.org"
|
||||
email "libc-alpha@sourceware.org, softaragones@softaragones.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Aragonese"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for United Arab Emirates"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Bahrain"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Algeria"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Egypt"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -14,7 +14,7 @@ title "Arabic language locale for India"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Iraq"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Jordan"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Kuwait"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Lebanon"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Libyan Arab Jamahiriya"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Morocco"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Oman"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Qatar"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -17,7 +17,7 @@ title "Arabic locale for Saudi Arabia"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -19,7 +19,7 @@ title "Arabic language locale for Sudan"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -19,7 +19,7 @@ title "Arabic language locale for South Sudan"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Syrian Arab Republic"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Tunisia"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Arabic language locale for Yemen"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Arabic"
|
||||
|
||||
@@ -16,7 +16,7 @@ title "Assamese language locale for India"
|
||||
source "Amitakhya Phukan, Red Hat"
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Assamese"
|
||||
|
||||
@@ -23,7 +23,7 @@ title "Belarusian locale for Belarus"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Belarusian"
|
||||
|
||||
@@ -23,7 +23,7 @@ title "Belarusian Latin-Script locale for Belarus"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Belarusian"
|
||||
|
||||
@@ -17,7 +17,7 @@ LC_IDENTIFICATION
|
||||
title "Bangla language locale for India"
|
||||
source "IBM Globalization Center of Competency, Yamato Software Laboratory"
|
||||
address "1623-14, Shimotsuruma, Yamato-shi, Kanagawa-ken, 242-8502, Japan"
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Bangla"
|
||||
|
||||
@@ -17,7 +17,7 @@ title "Tibetan language locale for P.R. of China"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Tibetan"
|
||||
|
||||
@@ -17,7 +17,7 @@ title "Tibetan language locale for India"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Tibetan"
|
||||
|
||||
@@ -19,7 +19,7 @@ LC_IDENTIFICATION
|
||||
title "Breton locale for France with Euro"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Breton"
|
||||
|
||||
@@ -16,7 +16,7 @@ title "Bodo language locale for India"
|
||||
source "Red Hat Pune"
|
||||
address "Level 1, Tower X, Cybercity, Magarpatta City, Hadapsar, Pune-411013 "
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Bodo"
|
||||
|
||||
@@ -26,7 +26,7 @@ title "Catalan locale for Spain"
|
||||
source "RAP"
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Catalan"
|
||||
|
||||
@@ -22,7 +22,7 @@ title "Catalan locale for Catalonia with Euro"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Catalan"
|
||||
|
||||
@@ -21,7 +21,7 @@ title "Mandarin Chinese locale for the Republic of China"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Mandarin Chinese"
|
||||
|
||||
@@ -113,7 +113,7 @@ title "Czech locale for the Czech Republic"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Czech"
|
||||
|
||||
@@ -26,7 +26,7 @@ title "Kashubian locale for Poland"
|
||||
source "csb_PL locale"
|
||||
address ""
|
||||
contact "Michal Ostrowski"
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Kashubian"
|
||||
|
||||
@@ -35,7 +35,7 @@ title "Danish locale for Denmark"
|
||||
source "Danish Standards Association"
|
||||
address "Kollegievej 6, DK-2920 Charlottenlund, Danmark"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Danish"
|
||||
|
||||
@@ -26,7 +26,7 @@ title "German locale for Austria"
|
||||
source "O:sterreiches Normungsinstitut"
|
||||
address "Postfach 130, A-1021 Wien"
|
||||
contact "Gerhard Budin"
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Austrian German"
|
||||
|
||||
@@ -26,7 +26,7 @@ title "German locale for Austria with Euro"
|
||||
source "O:sterreiches Normungsinstitut"
|
||||
address "Postfach 130, A-1021 Wien"
|
||||
contact "Gerhard Budin"
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -27,7 +27,7 @@ title "German locale for Belgium"
|
||||
source "RAP"
|
||||
address "Sankt Jørgens Alle 8, DK-1615 København V, Danmark"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -20,7 +20,7 @@ title "German locale for Belgium with Euro"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -27,7 +27,7 @@ title "German locale for Switzerland"
|
||||
source "RAP"
|
||||
address "Sankt Jørgens Alle 8, DK-1615 København V, Danmark"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Swiss High German"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "German locale for Germany"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "German locale for Germany with Euro"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -25,7 +25,7 @@ title "German language locale for Italy"
|
||||
source ""
|
||||
address "I-39100 Bolzano//Bozen"
|
||||
contact "Matthias Dieter Wallno:fer"
|
||||
email "libc-locales@sourceware.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "German locale for Liechtenstein"
|
||||
source ""
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -27,7 +27,7 @@ title "German locale for Luxemburg"
|
||||
source "RAP"
|
||||
address "Sankt Jørgens Alle 8, DK-1615 København V, Danmark"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -20,7 +20,7 @@ title "German locale for Luxemburg with Euro"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "German"
|
||||
|
||||
@@ -17,7 +17,7 @@ title "Lower Sorbian locale for Germany"
|
||||
source "Information from Michael Wolf"
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Lower Sorbian"
|
||||
|
||||
@@ -27,7 +27,7 @@ title "Dzongkha language locale for Bhutan"
|
||||
source "Sherubtse College"
|
||||
address "Kanglung, Bhutan"
|
||||
contact ""
|
||||
email "bug-glibc@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Dzongkha"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "Greek locale for Cyprus"
|
||||
source "Greek Debian Translation Team"
|
||||
address "Konstantinos Margaritis, M. Asias 50, Nafplion 21100, Greece"
|
||||
contact ""
|
||||
email "bug-glibc@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Greek"
|
||||
|
||||
@@ -27,7 +27,7 @@ title "Greek locale for Greece"
|
||||
source "RAP"
|
||||
address "Sankt Jorgens Alle 8, DK-1615 Kobenhavn V, Danmark"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Greek"
|
||||
|
||||
@@ -13,7 +13,7 @@ title "Greek locale for Greece with Euro"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Greek"
|
||||
|
||||
@@ -15,7 +15,7 @@ title "English language locale for Antigua and Barbuda"
|
||||
source "Free Software Foundation, Inc."
|
||||
address "https:////www.gnu.org//software//libc//"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "English"
|
||||
|
||||
@@ -27,7 +27,7 @@ title "English locale for Australia"
|
||||
source "RAP"
|
||||
address "Sankt Jørgens Alle 8, DK-1615 København V, Danmark"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Australian English"
|
||||
|
||||
@@ -24,7 +24,7 @@ title "English locale for Botswana"
|
||||
source "RAP"
|
||||
address ""
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "English"
|
||||
|
||||
@@ -29,7 +29,7 @@ title "English locale for Canada"
|
||||
source "RAP"
|
||||
address "Sankt Jørgens Alle 8, DK-1615 København V, Danmark"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "Canadian English"
|
||||
|
||||
@@ -32,7 +32,7 @@ title "English locale for Denmark"
|
||||
source "Danish Standards Association"
|
||||
address "Kollegievej 6, DK-2920 Charlottenlund, Danmark"
|
||||
contact ""
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "English"
|
||||
|
||||
@@ -27,7 +27,7 @@ title "English locale for Britain"
|
||||
source "RAP"
|
||||
address "Sankt Jørgens Alle 8, DK-1615 København V, Danmark"
|
||||
contact "Keld Simonsen"
|
||||
email "bug-glibc-locales@gnu.org"
|
||||
email "libc-alpha@sourceware.org"
|
||||
tel ""
|
||||
fax ""
|
||||
language "British English"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user